generic

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package generic implements a data-driven "breadth-tier" adapter: one Go implementation that supports many agents from a table of Specs, rather than a hand-written package per agent. It is for the long tail of agents whose agentsync surface is a rules/memory file plus (optionally) an `mcpServers` JSON and/or an Agent-Skills (SKILL.md) directory — the same shapes the deep adapters (Windsurf/Cline/Continue/Codex) already take.

The DEEP adapters (claude, codex, cursor, gemini, opencode, continuedev, windsurf, roo, cline) are NOT generic — they have richer, agent-specific component support (subagents, commands, hooks, …) and bidirectional nuances that don't fit a table. The generic tier deliberately covers memory, MCP, and Agent Skills (the open SKILL.md spec, where the agent natively scans a skills directory), and reports every other component as a skip, so its coverage is never overstated. Skills fit the table because their on-disk format is uniform across agents — only the scanned directory varies, with no dialect to model. Breadth-tier agents still flow through agentsync's normal apply/import pipeline, so they inherit drift detection, secret resolution, and capture — which a one-way "rules dump" (ruler/rulesync) does not provide.

Each agent is one verified Spec (see specs.go); adding an agent is a data entry, not a package. Every path in a Spec MUST be verified against the agent's upstream docs (and corroborated by prior-art tools) before being added — the count stays honest because each row reflects the agent's real coverage.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter implements adapter.Adapter for one Spec.

func New

func New(spec Spec, opts Options) *Adapter

New constructs a generic adapter for the given Spec.

func (*Adapter) Apply

func (a *Adapter) Apply(ops []adapter.FileOp, w adapter.DestWriter) error

Apply routes every destination write through the supplied DestWriter rather than calling iox.AtomicWrite directly. The DestWriter owns the foreign-collision backup invariant — see the doc on adapter.DestWriter.

func (*Adapter) Capabilities

func (a *Adapter) Capabilities() adapter.Capability

func (*Adapter) Detect

func (a *Adapter) Detect() (bool, error)

func (*Adapter) Ingest

func (a *Adapter) Ingest(scope adapter.Scope, project string) (source.Canonical, error)

Ingest reads this breadth-tier agent's memory, MCP, and skills back into a partial canonical. Inverse of Render (memory + MCP + skills; the components the tier never projects are simply not read).

func (*Adapter) KeyMergeStrategy

func (a *Adapter) KeyMergeStrategy() string

