@agentproto/cli 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +59584 -10574
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +18306 -5925
- package/dist/index.mjs.map +1 -1
- package/dist/registry/builtins.mjs +6 -2
- package/dist/registry/builtins.mjs.map +1 -1
- package/dist/registry/manifest.mjs +6 -2
- package/dist/registry/manifest.mjs.map +1 -1
- package/dist/registry/plugins.mjs +8 -4
- package/dist/registry/plugins.mjs.map +1 -1
- package/dist/registry/runtime.mjs +7 -1
- package/dist/registry/runtime.mjs.map +1 -1
- package/dist/util/credentials.mjs +6 -2
- package/dist/util/credentials.mjs.map +1 -1
- package/package.json +24 -7
- package/skill/agentproto/SKILL.md +261 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { resolve, dirname } from 'path';
|
|
2
3
|
import { appendFile, readFile, writeFile, stat, mkdir } from 'fs/promises';
|
|
3
4
|
import { createHash } from 'crypto';
|
|
@@ -5,10 +6,13 @@ import matter from 'gray-matter';
|
|
|
5
6
|
import { spawn } from 'child_process';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* @agentproto/cli v0.
|
|
9
|
+
* @agentproto/cli v0.3.0
|
|
9
10
|
* The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
// Provide a real `require` in the ESM bundle. Bundling the Ink stack pulls in
|
|
13
|
+
// CJS deps (e.g. signal-exit@3) that call `require("assert")`; without this
|
|
14
|
+
// esbuild's interop shim throws "Dynamic require is not supported".
|
|
15
|
+
createRequire(import.meta.url);
|
|
12
16
|
var HEADER_RE = /^=== TURN id=([^\s]+) participant=([^\s]+) ts=([^\s]+) ===$/;
|
|
13
17
|
var FileSubstrate = class {
|
|
14
18
|
constructor(opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../agent-runtime/src/adapters/substrate-file.ts","../../../agent-runtime/src/util/mention-parser.mjs","../../../agent-runtime/src/adapters/dispatcher-mention.ts","../../../agent-runtime/src/adapters/state-fs.ts","../../../cli-exec/src/spawn-stdin.ts","../../../cli-exec/src/parse.ts","../../../agent-runtime/src/adapters/participant-agent-cli.ts","../../src/registry/runtime.ts","../../src/registry/builtins.ts"],"names":["readFile","isNotFound","ensureDir","writeFile","resolvePath","stat","mkdir","resolve"],"mappings":"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","file":"builtins.mjs","sourcesContent":["/**\n * File substrate — append-only markdown journal.\n *\n * Each turn is delimited by a header line:\n * === TURN id=<id> participant=<pid> ts=<iso> ===\n * <body lines…>\n *\n * Ids are content-hashed, so re-running an append with the same body\n * is idempotent at the row level.\n *\n * Caveats:\n * - `appendFile` does not fsync. A power-loss between buffered write\n * and disk flush can lose the most recent turn(s); callers that\n * need durability across crashes should layer their own fsync.\n * - The parser splits on lines matching `=== TURN ... ===`. Turn\n * content containing such a line will corrupt subsequent parses.\n * Treat turn content as untrusted? Sanitize before append.\n */\n\nimport { appendFile, readFile, writeFile, mkdir, stat } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\nimport { createHash } from \"node:crypto\"\nimport type { Substrate, Turn, TurnInput, TurnId } from \"../ports.js\"\n\nexport type FileSubstrateOptions = {\n /** Absolute path to the journal file. */\n readonly path: string\n}\n\nconst HEADER_RE =\n /^=== TURN id=([^\\s]+) participant=([^\\s]+) ts=([^\\s]+) ===$/\n\nexport class FileSubstrate implements Substrate {\n readonly kind = \"file\"\n\n constructor(private readonly opts: FileSubstrateOptions) {}\n\n async append(input: TurnInput): Promise<Turn> {\n const timestamp = input.timestamp ?? new Date().toISOString()\n const id = hashTurnId(input.participantId, timestamp, input.content)\n const turn: Turn = {\n id,\n participantId: input.participantId,\n timestamp,\n content: input.content,\n meta: input.meta,\n }\n await ensureDir(this.opts.path)\n const block = formatTurnBlock(turn)\n await appendFile(this.opts.path, block, \"utf8\")\n return turn\n }\n\n async read(since?: TurnId): Promise<readonly Turn[]> {\n let raw: string\n try {\n raw = await readFile(this.opts.path, \"utf8\")\n } catch (err) {\n if (isNotFound(err)) return []\n throw err\n }\n const turns = parseJournal(raw)\n if (since === undefined) return turns\n const cutoff = turns.findIndex((t) => t.id === since)\n if (cutoff === -1) return turns\n return turns.slice(cutoff + 1)\n }\n}\n\n/**\n * Reset the journal by truncating it. Useful for tests. Not part of the\n * Substrate interface — callers must reach for the adapter directly.\n */\nexport async function resetFileSubstrate(path: string): Promise<void> {\n await ensureDir(path)\n await writeFile(path, \"\", \"utf8\")\n}\n\nfunction formatTurnBlock(turn: Turn): string {\n const header = `=== TURN id=${turn.id} participant=${turn.participantId} ts=${turn.timestamp} ===\\n`\n const body = turn.content.endsWith(\"\\n\") ? turn.content : `${turn.content}\\n`\n return `${header}${body}`\n}\n\nfunction parseJournal(raw: string): Turn[] {\n const lines = raw.split(\"\\n\")\n const turns: Turn[] = []\n let current: { id: string; pid: string; ts: string; buf: string[] } | null = null\n\n for (const line of lines) {\n const match = HEADER_RE.exec(line)\n if (match && match[1] && match[2] && match[3]) {\n if (current) turns.push(materialise(current))\n current = { id: match[1], pid: match[2], ts: match[3], buf: [] }\n continue\n }\n if (current) current.buf.push(line)\n }\n if (current) turns.push(materialise(current))\n return turns\n}\n\nfunction materialise(c: {\n id: string\n pid: string\n ts: string\n buf: string[]\n}): Turn {\n // Drop the trailing empty line that appendFile leaves between blocks.\n let body = c.buf.join(\"\\n\")\n while (body.endsWith(\"\\n\")) body = body.slice(0, -1)\n return {\n id: c.id,\n participantId: c.pid,\n timestamp: c.ts,\n content: body,\n }\n}\n\nfunction hashTurnId(pid: string, ts: string, content: string): string {\n const h = createHash(\"sha256\")\n h.update(pid)\n h.update(\"\\x00\")\n h.update(ts)\n h.update(\"\\x00\")\n h.update(content)\n return `t_${h.digest(\"hex\").slice(0, 12)}`\n}\n\nasync function ensureDir(path: string): Promise<void> {\n const dir = dirname(path)\n try {\n await stat(dir)\n } catch (err) {\n if (isNotFound(err)) {\n await mkdir(dir, { recursive: true })\n return\n }\n throw err\n }\n}\n\nfunction isNotFound(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n )\n}\n","/**\n * Canonical @-mention parser.\n *\n * Lives as raw JavaScript (no types) because it's consumed in two\n * places that don't share a build:\n *\n * 1. The kernel imports `textContainsMention` from this file as a\n * normal ESM module (the dispatcher in `adapters/dispatcher-mention.ts`).\n *\n * 2. Runtime profiles inline this file's source into Claude Code\n * hooks at profile-build time, because `.claude/` has no\n * module-resolution at hook-execution time. The build script\n * reads this file as text and stamps it into the hook template.\n *\n * Two cases:\n * 1. Literal `@<name>` substring (case-sensitive, full name).\n * 2. For multi-word names, also `@<firstName>` with non-word\n * boundary (case-insensitive).\n *\n * Edit here only — both consumers stay in sync via build pipelines.\n */\n\n/** @param {string} text @param {string} name @returns {boolean} */\nexport function textContainsMention(text, name) {\n if (text.includes(`@${name}`)) return true\n if (name.includes(\" \")) {\n const firstName = name.split(\" \")[0]?.trim()\n if (!firstName) return false\n const regex = new RegExp(`@${firstName}(?!\\\\w)`, \"i\")\n return regex.test(text)\n }\n return false\n}\n","/**\n * Mention dispatcher — selects participants whose displayName is\n * @-mentioned in the most recent turn.\n *\n * Skip rules:\n * - never re-select the participant who authored the trigger turn\n * (otherwise they'd reply to themselves indefinitely)\n * - never dispatch on a trigger we already processed (in-memory cursor —\n * prevents the loop from re-firing on the same @mention every poll\n * when the kernel's own reply isn't yet visible in the next read).\n * Per-dispatcher-instance state; a fresh swarm process starts with\n * no cursor and naturally responds to the latest unhandled mention\n * exactly once.\n * - if no mentions match any known participant, return [] (idle)\n *\n * The parser itself lives in `../util/mention-parser.mjs` (vanilla JS)\n * so runtime profiles can stamp the same implementation into Claude\n * Code hooks at build time without depending on the TS build pipeline.\n */\n\nimport type {\n Dispatcher,\n DispatcherInput,\n ParticipantId,\n TurnId,\n} from \"../ports.js\"\nimport { textContainsMention } from \"../util/mention-parser.mjs\"\n\nexport class MentionDispatcher implements Dispatcher {\n readonly kind = \"mention\"\n private lastProcessedTriggerId: TurnId | undefined\n\n async selectNext(input: DispatcherInput): Promise<readonly ParticipantId[]> {\n const trigger = input.recentTurns[input.recentTurns.length - 1]\n if (!trigger) return []\n if (trigger.id === this.lastProcessedTriggerId) return []\n const text = trigger.content\n\n const selected: ParticipantId[] = []\n for (const p of input.participants) {\n if (p.id === trigger.participantId) continue\n if (textContainsMention(text, p.displayName)) {\n selected.push(p.id)\n }\n }\n\n if (selected.length > 0) {\n this.lastProcessedTriggerId = trigger.id\n }\n return selected\n }\n}\n\n// Re-exported so callers writing their own adapters can detect\n// mentions with identical semantics.\nexport { textContainsMention }\n","/**\n * Filesystem state store — one JSON file per participant.\n *\n * <stateDir>/<participantId>.json\n *\n * Missing files read as {}. Writes are full overwrites; callers\n * pass the merged state, the adapter doesn't merge on its own.\n */\n\nimport { readFile, writeFile, mkdir, stat } from \"node:fs/promises\"\nimport { resolve as resolvePath } from \"node:path\"\nimport type { ParticipantId, StateStore } from \"../ports.js\"\n\nexport type FileStateStoreOptions = {\n /** Directory to hold the per-participant JSON files. */\n readonly dir: string\n}\n\nexport class FileStateStore implements StateStore {\n readonly kind = \"fs\"\n\n constructor(private readonly opts: FileStateStoreOptions) {}\n\n async read(participantId: ParticipantId): Promise<Readonly<Record<string, unknown>>> {\n const path = this.pathFor(participantId)\n try {\n const raw = await readFile(path, \"utf8\")\n return JSON.parse(raw) as Record<string, unknown>\n } catch (err) {\n if (isNotFound(err)) return Object.freeze({})\n throw err\n }\n }\n\n async write(\n participantId: ParticipantId,\n state: Readonly<Record<string, unknown>>\n ): Promise<void> {\n await ensureDir(this.opts.dir)\n const path = this.pathFor(participantId)\n await writeFile(path, JSON.stringify(state, null, 2), \"utf8\")\n }\n\n private pathFor(participantId: ParticipantId): string {\n // Sanitize: participant ids are user-controlled. Disallow path traversal.\n const safe = participantId.replace(/[^a-zA-Z0-9._-]/g, \"_\")\n return resolvePath(this.opts.dir, `${safe}.json`)\n }\n}\n\nasync function ensureDir(dir: string): Promise<void> {\n try {\n await stat(dir)\n } catch (err) {\n if (isNotFound(err)) {\n await mkdir(dir, { recursive: true })\n return\n }\n throw err\n }\n}\n\nfunction isNotFound(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n )\n}\n","import { spawn } from \"node:child_process\"\n\nexport interface SpawnWithStdinOptions {\n /** Executable to invoke (must be on PATH). */\n readonly command: string\n /** Static argv. The prompt is fed over stdin, not as an argument. */\n readonly args?: readonly string[]\n /** Text written to the child's stdin, then closed. */\n readonly stdin: string\n /** Working directory. Defaults to process.cwd(). */\n readonly cwd?: string\n /** Hard timeout in ms; the child is killed and the call rejects. Default 90000. */\n readonly timeoutMs?: number\n /** Abort the call — kills the child and rejects. */\n readonly signal?: AbortSignal\n /** Signal used to kill on timeout/abort. Default \"SIGTERM\". */\n readonly killSignal?: NodeJS.Signals\n}\n\n/**\n * Spawn a command in one-shot mode: write `stdin`, close it, capture stdout.\n *\n * Resolves with captured stdout on exit code 0; rejects on non-zero exit (with\n * trimmed stderr), spawn error, timeout, or abort. A single settle guard makes\n * the late `close` event after a kill a no-op.\n */\nexport function spawnWithStdin(opts: SpawnWithStdinOptions): Promise<string> {\n const {\n command,\n args = [],\n stdin,\n cwd,\n timeoutMs = 90_000,\n signal,\n killSignal = \"SIGTERM\",\n } = opts\n\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(`${command} aborted before start`))\n return\n }\n\n const child = spawn(command, [...args], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n ...(cwd ? { cwd } : {}),\n })\n\n let out = \"\"\n let err = \"\"\n let settled = false\n\n const finish = (fn: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n signal?.removeEventListener(\"abort\", onAbort)\n fn()\n }\n\n const onAbort = () => {\n child.kill(killSignal)\n finish(() => reject(new Error(`${command} aborted`)))\n }\n const timer = setTimeout(() => {\n child.kill(killSignal)\n finish(() => reject(new Error(`${command} timed out after ${timeoutMs}ms`)))\n }, timeoutMs)\n\n signal?.addEventListener(\"abort\", onAbort)\n\n child.stdout.on(\"data\", d => (out += d))\n child.stderr.on(\"data\", d => (err += d))\n child.on(\"error\", e =>\n finish(() => reject(new Error(`${command} not runnable: ${e.message}`)))\n )\n child.on(\"close\", code =>\n finish(() => {\n if (code === 0) resolve(out)\n else\n reject(\n new Error(`${command} exited with code ${code}: ${err.trim().slice(0, 200) || \"(no stderr)\"}`)\n )\n })\n )\n\n // child may exit before stdin drains → EPIPE on the stream; the close\n // handler already drives resolve/reject, so this write error is benign\n child.stdin.on(\"error\", () => {})\n child.stdin.write(stdin)\n child.stdin.end()\n })\n}\n","/**\n * Parse a `claude --output-format json` response: return the `result` field as\n * the model's text, or null if the JSON isn't that shape (caller falls back to\n * raw stdout). The same envelope is emitted by several agent CLIs in JSON mode.\n */\nexport function parseClaudeJsonOutput(stdout: string): string | null {\n try {\n const parsed = JSON.parse(stdout) as unknown\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"result\" in parsed &&\n typeof (parsed as { result: unknown }).result === \"string\"\n ) {\n return (parsed as { result: string }).result\n }\n return null\n } catch {\n return null\n }\n}\n","/**\n * Agent-CLI participant — spawns a CLI binary, pipes the assembled prompt\n * over stdin, and uses captured stdout as the turn content.\n *\n * Works for any CLI that supports a one-shot \"read prompt from stdin,\n * print response to stdout\" mode (claude-code's `--print`, hermes' `-p`,\n * etc.).\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport matter from \"gray-matter\"\nimport { spawnWithStdin } from \"@agentproto/cli-exec\"\nimport type {\n ParticipantExecuteInput,\n ParticipantExecuteOutput,\n ParticipantExecutor,\n} from \"../ports.js\"\n\n// Re-exported for back-compat: the JSON-envelope parser now lives in the shared\n// @agentproto/cli-exec package alongside the spawn helper.\nexport { parseClaudeJsonOutput } from \"@agentproto/cli-exec\"\n\nexport type AgentCliParticipantOptions = {\n /** Executable to invoke. Examples: \"claude\", \"hermes\", \"goose\". */\n readonly command: string\n /** Static args. The prompt is fed over stdin, not as an argument. */\n readonly args?: readonly string[]\n /** Working directory. Defaults to process.cwd(). */\n readonly cwd?: string\n /** Hard timeout in ms. Default 90000. */\n readonly timeoutMs?: number\n /** Optional output parser — if returns null, content falls back to raw stdout. */\n readonly parseOutput?: (stdout: string) => string | null\n}\n\nexport class AgentCliParticipant implements ParticipantExecutor {\n readonly kind = \"agent-cli\"\n\n constructor(private readonly opts: AgentCliParticipantOptions) {}\n\n async executeTurn(\n input: ParticipantExecuteInput\n ): Promise<ParticipantExecuteOutput> {\n const prompt = await assemblePrompt(input)\n const stdout = await spawnWithStdin({\n command: this.opts.command,\n args: this.opts.args ?? [],\n cwd: this.opts.cwd ?? process.cwd(),\n timeoutMs: this.opts.timeoutMs ?? 90000,\n stdin: prompt,\n signal: input.signal,\n })\n const parsed = this.opts.parseOutput?.(stdout) ?? null\n const content = parsed ?? stdout.trimEnd()\n return { content }\n }\n}\n\nasync function assemblePrompt(\n input: ParticipantExecuteInput\n): Promise<string> {\n const roleText = input.participant.role\n ? await loadRole(input.participant.role)\n : \"\"\n\n const transcript = input.recentTurns\n .map((t) => `[${t.participantId}] ${t.content}`)\n .join(\"\\n\\n\")\n\n return [\n roleText && `# Your role\\n\\n${roleText}`,\n `# Recent conversation\\n\\n${transcript}`,\n `# Your turn\\n\\nYou are ${input.participant.displayName}. The latest message in the conversation triggered you (most likely because it mentions you). Read the transcript above and reply in character. Keep it conversational unless the trigger asks for detailed work. Output only your reply — no preamble, no role labels, no quotes around the response.`,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\")\n}\n\n// File extensions we treat as a path-to-role-file. Anything else is\n// inline role text — even strings that contain `/`, which are common\n// in normal sentences (\"I am an AI/ML reviewer\").\nconst ROLE_FILE_EXTENSIONS = [\".md\", \".markdown\", \".txt\"]\n\nasync function loadRole(roleField: string): Promise<string> {\n if (!looksLikeRoleFile(roleField)) return roleField\n try {\n const raw = await readFile(roleField, \"utf8\")\n // Strip optional YAML frontmatter — lets a Claude Code agent\n // definition file (.claude/agents/*.md) double as a swarm role\n // without ferrying the agent's metadata into the prompt.\n const parsed = matter(raw)\n return parsed.content.trim()\n } catch (err) {\n // The string had a role-file extension but the file isn't readable\n // — surface a hint on stderr so authors don't silently get the\n // literal path as a prompt. Still fall back to inline so the swarm\n // doesn't crash on a typo.\n const code = (err as NodeJS.ErrnoException).code\n process.stderr.write(\n `agent-cli participant: role path '${roleField}' not readable (${code ?? \"unknown\"}); using the literal string as inline role text.\\n`\n )\n return roleField\n }\n}\n\nfunction looksLikeRoleFile(s: string): boolean {\n const lower = s.toLowerCase()\n return ROLE_FILE_EXTENSIONS.some((ext) => lower.endsWith(ext))\n}\n","/**\n * MultiAgentRuntime adapter registry — the seam third-party packages\n * use to plug substrates, dispatchers, participant executors, and\n * state stores into `agentproto run-swarm` without forking the CLI.\n *\n * A plugin module exports nothing required by name — it just imports\n * `register*` helpers from `@agentproto/cli/registry/runtime` and\n * calls them at module load. The CLI discovers plugins via:\n *\n * 1. `--plugin <module-id>` flags on `run-swarm`\n * 2. The `plugins[]` array in `~/.agentproto/config.json`\n * 3. Auto-registered built-ins (file substrate, mention dispatcher,\n * fs state, agent-cli participant) — registered by\n * `registerBuiltins()` at startup.\n *\n * Manifest `kind` strings are resolved through the registry: the kind\n * is the lookup key; the factory builds the concrete adapter from the\n * (loose) manifest config + shared context.\n */\n\nimport type {\n Dispatcher,\n ParticipantExecutor,\n StateStore,\n Substrate,\n} from \"@agentproto/agent-runtime\"\n\n// ── Context passed to every factory ──\n\n/**\n * Shared context every factory receives. Carries the manifest's base\n * directory (for resolving relative paths declared in adapter configs)\n * and a `cleanup` collector so adapters that hold disposable resources\n * (MCP clients, sockets, child processes) can register teardown callbacks\n * that the CLI runs on shutdown.\n */\nexport interface AdapterContext {\n /** Absolute directory of the manifest file. */\n readonly baseDir: string\n /** Register a teardown callback to run when the swarm shuts down. */\n registerCleanup(fn: () => Promise<void> | void): void\n}\n\n// ── Loose config shape ──\n\n/**\n * Manifest adapter blocks are loose: `{ kind: string, ...host-extension }`.\n * Each factory pulls its own typed fields off the config and validates\n * them inline.\n */\nexport interface AdapterConfig {\n readonly kind: string\n readonly [extension: string]: unknown\n}\n\n// ── Factory signatures ──\n\nexport type SubstrateFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Substrate> | Substrate\n\nexport type DispatcherFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Dispatcher> | Dispatcher\n\nexport type ExecutorFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<ParticipantExecutor> | ParticipantExecutor\n\nexport type StateStoreFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<StateStore> | StateStore\n\n// ── Registry state ──\n\nconst substrates = new Map<string, SubstrateFactory>()\nconst dispatchers = new Map<string, DispatcherFactory>()\nconst executors = new Map<string, ExecutorFactory>()\nconst stateStores = new Map<string, StateStoreFactory>()\n\n// ── Public registration API ──\n\nexport function registerSubstrate(kind: string, factory: SubstrateFactory): void {\n substrates.set(kind, factory)\n}\n\nexport function registerDispatcher(\n kind: string,\n factory: DispatcherFactory\n): void {\n dispatchers.set(kind, factory)\n}\n\nexport function registerExecutor(kind: string, factory: ExecutorFactory): void {\n executors.set(kind, factory)\n}\n\nexport function registerStateStore(\n kind: string,\n factory: StateStoreFactory\n): void {\n stateStores.set(kind, factory)\n}\n\n// ── Lookup API (used by run-swarm wiring) ──\n\nexport function getSubstrateFactory(kind: string): SubstrateFactory | undefined {\n return substrates.get(kind)\n}\n\nexport function getDispatcherFactory(\n kind: string\n): DispatcherFactory | undefined {\n return dispatchers.get(kind)\n}\n\nexport function getExecutorFactory(kind: string): ExecutorFactory | undefined {\n return executors.get(kind)\n}\n\nexport function getStateStoreFactory(\n kind: string\n): StateStoreFactory | undefined {\n return stateStores.get(kind)\n}\n\nexport function listRegisteredKinds(): {\n substrates: readonly string[]\n dispatchers: readonly string[]\n executors: readonly string[]\n stateStores: readonly string[]\n} {\n return {\n substrates: [...substrates.keys()],\n dispatchers: [...dispatchers.keys()],\n executors: [...executors.keys()],\n stateStores: [...stateStores.keys()],\n }\n}\n\n/**\n * Test-only: drop every registration. Plugin registrations persist for\n * the lifetime of the process, so tests that load + unload plugins use\n * this to start from a clean slate.\n */\nexport function _resetRegistryForTests(): void {\n substrates.clear()\n dispatchers.clear()\n executors.clear()\n stateStores.clear()\n}\n","/**\n * Built-in MultiAgentRuntime adapters. Registers reference adapters\n * shipped by `@agentproto/agent-runtime` against the runtime registry\n * so a vanilla `agentproto run-swarm` works without any plugins.\n *\n * Built-in `kind` strings: `file`, `mention`, `fs`, `agent-cli`.\n */\n\nimport { resolve as resolvePath } from \"node:path\"\nimport { FileSubstrate } from \"@agentproto/agent-runtime/adapters/substrate-file\"\nimport { MentionDispatcher } from \"@agentproto/agent-runtime/adapters/dispatcher-mention\"\nimport { FileStateStore } from \"@agentproto/agent-runtime/adapters/state-fs\"\nimport {\n AgentCliParticipant,\n parseClaudeJsonOutput,\n} from \"@agentproto/agent-runtime/adapters/participant-agent-cli\"\nimport {\n registerDispatcher,\n registerExecutor,\n registerStateStore,\n registerSubstrate,\n type AdapterConfig,\n type AdapterContext,\n} from \"./runtime.js\"\n\nexport function registerBuiltins(): void {\n registerSubstrate(\"file\", (cfg, ctx) => {\n const path = typeof cfg.path === \"string\" ? cfg.path : \".runtime/conversation.md\"\n return new FileSubstrate({ path: resolvePath(ctx.baseDir, path) })\n })\n\n registerDispatcher(\"mention\", () => new MentionDispatcher())\n\n registerStateStore(\"fs\", (cfg, ctx) => {\n const dir = typeof cfg.dir === \"string\" ? cfg.dir : \".runtime/state\"\n return new FileStateStore({ dir: resolvePath(ctx.baseDir, dir) })\n })\n\n registerExecutor(\"agent-cli\", (cfg) => buildAgentCli(cfg))\n}\n\nfunction buildAgentCli(cfg: AdapterConfig): AgentCliParticipant {\n const command = typeof cfg.command === \"string\" ? cfg.command : \"claude\"\n const args = Array.isArray(cfg.args)\n ? cfg.args.filter((a): a is string => typeof a === \"string\")\n : [\"--print\", \"--output-format=json\"]\n const useClaudeJson = cfg.parseJson !== false && command === \"claude\"\n return new AgentCliParticipant({\n command,\n args,\n parseOutput: useClaudeJson ? parseClaudeJsonOutput : undefined,\n })\n}\n\n// Suppress unused-context warning on registrations that don't read it.\nexport type { AdapterContext }\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../agent-runtime/src/adapters/substrate-file.ts","../../../agent-runtime/src/util/mention-parser.mjs","../../../agent-runtime/src/adapters/dispatcher-mention.ts","../../../agent-runtime/src/adapters/state-fs.ts","../../../cli-exec/src/spawn-stdin.ts","../../../cli-exec/src/parse.ts","../../../agent-runtime/src/adapters/participant-agent-cli.ts","../../src/registry/runtime.ts","../../src/registry/builtins.ts"],"names":["readFile","isNotFound","ensureDir","writeFile","resolvePath","stat","mkdir","resolve"],"mappings":"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","file":"builtins.mjs","sourcesContent":["/**\n * File substrate — append-only markdown journal.\n *\n * Each turn is delimited by a header line:\n * === TURN id=<id> participant=<pid> ts=<iso> ===\n * <body lines…>\n *\n * Ids are content-hashed, so re-running an append with the same body\n * is idempotent at the row level.\n *\n * Caveats:\n * - `appendFile` does not fsync. A power-loss between buffered write\n * and disk flush can lose the most recent turn(s); callers that\n * need durability across crashes should layer their own fsync.\n * - The parser splits on lines matching `=== TURN ... ===`. Turn\n * content containing such a line will corrupt subsequent parses.\n * Treat turn content as untrusted? Sanitize before append.\n */\n\nimport { appendFile, readFile, writeFile, mkdir, stat } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\nimport { createHash } from \"node:crypto\"\nimport type { Substrate, Turn, TurnInput, TurnId } from \"../ports.js\"\n\nexport type FileSubstrateOptions = {\n /** Absolute path to the journal file. */\n readonly path: string\n}\n\nconst HEADER_RE =\n /^=== TURN id=([^\\s]+) participant=([^\\s]+) ts=([^\\s]+) ===$/\n\nexport class FileSubstrate implements Substrate {\n readonly kind = \"file\"\n\n constructor(private readonly opts: FileSubstrateOptions) {}\n\n async append(input: TurnInput): Promise<Turn> {\n const timestamp = input.timestamp ?? new Date().toISOString()\n const id = hashTurnId(input.participantId, timestamp, input.content)\n const turn: Turn = {\n id,\n participantId: input.participantId,\n timestamp,\n content: input.content,\n meta: input.meta,\n }\n await ensureDir(this.opts.path)\n const block = formatTurnBlock(turn)\n await appendFile(this.opts.path, block, \"utf8\")\n return turn\n }\n\n async read(since?: TurnId): Promise<readonly Turn[]> {\n let raw: string\n try {\n raw = await readFile(this.opts.path, \"utf8\")\n } catch (err) {\n if (isNotFound(err)) return []\n throw err\n }\n const turns = parseJournal(raw)\n if (since === undefined) return turns\n const cutoff = turns.findIndex((t) => t.id === since)\n if (cutoff === -1) return turns\n return turns.slice(cutoff + 1)\n }\n}\n\n/**\n * Reset the journal by truncating it. Useful for tests. Not part of the\n * Substrate interface — callers must reach for the adapter directly.\n */\nexport async function resetFileSubstrate(path: string): Promise<void> {\n await ensureDir(path)\n await writeFile(path, \"\", \"utf8\")\n}\n\nfunction formatTurnBlock(turn: Turn): string {\n const header = `=== TURN id=${turn.id} participant=${turn.participantId} ts=${turn.timestamp} ===\\n`\n const body = turn.content.endsWith(\"\\n\") ? turn.content : `${turn.content}\\n`\n return `${header}${body}`\n}\n\nfunction parseJournal(raw: string): Turn[] {\n const lines = raw.split(\"\\n\")\n const turns: Turn[] = []\n let current: { id: string; pid: string; ts: string; buf: string[] } | null = null\n\n for (const line of lines) {\n const match = HEADER_RE.exec(line)\n if (match && match[1] && match[2] && match[3]) {\n if (current) turns.push(materialise(current))\n current = { id: match[1], pid: match[2], ts: match[3], buf: [] }\n continue\n }\n if (current) current.buf.push(line)\n }\n if (current) turns.push(materialise(current))\n return turns\n}\n\nfunction materialise(c: {\n id: string\n pid: string\n ts: string\n buf: string[]\n}): Turn {\n // Drop the trailing empty line that appendFile leaves between blocks.\n let body = c.buf.join(\"\\n\")\n while (body.endsWith(\"\\n\")) body = body.slice(0, -1)\n return {\n id: c.id,\n participantId: c.pid,\n timestamp: c.ts,\n content: body,\n }\n}\n\nfunction hashTurnId(pid: string, ts: string, content: string): string {\n const h = createHash(\"sha256\")\n h.update(pid)\n h.update(\"\\x00\")\n h.update(ts)\n h.update(\"\\x00\")\n h.update(content)\n return `t_${h.digest(\"hex\").slice(0, 12)}`\n}\n\nasync function ensureDir(path: string): Promise<void> {\n const dir = dirname(path)\n try {\n await stat(dir)\n } catch (err) {\n if (isNotFound(err)) {\n await mkdir(dir, { recursive: true })\n return\n }\n throw err\n }\n}\n\nfunction isNotFound(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n )\n}\n","/**\n * Canonical @-mention parser.\n *\n * Lives as raw JavaScript (no types) because it's consumed in two\n * places that don't share a build:\n *\n * 1. The kernel imports `textContainsMention` from this file as a\n * normal ESM module (the dispatcher in `adapters/dispatcher-mention.ts`).\n *\n * 2. Runtime profiles inline this file's source into Claude Code\n * hooks at profile-build time, because `.claude/` has no\n * module-resolution at hook-execution time. The build script\n * reads this file as text and stamps it into the hook template.\n *\n * Two cases:\n * 1. Literal `@<name>` substring (case-sensitive, full name).\n * 2. For multi-word names, also `@<firstName>` with non-word\n * boundary (case-insensitive).\n *\n * Edit here only — both consumers stay in sync via build pipelines.\n */\n\n/** @param {string} text @param {string} name @returns {boolean} */\nexport function textContainsMention(text, name) {\n if (text.includes(`@${name}`)) return true\n if (name.includes(\" \")) {\n const firstName = name.split(\" \")[0]?.trim()\n if (!firstName) return false\n const regex = new RegExp(`@${firstName}(?!\\\\w)`, \"i\")\n return regex.test(text)\n }\n return false\n}\n","/**\n * Mention dispatcher — selects participants whose displayName is\n * @-mentioned in the most recent turn.\n *\n * Skip rules:\n * - never re-select the participant who authored the trigger turn\n * (otherwise they'd reply to themselves indefinitely)\n * - never dispatch on a trigger we already processed (in-memory cursor —\n * prevents the loop from re-firing on the same @mention every poll\n * when the kernel's own reply isn't yet visible in the next read).\n * Per-dispatcher-instance state; a fresh swarm process starts with\n * no cursor and naturally responds to the latest unhandled mention\n * exactly once.\n * - if no mentions match any known participant, return [] (idle)\n *\n * The parser itself lives in `../util/mention-parser.mjs` (vanilla JS)\n * so runtime profiles can stamp the same implementation into Claude\n * Code hooks at build time without depending on the TS build pipeline.\n */\n\nimport type {\n Dispatcher,\n DispatcherInput,\n ParticipantId,\n TurnId,\n} from \"../ports.js\"\nimport { textContainsMention } from \"../util/mention-parser.mjs\"\n\nexport class MentionDispatcher implements Dispatcher {\n readonly kind = \"mention\"\n private lastProcessedTriggerId: TurnId | undefined\n\n async selectNext(input: DispatcherInput): Promise<readonly ParticipantId[]> {\n const trigger = input.recentTurns[input.recentTurns.length - 1]\n if (!trigger) return []\n if (trigger.id === this.lastProcessedTriggerId) return []\n const text = trigger.content\n\n const selected: ParticipantId[] = []\n for (const p of input.participants) {\n if (p.id === trigger.participantId) continue\n if (textContainsMention(text, p.displayName)) {\n selected.push(p.id)\n }\n }\n\n if (selected.length > 0) {\n this.lastProcessedTriggerId = trigger.id\n }\n return selected\n }\n}\n\n// Re-exported so callers writing their own adapters can detect\n// mentions with identical semantics.\nexport { textContainsMention }\n","/**\n * Filesystem state store — one JSON file per participant.\n *\n * <stateDir>/<participantId>.json\n *\n * Missing files read as {}. Writes are full overwrites; callers\n * pass the merged state, the adapter doesn't merge on its own.\n */\n\nimport { readFile, writeFile, mkdir, stat } from \"node:fs/promises\"\nimport { resolve as resolvePath } from \"node:path\"\nimport type { ParticipantId, StateStore } from \"../ports.js\"\n\nexport type FileStateStoreOptions = {\n /** Directory to hold the per-participant JSON files. */\n readonly dir: string\n}\n\nexport class FileStateStore implements StateStore {\n readonly kind = \"fs\"\n\n constructor(private readonly opts: FileStateStoreOptions) {}\n\n async read(participantId: ParticipantId): Promise<Readonly<Record<string, unknown>>> {\n const path = this.pathFor(participantId)\n try {\n const raw = await readFile(path, \"utf8\")\n return JSON.parse(raw) as Record<string, unknown>\n } catch (err) {\n if (isNotFound(err)) return Object.freeze({})\n throw err\n }\n }\n\n async write(\n participantId: ParticipantId,\n state: Readonly<Record<string, unknown>>\n ): Promise<void> {\n await ensureDir(this.opts.dir)\n const path = this.pathFor(participantId)\n await writeFile(path, JSON.stringify(state, null, 2), \"utf8\")\n }\n\n private pathFor(participantId: ParticipantId): string {\n // Sanitize: participant ids are user-controlled. Disallow path traversal.\n const safe = participantId.replace(/[^a-zA-Z0-9._-]/g, \"_\")\n return resolvePath(this.opts.dir, `${safe}.json`)\n }\n}\n\nasync function ensureDir(dir: string): Promise<void> {\n try {\n await stat(dir)\n } catch (err) {\n if (isNotFound(err)) {\n await mkdir(dir, { recursive: true })\n return\n }\n throw err\n }\n}\n\nfunction isNotFound(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n )\n}\n","import { spawn } from \"node:child_process\"\n\nexport interface SpawnWithStdinOptions {\n /** Executable to invoke (must be on PATH). */\n readonly command: string\n /** Static argv. The prompt is fed over stdin, not as an argument. */\n readonly args?: readonly string[]\n /** Text written to the child's stdin, then closed. */\n readonly stdin: string\n /** Working directory. Defaults to process.cwd(). */\n readonly cwd?: string\n /** Hard timeout in ms; the child is killed and the call rejects. Default 90000. */\n readonly timeoutMs?: number\n /** Abort the call — kills the child and rejects. */\n readonly signal?: AbortSignal\n /** Signal used to kill on timeout/abort. Default \"SIGTERM\". */\n readonly killSignal?: NodeJS.Signals\n}\n\n/**\n * Spawn a command in one-shot mode: write `stdin`, close it, capture stdout.\n *\n * Resolves with captured stdout on exit code 0; rejects on non-zero exit (with\n * trimmed stderr), spawn error, timeout, or abort. A single settle guard makes\n * the late `close` event after a kill a no-op.\n */\nexport function spawnWithStdin(opts: SpawnWithStdinOptions): Promise<string> {\n const {\n command,\n args = [],\n stdin,\n cwd,\n timeoutMs = 90_000,\n signal,\n killSignal = \"SIGTERM\",\n } = opts\n\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(`${command} aborted before start`))\n return\n }\n\n const child = spawn(command, [...args], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n ...(cwd ? { cwd } : {}),\n })\n\n let out = \"\"\n let err = \"\"\n let settled = false\n\n const finish = (fn: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n signal?.removeEventListener(\"abort\", onAbort)\n fn()\n }\n\n const onAbort = () => {\n child.kill(killSignal)\n finish(() => reject(new Error(`${command} aborted`)))\n }\n const timer = setTimeout(() => {\n child.kill(killSignal)\n finish(() => reject(new Error(`${command} timed out after ${timeoutMs}ms`)))\n }, timeoutMs)\n\n signal?.addEventListener(\"abort\", onAbort)\n\n child.stdout.on(\"data\", d => (out += d))\n child.stderr.on(\"data\", d => (err += d))\n child.on(\"error\", e =>\n finish(() => reject(new Error(`${command} not runnable: ${e.message}`)))\n )\n child.on(\"close\", code =>\n finish(() => {\n if (code === 0) resolve(out)\n else\n reject(\n new Error(`${command} exited with code ${code}: ${err.trim().slice(0, 200) || \"(no stderr)\"}`)\n )\n })\n )\n\n // child may exit before stdin drains → EPIPE on the stream; the close\n // handler already drives resolve/reject, so this write error is benign\n child.stdin.on(\"error\", () => {})\n child.stdin.write(stdin)\n child.stdin.end()\n })\n}\n","/**\n * Parse a `claude --output-format json` response: return the `result` field as\n * the model's text, or null if the JSON isn't that shape (caller falls back to\n * raw stdout). The same envelope is emitted by several agent CLIs in JSON mode.\n */\nexport function parseClaudeJsonOutput(stdout: string): string | null {\n try {\n const parsed = JSON.parse(stdout) as unknown\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"result\" in parsed &&\n typeof (parsed as { result: unknown }).result === \"string\"\n ) {\n return (parsed as { result: string }).result\n }\n return null\n } catch {\n return null\n }\n}\n","/**\n * Agent-CLI participant — spawns a CLI binary, pipes the assembled prompt\n * over stdin, and uses captured stdout as the turn content.\n *\n * Works for any CLI that supports a one-shot \"read prompt from stdin,\n * print response to stdout\" mode (claude-code's `--print`, hermes' `-p`,\n * etc.).\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport matter from \"gray-matter\"\nimport { spawnWithStdin } from \"@agentproto/cli-exec\"\nimport type {\n ParticipantExecuteInput,\n ParticipantExecuteOutput,\n ParticipantExecutor,\n} from \"../ports.js\"\n\n// Re-exported for back-compat: the JSON-envelope parser now lives in the shared\n// @agentproto/cli-exec package alongside the spawn helper.\nexport { parseClaudeJsonOutput } from \"@agentproto/cli-exec\"\n\nexport type AgentCliParticipantOptions = {\n /** Executable to invoke. Examples: \"claude\", \"hermes\", \"goose\". */\n readonly command: string\n /** Static args. The prompt is fed over stdin, not as an argument. */\n readonly args?: readonly string[]\n /** Working directory. Defaults to process.cwd(). */\n readonly cwd?: string\n /** Hard timeout in ms. Default 90000. */\n readonly timeoutMs?: number\n /** Optional output parser — if returns null, content falls back to raw stdout. */\n readonly parseOutput?: (stdout: string) => string | null\n}\n\nexport class AgentCliParticipant implements ParticipantExecutor {\n readonly kind = \"agent-cli\"\n\n constructor(private readonly opts: AgentCliParticipantOptions) {}\n\n async executeTurn(\n input: ParticipantExecuteInput\n ): Promise<ParticipantExecuteOutput> {\n const prompt = await assemblePrompt(input)\n const stdout = await spawnWithStdin({\n command: this.opts.command,\n args: this.opts.args ?? [],\n cwd: this.opts.cwd ?? process.cwd(),\n timeoutMs: this.opts.timeoutMs ?? 90000,\n stdin: prompt,\n signal: input.signal,\n })\n const parsed = this.opts.parseOutput?.(stdout) ?? null\n const content = parsed ?? stdout.trimEnd()\n return { content }\n }\n}\n\nasync function assemblePrompt(\n input: ParticipantExecuteInput\n): Promise<string> {\n const roleText = input.participant.role\n ? await loadRole(input.participant.role)\n : \"\"\n\n const transcript = input.recentTurns\n .map((t) => `[${t.participantId}] ${t.content}`)\n .join(\"\\n\\n\")\n\n return [\n roleText && `# Your role\\n\\n${roleText}`,\n `# Recent conversation\\n\\n${transcript}`,\n `# Your turn\\n\\nYou are ${input.participant.displayName}. The latest message in the conversation triggered you (most likely because it mentions you). Read the transcript above and reply in character. Keep it conversational unless the trigger asks for detailed work. Output only your reply — no preamble, no role labels, no quotes around the response.`,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\")\n}\n\n// File extensions we treat as a path-to-role-file. Anything else is\n// inline role text — even strings that contain `/`, which are common\n// in normal sentences (\"I am an AI/ML reviewer\").\nconst ROLE_FILE_EXTENSIONS = [\".md\", \".markdown\", \".txt\"]\n\nasync function loadRole(roleField: string): Promise<string> {\n if (!looksLikeRoleFile(roleField)) return roleField\n try {\n const raw = await readFile(roleField, \"utf8\")\n // Strip optional YAML frontmatter — lets a Claude Code agent\n // definition file (.claude/agents/*.md) double as a swarm role\n // without ferrying the agent's metadata into the prompt.\n const parsed = matter(raw)\n return parsed.content.trim()\n } catch (err) {\n // The string had a role-file extension but the file isn't readable\n // — surface a hint on stderr so authors don't silently get the\n // literal path as a prompt. Still fall back to inline so the swarm\n // doesn't crash on a typo.\n const code = (err as NodeJS.ErrnoException).code\n process.stderr.write(\n `agent-cli participant: role path '${roleField}' not readable (${code ?? \"unknown\"}); using the literal string as inline role text.\\n`\n )\n return roleField\n }\n}\n\nfunction looksLikeRoleFile(s: string): boolean {\n const lower = s.toLowerCase()\n return ROLE_FILE_EXTENSIONS.some((ext) => lower.endsWith(ext))\n}\n","/**\n * MultiAgentRuntime adapter registry — the seam third-party packages\n * use to plug substrates, dispatchers, participant executors, and\n * state stores into `agentproto run-swarm` without forking the CLI.\n *\n * A plugin module exports nothing required by name — it just imports\n * `register*` helpers from `@agentproto/cli/registry/runtime` and\n * calls them at module load. The CLI discovers plugins via:\n *\n * 1. `--plugin <module-id>` flags on `run-swarm`\n * 2. The `plugins[]` array in `~/.agentproto/config.json`\n * 3. Auto-registered built-ins (file substrate, mention dispatcher,\n * fs state, agent-cli participant) — registered by\n * `registerBuiltins()` at startup.\n *\n * Manifest `kind` strings are resolved through the registry: the kind\n * is the lookup key; the factory builds the concrete adapter from the\n * (loose) manifest config + shared context.\n */\n\nimport type {\n Dispatcher,\n ParticipantExecutor,\n StateStore,\n Substrate,\n} from \"@agentproto/agent-runtime\"\n\n// ── Context passed to every factory ──\n\n/**\n * Shared context every factory receives. Carries the manifest's base\n * directory (for resolving relative paths declared in adapter configs)\n * and a `cleanup` collector so adapters that hold disposable resources\n * (MCP clients, sockets, child processes) can register teardown callbacks\n * that the CLI runs on shutdown.\n */\nexport interface AdapterContext {\n /** Absolute directory of the manifest file. */\n readonly baseDir: string\n /** Register a teardown callback to run when the swarm shuts down. */\n registerCleanup(fn: () => Promise<void> | void): void\n}\n\n// ── Loose config shape ──\n\n/**\n * Manifest adapter blocks are loose: `{ kind: string, ...host-extension }`.\n * Each factory pulls its own typed fields off the config and validates\n * them inline.\n */\nexport interface AdapterConfig {\n readonly kind: string\n readonly [extension: string]: unknown\n}\n\n// ── Factory signatures ──\n\nexport type SubstrateFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Substrate> | Substrate\n\nexport type DispatcherFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Dispatcher> | Dispatcher\n\nexport type ExecutorFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<ParticipantExecutor> | ParticipantExecutor\n\nexport type StateStoreFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<StateStore> | StateStore\n\n// ── Registry state ──\n\nconst substrates = new Map<string, SubstrateFactory>()\nconst dispatchers = new Map<string, DispatcherFactory>()\nconst executors = new Map<string, ExecutorFactory>()\nconst stateStores = new Map<string, StateStoreFactory>()\n\n// ── Public registration API ──\n\nexport function registerSubstrate(kind: string, factory: SubstrateFactory): void {\n substrates.set(kind, factory)\n}\n\nexport function registerDispatcher(\n kind: string,\n factory: DispatcherFactory\n): void {\n dispatchers.set(kind, factory)\n}\n\nexport function registerExecutor(kind: string, factory: ExecutorFactory): void {\n executors.set(kind, factory)\n}\n\nexport function registerStateStore(\n kind: string,\n factory: StateStoreFactory\n): void {\n stateStores.set(kind, factory)\n}\n\n// ── Lookup API (used by run-swarm wiring) ──\n\nexport function getSubstrateFactory(kind: string): SubstrateFactory | undefined {\n return substrates.get(kind)\n}\n\nexport function getDispatcherFactory(\n kind: string\n): DispatcherFactory | undefined {\n return dispatchers.get(kind)\n}\n\nexport function getExecutorFactory(kind: string): ExecutorFactory | undefined {\n return executors.get(kind)\n}\n\nexport function getStateStoreFactory(\n kind: string\n): StateStoreFactory | undefined {\n return stateStores.get(kind)\n}\n\nexport function listRegisteredKinds(): {\n substrates: readonly string[]\n dispatchers: readonly string[]\n executors: readonly string[]\n stateStores: readonly string[]\n} {\n return {\n substrates: [...substrates.keys()],\n dispatchers: [...dispatchers.keys()],\n executors: [...executors.keys()],\n stateStores: [...stateStores.keys()],\n }\n}\n\n/**\n * Test-only: drop every registration. Plugin registrations persist for\n * the lifetime of the process, so tests that load + unload plugins use\n * this to start from a clean slate.\n */\nexport function _resetRegistryForTests(): void {\n substrates.clear()\n dispatchers.clear()\n executors.clear()\n stateStores.clear()\n}\n","/**\n * Built-in MultiAgentRuntime adapters. Registers reference adapters\n * shipped by `@agentproto/agent-runtime` against the runtime registry\n * so a vanilla `agentproto run-swarm` works without any plugins.\n *\n * Built-in `kind` strings: `file`, `mention`, `fs`, `agent-cli`.\n */\n\nimport { resolve as resolvePath } from \"node:path\"\nimport { FileSubstrate } from \"@agentproto/agent-runtime/adapters/substrate-file\"\nimport { MentionDispatcher } from \"@agentproto/agent-runtime/adapters/dispatcher-mention\"\nimport { FileStateStore } from \"@agentproto/agent-runtime/adapters/state-fs\"\nimport {\n AgentCliParticipant,\n parseClaudeJsonOutput,\n} from \"@agentproto/agent-runtime/adapters/participant-agent-cli\"\nimport {\n registerDispatcher,\n registerExecutor,\n registerStateStore,\n registerSubstrate,\n type AdapterConfig,\n type AdapterContext,\n} from \"./runtime.js\"\n\nexport function registerBuiltins(): void {\n registerSubstrate(\"file\", (cfg, ctx) => {\n const path = typeof cfg.path === \"string\" ? cfg.path : \".runtime/conversation.md\"\n return new FileSubstrate({ path: resolvePath(ctx.baseDir, path) })\n })\n\n registerDispatcher(\"mention\", () => new MentionDispatcher())\n\n registerStateStore(\"fs\", (cfg, ctx) => {\n const dir = typeof cfg.dir === \"string\" ? cfg.dir : \".runtime/state\"\n return new FileStateStore({ dir: resolvePath(ctx.baseDir, dir) })\n })\n\n registerExecutor(\"agent-cli\", (cfg) => buildAgentCli(cfg))\n}\n\nfunction buildAgentCli(cfg: AdapterConfig): AgentCliParticipant {\n const command = typeof cfg.command === \"string\" ? cfg.command : \"claude\"\n const args = Array.isArray(cfg.args)\n ? cfg.args.filter((a): a is string => typeof a === \"string\")\n : [\"--print\", \"--output-format=json\"]\n const useClaudeJson = cfg.parseJson !== false && command === \"claude\"\n return new AgentCliParticipant({\n command,\n args,\n parseOutput: useClaudeJson ? parseClaudeJsonOutput : undefined,\n })\n}\n\n// Suppress unused-context warning on registrations that don't read it.\nexport type { AdapterContext }\n"]}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
* @agentproto/cli v0.
|
|
5
|
+
* @agentproto/cli v0.3.0
|
|
5
6
|
* The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
+
// Provide a real `require` in the ESM bundle. Bundling the Ink stack pulls in
|
|
9
|
+
// CJS deps (e.g. signal-exit@3) that call `require("assert")`; without this
|
|
10
|
+
// esbuild's interop shim throws "Dynamic require is not supported".
|
|
11
|
+
createRequire(import.meta.url);
|
|
8
12
|
var PLUGIN_MANIFEST_SCHEMA = "agentproto/plugin/v1";
|
|
9
13
|
var AdapterEntrySchema = z.object({
|
|
10
14
|
/** The `kind` string the manifest's substrate/dispatcher/etc. block uses. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/registry/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/registry/manifest.ts"],"names":[],"mappings":";;;;;;;;;;;AAyCO,IAAM,sBAAA,GAAyB;AAEtC,IAAM,kBAAA,GAAqB,EACxB,MAAA,CAAO;AAAA;AAAA,EAEN,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEvB,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAExB,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAC1B,CAAC,EACA,KAAA,EAAM;AAET,IAAM,oBAAA,GAAuB,mBAAmB,MAAA,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrD,cAAc,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA;AACpC,CAAC,CAAA;AAEM,IAAM,oBAAA,GAAuB,EACjC,MAAA,CAAO;AAAA,EACN,MAAA,EAAQ,CAAA,CAAE,OAAA,CAAQ,sBAAsB,CAAA;AAAA,EACxC,YAAY,CAAA,CAAE,KAAA,CAAM,oBAAoB,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACpD,aAAa,CAAA,CAAE,KAAA,CAAM,kBAAkB,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACnD,WAAW,CAAA,CAAE,KAAA,CAAM,kBAAkB,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACjD,aAAa,CAAA,CAAE,KAAA,CAAM,kBAAkB,CAAA,CAAE,OAAA,CAAQ,EAAE;AACrD,CAAC,EACA,KAAA","file":"manifest.mjs","sourcesContent":["/**\n * Plugin manifest — `agentproto/plugin/v1`.\n *\n * Plugins declare what they provide in either:\n * - their `package.json` under the `agentproto` key, OR\n * - a standalone `agentproto.json` next to their `package.json`.\n *\n * The CLI reads this manifest, dynamic-imports each adapter entry,\n * and registers it with the runtime registry. Plugins don't need\n * side-effect imports any more — they just export their factory\n * functions and let the manifest do the wiring.\n *\n * Example (in @guilde/agentproto-bridge's package.json):\n *\n * {\n * \"name\": \"@guilde/agentproto-bridge\",\n * \"agentproto\": {\n * \"schema\": \"agentproto/plugin/v1\",\n * \"substrates\": [\n * {\n * \"kind\": \"guilde-mcp\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"guildeMcpSubstrateFactory\",\n * \"capabilities\": [\"mentions\", \"reactions\", \"identity\"],\n * \"description\": \"Reads/writes turns through Guilde's MCP server.\"\n * }\n * ],\n * \"executors\": [\n * {\n * \"kind\": \"db-operator\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"dbOperatorExecutorFactory\",\n * \"description\": \"Delegates to Mastra operators via run_operator.\"\n * }\n * ]\n * }\n * }\n */\n\nimport { z } from \"zod\"\n\nexport const PLUGIN_MANIFEST_SCHEMA = \"agentproto/plugin/v1\" as const\n\nconst AdapterEntrySchema = z\n .object({\n /** The `kind` string the manifest's substrate/dispatcher/etc. block uses. */\n kind: z.string().min(1),\n /**\n * Path to the entry module, relative to the plugin package root.\n * Resolved via the plugin's `package.json#main`/`exports` (i.e. you\n * can use a subpath like `./dist/substrates.mjs` or an export name\n * like `.` if the plugin re-exports everything from its root).\n */\n entry: z.string().min(1),\n /** Named export inside `entry` — the factory function. */\n export: z.string().min(1),\n /** Free-form description; shown by `agentproto plugins show`. */\n description: z.string().optional(),\n })\n .loose()\n\nconst SubstrateEntrySchema = AdapterEntrySchema.extend({\n /**\n * Free-form capability tags. Not gated by the kernel yet, but\n * surfaced by `agentproto plugins show` so users can see what the\n * substrate claims to support (mentions, reactions, visibility, …).\n */\n capabilities: z.array(z.string()).optional(),\n})\n\nexport const PluginManifestSchema = z\n .object({\n schema: z.literal(PLUGIN_MANIFEST_SCHEMA),\n substrates: z.array(SubstrateEntrySchema).default([]),\n dispatchers: z.array(AdapterEntrySchema).default([]),\n executors: z.array(AdapterEntrySchema).default([]),\n stateStores: z.array(AdapterEntrySchema).default([]),\n })\n .loose()\n\nexport type PluginManifest = z.infer<typeof PluginManifestSchema>\nexport type AdapterEntry = z.infer<typeof AdapterEntrySchema>\nexport type SubstrateEntry = z.infer<typeof SubstrateEntrySchema>\n"]}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { readFile } from 'fs/promises';
|
|
2
3
|
import { homedir } from 'os';
|
|
3
4
|
import { join, dirname } from 'path';
|
|
4
|
-
import { createRequire } from 'module';
|
|
5
|
+
import { createRequire as createRequire$1 } from 'module';
|
|
5
6
|
import { pathToFileURL } from 'url';
|
|
6
7
|
import { z } from 'zod';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* @agentproto/cli v0.
|
|
10
|
+
* @agentproto/cli v0.3.0
|
|
10
11
|
* The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
// Provide a real `require` in the ESM bundle. Bundling the Ink stack pulls in
|
|
14
|
+
// CJS deps (e.g. signal-exit@3) that call `require("assert")`; without this
|
|
15
|
+
// esbuild's interop shim throws "Dynamic require is not supported".
|
|
16
|
+
createRequire(import.meta.url);
|
|
13
17
|
var PLUGIN_MANIFEST_SCHEMA = "agentproto/plugin/v1";
|
|
14
18
|
var AdapterEntrySchema = z.object({
|
|
15
19
|
/** The `kind` string the manifest's substrate/dispatcher/etc. block uses. */
|
|
@@ -143,7 +147,7 @@ function resolvePluginPackageJson(pluginId) {
|
|
|
143
147
|
];
|
|
144
148
|
for (const root of candidates) {
|
|
145
149
|
try {
|
|
146
|
-
return createRequire(root).resolve(`${pluginId}/package.json`);
|
|
150
|
+
return createRequire$1(root).resolve(`${pluginId}/package.json`);
|
|
147
151
|
} catch {
|
|
148
152
|
}
|
|
149
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/registry/manifest.ts","../../src/registry/runtime.ts","../../src/registry/manifest-loader.ts","../../src/registry/plugins.ts"],"names":["readFile","join"],"mappings":"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","file":"plugins.mjs","sourcesContent":["/**\n * Plugin manifest — `agentproto/plugin/v1`.\n *\n * Plugins declare what they provide in either:\n * - their `package.json` under the `agentproto` key, OR\n * - a standalone `agentproto.json` next to their `package.json`.\n *\n * The CLI reads this manifest, dynamic-imports each adapter entry,\n * and registers it with the runtime registry. Plugins don't need\n * side-effect imports any more — they just export their factory\n * functions and let the manifest do the wiring.\n *\n * Example (in @guilde/agentproto-bridge's package.json):\n *\n * {\n * \"name\": \"@guilde/agentproto-bridge\",\n * \"agentproto\": {\n * \"schema\": \"agentproto/plugin/v1\",\n * \"substrates\": [\n * {\n * \"kind\": \"guilde-mcp\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"guildeMcpSubstrateFactory\",\n * \"capabilities\": [\"mentions\", \"reactions\", \"identity\"],\n * \"description\": \"Reads/writes turns through Guilde's MCP server.\"\n * }\n * ],\n * \"executors\": [\n * {\n * \"kind\": \"db-operator\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"dbOperatorExecutorFactory\",\n * \"description\": \"Delegates to Mastra operators via run_operator.\"\n * }\n * ]\n * }\n * }\n */\n\nimport { z } from \"zod\"\n\nexport const PLUGIN_MANIFEST_SCHEMA = \"agentproto/plugin/v1\" as const\n\nconst AdapterEntrySchema = z\n .object({\n /** The `kind` string the manifest's substrate/dispatcher/etc. block uses. */\n kind: z.string().min(1),\n /**\n * Path to the entry module, relative to the plugin package root.\n * Resolved via the plugin's `package.json#main`/`exports` (i.e. you\n * can use a subpath like `./dist/substrates.mjs` or an export name\n * like `.` if the plugin re-exports everything from its root).\n */\n entry: z.string().min(1),\n /** Named export inside `entry` — the factory function. */\n export: z.string().min(1),\n /** Free-form description; shown by `agentproto plugins show`. */\n description: z.string().optional(),\n })\n .loose()\n\nconst SubstrateEntrySchema = AdapterEntrySchema.extend({\n /**\n * Free-form capability tags. Not gated by the kernel yet, but\n * surfaced by `agentproto plugins show` so users can see what the\n * substrate claims to support (mentions, reactions, visibility, …).\n */\n capabilities: z.array(z.string()).optional(),\n})\n\nexport const PluginManifestSchema = z\n .object({\n schema: z.literal(PLUGIN_MANIFEST_SCHEMA),\n substrates: z.array(SubstrateEntrySchema).default([]),\n dispatchers: z.array(AdapterEntrySchema).default([]),\n executors: z.array(AdapterEntrySchema).default([]),\n stateStores: z.array(AdapterEntrySchema).default([]),\n })\n .loose()\n\nexport type PluginManifest = z.infer<typeof PluginManifestSchema>\nexport type AdapterEntry = z.infer<typeof AdapterEntrySchema>\nexport type SubstrateEntry = z.infer<typeof SubstrateEntrySchema>\n","/**\n * MultiAgentRuntime adapter registry — the seam third-party packages\n * use to plug substrates, dispatchers, participant executors, and\n * state stores into `agentproto run-swarm` without forking the CLI.\n *\n * A plugin module exports nothing required by name — it just imports\n * `register*` helpers from `@agentproto/cli/registry/runtime` and\n * calls them at module load. The CLI discovers plugins via:\n *\n * 1. `--plugin <module-id>` flags on `run-swarm`\n * 2. The `plugins[]` array in `~/.agentproto/config.json`\n * 3. Auto-registered built-ins (file substrate, mention dispatcher,\n * fs state, agent-cli participant) — registered by\n * `registerBuiltins()` at startup.\n *\n * Manifest `kind` strings are resolved through the registry: the kind\n * is the lookup key; the factory builds the concrete adapter from the\n * (loose) manifest config + shared context.\n */\n\nimport type {\n Dispatcher,\n ParticipantExecutor,\n StateStore,\n Substrate,\n} from \"@agentproto/agent-runtime\"\n\n// ── Context passed to every factory ──\n\n/**\n * Shared context every factory receives. Carries the manifest's base\n * directory (for resolving relative paths declared in adapter configs)\n * and a `cleanup` collector so adapters that hold disposable resources\n * (MCP clients, sockets, child processes) can register teardown callbacks\n * that the CLI runs on shutdown.\n */\nexport interface AdapterContext {\n /** Absolute directory of the manifest file. */\n readonly baseDir: string\n /** Register a teardown callback to run when the swarm shuts down. */\n registerCleanup(fn: () => Promise<void> | void): void\n}\n\n// ── Loose config shape ──\n\n/**\n * Manifest adapter blocks are loose: `{ kind: string, ...host-extension }`.\n * Each factory pulls its own typed fields off the config and validates\n * them inline.\n */\nexport interface AdapterConfig {\n readonly kind: string\n readonly [extension: string]: unknown\n}\n\n// ── Factory signatures ──\n\nexport type SubstrateFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Substrate> | Substrate\n\nexport type DispatcherFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Dispatcher> | Dispatcher\n\nexport type ExecutorFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<ParticipantExecutor> | ParticipantExecutor\n\nexport type StateStoreFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<StateStore> | StateStore\n\n// ── Registry state ──\n\nconst substrates = new Map<string, SubstrateFactory>()\nconst dispatchers = new Map<string, DispatcherFactory>()\nconst executors = new Map<string, ExecutorFactory>()\nconst stateStores = new Map<string, StateStoreFactory>()\n\n// ── Public registration API ──\n\nexport function registerSubstrate(kind: string, factory: SubstrateFactory): void {\n substrates.set(kind, factory)\n}\n\nexport function registerDispatcher(\n kind: string,\n factory: DispatcherFactory\n): void {\n dispatchers.set(kind, factory)\n}\n\nexport function registerExecutor(kind: string, factory: ExecutorFactory): void {\n executors.set(kind, factory)\n}\n\nexport function registerStateStore(\n kind: string,\n factory: StateStoreFactory\n): void {\n stateStores.set(kind, factory)\n}\n\n// ── Lookup API (used by run-swarm wiring) ──\n\nexport function getSubstrateFactory(kind: string): SubstrateFactory | undefined {\n return substrates.get(kind)\n}\n\nexport function getDispatcherFactory(\n kind: string\n): DispatcherFactory | undefined {\n return dispatchers.get(kind)\n}\n\nexport function getExecutorFactory(kind: string): ExecutorFactory | undefined {\n return executors.get(kind)\n}\n\nexport function getStateStoreFactory(\n kind: string\n): StateStoreFactory | undefined {\n return stateStores.get(kind)\n}\n\nexport function listRegisteredKinds(): {\n substrates: readonly string[]\n dispatchers: readonly string[]\n executors: readonly string[]\n stateStores: readonly string[]\n} {\n return {\n substrates: [...substrates.keys()],\n dispatchers: [...dispatchers.keys()],\n executors: [...executors.keys()],\n stateStores: [...stateStores.keys()],\n }\n}\n\n/**\n * Test-only: drop every registration. Plugin registrations persist for\n * the lifetime of the process, so tests that load + unload plugins use\n * this to start from a clean slate.\n */\nexport function _resetRegistryForTests(): void {\n substrates.clear()\n dispatchers.clear()\n executors.clear()\n stateStores.clear()\n}\n","/**\n * Manifest-based plugin wiring.\n *\n * Given a plugin package id, locate its plugin manifest, validate it,\n * and register every declared adapter (substrate, dispatcher,\n * executor, state store) with the runtime registry. The plugin\n * doesn't need to call register* itself — the manifest declares what\n * it provides, this loader handles the wiring.\n *\n * Discovery order, per plugin:\n * 1. `<package-root>/agentproto.json`\n * 2. `<package-root>/package.json` → `.agentproto` block\n *\n * Returns the manifest (so callers like `agentproto plugins show` can\n * print it) or `null` if neither location declares one. A `null`\n * return is not an error — the caller may fall back to side-effect\n * imports for legacy plugins.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { dirname, join } from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\nimport {\n PluginManifestSchema,\n type PluginManifest,\n} from \"./manifest.js\"\nimport {\n registerDispatcher,\n registerExecutor,\n registerStateStore,\n registerSubstrate,\n type DispatcherFactory,\n type ExecutorFactory,\n type StateStoreFactory,\n type SubstrateFactory,\n} from \"./runtime.js\"\n\n/**\n * Load and register every adapter declared in a plugin's manifest.\n * Returns the manifest on success, `null` if the plugin doesn't ship\n * one (so the caller can fall back to side-effect import).\n */\nexport async function loadPluginFromManifest(\n pluginId: string\n): Promise<PluginManifest | null> {\n const result = await readPluginManifest(pluginId)\n if (!result) return null\n const { manifest, packageRoot } = result\n\n for (const sub of manifest.substrates) {\n const factory = await importFactory<SubstrateFactory>(\n packageRoot,\n pluginId,\n sub.entry,\n sub.export\n )\n registerSubstrate(sub.kind, factory)\n }\n for (const dis of manifest.dispatchers) {\n const factory = await importFactory<DispatcherFactory>(\n packageRoot,\n pluginId,\n dis.entry,\n dis.export\n )\n registerDispatcher(dis.kind, factory)\n }\n for (const exe of manifest.executors) {\n const factory = await importFactory<ExecutorFactory>(\n packageRoot,\n pluginId,\n exe.entry,\n exe.export\n )\n registerExecutor(exe.kind, factory)\n }\n for (const st of manifest.stateStores) {\n const factory = await importFactory<StateStoreFactory>(\n packageRoot,\n pluginId,\n st.entry,\n st.export\n )\n registerStateStore(st.kind, factory)\n }\n\n return manifest\n}\n\n/**\n * Read + validate a plugin's manifest without registering anything.\n * Used by `agentproto plugins show` to introspect installed plugins.\n */\nexport async function readPluginManifest(\n pluginId: string\n): Promise<{ manifest: PluginManifest; packageRoot: string } | null> {\n const packageJsonPath = resolvePluginPackageJson(pluginId)\n if (!packageJsonPath) return null\n\n const packageRoot = dirname(packageJsonPath)\n\n // 1. Try standalone agentproto.json first.\n const standalonePath = join(packageRoot, \"agentproto.json\")\n const standalone = await readJsonIfExists(standalonePath)\n if (standalone !== undefined) {\n return {\n manifest: PluginManifestSchema.parse(standalone),\n packageRoot,\n }\n }\n\n // 2. Fall back to package.json#agentproto.\n const pkgJson = (await readJsonIfExists(packageJsonPath)) as\n | { agentproto?: unknown }\n | undefined\n if (pkgJson && typeof pkgJson === \"object\" && pkgJson.agentproto) {\n return {\n manifest: PluginManifestSchema.parse(pkgJson.agentproto),\n packageRoot,\n }\n }\n\n return null\n}\n\nasync function importFactory<TFactory>(\n packageRoot: string,\n pluginId: string,\n entry: string,\n exportName: string\n): Promise<TFactory> {\n // Resolve the entry path relative to the package root. We dynamic-\n // import via file:// URL so an absolute path works without going\n // through Node's package resolver (which would need the export to\n // be declared in `exports`).\n const abs = entry.startsWith(\".\") ? join(packageRoot, entry) : entry\n const url = entry.startsWith(\".\") ? pathToFileURL(abs).href : entry\n const mod = (await import(url)) as Record<string, unknown>\n const exported = mod[exportName]\n if (typeof exported !== \"function\") {\n throw new Error(\n `agentproto plugin '${pluginId}': manifest entry '${entry}' has no callable export '${exportName}' (got ${typeof exported}).`\n )\n }\n return exported as TFactory\n}\n\nfunction resolvePluginPackageJson(pluginId: string): string | null {\n // Try the cli's own resolution first (global install + monorepo\n // workspace deps), then the user's cwd (locally-installed plugins).\n // `require.resolve` needs `createRequire` since we're an ESM bundle.\n const candidates = [\n import.meta.url,\n pathToFileURL(join(process.cwd(), \"package.json\")).href,\n ]\n for (const root of candidates) {\n try {\n return createRequire(root).resolve(`${pluginId}/package.json`)\n } catch {\n // try next root\n }\n }\n return null\n}\n\nasync function readJsonIfExists(path: string): Promise<unknown> {\n try {\n const raw = await readFile(path, \"utf8\")\n return JSON.parse(raw)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined\n throw err\n }\n}\n","/**\n * Plugin loader. For each plugin id:\n *\n * 1. Try manifest-based wiring — read the plugin's\n * `package.json#agentproto` (or standalone `agentproto.json`),\n * validate the `agentproto/plugin/v1` schema, dynamic-import\n * each declared adapter entry, register with the runtime\n * registry.\n * 2. Fall back to side-effect import — older plugins that just\n * `registerSubstrate(...)` at module load are still supported.\n *\n * Discovery sources for plugin ids:\n * - `--plugin <module-id>` flag(s) on the verb\n * - `plugins[]` array in `~/.agentproto/config.json`\n *\n * Failures: a plugin that throws on load is reported on stderr and\n * the load skips it. The CLI continues — a single bad plugin\n * shouldn't take down the swarm.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { loadPluginFromManifest } from \"./manifest-loader.js\"\n\ninterface AgentprotoConfig {\n plugins?: readonly string[]\n}\n\nexport async function loadPluginsFromConfig(): Promise<readonly string[]> {\n const path = configPath()\n try {\n const raw = await readFile(path, \"utf8\")\n const parsed = JSON.parse(raw) as AgentprotoConfig\n return parsed.plugins ?? []\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return []\n process.stderr.write(\n `agentproto: failed to read ${path} — ${err instanceof Error ? err.message : String(err)}\\n`\n )\n return []\n }\n}\n\nexport async function loadPlugins(moduleIds: readonly string[]): Promise<void> {\n for (const id of moduleIds) {\n try {\n const manifest = await loadPluginFromManifest(id)\n if (manifest === null) {\n // No manifest declared → side-effect import for legacy plugins.\n await import(id)\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n process.stderr.write(\n `agentproto: plugin '${id}' failed to load — ${msg}\\n`\n )\n }\n }\n}\n\nfunction configPath(): string {\n const base = process.env[\"AGENTPROTO_HOME\"] ?? join(homedir(), \".agentproto\")\n return join(base, \"config.json\")\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/registry/manifest.ts","../../src/registry/runtime.ts","../../src/registry/manifest-loader.ts","../../src/registry/plugins.ts"],"names":["createRequire","readFile","join"],"mappings":"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","file":"plugins.mjs","sourcesContent":["/**\n * Plugin manifest — `agentproto/plugin/v1`.\n *\n * Plugins declare what they provide in either:\n * - their `package.json` under the `agentproto` key, OR\n * - a standalone `agentproto.json` next to their `package.json`.\n *\n * The CLI reads this manifest, dynamic-imports each adapter entry,\n * and registers it with the runtime registry. Plugins don't need\n * side-effect imports any more — they just export their factory\n * functions and let the manifest do the wiring.\n *\n * Example (in @guilde/agentproto-bridge's package.json):\n *\n * {\n * \"name\": \"@guilde/agentproto-bridge\",\n * \"agentproto\": {\n * \"schema\": \"agentproto/plugin/v1\",\n * \"substrates\": [\n * {\n * \"kind\": \"guilde-mcp\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"guildeMcpSubstrateFactory\",\n * \"capabilities\": [\"mentions\", \"reactions\", \"identity\"],\n * \"description\": \"Reads/writes turns through Guilde's MCP server.\"\n * }\n * ],\n * \"executors\": [\n * {\n * \"kind\": \"db-operator\",\n * \"entry\": \"./dist/index.mjs\",\n * \"export\": \"dbOperatorExecutorFactory\",\n * \"description\": \"Delegates to Mastra operators via run_operator.\"\n * }\n * ]\n * }\n * }\n */\n\nimport { z } from \"zod\"\n\nexport const PLUGIN_MANIFEST_SCHEMA = \"agentproto/plugin/v1\" as const\n\nconst AdapterEntrySchema = z\n .object({\n /** The `kind` string the manifest's substrate/dispatcher/etc. block uses. */\n kind: z.string().min(1),\n /**\n * Path to the entry module, relative to the plugin package root.\n * Resolved via the plugin's `package.json#main`/`exports` (i.e. you\n * can use a subpath like `./dist/substrates.mjs` or an export name\n * like `.` if the plugin re-exports everything from its root).\n */\n entry: z.string().min(1),\n /** Named export inside `entry` — the factory function. */\n export: z.string().min(1),\n /** Free-form description; shown by `agentproto plugins show`. */\n description: z.string().optional(),\n })\n .loose()\n\nconst SubstrateEntrySchema = AdapterEntrySchema.extend({\n /**\n * Free-form capability tags. Not gated by the kernel yet, but\n * surfaced by `agentproto plugins show` so users can see what the\n * substrate claims to support (mentions, reactions, visibility, …).\n */\n capabilities: z.array(z.string()).optional(),\n})\n\nexport const PluginManifestSchema = z\n .object({\n schema: z.literal(PLUGIN_MANIFEST_SCHEMA),\n substrates: z.array(SubstrateEntrySchema).default([]),\n dispatchers: z.array(AdapterEntrySchema).default([]),\n executors: z.array(AdapterEntrySchema).default([]),\n stateStores: z.array(AdapterEntrySchema).default([]),\n })\n .loose()\n\nexport type PluginManifest = z.infer<typeof PluginManifestSchema>\nexport type AdapterEntry = z.infer<typeof AdapterEntrySchema>\nexport type SubstrateEntry = z.infer<typeof SubstrateEntrySchema>\n","/**\n * MultiAgentRuntime adapter registry — the seam third-party packages\n * use to plug substrates, dispatchers, participant executors, and\n * state stores into `agentproto run-swarm` without forking the CLI.\n *\n * A plugin module exports nothing required by name — it just imports\n * `register*` helpers from `@agentproto/cli/registry/runtime` and\n * calls them at module load. The CLI discovers plugins via:\n *\n * 1. `--plugin <module-id>` flags on `run-swarm`\n * 2. The `plugins[]` array in `~/.agentproto/config.json`\n * 3. Auto-registered built-ins (file substrate, mention dispatcher,\n * fs state, agent-cli participant) — registered by\n * `registerBuiltins()` at startup.\n *\n * Manifest `kind` strings are resolved through the registry: the kind\n * is the lookup key; the factory builds the concrete adapter from the\n * (loose) manifest config + shared context.\n */\n\nimport type {\n Dispatcher,\n ParticipantExecutor,\n StateStore,\n Substrate,\n} from \"@agentproto/agent-runtime\"\n\n// ── Context passed to every factory ──\n\n/**\n * Shared context every factory receives. Carries the manifest's base\n * directory (for resolving relative paths declared in adapter configs)\n * and a `cleanup` collector so adapters that hold disposable resources\n * (MCP clients, sockets, child processes) can register teardown callbacks\n * that the CLI runs on shutdown.\n */\nexport interface AdapterContext {\n /** Absolute directory of the manifest file. */\n readonly baseDir: string\n /** Register a teardown callback to run when the swarm shuts down. */\n registerCleanup(fn: () => Promise<void> | void): void\n}\n\n// ── Loose config shape ──\n\n/**\n * Manifest adapter blocks are loose: `{ kind: string, ...host-extension }`.\n * Each factory pulls its own typed fields off the config and validates\n * them inline.\n */\nexport interface AdapterConfig {\n readonly kind: string\n readonly [extension: string]: unknown\n}\n\n// ── Factory signatures ──\n\nexport type SubstrateFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Substrate> | Substrate\n\nexport type DispatcherFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Dispatcher> | Dispatcher\n\nexport type ExecutorFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<ParticipantExecutor> | ParticipantExecutor\n\nexport type StateStoreFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<StateStore> | StateStore\n\n// ── Registry state ──\n\nconst substrates = new Map<string, SubstrateFactory>()\nconst dispatchers = new Map<string, DispatcherFactory>()\nconst executors = new Map<string, ExecutorFactory>()\nconst stateStores = new Map<string, StateStoreFactory>()\n\n// ── Public registration API ──\n\nexport function registerSubstrate(kind: string, factory: SubstrateFactory): void {\n substrates.set(kind, factory)\n}\n\nexport function registerDispatcher(\n kind: string,\n factory: DispatcherFactory\n): void {\n dispatchers.set(kind, factory)\n}\n\nexport function registerExecutor(kind: string, factory: ExecutorFactory): void {\n executors.set(kind, factory)\n}\n\nexport function registerStateStore(\n kind: string,\n factory: StateStoreFactory\n): void {\n stateStores.set(kind, factory)\n}\n\n// ── Lookup API (used by run-swarm wiring) ──\n\nexport function getSubstrateFactory(kind: string): SubstrateFactory | undefined {\n return substrates.get(kind)\n}\n\nexport function getDispatcherFactory(\n kind: string\n): DispatcherFactory | undefined {\n return dispatchers.get(kind)\n}\n\nexport function getExecutorFactory(kind: string): ExecutorFactory | undefined {\n return executors.get(kind)\n}\n\nexport function getStateStoreFactory(\n kind: string\n): StateStoreFactory | undefined {\n return stateStores.get(kind)\n}\n\nexport function listRegisteredKinds(): {\n substrates: readonly string[]\n dispatchers: readonly string[]\n executors: readonly string[]\n stateStores: readonly string[]\n} {\n return {\n substrates: [...substrates.keys()],\n dispatchers: [...dispatchers.keys()],\n executors: [...executors.keys()],\n stateStores: [...stateStores.keys()],\n }\n}\n\n/**\n * Test-only: drop every registration. Plugin registrations persist for\n * the lifetime of the process, so tests that load + unload plugins use\n * this to start from a clean slate.\n */\nexport function _resetRegistryForTests(): void {\n substrates.clear()\n dispatchers.clear()\n executors.clear()\n stateStores.clear()\n}\n","/**\n * Manifest-based plugin wiring.\n *\n * Given a plugin package id, locate its plugin manifest, validate it,\n * and register every declared adapter (substrate, dispatcher,\n * executor, state store) with the runtime registry. The plugin\n * doesn't need to call register* itself — the manifest declares what\n * it provides, this loader handles the wiring.\n *\n * Discovery order, per plugin:\n * 1. `<package-root>/agentproto.json`\n * 2. `<package-root>/package.json` → `.agentproto` block\n *\n * Returns the manifest (so callers like `agentproto plugins show` can\n * print it) or `null` if neither location declares one. A `null`\n * return is not an error — the caller may fall back to side-effect\n * imports for legacy plugins.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { dirname, join } from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\nimport {\n PluginManifestSchema,\n type PluginManifest,\n} from \"./manifest.js\"\nimport {\n registerDispatcher,\n registerExecutor,\n registerStateStore,\n registerSubstrate,\n type DispatcherFactory,\n type ExecutorFactory,\n type StateStoreFactory,\n type SubstrateFactory,\n} from \"./runtime.js\"\n\n/**\n * Load and register every adapter declared in a plugin's manifest.\n * Returns the manifest on success, `null` if the plugin doesn't ship\n * one (so the caller can fall back to side-effect import).\n */\nexport async function loadPluginFromManifest(\n pluginId: string\n): Promise<PluginManifest | null> {\n const result = await readPluginManifest(pluginId)\n if (!result) return null\n const { manifest, packageRoot } = result\n\n for (const sub of manifest.substrates) {\n const factory = await importFactory<SubstrateFactory>(\n packageRoot,\n pluginId,\n sub.entry,\n sub.export\n )\n registerSubstrate(sub.kind, factory)\n }\n for (const dis of manifest.dispatchers) {\n const factory = await importFactory<DispatcherFactory>(\n packageRoot,\n pluginId,\n dis.entry,\n dis.export\n )\n registerDispatcher(dis.kind, factory)\n }\n for (const exe of manifest.executors) {\n const factory = await importFactory<ExecutorFactory>(\n packageRoot,\n pluginId,\n exe.entry,\n exe.export\n )\n registerExecutor(exe.kind, factory)\n }\n for (const st of manifest.stateStores) {\n const factory = await importFactory<StateStoreFactory>(\n packageRoot,\n pluginId,\n st.entry,\n st.export\n )\n registerStateStore(st.kind, factory)\n }\n\n return manifest\n}\n\n/**\n * Read + validate a plugin's manifest without registering anything.\n * Used by `agentproto plugins show` to introspect installed plugins.\n */\nexport async function readPluginManifest(\n pluginId: string\n): Promise<{ manifest: PluginManifest; packageRoot: string } | null> {\n const packageJsonPath = resolvePluginPackageJson(pluginId)\n if (!packageJsonPath) return null\n\n const packageRoot = dirname(packageJsonPath)\n\n // 1. Try standalone agentproto.json first.\n const standalonePath = join(packageRoot, \"agentproto.json\")\n const standalone = await readJsonIfExists(standalonePath)\n if (standalone !== undefined) {\n return {\n manifest: PluginManifestSchema.parse(standalone),\n packageRoot,\n }\n }\n\n // 2. Fall back to package.json#agentproto.\n const pkgJson = (await readJsonIfExists(packageJsonPath)) as\n | { agentproto?: unknown }\n | undefined\n if (pkgJson && typeof pkgJson === \"object\" && pkgJson.agentproto) {\n return {\n manifest: PluginManifestSchema.parse(pkgJson.agentproto),\n packageRoot,\n }\n }\n\n return null\n}\n\nasync function importFactory<TFactory>(\n packageRoot: string,\n pluginId: string,\n entry: string,\n exportName: string\n): Promise<TFactory> {\n // Resolve the entry path relative to the package root. We dynamic-\n // import via file:// URL so an absolute path works without going\n // through Node's package resolver (which would need the export to\n // be declared in `exports`).\n const abs = entry.startsWith(\".\") ? join(packageRoot, entry) : entry\n const url = entry.startsWith(\".\") ? pathToFileURL(abs).href : entry\n const mod = (await import(url)) as Record<string, unknown>\n const exported = mod[exportName]\n if (typeof exported !== \"function\") {\n throw new Error(\n `agentproto plugin '${pluginId}': manifest entry '${entry}' has no callable export '${exportName}' (got ${typeof exported}).`\n )\n }\n return exported as TFactory\n}\n\nfunction resolvePluginPackageJson(pluginId: string): string | null {\n // Try the cli's own resolution first (global install + monorepo\n // workspace deps), then the user's cwd (locally-installed plugins).\n // `require.resolve` needs `createRequire` since we're an ESM bundle.\n const candidates = [\n import.meta.url,\n pathToFileURL(join(process.cwd(), \"package.json\")).href,\n ]\n for (const root of candidates) {\n try {\n return createRequire(root).resolve(`${pluginId}/package.json`)\n } catch {\n // try next root\n }\n }\n return null\n}\n\nasync function readJsonIfExists(path: string): Promise<unknown> {\n try {\n const raw = await readFile(path, \"utf8\")\n return JSON.parse(raw)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined\n throw err\n }\n}\n","/**\n * Plugin loader. For each plugin id:\n *\n * 1. Try manifest-based wiring — read the plugin's\n * `package.json#agentproto` (or standalone `agentproto.json`),\n * validate the `agentproto/plugin/v1` schema, dynamic-import\n * each declared adapter entry, register with the runtime\n * registry.\n * 2. Fall back to side-effect import — older plugins that just\n * `registerSubstrate(...)` at module load are still supported.\n *\n * Discovery sources for plugin ids:\n * - `--plugin <module-id>` flag(s) on the verb\n * - `plugins[]` array in `~/.agentproto/config.json`\n *\n * Failures: a plugin that throws on load is reported on stderr and\n * the load skips it. The CLI continues — a single bad plugin\n * shouldn't take down the swarm.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { loadPluginFromManifest } from \"./manifest-loader.js\"\n\ninterface AgentprotoConfig {\n plugins?: readonly string[]\n}\n\nexport async function loadPluginsFromConfig(): Promise<readonly string[]> {\n const path = configPath()\n try {\n const raw = await readFile(path, \"utf8\")\n const parsed = JSON.parse(raw) as AgentprotoConfig\n return parsed.plugins ?? []\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return []\n process.stderr.write(\n `agentproto: failed to read ${path} — ${err instanceof Error ? err.message : String(err)}\\n`\n )\n return []\n }\n}\n\nexport async function loadPlugins(moduleIds: readonly string[]): Promise<void> {\n for (const id of moduleIds) {\n try {\n const manifest = await loadPluginFromManifest(id)\n if (manifest === null) {\n // No manifest declared → side-effect import for legacy plugins.\n await import(id)\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n process.stderr.write(\n `agentproto: plugin '${id}' failed to load — ${msg}\\n`\n )\n }\n }\n}\n\nfunction configPath(): string {\n const base = process.env[\"AGENTPROTO_HOME\"] ?? join(homedir(), \".agentproto\")\n return join(base, \"config.json\")\n}\n"]}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
* @agentproto/cli v0.
|
|
4
|
+
* @agentproto/cli v0.3.0
|
|
3
5
|
* The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
|
|
4
6
|
*/
|
|
7
|
+
// Provide a real `require` in the ESM bundle. Bundling the Ink stack pulls in
|
|
8
|
+
// CJS deps (e.g. signal-exit@3) that call `require("assert")`; without this
|
|
9
|
+
// esbuild's interop shim throws "Dynamic require is not supported".
|
|
10
|
+
createRequire(import.meta.url);
|
|
5
11
|
|
|
6
12
|
// src/registry/runtime.ts
|
|
7
13
|
var substrates = /* @__PURE__ */ new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/registry/runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/registry/runtime.ts"],"names":[],"mappings":";;;;;;;;;;;;AA+EA,IAAM,UAAA,uBAAiB,GAAA,EAA8B;AACrD,IAAM,WAAA,uBAAkB,GAAA,EAA+B;AACvD,IAAM,SAAA,uBAAgB,GAAA,EAA6B;AACnD,IAAM,WAAA,uBAAkB,GAAA,EAA+B;AAIhD,SAAS,iBAAA,CAAkB,MAAc,OAAA,EAAiC;AAC/E,EAAA,UAAA,CAAW,GAAA,CAAI,MAAM,OAAO,CAAA;AAC9B;AAEO,SAAS,kBAAA,CACd,MACA,OAAA,EACM;AACN,EAAA,WAAA,CAAY,GAAA,CAAI,MAAM,OAAO,CAAA;AAC/B;AAEO,SAAS,gBAAA,CAAiB,MAAc,OAAA,EAAgC;AAC7E,EAAA,SAAA,CAAU,GAAA,CAAI,MAAM,OAAO,CAAA;AAC7B;AAEO,SAAS,kBAAA,CACd,MACA,OAAA,EACM;AACN,EAAA,WAAA,CAAY,GAAA,CAAI,MAAM,OAAO,CAAA;AAC/B;AAIO,SAAS,oBAAoB,IAAA,EAA4C;AAC9E,EAAA,OAAO,UAAA,CAAW,IAAI,IAAI,CAAA;AAC5B;AAEO,SAAS,qBACd,IAAA,EAC+B;AAC/B,EAAA,OAAO,WAAA,CAAY,IAAI,IAAI,CAAA;AAC7B;AAEO,SAAS,mBAAmB,IAAA,EAA2C;AAC5E,EAAA,OAAO,SAAA,CAAU,IAAI,IAAI,CAAA;AAC3B;AAEO,SAAS,qBACd,IAAA,EAC+B;AAC/B,EAAA,OAAO,WAAA,CAAY,IAAI,IAAI,CAAA;AAC7B;AAEO,SAAS,mBAAA,GAKd;AACA,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,CAAC,GAAG,UAAA,CAAW,MAAM,CAAA;AAAA,IACjC,WAAA,EAAa,CAAC,GAAG,WAAA,CAAY,MAAM,CAAA;AAAA,IACnC,SAAA,EAAW,CAAC,GAAG,SAAA,CAAU,MAAM,CAAA;AAAA,IAC/B,WAAA,EAAa,CAAC,GAAG,WAAA,CAAY,MAAM;AAAA,GACrC;AACF;AAOO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,UAAA,CAAW,KAAA,EAAM;AACjB,EAAA,WAAA,CAAY,KAAA,EAAM;AAClB,EAAA,SAAA,CAAU,KAAA,EAAM;AAChB,EAAA,WAAA,CAAY,KAAA,EAAM;AACpB","file":"runtime.mjs","sourcesContent":["/**\n * MultiAgentRuntime adapter registry — the seam third-party packages\n * use to plug substrates, dispatchers, participant executors, and\n * state stores into `agentproto run-swarm` without forking the CLI.\n *\n * A plugin module exports nothing required by name — it just imports\n * `register*` helpers from `@agentproto/cli/registry/runtime` and\n * calls them at module load. The CLI discovers plugins via:\n *\n * 1. `--plugin <module-id>` flags on `run-swarm`\n * 2. The `plugins[]` array in `~/.agentproto/config.json`\n * 3. Auto-registered built-ins (file substrate, mention dispatcher,\n * fs state, agent-cli participant) — registered by\n * `registerBuiltins()` at startup.\n *\n * Manifest `kind` strings are resolved through the registry: the kind\n * is the lookup key; the factory builds the concrete adapter from the\n * (loose) manifest config + shared context.\n */\n\nimport type {\n Dispatcher,\n ParticipantExecutor,\n StateStore,\n Substrate,\n} from \"@agentproto/agent-runtime\"\n\n// ── Context passed to every factory ──\n\n/**\n * Shared context every factory receives. Carries the manifest's base\n * directory (for resolving relative paths declared in adapter configs)\n * and a `cleanup` collector so adapters that hold disposable resources\n * (MCP clients, sockets, child processes) can register teardown callbacks\n * that the CLI runs on shutdown.\n */\nexport interface AdapterContext {\n /** Absolute directory of the manifest file. */\n readonly baseDir: string\n /** Register a teardown callback to run when the swarm shuts down. */\n registerCleanup(fn: () => Promise<void> | void): void\n}\n\n// ── Loose config shape ──\n\n/**\n * Manifest adapter blocks are loose: `{ kind: string, ...host-extension }`.\n * Each factory pulls its own typed fields off the config and validates\n * them inline.\n */\nexport interface AdapterConfig {\n readonly kind: string\n readonly [extension: string]: unknown\n}\n\n// ── Factory signatures ──\n\nexport type SubstrateFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Substrate> | Substrate\n\nexport type DispatcherFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<Dispatcher> | Dispatcher\n\nexport type ExecutorFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<ParticipantExecutor> | ParticipantExecutor\n\nexport type StateStoreFactory = (\n config: AdapterConfig,\n ctx: AdapterContext\n) => Promise<StateStore> | StateStore\n\n// ── Registry state ──\n\nconst substrates = new Map<string, SubstrateFactory>()\nconst dispatchers = new Map<string, DispatcherFactory>()\nconst executors = new Map<string, ExecutorFactory>()\nconst stateStores = new Map<string, StateStoreFactory>()\n\n// ── Public registration API ──\n\nexport function registerSubstrate(kind: string, factory: SubstrateFactory): void {\n substrates.set(kind, factory)\n}\n\nexport function registerDispatcher(\n kind: string,\n factory: DispatcherFactory\n): void {\n dispatchers.set(kind, factory)\n}\n\nexport function registerExecutor(kind: string, factory: ExecutorFactory): void {\n executors.set(kind, factory)\n}\n\nexport function registerStateStore(\n kind: string,\n factory: StateStoreFactory\n): void {\n stateStores.set(kind, factory)\n}\n\n// ── Lookup API (used by run-swarm wiring) ──\n\nexport function getSubstrateFactory(kind: string): SubstrateFactory | undefined {\n return substrates.get(kind)\n}\n\nexport function getDispatcherFactory(\n kind: string\n): DispatcherFactory | undefined {\n return dispatchers.get(kind)\n}\n\nexport function getExecutorFactory(kind: string): ExecutorFactory | undefined {\n return executors.get(kind)\n}\n\nexport function getStateStoreFactory(\n kind: string\n): StateStoreFactory | undefined {\n return stateStores.get(kind)\n}\n\nexport function listRegisteredKinds(): {\n substrates: readonly string[]\n dispatchers: readonly string[]\n executors: readonly string[]\n stateStores: readonly string[]\n} {\n return {\n substrates: [...substrates.keys()],\n dispatchers: [...dispatchers.keys()],\n executors: [...executors.keys()],\n stateStores: [...stateStores.keys()],\n }\n}\n\n/**\n * Test-only: drop every registration. Plugin registrations persist for\n * the lifetime of the process, so tests that load + unload plugins use\n * this to start from a clean slate.\n */\nexport function _resetRegistryForTests(): void {\n substrates.clear()\n dispatchers.clear()\n executors.clear()\n stateStores.clear()\n}\n"]}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { readFile, mkdir, writeFile, chmod, unlink } from 'fs/promises';
|
|
2
3
|
import { homedir } from 'os';
|
|
3
4
|
import { join, dirname } from 'path';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* @agentproto/cli v0.
|
|
7
|
+
* @agentproto/cli v0.3.0
|
|
7
8
|
* The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
+
// Provide a real `require` in the ESM bundle. Bundling the Ink stack pulls in
|
|
11
|
+
// CJS deps (e.g. signal-exit@3) that call `require("assert")`; without this
|
|
12
|
+
// esbuild's interop shim throws "Dynamic require is not supported".
|
|
13
|
+
createRequire(import.meta.url);
|
|
10
14
|
var FILE_VERSION = 1;
|
|
11
15
|
function credentialsPath() {
|
|
12
16
|
const base = process.env["AGENTPROTO_HOME"] ?? join(homedir(), ".agentproto");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/credentials.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/util/credentials.ts"],"names":[],"mappings":"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","file":"credentials.mjs","sourcesContent":["/**\n * Credential store for `agentproto auth login`.\n *\n * Format on disk (JSON, mode 0600):\n *\n * {\n * \"version\": 1,\n * \"hosts\": {\n * \"wss://guilde.work/api/v1/agentproto/tunnel\": {\n * \"token\": \"eyJ…\",\n * \"tokenType\": \"Bearer\",\n * \"expiresAt\": \"2026-08-08T12:34:56.000Z\",\n * \"refreshToken\": \"rt_…\", // optional\n * \"scope\": \"tunnel:connect\",\n * \"subject\": \"user_abc\",\n * \"obtainedAt\": \"2026-05-10T08:21:11.000Z\",\n * \"deviceLabel\": \"jeremy@laptop\"\n * }\n * }\n * }\n *\n * One file per *user*, multiple hosts under the same file. Hosts are\n * keyed by the URL the user passed to `agentproto auth login --host`,\n * stripped of trailing slash. `agentproto serve --connect <url>` looks\n * up the same key when no `--token` is passed.\n *\n * Storage location:\n * - `$AGENTPROTO_HOME/credentials.json`, falling back to\n * - `~/.agentproto/credentials.json`\n *\n * The file holds bearer tokens, so it's chmod'd 0600 on every write.\n * On Windows we rely on the per-user profile path being already\n * private and skip chmod. Never log the token contents.\n */\n\nimport { mkdir, readFile, writeFile, chmod, unlink } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, dirname } from \"node:path\"\n\nexport interface HostCredential {\n /** Bearer token. Bearer-form is the only one supported for v1. */\n token: string\n /** Always \"Bearer\" today; reserved for future schemes. */\n tokenType: \"Bearer\"\n /** ISO-8601. May be in the past — callers must check `isExpired`. */\n expiresAt: string\n /** OAuth 2.0 refresh token. Present when the host issues one. */\n refreshToken?: string\n /** Space-separated scopes the token was issued with. */\n scope?: string\n /** Human-readable subject — usually the user id, surfaced in `auth status`. */\n subject?: string\n /** ISO-8601 of when this credential was minted. */\n obtainedAt: string\n /** Friendly device label shown on the host's Machine-tokens page. */\n deviceLabel?: string\n /** Opaque revocation hint surfaced by the host (e.g. JTI). The CLI\n * passes it back on `auth logout` so the host can revoke the right\n * row server-side, not just delete the local copy. */\n revocationId?: string\n}\n\ninterface CredentialsFile {\n version: 1\n hosts: Record<string, HostCredential>\n}\n\nconst FILE_VERSION = 1 as const\n\nexport function credentialsPath(): string {\n const base = process.env[\"AGENTPROTO_HOME\"] ?? join(homedir(), \".agentproto\")\n return join(base, \"credentials.json\")\n}\n\nexport function normaliseHost(host: string): string {\n return host.replace(/\\/+$/, \"\")\n}\n\nexport async function loadCredentials(): Promise<CredentialsFile> {\n const path = credentialsPath()\n try {\n const raw = await readFile(path, \"utf8\")\n const parsed = JSON.parse(raw) as CredentialsFile\n if (parsed.version !== FILE_VERSION) {\n throw new Error(\n `credentials.json: unknown version ${parsed.version}; expected ${FILE_VERSION}. ` +\n `Delete the file and re-run \\`agentproto auth login\\`.`\n )\n }\n return parsed\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { version: FILE_VERSION, hosts: {} }\n }\n throw err\n }\n}\n\nexport async function saveCredentials(file: CredentialsFile): Promise<void> {\n const path = credentialsPath()\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, JSON.stringify(file, null, 2))\n await chmod(path, 0o600).catch(() => {\n // Windows + some sandboxed FSes (e.g. WSL on a Windows mount) don't\n // honour chmod. The file lives under the user profile in those\n // cases, which is already user-private; not worth refusing.\n })\n}\n\nexport async function readHost(host: string): Promise<HostCredential | null> {\n const f = await loadCredentials()\n return f.hosts[normaliseHost(host)] ?? null\n}\n\nexport async function writeHost(\n host: string,\n cred: HostCredential\n): Promise<void> {\n const f = await loadCredentials()\n f.hosts[normaliseHost(host)] = cred\n await saveCredentials(f)\n}\n\nexport async function deleteHost(host: string): Promise<HostCredential | null> {\n const f = await loadCredentials()\n const key = normaliseHost(host)\n const prev = f.hosts[key] ?? null\n if (prev) {\n delete f.hosts[key]\n if (Object.keys(f.hosts).length === 0) {\n // Empty file is a valid state (`auth login` re-creates), but\n // unlinking is cleaner — `auth status` then prints \"no credentials\".\n await unlink(credentialsPath()).catch(() => {})\n } else {\n await saveCredentials(f)\n }\n }\n return prev\n}\n\nexport function isExpired(cred: HostCredential, gracePeriodMs = 30_000): boolean {\n const exp = Date.parse(cred.expiresAt)\n if (!Number.isFinite(exp)) return false // unparseable expiry → trust the host\n return exp - gracePeriodMs <= Date.now()\n}\n\nexport function formatExpiry(cred: HostCredential): string {\n const exp = new Date(cred.expiresAt)\n if (Number.isNaN(exp.getTime())) return \"unknown\"\n const ms = exp.getTime() - Date.now()\n if (ms < 0) return `expired ${formatRelative(-ms)} ago`\n return `expires in ${formatRelative(ms)}`\n}\n\nfunction formatRelative(ms: number): string {\n if (ms < 60_000) return `${Math.round(ms / 1000)}s`\n if (ms < 3_600_000) return `${Math.round(ms / 60_000)}m`\n if (ms < 86_400_000) return `${Math.round(ms / 3_600_000)}h`\n return `${Math.round(ms / 86_400_000)}d`\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentproto/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "@agentproto/cli — the `agentproto` binary. Install AIP-45 agent CLI adapters, run them locally, or expose them over a tunnel as a long-running daemon. Reference host for hermes / claude-code / opencode / gemini-cli / goose, all driven through @agentproto/driver-agent-cli.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentproto",
|
|
@@ -66,32 +66,49 @@
|
|
|
66
66
|
},
|
|
67
67
|
"files": [
|
|
68
68
|
"dist",
|
|
69
|
+
"skill",
|
|
69
70
|
"README.md"
|
|
70
71
|
],
|
|
71
72
|
"dependencies": {
|
|
72
73
|
"@clack/prompts": "^1.5.0",
|
|
73
74
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
75
|
+
"cli-highlight": "^2.1.11",
|
|
74
76
|
"gray-matter": "^4.0.3",
|
|
77
|
+
"ink": "^5.0.1",
|
|
78
|
+
"ink-spinner": "^5.0.0",
|
|
79
|
+
"ink-text-input": "^5.0.1",
|
|
80
|
+
"marked": "^14.0.0",
|
|
81
|
+
"marked-terminal": "^7.2.1",
|
|
82
|
+
"react": "^18.3.1",
|
|
75
83
|
"ws": "^8.20.0",
|
|
76
84
|
"zod": "^4.4.3",
|
|
77
|
-
"@agentproto/acp": "0.
|
|
78
|
-
"@agentproto/
|
|
79
|
-
"@agentproto/
|
|
85
|
+
"@agentproto/acp": "0.2.0",
|
|
86
|
+
"@agentproto/adapter-browser": "0.1.0",
|
|
87
|
+
"@agentproto/adapter-kit": "0.1.0",
|
|
88
|
+
"@agentproto/driver": "0.1.2",
|
|
89
|
+
"@agentproto/driver-agent-cli": "0.2.0",
|
|
90
|
+
"@agentproto/model-catalog": "0.2.0",
|
|
80
91
|
"@agentproto/runtime-profile-standard": "0.1.0"
|
|
81
92
|
},
|
|
82
93
|
"optionalDependencies": {
|
|
83
94
|
"node-pty": "^1.0.0"
|
|
84
95
|
},
|
|
85
96
|
"devDependencies": {
|
|
97
|
+
"@types/marked-terminal": "^6.1.1",
|
|
86
98
|
"@types/node": "^25.6.2",
|
|
99
|
+
"@types/react": "^18.3.0",
|
|
87
100
|
"@types/ws": "^8.18.1",
|
|
88
101
|
"tsup": "^8.5.1",
|
|
89
102
|
"typescript": "^5.9.3",
|
|
90
103
|
"vitest": "^3.2.4",
|
|
91
|
-
"@agentproto/adapter-claude-code": "0.1.0
|
|
92
|
-
"@agentproto/adapter-
|
|
104
|
+
"@agentproto/adapter-claude-code": "0.1.0",
|
|
105
|
+
"@agentproto/adapter-codex": "0.1.0",
|
|
106
|
+
"@agentproto/adapter-hermes": "0.1.0",
|
|
107
|
+
"@agentproto/adapter-mastra-agent": "0.1.0",
|
|
108
|
+
"@agentproto/adapter-openclaw": "0.1.0",
|
|
109
|
+
"@agentproto/adapter-opencode": "0.1.0",
|
|
93
110
|
"@agentproto/agent-runtime": "0.1.0-alpha.0",
|
|
94
|
-
"@agentproto/runtime": "0.
|
|
111
|
+
"@agentproto/runtime": "0.3.0",
|
|
95
112
|
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
96
113
|
},
|
|
97
114
|
"engines": {
|