@agentproto/worktree 0.5.5 → 0.6.2

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,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { connectDaemonAgentSessionHost, worktreeAgentWorkflow } from '../chunk-R6UERXV4.mjs';
2
+ import { connectDaemonAgentSessionHost, worktreeAgentWorkflow } from '../chunk-5TEU6UGY.mjs';
3
3
  import '../chunk-E3EM24BS.mjs';
4
- import '../chunk-Y2TW7PBC.mjs';
5
- import '../chunk-CM3XGWTY.mjs';
4
+ import '../chunk-Y337JFBG.mjs';
5
+ import '../chunk-BBDKRTJK.mjs';
6
6
  import { runWorkflow } from '@agentproto/workflow-runtime';
7
7
  import { resolve } from 'path';
8
8
  import { openSync, closeSync, createReadStream, createWriteStream } from 'fs';
@@ -14,7 +14,7 @@ import { createInterface } from 'readline';
14
14
  */
15
15
  var USAGE = `usage: worktree-agent run --repo <abs repo root> --slug <id> --task "<prompt>" --gate "<check cmd>"
16
16
  [--base <ref>] [--adapter <slug>] [--deps-cmd "<cmd>"] [--copy-glob <glob>]...
17
- [--link <path>]... [--no-cleanup] [--yes]
17
+ [--link <path>]... [--write-file <json>]... [--no-cleanup] [--yes]
18
18
 
19
19
  --repo Absolute (or cwd-relative) path to the git repository root.
20
20
  --slug Worktree/branch identifier, e.g. 'fix-flaky-test'.
@@ -26,6 +26,8 @@ var USAGE = `usage: worktree-agent run --repo <abs repo root> --slug <id> --task
26
26
  --copy-glob Gitignored glob to copy into the worktree (repeatable).
27
27
  --link Gitignored dir/file to symlink from the host repo into the worktree
28
28
  before deps (node_modules, sibling workspace repos); repeatable.
29
+ --write-file JSON {"path","content","mode"?} written into the worktree before
30
+ deps, e.g. generated package-manager config (repeatable).
29
31
  --no-cleanup Keep the worktree's branch after cleanup (still removes the worktree dir).
30
32
  --yes Auto-approve the cleanup step instead of prompting.
31
33
  `;
@@ -47,6 +49,7 @@ ${USAGE}` : USAGE);
47
49
  let depsCmd;
48
50
  const copyGlobs = [];
49
51
  const linkPaths = [];
52
+ const writeFiles = [];
50
53
  let deleteBranch = true;
51
54
  let yes = false;
52
55
  function nextValue(flag, i) {
@@ -86,6 +89,24 @@ ${USAGE}`);
86
89
  case "--link":
87
90
  linkPaths.push(nextValue(arg, ++i));
88
91
  break;
92
+ case "--write-file": {
93
+ const raw = nextValue(arg, ++i);
94
+ let parsed;
95
+ try {
96
+ parsed = JSON.parse(raw);
97
+ } catch {
98
+ throw new CliUsageError(`--write-file value is not valid JSON: ${raw}
99
+
100
+ ${USAGE}`);
101
+ }
102
+ if (typeof parsed !== "object" || parsed === null || typeof parsed.path !== "string" || typeof parsed.content !== "string") {
103
+ throw new CliUsageError(`--write-file requires {"path": string, "content": string, "mode"?: "create"|"append"}: ${raw}
104
+
105
+ ${USAGE}`);
106
+ }
107
+ writeFiles.push(parsed);
108
+ break;
109
+ }
89
110
  case "--no-cleanup":
90
111
  deleteBranch = false;
91
112
  break;
@@ -119,7 +140,8 @@ ${USAGE}`);
119
140
  ...adapter !== void 0 ? { adapter } : {},
120
141
  ...depsCmd !== void 0 ? { depsCmd } : {},
121
142
  ...copyGlobs.length > 0 ? { copyGlobs } : {},
122
- ...linkPaths.length > 0 ? { linkPaths } : {}
143
+ ...linkPaths.length > 0 ? { linkPaths } : {},
144
+ ...writeFiles.length > 0 ? { writeFiles } : {}
123
145
  };
124
146
  return { input, yes };
125
147
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/args.ts","../../src/bin/approve.ts","../../src/bin/worktree-agent.ts"],"names":[],"mappings":"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","file":"worktree-agent.mjs","sourcesContent":["import { resolve } from \"node:path\"\nimport type { WorktreeAgentInput } from \"../workflow.js\"\n\nexport const USAGE = `usage: worktree-agent run --repo <abs repo root> --slug <id> --task \"<prompt>\" --gate \"<check cmd>\"\n [--base <ref>] [--adapter <slug>] [--deps-cmd \"<cmd>\"] [--copy-glob <glob>]...\n [--link <path>]... [--no-cleanup] [--yes]\n\n --repo Absolute (or cwd-relative) path to the git repository root.\n --slug Worktree/branch identifier, e.g. 'fix-flaky-test'.\n --task The prompt sent to the coding agent.\n --gate Command run inside the worktree to check the agent's work.\n --base Ref to cut the worktree branch from. Default 'origin/main'.\n --adapter Agent adapter slug. Default 'claude-code'.\n --deps-cmd Command to install deps inside the worktree.\n --copy-glob Gitignored glob to copy into the worktree (repeatable).\n --link Gitignored dir/file to symlink from the host repo into the worktree\n before deps (node_modules, sibling workspace repos); repeatable.\n --no-cleanup Keep the worktree's branch after cleanup (still removes the worktree dir).\n --yes Auto-approve the cleanup step instead of prompting.\n`\n\nexport class CliUsageError extends Error {}\n\nexport interface ParsedCli {\n input: WorktreeAgentInput\n yes: boolean\n}\n\n/** Parse `worktree-agent run <flags>` into a `WorktreeAgentInput` + CLI-only options. */\nexport function parseArgs(argv: readonly string[]): ParsedCli {\n const [cmd, ...rest] = argv\n if (cmd !== \"run\") {\n throw new CliUsageError(cmd ? `unknown command '${cmd}'\\n\\n${USAGE}` : USAGE)\n }\n\n let repoRoot: string | undefined\n let slug: string | undefined\n let task: string | undefined\n let gateCmd: string | undefined\n let base: string | undefined\n let adapter: string | undefined\n let depsCmd: string | undefined\n const copyGlobs: string[] = []\n const linkPaths: string[] = []\n let deleteBranch = true\n let yes = false\n\n function nextValue(flag: string, i: number): string {\n const value = rest[i]\n if (value === undefined) throw new CliUsageError(`flag '${flag}' requires a value\\n\\n${USAGE}`)\n return value\n }\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i]\n switch (arg) {\n case \"--repo\":\n repoRoot = nextValue(arg, ++i)\n break\n case \"--slug\":\n slug = nextValue(arg, ++i)\n break\n case \"--task\":\n task = nextValue(arg, ++i)\n break\n case \"--gate\":\n gateCmd = nextValue(arg, ++i)\n break\n case \"--base\":\n base = nextValue(arg, ++i)\n break\n case \"--adapter\":\n adapter = nextValue(arg, ++i)\n break\n case \"--deps-cmd\":\n depsCmd = nextValue(arg, ++i)\n break\n case \"--copy-glob\":\n copyGlobs.push(nextValue(arg, ++i))\n break\n case \"--link\":\n linkPaths.push(nextValue(arg, ++i))\n break\n case \"--no-cleanup\":\n deleteBranch = false\n break\n case \"--yes\":\n yes = true\n break\n default:\n throw new CliUsageError(`unrecognized flag '${arg}'\\n\\n${USAGE}`)\n }\n }\n\n const missing = [\n !repoRoot && \"--repo\",\n !slug && \"--slug\",\n !task && \"--task\",\n !gateCmd && \"--gate\",\n ].filter((f): f is string => typeof f === \"string\")\n if (missing.length > 0) {\n throw new CliUsageError(`missing required flag(s): ${missing.join(\", \")}\\n\\n${USAGE}`)\n }\n\n const input: WorktreeAgentInput = {\n repoRoot: resolve(repoRoot!),\n slug: slug!,\n task: task!,\n gateCmd: gateCmd!,\n deleteBranch,\n ...(base !== undefined ? { base } : {}),\n ...(adapter !== undefined ? { adapter } : {}),\n ...(depsCmd !== undefined ? { depsCmd } : {}),\n ...(copyGlobs.length > 0 ? { copyGlobs } : {}),\n ...(linkPaths.length > 0 ? { linkPaths } : {}),\n }\n return { input, yes }\n}\n","import { closeSync, createReadStream, createWriteStream, openSync } from \"node:fs\"\nimport { createInterface } from \"node:readline\"\nimport type { ApprovalRequest } from \"@agentproto/workflow-runtime\"\n\n/** True when `/dev/tty` can be opened — i.e. a real terminal is attached. */\nexport function hasTty(): boolean {\n try {\n const fd = openSync(\"/dev/tty\", \"r+\")\n closeSync(fd)\n return true\n } catch {\n return false\n }\n}\n\n/** Prompt on `/dev/tty` (not stdin/stdout, which may be piping the workflow's own IO). */\nexport async function askTty(prompt: string): Promise<string> {\n const input = createReadStream(\"/dev/tty\")\n const output = createWriteStream(\"/dev/tty\")\n const rl = createInterface({ input, output })\n try {\n return await new Promise<string>((resolvePromise) => rl.question(prompt, resolvePromise))\n } finally {\n rl.close()\n input.destroy()\n output.destroy()\n }\n}\n\nexport interface ApproveDeps {\n hasTty?: () => boolean\n ask?: (prompt: string) => Promise<string>\n}\n\n/**\n * Build the workflow's `approve` callback: `--yes` auto-approves; otherwise a\n * y/n prompt on `/dev/tty`; with no TTY attached (non-interactive), don't\n * approve — the worktree is left in place rather than silently cleaned up.\n */\nexport function makeApprove(\n opts: { yes: boolean },\n deps: ApproveDeps = {},\n): (req: ApprovalRequest) => Promise<boolean> {\n const hasTtyFn = deps.hasTty ?? hasTty\n const askFn = deps.ask ?? askTty\n return async (req: ApprovalRequest): Promise<boolean> => {\n if (opts.yes) {\n process.stderr.write(`${req.prompt} — auto-approved (--yes)\\n`)\n return true\n }\n if (!hasTtyFn()) {\n process.stderr.write(`${req.prompt} — no TTY attached, not approving (worktree left in place)\\n`)\n return false\n }\n const answer = await askFn(`${req.prompt} [y/N] `)\n return /^y(es)?$/i.test(answer.trim())\n }\n}\n","#!/usr/bin/env node\n/**\n * `worktree-agent run` — runs `worktreeAgentWorkflow` end-to-end: provision a\n * git worktree, run a coding agent in it as a real daemon session (`agent_start`\n * against the agentproto daemon's MCP endpoint), gate the result, ask a human\n * to approve cleanup, then clean up (or leave it in place on gate failure /\n * rejection).\n */\nimport { runWorkflow } from \"@agentproto/workflow-runtime\"\nimport { worktreeAgentWorkflow } from \"../workflow.js\"\nimport { connectDaemonAgentSessionHost } from \"../agent-session-host.js\"\nimport { parseArgs, CliUsageError } from \"./args.js\"\nimport { makeApprove } from \"./approve.js\"\n\nasync function main(): Promise<void> {\n let parsed: ReturnType<typeof parseArgs>\n try {\n parsed = parseArgs(process.argv.slice(2))\n } catch (err) {\n if (!(err instanceof CliUsageError)) throw err\n process.stderr.write(`${err.message}\\n`)\n process.exit(1)\n }\n const { input, yes } = parsed\n\n const host = await connectDaemonAgentSessionHost()\n try {\n const { output } = await runWorkflow({\n workflow: worktreeAgentWorkflow,\n input,\n agents: host,\n approve: makeApprove({ yes }),\n })\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`)\n } finally {\n await host.close()\n }\n}\n\nmain().catch((err: unknown) => {\n process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`)\n process.exit(1)\n})\n"]}
1
+ {"version":3,"sources":["../../src/bin/args.ts","../../src/bin/approve.ts","../../src/bin/worktree-agent.ts"],"names":[],"mappings":"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","file":"worktree-agent.mjs","sourcesContent":["import { resolve } from \"node:path\"\nimport type { WorktreeAgentInput } from \"../workflow.js\"\n\nexport const USAGE = `usage: worktree-agent run --repo <abs repo root> --slug <id> --task \"<prompt>\" --gate \"<check cmd>\"\n [--base <ref>] [--adapter <slug>] [--deps-cmd \"<cmd>\"] [--copy-glob <glob>]...\n [--link <path>]... [--write-file <json>]... [--no-cleanup] [--yes]\n\n --repo Absolute (or cwd-relative) path to the git repository root.\n --slug Worktree/branch identifier, e.g. 'fix-flaky-test'.\n --task The prompt sent to the coding agent.\n --gate Command run inside the worktree to check the agent's work.\n --base Ref to cut the worktree branch from. Default 'origin/main'.\n --adapter Agent adapter slug. Default 'claude-code'.\n --deps-cmd Command to install deps inside the worktree.\n --copy-glob Gitignored glob to copy into the worktree (repeatable).\n --link Gitignored dir/file to symlink from the host repo into the worktree\n before deps (node_modules, sibling workspace repos); repeatable.\n --write-file JSON {\"path\",\"content\",\"mode\"?} written into the worktree before\n deps, e.g. generated package-manager config (repeatable).\n --no-cleanup Keep the worktree's branch after cleanup (still removes the worktree dir).\n --yes Auto-approve the cleanup step instead of prompting.\n`\n\nexport class CliUsageError extends Error {}\n\nexport interface ParsedCli {\n input: WorktreeAgentInput\n yes: boolean\n}\n\n/** Parse `worktree-agent run <flags>` into a `WorktreeAgentInput` + CLI-only options. */\nexport function parseArgs(argv: readonly string[]): ParsedCli {\n const [cmd, ...rest] = argv\n if (cmd !== \"run\") {\n throw new CliUsageError(cmd ? `unknown command '${cmd}'\\n\\n${USAGE}` : USAGE)\n }\n\n let repoRoot: string | undefined\n let slug: string | undefined\n let task: string | undefined\n let gateCmd: string | undefined\n let base: string | undefined\n let adapter: string | undefined\n let depsCmd: string | undefined\n const copyGlobs: string[] = []\n const linkPaths: string[] = []\n const writeFiles: NonNullable<WorktreeAgentInput[\"writeFiles\"]> = []\n let deleteBranch = true\n let yes = false\n\n function nextValue(flag: string, i: number): string {\n const value = rest[i]\n if (value === undefined) throw new CliUsageError(`flag '${flag}' requires a value\\n\\n${USAGE}`)\n return value\n }\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i]\n switch (arg) {\n case \"--repo\":\n repoRoot = nextValue(arg, ++i)\n break\n case \"--slug\":\n slug = nextValue(arg, ++i)\n break\n case \"--task\":\n task = nextValue(arg, ++i)\n break\n case \"--gate\":\n gateCmd = nextValue(arg, ++i)\n break\n case \"--base\":\n base = nextValue(arg, ++i)\n break\n case \"--adapter\":\n adapter = nextValue(arg, ++i)\n break\n case \"--deps-cmd\":\n depsCmd = nextValue(arg, ++i)\n break\n case \"--copy-glob\":\n copyGlobs.push(nextValue(arg, ++i))\n break\n case \"--link\":\n linkPaths.push(nextValue(arg, ++i))\n break\n case \"--write-file\": {\n const raw = nextValue(arg, ++i)\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new CliUsageError(`--write-file value is not valid JSON: ${raw}\\n\\n${USAGE}`)\n }\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as { path?: unknown }).path !== \"string\" ||\n typeof (parsed as { content?: unknown }).content !== \"string\"\n ) {\n throw new CliUsageError(`--write-file requires {\"path\": string, \"content\": string, \"mode\"?: \"create\"|\"append\"}: ${raw}\\n\\n${USAGE}`)\n }\n writeFiles.push(parsed as NonNullable<WorktreeAgentInput[\"writeFiles\"]>[number])\n break\n }\n case \"--no-cleanup\":\n deleteBranch = false\n break\n case \"--yes\":\n yes = true\n break\n default:\n throw new CliUsageError(`unrecognized flag '${arg}'\\n\\n${USAGE}`)\n }\n }\n\n const missing = [\n !repoRoot && \"--repo\",\n !slug && \"--slug\",\n !task && \"--task\",\n !gateCmd && \"--gate\",\n ].filter((f): f is string => typeof f === \"string\")\n if (missing.length > 0) {\n throw new CliUsageError(`missing required flag(s): ${missing.join(\", \")}\\n\\n${USAGE}`)\n }\n\n const input: WorktreeAgentInput = {\n repoRoot: resolve(repoRoot!),\n slug: slug!,\n task: task!,\n gateCmd: gateCmd!,\n deleteBranch,\n ...(base !== undefined ? { base } : {}),\n ...(adapter !== undefined ? { adapter } : {}),\n ...(depsCmd !== undefined ? { depsCmd } : {}),\n ...(copyGlobs.length > 0 ? { copyGlobs } : {}),\n ...(linkPaths.length > 0 ? { linkPaths } : {}),\n ...(writeFiles.length > 0 ? { writeFiles } : {}),\n }\n return { input, yes }\n}\n","import { closeSync, createReadStream, createWriteStream, openSync } from \"node:fs\"\nimport { createInterface } from \"node:readline\"\nimport type { ApprovalRequest } from \"@agentproto/workflow-runtime\"\n\n/** True when `/dev/tty` can be opened — i.e. a real terminal is attached. */\nexport function hasTty(): boolean {\n try {\n const fd = openSync(\"/dev/tty\", \"r+\")\n closeSync(fd)\n return true\n } catch {\n return false\n }\n}\n\n/** Prompt on `/dev/tty` (not stdin/stdout, which may be piping the workflow's own IO). */\nexport async function askTty(prompt: string): Promise<string> {\n const input = createReadStream(\"/dev/tty\")\n const output = createWriteStream(\"/dev/tty\")\n const rl = createInterface({ input, output })\n try {\n return await new Promise<string>((resolvePromise) => rl.question(prompt, resolvePromise))\n } finally {\n rl.close()\n input.destroy()\n output.destroy()\n }\n}\n\nexport interface ApproveDeps {\n hasTty?: () => boolean\n ask?: (prompt: string) => Promise<string>\n}\n\n/**\n * Build the workflow's `approve` callback: `--yes` auto-approves; otherwise a\n * y/n prompt on `/dev/tty`; with no TTY attached (non-interactive), don't\n * approve — the worktree is left in place rather than silently cleaned up.\n */\nexport function makeApprove(\n opts: { yes: boolean },\n deps: ApproveDeps = {},\n): (req: ApprovalRequest) => Promise<boolean> {\n const hasTtyFn = deps.hasTty ?? hasTty\n const askFn = deps.ask ?? askTty\n return async (req: ApprovalRequest): Promise<boolean> => {\n if (opts.yes) {\n process.stderr.write(`${req.prompt} — auto-approved (--yes)\\n`)\n return true\n }\n if (!hasTtyFn()) {\n process.stderr.write(`${req.prompt} — no TTY attached, not approving (worktree left in place)\\n`)\n return false\n }\n const answer = await askFn(`${req.prompt} [y/N] `)\n return /^y(es)?$/i.test(answer.trim())\n }\n}\n","#!/usr/bin/env node\n/**\n * `worktree-agent run` — runs `worktreeAgentWorkflow` end-to-end: provision a\n * git worktree, run a coding agent in it as a real daemon session (`agent_start`\n * against the agentproto daemon's MCP endpoint), gate the result, ask a human\n * to approve cleanup, then clean up (or leave it in place on gate failure /\n * rejection).\n */\nimport { runWorkflow } from \"@agentproto/workflow-runtime\"\nimport { worktreeAgentWorkflow } from \"../workflow.js\"\nimport { connectDaemonAgentSessionHost } from \"../agent-session-host.js\"\nimport { parseArgs, CliUsageError } from \"./args.js\"\nimport { makeApprove } from \"./approve.js\"\n\nasync function main(): Promise<void> {\n let parsed: ReturnType<typeof parseArgs>\n try {\n parsed = parseArgs(process.argv.slice(2))\n } catch (err) {\n if (!(err instanceof CliUsageError)) throw err\n process.stderr.write(`${err.message}\\n`)\n process.exit(1)\n }\n const { input, yes } = parsed\n\n const host = await connectDaemonAgentSessionHost()\n try {\n const { output } = await runWorkflow({\n workflow: worktreeAgentWorkflow,\n input,\n agents: host,\n approve: makeApprove({ yes }),\n })\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`)\n } finally {\n await host.close()\n }\n}\n\nmain().catch((err: unknown) => {\n process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`)\n process.exit(1)\n})\n"]}
@@ -1,5 +1,5 @@
1
- import { worktreeProvider } from './chunk-Y2TW7PBC.mjs';
2
- import { provisionWorktreeTool, runGateTool, cleanupWorktreeTool } from './chunk-CM3XGWTY.mjs';
1
+ import { worktreeProvider } from './chunk-Y337JFBG.mjs';
2
+ import { provisionWorktreeTool, runGateTool, cleanupWorktreeTool } from './chunk-BBDKRTJK.mjs';
3
3
  import { z } from 'zod';