KeyMergeStrategy is merge-jsonc-keys when the spec has an MCP file (the only key-merge surface); otherwise "" (memory is a whole-file write). The breadth tier always uses the JSONC-tolerant merge so a commented settings file (Zed, Copilot's .vscode/mcp.json, Amp) is parsed rather than clobbered — hujson reads plain JSON identically, so dedicated *.json MCP files are unaffected.

func (*Adapter) Name

func (a *Adapter) Name() string

func (*Adapter) Render

func (a *Adapter) Render(r secrets.Resolved, scope adapter.Scope, project string) ([]adapter.FileOp, []adapter.Skip, error)

Render projects the canonical model into this breadth-tier agent's memory (rules) file, its mcpServers JSON, and its Agent-Skills directory — each when the spec declares a target for it. Every other component (subagents, commands, hooks, LSP), and skills/MCP for a spec that declares no target, is reported as a skip: the generic tier deliberately covers memory + MCP + skills only. A component the spec does not support at the requested scope (e.g. user-scope memory for a project-only agent) is likewise reported as a skip rather than written somewhere wrong.

type FileTarget

type FileTarget struct {
	User    string // file path or directory root under the user home (targetRoot)
	Project string // file path or directory root under the project root
}

FileTarget is a per-scope path (relative to the scope root) for a file component (Memory: a single markdown file) or a directory component (Skills: the Agent-Skills root directory under which each skill is a <name>/SKILL.md subtree). An empty path means the component is unsupported at that scope.

type MCPTarget

type MCPTarget struct {
	User         string
	Project      string
	RootKey      string
	TransportKey string
	StdioValue   string
	RemoteValue  string
	RemoteURLKey string
	SSEURLKey    string
}

MCPTarget describes an agent's MCP servers JSON file and its on-disk dialect. The breadth tier only handles JSON `<rootKey>` server-map files; agents whose MCP is TOML, app-storage, or otherwise unmodeled simply leave User/Project empty (MCP unsupported) and are reported as a skip.

The dialect knobs capture the variance the prior-art research surfaced across the tail (all with Claude-compatible defaults):

  • RootKey: the top-level object key. Default "mcpServers"; e.g. "servers" (VS Code Copilot), "mcp" (Crush).
  • TransportKey: the per-server field naming the transport. "" = inferred from command-vs-url (no field). Else e.g. "type" or "transport".
  • StdioValue / RemoteValue: the TransportKey values for stdio vs remote (defaults "stdio"/"http"; Copilot CLI uses "local" for stdio). Ignored when TransportKey == "".
  • RemoteURLKey: the per-server field holding a remote server's URL. Default "url"; some agents use "httpUrl" (Qwen) or "serverUrl" (Antigravity).
  • SSEURLKey: for Gemini-lineage agents that split remote transports across TWO url fields (Qwen: `httpUrl` = streamable HTTP, `url` = SSE), the field holding an SSE server's URL. "" = no split (SSE shares RemoteURLKey). When set, ingest reads both fields (RemoteURLKey wins when both are present, mirroring the upstream precedence) and render routes a canonical `sse` server to this key.

type Options

type Options struct {
	TargetRoot string
	LookPath   func(file string) (string, error)
}

Options configure a generic adapter instance.

type Spec

type Spec struct {
	Name      string     // agent name (Adapter.Name())
	DetectBin string     // binary on PATH (best-effort); "" to skip
	DetectDir string     // dir under targetRoot whose existence implies installed; "" to skip
	Memory    FileTarget // rules/instructions FILE path (plain markdown)
	MCP       MCPTarget  // mcpServers JSON
	Skills    FileTarget // Agent-Skills DIRECTORY root (holds <name>/SKILL.md subtrees); empty = unsupported
}

Spec is the verified, data-driven description of one breadth-tier agent.

func Specs

func Specs() []Spec

Specs returns the verified breadth-tier agent table. Each entry's paths were cross-referenced against the agent's upstream docs AND prior-art config-sync tools (ruler, rulesync) before inclusion — see docs/capability-matrix.md (§ "Breadth tier") for the per-agent basis and the deliberate exclusions.

Rules of the table:

  • MEMORY is the universal axis: every entry projects the canonical memory to the agent's verified rules/instructions file (the AGENTS.md standard where the agent reads it, else its agent-specific file). Plain markdown body.
  • MCP is enabled ONLY where the agent reads a JSON server-map file whose dialect the engine can express faithfully (root key + transport field + url key). Agents whose MCP is an array, YAML, TOML, app-storage, or otherwise unmodeled leave MCP empty — the engine reports it as a skip rather than write a shape the agent can't read.
  • SKILLS is enabled where the agent natively scans Agent-Skills (SKILL.md) directories (the open agentskills.io spec). The on-disk skill format is uniform across agents, so there is no dialect to model — only the scanned directory varies. Most agents read the cross-vendor `.agents/skills` convention (shared with Codex, so the render pipeline dedupes the byte-identical ops); a few scan only their own `.<agent>/skills`. Agents that don't natively scan a SKILL.md directory — Jules/Firebase (publish skills FOR other agents), Amazon Q (skills only via an MCP server, a different component), OpenHands (programmatic load, no auto-scanned dir) — leave Skills empty and report it as a skip.
  • A scope with no verified target is left empty (reported as a skip), never guessed. Low-confidence user-scope paths from the research are omitted.

Deep, agent-specific adapters (claude, codex, cursor, gemini, opencode, continuedev, windsurf, roo, cline) are NOT here — they live in their own packages with richer component support.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL