@agimon-ai/doompi-git 0.0.1-alpha.27 → 0.0.1-alpha.29

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.
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_gitDependencies = require("../gitDependencies-B3-4uPtg.cjs");
6
- const require_runWorktree = require("../runWorktree-DWJoUwjg.cjs");
5
+ const require_gitDependencies = require("../gitDependencies-DKJr5kLQ.cjs");
6
+ const require_runWorktree = require("../runWorktree-B6ikYRrG.cjs");
7
7
  let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
8
8
  let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
9
9
  //#region src/extensions/workspaces/sessions/(backend)/_lib/root.cli.ts
@@ -1,5 +1,5 @@
1
- import { t as createGitDependencies } from "../gitDependencies-DU88TZRH.mjs";
2
- import { a as RunWorktreeToolSchema, i as validateParams, n as RUN_WORKTREE_TOOL_NAME, r as executeRunWorktreeTool, t as RUN_WORKTREE_DESCRIPTION } from "../runWorktree-CB6nWQ6k.mjs";
1
+ import { t as createGitDependencies } from "../gitDependencies-D-EUEIkE.mjs";
2
+ import { a as RunWorktreeToolSchema, i as validateParams, n as RUN_WORKTREE_TOOL_NAME, r as executeRunWorktreeTool, t as RUN_WORKTREE_DESCRIPTION } from "../runWorktree-BL99h9oH.mjs";
3
3
  import { definePiExtension, definePiTool, piToolContributions } from "@agimon-ai/doompi-core/piExtension";
4
4
  import { composeRootHooks, defineCliCommand, defineCliTool, defineResource, defineRoot } from "@agimon-ai/doompi-core/extensionFile";
5
5
  //#region src/extensions/workspaces/sessions/(backend)/_lib/root.cli.ts
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_worktreeOperations = require("../worktreeOperations-Br5QpCXh.cjs");
6
- const require_runWorktree = require("../runWorktree-DWJoUwjg.cjs");
5
+ const require_worktreeOperations = require("../worktreeOperations-DjO_Y5Yv.cjs");
6
+ const require_runWorktree = require("../runWorktree-B6ikYRrG.cjs");
7
7
  let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
8
8
  let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
9
9
  let _agimon_ai_doompi_session = require("@agimon-ai/doompi-session");
@@ -1,5 +1,5 @@
1
- import { a as isWorktreeLifecycleEvent, c as HubUnavailableError, i as createWorktreeMessageInbox, n as createWorktreeRegistry, o as registryFile, r as GIT_WORKTREE_LIFECYCLE_EVENT, s as DoomGitExpectedError, t as createWorktreeOperations, u as createWorktreeGit } from "../worktreeOperations--7Qao957.mjs";
2
- import { a as RunWorktreeToolSchema, i as validateParams, n as RUN_WORKTREE_TOOL_NAME, r as executeRunWorktreeTool, t as RUN_WORKTREE_DESCRIPTION } from "../runWorktree-CB6nWQ6k.mjs";
1
+ import { a as isWorktreeLifecycleEvent, c as HubUnavailableError, i as createWorktreeMessageInbox, n as createWorktreeRegistry, o as registryFile, r as GIT_WORKTREE_LIFECYCLE_EVENT, s as DoomGitExpectedError, t as createWorktreeOperations, u as createWorktreeGit } from "../worktreeOperations-DAbs0ZTX.mjs";
2
+ import { a as RunWorktreeToolSchema, i as validateParams, n as RUN_WORKTREE_TOOL_NAME, r as executeRunWorktreeTool, t as RUN_WORKTREE_DESCRIPTION } from "../runWorktree-BL99h9oH.mjs";
3
3
  import { composeRootHooks, defineChannel, defineResource, defineRoot, defineRoute, defineServerTool } from "@agimon-ai/doompi-core/extensionFile";
4
4
  import { defineServerPlugin, readPackageResource } from "@agimon-ai/doompi-core/serverFacet";
5
5
  import { readDoomSessionDelivery } from "@agimon-ai/doompi-session";
@@ -1,4 +1,4 @@
1
- import { t as createWorktreeOperations, u as createWorktreeGit } from "./worktreeOperations--7Qao957.mjs";
1
+ import { t as createWorktreeOperations, u as createWorktreeGit } from "./worktreeOperations-DAbs0ZTX.mjs";
2
2
  //#region src/services/extensionService/index.ts