4
4
  import { resolveMcpUrl, HarnessClient } from '@agentproto/harness';
5
5
 
@@ -14,6 +14,13 @@ var worktreeAgentInputSchema = z.object({
14
14
  depsCmd: z.string().optional().describe("Command to install deps inside the worktree, e.g. 'pnpm install --prefer-offline'."),
15
15
  copyGlobs: z.array(z.string()).optional().describe("Gitignored files to copy into the worktree, e.g. secrets."),
16
16
  linkPaths: z.array(z.string()).optional().describe("Gitignored dirs/files symlinked from the host repo into the worktree before depsCmd (node_modules, sibling workspace repos) so the graph resolves without a full reinstall."),
17
+ writeFiles: z.array(
18
+ z.object({
19
+ path: z.string().describe("Path relative to the worktree root."),
20
+ content: z.string().describe("File content, written or appended verbatim."),
21
+ mode: z.enum(["create", "append"]).optional().describe("'create' (default): write only if path doesn't already exist. 'append': always append (creating if missing); if git tracks the path, it's marked skip-worktree afterwards.")
22
+ })
23
+ ).optional().describe("Files written into the worktree before depsCmd runs, e.g. a package-manager config generated for this specific worktree."),
17
24
  task: z.string().describe("The prompt sent to the coding agent."),
18
25
  adapter: z.string().optional().describe("Agent adapter slug. Default 'claude-code'."),
19
26
  gateCmd: z.string().describe("Command run inside the worktree to check the agent's work, e.g. 'pnpm test'."),
@@ -40,7 +47,8 @@ var worktreeAgentWorkflow = {
40
47
  base: i.base,
41
48
  depsCmd: i.depsCmd,
42
49
  copyGlobs: i.copyGlobs,
43
- linkPaths: i.linkPaths
50
+ linkPaths: i.linkPaths,
51
+ writeFiles: i.writeFiles
44
52
  };
45
53
  }
46
54
  },
