@agentproto/adapter-mastra-agent 0.3.0 → 0.4.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.
@@ -1,9 +1,10 @@
1
1
  import { mkdirSync, promises } from 'fs';
2
- import { homedir } from 'os';
2
+ import { homedir, tmpdir } from 'os';
3
3
  import { join, resolve, isAbsolute, relative, sep } from 'path';
4
4
  import { LibSQLStore } from '@mastra/libsql';
5
5
  import { Memory } from '@mastra/memory';
6
- import { exec } from 'child_process';
6
+ import { exec, execFile } from 'child_process';
7
+ import { randomUUID } from 'crypto';
7
8
  import { promisify } from 'util';
8
9
  import { createTool } from '@mastra/core/tools';
9
10
  import { z } from 'zod';
@@ -83,6 +84,22 @@ function resolveMastraModel(ref, env = process.env) {
83
84
  return modelId;
84
85
  }
85
86
  var execAsync = promisify(exec);
87
+ var execFileAsync = promisify(execFile);
88
+ var ALLOWED_TEST_ARGV0 = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "node", "npx"]);
89
+ function tail(s, maxChars = 4e3) {
90
+ return s.length > maxChars ? s.slice(-maxChars) : s;
91
+ }
92
+ function extractPatchPaths(patch) {
93
+ const paths = /* @__PURE__ */ new Set();
94
+ for (const line of patch.split("\n")) {
95
+ const m = /^(?:\+\+\+|---) (?:a\/|b\/)?(.+?)(?:\t.*)?$/.exec(line);
96
+ if (!m) continue;
97
+ const p = m[1].trim();
98
+ if (p === "/dev/null") continue;
99
+ paths.add(p);
100
+ }
101
+ return [...paths];
102
+ }
86
103
  function resolveInCwd(cwd, p) {
87
104
  const base = resolve(cwd);
88
105
  const target = isAbsolute(p) ? resolve(p) : resolve(base, p);
@@ -99,6 +116,7 @@ function makeWorkspaceTools(opts) {
99
116
  const cwd = resolve(opts.cwd);
100
117
  const allowExec = opts.allowExec ?? true;
101
118
  const execTimeoutMs = opts.execTimeoutMs ?? 12e4;
119
+ const execEnv = { ...process.env, GIT_CEILING_DIRECTORIES: resolve(cwd, "..") };
102
120
  const list_dir = createTool({
103
121
  id: "list_dir",
104
122
  description: "List the entries of a directory in the workspace. Returns names with a trailing '/' for directories. Path is relative to the workspace root (default '.').",
@@ -185,7 +203,8 @@ function makeWorkspaceTools(opts) {
185
203
  const { stdout, stderr } = await execAsync(input.command, {
186
204
  cwd,
187
205
  timeout: execTimeoutMs,
188
- maxBuffer: 10 * 1024 * 1024
206
+ maxBuffer: 10 * 1024 * 1024,
207
+ env: execEnv
189
208
  });
190
209
  return { stdout, stderr, exitCode: 0 };
191
210
  } catch (err) {
@@ -198,8 +217,104 @@ function makeWorkspaceTools(opts) {
198
217
  }
199
218
  }
200
219
  });
220
+ tools.read_diff = createTool({
221
+ id: "read_diff",
222
+ description: "Show `git diff` for the workspace \u2014 staged and unstaged changes against HEAD (or against `base` if given), as unified diff text. Optionally scoped to `paths`.",
223
+ inputSchema: z.object({
224
+ paths: z.array(z.string()).optional().describe("Restrict the diff to these paths, relative to the workspace root."),
225
+ base: z.string().optional().describe("Git ref to diff against. Defaults to HEAD.")
226
+ }),
227
+ outputSchema: z.object({ diff: z.string() }),
228
+ execute: async (input) => {
229
+ const relPaths = (input.paths ?? []).map((p) => {
230
+ const abs = resolveInCwd(cwd, p);
231
+ return relative(cwd, abs) || ".";
232
+ });
233
+ const args = [
234
+ "diff",
235
+ input.base ?? "HEAD",
236
+ ...relPaths.length ? ["--", ...relPaths] : []
237
+ ];
238
+ try {
239
+ const { stdout } = await execFileAsync("git", args, {
240
+ cwd,
241
+ timeout: execTimeoutMs,
242
+ maxBuffer: 10 * 1024 * 1024,
243
+ env: execEnv
244
+ });
245
+ return { diff: stdout };
246
+ } catch (err) {
247
+ const e = err;
248
+ throw new Error(`git diff failed: ${e.stderr ?? e.message ?? String(err)}`);
249
+ }
250
+ }
251
+ });
252
+ tools.apply_patch = createTool({
253
+ id: "apply_patch",
254
+ description: "Apply a unified diff to files in the workspace (`git apply --whitespace=nowarn`). Paths in the patch that escape the workspace are rejected.",
255
+ inputSchema: z.object({
256
+ patch: z.string().describe("Unified diff text to apply.")
257
+ }),
258
+ outputSchema: z.object({ applied: z.boolean(), output: z.string() }),
259
+ execute: async (input) => {
260
+ for (const p of extractPatchPaths(input.patch)) {
261
+ resolveInCwd(cwd, p);
262
+ }
263
+ const patchFile = join(tmpdir(), `mastra-agent-patch-${randomUUID()}.diff`);
264
+ await promises.writeFile(patchFile, input.patch, "utf8");
265
+ try {
266
+ const { stdout, stderr } = await execFileAsync(
267
+ "git",
268
+ ["apply", "--whitespace=nowarn", patchFile],
269
+ { cwd, timeout: execTimeoutMs, maxBuffer: 10 * 1024 * 1024, env: execEnv }
270
+ );
271
+ return { applied: true, output: stdout || stderr || "" };
272
+ } catch (err) {
273
+ const e = err;
274
+ throw new Error(`git apply failed: ${e.stderr ?? e.stdout ?? e.message ?? String(err)}`);
275
+ } finally {
276
+ await promises.unlink(patchFile).catch(() => {
277
+ });
278
+ }
279
+ }
280
+ });
281
+ tools.run_tests = createTool({
282
+ id: "run_tests",
283
+ description: "Run the workspace's test command (default `npm test`, overridable via `command` or the MASTRA_AGENT_TEST_CMD env) and return its exit code + output tail.",
284
+ inputSchema: z.object({
285
+ command: z.string().optional().describe("Override the test command. Its argv0 must be one of npm, pnpm, yarn, node, npx.")
286
+ }),
287
+ outputSchema: z.object({ exitCode: z.number(), output: z.string() }),
288
+ execute: async (input) => {
289
+ const commandStr = input.command ?? process.env.MASTRA_AGENT_TEST_CMD ?? "npm test";
290
+ const argv0 = commandStr.trim().split(/\s+/)[0];
291
+ if (!argv0 || !ALLOWED_TEST_ARGV0.has(argv0)) {
292
+ throw new Error(
293
+ `run_tests: command '${commandStr}' is not allowed \u2014 argv0 must be one of ${[...ALLOWED_TEST_ARGV0].join(", ")}.`
294
+ );
295
+ }
296
+ try {
297
+ const { stdout, stderr } = await execAsync(commandStr, {
298
+ cwd,
299
+ timeout: execTimeoutMs,
300
+ maxBuffer: 10 * 1024 * 1024,
301
+ env: execEnv
302
+ });
303
+ return { exitCode: 0, output: tail(stdout + stderr) };
304
+ } catch (err) {
305
+ const e = err;
306
+ return {
307
+ exitCode: typeof e.code === "number" ? e.code : 1,
308
+ output: tail((e.stdout ?? "") + (e.stderr ?? e.message ?? String(err)))
309
+ };
310
+ }
311
+ }
312
+ });
201
313
  }
202
- return tools;
314
+ return {
315
+ ...tools,
316
+ ...opts.extraTools
317
+ };
203
318
  }
204
319
  var DEFAULT_MODEL = "openrouter/z-ai/glm-5.2";