3
3
  var DefaultGitExtensionService = class {
4
4
  async execute() {
@@ -19,4 +19,4 @@ function createGitDependencies(overrides = {}) {
19
19
  //#endregion
20
20
  export { DefaultGitExtensionService as n, createGitDependencies as t };
21
21
 
22
- //# sourceMappingURL=gitDependencies-DU88TZRH.mjs.map
22
+ //# sourceMappingURL=gitDependencies-D-EUEIkE.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitDependencies-DU88TZRH.mjs","names":[],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAc,yBAAyB,EAAE,KAAK,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
1
+ {"version":3,"file":"gitDependencies-D-EUEIkE.mjs","names":[],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAc,yBAAyB,EAAE,KAAK,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
@@ -1,4 +1,4 @@
1
- const require_worktreeOperations = require("./worktreeOperations-Br5QpCXh.cjs");
1
+ const require_worktreeOperations = require("./worktreeOperations-DjO_Y5Yv.cjs");
2
2
  //#region src/services/extensionService/index.ts
3
3
  var DefaultGitExtensionService = class {
4
4
  async execute() {
@@ -30,4 +30,4 @@ Object.defineProperty(exports, "createGitDependencies", {
30
30
  }
31
31
  });
32
32
 
33
- //# sourceMappingURL=gitDependencies-B3-4uPtg.cjs.map
33
+ //# sourceMappingURL=gitDependencies-DKJr5kLQ.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitDependencies-B3-4uPtg.cjs","names":["createWorktreeOperations","createWorktreeGit"],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAcA,2BAAAA,yBAAyB,EAAE,KAAKC,2BAAAA,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
1
+ {"version":3,"file":"gitDependencies-DKJr5kLQ.cjs","names":["createWorktreeOperations","createWorktreeGit"],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAcA,2BAAAA,yBAAyB,EAAE,KAAKC,2BAAAA,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_gitDependencies = require("./gitDependencies-B3-4uPtg.cjs");
2
+ const require_gitDependencies = require("./gitDependencies-DKJr5kLQ.cjs");
3
3
  exports.DefaultGitExtensionService = require_gitDependencies.DefaultGitExtensionService;
4
4
  exports.createGitDependencies = require_gitDependencies.createGitDependencies;
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as DefaultGitExtensionService, t as createGitDependencies } from "./gitDependencies-DU88TZRH.mjs";
1
+ import { n as DefaultGitExtensionService, t as createGitDependencies } from "./gitDependencies-D-EUEIkE.mjs";
2
2
  export { DefaultGitExtensionService, createGitDependencies };
@@ -1,4 +1,4 @@
1
- const require_worktreeOperations = require("./worktreeOperations-Br5QpCXh.cjs");
1
+ const require_worktreeOperations = require("./worktreeOperations-DjO_Y5Yv.cjs");
2
2
  let typebox = require("typebox");
3
3
  //#region src/schemas/runWorktreeTool.ts
4
4
  /**
@@ -315,4 +315,4 @@ Object.defineProperty(exports, "validateParams", {
315
315
  }
316
316
  });
317
317
 
318
- //# sourceMappingURL=runWorktree-DWJoUwjg.cjs.map
318
+ //# sourceMappingURL=runWorktree-B6ikYRrG.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"runWorktree-DWJoUwjg.cjs","names":["Type","invalidRequest"],"sources":["../src/schemas/runWorktreeTool.ts","../src/services/runWorktree/index.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\n/** The actions that accept `field`, so the declared docs cannot drift from the validator. */\nfunction acceptingActions(field: string): string {\n return Object.values(WORKTREE_ACTIONS)\n .filter((action) => WORKTREE_ACTION_FIELDS[action].includes(field))\n .join(', ');\n}\n\n/**\n * The schema declared to the model.\n *\n * A flat object rather than `RunWorktreeParams` itself. A top-level union is\n * `{anyOf:[...]}` with no `properties`, and Pi's Anthropic Messages adapter\n * rebuilds tool input as `{type:'object', properties: schema.properties ?? {},\n * required: schema.required ?? []}`, so the union arrived at the model as an\n * empty object while the host went on validating calls against it. Nothing here\n * relaxes what is accepted: `validateParams` still rejects an unknown action, a\n * field the action does not take, and a missing required one.\n */\nexport const RunWorktreeToolSchema = Type.Object(\n {\n action: Type.String({\n enum: Object.values(WORKTREE_ACTIONS),\n description: 'The operation to run. Every other field is accepted only by the actions its description names.',\n }),\n branch: Type.Optional(\n Type.String({ minLength: 1, description: `New branch to create. Actions: ${acceptingActions('branch')}.` }),\n ),\n baseRef: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Base ref, defaulting to the current branch. Actions: ${acceptingActions('baseRef')}.`,\n }),\n ),\n task: Type.Optional(\n Type.String({\n minLength: 1,\n description: `First message for the new session. Actions: ${acceptingActions('task')}.`,\n }),\n ),\n name: Type.Optional(\n Type.String({ minLength: 1, description: `Rail label for the worktree. Actions: ${acceptingActions('name')}.` }),\n ),\n id: Type.Optional(Type.String({ minLength: 1, description: `Worktree id. Actions: ${acceptingActions('id')}.` })),\n force: Type.Optional(\n Type.Boolean({ description: `Close even when the tree is dirty. Actions: ${acceptingActions('force')}.` }),\n ),\n message: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Merge commit message, or the text to send. Actions: ${acceptingActions('message')}.`,\n }),\n ),\n dryRun: Type.Optional(\n Type.Boolean({\n description: `Report the plan without destroying anything. Actions: ${acceptingActions('dryRun')}.`,\n }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n","import {\n RunWorktreeParams,\n WORKTREE_ACTION_FIELDS,\n WORKTREE_ACTIONS,\n type WorktreeAction,\n type RunWorktreeToolParams,\n} from '../../schemas/runWorktreeTool';\nimport type { WorktreeRecord } from '../../types/worktreeRegistry';\nimport { invalidRequest } from '../errors';\nimport type { WorktreeOperations } from '../worktreeOperations';\n\nexport { RunWorktreeParams };\nexport type { RunWorktreeToolParams, WorktreeAction };\n\nexport const RUN_WORKTREE_TOOL_NAME = 'run_worktree';\n\nconst IMPLEMENTED_ACTIONS: ReadonlySet<string> = new Set(Object.values(WORKTREE_ACTIONS));\n\nexport const RUN_WORKTREE_DESCRIPTION = `Create and manage git worktrees, each with its own DoomPi session nested under this one.\n\nActions:\n- spawn_worktree: create a worktree on a new branch and start a session in it. Requires 'branch'. Optional 'baseRef' (defaults to the current branch's remote-tracking ref, then the remote default branch), 'name' for the rail, 'task' as the first message.\n- close_worktree: stop a worktree's session, delete its checkout, and remove its generated sync storage. Requires 'id'. Refuses a dirty tree unless 'force' is true.\n- list: every worktree for this repository, with status.\n- status: one worktree and its uncommitted files. Requires 'id'.\n- merge: merge a worktree's branch into this checkout. Requires 'id'. Refuses when this checkout is dirty.\n- prune: remove orphaned worktrees and their generated sync storage. Pass 'dryRun' to see the plan without destroying anything.\n- send: send a message to the other side of a worktree. Requires 'id' and 'message'.\n- messages: read messages waiting for you from a worktree. Requires 'id'.\n\nWorktrees live outside the repository, under ~/.pi/.doom/git/worktrees.`;\n\nexport interface RunWorktreeToolDetails {\n action: WorktreeAction;\n records?: WorktreeRecord[];\n}\n\nexport interface RunWorktreeToolResult {\n content: [{ type: 'text'; text: string }];\n details: RunWorktreeToolDetails;\n}\n\nexport interface RunWorktreeExecutionContext {\n readonly cwd: string;\n readonly sessionId: string;\n}\n\nexport interface RunWorktreeExecutionOptions {\n readonly signal?: AbortSignal;\n readonly onProgress?: (label: string) => void;\n}\n\n/** Rejects calls that do not match one documented action shape. */\nexport function validateParams(input: unknown): RunWorktreeToolParams {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw invalidRequest('run_worktree parameters must be an object.', 'Call it with one documented action shape.');\n }\n const record = input as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unknown action ${typeof action === 'string' ? `'${action}'` : 'value'}.`,\n `Use one of: ${[...IMPLEMENTED_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = WORKTREE_ACTION_FIELDS[action as WorktreeAction];\n const unexpected = Object.keys(record).filter((key) => !allowed.includes(key));\n if (unexpected.length > 0) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unexpected.join(', ')}.`,\n `Fields for '${action}': ${allowed.join(', ')}.`,\n );\n }\n for (const field of ['branch', 'id'] as const) {\n if (allowed.includes(field) && field in record) {\n const value = record[field];\n if (typeof value !== 'string' || value.trim() === '') {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n }\n const stringFields = ['baseRef', 'name', 'task', 'message'] as const;\n for (const field of stringFields) {\n if (field in record && (typeof record[field] !== 'string' || record[field].trim() === '')) {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n for (const field of ['force', 'dryRun'] as const) {\n if (field in record && typeof record[field] !== 'boolean') {\n throw invalidRequest(`action='${action}' requires boolean '${field}'.`, `Pass true or false for ${field}.`);\n }\n }\n if (action === WORKTREE_ACTIONS.send && typeof record.message !== 'string') {\n throw invalidRequest(\"action='send' requires 'message'.\", 'Pass the message to send.');\n }\n if (action === WORKTREE_ACTIONS.spawn_worktree && typeof record.branch !== 'string') {\n throw invalidRequest(\"action='spawn_worktree' requires 'branch'.\", 'Name the branch to create.');\n }\n if (\n (action === WORKTREE_ACTIONS.close_worktree ||\n action === WORKTREE_ACTIONS.status ||\n action === WORKTREE_ACTIONS.merge ||\n action === WORKTREE_ACTIONS.send ||\n action === WORKTREE_ACTIONS.messages) &&\n typeof record.id !== 'string'\n ) {\n throw invalidRequest(`action='${action}' requires 'id'.`, 'Call list to see the current ids.');\n }\n return record as RunWorktreeToolParams;\n}\n\nfunction describe(record: WorktreeRecord): string {\n return `${record.id} ${record.branch} ${record.status} ${record.path}`;\n}\n\nfunction text(...lines: readonly string[]): [{ type: 'text'; text: string }] {\n return [{ type: 'text', text: lines.join('\\n') }];\n}\n\nexport async function executeRunWorktreeTool(\n params: RunWorktreeToolParams,\n operations: WorktreeOperations,\n context: RunWorktreeExecutionContext,\n options: RunWorktreeExecutionOptions = {},\n): Promise<RunWorktreeToolResult> {\n switch (params.action) {\n case WORKTREE_ACTIONS.spawn_worktree: {\n const record = await operations.spawn(\n context,\n {\n branch: params.branch,\n ...(params.baseRef === undefined ? {} : { baseRef: params.baseRef }),\n ...(params.name === undefined ? {} : { name: params.name }),\n ...(params.task === undefined ? {} : { task: params.task }),\n },\n options,\n );\n return {\n content: text(\n `Worktree ${record.id} created on ${record.branch} from ${record.baseRef}.`,\n `Path: ${record.path}`,\n params.task === undefined\n ? `Session ${record.sessionId} is starting; it appears nested under this one in the rail.`\n : `Session ${record.sessionId} is starting with its task; it appears nested under this one in the rail.`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.close_worktree: {\n const record = await operations.close(context, params.id, params.force ?? false);\n return {\n content: text(`Worktree ${record.id} (${record.branch}) closed and removed.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.list: {\n const records = await operations.list(context);\n return {\n content:\n records.length === 0\n ? text('No worktrees for this repository.')\n : text(`${String(records.length)} worktree(s):`, ...records.map(describe)),\n details: { action: params.action, records },\n };\n }\n case WORKTREE_ACTIONS.status: {\n const { record, dirtyFiles } = await operations.status(context, params.id);\n return {\n content: text(\n describe(record),\n `Session: ${record.sessionId}`,\n dirtyFiles.length === 0\n ? 'Clean.'\n : `${String(dirtyFiles.length)} uncommitted file(s): ${dirtyFiles.slice(0, 20).join(', ')}`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.merge: {\n const record = await operations.merge(\n context,\n params.id,\n ...(params.message === undefined ? [] : ([params.message] as const)),\n );\n return {\n content: text(`Merged ${record.branch} into this checkout.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.send: {\n await operations.send(context, params.id, params.message);\n return { content: text(`Message sent to worktree ${params.id}.`), details: { action: params.action } };\n }\n case WORKTREE_ACTIONS.messages: {\n const waiting = await operations.messages(context, params.id);\n return {\n content:\n waiting.length === 0\n ? text('No messages.')\n : text(\n `${String(waiting.length)} message(s):`,\n ...waiting.map((entry) => `[${entry.sentAt}] ${entry.from}: ${entry.text}`),\n ),\n details: { action: params.action },\n };\n }\n case WORKTREE_ACTIONS.prune: {\n const dryRun = params.dryRun ?? false;\n const plan = await operations.prune(context, dryRun);\n const lines = [\n dryRun ? 'Prune plan (nothing was changed):' : 'Pruned:',\n `Remove: ${plan.remove.length === 0 ? 'none' : plan.remove.map((record) => record.id).join(', ')}`,\n `Forget: ${plan.forget.length === 0 ? 'none' : plan.forget.map((record) => record.id).join(', ')}`,\n `Kept, uncommitted work: ${plan.keptDirty.length === 0 ? 'none' : plan.keptDirty.map((record) => record.id).join(', ')}`,\n `Untracked directories, left alone: ${plan.untracked.length === 0 ? 'none' : plan.untracked.join(', ')}`,\n ...(plan.keptBranches.length === 0\n ? []\n : [`Branches kept, they hold commits: ${plan.keptBranches.join(', ')}`]),\n ];\n return { content: text(...lines), details: { action: params.action } };\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runWorktree-B6ikYRrG.cjs","names":["Type","invalidRequest"],"sources":["../src/schemas/runWorktreeTool.ts","../src/services/runWorktree/index.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\n/** The actions that accept `field`, so the declared docs cannot drift from the validator. */\nfunction acceptingActions(field: string): string {\n return Object.values(WORKTREE_ACTIONS)\n .filter((action) => WORKTREE_ACTION_FIELDS[action].includes(field))\n .join(', ');\n}\n\n/**\n * The schema declared to the model.\n *\n * A flat object rather than `RunWorktreeParams` itself. A top-level union is\n * `{anyOf:[...]}` with no `properties`, and Pi's Anthropic Messages adapter\n * rebuilds tool input as `{type:'object', properties: schema.properties ?? {},\n * required: schema.required ?? []}`, so the union arrived at the model as an\n * empty object while the host went on validating calls against it. Nothing here\n * relaxes what is accepted: `validateParams` still rejects an unknown action, a\n * field the action does not take, and a missing required one.\n */\nexport const RunWorktreeToolSchema = Type.Object(\n {\n action: Type.String({\n enum: Object.values(WORKTREE_ACTIONS),\n description: 'The operation to run. Every other field is accepted only by the actions its description names.',\n }),\n branch: Type.Optional(\n Type.String({ minLength: 1, description: `New branch to create. Actions: ${acceptingActions('branch')}.` }),\n ),\n baseRef: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Base ref, defaulting to the current branch. Actions: ${acceptingActions('baseRef')}.`,\n }),\n ),\n task: Type.Optional(\n Type.String({\n minLength: 1,\n description: `First message for the new session. Actions: ${acceptingActions('task')}.`,\n }),\n ),\n name: Type.Optional(\n Type.String({ minLength: 1, description: `Rail label for the worktree. Actions: ${acceptingActions('name')}.` }),\n ),\n id: Type.Optional(Type.String({ minLength: 1, description: `Worktree id. Actions: ${acceptingActions('id')}.` })),\n force: Type.Optional(\n Type.Boolean({ description: `Close even when the tree is dirty. Actions: ${acceptingActions('force')}.` }),\n ),\n message: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Merge commit message, or the text to send. Actions: ${acceptingActions('message')}.`,\n }),\n ),\n dryRun: Type.Optional(\n Type.Boolean({\n description: `Report the plan without destroying anything. Actions: ${acceptingActions('dryRun')}.`,\n }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n","import {\n RunWorktreeParams,\n WORKTREE_ACTION_FIELDS,\n WORKTREE_ACTIONS,\n type WorktreeAction,\n type RunWorktreeToolParams,\n} from '../../schemas/runWorktreeTool';\nimport type { WorktreeRecord } from '../../types/worktreeRegistry';\nimport { invalidRequest } from '../errors';\nimport type { WorktreeOperations } from '../worktreeOperations';\n\nexport { RunWorktreeParams };\nexport type { RunWorktreeToolParams, WorktreeAction };\n\nexport const RUN_WORKTREE_TOOL_NAME = 'run_worktree';\n\nconst IMPLEMENTED_ACTIONS: ReadonlySet<string> = new Set(Object.values(WORKTREE_ACTIONS));\n\nexport const RUN_WORKTREE_DESCRIPTION = `Create and manage git worktrees, each with its own DoomPi session nested under this one.\n\nActions:\n- spawn_worktree: create a worktree on a new branch and start a session in it. Requires 'branch'. Optional 'baseRef' (defaults to the current branch's remote-tracking ref, then the remote default branch), 'name' for the rail, 'task' as the first message.\n- close_worktree: stop a worktree's session, delete its checkout, and remove its generated sync storage. Requires 'id'. Refuses a dirty tree unless 'force' is true.\n- list: every worktree for this repository, with status.\n- status: one worktree and its uncommitted files. Requires 'id'.\n- merge: merge a worktree's branch into this checkout. Requires 'id'. Refuses when this checkout is dirty.\n- prune: remove orphaned worktrees and their generated sync storage. Pass 'dryRun' to see the plan without destroying anything.\n- send: send a message to the other side of a worktree. Requires 'id' and 'message'.\n- messages: read messages waiting for you from a worktree. Requires 'id'.\n\nWorktrees live outside the repository, under ~/.pi/.doom/git/worktrees.`;\n\nexport interface RunWorktreeToolDetails {\n action: WorktreeAction;\n records?: WorktreeRecord[];\n}\n\nexport interface RunWorktreeToolResult {\n content: [{ type: 'text'; text: string }];\n details: RunWorktreeToolDetails;\n}\n\nexport interface RunWorktreeExecutionContext {\n readonly cwd: string;\n readonly sessionId: string;\n}\n\nexport interface RunWorktreeExecutionOptions {\n readonly signal?: AbortSignal;\n readonly onProgress?: (label: string) => void;\n}\n\n/** Rejects calls that do not match one documented action shape. */\nexport function validateParams(input: unknown): RunWorktreeToolParams {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw invalidRequest('run_worktree parameters must be an object.', 'Call it with one documented action shape.');\n }\n const record = input as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unknown action ${typeof action === 'string' ? `'${action}'` : 'value'}.`,\n `Use one of: ${[...IMPLEMENTED_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = WORKTREE_ACTION_FIELDS[action as WorktreeAction];\n const unexpected = Object.keys(record).filter((key) => !allowed.includes(key));\n if (unexpected.length > 0) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unexpected.join(', ')}.`,\n `Fields for '${action}': ${allowed.join(', ')}.`,\n );\n }\n for (const field of ['branch', 'id'] as const) {\n if (allowed.includes(field) && field in record) {\n const value = record[field];\n if (typeof value !== 'string' || value.trim() === '') {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n }\n const stringFields = ['baseRef', 'name', 'task', 'message'] as const;\n for (const field of stringFields) {\n if (field in record && (typeof record[field] !== 'string' || record[field].trim() === '')) {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n for (const field of ['force', 'dryRun'] as const) {\n if (field in record && typeof record[field] !== 'boolean') {\n throw invalidRequest(`action='${action}' requires boolean '${field}'.`, `Pass true or false for ${field}.`);\n }\n }\n if (action === WORKTREE_ACTIONS.send && typeof record.message !== 'string') {\n throw invalidRequest(\"action='send' requires 'message'.\", 'Pass the message to send.');\n }\n if (action === WORKTREE_ACTIONS.spawn_worktree && typeof record.branch !== 'string') {\n throw invalidRequest(\"action='spawn_worktree' requires 'branch'.\", 'Name the branch to create.');\n }\n if (\n (action === WORKTREE_ACTIONS.close_worktree ||\n action === WORKTREE_ACTIONS.status ||\n action === WORKTREE_ACTIONS.merge ||\n action === WORKTREE_ACTIONS.send ||\n action === WORKTREE_ACTIONS.messages) &&\n typeof record.id !== 'string'\n ) {\n throw invalidRequest(`action='${action}' requires 'id'.`, 'Call list to see the current ids.');\n }\n return record as RunWorktreeToolParams;\n}\n\nfunction describe(record: WorktreeRecord): string {\n return `${record.id} ${record.branch} ${record.status} ${record.path}`;\n}\n\nfunction text(...lines: readonly string[]): [{ type: 'text'; text: string }] {\n return [{ type: 'text', text: lines.join('\\n') }];\n}\n\nexport async function executeRunWorktreeTool(\n params: RunWorktreeToolParams,\n operations: WorktreeOperations,\n context: RunWorktreeExecutionContext,\n options: RunWorktreeExecutionOptions = {},\n): Promise<RunWorktreeToolResult> {\n switch (params.action) {\n case WORKTREE_ACTIONS.spawn_worktree: {\n const record = await operations.spawn(\n context,\n {\n branch: params.branch,\n ...(params.baseRef === undefined ? {} : { baseRef: params.baseRef }),\n ...(params.name === undefined ? {} : { name: params.name }),\n ...(params.task === undefined ? {} : { task: params.task }),\n },\n options,\n );\n return {\n content: text(\n `Worktree ${record.id} created on ${record.branch} from ${record.baseRef}.`,\n `Path: ${record.path}`,\n params.task === undefined\n ? `Session ${record.sessionId} is starting; it appears nested under this one in the rail.`\n : `Session ${record.sessionId} is starting with its task; it appears nested under this one in the rail.`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.close_worktree: {\n const record = await operations.close(context, params.id, params.force ?? false);\n return {\n content: text(`Worktree ${record.id} (${record.branch}) closed and removed.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.list: {\n const records = await operations.list(context);\n return {\n content:\n records.length === 0\n ? text('No worktrees for this repository.')\n : text(`${String(records.length)} worktree(s):`, ...records.map(describe)),\n details: { action: params.action, records },\n };\n }\n case WORKTREE_ACTIONS.status: {\n const { record, dirtyFiles } = await operations.status(context, params.id);\n return {\n content: text(\n describe(record),\n `Session: ${record.sessionId}`,\n dirtyFiles.length === 0\n ? 'Clean.'\n : `${String(dirtyFiles.length)} uncommitted file(s): ${dirtyFiles.slice(0, 20).join(', ')}`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.merge: {\n const record = await operations.merge(\n context,\n params.id,\n ...(params.message === undefined ? [] : ([params.message] as const)),\n );\n return {\n content: text(`Merged ${record.branch} into this checkout.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.send: {\n await operations.send(context, params.id, params.message);\n return { content: text(`Message sent to worktree ${params.id}.`), details: { action: params.action } };\n }\n case WORKTREE_ACTIONS.messages: {\n const waiting = await operations.messages(context, params.id);\n return {\n content:\n waiting.length === 0\n ? text('No messages.')\n : text(\n `${String(waiting.length)} message(s):`,\n ...waiting.map((entry) => `[${entry.sentAt}] ${entry.from}: ${entry.text}`),\n ),\n details: { action: params.action },\n };\n }\n case WORKTREE_ACTIONS.prune: {\n const dryRun = params.dryRun ?? false;\n const plan = await operations.prune(context, dryRun);\n const lines = [\n dryRun ? 'Prune plan (nothing was changed):' : 'Pruned:',\n `Remove: ${plan.remove.length === 0 ? 'none' : plan.remove.map((record) => record.id).join(', ')}`,\n `Forget: ${plan.forget.length === 0 ? 'none' : plan.forget.map((record) => record.id).join(', ')}`,\n `Kept, uncommitted work: ${plan.keptDirty.length === 0 ? 'none' : plan.keptDirty.map((record) => record.id).join(', ')}`,\n `Untracked directories, left alone: ${plan.untracked.length === 0 ? 'none' : plan.untracked.join(', ')}`,\n ...(plan.keptBranches.length === 0\n ? []\n : [`Branches kept, they hold commits: ${plan.keptBranches.join(', ')}`]),\n ];\n return { content: text(...lines), details: { action: params.action } };\n }\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { l as invalidRequest } from "./worktreeOperations--7Qao957.mjs";
1
+ import { l as invalidRequest } from "./worktreeOperations-DAbs0ZTX.mjs";
2
2
  import { Type } from "typebox";
3
3
  //#region src/schemas/runWorktreeTool.ts
4
4
  /**
@@ -286,4 +286,4 @@ async function executeRunWorktreeTool(params, operations, context, options = {})
286
286
  //#endregion
287
287
  export { RunWorktreeToolSchema as a, validateParams as i, RUN_WORKTREE_TOOL_NAME as n, executeRunWorktreeTool as r, RUN_WORKTREE_DESCRIPTION as t };
288
288
 
289
- //# sourceMappingURL=runWorktree-CB6nWQ6k.mjs.map
289
+ //# sourceMappingURL=runWorktree-BL99h9oH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"runWorktree-CB6nWQ6k.mjs","names":[],"sources":["../src/schemas/runWorktreeTool.ts","../src/services/runWorktree/index.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\n/** The actions that accept `field`, so the declared docs cannot drift from the validator. */\nfunction acceptingActions(field: string): string {\n return Object.values(WORKTREE_ACTIONS)\n .filter((action) => WORKTREE_ACTION_FIELDS[action].includes(field))\n .join(', ');\n}\n\n/**\n * The schema declared to the model.\n *\n * A flat object rather than `RunWorktreeParams` itself. A top-level union is\n * `{anyOf:[...]}` with no `properties`, and Pi's Anthropic Messages adapter\n * rebuilds tool input as `{type:'object', properties: schema.properties ?? {},\n * required: schema.required ?? []}`, so the union arrived at the model as an\n * empty object while the host went on validating calls against it. Nothing here\n * relaxes what is accepted: `validateParams` still rejects an unknown action, a\n * field the action does not take, and a missing required one.\n */\nexport const RunWorktreeToolSchema = Type.Object(\n {\n action: Type.String({\n enum: Object.values(WORKTREE_ACTIONS),\n description: 'The operation to run. Every other field is accepted only by the actions its description names.',\n }),\n branch: Type.Optional(\n Type.String({ minLength: 1, description: `New branch to create. Actions: ${acceptingActions('branch')}.` }),\n ),\n baseRef: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Base ref, defaulting to the current branch. Actions: ${acceptingActions('baseRef')}.`,\n }),\n ),\n task: Type.Optional(\n Type.String({\n minLength: 1,\n description: `First message for the new session. Actions: ${acceptingActions('task')}.`,\n }),\n ),\n name: Type.Optional(\n Type.String({ minLength: 1, description: `Rail label for the worktree. Actions: ${acceptingActions('name')}.` }),\n ),\n id: Type.Optional(Type.String({ minLength: 1, description: `Worktree id. Actions: ${acceptingActions('id')}.` })),\n force: Type.Optional(\n Type.Boolean({ description: `Close even when the tree is dirty. Actions: ${acceptingActions('force')}.` }),\n ),\n message: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Merge commit message, or the text to send. Actions: ${acceptingActions('message')}.`,\n }),\n ),\n dryRun: Type.Optional(\n Type.Boolean({\n description: `Report the plan without destroying anything. Actions: ${acceptingActions('dryRun')}.`,\n }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n","import {\n RunWorktreeParams,\n WORKTREE_ACTION_FIELDS,\n WORKTREE_ACTIONS,\n type WorktreeAction,\n type RunWorktreeToolParams,\n} from '../../schemas/runWorktreeTool';\nimport type { WorktreeRecord } from '../../types/worktreeRegistry';\nimport { invalidRequest } from '../errors';\nimport type { WorktreeOperations } from '../worktreeOperations';\n\nexport { RunWorktreeParams };\nexport type { RunWorktreeToolParams, WorktreeAction };\n\nexport const RUN_WORKTREE_TOOL_NAME = 'run_worktree';\n\nconst IMPLEMENTED_ACTIONS: ReadonlySet<string> = new Set(Object.values(WORKTREE_ACTIONS));\n\nexport const RUN_WORKTREE_DESCRIPTION = `Create and manage git worktrees, each with its own DoomPi session nested under this one.\n\nActions:\n- spawn_worktree: create a worktree on a new branch and start a session in it. Requires 'branch'. Optional 'baseRef' (defaults to the current branch's remote-tracking ref, then the remote default branch), 'name' for the rail, 'task' as the first message.\n- close_worktree: stop a worktree's session, delete its checkout, and remove its generated sync storage. Requires 'id'. Refuses a dirty tree unless 'force' is true.\n- list: every worktree for this repository, with status.\n- status: one worktree and its uncommitted files. Requires 'id'.\n- merge: merge a worktree's branch into this checkout. Requires 'id'. Refuses when this checkout is dirty.\n- prune: remove orphaned worktrees and their generated sync storage. Pass 'dryRun' to see the plan without destroying anything.\n- send: send a message to the other side of a worktree. Requires 'id' and 'message'.\n- messages: read messages waiting for you from a worktree. Requires 'id'.\n\nWorktrees live outside the repository, under ~/.pi/.doom/git/worktrees.`;\n\nexport interface RunWorktreeToolDetails {\n action: WorktreeAction;\n records?: WorktreeRecord[];\n}\n\nexport interface RunWorktreeToolResult {\n content: [{ type: 'text'; text: string }];\n details: RunWorktreeToolDetails;\n}\n\nexport interface RunWorktreeExecutionContext {\n readonly cwd: string;\n readonly sessionId: string;\n}\n\nexport interface RunWorktreeExecutionOptions {\n readonly signal?: AbortSignal;\n readonly onProgress?: (label: string) => void;\n}\n\n/** Rejects calls that do not match one documented action shape. */\nexport function validateParams(input: unknown): RunWorktreeToolParams {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw invalidRequest('run_worktree parameters must be an object.', 'Call it with one documented action shape.');\n }\n const record = input as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unknown action ${typeof action === 'string' ? `'${action}'` : 'value'}.`,\n `Use one of: ${[...IMPLEMENTED_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = WORKTREE_ACTION_FIELDS[action as WorktreeAction];\n const unexpected = Object.keys(record).filter((key) => !allowed.includes(key));\n if (unexpected.length > 0) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unexpected.join(', ')}.`,\n `Fields for '${action}': ${allowed.join(', ')}.`,\n );\n }\n for (const field of ['branch', 'id'] as const) {\n if (allowed.includes(field) && field in record) {\n const value = record[field];\n if (typeof value !== 'string' || value.trim() === '') {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n }\n const stringFields = ['baseRef', 'name', 'task', 'message'] as const;\n for (const field of stringFields) {\n if (field in record && (typeof record[field] !== 'string' || record[field].trim() === '')) {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n for (const field of ['force', 'dryRun'] as const) {\n if (field in record && typeof record[field] !== 'boolean') {\n throw invalidRequest(`action='${action}' requires boolean '${field}'.`, `Pass true or false for ${field}.`);\n }\n }\n if (action === WORKTREE_ACTIONS.send && typeof record.message !== 'string') {\n throw invalidRequest(\"action='send' requires 'message'.\", 'Pass the message to send.');\n }\n if (action === WORKTREE_ACTIONS.spawn_worktree && typeof record.branch !== 'string') {\n throw invalidRequest(\"action='spawn_worktree' requires 'branch'.\", 'Name the branch to create.');\n }\n if (\n (action === WORKTREE_ACTIONS.close_worktree ||\n action === WORKTREE_ACTIONS.status ||\n action === WORKTREE_ACTIONS.merge ||\n action === WORKTREE_ACTIONS.send ||\n action === WORKTREE_ACTIONS.messages) &&\n typeof record.id !== 'string'\n ) {\n throw invalidRequest(`action='${action}' requires 'id'.`, 'Call list to see the current ids.');\n }\n return record as RunWorktreeToolParams;\n}\n\nfunction describe(record: WorktreeRecord): string {\n return `${record.id} ${record.branch} ${record.status} ${record.path}`;\n}\n\nfunction text(...lines: readonly string[]): [{ type: 'text'; text: string }] {\n return [{ type: 'text', text: lines.join('\\n') }];\n}\n\nexport async function executeRunWorktreeTool(\n params: RunWorktreeToolParams,\n operations: WorktreeOperations,\n context: RunWorktreeExecutionContext,\n options: RunWorktreeExecutionOptions = {},\n): Promise<RunWorktreeToolResult> {\n switch (params.action) {\n case WORKTREE_ACTIONS.spawn_worktree: {\n const record = await operations.spawn(\n context,\n {\n branch: params.branch,\n ...(params.baseRef === undefined ? {} : { baseRef: params.baseRef }),\n ...(params.name === undefined ? {} : { name: params.name }),\n ...(params.task === undefined ? {} : { task: params.task }),\n },\n options,\n );\n return {\n content: text(\n `Worktree ${record.id} created on ${record.branch} from ${record.baseRef}.`,\n `Path: ${record.path}`,\n params.task === undefined\n ? `Session ${record.sessionId} is starting; it appears nested under this one in the rail.`\n : `Session ${record.sessionId} is starting with its task; it appears nested under this one in the rail.`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.close_worktree: {\n const record = await operations.close(context, params.id, params.force ?? false);\n return {\n content: text(`Worktree ${record.id} (${record.branch}) closed and removed.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.list: {\n const records = await operations.list(context);\n return {\n content:\n records.length === 0\n ? text('No worktrees for this repository.')\n : text(`${String(records.length)} worktree(s):`, ...records.map(describe)),\n details: { action: params.action, records },\n };\n }\n case WORKTREE_ACTIONS.status: {\n const { record, dirtyFiles } = await operations.status(context, params.id);\n return {\n content: text(\n describe(record),\n `Session: ${record.sessionId}`,\n dirtyFiles.length === 0\n ? 'Clean.'\n : `${String(dirtyFiles.length)} uncommitted file(s): ${dirtyFiles.slice(0, 20).join(', ')}`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.merge: {\n const record = await operations.merge(\n context,\n params.id,\n ...(params.message === undefined ? [] : ([params.message] as const)),\n );\n return {\n content: text(`Merged ${record.branch} into this checkout.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.send: {\n await operations.send(context, params.id, params.message);\n return { content: text(`Message sent to worktree ${params.id}.`), details: { action: params.action } };\n }\n case WORKTREE_ACTIONS.messages: {\n const waiting = await operations.messages(context, params.id);\n return {\n content:\n waiting.length === 0\n ? text('No messages.')\n : text(\n `${String(waiting.length)} message(s):`,\n ...waiting.map((entry) => `[${entry.sentAt}] ${entry.from}: ${entry.text}`),\n ),\n details: { action: params.action },\n };\n }\n case WORKTREE_ACTIONS.prune: {\n const dryRun = params.dryRun ?? false;\n const plan = await operations.prune(context, dryRun);\n const lines = [\n dryRun ? 'Prune plan (nothing was changed):' : 'Pruned:',\n `Remove: ${plan.remove.length === 0 ? 'none' : plan.remove.map((record) => record.id).join(', ')}`,\n `Forget: ${plan.forget.length === 0 ? 'none' : plan.forget.map((record) => record.id).join(', ')}`,\n `Kept, uncommitted work: ${plan.keptDirty.length === 0 ? 'none' : plan.keptDirty.map((record) => record.id).join(', ')}`,\n `Untracked directories, left alone: ${plan.untracked.length === 0 ? 'none' : plan.untracked.join(', ')}`,\n ...(plan.keptBranches.length === 0\n ? []\n : [`Branches kept, they hold commits: ${plan.keptBranches.join(', ')}`]),\n ];\n return { content: text(...lines), details: { action: params.action } };\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runWorktree-BL99h9oH.mjs","names":[],"sources":["../src/schemas/runWorktreeTool.ts","../src/services/runWorktree/index.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\n/** The actions that accept `field`, so the declared docs cannot drift from the validator. */\nfunction acceptingActions(field: string): string {\n return Object.values(WORKTREE_ACTIONS)\n .filter((action) => WORKTREE_ACTION_FIELDS[action].includes(field))\n .join(', ');\n}\n\n/**\n * The schema declared to the model.\n *\n * A flat object rather than `RunWorktreeParams` itself. A top-level union is\n * `{anyOf:[...]}` with no `properties`, and Pi's Anthropic Messages adapter\n * rebuilds tool input as `{type:'object', properties: schema.properties ?? {},\n * required: schema.required ?? []}`, so the union arrived at the model as an\n * empty object while the host went on validating calls against it. Nothing here\n * relaxes what is accepted: `validateParams` still rejects an unknown action, a\n * field the action does not take, and a missing required one.\n */\nexport const RunWorktreeToolSchema = Type.Object(\n {\n action: Type.String({\n enum: Object.values(WORKTREE_ACTIONS),\n description: 'The operation to run. Every other field is accepted only by the actions its description names.',\n }),\n branch: Type.Optional(\n Type.String({ minLength: 1, description: `New branch to create. Actions: ${acceptingActions('branch')}.` }),\n ),\n baseRef: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Base ref, defaulting to the current branch. Actions: ${acceptingActions('baseRef')}.`,\n }),\n ),\n task: Type.Optional(\n Type.String({\n minLength: 1,\n description: `First message for the new session. Actions: ${acceptingActions('task')}.`,\n }),\n ),\n name: Type.Optional(\n Type.String({ minLength: 1, description: `Rail label for the worktree. Actions: ${acceptingActions('name')}.` }),\n ),\n id: Type.Optional(Type.String({ minLength: 1, description: `Worktree id. Actions: ${acceptingActions('id')}.` })),\n force: Type.Optional(\n Type.Boolean({ description: `Close even when the tree is dirty. Actions: ${acceptingActions('force')}.` }),\n ),\n message: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Merge commit message, or the text to send. Actions: ${acceptingActions('message')}.`,\n }),\n ),\n dryRun: Type.Optional(\n Type.Boolean({\n description: `Report the plan without destroying anything. Actions: ${acceptingActions('dryRun')}.`,\n }),\n ),\n },\n { additionalProperties: false },\n);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n","import {\n RunWorktreeParams,\n WORKTREE_ACTION_FIELDS,\n WORKTREE_ACTIONS,\n type WorktreeAction,\n type RunWorktreeToolParams,\n} from '../../schemas/runWorktreeTool';\nimport type { WorktreeRecord } from '../../types/worktreeRegistry';\nimport { invalidRequest } from '../errors';\nimport type { WorktreeOperations } from '../worktreeOperations';\n\nexport { RunWorktreeParams };\nexport type { RunWorktreeToolParams, WorktreeAction };\n\nexport const RUN_WORKTREE_TOOL_NAME = 'run_worktree';\n\nconst IMPLEMENTED_ACTIONS: ReadonlySet<string> = new Set(Object.values(WORKTREE_ACTIONS));\n\nexport const RUN_WORKTREE_DESCRIPTION = `Create and manage git worktrees, each with its own DoomPi session nested under this one.\n\nActions:\n- spawn_worktree: create a worktree on a new branch and start a session in it. Requires 'branch'. Optional 'baseRef' (defaults to the current branch's remote-tracking ref, then the remote default branch), 'name' for the rail, 'task' as the first message.\n- close_worktree: stop a worktree's session, delete its checkout, and remove its generated sync storage. Requires 'id'. Refuses a dirty tree unless 'force' is true.\n- list: every worktree for this repository, with status.\n- status: one worktree and its uncommitted files. Requires 'id'.\n- merge: merge a worktree's branch into this checkout. Requires 'id'. Refuses when this checkout is dirty.\n- prune: remove orphaned worktrees and their generated sync storage. Pass 'dryRun' to see the plan without destroying anything.\n- send: send a message to the other side of a worktree. Requires 'id' and 'message'.\n- messages: read messages waiting for you from a worktree. Requires 'id'.\n\nWorktrees live outside the repository, under ~/.pi/.doom/git/worktrees.`;\n\nexport interface RunWorktreeToolDetails {\n action: WorktreeAction;\n records?: WorktreeRecord[];\n}\n\nexport interface RunWorktreeToolResult {\n content: [{ type: 'text'; text: string }];\n details: RunWorktreeToolDetails;\n}\n\nexport interface RunWorktreeExecutionContext {\n readonly cwd: string;\n readonly sessionId: string;\n}\n\nexport interface RunWorktreeExecutionOptions {\n readonly signal?: AbortSignal;\n readonly onProgress?: (label: string) => void;\n}\n\n/** Rejects calls that do not match one documented action shape. */\nexport function validateParams(input: unknown): RunWorktreeToolParams {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw invalidRequest('run_worktree parameters must be an object.', 'Call it with one documented action shape.');\n }\n const record = input as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unknown action ${typeof action === 'string' ? `'${action}'` : 'value'}.`,\n `Use one of: ${[...IMPLEMENTED_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = WORKTREE_ACTION_FIELDS[action as WorktreeAction];\n const unexpected = Object.keys(record).filter((key) => !allowed.includes(key));\n if (unexpected.length > 0) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unexpected.join(', ')}.`,\n `Fields for '${action}': ${allowed.join(', ')}.`,\n );\n }\n for (const field of ['branch', 'id'] as const) {\n if (allowed.includes(field) && field in record) {\n const value = record[field];\n if (typeof value !== 'string' || value.trim() === '') {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n }\n const stringFields = ['baseRef', 'name', 'task', 'message'] as const;\n for (const field of stringFields) {\n if (field in record && (typeof record[field] !== 'string' || record[field].trim() === '')) {\n throw invalidRequest(`action='${action}' requires a nonblank '${field}'.`, `Pass a ${field}.`);\n }\n }\n for (const field of ['force', 'dryRun'] as const) {\n if (field in record && typeof record[field] !== 'boolean') {\n throw invalidRequest(`action='${action}' requires boolean '${field}'.`, `Pass true or false for ${field}.`);\n }\n }\n if (action === WORKTREE_ACTIONS.send && typeof record.message !== 'string') {\n throw invalidRequest(\"action='send' requires 'message'.\", 'Pass the message to send.');\n }\n if (action === WORKTREE_ACTIONS.spawn_worktree && typeof record.branch !== 'string') {\n throw invalidRequest(\"action='spawn_worktree' requires 'branch'.\", 'Name the branch to create.');\n }\n if (\n (action === WORKTREE_ACTIONS.close_worktree ||\n action === WORKTREE_ACTIONS.status ||\n action === WORKTREE_ACTIONS.merge ||\n action === WORKTREE_ACTIONS.send ||\n action === WORKTREE_ACTIONS.messages) &&\n typeof record.id !== 'string'\n ) {\n throw invalidRequest(`action='${action}' requires 'id'.`, 'Call list to see the current ids.');\n }\n return record as RunWorktreeToolParams;\n}\n\nfunction describe(record: WorktreeRecord): string {\n return `${record.id} ${record.branch} ${record.status} ${record.path}`;\n}\n\nfunction text(...lines: readonly string[]): [{ type: 'text'; text: string }] {\n return [{ type: 'text', text: lines.join('\\n') }];\n}\n\nexport async function executeRunWorktreeTool(\n params: RunWorktreeToolParams,\n operations: WorktreeOperations,\n context: RunWorktreeExecutionContext,\n options: RunWorktreeExecutionOptions = {},\n): Promise<RunWorktreeToolResult> {\n switch (params.action) {\n case WORKTREE_ACTIONS.spawn_worktree: {\n const record = await operations.spawn(\n context,\n {\n branch: params.branch,\n ...(params.baseRef === undefined ? {} : { baseRef: params.baseRef }),\n ...(params.name === undefined ? {} : { name: params.name }),\n ...(params.task === undefined ? {} : { task: params.task }),\n },\n options,\n );\n return {\n content: text(\n `Worktree ${record.id} created on ${record.branch} from ${record.baseRef}.`,\n `Path: ${record.path}`,\n params.task === undefined\n ? `Session ${record.sessionId} is starting; it appears nested under this one in the rail.`\n : `Session ${record.sessionId} is starting with its task; it appears nested under this one in the rail.`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.close_worktree: {\n const record = await operations.close(context, params.id, params.force ?? false);\n return {\n content: text(`Worktree ${record.id} (${record.branch}) closed and removed.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.list: {\n const records = await operations.list(context);\n return {\n content:\n records.length === 0\n ? text('No worktrees for this repository.')\n : text(`${String(records.length)} worktree(s):`, ...records.map(describe)),\n details: { action: params.action, records },\n };\n }\n case WORKTREE_ACTIONS.status: {\n const { record, dirtyFiles } = await operations.status(context, params.id);\n return {\n content: text(\n describe(record),\n `Session: ${record.sessionId}`,\n dirtyFiles.length === 0\n ? 'Clean.'\n : `${String(dirtyFiles.length)} uncommitted file(s): ${dirtyFiles.slice(0, 20).join(', ')}`,\n ),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.merge: {\n const record = await operations.merge(\n context,\n params.id,\n ...(params.message === undefined ? [] : ([params.message] as const)),\n );\n return {\n content: text(`Merged ${record.branch} into this checkout.`),\n details: { action: params.action, records: [record] },\n };\n }\n case WORKTREE_ACTIONS.send: {\n await operations.send(context, params.id, params.message);\n return { content: text(`Message sent to worktree ${params.id}.`), details: { action: params.action } };\n }\n case WORKTREE_ACTIONS.messages: {\n const waiting = await operations.messages(context, params.id);\n return {\n content:\n waiting.length === 0\n ? text('No messages.')\n : text(\n `${String(waiting.length)} message(s):`,\n ...waiting.map((entry) => `[${entry.sentAt}] ${entry.from}: ${entry.text}`),\n ),\n details: { action: params.action },\n };\n }\n case WORKTREE_ACTIONS.prune: {\n const dryRun = params.dryRun ?? false;\n const plan = await operations.prune(context, dryRun);\n const lines = [\n dryRun ? 'Prune plan (nothing was changed):' : 'Pruned:',\n `Remove: ${plan.remove.length === 0 ? 'none' : plan.remove.map((record) => record.id).join(', ')}`,\n `Forget: ${plan.forget.length === 0 ? 'none' : plan.forget.map((record) => record.id).join(', ')}`,\n `Kept, uncommitted work: ${plan.keptDirty.length === 0 ? 'none' : plan.keptDirty.map((record) => record.id).join(', ')}`,\n `Untracked directories, left alone: ${plan.untracked.length === 0 ? 'none' : plan.untracked.join(', ')}`,\n ...(plan.keptBranches.length === 0\n ? []\n : [`Branches kept, they hold commits: ${plan.keptBranches.join(', ')}`]),\n ];\n return { content: text(...lines), details: { action: params.action } };\n }\n }\n}\n"],"mappings":"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"}
@@ -5,7 +5,6 @@ import { removeSyncLocation, resolveWorktreeSyncLocation } from "@agimon-ai/doom
5
5
  import path from "node:path";
6
6
  import os from "node:os";
7
7
  import { isDeepStrictEqual } from "node:util";
8
- import "@agimon-ai/doompi-core/web";
9
8
  import { setTimeout } from "node:timers/promises";
10
9
  //#region src/services/gitCli/index.ts
11
10
  /**
@@ -354,14 +353,20 @@ const MAX_LABEL_LENGTH = 32;
354
353
  * at the shared directory. Following that chain is what makes every worktree of
355
354
  * one repository agree on the repository's identity, which matters here because
356
355
  * the registry is per repository and must be found from inside a worktree too.
356
+ * A session may run in a subdirectory, so the nearest enclosing checkout is used.
357
357
  */
358
- function gitCommonDirectory(root) {
359
- const marker = path.join(root, ".git");
358
+ function gitCommonDirectory(directory) {
359
+ let root = path.resolve(directory);
360
+ let marker = path.join(root, ".git");
360
361
  let stat;
361
- try {
362
+ for (;;) try {
362
363
  stat = fs.statSync(marker);
364
+ break;
363
365
  } catch {
364
- return;
366
+ const parent = path.dirname(root);
367
+ if (parent === root) return void 0;
368
+ root = parent;
369
+ marker = path.join(root, ".git");
365
370
  }
366
371
  if (stat.isDirectory()) return marker;
367
372
  let pointer;
@@ -1046,4 +1051,4 @@ function createWorktreeOperations(deps) {
1046
1051
  //#endregion
1047
1052
  export { isWorktreeLifecycleEvent as a, HubUnavailableError as c, createWorktreeMessageInbox as i, invalidRequest as l, createWorktreeRegistry as n, registryFile as o, GIT_WORKTREE_LIFECYCLE_EVENT as r, DoomGitExpectedError as s, createWorktreeOperations as t, createWorktreeGit as u };
1048
1053
 
1049
- //# sourceMappingURL=worktreeOperations--7Qao957.mjs.map
1054
+ //# sourceMappingURL=worktreeOperations-DAbs0ZTX.mjs.map