@@ -188,5 +196,5 @@ async function waitForSettled(client, sessionId, since) {
188
196
  }
189
197
 
190
198
  export { connectDaemonAgentSessionHost, makeDaemonAgentSessionHost, worktreeAgentInputSchema, worktreeAgentWorkflow };
191
- //# sourceMappingURL=chunk-R6UERXV4.mjs.map
192
- //# sourceMappingURL=chunk-R6UERXV4.mjs.map
199
+ //# sourceMappingURL=chunk-5TEU6UGY.mjs.map
200
+ //# sourceMappingURL=chunk-5TEU6UGY.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workflow.ts","../src/agent-session-host.ts"],"names":[],"mappings":"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","file":"chunk-5TEU6UGY.mjs","sourcesContent":["import { z } from \"zod\"\nimport type { Bindings, RuntimeWorkflow } from \"@agentproto/workflow-runtime\"\nimport { provisionWorktreeTool, cleanupWorktreeTool, runGateTool } from \"./tools/index.js\"\nimport { worktreeProvider } from \"./provider/index.js\"\n\n/**\n * Input to the worktree-agent workflow: launch a coding agent inside a\n * fresh git worktree, gate its work, and — on approval — clean up.\n */\nexport const worktreeAgentInputSchema = z.object({\n repoRoot: z.string().describe(\"Absolute path to the git repository root.\"),\n slug: z.string().describe(\"Worktree/branch identifier, e.g. 'fix-flaky-test'.\"),\n base: z.string().optional().describe(\"Ref to cut the worktree branch from. Default 'origin/main'.\"),\n depsCmd: z.string().optional().describe(\"Command to install deps inside the worktree, e.g. 'pnpm install --prefer-offline'.\"),\n copyGlobs: z.array(z.string()).optional().describe(\"Gitignored files to copy into the worktree, e.g. secrets.\"),\n linkPaths: z.array(z.string()).optional().describe(\"Gitignored dirs/files symlinked from the host repo into the worktree before depsCmd (node_modules, sibling workspace repos) so the graph resolves without a full reinstall.\"),\n writeFiles: z\n .array(\n z.object({\n path: z.string().describe(\"Path relative to the worktree root.\"),\n content: z.string().describe(\"File content, written or appended verbatim.\"),\n mode: z\n .enum([\"create\", \"append\"])\n .optional()\n .describe(\"'create' (default): write only if path doesn't already exist. 'append': always append (creating if missing); if git tracks the path, it's marked skip-worktree afterwards.\"),\n }),\n )\n .optional()\n .describe(\"Files written into the worktree before depsCmd runs, e.g. a package-manager config generated for this specific worktree.\"),\n task: z.string().describe(\"The prompt sent to the coding agent.\"),\n adapter: z.string().optional().describe(\"Agent adapter slug. Default 'claude-code'.\"),\n gateCmd: z.string().describe(\"Command run inside the worktree to check the agent's work, e.g. 'pnpm test'.\"),\n deleteBranch: z.boolean().optional().describe(\"Delete the worktree's branch on cleanup. Default true.\"),\n})\n\nexport type WorktreeAgentInput = z.infer<typeof worktreeAgentInputSchema>\n\nconst candidates = [worktreeProvider]\n\nfunction input(b: { input: unknown }): WorktreeAgentInput {\n return b.input as WorktreeAgentInput\n}\n\n/**\n * provision (tool) → code (AgentStep, cwd bound to provision's output) →\n * gate (tool) → on pass: approval → cleanup (tool); on fail: leave the\n * worktree in place for inspection.\n */\nexport const worktreeAgentWorkflow: RuntimeWorkflow = {\n id: \"worktree-agent\",\n description:\n \"Launch a coding agent inside a fresh git worktree, gate its work with a \" +\n \"check command, get a human ack, then clean up. On gate failure the \" +\n \"worktree is left in place for inspection instead of being cleaned up.\",\n steps: [\n {\n kind: \"tool\",\n id: \"provision\",\n tool: provisionWorktreeTool,\n candidates,\n input: (b: Bindings) => {\n const i = input(b)\n return {\n repoRoot: i.repoRoot,\n slug: i.slug,\n base: i.base,\n depsCmd: i.depsCmd,\n copyGlobs: i.copyGlobs,\n linkPaths: i.linkPaths,\n writeFiles: i.writeFiles,\n }\n },\n },\n {\n kind: \"agent\",\n id: \"code\",\n adapter: (b: Bindings) => input(b).adapter ?? \"claude-code\",\n cwd: (b: Bindings) => (b.steps.provision as { cwd: string }).cwd,\n prompt: (b: Bindings) => input(b).task,\n },\n {\n kind: \"tool\",\n id: \"gate\",\n tool: runGateTool,\n candidates,\n input: (b: Bindings) => ({\n cwd: (b.steps.provision as { cwd: string }).cwd,\n cmd: input(b).gateCmd,\n }),\n },\n {\n kind: \"branch\",\n id: \"route\",\n cond: (b: Bindings) => (b.steps.gate as { passed: boolean }).passed,\n then: [\n {\n kind: \"approval\",\n id: \"approval\",\n prompt: () => \"Gate passed. Approve worktree cleanup?\",\n onApprove: [\n {\n kind: \"tool\",\n id: \"cleanup\",\n tool: cleanupWorktreeTool,\n candidates,\n // discardUntracked/discardModified: worktree.cleanup refuses a\n // dirty tree by default (PLAN.md §5.2 layer 3). This workflow's\n // own approval step, just above, is that guard already — a\n // human explicitly approved tearing this worktree down, so\n // both flags are granted here rather than surfacing a second,\n // redundant refusal.\n input: (b: Bindings) => ({\n repoRoot: input(b).repoRoot,\n cwd: (b.steps.provision as { cwd: string }).cwd,\n branch: (b.steps.provision as { branch: string }).branch,\n deleteBranch: input(b).deleteBranch ?? true,\n discardUntracked: true,\n discardModified: true,\n }),\n },\n ],\n onReject: [\n {\n kind: \"transform\",\n id: \"held\",\n compute: () => ({ removed: false, reason: \"cleanup_rejected\" as const }),\n },\n ],\n },\n ],\n otherwise: [\n {\n kind: \"transform\",\n id: \"gate-failed\",\n compute: () => ({ removed: false, reason: \"gate_failed\" as const }),\n },\n ],\n },\n ],\n output: (b: Bindings) => ({\n cwd: (b.steps.provision as { cwd: string }).cwd,\n branch: (b.steps.provision as { branch: string }).branch,\n gate: b.steps.gate,\n cleanup: b.steps.cleanup ?? b.steps.held ?? b.steps[\"gate-failed\"],\n }),\n}\n","import {\n HarnessClient,\n resolveMcpUrl,\n type ConnectHarnessOptions,\n type SessionDescriptor,\n type SessionUsageSnapshot,\n type StartAgentArgs,\n type TurnEvent,\n type TurnResult,\n} from \"@agentproto/harness\"\nimport type { AgentSessionHost } from \"@agentproto/workflow-runtime\"\n\n/** `session_monitor`'s max accepted long-poll window (`orchestration-tools.ts`). */\nconst MAX_POLL_MS = 49_000\n\n/** The subset of `HarnessClient` the host drives — narrowed for fake-client tests. */\nexport type DaemonClient = Pick<\n HarnessClient,\n \"start\" | \"prompt\" | \"output\" | \"kill\" | \"waitForAny\" | \"currentEventsCursor\" | \"close\"\n> & {\n /** `session_usage` — optional so pre-existing fakes/clients without it still\n * satisfy the type; the host simply exposes no `usage` then. */\n usage?: HarnessClient[\"usage\"]\n}\n\nexport interface DaemonAgentSessionHost extends AgentSessionHost {\n close(): Promise<void>\n /** Full `agent_start`, returning the raw descriptor and forwarding every\n * `StartAgentArgs` field (`mcpServers`, `model`, `effort`, `label`, …) —\n * unlike `spawn()` above (the narrow AgentStep-shaped convenience\n * wrapper), which only takes `cwd`/`workspaceSlug`/`stepId`. Consumers\n * that need finer per-turn control than the AgentStep contract provides\n * (e.g. `@agentproto/sandbox`'s sandbox agent-session proxy) use this\n * plus `prompt`/`output`/`kill`/`waitForAny` directly instead of\n * `spawn`/`sendPromptAndWait`. */\n start(args: StartAgentArgs): Promise<SessionDescriptor>\n /** Send a follow-up turn — `opts.interrupt` cancels an in-flight turn and\n * redirects the session onto this prompt (mirrors `agent_prompt`). */\n prompt(sessionId: string, prompt: string, opts?: { interrupt?: boolean }): Promise<void>\n /** Tail the ring buffer (`agent_output`). */\n output(sessionId: string, lastN?: number): Promise<string>\n /** SIGTERM the session (`agent_kill`). */\n kill(sessionId: string): Promise<void>\n /** Multiplexed long-poll (`session_monitor`) — see `HarnessClient.waitForAny`. */\n waitForAny(\n sessionIds: string[],\n opts?: { timeoutMs?: number; event?: TurnEvent; since?: number },\n ): Promise<TurnResult>\n /** Race-free cursor for a subsequent `waitForAny({ since })` — see\n * `HarnessClient.currentEventsCursor`. */\n currentEventsCursor(): Promise<number>\n /** Usage accounting for a session on this daemon (`session_usage`) — present\n * when the underlying client can answer it. `@agentproto/sandbox`'s host\n * inherits it, which is how a sandboxed session's cost/tokens/model reach\n * the HOST daemon's descriptor (the proxy's text stream carries none). */\n usage?(sessionId: string): Promise<SessionUsageSnapshot>\n}\n\n/**\n * Connect to the agentproto daemon's MCP endpoint and return a real,\n * supervisable `AgentSessionHost` — every `AgentStep` becomes an `agent_start`\n * daemon session rather than a bare subprocess. Fails loudly (no silent\n * fallback) if the daemon isn't reachable.\n */\nexport async function connectDaemonAgentSessionHost(\n opts?: ConnectHarnessOptions,\n): Promise<DaemonAgentSessionHost> {\n const url = resolveMcpUrl(opts)\n let client: HarnessClient\n try {\n client = await HarnessClient.connect({ url })\n } catch (err) {\n throw new Error(\n `worktree-agent: could not reach the agentproto daemon's MCP endpoint at ${url}. ` +\n \"Start the daemon (`agentproto daemon start`), or point at a running one via \" +\n `AGENTPROTO_MCP_URL, before running this command.\\n` +\n `(${err instanceof Error ? err.message : String(err)})`,\n )\n }\n return makeDaemonAgentSessionHost(client)\n}\n\n/** Build the host over an already-connected client (exported for tests with a fake client). */\nexport function makeDaemonAgentSessionHost(client: DaemonClient): DaemonAgentSessionHost {\n const sessionByStepId = new Map<string, string>()\n\n return {\n async spawn(adapter, opts): Promise<string> {\n const desc = await client.start({\n adapter,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.workspaceSlug !== undefined ? { workspaceSlug: opts.workspaceSlug } : {}),\n ...(opts.stepId !== undefined ? { label: opts.stepId } : {}),\n })\n if (opts.stepId) sessionByStepId.set(opts.stepId, desc.id)\n return desc.id\n },\n\n async sendPromptAndWait(sessionId, prompt): Promise<void> {\n // Capture a race-free cursor BEFORE sending: an extremely fast turn\n // can settle before a live bus subscription even starts — a real\n // race over the network round-trip to `prompt`/`waitForAny`, not\n // just in-process call ordering (see `HarnessClient\n // .currentEventsCursor`'s doc). The awaited cursor fetch completes\n // strictly before `prompt` is sent, so the daemon's ring-replay\n // branch can always find the matching turn-end regardless of how\n // late the long-poll's own subscription lands.\n const since = await client.currentEventsCursor()\n await client.prompt(sessionId, prompt)\n await waitForSettled(client, sessionId, since)\n },\n\n resolveByLabel(stepId): string | undefined {\n return sessionByStepId.get(stepId)\n },\n\n async start(args): Promise<SessionDescriptor> {\n return client.start(args)\n },\n\n async prompt(sessionId, prompt, opts): Promise<void> {\n await client.prompt(sessionId, prompt, opts)\n },\n\n async output(sessionId, lastN): Promise<string> {\n return client.output(sessionId, lastN)\n },\n\n async kill(sessionId): Promise<void> {\n await client.kill(sessionId)\n },\n\n async waitForAny(sessionIds, opts): Promise<TurnResult> {\n return client.waitForAny(sessionIds, opts)\n },\n\n async currentEventsCursor(): Promise<number> {\n return client.currentEventsCursor()\n },\n\n ...(typeof client.usage === \"function\"\n ? {\n async usage(sessionId: string): Promise<SessionUsageSnapshot> {\n return client.usage!(sessionId)\n },\n }\n : {}),\n\n async close(): Promise<void> {\n await client.close()\n },\n }\n}\n\n/**\n * `session_monitor` long-polls cap at 49s; loop past timeouts for longer\n * turns. A clean timeout comes back as `{ timedOut: true, sessionIds }` —\n * there is no `event: \"timeout\"` on the wire, `event` is only ever set on a\n * real match. Keep polling while `timedOut` is true; stop once it's\n * falsy/absent (a real turn-end/awaiting-input/exited match). `since` is\n * reused unchanged across retries — a timeout means nothing has matched\n * since that cursor yet, so there is nothing to advance.\n */\nasync function waitForSettled(client: DaemonClient, sessionId: string, since: number): Promise<void> {\n for (;;) {\n const result = await client.waitForAny([sessionId], { event: \"any\", timeoutMs: MAX_POLL_MS, since })\n if (!result.timedOut) return\n }\n}\n"]}
@@ -8,7 +8,7 @@ import { defineTool } from '@agentproto/tool';
8
8
 