205
320
  var DEFAULT_TOOL_IDS = [
@@ -248,7 +363,11 @@ function makeAgentFactory(opts = {}) {
248
363
  const { frontmatter, body } = parseAgentManifest(source);
249
364
  const handle = agentFromManifest({ frontmatter, body });
250
365
  const cwd = opts.cwd ?? process.cwd();
251
- const workspaceTools = makeWorkspaceTools({ cwd, allowExec: opts.allowExec });
366
+ const workspaceTools = makeWorkspaceTools({
367
+ cwd,
368
+ allowExec: opts.allowExec,
369
+ extraTools: opts.extraTools
370
+ });
252
371
  const { agent } = await buildMastraAgent(handle, {
253
372
  resolveModel: (ref) => resolveMastraModel(ref),
254
373
  // Match each declared tool ref against the workspace toolset by id.
@@ -479,5 +598,5 @@ function runAcpOverStdio(buildAgent) {
479
598
  }
480
599
 
481
600
  export { DEFAULT_MODEL, DEFAULT_TOOL_IDS, MastraAcpAgent, buildSqliteMemory, chunkToSessionUpdate, defaultAgentManifest, makeAgentFactory, makeWorkspaceTools, modelRefToString, promptText, providerOf, resolveInCwd, resolveMastraModel, resolveMemoryDbPath, runAcpOverStdio, toolCallTitle, toolKindFor };
482
- //# sourceMappingURL=chunk-LHQSSCUP.mjs.map
483
- //# sourceMappingURL=chunk-LHQSSCUP.mjs.map
601
+ //# sourceMappingURL=chunk-ZVLJDGI4.mjs.map
602
+ //# sourceMappingURL=chunk-ZVLJDGI4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory.ts","../src/model-resolver.ts","../src/workspace-tools.ts","../src/default-agent.ts","../src/tool-call-map.ts","../src/acp-host.ts","../src/run.ts"],"names":["fs","join"],"mappings":"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","file":"chunk-ZVLJDGI4.mjs","sourcesContent":["/**\n * SQLite-backed memory for the agent, via Mastra's LibSQL store.\n *\n * Each ACP session is a memory *thread* (see acp-host.ts), so the agent recalls\n * earlier turns within a session. The db is a single SQLite file (LibSQL is a\n * SQLite fork) under `~/.agentproto/mastra-agent/` by default — persistent\n * across spawns — overridable with `AGENTPROTO_MASTRA_MEMORY_DB`.\n */\n\nimport { mkdirSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { LibSQLStore } from \"@mastra/libsql\"\nimport { Memory } from \"@mastra/memory\"\nimport type { MemoryConfig } from \"@agentproto/agent\"\n\n/** A built Mastra memory — structural, matching `@agentproto/mastra`'s\n * `MastraMemoryLike` expectation without importing the exact type. */\nexport type MastraMemoryLike = Memory\n\n/** Resolve the SQLite file path, creating the parent dir. `AGENTPROTO_MASTRA_MEMORY_DB`\n * wins; otherwise `~/.agentproto/mastra-agent/memory.db`. */\nexport function resolveMemoryDbPath(\n env: Record<string, string | undefined> = process.env,\n): string {\n const override = env.AGENTPROTO_MASTRA_MEMORY_DB\n if (override) return override\n const dir = join(homedir(), \".agentproto\", \"mastra-agent\")\n mkdirSync(dir, { recursive: true })\n return join(dir, \"memory.db\")\n}\n\n/**\n * Build a Mastra `Memory` from an AIP-42 `memory:` config. Returns `undefined`\n * when memory is disabled (`scope: \"none\"`) so `buildMastraAgent` attaches none.\n *\n * - `retention_turns` → `options.lastMessages` (how many recent messages to\n * replay into context). Defaults to 20.\n * - Semantic recall is left off (it needs an embedder + vector index) — this is\n * conversation-history memory, the SQLite ask.\n */\nexport function buildSqliteMemory(\n config?: MemoryConfig,\n env: Record<string, string | undefined> = process.env,\n): MastraMemoryLike | undefined {\n if (config?.scope === \"none\") return undefined\n const dbPath = resolveMemoryDbPath(env)\n const lastMessages =\n typeof config?.retention_turns === \"number\" && config.retention_turns > 0\n ? config.retention_turns\n : 20\n return new Memory({\n storage: new LibSQLStore({ id: \"mastra-agent-memory\", url: `file:${dbPath}` }),\n options: {\n lastMessages,\n semanticRecall: false,\n workingMemory: { enabled: false },\n },\n })\n}\n","/**\n * WP1 — AIP-42 `model:` ref -> a model Mastra's `Agent` can run.\n *\n * Mastra 1.x ships a model router (`models.dev` gateway) that accepts a bare\n * `provider/model` string (e.g. `anthropic/claude-opus-4-8`,\n * `openrouter/z-ai/glm-5.2`) and resolves it to a live ai-sdk model, reading\n * the provider's key from the environment. So the resolver is a thin,\n * *validated* pass-through: extract the ref string, sanity-check the shape,\n * surface a friendly error when the obvious provider key is missing, and hand\n * the string to Mastra. No bespoke provider wiring, no extra ai-sdk deps.\n */\n\nimport type { ModelRef } from \"@agentproto/agent\"\n\n/** Best-effort provider -> env var map, used only for a friendly preflight\n * error. Mastra's gateway is the source of truth; this list just turns the\n * common \"forgot the key\" case into a clear message instead of a deep ai-sdk\n * stack trace. Providers not listed here skip the preflight check. */\nconst PROVIDER_ENV: Record<string, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n groq: \"GROQ_API_KEY\",\n xai: \"XAI_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n deepseek: \"DEEPSEEK_API_KEY\",\n}\n\n/** Pull the model id string out of an AIP-42 `ModelRef` (string | { ref }). */\nexport function modelRefToString(ref: ModelRef): string {\n if (typeof ref === \"string\") return ref.trim()\n if (ref && typeof ref === \"object\" && typeof ref.ref === \"string\") {\n return ref.ref.trim()\n }\n throw new Error(\n \"mastra-agent: AGENT.md `model` must be a `provider/model` string \" +\n \"(or { ref }); inline model objects are not supported by this adapter.\",\n )\n}\n\n/** The provider segment is everything before the first `/`. */\nexport function providerOf(modelId: string): string {\n const slash = modelId.indexOf(\"/\")\n return slash > 0 ? modelId.slice(0, slash) : modelId\n}\n\n/**\n * Infer the provider for a bare, unambiguous id so an AGENT.md stays\n * adapter-agnostic. `claude-sonnet-5` — what the claude-code / claude-sdk\n * adapters already accept bare — routes here as `anthropic/claude-sonnet-5`,\n * instead of being handed to Mastra's gateway with no provider (which fails\n * with \"could not resolve model configuration\"). Only Claude ids are\n * unambiguous today; every other provider still needs the explicit prefix.\n */\nexport function normalizeModelId(modelId: string): string {\n if (modelId.includes(\"/\")) return modelId\n if (/^claude[-.]/i.test(modelId)) return `anthropic/${modelId}`\n return modelId\n}\n\n/**\n * Resolve an AIP-42 model ref to the value Mastra's `Agent` constructor takes.\n * Returns the `provider/model` string — Mastra routes it. `env` defaults to\n * `process.env`; injectable for tests.\n */\nexport function resolveMastraModel(\n ref: ModelRef,\n env: Record<string, string | undefined> = process.env,\n): string {\n const modelId = normalizeModelId(modelRefToString(ref))\n if (!modelId) {\n throw new Error(\"mastra-agent: empty `model` ref.\")\n }\n const provider = providerOf(modelId)\n const envKey = PROVIDER_ENV[provider]\n if (envKey && !env[envKey]) {\n throw new Error(\n `mastra-agent: model '${modelId}' needs ${envKey} in the environment ` +\n `(provider '${provider}'). Set it on the spawn env or export it.`,\n )\n }\n return modelId\n}\n","/**\n * Workspace toolset — gives the Mastra agent the ability to inspect, edit, and\n * run commands inside its session working directory, like a coding agent.\n *\n * SAFETY: every file path is resolved against the session `cwd` and rejected if\n * it escapes (no `../` traversal, no absolute paths outside cwd). Command\n * execution runs with `cwd` and a timeout, and is gated by `allowExec` (the CLI\n * sets it from `AGENTPROTO_MASTRA_NO_EXEC`). The agent only ever touches the\n * directory the daemon spawned it in.\n */\n\nimport { exec, execFile } from \"node:child_process\"\nimport { randomUUID } from \"node:crypto\"\nimport { promises as fs } from \"node:fs\"\nimport { tmpdir } from \"node:os\"\nimport { isAbsolute, join, relative, resolve, sep } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { createTool } from \"@mastra/core/tools\"\nimport type { MastraToolLike } from \"@agentproto/mastra\"\nimport { z } from \"zod\"\n\nconst execAsync = promisify(exec)\nconst execFileAsync = promisify(execFile)\n\n/** A Mastra tool (structural — avoids coupling to a @mastra/core type name). */\nexport interface WorkspaceTool {\n id: string\n}\n\n/** `command`'s argv0 must be one of these for `run_tests` — no arbitrary exec. */\nconst ALLOWED_TEST_ARGV0 = new Set([\"npm\", \"pnpm\", \"yarn\", \"node\", \"npx\"])\n\n/** Keep tool output bounded — return only the tail. */\nfunction tail(s: string, maxChars = 4000): string {\n return s.length > maxChars ? s.slice(-maxChars) : s\n}\n\n/** Pull the file paths a unified diff touches out of its `---`/`+++` headers. */\nfunction extractPatchPaths(patch: string): string[] {\n const paths = new Set<string>()\n for (const line of patch.split(\"\\n\")) {\n const m = /^(?:\\+\\+\\+|---) (?:a\\/|b\\/)?(.+?)(?:\\t.*)?$/.exec(line)\n if (!m) continue\n const p = m[1]!.trim()\n if (p === \"/dev/null\") continue\n paths.add(p)\n }\n return [...paths]\n}\n\nexport interface WorkspaceToolsOptions {\n /** Absolute path the agent is confined to (the spawn cwd). */\n cwd: string\n /** When false, `run_command` (and the other exec-gated tools) are omitted. Default true. */\n allowExec?: boolean\n /** Per-command timeout (ms). Default 120_000. */\n execTimeoutMs?: number\n /**\n * Extra tools merged over the built-ins, keyed by id — lets an embedding\n * host add tools the built-in toolset doesn't cover. On id collision, an\n * extra tool wins over a built-in of the same id.\n */\n extraTools?: Record<string, MastraToolLike>\n}\n\n/** Resolve `p` against `cwd`, throwing if the result escapes the workspace. */\nexport function resolveInCwd(cwd: string, p: string): string {\n const base = resolve(cwd)\n const target = isAbsolute(p) ? resolve(p) : resolve(base, p)\n const rel = relative(base, target)\n if (rel === \"\" ) return target // the workspace root itself\n if (rel.startsWith(\"..\") || (isAbsolute(rel) && !target.startsWith(base + sep))) {\n throw new Error(\n `path '${p}' escapes the workspace (resolved to '${target}', outside '${base}').`,\n )\n }\n return target\n}\n\n/**\n * Build the workspace toolset, all confined to `cwd`. Returns a record keyed by\n * tool id (also the AGENT.md tool ref the resolver matches).\n */\nexport function makeWorkspaceTools(\n opts: WorkspaceToolsOptions,\n): Record<string, ReturnType<typeof createTool>> {\n const cwd = resolve(opts.cwd)\n const allowExec = opts.allowExec ?? true\n const execTimeoutMs = opts.execTimeoutMs ?? 120_000\n /**\n * Shared env for all exec calls — sets GIT_CEILING_DIRECTORIES to prevent\n * git from discovering repos above cwd (fixes #818: read_diff escaping the\n * workspace to operate on an enclosing repo).\n */\n const execEnv = { ...process.env, GIT_CEILING_DIRECTORIES: resolve(cwd, \"..\") }\n\n const list_dir = createTool({\n id: \"list_dir\",\n description:\n \"List the entries of a directory in the workspace. Returns names with a trailing '/' for directories. Path is relative to the workspace root (default '.').\",\n inputSchema: z.object({\n path: z.string().default(\".\").describe(\"Directory path, relative to the workspace root.\"),\n }),\n outputSchema: z.object({ entries: z.array(z.string()) }),\n execute: async (input: { path?: string }) => {\n const dir = resolveInCwd(cwd, input.path ?? \".\")\n const dirents = await fs.readdir(dir, { withFileTypes: true })\n return {\n entries: dirents.map((d) => (d.isDirectory() ? `${d.name}/` : d.name)).sort(),\n }\n },\n })\n\n const read_file = createTool({\n id: \"read_file\",\n description:\n \"Read a UTF-8 text file from the workspace. Path is relative to the workspace root.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n }),\n outputSchema: z.object({ content: z.string() }),\n execute: async (input: { path: string }) => {\n const file = resolveInCwd(cwd, input.path)\n return { content: await fs.readFile(file, \"utf8\") }\n },\n })\n\n const write_file = createTool({\n id: \"write_file\",\n description:\n \"Write (creating or overwriting) a UTF-8 text file in the workspace. Creates parent directories as needed. Path is relative to the workspace root.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n content: z.string().describe(\"Full file contents to write.\"),\n }),\n outputSchema: z.object({ path: z.string(), bytes: z.number() }),\n execute: async (input: { path: string; content: string }) => {\n const file = resolveInCwd(cwd, input.path)\n await fs.mkdir(resolve(file, \"..\"), { recursive: true })\n await fs.writeFile(file, input.content, \"utf8\")\n return { path: input.path, bytes: Buffer.byteLength(input.content, \"utf8\") }\n },\n })\n\n const edit_file = createTool({\n id: \"edit_file\",\n description:\n \"Replace an exact substring in a workspace file. `old_string` must occur exactly once. Use for targeted edits instead of rewriting the whole file.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n old_string: z.string().describe(\"Exact text to replace (must be unique in the file).\"),\n new_string: z.string().describe(\"Replacement text.\"),\n }),\n outputSchema: z.object({ path: z.string(), replaced: z.boolean() }),\n execute: async (input: { path: string; old_string: string; new_string: string }) => {\n const file = resolveInCwd(cwd, input.path)\n const current = await fs.readFile(file, \"utf8\")\n const count = current.split(input.old_string).length - 1\n if (count === 0) throw new Error(`old_string not found in '${input.path}'.`)\n if (count > 1) {\n throw new Error(`old_string occurs ${count}× in '${input.path}' — make it unique.`)\n }\n await fs.writeFile(file, current.replace(input.old_string, input.new_string), \"utf8\")\n return { path: input.path, replaced: true }\n },\n })\n\n const tools: Record<string, ReturnType<typeof createTool>> = {\n list_dir,\n read_file,\n write_file,\n edit_file,\n }\n\n if (allowExec) {\n tools.run_command = createTool({\n id: \"run_command\",\n description:\n \"Run a shell command in the workspace directory and return its stdout/stderr/exit code. Runs with a timeout; use for builds, tests, git, etc.\",\n inputSchema: z.object({\n command: z.string().describe(\"The shell command to run (executed in the workspace root).\"),\n }),\n outputSchema: z.object({\n stdout: z.string(),\n stderr: z.string(),\n exitCode: z.number(),\n }),\n execute: async (input: { command: string }) => {\n try {\n const { stdout, stderr } = await execAsync(input.command, {\n cwd,\n timeout: execTimeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n env: execEnv,\n })\n return { stdout, stderr, exitCode: 0 }\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; code?: number; message?: string }\n return {\n stdout: e.stdout ?? \"\",\n stderr: e.stderr ?? e.message ?? String(err),\n exitCode: typeof e.code === \"number\" ? e.code : 1,\n }\n }\n },\n })\n\n tools.read_diff = createTool({\n id: \"read_diff\",\n description:\n \"Show `git diff` for the workspace — staged and unstaged changes against HEAD (or against `base` if given), as unified diff text. Optionally scoped to `paths`.\",\n inputSchema: z.object({\n paths: z\n .array(z.string())\n .optional()\n .describe(\"Restrict the diff to these paths, relative to the workspace root.\"),\n base: z.string().optional().describe(\"Git ref to diff against. Defaults to HEAD.\"),\n }),\n outputSchema: z.object({ diff: z.string() }),\n execute: async (input: { paths?: string[]; base?: string }) => {\n const relPaths = (input.paths ?? []).map((p) => {\n const abs = resolveInCwd(cwd, p)\n return relative(cwd, abs) || \".\"\n })\n const args = [\n \"diff\",\n input.base ?? \"HEAD\",\n ...(relPaths.length ? [\"--\", ...relPaths] : []),\n ]\n try {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd,\n timeout: execTimeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n env: execEnv,\n })\n return { diff: stdout }\n } catch (err) {\n const e = err as { stderr?: string; message?: string }\n throw new Error(`git diff failed: ${e.stderr ?? e.message ?? String(err)}`)\n }\n },\n })\n\n tools.apply_patch = createTool({\n id: \"apply_patch\",\n description:\n \"Apply a unified diff to files in the workspace (`git apply --whitespace=nowarn`). Paths in the patch that escape the workspace are rejected.\",\n inputSchema: z.object({\n patch: z.string().describe(\"Unified diff text to apply.\"),\n }),\n outputSchema: z.object({ applied: z.boolean(), output: z.string() }),\n execute: async (input: { patch: string }) => {\n for (const p of extractPatchPaths(input.patch)) {\n resolveInCwd(cwd, p) // throws if the patch touches a path outside cwd\n }\n const patchFile = join(tmpdir(), `mastra-agent-patch-${randomUUID()}.diff`)\n await fs.writeFile(patchFile, input.patch, \"utf8\")\n try {\n const { stdout, stderr } = await execFileAsync(\n \"git\",\n [\"apply\", \"--whitespace=nowarn\", patchFile],\n { cwd, timeout: execTimeoutMs, maxBuffer: 10 * 1024 * 1024, env: execEnv },\n )\n return { applied: true, output: stdout || stderr || \"\" }\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; message?: string }\n throw new Error(`git apply failed: ${e.stderr ?? e.stdout ?? e.message ?? String(err)}`)\n } finally {\n await fs.unlink(patchFile).catch(() => {})\n }\n },\n })\n\n tools.run_tests = createTool({\n id: \"run_tests\",\n description:\n \"Run the workspace's test command (default `npm test`, overridable via `command` or the MASTRA_AGENT_TEST_CMD env) and return its exit code + output tail.\",\n inputSchema: z.object({\n command: z\n .string()\n .optional()\n .describe(\"Override the test command. Its argv0 must be one of npm, pnpm, yarn, node, npx.\"),\n }),\n outputSchema: z.object({ exitCode: z.number(), output: z.string() }),\n execute: async (input: { command?: string }) => {\n const commandStr = input.command ?? process.env.MASTRA_AGENT_TEST_CMD ?? \"npm test\"\n const argv0 = commandStr.trim().split(/\\s+/)[0]\n if (!argv0 || !ALLOWED_TEST_ARGV0.has(argv0)) {\n throw new Error(\n `run_tests: command '${commandStr}' is not allowed — argv0 must be one of ${[...ALLOWED_TEST_ARGV0].join(\", \")}.`,\n )\n }\n try {\n const { stdout, stderr } = await execAsync(commandStr, {\n cwd,\n timeout: execTimeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n env: execEnv,\n })\n return { exitCode: 0, output: tail(stdout + stderr) }\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; code?: number; message?: string }\n return {\n exitCode: typeof e.code === \"number\" ? e.code : 1,\n output: tail((e.stdout ?? \"\") + (e.stderr ?? e.message ?? String(err))),\n }\n }\n },\n })\n }\n\n return {\n ...tools,\n ...(opts.extraTools as Record<string, ReturnType<typeof createTool>> | undefined),\n }\n}\n","/**\n * Builds a runnable Mastra agent from an AIP-42 AGENT.md — either a caller's\n * file or a zero-config built-in default — wiring the model, the markdown body\n * as instructions, the SQLite memory, and the workspace toolset.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { agentFromManifest, parseAgentManifest } from \"@agentproto/agent\"\nimport { buildMastraAgent } from \"@agentproto/mastra\"\nimport type { MastraToolLike } from \"@agentproto/mastra\"\nimport type { MastraLike } from \"./acp-host.js\"\nimport { buildSqliteMemory } from \"./memory.js\"\nimport { resolveMastraModel } from \"./model-resolver.js\"\nimport { makeWorkspaceTools } from \"./workspace-tools.js\"\n\n/** Cheap OpenRouter coder by default — this is the budget first-party arm,\n * same rationale as the hermes default. Override with --model / env. */\nexport const DEFAULT_MODEL = \"openrouter/z-ai/glm-5.2\"\n\n/** Tool ids the built-in default agent is granted (the workspace toolset). */\nexport const DEFAULT_TOOL_IDS = [\n \"list_dir\",\n \"read_file\",\n \"write_file\",\n \"edit_file\",\n \"run_command\",\n] as const\n\nexport interface AgentSourceOptions {\n /** Path to an AGENT.md. When omitted, the built-in default agent is used. */\n agentFile?: string\n /** Model id for the default agent (ignored when agentFile carries a model). */\n model?: string\n /** Workspace dir the tools are confined to. Defaults to `process.cwd()`. */\n cwd?: string\n /** When false, the `run_command` tool is withheld. Default true. */\n allowExec?: boolean\n /**\n * Extra tools merged over the built-in workspace toolset (extra wins on id\n * collision) — programmatic-only, for a host embedding this agent that\n * wants to grant tools the built-in toolset doesn't cover. No CLI flag.\n */\n extraTools?: Record<string, MastraToolLike>\n}\n\n/** The built-in AGENT.md used when no file is supplied. */\nexport function defaultAgentManifest(model: string): string {\n return [\n \"---\",\n \"schema: agent/v1\",\n \"id: mastra-agent\",\n \"description: A first-party agentproto agent powered by Mastra.\",\n `model: ${model}`,\n \"version: 0.1.0\",\n \"tools:\",\n ...DEFAULT_TOOL_IDS.map((id) => ` - ${id}`),\n \"memory:\",\n \" scope: per-conversation\",\n \" retention_turns: 20\",\n \"---\",\n \"\",\n \"You are a capable, concise coding agent operating inside a workspace \",\n \"directory. You can list, read, write, and edit files and run shell \",\n \"commands there using your tools. Do exactly what the user asks — when \",\n \"asked to reply with an exact string, reply with only that string.\",\n \"\",\n ].join(\"\\n\")\n}\n\n/** Pull the id string out of an AIP-42 tool ref (string | { ref }). */\nfunction toolRefId(ref: unknown): string | undefined {\n if (typeof ref === \"string\") return ref\n if (ref && typeof ref === \"object\" && typeof (ref as { ref?: unknown }).ref === \"string\") {\n return (ref as { ref: string }).ref\n }\n return undefined\n}\n\n/** Resolve the AGENT.md source for these options (file or built-in default). */\nexport async function resolveAgentSource(\n opts: AgentSourceOptions = {},\n): Promise<string> {\n if (opts.agentFile) return readFile(opts.agentFile, \"utf8\")\n return defaultAgentManifest(opts.model ?? DEFAULT_MODEL)\n}\n\n/**\n * A lazy factory: parses the AGENT.md, builds the Mastra agent with the model\n * resolver, SQLite memory, the markdown body as instructions, and the\n * workspace toolset (matched by tool id), then returns it as the structural\n * `MastraLike` the ACP host needs.\n */\nexport function makeAgentFactory(\n opts: AgentSourceOptions = {},\n): () => Promise<MastraLike> {\n return async () => {\n const source = await resolveAgentSource(opts)\n const { frontmatter, body } = parseAgentManifest(source)\n const handle = agentFromManifest({ frontmatter, body })\n\n const cwd = opts.cwd ?? process.cwd()\n const workspaceTools = makeWorkspaceTools({\n cwd,\n allowExec: opts.allowExec,\n extraTools: opts.extraTools,\n })\n\n const { agent } = await buildMastraAgent(handle, {\n resolveModel: (ref) => resolveMastraModel(ref),\n // Match each declared tool ref against the workspace toolset by id.\n resolveTool: (ref) => {\n const id = toolRefId(ref)\n const tool = id ? workspaceTools[id] : undefined\n return tool ? { name: id as string, tool } : undefined\n },\n buildMemory: (config) => buildSqliteMemory(config),\n // The markdown body is the agent's primary system prompt (AIP-42).\n body,\n })\n return agent as unknown as MastraLike\n }\n}\n","/**\n * Pure mapping from Mastra `fullStream` chunks to AIP-44 ACP `session/update`\n * payloads. Kept dependency-light (no SDK import beyond types) and side-effect\n * free so it is straightforward to unit-test; the ACP host (acp-host.ts) owns\n * the wire/IO and just forwards whatever this returns.\n *\n * Mastra emits a typed chunk union on `agent.stream(...).fullStream`. We care\n * about three kinds:\n * - `text-delta` → ACP `agent_message_chunk` (assistant prose)\n * - `tool-call` → ACP `tool_call` (a tool started, status in_progress)\n * - `tool-result` → ACP `tool_call_update` (that tool finished/failed)\n * Everything else (reasoning, step boundaries, finish, …) is not surfaced.\n */\n\nimport type { SessionUpdate, ToolKind } from \"@agentclientprotocol/sdk\"\n\n/** The narrow slice of a Mastra fullStream chunk we read. Typed structurally\n * so we don't couple to a specific @mastra/core version.\n * Mastra 1.45 wraps all chunk data in a `payload` field. */\nexport type MastraStreamChunk =\n | { type: \"text-delta\"; payload?: { text?: string } }\n | { type: \"tool-call\"; payload?: { toolCallId?: string; toolName?: string; args?: unknown } }\n | { type: \"tool-result\"; payload?: { toolCallId?: string; result?: unknown; isError?: boolean } }\n\n/** Map a workspace tool id to the ACP {@link ToolKind} that drives client\n * icon/UI treatment. Unknown ids fall back to \"other\". */\nexport function toolKindFor(toolName: string): ToolKind {\n switch (toolName) {\n case \"read_file\":\n case \"list_dir\":\n return \"read\"\n case \"write_file\":\n case \"edit_file\":\n return \"edit\"\n case \"run_command\":\n return \"execute\"\n default:\n return \"other\"\n }\n}\n\n/** A short, human-readable title for a tool call, e.g. `run_command: ls -la`\n * or `read_file: src/index.ts`. Falls back to the bare tool name. */\nexport function toolCallTitle(toolName: string, args: unknown): string {\n if (args && typeof args === \"object\") {\n const { command, path, file } = args as Record<string, unknown>\n const hint =\n (typeof command === \"string\" && command) ||\n (typeof path === \"string\" && path) ||\n (typeof file === \"string\" && file) ||\n \"\"\n if (hint) return `${toolName}: ${hint}`\n }\n return toolName\n}\n\n/**\n * Translate one Mastra chunk into an ACP `session/update` payload, or `null`\n * when the chunk has no ACP surface (or is missing the ids we need). The ACP\n * host wraps the result with the `sessionId`.\n */\nexport function chunkToSessionUpdate(\n chunk: MastraStreamChunk,\n): SessionUpdate | null {\n switch (chunk.type) {\n case \"text-delta\": {\n const text = chunk.payload?.text\n if (!text) return null\n return {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text },\n }\n }\n case \"tool-call\": {\n const toolCallId = chunk.payload?.toolCallId\n if (!toolCallId) return null\n const toolName = chunk.payload?.toolName ?? \"tool\"\n const args = chunk.payload?.args\n return {\n sessionUpdate: \"tool_call\",\n toolCallId,\n title: toolCallTitle(toolName, args),\n kind: toolKindFor(toolName),\n status: \"in_progress\",\n rawInput: args,\n }\n }\n case \"tool-result\": {\n const toolCallId = chunk.payload?.toolCallId\n if (!toolCallId) return null\n return {\n sessionUpdate: \"tool_call_update\",\n toolCallId,\n status: chunk.payload?.isError ? \"failed\" : \"completed\",\n rawOutput: chunk.payload?.result,\n }\n }\n default:\n return null\n }\n}\n","/**\n * WP2 — the agent side of AIP-44 ACP, backed by a live Mastra agent.\n *\n * Implements the `@agentclientprotocol/sdk` `Agent` interface: handles the\n * session lifecycle and, on `session/prompt`, drives a Mastra agent's\n * `stream()` — relaying each text delta as an `agent_message_chunk`\n * `session/update`, exactly as an IDE/host expects from codex or claude-code.\n *\n * No Mastra-specific protocol knowledge leaks past this file; everything above\n * is the standard ACP wire, so the daemon spawns this like any other arm.\n */\n\nimport type {\n AgentSideConnection,\n Agent as AcpAgent,\n AuthenticateRequest,\n CancelNotification,\n InitializeRequest,\n InitializeResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n SetSessionConfigOptionRequest,\n SetSessionConfigOptionResponse,\n SetSessionModeRequest,\n} from \"@agentclientprotocol/sdk\"\nimport { PROTOCOL_VERSION } from \"@agentclientprotocol/sdk\"\nimport { type MastraStreamChunk, chunkToSessionUpdate } from \"./tool-call-map.js\"\n\n/** A built Mastra agent — only the surface we need (its `stream`). Typed\n * structurally so we don't couple to a specific @mastra/core version.\n *\n * We read `fullStream` (the typed chunk union: text deltas AND tool-call /\n * tool-result events) so tool activity surfaces as ACP `tool_call` updates,\n * not only the final prose. `textStream` is kept as an optional fallback for\n * a stripped agent that exposes only text. */\nexport interface MastraLike {\n stream(\n input: string,\n options?: {\n abortSignal?: AbortSignal\n /** Memory threading — `thread` scopes recall to one ACP session. */\n memory?: { thread?: string; resource?: string }\n /** Max agentic loop steps (tool-call → execute → continue). Default 1 = no loop. */\n maxSteps?: number\n },\n ): Promise<{\n fullStream?: ReadableStream<unknown>\n textStream?: ReadableStream<string>\n text?: Promise<string>\n }>\n}\n\n/** Lazily builds the Mastra agent (so model/key errors surface on the first\n * prompt with a clear message, not at process spawn). */\nexport type AgentFactory = () => Promise<MastraLike>\n\ninterface SessionState {\n prompt: AbortController | null\n}\n\n/** Pull the user's text out of an ACP prompt (its `text` content blocks). */\nexport function promptText(params: PromptRequest): string {\n const blocks = Array.isArray(params.prompt) ? params.prompt : []\n return blocks\n .filter((b): b is { type: \"text\"; text: string } =>\n Boolean(b) && (b as { type?: string }).type === \"text\" &&\n typeof (b as { text?: unknown }).text === \"string\",\n )\n .map((b) => b.text)\n .join(\"\")\n .trim()\n}\n\nexport class MastraAcpAgent implements AcpAgent {\n readonly #conn: AgentSideConnection\n readonly #buildAgent: AgentFactory\n readonly #resource: string\n readonly #sessions = new Map<string, SessionState>()\n #agent: MastraLike | null = null\n\n constructor(\n conn: AgentSideConnection,\n buildAgent: AgentFactory,\n resource = \"mastra-agent\",\n ) {\n this.#conn = conn\n this.#buildAgent = buildAgent\n // `resource` groups a user's threads in Mastra memory; one per agent here.\n this.#resource = resource\n }\n\n async initialize(_params: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentCapabilities: {\n // Stateless per-prompt for now; no resume/replay surface.\n loadSession: false,\n },\n }\n }\n\n async authenticate(\n _params: AuthenticateRequest,\n ): Promise<Record<string, never>> {\n // The provider key is read from the spawn env by the model gateway — no\n // ACP-level auth handshake needed.\n return {}\n }\n\n async newSession(_params: NewSessionRequest): Promise<NewSessionResponse> {\n const sessionId = randomId()\n this.#sessions.set(sessionId, { prompt: null })\n return { sessionId }\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.#sessions.get(params.sessionId)\n if (!session) throw new Error(`unknown session ${params.sessionId}`)\n\n // Cancel any in-flight turn for this session before starting a new one.\n session.prompt?.abort()\n const ac = new AbortController()\n session.prompt = ac\n\n const text = promptText(params)\n try {\n const agent = await this.#ensureAgent()\n // Thread = ACP session id → recall is scoped to this session's history.\n const result = await agent.stream(text, {\n abortSignal: ac.signal,\n memory: { thread: params.sessionId, resource: this.#resource },\n maxSteps: 200,\n })\n if (result.fullStream) {\n // Preferred path: the typed chunk stream carries text deltas AND\n // tool-call / tool-result events, so tool activity surfaces live.\n await this.#pumpFullStream(params.sessionId, result.fullStream, ac)\n } else if (result.textStream) {\n // Fallback: a text-only agent — relay prose deltas, no tool surface.\n await this.#pumpTextStream(params.sessionId, result.textStream, ac)\n }\n } catch (err) {\n if (ac.signal.aborted) return { stopReason: \"cancelled\" }\n // Surface the failure to the client as a message chunk, then end the\n // turn — better UX than a bare JSON-RPC error the host may swallow.\n await this.#conn.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: {\n type: \"text\",\n text: `\\n[mastra-agent error] ${(err as Error).message}\\n`,\n },\n },\n })\n session.prompt = null\n return { stopReason: \"refusal\" }\n }\n\n const cancelled = ac.signal.aborted\n session.prompt = null\n return { stopReason: cancelled ? \"cancelled\" : \"end_turn\" }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n this.#sessions.get(params.sessionId)?.prompt?.abort()\n }\n\n /**\n * The host applies the `model` (and other operator options) as a `--model`\n * spawn arg via the manifest `bin_args_template`, then ALSO calls this ACP\n * config hook (the daemon's default \"config\" apply path). The model is\n * already in effect, so this is a no-op that just reports our (empty) set of\n * runtime-configurable options. Without it the spawn fails with\n * \"Method not found: session/set_config_option\".\n */\n async setSessionConfigOption(\n _params: SetSessionConfigOptionRequest,\n ): Promise<SetSessionConfigOptionResponse> {\n return { configOptions: [] }\n }\n\n /** No agent-specific modes; accept and ignore so a host that sets one\n * doesn't error. */\n async setSessionMode(\n _params: SetSessionModeRequest,\n ): Promise<Record<string, never>> {\n return {}\n }\n\n /** Drain Mastra's typed `fullStream`, mapping each chunk to an ACP\n * `session/update` (text deltas + tool_call / tool_call_update). */\n async #pumpFullStream(\n sessionId: string,\n stream: ReadableStream<unknown>,\n ac: AbortController,\n ): Promise<void> {\n const reader = stream.getReader()\n try {\n for (;;) {\n const { value, done } = await reader.read()\n if (done || ac.signal.aborted) break\n if (!value) continue\n // Single boundary cast: raw Mastra chunks include many event types\n // beyond what MastraStreamChunk models; chunkToSessionUpdate returns\n // null for anything it doesn't recognise.\n const update = chunkToSessionUpdate(value as MastraStreamChunk)\n if (update) await this.#conn.sessionUpdate({ sessionId, update })\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n /** Fallback drain for an agent exposing only a plain text stream. */\n async #pumpTextStream(\n sessionId: string,\n stream: ReadableStream<string>,\n ac: AbortController,\n ): Promise<void> {\n const reader = stream.getReader()\n try {\n for (;;) {\n const { value, done } = await reader.read()\n if (done || ac.signal.aborted) break\n if (value) {\n await this.#conn.sessionUpdate({\n sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: value },\n },\n })\n }\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n async #ensureAgent(): Promise<MastraLike> {\n if (!this.#agent) this.#agent = await this.#buildAgent()\n return this.#agent\n }\n}\n\n/** 16 random bytes as hex — matches the SDK example's session id shape. */\nfunction randomId(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")\n}\n","/**\n * Boots the ACP server over stdio — the standard wiring for a spawned ACP\n * agent (mirrors the @agentclientprotocol/sdk agent example): the agent writes\n * JSON-RPC to stdout and reads from stdin.\n */\n\nimport { Readable, Writable } from \"node:stream\"\nimport { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\"\nimport { MastraAcpAgent, type AgentFactory } from \"./acp-host.js\"\n\nexport function runAcpOverStdio(buildAgent: AgentFactory): AgentSideConnection {\n // ndJsonStream(writable, readable): outgoing bytes -> stdout, incoming <- stdin.\n const toClient = Writable.toWeb(process.stdout) as WritableStream<Uint8Array>\n const fromClient = Readable.toWeb(\n process.stdin,\n ) as unknown as ReadableStream<Uint8Array>\n const stream = ndJsonStream(toClient, fromClient)\n return new AgentSideConnection(\n (conn) => new MastraAcpAgent(conn, buildAgent),\n stream,\n )\n}\n"]}
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { runAcpOverStdio, makeAgentFactory } from './chunk-LHQSSCUP.mjs';
2
+ import { runAcpOverStdio, makeAgentFactory } from './chunk-ZVLJDGI4.mjs';
3
3
 
4
4
  /**
5
5
  * @agentproto/adapter-mastra-agent v0.1.0-alpha
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
2
2
  export { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
3
+ import { MastraToolLike } from '@agentproto/mastra';
3
4
  import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, AuthenticateRequest, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SessionUpdate, ToolKind } from '@agentclientprotocol/sdk';
4
5
  import { ModelRef, MemoryConfig } from '@agentproto/agent';
5
6
  import { createTool } from '@mastra/core/tools';
@@ -87,6 +88,12 @@ interface AgentSourceOptions {
87
88
  cwd?: string;
88
89
  /** When false, the `run_command` tool is withheld. Default true. */
89
90
  allowExec?: boolean;
91
+ /**
92
+ * Extra tools merged over the built-in workspace toolset (extra wins on id
93
+ * collision) — programmatic-only, for a host embedding this agent that
94
+ * wants to grant tools the built-in toolset doesn't cover. No CLI flag.
95
+ */
96
+ extraTools?: Record<string, MastraToolLike>;
90
97
  }
91
98
  /** The built-in AGENT.md used when no file is supplied. */
92
99
  declare function defaultAgentManifest(model: string): string;
@@ -135,10 +142,16 @@ declare function resolveMastraModel(ref: ModelRef, env?: Record<string, string |
135
142
  interface WorkspaceToolsOptions {
136
143
  /** Absolute path the agent is confined to (the spawn cwd). */
137
144
  cwd: string;
138
- /** When false, `run_command` is omitted from the toolset. Default true. */
145
+ /** When false, `run_command` (and the other exec-gated tools) are omitted. Default true. */
139
146
  allowExec?: boolean;
140
147
  /** Per-command timeout (ms). Default 120_000. */
141
148
  execTimeoutMs?: number;
149
+ /**
150
+ * Extra tools merged over the built-ins, keyed by id — lets an embedding
151
+ * host add tools the built-in toolset doesn't cover. On id collision, an
152
+ * extra tool wins over a built-in of the same id.
153
+ */
154
+ extraTools?: Record<string, MastraToolLike>;
142
155
  }
143
156
  /** Resolve `p` against `cwd`, throwing if the result escapes the workspace. */
144
157
  declare function resolveInCwd(cwd: string, p: string): string;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { DEFAULT_MODEL, DEFAULT_TOOL_IDS, MastraAcpAgent, buildSqliteMemory, chunkToSessionUpdate, defaultAgentManifest, makeAgentFactory, makeWorkspaceTools, modelRefToString, promptText, providerOf, resolveInCwd, resolveMastraModel, resolveMemoryDbPath, runAcpOverStdio, toolCallTitle, toolKindFor } from './chunk-LHQSSCUP.mjs';
1
+ export { DEFAULT_MODEL, DEFAULT_TOOL_IDS, MastraAcpAgent, buildSqliteMemory, chunkToSessionUpdate, defaultAgentManifest, makeAgentFactory, makeWorkspaceTools, modelRefToString, promptText, providerOf, resolveInCwd, resolveMastraModel, resolveMemoryDbPath, runAcpOverStdio, toolCallTitle, toolKindFor } from './chunk-ZVLJDGI4.mjs';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { defineAgentCli, createAgentCliRuntime } from '@agentproto/driver-agent-cli';
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/adapter-mastra-agent",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "@agentproto/adapter-mastra-agent — first-party agentproto agent. An AIP-42 AGENT.md run as a live Mastra agent behind an AIP-44 ACP server, spawnable by the daemon like any other AGENT-CLI arm AND launchable standalone via `agentproto-mastra acp`. Our own loop, our own models — no external CLI.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -48,19 +48,21 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@agentclientprotocol/sdk": "^0.21.0",
51
- "@mastra/core": "^1.52.1",
52
- "@mastra/libsql": "~1.17.0",
53
- "@mastra/memory": "^1.23.1",
51
+ "@mastra/core": "^1.55.0",
52
+ "@mastra/libsql": "~1.18.0",
53
+ "@mastra/memory": "^1.24.0",
54
54
  "zod": "^4.4.3",
55
55
  "@agentproto/agent": "0.2.1",
56
- "@agentproto/driver-agent-cli": "2.1.0",
57
- "@agentproto/mastra": "0.2.3"
56
+ "@agentproto/driver-agent-cli": "2.2.0",
57
+ "@agentproto/mastra": "0.2.5"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^25.6.2",
61
61
  "tsup": "^8.5.1",
62
62
  "typescript": "^5.9.3",
63
63
  "vitest": "^3.2.4",
64
+ "@agentproto/app-kit": "0.4.0",
65
+ "@agentproto/apps": "0.3.0",
64
66
  "@agentproto/tooling": "0.1.0-alpha.0"
65
67
  },
66
68
  "scripts": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/memory.ts","../src/model-resolver.ts","../src/workspace-tools.ts","../src/default-agent.ts","../src/tool-call-map.ts","../src/acp-host.ts","../src/run.ts"],"names":["fs"],"mappings":"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","file":"chunk-LHQSSCUP.mjs","sourcesContent":["/**\n * SQLite-backed memory for the agent, via Mastra's LibSQL store.\n *\n * Each ACP session is a memory *thread* (see acp-host.ts), so the agent recalls\n * earlier turns within a session. The db is a single SQLite file (LibSQL is a\n * SQLite fork) under `~/.agentproto/mastra-agent/` by default — persistent\n * across spawns — overridable with `AGENTPROTO_MASTRA_MEMORY_DB`.\n */\n\nimport { mkdirSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { LibSQLStore } from \"@mastra/libsql\"\nimport { Memory } from \"@mastra/memory\"\nimport type { MemoryConfig } from \"@agentproto/agent\"\n\n/** A built Mastra memory — structural, matching `@agentproto/mastra`'s\n * `MastraMemoryLike` expectation without importing the exact type. */\nexport type MastraMemoryLike = Memory\n\n/** Resolve the SQLite file path, creating the parent dir. `AGENTPROTO_MASTRA_MEMORY_DB`\n * wins; otherwise `~/.agentproto/mastra-agent/memory.db`. */\nexport function resolveMemoryDbPath(\n env: Record<string, string | undefined> = process.env,\n): string {\n const override = env.AGENTPROTO_MASTRA_MEMORY_DB\n if (override) return override\n const dir = join(homedir(), \".agentproto\", \"mastra-agent\")\n mkdirSync(dir, { recursive: true })\n return join(dir, \"memory.db\")\n}\n\n/**\n * Build a Mastra `Memory` from an AIP-42 `memory:` config. Returns `undefined`\n * when memory is disabled (`scope: \"none\"`) so `buildMastraAgent` attaches none.\n *\n * - `retention_turns` → `options.lastMessages` (how many recent messages to\n * replay into context). Defaults to 20.\n * - Semantic recall is left off (it needs an embedder + vector index) — this is\n * conversation-history memory, the SQLite ask.\n */\nexport function buildSqliteMemory(\n config?: MemoryConfig,\n env: Record<string, string | undefined> = process.env,\n): MastraMemoryLike | undefined {\n if (config?.scope === \"none\") return undefined\n const dbPath = resolveMemoryDbPath(env)\n const lastMessages =\n typeof config?.retention_turns === \"number\" && config.retention_turns > 0\n ? config.retention_turns\n : 20\n return new Memory({\n storage: new LibSQLStore({ id: \"mastra-agent-memory\", url: `file:${dbPath}` }),\n options: {\n lastMessages,\n semanticRecall: false,\n workingMemory: { enabled: false },\n },\n })\n}\n","/**\n * WP1 — AIP-42 `model:` ref -> a model Mastra's `Agent` can run.\n *\n * Mastra 1.x ships a model router (`models.dev` gateway) that accepts a bare\n * `provider/model` string (e.g. `anthropic/claude-opus-4-8`,\n * `openrouter/z-ai/glm-5.2`) and resolves it to a live ai-sdk model, reading\n * the provider's key from the environment. So the resolver is a thin,\n * *validated* pass-through: extract the ref string, sanity-check the shape,\n * surface a friendly error when the obvious provider key is missing, and hand\n * the string to Mastra. No bespoke provider wiring, no extra ai-sdk deps.\n */\n\nimport type { ModelRef } from \"@agentproto/agent\"\n\n/** Best-effort provider -> env var map, used only for a friendly preflight\n * error. Mastra's gateway is the source of truth; this list just turns the\n * common \"forgot the key\" case into a clear message instead of a deep ai-sdk\n * stack trace. Providers not listed here skip the preflight check. */\nconst PROVIDER_ENV: Record<string, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n groq: \"GROQ_API_KEY\",\n xai: \"XAI_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n deepseek: \"DEEPSEEK_API_KEY\",\n}\n\n/** Pull the model id string out of an AIP-42 `ModelRef` (string | { ref }). */\nexport function modelRefToString(ref: ModelRef): string {\n if (typeof ref === \"string\") return ref.trim()\n if (ref && typeof ref === \"object\" && typeof ref.ref === \"string\") {\n return ref.ref.trim()\n }\n throw new Error(\n \"mastra-agent: AGENT.md `model` must be a `provider/model` string \" +\n \"(or { ref }); inline model objects are not supported by this adapter.\",\n )\n}\n\n/** The provider segment is everything before the first `/`. */\nexport function providerOf(modelId: string): string {\n const slash = modelId.indexOf(\"/\")\n return slash > 0 ? modelId.slice(0, slash) : modelId\n}\n\n/**\n * Infer the provider for a bare, unambiguous id so an AGENT.md stays\n * adapter-agnostic. `claude-sonnet-5` — what the claude-code / claude-sdk\n * adapters already accept bare — routes here as `anthropic/claude-sonnet-5`,\n * instead of being handed to Mastra's gateway with no provider (which fails\n * with \"could not resolve model configuration\"). Only Claude ids are\n * unambiguous today; every other provider still needs the explicit prefix.\n */\nexport function normalizeModelId(modelId: string): string {\n if (modelId.includes(\"/\")) return modelId\n if (/^claude[-.]/i.test(modelId)) return `anthropic/${modelId}`\n return modelId\n}\n\n/**\n * Resolve an AIP-42 model ref to the value Mastra's `Agent` constructor takes.\n * Returns the `provider/model` string — Mastra routes it. `env` defaults to\n * `process.env`; injectable for tests.\n */\nexport function resolveMastraModel(\n ref: ModelRef,\n env: Record<string, string | undefined> = process.env,\n): string {\n const modelId = normalizeModelId(modelRefToString(ref))\n if (!modelId) {\n throw new Error(\"mastra-agent: empty `model` ref.\")\n }\n const provider = providerOf(modelId)\n const envKey = PROVIDER_ENV[provider]\n if (envKey && !env[envKey]) {\n throw new Error(\n `mastra-agent: model '${modelId}' needs ${envKey} in the environment ` +\n `(provider '${provider}'). Set it on the spawn env or export it.`,\n )\n }\n return modelId\n}\n","/**\n * Workspace toolset — gives the Mastra agent the ability to inspect, edit, and\n * run commands inside its session working directory, like a coding agent.\n *\n * SAFETY: every file path is resolved against the session `cwd` and rejected if\n * it escapes (no `../` traversal, no absolute paths outside cwd). Command\n * execution runs with `cwd` and a timeout, and is gated by `allowExec` (the CLI\n * sets it from `AGENTPROTO_MASTRA_NO_EXEC`). The agent only ever touches the\n * directory the daemon spawned it in.\n */\n\nimport { exec } from \"node:child_process\"\nimport { promises as fs } from \"node:fs\"\nimport { isAbsolute, relative, resolve, sep } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { createTool } from \"@mastra/core/tools\"\nimport { z } from \"zod\"\n\nconst execAsync = promisify(exec)\n\n/** A Mastra tool (structural — avoids coupling to a @mastra/core type name). */\nexport interface WorkspaceTool {\n id: string\n}\n\nexport interface WorkspaceToolsOptions {\n /** Absolute path the agent is confined to (the spawn cwd). */\n cwd: string\n /** When false, `run_command` is omitted from the toolset. Default true. */\n allowExec?: boolean\n /** Per-command timeout (ms). Default 120_000. */\n execTimeoutMs?: number\n}\n\n/** Resolve `p` against `cwd`, throwing if the result escapes the workspace. */\nexport function resolveInCwd(cwd: string, p: string): string {\n const base = resolve(cwd)\n const target = isAbsolute(p) ? resolve(p) : resolve(base, p)\n const rel = relative(base, target)\n if (rel === \"\" ) return target // the workspace root itself\n if (rel.startsWith(\"..\") || (isAbsolute(rel) && !target.startsWith(base + sep))) {\n throw new Error(\n `path '${p}' escapes the workspace (resolved to '${target}', outside '${base}').`,\n )\n }\n return target\n}\n\n/**\n * Build the workspace toolset, all confined to `cwd`. Returns a record keyed by\n * tool id (also the AGENT.md tool ref the resolver matches).\n */\nexport function makeWorkspaceTools(\n opts: WorkspaceToolsOptions,\n): Record<string, ReturnType<typeof createTool>> {\n const cwd = resolve(opts.cwd)\n const allowExec = opts.allowExec ?? true\n const execTimeoutMs = opts.execTimeoutMs ?? 120_000\n\n const list_dir = createTool({\n id: \"list_dir\",\n description:\n \"List the entries of a directory in the workspace. Returns names with a trailing '/' for directories. Path is relative to the workspace root (default '.').\",\n inputSchema: z.object({\n path: z.string().default(\".\").describe(\"Directory path, relative to the workspace root.\"),\n }),\n outputSchema: z.object({ entries: z.array(z.string()) }),\n execute: async (input: { path?: string }) => {\n const dir = resolveInCwd(cwd, input.path ?? \".\")\n const dirents = await fs.readdir(dir, { withFileTypes: true })\n return {\n entries: dirents.map((d) => (d.isDirectory() ? `${d.name}/` : d.name)).sort(),\n }\n },\n })\n\n const read_file = createTool({\n id: \"read_file\",\n description:\n \"Read a UTF-8 text file from the workspace. Path is relative to the workspace root.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n }),\n outputSchema: z.object({ content: z.string() }),\n execute: async (input: { path: string }) => {\n const file = resolveInCwd(cwd, input.path)\n return { content: await fs.readFile(file, \"utf8\") }\n },\n })\n\n const write_file = createTool({\n id: \"write_file\",\n description:\n \"Write (creating or overwriting) a UTF-8 text file in the workspace. Creates parent directories as needed. Path is relative to the workspace root.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n content: z.string().describe(\"Full file contents to write.\"),\n }),\n outputSchema: z.object({ path: z.string(), bytes: z.number() }),\n execute: async (input: { path: string; content: string }) => {\n const file = resolveInCwd(cwd, input.path)\n await fs.mkdir(resolve(file, \"..\"), { recursive: true })\n await fs.writeFile(file, input.content, \"utf8\")\n return { path: input.path, bytes: Buffer.byteLength(input.content, \"utf8\") }\n },\n })\n\n const edit_file = createTool({\n id: \"edit_file\",\n description:\n \"Replace an exact substring in a workspace file. `old_string` must occur exactly once. Use for targeted edits instead of rewriting the whole file.\",\n inputSchema: z.object({\n path: z.string().describe(\"File path, relative to the workspace root.\"),\n old_string: z.string().describe(\"Exact text to replace (must be unique in the file).\"),\n new_string: z.string().describe(\"Replacement text.\"),\n }),\n outputSchema: z.object({ path: z.string(), replaced: z.boolean() }),\n execute: async (input: { path: string; old_string: string; new_string: string }) => {\n const file = resolveInCwd(cwd, input.path)\n const current = await fs.readFile(file, \"utf8\")\n const count = current.split(input.old_string).length - 1\n if (count === 0) throw new Error(`old_string not found in '${input.path}'.`)\n if (count > 1) {\n throw new Error(`old_string occurs ${count}× in '${input.path}' — make it unique.`)\n }\n await fs.writeFile(file, current.replace(input.old_string, input.new_string), \"utf8\")\n return { path: input.path, replaced: true }\n },\n })\n\n const tools: Record<string, ReturnType<typeof createTool>> = {\n list_dir,\n read_file,\n write_file,\n edit_file,\n }\n\n if (allowExec) {\n tools.run_command = createTool({\n id: \"run_command\",\n description:\n \"Run a shell command in the workspace directory and return its stdout/stderr/exit code. Runs with a timeout; use for builds, tests, git, etc.\",\n inputSchema: z.object({\n command: z.string().describe(\"The shell command to run (executed in the workspace root).\"),\n }),\n outputSchema: z.object({\n stdout: z.string(),\n stderr: z.string(),\n exitCode: z.number(),\n }),\n execute: async (input: { command: string }) => {\n try {\n const { stdout, stderr } = await execAsync(input.command, {\n cwd,\n timeout: execTimeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n })\n return { stdout, stderr, exitCode: 0 }\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; code?: number; message?: string }\n return {\n stdout: e.stdout ?? \"\",\n stderr: e.stderr ?? e.message ?? String(err),\n exitCode: typeof e.code === \"number\" ? e.code : 1,\n }\n }\n },\n })\n }\n\n return tools\n}\n","/**\n * Builds a runnable Mastra agent from an AIP-42 AGENT.md — either a caller's\n * file or a zero-config built-in default — wiring the model, the markdown body\n * as instructions, the SQLite memory, and the workspace toolset.\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { agentFromManifest, parseAgentManifest } from \"@agentproto/agent\"\nimport { buildMastraAgent } from \"@agentproto/mastra\"\nimport type { MastraLike } from \"./acp-host.js\"\nimport { buildSqliteMemory } from \"./memory.js\"\nimport { resolveMastraModel } from \"./model-resolver.js\"\nimport { makeWorkspaceTools } from \"./workspace-tools.js\"\n\n/** Cheap OpenRouter coder by default — this is the budget first-party arm,\n * same rationale as the hermes default. Override with --model / env. */\nexport const DEFAULT_MODEL = \"openrouter/z-ai/glm-5.2\"\n\n/** Tool ids the built-in default agent is granted (the workspace toolset). */\nexport const DEFAULT_TOOL_IDS = [\n \"list_dir\",\n \"read_file\",\n \"write_file\",\n \"edit_file\",\n \"run_command\",\n] as const\n\nexport interface AgentSourceOptions {\n /** Path to an AGENT.md. When omitted, the built-in default agent is used. */\n agentFile?: string\n /** Model id for the default agent (ignored when agentFile carries a model). */\n model?: string\n /** Workspace dir the tools are confined to. Defaults to `process.cwd()`. */\n cwd?: string\n /** When false, the `run_command` tool is withheld. Default true. */\n allowExec?: boolean\n}\n\n/** The built-in AGENT.md used when no file is supplied. */\nexport function defaultAgentManifest(model: string): string {\n return [\n \"---\",\n \"schema: agent/v1\",\n \"id: mastra-agent\",\n \"description: A first-party agentproto agent powered by Mastra.\",\n `model: ${model}`,\n \"version: 0.1.0\",\n \"tools:\",\n ...DEFAULT_TOOL_IDS.map((id) => ` - ${id}`),\n \"memory:\",\n \" scope: per-conversation\",\n \" retention_turns: 20\",\n \"---\",\n \"\",\n \"You are a capable, concise coding agent operating inside a workspace \",\n \"directory. You can list, read, write, and edit files and run shell \",\n \"commands there using your tools. Do exactly what the user asks — when \",\n \"asked to reply with an exact string, reply with only that string.\",\n \"\",\n ].join(\"\\n\")\n}\n\n/** Pull the id string out of an AIP-42 tool ref (string | { ref }). */\nfunction toolRefId(ref: unknown): string | undefined {\n if (typeof ref === \"string\") return ref\n if (ref && typeof ref === \"object\" && typeof (ref as { ref?: unknown }).ref === \"string\") {\n return (ref as { ref: string }).ref\n }\n return undefined\n}\n\n/** Resolve the AGENT.md source for these options (file or built-in default). */\nexport async function resolveAgentSource(\n opts: AgentSourceOptions = {},\n): Promise<string> {\n if (opts.agentFile) return readFile(opts.agentFile, \"utf8\")\n return defaultAgentManifest(opts.model ?? DEFAULT_MODEL)\n}\n\n/**\n * A lazy factory: parses the AGENT.md, builds the Mastra agent with the model\n * resolver, SQLite memory, the markdown body as instructions, and the\n * workspace toolset (matched by tool id), then returns it as the structural\n * `MastraLike` the ACP host needs.\n */\nexport function makeAgentFactory(\n opts: AgentSourceOptions = {},\n): () => Promise<MastraLike> {\n return async () => {\n const source = await resolveAgentSource(opts)\n const { frontmatter, body } = parseAgentManifest(source)\n const handle = agentFromManifest({ frontmatter, body })\n\n const cwd = opts.cwd ?? process.cwd()\n const workspaceTools = makeWorkspaceTools({ cwd, allowExec: opts.allowExec })\n\n const { agent } = await buildMastraAgent(handle, {\n resolveModel: (ref) => resolveMastraModel(ref),\n // Match each declared tool ref against the workspace toolset by id.\n resolveTool: (ref) => {\n const id = toolRefId(ref)\n const tool = id ? workspaceTools[id] : undefined\n return tool ? { name: id as string, tool } : undefined\n },\n buildMemory: (config) => buildSqliteMemory(config),\n // The markdown body is the agent's primary system prompt (AIP-42).\n body,\n })\n return agent as unknown as MastraLike\n }\n}\n","/**\n * Pure mapping from Mastra `fullStream` chunks to AIP-44 ACP `session/update`\n * payloads. Kept dependency-light (no SDK import beyond types) and side-effect\n * free so it is straightforward to unit-test; the ACP host (acp-host.ts) owns\n * the wire/IO and just forwards whatever this returns.\n *\n * Mastra emits a typed chunk union on `agent.stream(...).fullStream`. We care\n * about three kinds:\n * - `text-delta` → ACP `agent_message_chunk` (assistant prose)\n * - `tool-call` → ACP `tool_call` (a tool started, status in_progress)\n * - `tool-result` → ACP `tool_call_update` (that tool finished/failed)\n * Everything else (reasoning, step boundaries, finish, …) is not surfaced.\n */\n\nimport type { SessionUpdate, ToolKind } from \"@agentclientprotocol/sdk\"\n\n/** The narrow slice of a Mastra fullStream chunk we read. Typed structurally\n * so we don't couple to a specific @mastra/core version.\n * Mastra 1.45 wraps all chunk data in a `payload` field. */\nexport type MastraStreamChunk =\n | { type: \"text-delta\"; payload?: { text?: string } }\n | { type: \"tool-call\"; payload?: { toolCallId?: string; toolName?: string; args?: unknown } }\n | { type: \"tool-result\"; payload?: { toolCallId?: string; result?: unknown; isError?: boolean } }\n\n/** Map a workspace tool id to the ACP {@link ToolKind} that drives client\n * icon/UI treatment. Unknown ids fall back to \"other\". */\nexport function toolKindFor(toolName: string): ToolKind {\n switch (toolName) {\n case \"read_file\":\n case \"list_dir\":\n return \"read\"\n case \"write_file\":\n case \"edit_file\":\n return \"edit\"\n case \"run_command\":\n return \"execute\"\n default:\n return \"other\"\n }\n}\n\n/** A short, human-readable title for a tool call, e.g. `run_command: ls -la`\n * or `read_file: src/index.ts`. Falls back to the bare tool name. */\nexport function toolCallTitle(toolName: string, args: unknown): string {\n if (args && typeof args === \"object\") {\n const { command, path, file } = args as Record<string, unknown>\n const hint =\n (typeof command === \"string\" && command) ||\n (typeof path === \"string\" && path) ||\n (typeof file === \"string\" && file) ||\n \"\"\n if (hint) return `${toolName}: ${hint}`\n }\n return toolName\n}\n\n/**\n * Translate one Mastra chunk into an ACP `session/update` payload, or `null`\n * when the chunk has no ACP surface (or is missing the ids we need). The ACP\n * host wraps the result with the `sessionId`.\n */\nexport function chunkToSessionUpdate(\n chunk: MastraStreamChunk,\n): SessionUpdate | null {\n switch (chunk.type) {\n case \"text-delta\": {\n const text = chunk.payload?.text\n if (!text) return null\n return {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text },\n }\n }\n case \"tool-call\": {\n const toolCallId = chunk.payload?.toolCallId\n if (!toolCallId) return null\n const toolName = chunk.payload?.toolName ?? \"tool\"\n const args = chunk.payload?.args\n return {\n sessionUpdate: \"tool_call\",\n toolCallId,\n title: toolCallTitle(toolName, args),\n kind: toolKindFor(toolName),\n status: \"in_progress\",\n rawInput: args,\n }\n }\n case \"tool-result\": {\n const toolCallId = chunk.payload?.toolCallId\n if (!toolCallId) return null\n return {\n sessionUpdate: \"tool_call_update\",\n toolCallId,\n status: chunk.payload?.isError ? \"failed\" : \"completed\",\n rawOutput: chunk.payload?.result,\n }\n }\n default:\n return null\n }\n}\n","/**\n * WP2 — the agent side of AIP-44 ACP, backed by a live Mastra agent.\n *\n * Implements the `@agentclientprotocol/sdk` `Agent` interface: handles the\n * session lifecycle and, on `session/prompt`, drives a Mastra agent's\n * `stream()` — relaying each text delta as an `agent_message_chunk`\n * `session/update`, exactly as an IDE/host expects from codex or claude-code.\n *\n * No Mastra-specific protocol knowledge leaks past this file; everything above\n * is the standard ACP wire, so the daemon spawns this like any other arm.\n */\n\nimport type {\n AgentSideConnection,\n Agent as AcpAgent,\n AuthenticateRequest,\n CancelNotification,\n InitializeRequest,\n InitializeResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n SetSessionConfigOptionRequest,\n SetSessionConfigOptionResponse,\n SetSessionModeRequest,\n} from \"@agentclientprotocol/sdk\"\nimport { PROTOCOL_VERSION } from \"@agentclientprotocol/sdk\"\nimport { type MastraStreamChunk, chunkToSessionUpdate } from \"./tool-call-map.js\"\n\n/** A built Mastra agent — only the surface we need (its `stream`). Typed\n * structurally so we don't couple to a specific @mastra/core version.\n *\n * We read `fullStream` (the typed chunk union: text deltas AND tool-call /\n * tool-result events) so tool activity surfaces as ACP `tool_call` updates,\n * not only the final prose. `textStream` is kept as an optional fallback for\n * a stripped agent that exposes only text. */\nexport interface MastraLike {\n stream(\n input: string,\n options?: {\n abortSignal?: AbortSignal\n /** Memory threading — `thread` scopes recall to one ACP session. */\n memory?: { thread?: string; resource?: string }\n /** Max agentic loop steps (tool-call → execute → continue). Default 1 = no loop. */\n maxSteps?: number\n },\n ): Promise<{\n fullStream?: ReadableStream<unknown>\n textStream?: ReadableStream<string>\n text?: Promise<string>\n }>\n}\n\n/** Lazily builds the Mastra agent (so model/key errors surface on the first\n * prompt with a clear message, not at process spawn). */\nexport type AgentFactory = () => Promise<MastraLike>\n\ninterface SessionState {\n prompt: AbortController | null\n}\n\n/** Pull the user's text out of an ACP prompt (its `text` content blocks). */\nexport function promptText(params: PromptRequest): string {\n const blocks = Array.isArray(params.prompt) ? params.prompt : []\n return blocks\n .filter((b): b is { type: \"text\"; text: string } =>\n Boolean(b) && (b as { type?: string }).type === \"text\" &&\n typeof (b as { text?: unknown }).text === \"string\",\n )\n .map((b) => b.text)\n .join(\"\")\n .trim()\n}\n\nexport class MastraAcpAgent implements AcpAgent {\n readonly #conn: AgentSideConnection\n readonly #buildAgent: AgentFactory\n readonly #resource: string\n readonly #sessions = new Map<string, SessionState>()\n #agent: MastraLike | null = null\n\n constructor(\n conn: AgentSideConnection,\n buildAgent: AgentFactory,\n resource = \"mastra-agent\",\n ) {\n this.#conn = conn\n this.#buildAgent = buildAgent\n // `resource` groups a user's threads in Mastra memory; one per agent here.\n this.#resource = resource\n }\n\n async initialize(_params: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentCapabilities: {\n // Stateless per-prompt for now; no resume/replay surface.\n loadSession: false,\n },\n }\n }\n\n async authenticate(\n _params: AuthenticateRequest,\n ): Promise<Record<string, never>> {\n // The provider key is read from the spawn env by the model gateway — no\n // ACP-level auth handshake needed.\n return {}\n }\n\n async newSession(_params: NewSessionRequest): Promise<NewSessionResponse> {\n const sessionId = randomId()\n this.#sessions.set(sessionId, { prompt: null })\n return { sessionId }\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.#sessions.get(params.sessionId)\n if (!session) throw new Error(`unknown session ${params.sessionId}`)\n\n // Cancel any in-flight turn for this session before starting a new one.\n session.prompt?.abort()\n const ac = new AbortController()\n session.prompt = ac\n\n const text = promptText(params)\n try {\n const agent = await this.#ensureAgent()\n // Thread = ACP session id → recall is scoped to this session's history.\n const result = await agent.stream(text, {\n abortSignal: ac.signal,\n memory: { thread: params.sessionId, resource: this.#resource },\n maxSteps: 200,\n })\n if (result.fullStream) {\n // Preferred path: the typed chunk stream carries text deltas AND\n // tool-call / tool-result events, so tool activity surfaces live.\n await this.#pumpFullStream(params.sessionId, result.fullStream, ac)\n } else if (result.textStream) {\n // Fallback: a text-only agent — relay prose deltas, no tool surface.\n await this.#pumpTextStream(params.sessionId, result.textStream, ac)\n }\n } catch (err) {\n if (ac.signal.aborted) return { stopReason: \"cancelled\" }\n // Surface the failure to the client as a message chunk, then end the\n // turn — better UX than a bare JSON-RPC error the host may swallow.\n await this.#conn.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: {\n type: \"text\",\n text: `\\n[mastra-agent error] ${(err as Error).message}\\n`,\n },\n },\n })\n session.prompt = null\n return { stopReason: \"refusal\" }\n }\n\n const cancelled = ac.signal.aborted\n session.prompt = null\n return { stopReason: cancelled ? \"cancelled\" : \"end_turn\" }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n this.#sessions.get(params.sessionId)?.prompt?.abort()\n }\n\n /**\n * The host applies the `model` (and other operator options) as a `--model`\n * spawn arg via the manifest `bin_args_template`, then ALSO calls this ACP\n * config hook (the daemon's default \"config\" apply path). The model is\n * already in effect, so this is a no-op that just reports our (empty) set of\n * runtime-configurable options. Without it the spawn fails with\n * \"Method not found: session/set_config_option\".\n */\n async setSessionConfigOption(\n _params: SetSessionConfigOptionRequest,\n ): Promise<SetSessionConfigOptionResponse> {\n return { configOptions: [] }\n }\n\n /** No agent-specific modes; accept and ignore so a host that sets one\n * doesn't error. */\n async setSessionMode(\n _params: SetSessionModeRequest,\n ): Promise<Record<string, never>> {\n return {}\n }\n\n /** Drain Mastra's typed `fullStream`, mapping each chunk to an ACP\n * `session/update` (text deltas + tool_call / tool_call_update). */\n async #pumpFullStream(\n sessionId: string,\n stream: ReadableStream<unknown>,\n ac: AbortController,\n ): Promise<void> {\n const reader = stream.getReader()\n try {\n for (;;) {\n const { value, done } = await reader.read()\n if (done || ac.signal.aborted) break\n if (!value) continue\n // Single boundary cast: raw Mastra chunks include many event types\n // beyond what MastraStreamChunk models; chunkToSessionUpdate returns\n // null for anything it doesn't recognise.\n const update = chunkToSessionUpdate(value as MastraStreamChunk)\n if (update) await this.#conn.sessionUpdate({ sessionId, update })\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n /** Fallback drain for an agent exposing only a plain text stream. */\n async #pumpTextStream(\n sessionId: string,\n stream: ReadableStream<string>,\n ac: AbortController,\n ): Promise<void> {\n const reader = stream.getReader()\n try {\n for (;;) {\n const { value, done } = await reader.read()\n if (done || ac.signal.aborted) break\n if (value) {\n await this.#conn.sessionUpdate({\n sessionId,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: value },\n },\n })\n }\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n async #ensureAgent(): Promise<MastraLike> {\n if (!this.#agent) this.#agent = await this.#buildAgent()\n return this.#agent\n }\n}\n\n/** 16 random bytes as hex — matches the SDK example's session id shape. */\nfunction randomId(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")\n}\n","/**\n * Boots the ACP server over stdio — the standard wiring for a spawned ACP\n * agent (mirrors the @agentclientprotocol/sdk agent example): the agent writes\n * JSON-RPC to stdout and reads from stdin.\n */\n\nimport { Readable, Writable } from \"node:stream\"\nimport { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\"\nimport { MastraAcpAgent, type AgentFactory } from \"./acp-host.js\"\n\nexport function runAcpOverStdio(buildAgent: AgentFactory): AgentSideConnection {\n // ndJsonStream(writable, readable): outgoing bytes -> stdout, incoming <- stdin.\n const toClient = Writable.toWeb(process.stdout) as WritableStream<Uint8Array>\n const fromClient = Readable.toWeb(\n process.stdin,\n ) as unknown as ReadableStream<Uint8Array>\n const stream = ndJsonStream(toClient, fromClient)\n return new AgentSideConnection(\n (conn) => new MastraAcpAgent(conn, buildAgent),\n stream,\n )\n}\n"]}