9
9
  var provisionWorktreeTool = defineTool({
10
10
  id: "worktree.provision",
11
- description: "Create a git worktree for `repoRoot` at a sibling '_worktrees/<slug>' directory (or `dir`, when given), on a new branch 'wt/<slug>' (or `branch`, when given) cut from `base`. If `depsCmd` is given, it runs inside the new worktree afterwards (e.g. install deps). If `copyGlobs` is given, matching files under `repoRoot` (including gitignored ones, e.g. local secrets) are copied into the worktree at the same relative path. If `linkPaths` is given, each is symlinked from `repoRoot` into the worktree before `depsCmd` runs \u2014 for gitignored, expensive-to-recreate trees a fresh worktree lacks (node_modules, sibling workspace repos) so the workspace graph resolves without a full reinstall. Also writes a creation-provenance marker into the worktree's private gitdir.",
11
+ description: "Create a git worktree for `repoRoot` at a sibling '_worktrees/<slug>' directory (or `dir`, when given), on a new branch 'wt/<slug>' (or `branch`, when given) cut from `base`. If `depsCmd` is given, it runs inside the new worktree afterwards (e.g. install deps). If `copyGlobs` is given, matching files under `repoRoot` (including gitignored ones, e.g. local secrets) are copied into the worktree at the same relative path. If `linkPaths` is given, each is symlinked from `repoRoot` into the worktree before `depsCmd` runs \u2014 for gitignored, expensive-to-recreate trees a fresh worktree lacks (node_modules, sibling workspace repos) so the workspace graph resolves without a full reinstall. If `writeFiles` is given, each entry's `content` is written into the worktree at `path` before `depsCmd` runs \u2014 for generated, worktree-specific config a tool invoked by `depsCmd` needs to see (e.g. a package-manager config pointing a cache/store dir outside the worktree, so it isn't shared with \u2014 or clobbered by \u2014 a sibling worktree). `mode: \"create\"` (default) skips an entry whose path already exists, matching `linkPaths`' never-clobber rule; `mode: \"append\"` always appends (creating the file if missing) and, if git already tracks that path, marks it `skip-worktree` afterwards so the tweak never shows up as a local modification the caller could accidentally commit \u2014 callers are responsible for making the content itself idempotent (e.g. checking `repoRoot`'s copy of the file for the line before including the entry, since a fresh worktree's tracked files start as a byte-identical checkout). Also writes a creation-provenance marker into the worktree's private gitdir.",
12
12
  version: "0.2.0",
13
13
  inputSchema: z.object({
14
14
  repoRoot: z.string().describe("Absolute path to the git repository root."),
@@ -19,6 +19,13 @@ var provisionWorktreeTool = defineTool({
19
19
  depsCmd: z.string().optional().describe("Shell command run inside the worktree after creation, e.g. 'pnpm install --prefer-offline'."),
20
20
  copyGlobs: z.array(z.string()).optional().describe("Glob patterns (relative to repoRoot) of gitignored files to copy into the worktree, e.g. 'envs/**/.env.local'."),
21
21
  linkPaths: z.array(z.string()).optional().describe("Relative paths (dirs or files) symlinked from repoRoot into the worktree before depsCmd, e.g. 'node_modules' or a gitignored sibling workspace repo. Lets the workspace graph resolve without a full reinstall."),
22
+ writeFiles: z.array(
23
+ z.object({
24
+ path: z.string().describe("Path relative to the worktree root."),
25
+ content: z.string().describe("File content, written or appended verbatim."),
26
+ mode: z.enum(["create", "append"]).optional().describe("'create' (default): write only if path doesn't already exist. 'append': always append (creating if missing); if git tracks the path, it's marked skip-worktree afterwards so the change never shows as a local modification.")
27
+ })
28
+ ).optional().describe("Files written into the worktree before depsCmd runs, e.g. a package-manager config generated for this specific worktree."),
22
29
  runSetup: z.boolean().optional().describe("Run the `worktree.setup` hooks from the base tree's agentproto.json after creation. Default true; a failing setup hook fails provisioning.")
23
30
  }),
24
31
  outputSchema: z.object({
@@ -151,5 +158,5 @@ var listServicesTool = defineTool({
151
158
  });
152
159
 
153
160
  export { cleanupWorktreeTool, listServicesTool, provisionWorktreeTool, runGateTool, runScriptTool, serviceStatusSchema, startServiceTool, stopServiceTool };
154
- //# sourceMappingURL=chunk-CM3XGWTY.mjs.map
155
- //# sourceMappingURL=chunk-CM3XGWTY.mjs.map
161
+ //# sourceMappingURL=chunk-BBDKRTJK.mjs.map
162
+ //# sourceMappingURL=chunk-BBDKRTJK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/provision-worktree.tool.ts","../src/tools/cleanup-worktree.tool.ts","../src/tools/run-gate.tool.ts","../src/tools/run-script.tool.ts","../src/tools/service.schema.ts","../src/tools/start-service.tool.ts","../src/tools/stop-service.tool.ts","../src/tools/list-services.tool.ts"],"names":["defineTool","z"],"mappings":"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","file":"chunk-BBDKRTJK.mjs","sourcesContent":["import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: create a git worktree off a base ref, on its own branch,\n * optionally installing deps and copying gitignored files (secrets) into it.\n * Agnostic — no hardcoded package manager or env layout; both are inputs.\n */\nexport const provisionWorktreeTool = defineTool({\n id: \"worktree.provision\",\n description:\n \"Create a git worktree for `repoRoot` at a sibling '_worktrees/<slug>' \" +\n \"directory (or `dir`, when given), on a new branch 'wt/<slug>' (or \" +\n \"`branch`, when given) cut from `base`. If `depsCmd` is given, it runs \" +\n \"inside the new worktree afterwards (e.g. install deps). If `copyGlobs` \" +\n \"is given, matching files under `repoRoot` (including gitignored ones, \" +\n \"e.g. local secrets) are copied into the worktree at the same relative \" +\n \"path. If `linkPaths` is given, each is symlinked from `repoRoot` into \" +\n \"the worktree before `depsCmd` runs — for gitignored, expensive-to-\" +\n \"recreate trees a fresh worktree lacks (node_modules, sibling workspace \" +\n \"repos) so the workspace graph resolves without a full reinstall. If \" +\n \"`writeFiles` is given, each entry's `content` is written into the \" +\n \"worktree at `path` before `depsCmd` runs — for generated, worktree-\" +\n \"specific config a tool invoked by `depsCmd` needs to see (e.g. a \" +\n \"package-manager config pointing a cache/store dir outside the \" +\n \"worktree, so it isn't shared with — or clobbered by — a sibling \" +\n \"worktree). `mode: \\\"create\\\"` (default) skips an entry whose path \" +\n \"already exists, matching `linkPaths`' never-clobber rule; \" +\n \"`mode: \\\"append\\\"` always appends (creating the file if missing) and, \" +\n \"if git already tracks that path, marks it `skip-worktree` afterwards \" +\n \"so the tweak never shows up as a local modification the caller could \" +\n \"accidentally commit — callers are responsible for making the content \" +\n \"itself idempotent (e.g. checking `repoRoot`'s copy of the file for the \" +\n \"line before including the entry, since a fresh worktree's tracked \" +\n \"files start as a byte-identical checkout). Also writes a creation-\" +\n \"provenance marker into the worktree's private gitdir.\",\n version: \"0.2.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the git repository root.\"),\n base: z\n .string()\n .optional()\n .describe(\"Ref the new branch is cut from. Default 'origin/main'.\"),\n slug: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-]*$/, \"slug must be lowercase kebab-case\")\n .describe(\"Short identifier — names both the worktree directory and its branch.\"),\n branch: z\n .string()\n .optional()\n .describe(\"Branch name for the new worktree. Default 'wt/<slug>'.\"),\n dir: z\n .string()\n .optional()\n .describe(\"Absolute path for the new worktree. Default '<repoRoot>/../_worktrees/<slug>'.\"),\n depsCmd: z\n .string()\n .optional()\n .describe(\"Shell command run inside the worktree after creation, e.g. 'pnpm install --prefer-offline'.\"),\n copyGlobs: z\n .array(z.string())\n .optional()\n .describe(\"Glob patterns (relative to repoRoot) of gitignored files to copy into the worktree, e.g. 'envs/**/.env.local'.\"),\n linkPaths: z\n .array(z.string())\n .optional()\n .describe(\"Relative paths (dirs or files) symlinked from repoRoot into the worktree before depsCmd, e.g. 'node_modules' or a gitignored sibling workspace repo. Lets the workspace graph resolve without a full reinstall.\"),\n writeFiles: z\n .array(\n z.object({\n path: z.string().describe(\"Path relative to the worktree root.\"),\n content: z.string().describe(\"File content, written or appended verbatim.\"),\n mode: z\n .enum([\"create\", \"append\"])\n .optional()\n .describe(\"'create' (default): write only if path doesn't already exist. 'append': always append (creating if missing); if git tracks the path, it's marked skip-worktree afterwards so the change never shows as a local modification.\"),\n }),\n )\n .optional()\n .describe(\"Files written into the worktree before depsCmd runs, e.g. a package-manager config generated for this specific worktree.\"),\n runSetup: z\n .boolean()\n .optional()\n .describe(\"Run the `worktree.setup` hooks from the base tree's agentproto.json after creation. Default true; a failing setup hook fails provisioning.\"),\n }),\n outputSchema: z.object({\n cwd: z.string().describe(\"Absolute path to the created worktree.\"),\n branch: z.string().describe(\"The branch the worktree was created on.\"),\n }),\n mutates: [\"fs:write\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: remove a git worktree, optionally deleting its branch.\n *\n * Guarded by default (PLAN.md §5.2 layer 3): with neither discard flag set,\n * this runs a plain `git worktree remove` — git itself is the final arbiter\n * and refuses on modified or unignored-untracked files, tolerating gitignored\n * trees like `node_modules/`. `discardUntracked` / `discardModified` each\n * authorize exactly one class of destruction git otherwise refuses; only\n * when the flags cover everything actually dirty does `--force` get passed\n * through. This replaces an unconditional `--force` that used to destroy\n * real edits indiscriminately (the incident this contract change exists to\n * prevent) — hence `riskLevel: 2`, up from the old unconditional-force `1`.\n */\nexport const cleanupWorktreeTool = defineTool({\n id: \"worktree.cleanup\",\n description:\n \"Remove a git worktree created by 'worktree.provision'. Refuses if the \" +\n \"worktree has modified tracked files or unignored untracked files, \" +\n \"unless the matching `discardModified` / `discardUntracked` flag is \" +\n \"set — a clean or gitignore-only tree (e.g. installed deps) always \" +\n \"removes with no flags. If `deleteBranch` is true and `branch` is \" +\n \"given, also force-delete that branch (only ever called for merged \" +\n \"branches by this package's own callers).\",\n version: \"0.2.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the git repository root.\"),\n cwd: z.string().describe(\"Absolute path to the worktree to remove.\"),\n branch: z.string().optional().describe(\"The worktree's branch, for deleteBranch.\"),\n deleteBranch: z.boolean().optional().describe(\"Also force-delete `branch` after removing the worktree.\"),\n base: z.string().optional().describe(\"Ref whose committed agentproto.json supplies teardown hooks. Default 'origin/main'.\"),\n runTeardown: z.boolean().optional().describe(\"Run the `worktree.teardown` hooks before removal. Default true; teardown failures are logged, never blocking.\"),\n discardUntracked: z.boolean().optional().describe(\"Authorize discarding unignored untracked files. Default false: refuse if any are present.\"),\n discardModified: z.boolean().optional().describe(\"Authorize discarding modified tracked files (staged or unstaged). Default false: refuse if any are present.\"),\n }),\n outputSchema: z.object({\n removed: z.literal(true),\n }),\n mutates: [\"fs:write\"],\n approval: \"auto\",\n riskLevel: 2,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: run a caller-provided gate/check command inside a\n * directory (typically a provisioned worktree) and report pass/fail.\n * `cmd` is a trusted, developer-authored config value (same trust model as\n * a CI job's `script:` line), run through a shell so it may include flags.\n */\nexport const runGateTool = defineTool({\n id: \"worktree.run-gate\",\n description:\n \"Run a gate command (e.g. 'pnpm test') inside `cwd` and report pass/fail \" +\n \"from its exit code, along with captured stdout/stderr.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n cwd: z.string().describe(\"Directory to run the command in.\"),\n cmd: z.string().describe(\"Shell command to run, e.g. 'pnpm test'.\"),\n }),\n outputSchema: z.object({\n passed: z.boolean(),\n exitCode: z.number().int(),\n stdout: z.string(),\n stderr: z.string(),\n }),\n mutates: [],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: run a one-shot named `scripts.<name>` command from the\n * repo's committed `agentproto.json` inside a worktree, with the\n * `AGENTPROTO_*` context env injected. For long-running services use\n * `worktree.start-service` instead.\n */\nexport const runScriptTool = defineTool({\n id: \"worktree.run-script\",\n description:\n \"Run a declared `scripts.<name>` command (from the base tree's \" +\n \"agentproto.json) inside `worktreePath`, injecting AGENTPROTO_* env, and \" +\n \"report pass/fail with captured stdout/stderr. For a `type: \\\"service\\\"` \" +\n \"script prefer `worktree.start-service`.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the source git repository root.\"),\n worktreePath: z.string().describe(\"Absolute path to the worktree to run in.\"),\n branch: z.string().describe(\"The worktree's branch name (for AGENTPROTO_BRANCH_NAME).\"),\n script: z.string().describe(\"Name of the script under `scripts` to run.\"),\n base: z.string().optional().describe(\"Ref whose committed agentproto.json is read. Default 'origin/main'.\"),\n }),\n outputSchema: z.object({\n passed: z.boolean(),\n exitCode: z.number().int(),\n stdout: z.string(),\n stderr: z.string(),\n }),\n mutates: [\"fs:write\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\n\n/** Shared shape of a supervised service's status across the service tools. */\nexport const serviceStatusSchema = z.object({\n name: z.string().describe(\"The declared script name.\"),\n hostname: z.string().describe(\"The *.localhost host the reverse proxy routes to this service.\"),\n port: z.number().int().describe(\"The port the service listens on.\"),\n url: z.string().describe(\"The service's reverse-proxy URL.\"),\n pid: z.number().int().nullable().describe(\"Child process id while running, else null.\"),\n status: z.enum([\"running\", \"exited\"]).describe(\"Whether the service process is up.\"),\n exitCode: z.number().int().nullable().describe(\"Exit code once it has exited, else null.\"),\n startedAt: z.string().nullable().describe(\"ISO timestamp of the last start, else null.\"),\n})\n\nexport type ServiceStatusOutput = z.infer<typeof serviceStatusSchema>\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\nimport { serviceStatusSchema } from \"./service.schema.js\"\n\n/**\n * AIP-14 contract: start a declared `type: \"service\"` script for a worktree.\n * Allocates the service's port (declared port if free, else ephemeral),\n * injects AGENTPROTO_PORT/URL + peer env, and registers its hostname with the\n * reverse proxy. Idempotent per worktree+name.\n */\nexport const startServiceTool = defineTool({\n id: \"worktree.start-service\",\n description:\n \"Start a declared `scripts.<name>` service for a worktree as a supervised \" +\n \"long-running child process. Allocates a port, injects AGENTPROTO_PORT / \" +\n \"AGENTPROTO_URL and AGENTPROTO_SERVICE_<PEER>_PORT|URL for siblings, and \" +\n \"registers a `<script>--<branch>--<repo>.localhost` proxy route.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the source git repository root.\"),\n worktreePath: z.string().describe(\"Absolute path to the worktree.\"),\n branch: z.string().describe(\"The worktree's branch name.\"),\n script: z.string().describe(\"Name of the `type: \\\"service\\\"` script to start.\"),\n base: z.string().optional().describe(\"Ref whose committed agentproto.json is read. Default 'origin/main'.\"),\n proxyPort: z.number().int().min(1).max(65535).optional().describe(\"Reverse-proxy port used to build the service URL.\"),\n }),\n outputSchema: serviceStatusSchema,\n mutates: [\"process:spawn\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/** AIP-14 contract: stop a running supervised service for a worktree. */\nexport const stopServiceTool = defineTool({\n id: \"worktree.stop-service\",\n description:\n \"Stop a supervised service (SIGTERM) for a worktree and drop its reverse-\" +\n \"proxy route. A no-op (stopped: false) if the service isn't running.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n worktreePath: z.string().describe(\"Absolute path to the worktree.\"),\n script: z.string().describe(\"Name of the service to stop.\"),\n }),\n outputSchema: z.object({\n stopped: z.boolean().describe(\"Whether a running service was actually stopped.\"),\n }),\n mutates: [\"process:spawn\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\nimport { serviceStatusSchema } from \"./service.schema.js\"\n\n/**\n * AIP-14 contract: list every declared service for a worktree with its\n * resolved port / proxy URL and current run status. Resolves (allocating\n * ports for) the worktree's services on first call so declared-but-unstarted\n * services still appear.\n */\nexport const listServicesTool = defineTool({\n id: \"worktree.list-services\",\n description:\n \"List the declared services for a worktree — each with its allocated \" +\n \"port, `*.localhost` proxy URL, and running/exited status.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the source git repository root.\"),\n worktreePath: z.string().describe(\"Absolute path to the worktree.\"),\n branch: z.string().describe(\"The worktree's branch name.\"),\n base: z.string().optional().describe(\"Ref whose committed agentproto.json is read. Default 'origin/main'.\"),\n proxyPort: z.number().int().min(1).max(65535).optional().describe(\"Reverse-proxy port used to build service URLs.\"),\n }),\n outputSchema: z.object({\n services: z.array(serviceStatusSchema),\n }),\n mutates: [],\n approval: \"auto\",\n riskLevel: 0,\n})\n"]}
@@ -1,7 +1,7 @@
1
- import { provisionWorktreeTool, cleanupWorktreeTool, runGateTool, runScriptTool, startServiceTool, stopServiceTool, listServicesTool } from './chunk-CM3XGWTY.mjs';
1
+ import { provisionWorktreeTool, cleanupWorktreeTool, runGateTool, runScriptTool, startServiceTool, stopServiceTool, listServicesTool } from './chunk-BBDKRTJK.mjs';
2
2
  import { implementTool, defineDriver } from '@agentproto/driver';
3
3
  import { randomUUID } from 'crypto';
4
- import { lstat, mkdir, symlink, copyFile, writeFile, readdir, stat, readFile } from 'fs/promises';
4
+ import { lstat, mkdir, symlink, appendFile, writeFile, copyFile, readdir, stat, readFile } from 'fs/promises';
5
5
  import { resolve, join, dirname, posix, basename, sep } from 'path';
6
6
  import { ToolError } from '@agentproto/tool';
7
7
  import { spawn } from 'child_process';
@@ -409,6 +409,19 @@ var provisionWorktreeBuiltin = implementTool(
409
409
  await mkdir(dirname(dest), { recursive: true });
410
410
  await symlink(target, dest, "dir");
411
411
  }
412
+ for (const file of input.writeFiles ?? []) {
413
+ const dest = join(cwd, file.path);
414
+ await mkdir(dirname(dest), { recursive: true });
415
+ if (file.mode === "append") {
416
+ await appendFile(dest, file.content);
417
+ await execGit(cwd, ["update-index", "--skip-worktree", file.path]).catch(() => {
418
+ });
419
+ } else {
420
+ const existing = await lstat(dest).catch(() => null);
421
+ if (existing) continue;
422
+ await writeFile(dest, file.content);
423
+ }
424
+ }
412
425
  if (input.depsCmd) {
413
426
  const result = await execShell(input.depsCmd, cwd);
414
427
  if (result.exitCode !== 0) {
@@ -1225,5 +1238,5 @@ var worktreeProvider = defineDriver({
1225
1238
  });
1226
1239
 
1227
1240
  export { CONFIG_FILENAME, ConfigError, DEFAULT_PROXY_PORT, ENV_VARS, FileVerdictMemoStore, HookError, InMemoryVerdictMemoStore, ProxyTable, SESSIONS_BUCKETS_ROOT, SESSIONS_FILE_PATH, ServiceSupervisor, VERDICT_MEMO_PATH, WORKTREES_TURBO_CACHE_DIR_ENV, WorktreeNotRemovableError, allocatePort, classify, computeLiveness, computeProvenance, computeTreeState, computeWorktreeStatus, detectDefaultBranch, disposeSupervisor, ephemeralPort, execArgv, execGit, execShell, expandGlob, getScript, getSupervisor, globToRegExp, hookEnv, isPortFree, listGitWorktrees, listScripts, listServices, listWorktreeStatuses, loadConfigFromBase, normalizeHook, parseConfig, peerEnv, peerEnvKey, readSessionsRegistry, readWorktreeMarker, reconcileIntegration, repoLabel, resolveSupervisor, resolveWorktreesTurboCacheDir, runSetup, runTeardown, serviceEnv, serviceEnvToken, serviceHostname, serviceUrl, sessionInWorktree, sharedProxyTable, slugify, stripPort, worktreeProvider, writeWorktreeMarker };
1228
- //# sourceMappingURL=chunk-Y2TW7PBC.mjs.map
1229
- //# sourceMappingURL=chunk-Y2TW7PBC.mjs.map
1241
+ //# sourceMappingURL=chunk-Y337JFBG.mjs.map
1242
+ //# sourceMappingURL=chunk-Y337JFBG.mjs.map