@agimon-ai/doompi-team 0.0.1-alpha.11 → 0.0.1-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/subagentTool.cjs +5 -5
- package/dist/extensions/subagentTool.cjs.map +1 -1
- package/dist/extensions/subagentTool.mjs +5 -5
- package/dist/extensions/subagentTool.mjs.map +1 -1
- package/dist/tui/agentCatalog.cjs +1 -1
- package/dist/tui/agentCatalog.cjs.map +1 -1
- package/dist/tui/agentCatalog.mjs +1 -1
- package/dist/tui/agentCatalog.mjs.map +1 -1
- package/dist/tui/fleet.cjs +1 -1
- package/dist/tui/fleet.cjs.map +1 -1
- package/dist/tui/fleet.mjs +1 -1
- package/dist/tui/fleet.mjs.map +1 -1
- package/dist/tui/fleetStatus.cjs +1 -1
- package/dist/tui/fleetStatus.cjs.map +1 -1
- package/dist/tui/fleetStatus.mjs +1 -1
- package/dist/tui/fleetStatus.mjs.map +1 -1
- package/dist/tui/fleetTranscript.cjs +1 -1
- package/dist/tui/fleetTranscript.cjs.map +1 -1
- package/dist/tui/fleetTranscript.mjs +1 -1
- package/dist/tui/fleetTranscript.mjs.map +1 -1
- package/dist/tui/subagentToolRender.cjs +3 -0
- package/dist/tui/subagentToolRender.cjs.map +1 -0
- package/dist/tui/subagentToolRender.mjs +3 -0
- package/dist/tui/subagentToolRender.mjs.map +1 -0
- package/package.json +7 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../services/agents/memory.cjs`),t=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs`),n=require(`../container/types.cjs`),r=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.cjs`),i=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.cjs`),a=require(`../shared/paths.cjs`),o=require(`../shared/errors.cjs`),s=require(`../shared/modelResolution.cjs`),c=require(`../services/runs/shared/modelFallback.cjs`),l=require(`../services/runs/shared/runtimeRegistry.cjs`),u=require(`./spawnPlan.cjs`),d=require(`../adapters/asyncJobTracker.cjs`);require(`../services/runs/background/asyncJobTracker.cjs`);const f=require(`../adapters/suspendedRuns.cjs`);require(`../services/runs/registry/suspendedRuns.cjs`);const p=require(`./config.cjs`),
|
|
2
|
-
`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}`,!0,`Call subagent({"action":"agents"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.`);let l=
|
|
5
|
-
`),{spawn:i,started:a.length,failed:s.length});return
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../services/agents/memory.cjs`),t=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs`),n=require(`../container/types.cjs`),r=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.cjs`),i=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.cjs`),a=require(`../shared/paths.cjs`),o=require(`../shared/errors.cjs`),s=require(`../shared/modelResolution.cjs`),c=require(`../services/runs/shared/modelFallback.cjs`),l=require(`../services/runs/shared/runtimeRegistry.cjs`),u=require(`./spawnPlan.cjs`),d=require(`../adapters/asyncJobTracker.cjs`);require(`../services/runs/background/asyncJobTracker.cjs`);const f=require(`../adapters/suspendedRuns.cjs`);require(`../services/runs/registry/suspendedRuns.cjs`);const p=require(`../tui/subagentToolRender.cjs`),m=require(`./config.cjs`),h=require(`./operationJournal.cjs`);require(`./schemas.cjs`);const g=require(`./statusViews.cjs`),_=require(`./toolDescription.cjs`);let v=require(`inversify`),y=require(`node:crypto`),b=require(`@agimon-ai/doompi-extension-contracts/subagent-tool`);const x=`subagent`,S=new Set(Object.values(b.SUBAGENT_ACTIONS));function C(e,t){return{content:[{type:`text`,text:e}],details:t}}function w(e,t){return C(e,{action:t,partial:!0})}function T(e){switch(e.action){case b.SUBAGENT_ACTIONS.run:return`Starting ${e.requests.length} subagent${e.requests.length===1?``:`s`}...`;case b.SUBAGENT_ACTIONS.steer:return`Steering subagent ${e.id}...`;case b.SUBAGENT_ACTIONS.stop:return`Requesting stop for subagent ${e.id}...`;case b.SUBAGENT_ACTIONS.restore:return`Restoring subagent ${e.id}...`;default:return}}function E(e,t){try{return e.getAllTools().some(e=>e.name===t)}catch{return!1}}function D(e){return e??`both`}function O(e){return[`Executable agents:`,...e.length?e.toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>`- ${e.name} (${e.source}): ${e.description}`):[`- (none)`]].join(`
|
|
2
|
+
`)}function k(t){let n=[...t.tools??[],...(t.mcpDirectTools??[]).map(e=>`mcp:${e}`)];return{name:t.name,source:t.source,description:t.description,runtime:t.runtime??`pi`,writeCapable:e.agentHasWriteTools(t),...t.model?{model:t.model}:{},...t.fallbackModels?.length?{fallbackModels:t.fallbackModels}:{},...n.length?{tools:n}:{}}}function A(e){return{...e,resumable:f.isSuspendedRunResumable(e)}}function j(e){let t=k(e);return[`Agent: ${e.name} (${e.source})`,`Description: ${e.description}`,`Runtime: ${String(t.runtime)}`,`Write capable: ${t.writeCapable?`yes`:`no`}`,...e.model?[`Model: ${e.model}`]:[],...Array.isArray(t.tools)?[`Tools: ${t.tools.join(`, `)}`]:[]].join(`
|
|
3
|
+
`)}function M(e,t,n){if(typeof e[t]!=`string`||!e[t].trim())throw o.invalidRequest(`action='${n}' requires nonblank '${t}'.`,`Correct the request and retry.`)}function N(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;if(typeof t.action!=`string`||!S.has(t.action)||t.action===b.SUBAGENT_ACTIONS.run||typeof t.model!=`string`)return e;let{model:n,...r}=t;return r}function P(e){let t=N(e);if(!t||typeof t!=`object`||Array.isArray(t))throw o.invalidRequest(`subagent parameters must be an object.`,`Call subagent with one documented action shape.`);let n=t,r=n.action;if(typeof r!=`string`||!S.has(r))throw o.invalidRequest(`Unsupported or missing subagent action ${JSON.stringify(r)}.`,`Use one of: ${[...S].join(`, `)}.`);let i=b.SUBAGENT_ACTION_FIELDS[r],a=Object.keys(n).filter(e=>!i.includes(e));if(a.length)throw o.invalidRequest(`action='${r}' does not accept: ${a.join(`, `)}.`,`Remove unknown fields and retry.`);if(r===b.SUBAGENT_ACTIONS.run&&(!Array.isArray(n.requests)||n.requests.length===0))throw o.invalidRequest(`action='run' requires a nonempty 'requests' array.`,`Add at least one agent and task.`);return r===b.SUBAGENT_ACTIONS.steer&&(M(n,`id`,r),M(n,`message`,r)),(r===b.SUBAGENT_ACTIONS.stop||r===b.SUBAGENT_ACTIONS.restore)&&M(n,`id`,r),t}let F=class{registeredHosts=new WeakSet;constructor(e,t,n,r){this.planner=e,this.management=t,this.tracker=n,this.discovery=r}registerTool(e){if(!this.registeredHosts.has(e)){if(E(e,`subagent`))throw new o.DoomTeamExpectedError(`tool_conflict`,`A foreign '${x}' tool is already registered.`,!1,`Disable the competing extension, then reload Doom Team.`);e.registerTool(this.buildTool()),this.registeredHosts.add(e)}}trackOutcomes(e,t){let n=this.tracker.forSession(t.sessionManager.getSessionId());for(let t of e.outcomes)t.runId&&n.track(t.runId);return e}buildSpawnRequest(e,t,n,r){let i=t.requests.map(e=>{if(!e.agent.trim()||!e.task.trim())throw o.invalidRequest(`Every run request requires nonblank agent and task values.`,`Correct the request and retry.`);return{agent:e.agent.trim(),...e.inlineAgent?{inlineAgent:e.inlineAgent}:{},task:e.task.trim(),...e.cwd?{cwd:e.cwd}:{},...e.model?{model:e.model}:{},...e.runtime?{runtime:e.runtime}:{}}}),a=u.captureSessionForkSource(n.sessionManager,`tool`),l=c.normalizeParentModel(n.model);return{tasks:i,cwd:n.cwd,agentScope:D(t.scope),parentSessionId:n.sessionManager.getSessionId(),...a?{parentSessionFile:a.sessionFile,parentLeafId:a.leafId}:{},...t.concurrency===void 0?{}:{concurrency:t.concurrency},...t.artifacts===void 0?{}:{artifacts:t.artifacts},availableModels:s.authenticatedModelInfos(n.modelRegistry),...l?{parentModel:l}:{},operationId:e,preallocatedRunIds:r}}async executeRun(e,t,n){let r=h.startOperation(e,t,t.requests.map(()=>(0,y.randomUUID)()));if(r.kind===`replay`){if(r.record.state===`completed`&&r.record.result)return r.record.result;throw new o.DoomTeamExpectedError(`delivery_unconfirmed`,`Operation '${e}' is already pending for runs: ${r.record.runIds.join(`, `)}.`,!0,`Call subagent({"action":"status"}) and do not submit the run again.`)}let i=this.trackOutcomes(await this.planner.spawn(this.buildSpawnRequest(e,t,n,r.record.runIds),m.loadConfig().config),n),a=i.outcomes.filter(e=>e.runId),s=i.outcomes.filter(e=>!e.runId),c=i.outcomes.map(e=>`- ${e.agent}: ${e.runId?`started as ${e.runId}`:`failed: ${e.error??`unknown error`}`}${e.warning?`\n Warning: ${e.warning}`:``}`);if(a.length===0&&s.length>0)throw new o.DoomTeamExpectedError(`runtime_unavailable`,`No requested subagent started.\n${c.join(`
|
|
4
|
+
`)}`,!0,`Call subagent({"action":"agents"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.`);let l=C([`Run request: started ${a.length}/${i.outcomes.length} background agents; failed ${s.length}.`,...c,...a.length>0?[``,`The subagent${a.length===1?` is`:`s are`} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`]:[],...s.length>0?[``,`Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.`]:[]].join(`
|
|
5
|
+
`),{spawn:i,started:a.length,failed:s.length});return h.completeOperation(e,r.record,l),l}executeAgents(e,t){let n=e.cwd??t.cwd,r=D(e.scope);if(!e.name){let e=this.discovery.discover(n,r);return C(O(e.agents),{agents:e.agents.map(k)})}let i=this.discovery.find(n,r,e.name);if(!i){let t=this.discovery.discover(n,r).agents.map(e=>e.name).toSorted();throw new o.DoomTeamExpectedError(`agent_not_found`,`No executable agent matches '${e.name}'.${t.length?` Available: ${t.join(`, `)}.`:``}`,!1,`Call subagent({"action":"agents"}) and retry with an exact name.`)}return C(j(i),{agent:k(i)})}async executeManagement(e,t,n,r,i){let c=this.tracker.forSession(t.sessionManager.getSessionId());switch(e.action){case b.SUBAGENT_ACTIONS.status:{let t=f.listSuspendedRuns(a.requireCurrentSessionScope());if(!(`id`in e)){if(`transcriptLines`in e&&e.transcriptLines!==void 0)throw o.invalidRequest(`transcriptLines requires a run id.`,`Add id or omit transcriptLines for fleet status.`);let n=c.list();return C(g.formatFleetView(n,Date.now(),t),{fleet:n,suspended:t.map(A)})}let n=e.id;if(!n)throw o.invalidRequest(`transcriptLines requires a run id.`,`Add id or omit transcriptLines for fleet status.`);let r=t.find(e=>e.runId===n);if(r&&e.transcriptLines===void 0){let e=f.isSuspendedRunResumable(r)?`Restore it with { action: "restore", id: "${r.runId}" }.`:`It is not resumable; submit a new explicit run.`;return C(`Run '${r.runId}' is suspended. ${e}`,{suspended:A(r)})}let i=this.management.status(n);if(!i.runDir&&!i.resultPath&&!r)throw new o.DoomTeamExpectedError(`run_not_found`,`No run matches '${n}'.`,!1,`Call subagent({"action":"status"}) and retry with an exact id.`);return e.transcriptLines===void 0?C(i.status?`Run '${i.runId}': ${i.status.state}`:`Run '${i.runId}' has no status yet.`,{status:i}):C(g.formatRunTranscript(i.status,e.transcriptLines??80),{transcript:{runId:i.runId}})}case b.SUBAGENT_ACTIONS.stop:{let t=d.resolveTrackedRunId(c,e.id),n=this.management.stop(t,e.reason);return C(`Stop requested for '${t}'.`,{control:n})}case b.SUBAGENT_ACTIONS.steer:{let t=d.resolveTrackedRunId(c,e.id),r=this.tracker.get(t)?.runtime;if(r&&!l.isPiRuntime(r))throw new o.DoomTeamExpectedError(`unsupported_operation`,`Run '${t}' uses '${r}', which does not support steering.`,!1,`Use subagent({"action":"stop","id":"${t}"}) to terminate it.`);let i=await this.management.steer(t,e.message,void 0,n);return C(`Steer request '${i.requestId}' for '${t}' is ${i.state}: ${i.message}`,{steer:i})}case b.SUBAGENT_ACTIONS.suspended:{let e=f.listSuspendedRuns(a.requireCurrentSessionScope());return C(e.length?f.formatSuspendedRuns(e):`No suspended subagents in this session.`,{suspended:e.map(A)})}case b.SUBAGENT_ACTIONS.restore:{let n=a.requireCurrentSessionScope(),c=f.listSuspendedRuns(n).find(t=>t.runId===e.id);if(!c)throw new o.DoomTeamExpectedError(`run_not_found`,`No suspended run matches '${e.id}'.`,!1,`Call subagent({"action":"suspended"}) and retry with an exact id.`);if(!f.isSuspendedRunResumable(c))throw new o.DoomTeamExpectedError(`not_resumable`,`Suspended run '${e.id}' does not have complete, readable Pi recovery state.`,!1,`Submit a new explicit run request instead of restoring this record.`);let l=this.trackOutcomes(await this.planner.spawn({single:{agent:c.agent,...c.inlineAgent?{inlineAgent:c.inlineAgent}:{},task:c.task,cwd:c.cwd,...c.model?{model:c.model}:{},sessionFile:c.sessionFile},cwd:c.cwd,agentScope:`both`,runtime:`pi`,availableModels:s.authenticatedModelInfos(t.modelRegistry),...i?{operationId:i}:{},...r?{preallocatedRunIds:r}:{}},m.loadConfig().config),t).outcomes[0];if(!l?.runId)throw new o.DoomTeamExpectedError(`not_resumable`,`Could not restore '${e.id}': ${l?.error??`the spawn produced no run.`}`,!0,`Inspect suspended state, then submit a new explicit run if recovery is not possible.`);return f.clearSuspendedRun(n,e.id),C(`Restored '${e.id}' as '${l.runId}', continuing its transcript.`,{restore:{...l,restoredFrom:e.id}})}}}buildTool(){return{name:x,label:`Subagent`,description:_.SUBAGENT_TOOL_DESCRIPTION,parameters:b.SubagentParams,prepareArguments:P,renderShell:`self`,renderCall:(e,t)=>p.renderSubagentCall(P(e),t),renderResult:(e,t,n)=>p.renderSubagentResult(e,t,n),execute:async(e,t,n,r,i)=>{let a=P(t),s=T(a);if(s&&r?.(w(s,a.action)),a.action===b.SUBAGENT_ACTIONS.run)return this.executeRun(e,a,i);if(a.action===b.SUBAGENT_ACTIONS.agents)return this.executeAgents(a,i);if(!(a.action===b.SUBAGENT_ACTIONS.steer||a.action===b.SUBAGENT_ACTIONS.stop||a.action===b.SUBAGENT_ACTIONS.restore))return this.executeManagement(a,i,n);let c=h.startOperation(e,a,a.action===b.SUBAGENT_ACTIONS.restore?[(0,y.randomUUID)()]:[]);if(c.kind===`replay`){if(c.record.state===`completed`&&c.record.result)return c.record.result;throw new o.DoomTeamExpectedError(`delivery_unconfirmed`,`Operation '${e}' is already pending.`,!0,`Inspect run status before retrying this control operation.`)}let l=await this.executeManagement(a,i,n,c.record.runIds,e);return h.completeOperation(e,c.record,l),l}}}};F=t.__decorate([(0,v.injectable)(),i.__decorateParam(0,(0,v.inject)(n.DOOM_TEAM_TYPES.SpawnPlanner)),i.__decorateParam(1,(0,v.inject)(n.DOOM_TEAM_TYPES.ManagementActions)),i.__decorateParam(2,(0,v.inject)(n.DOOM_TEAM_TYPES.AsyncJobTracker)),i.__decorateParam(3,(0,v.inject)(n.DOOM_TEAM_TYPES.AgentDiscoveryService)),r.__decorateMetadata(`design:paramtypes`,[Object,Object,Object,Object])],F),Object.defineProperty(exports,`SubagentToolService`,{enumerable:!0,get:function(){return F}});
|
|
6
6
|
//# sourceMappingURL=subagentTool.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentTool.cjs","names":["SUBAGENT_ACTIONS","agentHasWriteTools","isSuspendedRunResumable","invalidRequest","SUBAGENT_ACTION_FIELDS","DoomTeamExpectedError","captureSessionForkSource","normalizeParentModel","authenticatedModelInfos","startOperation","loadConfig","listSuspendedRuns","requireCurrentSessionScope","formatFleetView","formatRunTranscript","resolveTrackedRunId","isPiRuntime","formatSuspendedRuns","SUBAGENT_TOOL_DESCRIPTION","SubagentParams","DOOM_TEAM_TYPES"],"sources":["../../src/extensions/subagentTool.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { agentHasWriteTools } from '../services/agents/memory.ts';\nimport type { AgentConfig, AgentScope, IAgentDiscoveryService } from '../services/agents/types.ts';\nimport { type IAsyncJobTracker, resolveTrackedRunId } from '../services/runs/background/asyncJobTracker.ts';\nimport {\n clearSuspendedRun,\n formatSuspendedRuns,\n isSuspendedRunResumable,\n listSuspendedRuns,\n type SuspendedRun,\n} from '../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../services/runs/shared/modelFallback.ts';\nimport { isPiRuntime } from '../services/runs/shared/runtimeRegistry.ts';\nimport { DoomTeamExpectedError, invalidRequest } from '../shared/errors.ts';\nimport { authenticatedModelInfos } from '../shared/modelResolution.ts';\nimport { requireCurrentSessionScope } from '../shared/paths.ts';\nimport { loadConfig } from './config.ts';\nimport type { IManagementActions, StatusActionResult } from './managementActions.ts';\nimport { completeOperation, startOperation } from './operationJournal.ts';\nimport {\n SUBAGENT_ACTION_FIELDS,\n SUBAGENT_ACTIONS,\n type SubagentAction,\n SubagentParams,\n type SubagentToolParams,\n} from './schemas.ts';\nimport {\n captureSessionForkSource,\n type ISpawnPlanner,\n type SpawnPlanRequest,\n type SpawnPlanResult,\n} from './spawnPlan.ts';\nimport { DEFAULT_TRANSCRIPT_LINES, formatFleetView, formatRunTranscript } from './statusViews.ts';\nimport { SUBAGENT_TOOL_DESCRIPTION } from './toolDescription.ts';\n\nexport const SUBAGENT_TOOL_NAME = 'subagent';\nexport const IMPLEMENTED_SUBAGENT_ACTIONS: ReadonlySet<string> = new Set(Object.values(SUBAGENT_ACTIONS));\n\ntype SubagentToolDetails = Record<string, unknown>;\n\nfunction textResult<T extends SubagentToolDetails>(text: string, details: T): AgentToolResult<T> {\n return { content: [{ type: 'text', text }], details };\n}\n\nfunction progressResult(text: string, action: SubagentAction): AgentToolResult<SubagentToolDetails> {\n return textResult(text, { action, partial: true });\n}\n\nfunction progressMessage(params: SubagentToolParams): string | undefined {\n switch (params.action) {\n case SUBAGENT_ACTIONS.run:\n return `Starting ${params.requests.length} subagent${params.requests.length === 1 ? '' : 's'}...`;\n case SUBAGENT_ACTIONS.steer:\n return `Steering subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.stop:\n return `Requesting stop for subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.restore:\n return `Restoring subagent ${params.id}...`;\n default:\n return undefined;\n }\n}\n\nfunction hasTool(pi: ExtensionAPI, name: string): boolean {\n try {\n return pi.getAllTools().some((tool) => tool.name === name);\n } catch {\n return false;\n }\n}\n\nfunction scopeOrDefault(scope: AgentScope | undefined): AgentScope {\n return scope ?? 'both';\n}\n\nfunction formatAgentList(agents: AgentConfig[]): string {\n return [\n 'Executable agents:',\n ...(agents.length\n ? agents\n .toSorted((left, right) => left.name.localeCompare(right.name))\n .map((agent) => `- ${agent.name} (${agent.source}): ${agent.description}`)\n : ['- (none)']),\n ].join('\\n');\n}\n\nfunction publicAgent(agent: AgentConfig): Record<string, unknown> {\n const tools = [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((tool) => `mcp:${tool}`)];\n return {\n name: agent.name,\n source: agent.source,\n description: agent.description,\n runtime: agent.runtime ?? 'pi',\n writeCapable: agentHasWriteTools(agent),\n ...(agent.model ? { model: agent.model } : {}),\n ...(agent.fallbackModels?.length ? { fallbackModels: agent.fallbackModels } : {}),\n ...(tools.length ? { tools } : {}),\n };\n}\n\nfunction publicSuspendedRun(run: SuspendedRun): SuspendedRun & { resumable: boolean } {\n return { ...run, resumable: isSuspendedRunResumable(run) };\n}\n\nfunction formatAgentDetail(agent: AgentConfig): string {\n const detail = publicAgent(agent);\n return [\n `Agent: ${agent.name} (${agent.source})`,\n `Description: ${agent.description}`,\n `Runtime: ${String(detail.runtime)}`,\n `Write capable: ${detail.writeCapable ? 'yes' : 'no'}`,\n ...(agent.model ? [`Model: ${agent.model}`] : []),\n ...(Array.isArray(detail.tools) ? [`Tools: ${detail.tools.join(', ')}`] : []),\n ].join('\\n');\n}\n\nfunction requireNonblank(record: Record<string, unknown>, field: string, action: string): void {\n if (typeof record[field] !== 'string' || !record[field].trim()) {\n throw invalidRequest(`action='${action}' requires nonblank '${field}'.`, 'Correct the request and retry.');\n }\n}\n\n/** Remove the one legacy field emitted by Doom Plan before strict validation. */\nfunction normalizeCompatibilityParams(raw: unknown): unknown {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return raw;\n const record = raw as Record<string, unknown>;\n if (\n typeof record.action !== 'string' ||\n !IMPLEMENTED_SUBAGENT_ACTIONS.has(record.action) ||\n record.action === SUBAGENT_ACTIONS.run ||\n typeof record.model !== 'string'\n ) {\n return raw;\n }\n const { model: _model, ...normalized } = record;\n return normalized;\n}\n\nfunction validateParams(input: unknown): SubagentToolParams {\n const raw = normalizeCompatibilityParams(input);\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n throw invalidRequest('subagent parameters must be an object.', 'Call subagent with one documented action shape.');\n }\n const record = raw as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_SUBAGENT_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unsupported or missing subagent action ${JSON.stringify(action)}.`,\n `Use one of: ${[...IMPLEMENTED_SUBAGENT_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = SUBAGENT_ACTION_FIELDS[action as SubagentAction] as readonly string[];\n const unknown = Object.keys(record).filter((field) => !allowed.includes(field));\n if (unknown.length) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unknown.join(', ')}.`,\n 'Remove unknown fields and retry.',\n );\n }\n if (action === 'run' && (!Array.isArray(record.requests) || record.requests.length === 0)) {\n throw invalidRequest(\"action='run' requires a nonempty 'requests' array.\", 'Add at least one agent and task.');\n }\n if (action === 'steer') {\n requireNonblank(record, 'id', action);\n requireNonblank(record, 'message', action);\n }\n if (action === 'stop' || action === 'restore') requireNonblank(record, 'id', action);\n return raw as SubagentToolParams;\n}\n\nexport interface ISubagentToolService {\n registerTool(pi: ExtensionAPI): void;\n}\n\n@injectable()\nexport class SubagentToolService implements ISubagentToolService {\n private readonly registeredHosts = new WeakSet<ExtensionAPI>();\n\n constructor(\n @inject(DOOM_TEAM_TYPES.SpawnPlanner) private readonly planner: ISpawnPlanner,\n @inject(DOOM_TEAM_TYPES.ManagementActions) private readonly management: IManagementActions,\n @inject(DOOM_TEAM_TYPES.AsyncJobTracker) private readonly tracker: IAsyncJobTracker,\n @inject(DOOM_TEAM_TYPES.AgentDiscoveryService) private readonly discovery: IAgentDiscoveryService,\n ) {}\n\n registerTool(pi: ExtensionAPI): void {\n if (this.registeredHosts.has(pi)) return;\n if (hasTool(pi, SUBAGENT_TOOL_NAME)) {\n throw new DoomTeamExpectedError(\n 'tool_conflict',\n `A foreign '${SUBAGENT_TOOL_NAME}' tool is already registered.`,\n false,\n 'Disable the competing extension, then reload Doom Team.',\n );\n }\n pi.registerTool(this.buildTool());\n this.registeredHosts.add(pi);\n }\n\n private trackOutcomes(result: SpawnPlanResult, ctx: ExtensionContext): SpawnPlanResult {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n for (const outcome of result.outcomes) {\n if (outcome.runId) jobs.track(outcome.runId);\n }\n return result;\n }\n\n private buildSpawnRequest(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n preallocatedRunIds: string[],\n ): SpawnPlanRequest {\n const tasks = params.requests.map((request) => {\n if (!request.agent.trim() || !request.task.trim()) {\n throw invalidRequest(\n 'Every run request requires nonblank agent and task values.',\n 'Correct the request and retry.',\n );\n }\n return {\n agent: request.agent.trim(),\n ...(request.inlineAgent ? { inlineAgent: request.inlineAgent } : {}),\n task: request.task.trim(),\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.model ? { model: request.model } : {}),\n ...(request.runtime ? { runtime: request.runtime } : {}),\n };\n });\n const parentForkSource = captureSessionForkSource(ctx.sessionManager, 'tool');\n const parentModel = normalizeParentModel(ctx.model);\n return {\n tasks,\n cwd: ctx.cwd,\n agentScope: scopeOrDefault(params.scope),\n parentSessionId: ctx.sessionManager.getSessionId(),\n ...(parentForkSource\n ? { parentSessionFile: parentForkSource.sessionFile, parentLeafId: parentForkSource.leafId }\n : {}),\n ...(params.concurrency !== undefined ? { concurrency: params.concurrency } : {}),\n ...(params.artifacts !== undefined ? { artifacts: params.artifacts } : {}),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n operationId,\n preallocatedRunIds,\n };\n }\n\n private async executeRun(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n operationId,\n params,\n params.requests.map(() => randomUUID()),\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(', ')}.`,\n true,\n 'Call subagent({\"action\":\"status\"}) and do not submit the run again.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n this.buildSpawnRequest(operationId, params, ctx, operation.record.runIds),\n loadConfig().config,\n ),\n ctx,\n );\n const started = result.outcomes.filter((outcome) => outcome.runId);\n const failed = result.outcomes.filter((outcome) => !outcome.runId);\n const lines = result.outcomes.map(\n (outcome) =>\n `- ${outcome.agent}: ${outcome.runId ? `started as ${outcome.runId}` : `failed: ${outcome.error ?? 'unknown error'}`}${outcome.warning ? `\\n Warning: ${outcome.warning}` : ''}`,\n );\n if (started.length === 0 && failed.length > 0) {\n throw new DoomTeamExpectedError(\n 'runtime_unavailable',\n `No requested subagent started.\\n${lines.join('\\n')}`,\n true,\n 'Call subagent({\"action\":\"agents\"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.',\n );\n }\n const response = textResult(\n [\n `Run request: started ${started.length}/${result.outcomes.length} background agents; failed ${failed.length}.`,\n ...lines,\n ...(started.length > 0\n ? [\n '',\n `The subagent${started.length === 1 ? ' is' : 's are'} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`,\n ]\n : []),\n ...(failed.length > 0\n ? [\n '',\n 'Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.',\n ]\n : []),\n ].join('\\n'),\n { spawn: result, started: started.length, failed: failed.length },\n );\n completeOperation(operationId, operation.record, response);\n return response;\n }\n\n private executeAgents(\n params: Extract<SubagentToolParams, { action: 'agents' }>,\n ctx: ExtensionContext,\n ): AgentToolResult<SubagentToolDetails> {\n const cwd = params.cwd ?? ctx.cwd;\n const scope = scopeOrDefault(params.scope);\n if (!params.name) {\n const result = this.discovery.discover(cwd, scope);\n return textResult(formatAgentList(result.agents), { agents: result.agents.map(publicAgent) });\n }\n const agent = this.discovery.find(cwd, scope, params.name);\n if (!agent) {\n const candidates = this.discovery\n .discover(cwd, scope)\n .agents.map((candidate) => candidate.name)\n .toSorted();\n throw new DoomTeamExpectedError(\n 'agent_not_found',\n `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(', ')}.` : ''}`,\n false,\n 'Call subagent({\"action\":\"agents\"}) and retry with an exact name.',\n );\n }\n return textResult(formatAgentDetail(agent), { agent: publicAgent(agent) });\n }\n\n private async executeManagement(\n params: Exclude<SubagentToolParams, { action: 'run' } | { action: 'agents' }>,\n ctx: ExtensionContext,\n signal?: AbortSignal,\n preallocatedRunIds?: string[],\n operationId?: string,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n switch (params.action) {\n case SUBAGENT_ACTIONS.status: {\n const suspendedRuns = listSuspendedRuns(requireCurrentSessionScope());\n if (!('id' in params)) {\n if ('transcriptLines' in params && params.transcriptLines !== undefined) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const runs = jobs.list();\n return textResult(formatFleetView(runs, Date.now(), suspendedRuns), {\n fleet: runs,\n suspended: suspendedRuns.map(publicSuspendedRun),\n });\n }\n const runId = params.id;\n if (!runId) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const suspended = suspendedRuns.find((run) => run.runId === runId);\n if (suspended && params.transcriptLines === undefined) {\n const resumable = isSuspendedRunResumable(suspended);\n const recovery = resumable\n ? `Restore it with { action: \"restore\", id: \"${suspended.runId}\" }.`\n : 'It is not resumable; submit a new explicit run.';\n return textResult(`Run '${suspended.runId}' is suspended. ${recovery}`, {\n suspended: publicSuspendedRun(suspended),\n });\n }\n const result: StatusActionResult = this.management.status(runId);\n if (!result.runDir && !result.resultPath && !suspended) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No run matches '${runId}'.`,\n false,\n 'Call subagent({\"action\":\"status\"}) and retry with an exact id.',\n );\n }\n if (params.transcriptLines !== undefined) {\n return textResult(formatRunTranscript(result.status, params.transcriptLines ?? DEFAULT_TRANSCRIPT_LINES), {\n transcript: { runId: result.runId },\n });\n }\n return textResult(\n result.status ? `Run '${result.runId}': ${result.status.state}` : `Run '${result.runId}' has no status yet.`,\n { status: result },\n );\n }\n case SUBAGENT_ACTIONS.stop: {\n const id = resolveTrackedRunId(jobs, params.id);\n const result = this.management.stop(id, params.reason);\n return textResult(`Stop requested for '${id}'.`, { control: result });\n }\n case SUBAGENT_ACTIONS.steer: {\n const id = resolveTrackedRunId(jobs, params.id);\n const runtime = this.tracker.get(id)?.runtime;\n if (runtime && !isPiRuntime(runtime)) {\n throw new DoomTeamExpectedError(\n 'unsupported_operation',\n `Run '${id}' uses '${runtime}', which does not support steering.`,\n false,\n `Use subagent({\"action\":\"stop\",\"id\":\"${id}\"}) to terminate it.`,\n );\n }\n const result = await this.management.steer(id, params.message, undefined, signal);\n return textResult(`Steer request '${result.requestId}' for '${id}' is ${result.state}: ${result.message}`, {\n steer: result,\n });\n }\n case SUBAGENT_ACTIONS.suspended: {\n const runs = listSuspendedRuns(requireCurrentSessionScope());\n return textResult(runs.length ? formatSuspendedRuns(runs) : 'No suspended subagents in this session.', {\n suspended: runs.map(publicSuspendedRun),\n });\n }\n case SUBAGENT_ACTIONS.restore: {\n const scope = requireCurrentSessionScope();\n const record = listSuspendedRuns(scope).find((run) => run.runId === params.id);\n if (!record) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No suspended run matches '${params.id}'.`,\n false,\n 'Call subagent({\"action\":\"suspended\"}) and retry with an exact id.',\n );\n }\n if (!isSuspendedRunResumable(record)) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Suspended run '${params.id}' does not have complete, readable Pi recovery state.`,\n false,\n 'Submit a new explicit run request instead of restoring this record.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n {\n single: {\n agent: record.agent,\n ...(record.inlineAgent ? { inlineAgent: record.inlineAgent } : {}),\n task: record.task,\n cwd: record.cwd,\n ...(record.model ? { model: record.model } : {}),\n sessionFile: record.sessionFile,\n },\n cwd: record.cwd,\n agentScope: 'both',\n runtime: 'pi',\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(operationId ? { operationId } : {}),\n ...(preallocatedRunIds ? { preallocatedRunIds } : {}),\n },\n loadConfig().config,\n ),\n ctx,\n );\n const outcome = result.outcomes[0];\n if (!outcome?.runId) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Could not restore '${params.id}': ${outcome?.error ?? 'the spawn produced no run.'}`,\n true,\n 'Inspect suspended state, then submit a new explicit run if recovery is not possible.',\n );\n }\n clearSuspendedRun(scope, params.id);\n return textResult(`Restored '${params.id}' as '${outcome.runId}', continuing its transcript.`, {\n restore: { ...outcome, restoredFrom: params.id },\n });\n }\n }\n }\n\n private buildTool(): ToolDefinition<typeof SubagentParams, SubagentToolDetails> {\n return {\n name: SUBAGENT_TOOL_NAME,\n label: 'Subagent',\n description: SUBAGENT_TOOL_DESCRIPTION,\n parameters: SubagentParams,\n prepareArguments: validateParams,\n execute: async (id, rawParams, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentToolDetails>> => {\n const params = validateParams(rawParams);\n const progress = progressMessage(params);\n if (progress) onUpdate?.(progressResult(progress, params.action));\n if (params.action === SUBAGENT_ACTIONS.run) return this.executeRun(id, params, ctx);\n if (params.action === SUBAGENT_ACTIONS.agents) return this.executeAgents(params, ctx);\n const journaled =\n params.action === SUBAGENT_ACTIONS.steer ||\n params.action === SUBAGENT_ACTIONS.stop ||\n params.action === SUBAGENT_ACTIONS.restore;\n if (!journaled) return this.executeManagement(params, ctx, signal);\n\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n id,\n params,\n params.action === SUBAGENT_ACTIONS.restore ? [randomUUID()] : [],\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${id}' is already pending.`,\n true,\n 'Inspect run status before retrying this control operation.',\n );\n }\n const response = await this.executeManagement(params, ctx, signal, operation.record.runIds, id);\n completeOperation(id, operation.record, response);\n return response;\n },\n };\n }\n}\n"],"mappings":"wlCAuCA,MAAa,EAAqB,WACrB,EAAoD,IAAI,IAAI,OAAO,OAAOA,EAAAA,iBAAiB,CAAC,CAIzG,SAAS,EAA0C,EAAc,EAAgC,CAC/F,MAAO,CAAE,QAAS,CAAC,CAAE,KAAM,OAAQ,OAAM,CAAC,CAAE,UAAS,CAGvD,SAAS,EAAe,EAAc,EAA8D,CAClG,OAAO,EAAW,EAAM,CAAE,SAAQ,QAAS,GAAM,CAAC,CAGpD,SAAS,EAAgB,EAAgD,CACvE,OAAQ,EAAO,OAAf,CACE,KAAKA,EAAAA,iBAAiB,IACpB,MAAO,YAAY,EAAO,SAAS,OAAO,WAAW,EAAO,SAAS,SAAW,EAAI,GAAK,IAAI,KAC/F,KAAKA,EAAAA,iBAAiB,MACpB,MAAO,qBAAqB,EAAO,GAAG,KACxC,KAAKA,EAAAA,iBAAiB,KACpB,MAAO,gCAAgC,EAAO,GAAG,KACnD,KAAKA,EAAAA,iBAAiB,QACpB,MAAO,sBAAsB,EAAO,GAAG,KACzC,QACE,QAIN,SAAS,EAAQ,EAAkB,EAAuB,CACxD,GAAI,CACF,OAAO,EAAG,aAAa,CAAC,KAAM,GAAS,EAAK,OAAS,EAAK,MACpD,CACN,MAAO,IAIX,SAAS,EAAe,EAA2C,CACjE,OAAO,GAAS,OAGlB,SAAS,EAAgB,EAA+B,CACtD,MAAO,CACL,qBACA,GAAI,EAAO,OACP,EACG,UAAU,EAAM,IAAU,EAAK,KAAK,cAAc,EAAM,KAAK,CAAC,CAC9D,IAAK,GAAU,KAAK,EAAM,KAAK,IAAI,EAAM,OAAO,KAAK,EAAM,cAAc,CAC5E,CAAC,WAAW,CACjB,CAAC,KAAK;EAAK,CAGd,SAAS,EAAY,EAA6C,CAChE,IAAM,EAAQ,CAAC,GAAI,EAAM,OAAS,EAAE,CAAG,IAAI,EAAM,gBAAkB,EAAE,EAAE,IAAK,GAAS,OAAO,IAAO,CAAC,CACpG,MAAO,CACL,KAAM,EAAM,KACZ,OAAQ,EAAM,OACd,YAAa,EAAM,YACnB,QAAS,EAAM,SAAW,KAC1B,aAAcC,EAAAA,mBAAmB,EAAM,CACvC,GAAI,EAAM,MAAQ,CAAE,MAAO,EAAM,MAAO,CAAG,EAAE,CAC7C,GAAI,EAAM,gBAAgB,OAAS,CAAE,eAAgB,EAAM,eAAgB,CAAG,EAAE,CAChF,GAAI,EAAM,OAAS,CAAE,QAAO,CAAG,EAAE,CAClC,CAGH,SAAS,EAAmB,EAA0D,CACpF,MAAO,CAAE,GAAG,EAAK,UAAWC,EAAAA,wBAAwB,EAAI,CAAE,CAG5D,SAAS,EAAkB,EAA4B,CACrD,IAAM,EAAS,EAAY,EAAM,CACjC,MAAO,CACL,UAAU,EAAM,KAAK,IAAI,EAAM,OAAO,GACtC,gBAAgB,EAAM,cACtB,YAAY,OAAO,EAAO,QAAQ,GAClC,kBAAkB,EAAO,aAAe,MAAQ,OAChD,GAAI,EAAM,MAAQ,CAAC,UAAU,EAAM,QAAQ,CAAG,EAAE,CAChD,GAAI,MAAM,QAAQ,EAAO,MAAM,CAAG,CAAC,UAAU,EAAO,MAAM,KAAK,KAAK,GAAG,CAAG,EAAE,CAC7E,CAAC,KAAK;EAAK,CAGd,SAAS,EAAgB,EAAiC,EAAe,EAAsB,CAC7F,GAAI,OAAO,EAAO,IAAW,UAAY,CAAC,EAAO,GAAO,MAAM,CAC5D,MAAMC,EAAAA,eAAe,WAAW,EAAO,uBAAuB,EAAM,IAAK,iCAAiC,CAK9G,SAAS,EAA6B,EAAuB,CAC3D,GAAI,CAAC,GAAO,OAAO,GAAQ,UAAY,MAAM,QAAQ,EAAI,CAAE,OAAO,EAClE,IAAM,EAAS,EACf,GACE,OAAO,EAAO,QAAW,UACzB,CAAC,EAA6B,IAAI,EAAO,OAAO,EAChD,EAAO,SAAWH,EAAAA,iBAAiB,KACnC,OAAO,EAAO,OAAU,SAExB,OAAO,EAET,GAAM,CAAE,MAAO,EAAQ,GAAG,GAAe,EACzC,OAAO,EAGT,SAAS,EAAe,EAAoC,CAC1D,IAAM,EAAM,EAA6B,EAAM,CAC/C,GAAI,CAAC,GAAO,OAAO,GAAQ,UAAY,MAAM,QAAQ,EAAI,CACvD,MAAMG,EAAAA,eAAe,yCAA0C,kDAAkD,CAEnH,IAAM,EAAS,EACT,EAAS,EAAO,OACtB,GAAI,OAAO,GAAW,UAAY,CAAC,EAA6B,IAAI,EAAO,CACzE,MAAMA,EAAAA,eACJ,0CAA0C,KAAK,UAAU,EAAO,CAAC,GACjE,eAAe,CAAC,GAAG,EAA6B,CAAC,KAAK,KAAK,CAAC,GAC7D,CAEH,IAAM,EAAUC,EAAAA,uBAAuB,GACjC,EAAU,OAAO,KAAK,EAAO,CAAC,OAAQ,GAAU,CAAC,EAAQ,SAAS,EAAM,CAAC,CAC/E,GAAI,EAAQ,OACV,MAAMD,EAAAA,eACJ,WAAW,EAAO,qBAAqB,EAAQ,KAAK,KAAK,CAAC,GAC1D,mCACD,CAEH,GAAI,IAAW,QAAU,CAAC,MAAM,QAAQ,EAAO,SAAS,EAAI,EAAO,SAAS,SAAW,GACrF,MAAMA,EAAAA,eAAe,qDAAsD,mCAAmC,CAOhH,OALI,IAAW,UACb,EAAgB,EAAQ,KAAM,EAAO,CACrC,EAAgB,EAAQ,UAAW,EAAO,GAExC,IAAW,QAAU,IAAW,YAAW,EAAgB,EAAQ,KAAM,EAAO,CAC7E,EAQF,IAAA,EAAA,KAA0D,CAC/D,gBAAmC,IAAI,QAEvC,YACE,EACA,EACA,EACA,EACA,CAJuD,KAAA,QAAA,EACK,KAAA,WAAA,EACF,KAAA,QAAA,EACM,KAAA,UAAA,EAGlE,aAAa,EAAwB,CAC/B,SAAK,gBAAgB,IAAI,EAAG,CAChC,IAAI,EAAQ,EAAA,WAAuB,CACjC,MAAM,IAAIE,EAAAA,sBACR,gBACA,cAAc,EAAmB,+BACjC,GACA,0DACD,CAEH,EAAG,aAAa,KAAK,WAAW,CAAC,CACjC,KAAK,gBAAgB,IAAI,EAAG,EAG9B,cAAsB,EAAyB,EAAwC,CACrF,IAAM,EAAO,KAAK,QAAQ,WAAW,EAAI,eAAe,cAAc,CAAC,CACvE,IAAK,IAAM,KAAW,EAAO,SACvB,EAAQ,OAAO,EAAK,MAAM,EAAQ,MAAM,CAE9C,OAAO,EAGT,kBACE,EACA,EACA,EACA,EACkB,CAClB,IAAM,EAAQ,EAAO,SAAS,IAAK,GAAY,CAC7C,GAAI,CAAC,EAAQ,MAAM,MAAM,EAAI,CAAC,EAAQ,KAAK,MAAM,CAC/C,MAAMF,EAAAA,eACJ,6DACA,iCACD,CAEH,MAAO,CACL,MAAO,EAAQ,MAAM,MAAM,CAC3B,GAAI,EAAQ,YAAc,CAAE,YAAa,EAAQ,YAAa,CAAG,EAAE,CACnE,KAAM,EAAQ,KAAK,MAAM,CACzB,GAAI,EAAQ,IAAM,CAAE,IAAK,EAAQ,IAAK,CAAG,EAAE,CAC3C,GAAI,EAAQ,MAAQ,CAAE,MAAO,EAAQ,MAAO,CAAG,EAAE,CACjD,GAAI,EAAQ,QAAU,CAAE,QAAS,EAAQ,QAAS,CAAG,EAAE,CACxD,EACD,CACI,EAAmBG,EAAAA,yBAAyB,EAAI,eAAgB,OAAO,CACvE,EAAcC,EAAAA,qBAAqB,EAAI,MAAM,CACnD,MAAO,CACL,QACA,IAAK,EAAI,IACT,WAAY,EAAe,EAAO,MAAM,CACxC,gBAAiB,EAAI,eAAe,cAAc,CAClD,GAAI,EACA,CAAE,kBAAmB,EAAiB,YAAa,aAAc,EAAiB,OAAQ,CAC1F,EAAE,CACN,GAAI,EAAO,cAAgB,IAAA,GAAkD,EAAE,CAAxC,CAAE,YAAa,EAAO,YAAa,CAC1E,GAAI,EAAO,YAAc,IAAA,GAA8C,EAAE,CAApC,CAAE,UAAW,EAAO,UAAW,CACpE,gBAAiBC,EAAAA,wBAAwB,EAAI,cAAc,CAC3D,GAAI,EAAc,CAAE,cAAa,CAAG,EAAE,CACtC,cACA,qBACD,CAGH,MAAc,WACZ,EACA,EACA,EAC+C,CAC/C,IAAM,EAAYC,EAAAA,eAChB,EACA,EACA,EAAO,SAAS,SAAA,EAAA,EAAA,aAAsB,CAAC,CACxC,CACD,GAAI,EAAU,OAAS,SAAU,CAC/B,GAAI,EAAU,OAAO,QAAU,aAAe,EAAU,OAAO,OAAQ,OAAO,EAAU,OAAO,OAC/F,MAAM,IAAIJ,EAAAA,sBACR,uBACA,cAAc,EAAY,iCAAiC,EAAU,OAAO,OAAO,KAAK,KAAK,CAAC,GAC9F,GACA,sEACD,CAEH,IAAM,EAAS,KAAK,cAClB,MAAM,KAAK,QAAQ,MACjB,KAAK,kBAAkB,EAAa,EAAQ,EAAK,EAAU,OAAO,OAAO,CACzEK,EAAAA,YAAY,CAAC,OACd,CACD,EACD,CACK,EAAU,EAAO,SAAS,OAAQ,GAAY,EAAQ,MAAM,CAC5D,EAAS,EAAO,SAAS,OAAQ,GAAY,CAAC,EAAQ,MAAM,CAC5D,EAAQ,EAAO,SAAS,IAC3B,GACC,KAAK,EAAQ,MAAM,IAAI,EAAQ,MAAQ,cAAc,EAAQ,QAAU,WAAW,EAAQ,OAAS,oBAAoB,EAAQ,QAAU,gBAAgB,EAAQ,UAAY,KAChL,CACD,GAAI,EAAQ,SAAW,GAAK,EAAO,OAAS,EAC1C,MAAM,IAAIL,EAAAA,sBACR,sBACA,mCAAmC,EAAM,KAAK;EAAK,GACnD,GACA,kKACD,CAEH,IAAM,EAAW,EACf,CACE,wBAAwB,EAAQ,OAAO,GAAG,EAAO,SAAS,OAAO,6BAA6B,EAAO,OAAO,GAC5G,GAAG,EACH,GAAI,EAAQ,OAAS,EACjB,CACE,GACA,eAAe,EAAQ,SAAW,EAAI,MAAQ,QAAQ,sKACvD,CACD,EAAE,CACN,GAAI,EAAO,OAAS,EAChB,CACE,GACA,uJACD,CACD,EAAE,CACP,CAAC,KAAK;EAAK,CACZ,CAAE,MAAO,EAAQ,QAAS,EAAQ,OAAQ,OAAQ,EAAO,OAAQ,CAClE,CAED,OADA,EAAA,kBAAkB,EAAa,EAAU,OAAQ,EAAS,CACnD,EAGT,cACE,EACA,EACsC,CACtC,IAAM,EAAM,EAAO,KAAO,EAAI,IACxB,EAAQ,EAAe,EAAO,MAAM,CAC1C,GAAI,CAAC,EAAO,KAAM,CAChB,IAAM,EAAS,KAAK,UAAU,SAAS,EAAK,EAAM,CAClD,OAAO,EAAW,EAAgB,EAAO,OAAO,CAAE,CAAE,OAAQ,EAAO,OAAO,IAAI,EAAY,CAAE,CAAC,CAE/F,IAAM,EAAQ,KAAK,UAAU,KAAK,EAAK,EAAO,EAAO,KAAK,CAC1D,GAAI,CAAC,EAAO,CACV,IAAM,EAAa,KAAK,UACrB,SAAS,EAAK,EAAM,CACpB,OAAO,IAAK,GAAc,EAAU,KAAK,CACzC,UAAU,CACb,MAAM,IAAIA,EAAAA,sBACR,kBACA,gCAAgC,EAAO,KAAK,IAAI,EAAW,OAAS,eAAe,EAAW,KAAK,KAAK,CAAC,GAAK,KAC9G,GACA,mEACD,CAEH,OAAO,EAAW,EAAkB,EAAM,CAAE,CAAE,MAAO,EAAY,EAAM,CAAE,CAAC,CAG5E,MAAc,kBACZ,EACA,EACA,EACA,EACA,EAC+C,CAC/C,IAAM,EAAO,KAAK,QAAQ,WAAW,EAAI,eAAe,cAAc,CAAC,CACvE,OAAQ,EAAO,OAAf,CACE,KAAKL,EAAAA,iBAAiB,OAAQ,CAC5B,IAAM,EAAgBW,EAAAA,kBAAkBC,EAAAA,4BAA4B,CAAC,CACrE,GAAI,EAAE,OAAQ,GAAS,CACrB,GAAI,oBAAqB,GAAU,EAAO,kBAAoB,IAAA,GAC5D,MAAMT,EAAAA,eACJ,qCACA,mDACD,CAEH,IAAM,EAAO,EAAK,MAAM,CACxB,OAAO,EAAWU,EAAAA,gBAAgB,EAAM,KAAK,KAAK,CAAE,EAAc,CAAE,CAClE,MAAO,EACP,UAAW,EAAc,IAAI,EAAmB,CACjD,CAAC,CAEJ,IAAM,EAAQ,EAAO,GACrB,GAAI,CAAC,EACH,MAAMV,EAAAA,eACJ,qCACA,mDACD,CAEH,IAAM,EAAY,EAAc,KAAM,GAAQ,EAAI,QAAU,EAAM,CAClE,GAAI,GAAa,EAAO,kBAAoB,IAAA,GAAW,CAErD,IAAM,EADYD,EAAAA,wBAAwB,EAChB,CACtB,6CAA6C,EAAU,MAAM,MAC7D,kDACJ,OAAO,EAAW,QAAQ,EAAU,MAAM,kBAAkB,IAAY,CACtE,UAAW,EAAmB,EAAU,CACzC,CAAC,CAEJ,IAAM,EAA6B,KAAK,WAAW,OAAO,EAAM,CAChE,GAAI,CAAC,EAAO,QAAU,CAAC,EAAO,YAAc,CAAC,EAC3C,MAAM,IAAIG,EAAAA,sBACR,gBACA,mBAAmB,EAAM,IACzB,GACA,iEACD,CAOH,OALI,EAAO,kBAAoB,IAAA,GAKxB,EACL,EAAO,OAAS,QAAQ,EAAO,MAAM,KAAK,EAAO,OAAO,QAAU,QAAQ,EAAO,MAAM,sBACvF,CAAE,OAAQ,EAAQ,CACnB,CAPQ,EAAWS,EAAAA,oBAAoB,EAAO,OAAQ,EAAO,iBAAA,GAA4C,CAAE,CACxG,WAAY,CAAE,MAAO,EAAO,MAAO,CACpC,CAAC,CAON,KAAKd,EAAAA,iBAAiB,KAAM,CAC1B,IAAM,EAAKe,EAAAA,oBAAoB,EAAM,EAAO,GAAG,CACzC,EAAS,KAAK,WAAW,KAAK,EAAI,EAAO,OAAO,CACtD,OAAO,EAAW,uBAAuB,EAAG,IAAK,CAAE,QAAS,EAAQ,CAAC,CAEvE,KAAKf,EAAAA,iBAAiB,MAAO,CAC3B,IAAM,EAAKe,EAAAA,oBAAoB,EAAM,EAAO,GAAG,CACzC,EAAU,KAAK,QAAQ,IAAI,EAAG,EAAE,QACtC,GAAI,GAAW,CAACC,EAAAA,YAAY,EAAQ,CAClC,MAAM,IAAIX,EAAAA,sBACR,wBACA,QAAQ,EAAG,UAAU,EAAQ,qCAC7B,GACA,uCAAuC,EAAG,sBAC3C,CAEH,IAAM,EAAS,MAAM,KAAK,WAAW,MAAM,EAAI,EAAO,QAAS,IAAA,GAAW,EAAO,CACjF,OAAO,EAAW,kBAAkB,EAAO,UAAU,SAAS,EAAG,OAAO,EAAO,MAAM,IAAI,EAAO,UAAW,CACzG,MAAO,EACR,CAAC,CAEJ,KAAKL,EAAAA,iBAAiB,UAAW,CAC/B,IAAM,EAAOW,EAAAA,kBAAkBC,EAAAA,4BAA4B,CAAC,CAC5D,OAAO,EAAW,EAAK,OAASK,EAAAA,oBAAoB,EAAK,CAAG,0CAA2C,CACrG,UAAW,EAAK,IAAI,EAAmB,CACxC,CAAC,CAEJ,KAAKjB,EAAAA,iBAAiB,QAAS,CAC7B,IAAM,EAAQY,EAAAA,4BAA4B,CACpC,EAASD,EAAAA,kBAAkB,EAAM,CAAC,KAAM,GAAQ,EAAI,QAAU,EAAO,GAAG,CAC9E,GAAI,CAAC,EACH,MAAM,IAAIN,EAAAA,sBACR,gBACA,6BAA6B,EAAO,GAAG,IACvC,GACA,oEACD,CAEH,GAAI,CAACH,EAAAA,wBAAwB,EAAO,CAClC,MAAM,IAAIG,EAAAA,sBACR,gBACA,kBAAkB,EAAO,GAAG,uDAC5B,GACA,sEACD,CAwBH,IAAM,EAtBS,KAAK,cAClB,MAAM,KAAK,QAAQ,MACjB,CACE,OAAQ,CACN,MAAO,EAAO,MACd,GAAI,EAAO,YAAc,CAAE,YAAa,EAAO,YAAa,CAAG,EAAE,CACjE,KAAM,EAAO,KACb,IAAK,EAAO,IACZ,GAAI,EAAO,MAAQ,CAAE,MAAO,EAAO,MAAO,CAAG,EAAE,CAC/C,YAAa,EAAO,YACrB,CACD,IAAK,EAAO,IACZ,WAAY,OACZ,QAAS,KACT,gBAAiBG,EAAAA,wBAAwB,EAAI,cAAc,CAC3D,GAAI,EAAc,CAAE,cAAa,CAAG,EAAE,CACtC,GAAI,EAAqB,CAAE,qBAAoB,CAAG,EAAE,CACrD,CACDE,EAAAA,YAAY,CAAC,OACd,CACD,EAEoB,CAAC,SAAS,GAChC,GAAI,CAAC,GAAS,MACZ,MAAM,IAAIL,EAAAA,sBACR,gBACA,sBAAsB,EAAO,GAAG,KAAK,GAAS,OAAS,+BACvD,GACA,uFACD,CAGH,OADA,EAAA,kBAAkB,EAAO,EAAO,GAAG,CAC5B,EAAW,aAAa,EAAO,GAAG,QAAQ,EAAQ,MAAM,+BAAgC,CAC7F,QAAS,CAAE,GAAG,EAAS,aAAc,EAAO,GAAI,CACjD,CAAC,GAKR,WAAgF,CAC9E,MAAO,CACL,KAAM,EACN,MAAO,WACP,YAAaa,EAAAA,0BACb,WAAYC,EAAAA,eACZ,iBAAkB,EAClB,QAAS,MAAO,EAAI,EAAW,EAAQ,EAAU,IAAuD,CACtG,IAAM,EAAS,EAAe,EAAU,CAClC,EAAW,EAAgB,EAAO,CAExC,GADI,GAAU,IAAW,EAAe,EAAU,EAAO,OAAO,CAAC,CAC7D,EAAO,SAAWnB,EAAAA,iBAAiB,IAAK,OAAO,KAAK,WAAW,EAAI,EAAQ,EAAI,CACnF,GAAI,EAAO,SAAWA,EAAAA,iBAAiB,OAAQ,OAAO,KAAK,cAAc,EAAQ,EAAI,CAKrF,GAAI,EAHF,EAAO,SAAWA,EAAAA,iBAAiB,OACnC,EAAO,SAAWA,EAAAA,iBAAiB,MACnC,EAAO,SAAWA,EAAAA,iBAAiB,SACrB,OAAO,KAAK,kBAAkB,EAAQ,EAAK,EAAO,CAElE,IAAM,EAAYS,EAAAA,eAChB,EACA,EACA,EAAO,SAAWT,EAAAA,iBAAiB,QAAU,EAAA,EAAA,EAAA,aAAa,CAAC,CAAG,EAAE,CACjE,CACD,GAAI,EAAU,OAAS,SAAU,CAC/B,GAAI,EAAU,OAAO,QAAU,aAAe,EAAU,OAAO,OAAQ,OAAO,EAAU,OAAO,OAC/F,MAAM,IAAIK,EAAAA,sBACR,uBACA,cAAc,EAAG,uBACjB,GACA,6DACD,CAEH,IAAM,EAAW,MAAM,KAAK,kBAAkB,EAAQ,EAAK,EAAQ,EAAU,OAAO,OAAQ,EAAG,CAE/F,OADA,EAAA,kBAAkB,EAAI,EAAU,OAAQ,EAAS,CAC1C,GAEV,qCAzVQ,kCAKDe,EAAAA,gBAAgB,aAAa,CAAA,kCAC7BA,EAAAA,gBAAgB,kBAAkB,CAAA,kCAClCA,EAAAA,gBAAgB,gBAAgB,CAAA,kCAChCA,EAAAA,gBAAgB,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"subagentTool.cjs","names":["SUBAGENT_ACTIONS","agentHasWriteTools","isSuspendedRunResumable","invalidRequest","SUBAGENT_ACTION_FIELDS","DoomTeamExpectedError","captureSessionForkSource","normalizeParentModel","authenticatedModelInfos","startOperation","loadConfig","listSuspendedRuns","requireCurrentSessionScope","formatFleetView","formatRunTranscript","resolveTrackedRunId","isPiRuntime","formatSuspendedRuns","SUBAGENT_TOOL_DESCRIPTION","SubagentParams","renderSubagentCall","renderSubagentResult","DOOM_TEAM_TYPES"],"sources":["../../src/extensions/subagentTool.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { agentHasWriteTools } from '../services/agents/memory.ts';\nimport type { AgentConfig, AgentScope, IAgentDiscoveryService } from '../services/agents/types.ts';\nimport { type IAsyncJobTracker, resolveTrackedRunId } from '../services/runs/background/asyncJobTracker.ts';\nimport {\n clearSuspendedRun,\n formatSuspendedRuns,\n isSuspendedRunResumable,\n listSuspendedRuns,\n type SuspendedRun,\n} from '../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../services/runs/shared/modelFallback.ts';\nimport { isPiRuntime } from '../services/runs/shared/runtimeRegistry.ts';\nimport { DoomTeamExpectedError, invalidRequest } from '../shared/errors.ts';\nimport { authenticatedModelInfos } from '../shared/modelResolution.ts';\nimport { requireCurrentSessionScope } from '../shared/paths.ts';\nimport { renderSubagentCall, renderSubagentResult } from '../tui/subagentToolRender.ts';\nimport { loadConfig } from './config.ts';\nimport type { IManagementActions, StatusActionResult } from './managementActions.ts';\nimport { completeOperation, startOperation } from './operationJournal.ts';\nimport {\n SUBAGENT_ACTION_FIELDS,\n SUBAGENT_ACTIONS,\n type SubagentAction,\n SubagentParams,\n type SubagentToolParams,\n} from './schemas.ts';\nimport {\n captureSessionForkSource,\n type ISpawnPlanner,\n type SpawnPlanRequest,\n type SpawnPlanResult,\n} from './spawnPlan.ts';\nimport { DEFAULT_TRANSCRIPT_LINES, formatFleetView, formatRunTranscript } from './statusViews.ts';\nimport { SUBAGENT_TOOL_DESCRIPTION } from './toolDescription.ts';\n\nexport const SUBAGENT_TOOL_NAME = 'subagent';\nexport const IMPLEMENTED_SUBAGENT_ACTIONS: ReadonlySet<string> = new Set(Object.values(SUBAGENT_ACTIONS));\n\ntype SubagentToolDetails = Record<string, unknown>;\n\nfunction textResult<T extends SubagentToolDetails>(text: string, details: T): AgentToolResult<T> {\n return { content: [{ type: 'text', text }], details };\n}\n\nfunction progressResult(text: string, action: SubagentAction): AgentToolResult<SubagentToolDetails> {\n return textResult(text, { action, partial: true });\n}\n\nfunction progressMessage(params: SubagentToolParams): string | undefined {\n switch (params.action) {\n case SUBAGENT_ACTIONS.run:\n return `Starting ${params.requests.length} subagent${params.requests.length === 1 ? '' : 's'}...`;\n case SUBAGENT_ACTIONS.steer:\n return `Steering subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.stop:\n return `Requesting stop for subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.restore:\n return `Restoring subagent ${params.id}...`;\n default:\n return undefined;\n }\n}\n\nfunction hasTool(pi: ExtensionAPI, name: string): boolean {\n try {\n return pi.getAllTools().some((tool) => tool.name === name);\n } catch {\n return false;\n }\n}\n\nfunction scopeOrDefault(scope: AgentScope | undefined): AgentScope {\n return scope ?? 'both';\n}\n\nfunction formatAgentList(agents: AgentConfig[]): string {\n return [\n 'Executable agents:',\n ...(agents.length\n ? agents\n .toSorted((left, right) => left.name.localeCompare(right.name))\n .map((agent) => `- ${agent.name} (${agent.source}): ${agent.description}`)\n : ['- (none)']),\n ].join('\\n');\n}\n\nfunction publicAgent(agent: AgentConfig): Record<string, unknown> {\n const tools = [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((tool) => `mcp:${tool}`)];\n return {\n name: agent.name,\n source: agent.source,\n description: agent.description,\n runtime: agent.runtime ?? 'pi',\n writeCapable: agentHasWriteTools(agent),\n ...(agent.model ? { model: agent.model } : {}),\n ...(agent.fallbackModels?.length ? { fallbackModels: agent.fallbackModels } : {}),\n ...(tools.length ? { tools } : {}),\n };\n}\n\nfunction publicSuspendedRun(run: SuspendedRun): SuspendedRun & { resumable: boolean } {\n return { ...run, resumable: isSuspendedRunResumable(run) };\n}\n\nfunction formatAgentDetail(agent: AgentConfig): string {\n const detail = publicAgent(agent);\n return [\n `Agent: ${agent.name} (${agent.source})`,\n `Description: ${agent.description}`,\n `Runtime: ${String(detail.runtime)}`,\n `Write capable: ${detail.writeCapable ? 'yes' : 'no'}`,\n ...(agent.model ? [`Model: ${agent.model}`] : []),\n ...(Array.isArray(detail.tools) ? [`Tools: ${detail.tools.join(', ')}`] : []),\n ].join('\\n');\n}\n\nfunction requireNonblank(record: Record<string, unknown>, field: string, action: string): void {\n if (typeof record[field] !== 'string' || !record[field].trim()) {\n throw invalidRequest(`action='${action}' requires nonblank '${field}'.`, 'Correct the request and retry.');\n }\n}\n\n/** Remove the one legacy field emitted by Doom Plan before strict validation. */\nfunction normalizeCompatibilityParams(raw: unknown): unknown {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return raw;\n const record = raw as Record<string, unknown>;\n if (\n typeof record.action !== 'string' ||\n !IMPLEMENTED_SUBAGENT_ACTIONS.has(record.action) ||\n record.action === SUBAGENT_ACTIONS.run ||\n typeof record.model !== 'string'\n ) {\n return raw;\n }\n const { model: _model, ...normalized } = record;\n return normalized;\n}\n\nfunction validateParams(input: unknown): SubagentToolParams {\n const raw = normalizeCompatibilityParams(input);\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n throw invalidRequest('subagent parameters must be an object.', 'Call subagent with one documented action shape.');\n }\n const record = raw as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_SUBAGENT_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unsupported or missing subagent action ${JSON.stringify(action)}.`,\n `Use one of: ${[...IMPLEMENTED_SUBAGENT_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = SUBAGENT_ACTION_FIELDS[action as SubagentAction] as readonly string[];\n const unknown = Object.keys(record).filter((field) => !allowed.includes(field));\n if (unknown.length) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unknown.join(', ')}.`,\n 'Remove unknown fields and retry.',\n );\n }\n if (action === SUBAGENT_ACTIONS.run && (!Array.isArray(record.requests) || record.requests.length === 0)) {\n throw invalidRequest(\"action='run' requires a nonempty 'requests' array.\", 'Add at least one agent and task.');\n }\n if (action === SUBAGENT_ACTIONS.steer) {\n requireNonblank(record, 'id', action);\n requireNonblank(record, 'message', action);\n }\n if (action === SUBAGENT_ACTIONS.stop || action === SUBAGENT_ACTIONS.restore) requireNonblank(record, 'id', action);\n return raw as SubagentToolParams;\n}\n\nexport interface ISubagentToolService {\n registerTool(pi: ExtensionAPI): void;\n}\n\n@injectable()\nexport class SubagentToolService implements ISubagentToolService {\n private readonly registeredHosts = new WeakSet<ExtensionAPI>();\n\n constructor(\n @inject(DOOM_TEAM_TYPES.SpawnPlanner) private readonly planner: ISpawnPlanner,\n @inject(DOOM_TEAM_TYPES.ManagementActions) private readonly management: IManagementActions,\n @inject(DOOM_TEAM_TYPES.AsyncJobTracker) private readonly tracker: IAsyncJobTracker,\n @inject(DOOM_TEAM_TYPES.AgentDiscoveryService) private readonly discovery: IAgentDiscoveryService,\n ) {}\n\n registerTool(pi: ExtensionAPI): void {\n if (this.registeredHosts.has(pi)) return;\n if (hasTool(pi, SUBAGENT_TOOL_NAME)) {\n throw new DoomTeamExpectedError(\n 'tool_conflict',\n `A foreign '${SUBAGENT_TOOL_NAME}' tool is already registered.`,\n false,\n 'Disable the competing extension, then reload Doom Team.',\n );\n }\n pi.registerTool(this.buildTool());\n this.registeredHosts.add(pi);\n }\n\n private trackOutcomes(result: SpawnPlanResult, ctx: ExtensionContext): SpawnPlanResult {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n for (const outcome of result.outcomes) {\n if (outcome.runId) jobs.track(outcome.runId);\n }\n return result;\n }\n\n private buildSpawnRequest(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n preallocatedRunIds: string[],\n ): SpawnPlanRequest {\n const tasks = params.requests.map((request) => {\n if (!request.agent.trim() || !request.task.trim()) {\n throw invalidRequest(\n 'Every run request requires nonblank agent and task values.',\n 'Correct the request and retry.',\n );\n }\n return {\n agent: request.agent.trim(),\n ...(request.inlineAgent ? { inlineAgent: request.inlineAgent } : {}),\n task: request.task.trim(),\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.model ? { model: request.model } : {}),\n ...(request.runtime ? { runtime: request.runtime } : {}),\n };\n });\n const parentForkSource = captureSessionForkSource(ctx.sessionManager, 'tool');\n const parentModel = normalizeParentModel(ctx.model);\n return {\n tasks,\n cwd: ctx.cwd,\n agentScope: scopeOrDefault(params.scope),\n parentSessionId: ctx.sessionManager.getSessionId(),\n ...(parentForkSource\n ? { parentSessionFile: parentForkSource.sessionFile, parentLeafId: parentForkSource.leafId }\n : {}),\n ...(params.concurrency !== undefined ? { concurrency: params.concurrency } : {}),\n ...(params.artifacts !== undefined ? { artifacts: params.artifacts } : {}),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n operationId,\n preallocatedRunIds,\n };\n }\n\n private async executeRun(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n operationId,\n params,\n params.requests.map(() => randomUUID()),\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(', ')}.`,\n true,\n 'Call subagent({\"action\":\"status\"}) and do not submit the run again.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n this.buildSpawnRequest(operationId, params, ctx, operation.record.runIds),\n loadConfig().config,\n ),\n ctx,\n );\n const started = result.outcomes.filter((outcome) => outcome.runId);\n const failed = result.outcomes.filter((outcome) => !outcome.runId);\n const lines = result.outcomes.map(\n (outcome) =>\n `- ${outcome.agent}: ${outcome.runId ? `started as ${outcome.runId}` : `failed: ${outcome.error ?? 'unknown error'}`}${outcome.warning ? `\\n Warning: ${outcome.warning}` : ''}`,\n );\n if (started.length === 0 && failed.length > 0) {\n throw new DoomTeamExpectedError(\n 'runtime_unavailable',\n `No requested subagent started.\\n${lines.join('\\n')}`,\n true,\n 'Call subagent({\"action\":\"agents\"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.',\n );\n }\n const response = textResult(\n [\n `Run request: started ${started.length}/${result.outcomes.length} background agents; failed ${failed.length}.`,\n ...lines,\n ...(started.length > 0\n ? [\n '',\n `The subagent${started.length === 1 ? ' is' : 's are'} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`,\n ]\n : []),\n ...(failed.length > 0\n ? [\n '',\n 'Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.',\n ]\n : []),\n ].join('\\n'),\n { spawn: result, started: started.length, failed: failed.length },\n );\n completeOperation(operationId, operation.record, response);\n return response;\n }\n\n private executeAgents(\n params: Extract<SubagentToolParams, { action: 'agents' }>,\n ctx: ExtensionContext,\n ): AgentToolResult<SubagentToolDetails> {\n const cwd = params.cwd ?? ctx.cwd;\n const scope = scopeOrDefault(params.scope);\n if (!params.name) {\n const result = this.discovery.discover(cwd, scope);\n return textResult(formatAgentList(result.agents), { agents: result.agents.map(publicAgent) });\n }\n const agent = this.discovery.find(cwd, scope, params.name);\n if (!agent) {\n const candidates = this.discovery\n .discover(cwd, scope)\n .agents.map((candidate) => candidate.name)\n .toSorted();\n throw new DoomTeamExpectedError(\n 'agent_not_found',\n `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(', ')}.` : ''}`,\n false,\n 'Call subagent({\"action\":\"agents\"}) and retry with an exact name.',\n );\n }\n return textResult(formatAgentDetail(agent), { agent: publicAgent(agent) });\n }\n\n private async executeManagement(\n params: Exclude<SubagentToolParams, { action: 'run' } | { action: 'agents' }>,\n ctx: ExtensionContext,\n signal?: AbortSignal,\n preallocatedRunIds?: string[],\n operationId?: string,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n switch (params.action) {\n case SUBAGENT_ACTIONS.status: {\n const suspendedRuns = listSuspendedRuns(requireCurrentSessionScope());\n if (!('id' in params)) {\n if ('transcriptLines' in params && params.transcriptLines !== undefined) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const runs = jobs.list();\n return textResult(formatFleetView(runs, Date.now(), suspendedRuns), {\n fleet: runs,\n suspended: suspendedRuns.map(publicSuspendedRun),\n });\n }\n const runId = params.id;\n if (!runId) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const suspended = suspendedRuns.find((run) => run.runId === runId);\n if (suspended && params.transcriptLines === undefined) {\n const resumable = isSuspendedRunResumable(suspended);\n const recovery = resumable\n ? `Restore it with { action: \"restore\", id: \"${suspended.runId}\" }.`\n : 'It is not resumable; submit a new explicit run.';\n return textResult(`Run '${suspended.runId}' is suspended. ${recovery}`, {\n suspended: publicSuspendedRun(suspended),\n });\n }\n const result: StatusActionResult = this.management.status(runId);\n if (!result.runDir && !result.resultPath && !suspended) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No run matches '${runId}'.`,\n false,\n 'Call subagent({\"action\":\"status\"}) and retry with an exact id.',\n );\n }\n if (params.transcriptLines !== undefined) {\n return textResult(formatRunTranscript(result.status, params.transcriptLines ?? DEFAULT_TRANSCRIPT_LINES), {\n transcript: { runId: result.runId },\n });\n }\n return textResult(\n result.status ? `Run '${result.runId}': ${result.status.state}` : `Run '${result.runId}' has no status yet.`,\n { status: result },\n );\n }\n case SUBAGENT_ACTIONS.stop: {\n const id = resolveTrackedRunId(jobs, params.id);\n const result = this.management.stop(id, params.reason);\n return textResult(`Stop requested for '${id}'.`, { control: result });\n }\n case SUBAGENT_ACTIONS.steer: {\n const id = resolveTrackedRunId(jobs, params.id);\n const runtime = this.tracker.get(id)?.runtime;\n if (runtime && !isPiRuntime(runtime)) {\n throw new DoomTeamExpectedError(\n 'unsupported_operation',\n `Run '${id}' uses '${runtime}', which does not support steering.`,\n false,\n `Use subagent({\"action\":\"stop\",\"id\":\"${id}\"}) to terminate it.`,\n );\n }\n const result = await this.management.steer(id, params.message, undefined, signal);\n return textResult(`Steer request '${result.requestId}' for '${id}' is ${result.state}: ${result.message}`, {\n steer: result,\n });\n }\n case SUBAGENT_ACTIONS.suspended: {\n const runs = listSuspendedRuns(requireCurrentSessionScope());\n return textResult(runs.length ? formatSuspendedRuns(runs) : 'No suspended subagents in this session.', {\n suspended: runs.map(publicSuspendedRun),\n });\n }\n case SUBAGENT_ACTIONS.restore: {\n const scope = requireCurrentSessionScope();\n const record = listSuspendedRuns(scope).find((run) => run.runId === params.id);\n if (!record) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No suspended run matches '${params.id}'.`,\n false,\n 'Call subagent({\"action\":\"suspended\"}) and retry with an exact id.',\n );\n }\n if (!isSuspendedRunResumable(record)) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Suspended run '${params.id}' does not have complete, readable Pi recovery state.`,\n false,\n 'Submit a new explicit run request instead of restoring this record.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n {\n single: {\n agent: record.agent,\n ...(record.inlineAgent ? { inlineAgent: record.inlineAgent } : {}),\n task: record.task,\n cwd: record.cwd,\n ...(record.model ? { model: record.model } : {}),\n sessionFile: record.sessionFile,\n },\n cwd: record.cwd,\n agentScope: 'both',\n runtime: 'pi',\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(operationId ? { operationId } : {}),\n ...(preallocatedRunIds ? { preallocatedRunIds } : {}),\n },\n loadConfig().config,\n ),\n ctx,\n );\n const outcome = result.outcomes[0];\n if (!outcome?.runId) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Could not restore '${params.id}': ${outcome?.error ?? 'the spawn produced no run.'}`,\n true,\n 'Inspect suspended state, then submit a new explicit run if recovery is not possible.',\n );\n }\n clearSuspendedRun(scope, params.id);\n return textResult(`Restored '${params.id}' as '${outcome.runId}', continuing its transcript.`, {\n restore: { ...outcome, restoredFrom: params.id },\n });\n }\n }\n }\n\n private buildTool(): ToolDefinition<typeof SubagentParams, SubagentToolDetails> {\n return {\n name: SUBAGENT_TOOL_NAME,\n label: 'Subagent',\n description: SUBAGENT_TOOL_DESCRIPTION,\n parameters: SubagentParams,\n prepareArguments: validateParams,\n // Subagent output carries explicit lifecycle colors. Owning the shell keeps\n // Pi's broad pending/success/error backgrounds from washing out long lists.\n renderShell: 'self',\n renderCall: (rawParams, theme) => renderSubagentCall(validateParams(rawParams), theme),\n renderResult: (result, options, theme) => renderSubagentResult(result, options, theme),\n execute: async (id, rawParams, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentToolDetails>> => {\n const params = validateParams(rawParams);\n const progress = progressMessage(params);\n if (progress) onUpdate?.(progressResult(progress, params.action));\n if (params.action === SUBAGENT_ACTIONS.run) return this.executeRun(id, params, ctx);\n if (params.action === SUBAGENT_ACTIONS.agents) return this.executeAgents(params, ctx);\n const journaled =\n params.action === SUBAGENT_ACTIONS.steer ||\n params.action === SUBAGENT_ACTIONS.stop ||\n params.action === SUBAGENT_ACTIONS.restore;\n if (!journaled) return this.executeManagement(params, ctx, signal);\n\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n id,\n params,\n params.action === SUBAGENT_ACTIONS.restore ? [randomUUID()] : [],\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${id}' is already pending.`,\n true,\n 'Inspect run status before retrying this control operation.',\n );\n }\n const response = await this.executeManagement(params, ctx, signal, operation.record.runIds, id);\n completeOperation(id, operation.record, response);\n return response;\n },\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{__esmMin as e}from"../_virtual/_rolldown/runtime.mjs";import{agentHasWriteTools as t,init_memory as n}from"../services/agents/memory.mjs";import{__decorate as r,init_decorate as i}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs";import{DOOM_TEAM_TYPES as a,init_types as o}from"../container/types.mjs";import{__decorateMetadata as s,init_decorateMetadata as c}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.mjs";import{__decorateParam as l,init_decorateParam as u}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.mjs";import{init_paths as ee,requireCurrentSessionScope as d}from"../shared/paths.mjs";import{DoomTeamExpectedError as f,init_errors as p,invalidRequest as m}from"../shared/errors.mjs";import{authenticatedModelInfos as h,init_modelResolution as
|
|
2
|
-
`)}function K(e){let n=[...e.tools??[],...(e.mcpDirectTools??[]).map(e=>`mcp:${e}`)];return{name:e.name,source:e.source,description:e.description,runtime:e.runtime??`pi`,writeCapable:t(e),...e.model?{model:e.model}:{},...e.fallbackModels?.length?{fallbackModels:e.fallbackModels}:{},...n.length?{tools:n}:{}}}function q(e){return{...e,resumable:
|
|
3
|
-
`)}function J(e,t,n){if(typeof e[t]!=`string`||!e[t].trim())throw m(`action='${n}' requires nonblank '${t}'.`,`Correct the request and retry.`)}function
|
|
4
|
-
`)}`,!0,`Call subagent({"action":"agents"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.`);let c=
|
|
5
|
-
`),{spawn:i,started:a.length,failed:o.length});return E(e,r.record,c),c}executeAgents(e,t){let n=e.cwd??t.cwd,r=
|
|
1
|
+
import{__esmMin as e}from"../_virtual/_rolldown/runtime.mjs";import{agentHasWriteTools as t,init_memory as n}from"../services/agents/memory.mjs";import{__decorate as r,init_decorate as i}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs";import{DOOM_TEAM_TYPES as a,init_types as o}from"../container/types.mjs";import{__decorateMetadata as s,init_decorateMetadata as c}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.mjs";import{__decorateParam as l,init_decorateParam as u}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.mjs";import{init_paths as ee,requireCurrentSessionScope as d}from"../shared/paths.mjs";import{DoomTeamExpectedError as f,init_errors as p,invalidRequest as m}from"../shared/errors.mjs";import{authenticatedModelInfos as h,init_modelResolution as te}from"../shared/modelResolution.mjs";import{init_modelFallback as g,normalizeParentModel as _}from"../services/runs/shared/modelFallback.mjs";import{init_runtimeRegistry as v,isPiRuntime as ne}from"../services/runs/shared/runtimeRegistry.mjs";import{captureSessionForkSource as re,init_spawnPlan as y}from"./spawnPlan.mjs";import{resolveTrackedRunId as b}from"../adapters/asyncJobTracker.mjs";import{init_asyncJobTracker as x}from"../services/runs/background/asyncJobTracker.mjs";import{clearSuspendedRun as S,formatSuspendedRuns as ie,isSuspendedRunResumable as C,listSuspendedRuns as w}from"../adapters/suspendedRuns.mjs";import{init_suspendedRuns as ae}from"../services/runs/registry/suspendedRuns.mjs";import{init_subagentToolRender as oe,renderSubagentCall as se,renderSubagentResult as ce}from"../tui/subagentToolRender.mjs";import{init_config as le,loadConfig as T}from"./config.mjs";import{completeOperation as E,init_operationJournal as D,startOperation as O}from"./operationJournal.mjs";import{SUBAGENT_ACTIONS as k,SUBAGENT_ACTION_FIELDS as A,SubagentParams as j,init_schemas as M}from"./schemas.mjs";import{formatFleetView as N,formatRunTranscript as P,init_statusViews as F}from"./statusViews.mjs";import{SUBAGENT_TOOL_DESCRIPTION as I,init_toolDescription as L}from"./toolDescription.mjs";import{inject as R,injectable as z}from"inversify";import{randomUUID as B}from"node:crypto";function V(e,t){return{content:[{type:`text`,text:e}],details:t}}function H(e,t){return V(e,{action:t,partial:!0})}function U(e){switch(e.action){case k.run:return`Starting ${e.requests.length} subagent${e.requests.length===1?``:`s`}...`;case k.steer:return`Steering subagent ${e.id}...`;case k.stop:return`Requesting stop for subagent ${e.id}...`;case k.restore:return`Restoring subagent ${e.id}...`;default:return}}function W(e,t){try{return e.getAllTools().some(e=>e.name===t)}catch{return!1}}function G(e){return e??`both`}function ue(e){return[`Executable agents:`,...e.length?e.toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>`- ${e.name} (${e.source}): ${e.description}`):[`- (none)`]].join(`
|
|
2
|
+
`)}function K(e){let n=[...e.tools??[],...(e.mcpDirectTools??[]).map(e=>`mcp:${e}`)];return{name:e.name,source:e.source,description:e.description,runtime:e.runtime??`pi`,writeCapable:t(e),...e.model?{model:e.model}:{},...e.fallbackModels?.length?{fallbackModels:e.fallbackModels}:{},...n.length?{tools:n}:{}}}function q(e){return{...e,resumable:C(e)}}function de(e){let t=K(e);return[`Agent: ${e.name} (${e.source})`,`Description: ${e.description}`,`Runtime: ${String(t.runtime)}`,`Write capable: ${t.writeCapable?`yes`:`no`}`,...e.model?[`Model: ${e.model}`]:[],...Array.isArray(t.tools)?[`Tools: ${t.tools.join(`, `)}`]:[]].join(`
|
|
3
|
+
`)}function J(e,t,n){if(typeof e[t]!=`string`||!e[t].trim())throw m(`action='${n}' requires nonblank '${t}'.`,`Correct the request and retry.`)}function fe(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;if(typeof t.action!=`string`||!Z.has(t.action)||t.action===k.run||typeof t.model!=`string`)return e;let{model:n,...r}=t;return r}function Y(e){let t=fe(e);if(!t||typeof t!=`object`||Array.isArray(t))throw m(`subagent parameters must be an object.`,`Call subagent with one documented action shape.`);let n=t,r=n.action;if(typeof r!=`string`||!Z.has(r))throw m(`Unsupported or missing subagent action ${JSON.stringify(r)}.`,`Use one of: ${[...Z].join(`, `)}.`);let i=A[r],a=Object.keys(n).filter(e=>!i.includes(e));if(a.length)throw m(`action='${r}' does not accept: ${a.join(`, `)}.`,`Remove unknown fields and retry.`);if(r===k.run&&(!Array.isArray(n.requests)||n.requests.length===0))throw m(`action='run' requires a nonempty 'requests' array.`,`Add at least one agent and task.`);return r===k.steer&&(J(n,`id`,r),J(n,`message`,r)),(r===k.stop||r===k.restore)&&J(n,`id`,r),t}var X,Z,Q,$=e((()=>{o(),n(),x(),ae(),g(),v(),p(),te(),ee(),oe(),le(),D(),M(),y(),F(),L(),c(),u(),i(),X=`subagent`,Z=new Set(Object.values(k)),Q=class{registeredHosts=new WeakSet;constructor(e,t,n,r){this.planner=e,this.management=t,this.tracker=n,this.discovery=r}registerTool(e){if(!this.registeredHosts.has(e)){if(W(e,`subagent`))throw new f(`tool_conflict`,`A foreign '${X}' tool is already registered.`,!1,`Disable the competing extension, then reload Doom Team.`);e.registerTool(this.buildTool()),this.registeredHosts.add(e)}}trackOutcomes(e,t){let n=this.tracker.forSession(t.sessionManager.getSessionId());for(let t of e.outcomes)t.runId&&n.track(t.runId);return e}buildSpawnRequest(e,t,n,r){let i=t.requests.map(e=>{if(!e.agent.trim()||!e.task.trim())throw m(`Every run request requires nonblank agent and task values.`,`Correct the request and retry.`);return{agent:e.agent.trim(),...e.inlineAgent?{inlineAgent:e.inlineAgent}:{},task:e.task.trim(),...e.cwd?{cwd:e.cwd}:{},...e.model?{model:e.model}:{},...e.runtime?{runtime:e.runtime}:{}}}),a=re(n.sessionManager,`tool`),o=_(n.model);return{tasks:i,cwd:n.cwd,agentScope:G(t.scope),parentSessionId:n.sessionManager.getSessionId(),...a?{parentSessionFile:a.sessionFile,parentLeafId:a.leafId}:{},...t.concurrency===void 0?{}:{concurrency:t.concurrency},...t.artifacts===void 0?{}:{artifacts:t.artifacts},availableModels:h(n.modelRegistry),...o?{parentModel:o}:{},operationId:e,preallocatedRunIds:r}}async executeRun(e,t,n){let r=O(e,t,t.requests.map(()=>B()));if(r.kind===`replay`){if(r.record.state===`completed`&&r.record.result)return r.record.result;throw new f(`delivery_unconfirmed`,`Operation '${e}' is already pending for runs: ${r.record.runIds.join(`, `)}.`,!0,`Call subagent({"action":"status"}) and do not submit the run again.`)}let i=this.trackOutcomes(await this.planner.spawn(this.buildSpawnRequest(e,t,n,r.record.runIds),T().config),n),a=i.outcomes.filter(e=>e.runId),o=i.outcomes.filter(e=>!e.runId),s=i.outcomes.map(e=>`- ${e.agent}: ${e.runId?`started as ${e.runId}`:`failed: ${e.error??`unknown error`}`}${e.warning?`\n Warning: ${e.warning}`:``}`);if(a.length===0&&o.length>0)throw new f(`runtime_unavailable`,`No requested subagent started.\n${s.join(`
|
|
4
|
+
`)}`,!0,`Call subagent({"action":"agents"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.`);let c=V([`Run request: started ${a.length}/${i.outcomes.length} background agents; failed ${o.length}.`,...s,...a.length>0?[``,`The subagent${a.length===1?` is`:`s are`} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`]:[],...o.length>0?[``,`Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.`]:[]].join(`
|
|
5
|
+
`),{spawn:i,started:a.length,failed:o.length});return E(e,r.record,c),c}executeAgents(e,t){let n=e.cwd??t.cwd,r=G(e.scope);if(!e.name){let e=this.discovery.discover(n,r);return V(ue(e.agents),{agents:e.agents.map(K)})}let i=this.discovery.find(n,r,e.name);if(!i){let t=this.discovery.discover(n,r).agents.map(e=>e.name).toSorted();throw new f(`agent_not_found`,`No executable agent matches '${e.name}'.${t.length?` Available: ${t.join(`, `)}.`:``}`,!1,`Call subagent({"action":"agents"}) and retry with an exact name.`)}return V(de(i),{agent:K(i)})}async executeManagement(e,t,n,r,i){let a=this.tracker.forSession(t.sessionManager.getSessionId());switch(e.action){case k.status:{let t=w(d());if(!(`id`in e)){if(`transcriptLines`in e&&e.transcriptLines!==void 0)throw m(`transcriptLines requires a run id.`,`Add id or omit transcriptLines for fleet status.`);let n=a.list();return V(N(n,Date.now(),t),{fleet:n,suspended:t.map(q)})}let n=e.id;if(!n)throw m(`transcriptLines requires a run id.`,`Add id or omit transcriptLines for fleet status.`);let r=t.find(e=>e.runId===n);if(r&&e.transcriptLines===void 0){let e=C(r)?`Restore it with { action: "restore", id: "${r.runId}" }.`:`It is not resumable; submit a new explicit run.`;return V(`Run '${r.runId}' is suspended. ${e}`,{suspended:q(r)})}let i=this.management.status(n);if(!i.runDir&&!i.resultPath&&!r)throw new f(`run_not_found`,`No run matches '${n}'.`,!1,`Call subagent({"action":"status"}) and retry with an exact id.`);return e.transcriptLines===void 0?V(i.status?`Run '${i.runId}': ${i.status.state}`:`Run '${i.runId}' has no status yet.`,{status:i}):V(P(i.status,e.transcriptLines??80),{transcript:{runId:i.runId}})}case k.stop:{let t=b(a,e.id),n=this.management.stop(t,e.reason);return V(`Stop requested for '${t}'.`,{control:n})}case k.steer:{let t=b(a,e.id),r=this.tracker.get(t)?.runtime;if(r&&!ne(r))throw new f(`unsupported_operation`,`Run '${t}' uses '${r}', which does not support steering.`,!1,`Use subagent({"action":"stop","id":"${t}"}) to terminate it.`);let i=await this.management.steer(t,e.message,void 0,n);return V(`Steer request '${i.requestId}' for '${t}' is ${i.state}: ${i.message}`,{steer:i})}case k.suspended:{let e=w(d());return V(e.length?ie(e):`No suspended subagents in this session.`,{suspended:e.map(q)})}case k.restore:{let n=d(),a=w(n).find(t=>t.runId===e.id);if(!a)throw new f(`run_not_found`,`No suspended run matches '${e.id}'.`,!1,`Call subagent({"action":"suspended"}) and retry with an exact id.`);if(!C(a))throw new f(`not_resumable`,`Suspended run '${e.id}' does not have complete, readable Pi recovery state.`,!1,`Submit a new explicit run request instead of restoring this record.`);let o=this.trackOutcomes(await this.planner.spawn({single:{agent:a.agent,...a.inlineAgent?{inlineAgent:a.inlineAgent}:{},task:a.task,cwd:a.cwd,...a.model?{model:a.model}:{},sessionFile:a.sessionFile},cwd:a.cwd,agentScope:`both`,runtime:`pi`,availableModels:h(t.modelRegistry),...i?{operationId:i}:{},...r?{preallocatedRunIds:r}:{}},T().config),t).outcomes[0];if(!o?.runId)throw new f(`not_resumable`,`Could not restore '${e.id}': ${o?.error??`the spawn produced no run.`}`,!0,`Inspect suspended state, then submit a new explicit run if recovery is not possible.`);return S(n,e.id),V(`Restored '${e.id}' as '${o.runId}', continuing its transcript.`,{restore:{...o,restoredFrom:e.id}})}}}buildTool(){return{name:X,label:`Subagent`,description:I,parameters:j,prepareArguments:Y,renderShell:`self`,renderCall:(e,t)=>se(Y(e),t),renderResult:(e,t,n)=>ce(e,t,n),execute:async(e,t,n,r,i)=>{let a=Y(t),o=U(a);if(o&&r?.(H(o,a.action)),a.action===k.run)return this.executeRun(e,a,i);if(a.action===k.agents)return this.executeAgents(a,i);if(!(a.action===k.steer||a.action===k.stop||a.action===k.restore))return this.executeManagement(a,i,n);let s=O(e,a,a.action===k.restore?[B()]:[]);if(s.kind===`replay`){if(s.record.state===`completed`&&s.record.result)return s.record.result;throw new f(`delivery_unconfirmed`,`Operation '${e}' is already pending.`,!0,`Inspect run status before retrying this control operation.`)}let c=await this.executeManagement(a,i,n,s.record.runIds,e);return E(e,s.record,c),c}}}},Q=r([z(),l(0,R(a.SpawnPlanner)),l(1,R(a.ManagementActions)),l(2,R(a.AsyncJobTracker)),l(3,R(a.AgentDiscoveryService)),s(`design:paramtypes`,[Object,Object,Object,Object])],Q)}));$();export{Q as SubagentToolService,$ as init_subagentTool};
|
|
6
6
|
//# sourceMappingURL=subagentTool.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentTool.mjs","names":[],"sources":["../../src/extensions/subagentTool.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { agentHasWriteTools } from '../services/agents/memory.ts';\nimport type { AgentConfig, AgentScope, IAgentDiscoveryService } from '../services/agents/types.ts';\nimport { type IAsyncJobTracker, resolveTrackedRunId } from '../services/runs/background/asyncJobTracker.ts';\nimport {\n clearSuspendedRun,\n formatSuspendedRuns,\n isSuspendedRunResumable,\n listSuspendedRuns,\n type SuspendedRun,\n} from '../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../services/runs/shared/modelFallback.ts';\nimport { isPiRuntime } from '../services/runs/shared/runtimeRegistry.ts';\nimport { DoomTeamExpectedError, invalidRequest } from '../shared/errors.ts';\nimport { authenticatedModelInfos } from '../shared/modelResolution.ts';\nimport { requireCurrentSessionScope } from '../shared/paths.ts';\nimport { loadConfig } from './config.ts';\nimport type { IManagementActions, StatusActionResult } from './managementActions.ts';\nimport { completeOperation, startOperation } from './operationJournal.ts';\nimport {\n SUBAGENT_ACTION_FIELDS,\n SUBAGENT_ACTIONS,\n type SubagentAction,\n SubagentParams,\n type SubagentToolParams,\n} from './schemas.ts';\nimport {\n captureSessionForkSource,\n type ISpawnPlanner,\n type SpawnPlanRequest,\n type SpawnPlanResult,\n} from './spawnPlan.ts';\nimport { DEFAULT_TRANSCRIPT_LINES, formatFleetView, formatRunTranscript } from './statusViews.ts';\nimport { SUBAGENT_TOOL_DESCRIPTION } from './toolDescription.ts';\n\nexport const SUBAGENT_TOOL_NAME = 'subagent';\nexport const IMPLEMENTED_SUBAGENT_ACTIONS: ReadonlySet<string> = new Set(Object.values(SUBAGENT_ACTIONS));\n\ntype SubagentToolDetails = Record<string, unknown>;\n\nfunction textResult<T extends SubagentToolDetails>(text: string, details: T): AgentToolResult<T> {\n return { content: [{ type: 'text', text }], details };\n}\n\nfunction progressResult(text: string, action: SubagentAction): AgentToolResult<SubagentToolDetails> {\n return textResult(text, { action, partial: true });\n}\n\nfunction progressMessage(params: SubagentToolParams): string | undefined {\n switch (params.action) {\n case SUBAGENT_ACTIONS.run:\n return `Starting ${params.requests.length} subagent${params.requests.length === 1 ? '' : 's'}...`;\n case SUBAGENT_ACTIONS.steer:\n return `Steering subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.stop:\n return `Requesting stop for subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.restore:\n return `Restoring subagent ${params.id}...`;\n default:\n return undefined;\n }\n}\n\nfunction hasTool(pi: ExtensionAPI, name: string): boolean {\n try {\n return pi.getAllTools().some((tool) => tool.name === name);\n } catch {\n return false;\n }\n}\n\nfunction scopeOrDefault(scope: AgentScope | undefined): AgentScope {\n return scope ?? 'both';\n}\n\nfunction formatAgentList(agents: AgentConfig[]): string {\n return [\n 'Executable agents:',\n ...(agents.length\n ? agents\n .toSorted((left, right) => left.name.localeCompare(right.name))\n .map((agent) => `- ${agent.name} (${agent.source}): ${agent.description}`)\n : ['- (none)']),\n ].join('\\n');\n}\n\nfunction publicAgent(agent: AgentConfig): Record<string, unknown> {\n const tools = [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((tool) => `mcp:${tool}`)];\n return {\n name: agent.name,\n source: agent.source,\n description: agent.description,\n runtime: agent.runtime ?? 'pi',\n writeCapable: agentHasWriteTools(agent),\n ...(agent.model ? { model: agent.model } : {}),\n ...(agent.fallbackModels?.length ? { fallbackModels: agent.fallbackModels } : {}),\n ...(tools.length ? { tools } : {}),\n };\n}\n\nfunction publicSuspendedRun(run: SuspendedRun): SuspendedRun & { resumable: boolean } {\n return { ...run, resumable: isSuspendedRunResumable(run) };\n}\n\nfunction formatAgentDetail(agent: AgentConfig): string {\n const detail = publicAgent(agent);\n return [\n `Agent: ${agent.name} (${agent.source})`,\n `Description: ${agent.description}`,\n `Runtime: ${String(detail.runtime)}`,\n `Write capable: ${detail.writeCapable ? 'yes' : 'no'}`,\n ...(agent.model ? [`Model: ${agent.model}`] : []),\n ...(Array.isArray(detail.tools) ? [`Tools: ${detail.tools.join(', ')}`] : []),\n ].join('\\n');\n}\n\nfunction requireNonblank(record: Record<string, unknown>, field: string, action: string): void {\n if (typeof record[field] !== 'string' || !record[field].trim()) {\n throw invalidRequest(`action='${action}' requires nonblank '${field}'.`, 'Correct the request and retry.');\n }\n}\n\n/** Remove the one legacy field emitted by Doom Plan before strict validation. */\nfunction normalizeCompatibilityParams(raw: unknown): unknown {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return raw;\n const record = raw as Record<string, unknown>;\n if (\n typeof record.action !== 'string' ||\n !IMPLEMENTED_SUBAGENT_ACTIONS.has(record.action) ||\n record.action === SUBAGENT_ACTIONS.run ||\n typeof record.model !== 'string'\n ) {\n return raw;\n }\n const { model: _model, ...normalized } = record;\n return normalized;\n}\n\nfunction validateParams(input: unknown): SubagentToolParams {\n const raw = normalizeCompatibilityParams(input);\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n throw invalidRequest('subagent parameters must be an object.', 'Call subagent with one documented action shape.');\n }\n const record = raw as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_SUBAGENT_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unsupported or missing subagent action ${JSON.stringify(action)}.`,\n `Use one of: ${[...IMPLEMENTED_SUBAGENT_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = SUBAGENT_ACTION_FIELDS[action as SubagentAction] as readonly string[];\n const unknown = Object.keys(record).filter((field) => !allowed.includes(field));\n if (unknown.length) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unknown.join(', ')}.`,\n 'Remove unknown fields and retry.',\n );\n }\n if (action === 'run' && (!Array.isArray(record.requests) || record.requests.length === 0)) {\n throw invalidRequest(\"action='run' requires a nonempty 'requests' array.\", 'Add at least one agent and task.');\n }\n if (action === 'steer') {\n requireNonblank(record, 'id', action);\n requireNonblank(record, 'message', action);\n }\n if (action === 'stop' || action === 'restore') requireNonblank(record, 'id', action);\n return raw as SubagentToolParams;\n}\n\nexport interface ISubagentToolService {\n registerTool(pi: ExtensionAPI): void;\n}\n\n@injectable()\nexport class SubagentToolService implements ISubagentToolService {\n private readonly registeredHosts = new WeakSet<ExtensionAPI>();\n\n constructor(\n @inject(DOOM_TEAM_TYPES.SpawnPlanner) private readonly planner: ISpawnPlanner,\n @inject(DOOM_TEAM_TYPES.ManagementActions) private readonly management: IManagementActions,\n @inject(DOOM_TEAM_TYPES.AsyncJobTracker) private readonly tracker: IAsyncJobTracker,\n @inject(DOOM_TEAM_TYPES.AgentDiscoveryService) private readonly discovery: IAgentDiscoveryService,\n ) {}\n\n registerTool(pi: ExtensionAPI): void {\n if (this.registeredHosts.has(pi)) return;\n if (hasTool(pi, SUBAGENT_TOOL_NAME)) {\n throw new DoomTeamExpectedError(\n 'tool_conflict',\n `A foreign '${SUBAGENT_TOOL_NAME}' tool is already registered.`,\n false,\n 'Disable the competing extension, then reload Doom Team.',\n );\n }\n pi.registerTool(this.buildTool());\n this.registeredHosts.add(pi);\n }\n\n private trackOutcomes(result: SpawnPlanResult, ctx: ExtensionContext): SpawnPlanResult {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n for (const outcome of result.outcomes) {\n if (outcome.runId) jobs.track(outcome.runId);\n }\n return result;\n }\n\n private buildSpawnRequest(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n preallocatedRunIds: string[],\n ): SpawnPlanRequest {\n const tasks = params.requests.map((request) => {\n if (!request.agent.trim() || !request.task.trim()) {\n throw invalidRequest(\n 'Every run request requires nonblank agent and task values.',\n 'Correct the request and retry.',\n );\n }\n return {\n agent: request.agent.trim(),\n ...(request.inlineAgent ? { inlineAgent: request.inlineAgent } : {}),\n task: request.task.trim(),\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.model ? { model: request.model } : {}),\n ...(request.runtime ? { runtime: request.runtime } : {}),\n };\n });\n const parentForkSource = captureSessionForkSource(ctx.sessionManager, 'tool');\n const parentModel = normalizeParentModel(ctx.model);\n return {\n tasks,\n cwd: ctx.cwd,\n agentScope: scopeOrDefault(params.scope),\n parentSessionId: ctx.sessionManager.getSessionId(),\n ...(parentForkSource\n ? { parentSessionFile: parentForkSource.sessionFile, parentLeafId: parentForkSource.leafId }\n : {}),\n ...(params.concurrency !== undefined ? { concurrency: params.concurrency } : {}),\n ...(params.artifacts !== undefined ? { artifacts: params.artifacts } : {}),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n operationId,\n preallocatedRunIds,\n };\n }\n\n private async executeRun(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n operationId,\n params,\n params.requests.map(() => randomUUID()),\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(', ')}.`,\n true,\n 'Call subagent({\"action\":\"status\"}) and do not submit the run again.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n this.buildSpawnRequest(operationId, params, ctx, operation.record.runIds),\n loadConfig().config,\n ),\n ctx,\n );\n const started = result.outcomes.filter((outcome) => outcome.runId);\n const failed = result.outcomes.filter((outcome) => !outcome.runId);\n const lines = result.outcomes.map(\n (outcome) =>\n `- ${outcome.agent}: ${outcome.runId ? `started as ${outcome.runId}` : `failed: ${outcome.error ?? 'unknown error'}`}${outcome.warning ? `\\n Warning: ${outcome.warning}` : ''}`,\n );\n if (started.length === 0 && failed.length > 0) {\n throw new DoomTeamExpectedError(\n 'runtime_unavailable',\n `No requested subagent started.\\n${lines.join('\\n')}`,\n true,\n 'Call subagent({\"action\":\"agents\"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.',\n );\n }\n const response = textResult(\n [\n `Run request: started ${started.length}/${result.outcomes.length} background agents; failed ${failed.length}.`,\n ...lines,\n ...(started.length > 0\n ? [\n '',\n `The subagent${started.length === 1 ? ' is' : 's are'} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`,\n ]\n : []),\n ...(failed.length > 0\n ? [\n '',\n 'Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.',\n ]\n : []),\n ].join('\\n'),\n { spawn: result, started: started.length, failed: failed.length },\n );\n completeOperation(operationId, operation.record, response);\n return response;\n }\n\n private executeAgents(\n params: Extract<SubagentToolParams, { action: 'agents' }>,\n ctx: ExtensionContext,\n ): AgentToolResult<SubagentToolDetails> {\n const cwd = params.cwd ?? ctx.cwd;\n const scope = scopeOrDefault(params.scope);\n if (!params.name) {\n const result = this.discovery.discover(cwd, scope);\n return textResult(formatAgentList(result.agents), { agents: result.agents.map(publicAgent) });\n }\n const agent = this.discovery.find(cwd, scope, params.name);\n if (!agent) {\n const candidates = this.discovery\n .discover(cwd, scope)\n .agents.map((candidate) => candidate.name)\n .toSorted();\n throw new DoomTeamExpectedError(\n 'agent_not_found',\n `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(', ')}.` : ''}`,\n false,\n 'Call subagent({\"action\":\"agents\"}) and retry with an exact name.',\n );\n }\n return textResult(formatAgentDetail(agent), { agent: publicAgent(agent) });\n }\n\n private async executeManagement(\n params: Exclude<SubagentToolParams, { action: 'run' } | { action: 'agents' }>,\n ctx: ExtensionContext,\n signal?: AbortSignal,\n preallocatedRunIds?: string[],\n operationId?: string,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n switch (params.action) {\n case SUBAGENT_ACTIONS.status: {\n const suspendedRuns = listSuspendedRuns(requireCurrentSessionScope());\n if (!('id' in params)) {\n if ('transcriptLines' in params && params.transcriptLines !== undefined) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const runs = jobs.list();\n return textResult(formatFleetView(runs, Date.now(), suspendedRuns), {\n fleet: runs,\n suspended: suspendedRuns.map(publicSuspendedRun),\n });\n }\n const runId = params.id;\n if (!runId) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const suspended = suspendedRuns.find((run) => run.runId === runId);\n if (suspended && params.transcriptLines === undefined) {\n const resumable = isSuspendedRunResumable(suspended);\n const recovery = resumable\n ? `Restore it with { action: \"restore\", id: \"${suspended.runId}\" }.`\n : 'It is not resumable; submit a new explicit run.';\n return textResult(`Run '${suspended.runId}' is suspended. ${recovery}`, {\n suspended: publicSuspendedRun(suspended),\n });\n }\n const result: StatusActionResult = this.management.status(runId);\n if (!result.runDir && !result.resultPath && !suspended) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No run matches '${runId}'.`,\n false,\n 'Call subagent({\"action\":\"status\"}) and retry with an exact id.',\n );\n }\n if (params.transcriptLines !== undefined) {\n return textResult(formatRunTranscript(result.status, params.transcriptLines ?? DEFAULT_TRANSCRIPT_LINES), {\n transcript: { runId: result.runId },\n });\n }\n return textResult(\n result.status ? `Run '${result.runId}': ${result.status.state}` : `Run '${result.runId}' has no status yet.`,\n { status: result },\n );\n }\n case SUBAGENT_ACTIONS.stop: {\n const id = resolveTrackedRunId(jobs, params.id);\n const result = this.management.stop(id, params.reason);\n return textResult(`Stop requested for '${id}'.`, { control: result });\n }\n case SUBAGENT_ACTIONS.steer: {\n const id = resolveTrackedRunId(jobs, params.id);\n const runtime = this.tracker.get(id)?.runtime;\n if (runtime && !isPiRuntime(runtime)) {\n throw new DoomTeamExpectedError(\n 'unsupported_operation',\n `Run '${id}' uses '${runtime}', which does not support steering.`,\n false,\n `Use subagent({\"action\":\"stop\",\"id\":\"${id}\"}) to terminate it.`,\n );\n }\n const result = await this.management.steer(id, params.message, undefined, signal);\n return textResult(`Steer request '${result.requestId}' for '${id}' is ${result.state}: ${result.message}`, {\n steer: result,\n });\n }\n case SUBAGENT_ACTIONS.suspended: {\n const runs = listSuspendedRuns(requireCurrentSessionScope());\n return textResult(runs.length ? formatSuspendedRuns(runs) : 'No suspended subagents in this session.', {\n suspended: runs.map(publicSuspendedRun),\n });\n }\n case SUBAGENT_ACTIONS.restore: {\n const scope = requireCurrentSessionScope();\n const record = listSuspendedRuns(scope).find((run) => run.runId === params.id);\n if (!record) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No suspended run matches '${params.id}'.`,\n false,\n 'Call subagent({\"action\":\"suspended\"}) and retry with an exact id.',\n );\n }\n if (!isSuspendedRunResumable(record)) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Suspended run '${params.id}' does not have complete, readable Pi recovery state.`,\n false,\n 'Submit a new explicit run request instead of restoring this record.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n {\n single: {\n agent: record.agent,\n ...(record.inlineAgent ? { inlineAgent: record.inlineAgent } : {}),\n task: record.task,\n cwd: record.cwd,\n ...(record.model ? { model: record.model } : {}),\n sessionFile: record.sessionFile,\n },\n cwd: record.cwd,\n agentScope: 'both',\n runtime: 'pi',\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(operationId ? { operationId } : {}),\n ...(preallocatedRunIds ? { preallocatedRunIds } : {}),\n },\n loadConfig().config,\n ),\n ctx,\n );\n const outcome = result.outcomes[0];\n if (!outcome?.runId) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Could not restore '${params.id}': ${outcome?.error ?? 'the spawn produced no run.'}`,\n true,\n 'Inspect suspended state, then submit a new explicit run if recovery is not possible.',\n );\n }\n clearSuspendedRun(scope, params.id);\n return textResult(`Restored '${params.id}' as '${outcome.runId}', continuing its transcript.`, {\n restore: { ...outcome, restoredFrom: params.id },\n });\n }\n }\n }\n\n private buildTool(): ToolDefinition<typeof SubagentParams, SubagentToolDetails> {\n return {\n name: SUBAGENT_TOOL_NAME,\n label: 'Subagent',\n description: SUBAGENT_TOOL_DESCRIPTION,\n parameters: SubagentParams,\n prepareArguments: validateParams,\n execute: async (id, rawParams, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentToolDetails>> => {\n const params = validateParams(rawParams);\n const progress = progressMessage(params);\n if (progress) onUpdate?.(progressResult(progress, params.action));\n if (params.action === SUBAGENT_ACTIONS.run) return this.executeRun(id, params, ctx);\n if (params.action === SUBAGENT_ACTIONS.agents) return this.executeAgents(params, ctx);\n const journaled =\n params.action === SUBAGENT_ACTIONS.steer ||\n params.action === SUBAGENT_ACTIONS.stop ||\n params.action === SUBAGENT_ACTIONS.restore;\n if (!journaled) return this.executeManagement(params, ctx, signal);\n\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n id,\n params,\n params.action === SUBAGENT_ACTIONS.restore ? [randomUUID()] : [],\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${id}' is already pending.`,\n true,\n 'Inspect run status before retrying this control operation.',\n );\n }\n const response = await this.executeManagement(params, ctx, signal, operation.record.runIds, id);\n completeOperation(id, operation.record, response);\n return response;\n },\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"subagentTool.mjs","names":[],"sources":["../../src/extensions/subagentTool.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { agentHasWriteTools } from '../services/agents/memory.ts';\nimport type { AgentConfig, AgentScope, IAgentDiscoveryService } from '../services/agents/types.ts';\nimport { type IAsyncJobTracker, resolveTrackedRunId } from '../services/runs/background/asyncJobTracker.ts';\nimport {\n clearSuspendedRun,\n formatSuspendedRuns,\n isSuspendedRunResumable,\n listSuspendedRuns,\n type SuspendedRun,\n} from '../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../services/runs/shared/modelFallback.ts';\nimport { isPiRuntime } from '../services/runs/shared/runtimeRegistry.ts';\nimport { DoomTeamExpectedError, invalidRequest } from '../shared/errors.ts';\nimport { authenticatedModelInfos } from '../shared/modelResolution.ts';\nimport { requireCurrentSessionScope } from '../shared/paths.ts';\nimport { renderSubagentCall, renderSubagentResult } from '../tui/subagentToolRender.ts';\nimport { loadConfig } from './config.ts';\nimport type { IManagementActions, StatusActionResult } from './managementActions.ts';\nimport { completeOperation, startOperation } from './operationJournal.ts';\nimport {\n SUBAGENT_ACTION_FIELDS,\n SUBAGENT_ACTIONS,\n type SubagentAction,\n SubagentParams,\n type SubagentToolParams,\n} from './schemas.ts';\nimport {\n captureSessionForkSource,\n type ISpawnPlanner,\n type SpawnPlanRequest,\n type SpawnPlanResult,\n} from './spawnPlan.ts';\nimport { DEFAULT_TRANSCRIPT_LINES, formatFleetView, formatRunTranscript } from './statusViews.ts';\nimport { SUBAGENT_TOOL_DESCRIPTION } from './toolDescription.ts';\n\nexport const SUBAGENT_TOOL_NAME = 'subagent';\nexport const IMPLEMENTED_SUBAGENT_ACTIONS: ReadonlySet<string> = new Set(Object.values(SUBAGENT_ACTIONS));\n\ntype SubagentToolDetails = Record<string, unknown>;\n\nfunction textResult<T extends SubagentToolDetails>(text: string, details: T): AgentToolResult<T> {\n return { content: [{ type: 'text', text }], details };\n}\n\nfunction progressResult(text: string, action: SubagentAction): AgentToolResult<SubagentToolDetails> {\n return textResult(text, { action, partial: true });\n}\n\nfunction progressMessage(params: SubagentToolParams): string | undefined {\n switch (params.action) {\n case SUBAGENT_ACTIONS.run:\n return `Starting ${params.requests.length} subagent${params.requests.length === 1 ? '' : 's'}...`;\n case SUBAGENT_ACTIONS.steer:\n return `Steering subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.stop:\n return `Requesting stop for subagent ${params.id}...`;\n case SUBAGENT_ACTIONS.restore:\n return `Restoring subagent ${params.id}...`;\n default:\n return undefined;\n }\n}\n\nfunction hasTool(pi: ExtensionAPI, name: string): boolean {\n try {\n return pi.getAllTools().some((tool) => tool.name === name);\n } catch {\n return false;\n }\n}\n\nfunction scopeOrDefault(scope: AgentScope | undefined): AgentScope {\n return scope ?? 'both';\n}\n\nfunction formatAgentList(agents: AgentConfig[]): string {\n return [\n 'Executable agents:',\n ...(agents.length\n ? agents\n .toSorted((left, right) => left.name.localeCompare(right.name))\n .map((agent) => `- ${agent.name} (${agent.source}): ${agent.description}`)\n : ['- (none)']),\n ].join('\\n');\n}\n\nfunction publicAgent(agent: AgentConfig): Record<string, unknown> {\n const tools = [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((tool) => `mcp:${tool}`)];\n return {\n name: agent.name,\n source: agent.source,\n description: agent.description,\n runtime: agent.runtime ?? 'pi',\n writeCapable: agentHasWriteTools(agent),\n ...(agent.model ? { model: agent.model } : {}),\n ...(agent.fallbackModels?.length ? { fallbackModels: agent.fallbackModels } : {}),\n ...(tools.length ? { tools } : {}),\n };\n}\n\nfunction publicSuspendedRun(run: SuspendedRun): SuspendedRun & { resumable: boolean } {\n return { ...run, resumable: isSuspendedRunResumable(run) };\n}\n\nfunction formatAgentDetail(agent: AgentConfig): string {\n const detail = publicAgent(agent);\n return [\n `Agent: ${agent.name} (${agent.source})`,\n `Description: ${agent.description}`,\n `Runtime: ${String(detail.runtime)}`,\n `Write capable: ${detail.writeCapable ? 'yes' : 'no'}`,\n ...(agent.model ? [`Model: ${agent.model}`] : []),\n ...(Array.isArray(detail.tools) ? [`Tools: ${detail.tools.join(', ')}`] : []),\n ].join('\\n');\n}\n\nfunction requireNonblank(record: Record<string, unknown>, field: string, action: string): void {\n if (typeof record[field] !== 'string' || !record[field].trim()) {\n throw invalidRequest(`action='${action}' requires nonblank '${field}'.`, 'Correct the request and retry.');\n }\n}\n\n/** Remove the one legacy field emitted by Doom Plan before strict validation. */\nfunction normalizeCompatibilityParams(raw: unknown): unknown {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return raw;\n const record = raw as Record<string, unknown>;\n if (\n typeof record.action !== 'string' ||\n !IMPLEMENTED_SUBAGENT_ACTIONS.has(record.action) ||\n record.action === SUBAGENT_ACTIONS.run ||\n typeof record.model !== 'string'\n ) {\n return raw;\n }\n const { model: _model, ...normalized } = record;\n return normalized;\n}\n\nfunction validateParams(input: unknown): SubagentToolParams {\n const raw = normalizeCompatibilityParams(input);\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n throw invalidRequest('subagent parameters must be an object.', 'Call subagent with one documented action shape.');\n }\n const record = raw as Record<string, unknown>;\n const action = record.action;\n if (typeof action !== 'string' || !IMPLEMENTED_SUBAGENT_ACTIONS.has(action)) {\n throw invalidRequest(\n `Unsupported or missing subagent action ${JSON.stringify(action)}.`,\n `Use one of: ${[...IMPLEMENTED_SUBAGENT_ACTIONS].join(', ')}.`,\n );\n }\n const allowed = SUBAGENT_ACTION_FIELDS[action as SubagentAction] as readonly string[];\n const unknown = Object.keys(record).filter((field) => !allowed.includes(field));\n if (unknown.length) {\n throw invalidRequest(\n `action='${action}' does not accept: ${unknown.join(', ')}.`,\n 'Remove unknown fields and retry.',\n );\n }\n if (action === SUBAGENT_ACTIONS.run && (!Array.isArray(record.requests) || record.requests.length === 0)) {\n throw invalidRequest(\"action='run' requires a nonempty 'requests' array.\", 'Add at least one agent and task.');\n }\n if (action === SUBAGENT_ACTIONS.steer) {\n requireNonblank(record, 'id', action);\n requireNonblank(record, 'message', action);\n }\n if (action === SUBAGENT_ACTIONS.stop || action === SUBAGENT_ACTIONS.restore) requireNonblank(record, 'id', action);\n return raw as SubagentToolParams;\n}\n\nexport interface ISubagentToolService {\n registerTool(pi: ExtensionAPI): void;\n}\n\n@injectable()\nexport class SubagentToolService implements ISubagentToolService {\n private readonly registeredHosts = new WeakSet<ExtensionAPI>();\n\n constructor(\n @inject(DOOM_TEAM_TYPES.SpawnPlanner) private readonly planner: ISpawnPlanner,\n @inject(DOOM_TEAM_TYPES.ManagementActions) private readonly management: IManagementActions,\n @inject(DOOM_TEAM_TYPES.AsyncJobTracker) private readonly tracker: IAsyncJobTracker,\n @inject(DOOM_TEAM_TYPES.AgentDiscoveryService) private readonly discovery: IAgentDiscoveryService,\n ) {}\n\n registerTool(pi: ExtensionAPI): void {\n if (this.registeredHosts.has(pi)) return;\n if (hasTool(pi, SUBAGENT_TOOL_NAME)) {\n throw new DoomTeamExpectedError(\n 'tool_conflict',\n `A foreign '${SUBAGENT_TOOL_NAME}' tool is already registered.`,\n false,\n 'Disable the competing extension, then reload Doom Team.',\n );\n }\n pi.registerTool(this.buildTool());\n this.registeredHosts.add(pi);\n }\n\n private trackOutcomes(result: SpawnPlanResult, ctx: ExtensionContext): SpawnPlanResult {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n for (const outcome of result.outcomes) {\n if (outcome.runId) jobs.track(outcome.runId);\n }\n return result;\n }\n\n private buildSpawnRequest(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n preallocatedRunIds: string[],\n ): SpawnPlanRequest {\n const tasks = params.requests.map((request) => {\n if (!request.agent.trim() || !request.task.trim()) {\n throw invalidRequest(\n 'Every run request requires nonblank agent and task values.',\n 'Correct the request and retry.',\n );\n }\n return {\n agent: request.agent.trim(),\n ...(request.inlineAgent ? { inlineAgent: request.inlineAgent } : {}),\n task: request.task.trim(),\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.model ? { model: request.model } : {}),\n ...(request.runtime ? { runtime: request.runtime } : {}),\n };\n });\n const parentForkSource = captureSessionForkSource(ctx.sessionManager, 'tool');\n const parentModel = normalizeParentModel(ctx.model);\n return {\n tasks,\n cwd: ctx.cwd,\n agentScope: scopeOrDefault(params.scope),\n parentSessionId: ctx.sessionManager.getSessionId(),\n ...(parentForkSource\n ? { parentSessionFile: parentForkSource.sessionFile, parentLeafId: parentForkSource.leafId }\n : {}),\n ...(params.concurrency !== undefined ? { concurrency: params.concurrency } : {}),\n ...(params.artifacts !== undefined ? { artifacts: params.artifacts } : {}),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n operationId,\n preallocatedRunIds,\n };\n }\n\n private async executeRun(\n operationId: string,\n params: Extract<SubagentToolParams, { action: 'run' }>,\n ctx: ExtensionContext,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n operationId,\n params,\n params.requests.map(() => randomUUID()),\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(', ')}.`,\n true,\n 'Call subagent({\"action\":\"status\"}) and do not submit the run again.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n this.buildSpawnRequest(operationId, params, ctx, operation.record.runIds),\n loadConfig().config,\n ),\n ctx,\n );\n const started = result.outcomes.filter((outcome) => outcome.runId);\n const failed = result.outcomes.filter((outcome) => !outcome.runId);\n const lines = result.outcomes.map(\n (outcome) =>\n `- ${outcome.agent}: ${outcome.runId ? `started as ${outcome.runId}` : `failed: ${outcome.error ?? 'unknown error'}`}${outcome.warning ? `\\n Warning: ${outcome.warning}` : ''}`,\n );\n if (started.length === 0 && failed.length > 0) {\n throw new DoomTeamExpectedError(\n 'runtime_unavailable',\n `No requested subagent started.\\n${lines.join('\\n')}`,\n true,\n 'Call subagent({\"action\":\"agents\"}) to verify exact agent names, correct only the failed requests, or ask the user if a different delegation approach is needed.',\n );\n }\n const response = textResult(\n [\n `Run request: started ${started.length}/${result.outcomes.length} background agents; failed ${failed.length}.`,\n ...lines,\n ...(started.length > 0\n ? [\n '',\n `The subagent${started.length === 1 ? ' is' : 's are'} now running in the background independently of this turn. Completion will arrive asynchronously as a notification. Continue non-overlapping work, or end your turn.`,\n ]\n : []),\n ...(failed.length > 0\n ? [\n '',\n 'Do not retry the whole request because some runs already started. Inspect the failed entries and submit only corrected replacements for those items.',\n ]\n : []),\n ].join('\\n'),\n { spawn: result, started: started.length, failed: failed.length },\n );\n completeOperation(operationId, operation.record, response);\n return response;\n }\n\n private executeAgents(\n params: Extract<SubagentToolParams, { action: 'agents' }>,\n ctx: ExtensionContext,\n ): AgentToolResult<SubagentToolDetails> {\n const cwd = params.cwd ?? ctx.cwd;\n const scope = scopeOrDefault(params.scope);\n if (!params.name) {\n const result = this.discovery.discover(cwd, scope);\n return textResult(formatAgentList(result.agents), { agents: result.agents.map(publicAgent) });\n }\n const agent = this.discovery.find(cwd, scope, params.name);\n if (!agent) {\n const candidates = this.discovery\n .discover(cwd, scope)\n .agents.map((candidate) => candidate.name)\n .toSorted();\n throw new DoomTeamExpectedError(\n 'agent_not_found',\n `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(', ')}.` : ''}`,\n false,\n 'Call subagent({\"action\":\"agents\"}) and retry with an exact name.',\n );\n }\n return textResult(formatAgentDetail(agent), { agent: publicAgent(agent) });\n }\n\n private async executeManagement(\n params: Exclude<SubagentToolParams, { action: 'run' } | { action: 'agents' }>,\n ctx: ExtensionContext,\n signal?: AbortSignal,\n preallocatedRunIds?: string[],\n operationId?: string,\n ): Promise<AgentToolResult<SubagentToolDetails>> {\n const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId());\n switch (params.action) {\n case SUBAGENT_ACTIONS.status: {\n const suspendedRuns = listSuspendedRuns(requireCurrentSessionScope());\n if (!('id' in params)) {\n if ('transcriptLines' in params && params.transcriptLines !== undefined) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const runs = jobs.list();\n return textResult(formatFleetView(runs, Date.now(), suspendedRuns), {\n fleet: runs,\n suspended: suspendedRuns.map(publicSuspendedRun),\n });\n }\n const runId = params.id;\n if (!runId) {\n throw invalidRequest(\n 'transcriptLines requires a run id.',\n 'Add id or omit transcriptLines for fleet status.',\n );\n }\n const suspended = suspendedRuns.find((run) => run.runId === runId);\n if (suspended && params.transcriptLines === undefined) {\n const resumable = isSuspendedRunResumable(suspended);\n const recovery = resumable\n ? `Restore it with { action: \"restore\", id: \"${suspended.runId}\" }.`\n : 'It is not resumable; submit a new explicit run.';\n return textResult(`Run '${suspended.runId}' is suspended. ${recovery}`, {\n suspended: publicSuspendedRun(suspended),\n });\n }\n const result: StatusActionResult = this.management.status(runId);\n if (!result.runDir && !result.resultPath && !suspended) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No run matches '${runId}'.`,\n false,\n 'Call subagent({\"action\":\"status\"}) and retry with an exact id.',\n );\n }\n if (params.transcriptLines !== undefined) {\n return textResult(formatRunTranscript(result.status, params.transcriptLines ?? DEFAULT_TRANSCRIPT_LINES), {\n transcript: { runId: result.runId },\n });\n }\n return textResult(\n result.status ? `Run '${result.runId}': ${result.status.state}` : `Run '${result.runId}' has no status yet.`,\n { status: result },\n );\n }\n case SUBAGENT_ACTIONS.stop: {\n const id = resolveTrackedRunId(jobs, params.id);\n const result = this.management.stop(id, params.reason);\n return textResult(`Stop requested for '${id}'.`, { control: result });\n }\n case SUBAGENT_ACTIONS.steer: {\n const id = resolveTrackedRunId(jobs, params.id);\n const runtime = this.tracker.get(id)?.runtime;\n if (runtime && !isPiRuntime(runtime)) {\n throw new DoomTeamExpectedError(\n 'unsupported_operation',\n `Run '${id}' uses '${runtime}', which does not support steering.`,\n false,\n `Use subagent({\"action\":\"stop\",\"id\":\"${id}\"}) to terminate it.`,\n );\n }\n const result = await this.management.steer(id, params.message, undefined, signal);\n return textResult(`Steer request '${result.requestId}' for '${id}' is ${result.state}: ${result.message}`, {\n steer: result,\n });\n }\n case SUBAGENT_ACTIONS.suspended: {\n const runs = listSuspendedRuns(requireCurrentSessionScope());\n return textResult(runs.length ? formatSuspendedRuns(runs) : 'No suspended subagents in this session.', {\n suspended: runs.map(publicSuspendedRun),\n });\n }\n case SUBAGENT_ACTIONS.restore: {\n const scope = requireCurrentSessionScope();\n const record = listSuspendedRuns(scope).find((run) => run.runId === params.id);\n if (!record) {\n throw new DoomTeamExpectedError(\n 'run_not_found',\n `No suspended run matches '${params.id}'.`,\n false,\n 'Call subagent({\"action\":\"suspended\"}) and retry with an exact id.',\n );\n }\n if (!isSuspendedRunResumable(record)) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Suspended run '${params.id}' does not have complete, readable Pi recovery state.`,\n false,\n 'Submit a new explicit run request instead of restoring this record.',\n );\n }\n const result = this.trackOutcomes(\n await this.planner.spawn(\n {\n single: {\n agent: record.agent,\n ...(record.inlineAgent ? { inlineAgent: record.inlineAgent } : {}),\n task: record.task,\n cwd: record.cwd,\n ...(record.model ? { model: record.model } : {}),\n sessionFile: record.sessionFile,\n },\n cwd: record.cwd,\n agentScope: 'both',\n runtime: 'pi',\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(operationId ? { operationId } : {}),\n ...(preallocatedRunIds ? { preallocatedRunIds } : {}),\n },\n loadConfig().config,\n ),\n ctx,\n );\n const outcome = result.outcomes[0];\n if (!outcome?.runId) {\n throw new DoomTeamExpectedError(\n 'not_resumable',\n `Could not restore '${params.id}': ${outcome?.error ?? 'the spawn produced no run.'}`,\n true,\n 'Inspect suspended state, then submit a new explicit run if recovery is not possible.',\n );\n }\n clearSuspendedRun(scope, params.id);\n return textResult(`Restored '${params.id}' as '${outcome.runId}', continuing its transcript.`, {\n restore: { ...outcome, restoredFrom: params.id },\n });\n }\n }\n }\n\n private buildTool(): ToolDefinition<typeof SubagentParams, SubagentToolDetails> {\n return {\n name: SUBAGENT_TOOL_NAME,\n label: 'Subagent',\n description: SUBAGENT_TOOL_DESCRIPTION,\n parameters: SubagentParams,\n prepareArguments: validateParams,\n // Subagent output carries explicit lifecycle colors. Owning the shell keeps\n // Pi's broad pending/success/error backgrounds from washing out long lists.\n renderShell: 'self',\n renderCall: (rawParams, theme) => renderSubagentCall(validateParams(rawParams), theme),\n renderResult: (result, options, theme) => renderSubagentResult(result, options, theme),\n execute: async (id, rawParams, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentToolDetails>> => {\n const params = validateParams(rawParams);\n const progress = progressMessage(params);\n if (progress) onUpdate?.(progressResult(progress, params.action));\n if (params.action === SUBAGENT_ACTIONS.run) return this.executeRun(id, params, ctx);\n if (params.action === SUBAGENT_ACTIONS.agents) return this.executeAgents(params, ctx);\n const journaled =\n params.action === SUBAGENT_ACTIONS.steer ||\n params.action === SUBAGENT_ACTIONS.stop ||\n params.action === SUBAGENT_ACTIONS.restore;\n if (!journaled) return this.executeManagement(params, ctx, signal);\n\n const operation = startOperation<AgentToolResult<SubagentToolDetails>>(\n id,\n params,\n params.action === SUBAGENT_ACTIONS.restore ? [randomUUID()] : [],\n );\n if (operation.kind === 'replay') {\n if (operation.record.state === 'completed' && operation.record.result) return operation.record.result;\n throw new DoomTeamExpectedError(\n 'delivery_unconfirmed',\n `Operation '${id}' is already pending.`,\n true,\n 'Inspect run status before retrying this control operation.',\n );\n }\n const response = await this.executeManagement(params, ctx, signal, operation.record.runIds, id);\n completeOperation(id, operation.record, response);\n return response;\n },\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);let e=require(`@earendil-works/pi-tui`),t=require(`@agimon-ai/doompi-ui/components/doomOverlay`);t.DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;const
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);let e=require(`@earendil-works/pi-tui`),t=require(`@agimon-ai/doompi-ui/components/doomOverlay`),n=require(`@agimon-ai/doompi-ui/rendering`);t.DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;const r=`Launch projection from the current parent-policy snapshot. Child resource loading can still change qualified resources.`,i=[`tools`,`skills`,`extensions`],a=[[`↑↓/jk`,`move`],[`enter`,`view`],[`tab`,`cycle`],[`J/K`,`scroll`]];function o(e,t){return(0,n.fitStyledLine)(e,t,`…`)}function s(t,n,r){let i=Math.max(0,r),a=(0,e.visibleWidth)(n);return a+2>=i?o(t,i):`${o(t,Math.max(1,i-a-2))} ${o(n,a)}`}function c(t,n,r,i,a){for(let o of(0,e.wrapTextWithAnsi)(n,Math.max(1,r)))t.push(a.fg(i,o))}function l(e,t,n,r,i){if(e.push(i.bold(i.fg(`accent`,t))),n.length===0)e.push(i.fg(`dim`,` none`));else for(let t of n)c(e,` • ${t.name}`,r,`text`,i),t.detail&&c(e,` ${t.detail}`,r,`dim`,i);e.push(``)}function u(e,t){return t===`skills`?e.skills:t===`extensions`?e.extensions:e.tools}function d(e,t,n,r){let i=[];e.error&&(i.push(r.bold(r.fg(`error`,`PROJECTION ERROR`))),c(i,e.error,n,`error`,r),i.push(``));let a=u(e,t);return l(i,`PROJECTED EFFECTIVE`,a.effective,n,r),l(i,`REMOVED BY PARENT`,a.removed,n,r),l(i,`UNRESOLVED AT PREVIEW`,a.unresolved,n,r),i}function f(t,n,r){return(0,e.truncateToWidth)(i.map(e=>{let n=e.toUpperCase();return e===t?r.inverse(r.bold(` ${n} `)):r.fg(`dim`,` ${n} `)}).join(` `),Math.max(0,n),`…`)}function p(t){let n=Math.max(2,t-(0,e.visibleWidth)(`│`)),r=Math.max(1,Math.floor(n/3)),i=Math.max(1,n-r),a=+(r>=3&&i>=3);return{leftContentWidth:Math.max(1,r-a),rightContentWidth:Math.max(1,i-a),gutterWidth:a}}var m=class extends t.DoomOverlay{entries;cursorIndex=0;inspectedIndex;tab=`tools`;listPageSize=1;detailPageSize=1;detailOffset=0;detailTotal=0;constructor(e,t,n,r){super(e,t),this.done=r,this.entries=[...n].sort((e,t)=>e.agent.name.localeCompare(t.agent.name))}cursorEntry(){return this.entries[Math.min(this.cursorIndex,Math.max(0,this.entries.length-1))]}inspectedEntry(){if(this.inspectedIndex!==void 0)return this.entries[this.inspectedIndex]}moveCursor(e){if(this.entries.length===0)return;let t=Math.max(0,Math.min(this.entries.length-1,this.cursorIndex+e));t!==this.cursorIndex&&(this.cursorIndex=t,this.invalidate())}inspectCursor(){this.cursorEntry()&&(this.inspectedIndex=this.cursorIndex,this.detailOffset=0,this.invalidate())}switchTab(e){this.tab!==e&&(this.tab=e,this.detailOffset=0,this.invalidate())}cycleTab(){let e=i.indexOf(this.tab);this.switchTab(i[(e+1)%i.length]??`tools`)}scrollDetail(e){if(!this.inspectedEntry())return;let t=Math.max(0,this.detailTotal-this.detailPageSize),n=Math.max(0,Math.min(t,this.detailOffset+e));n!==this.detailOffset&&(this.detailOffset=n,this.invalidate())}handleInput(t){if((0,e.matchesKey)(t,`escape`)||(0,e.matchesKey)(t,`ctrl+c`)){this.done(void 0);return}if((0,e.matchesKey)(t,e.Key.shift(`k`))){this.scrollDetail(-1);return}if((0,e.matchesKey)(t,e.Key.shift(`j`))){this.scrollDetail(1);return}if((0,e.matchesKey)(t,`up`)||t===`k`){this.moveCursor(-1);return}if((0,e.matchesKey)(t,`down`)||t===`j`){this.moveCursor(1);return}if((0,e.matchesKey)(t,`pageUp`)){this.moveCursor(-this.listPageSize);return}if((0,e.matchesKey)(t,`pageDown`)){this.moveCursor(this.listPageSize);return}if((0,e.matchesKey)(t,`enter`)){this.inspectCursor();return}if((0,e.matchesKey)(t,`tab`)){this.cycleTab();return}t===`t`?this.switchTab(`tools`):t===`s`?this.switchTab(`skills`):t===`e`&&this.switchTab(`extensions`)}getChrome(){let e=this.cursorEntry(),n=this.inspectedEntry(),r=this.entries.length?String(this.cursorIndex+1):`empty`,i=e?n?`C${r} I${(this.inspectedIndex??0)+1}`:`C${r} I-`:`empty`;return{title:`AGENTS`,accent:t.DOOM_OVERLAY_ACCENT,breadcrumb:`SPC › a / agents › l / available`,headerRight:`${this.entries.length} available · ${this.tab}`,footer:`↑↓/jk cursor · PgUp/PgDn page · enter inspect · tab resource · J/K scroll · esc close`,footerHints:a,footerRight:i}}renderBody(e,t){let n=p(e),r=this.renderList(n.leftContentWidth,t),i=this.renderDetail(n.rightContentWidth,t),a=` `.repeat(n.gutterWidth),s=this.theme.fg(`borderMuted`,`│`),c=[];for(let e=0;e<t;e++)c.push(`${o(r[e]??``,n.leftContentWidth)}${a}${s}${a}${o(i[e]??``,n.rightContentWidth)}`);return c.map(t=>o(t,e))}renderList(e,t){let n=[this.theme.bold(this.theme.fg(`accent`,`AGENTS ${this.entries.length}`))];if(this.entries.length===0)return c(n,`No enabled agents are available from this session cwd.`,e,`dim`,this.theme),this.listPageSize=1,n.slice(0,t);this.listPageSize=Math.max(1,t-1);let r=Math.max(0,Math.min(this.cursorIndex-this.listPageSize+1,Math.max(0,this.entries.length-this.listPageSize)));for(let[t,i]of this.entries.slice(r,r+this.listPageSize).entries()){let a=r+t===this.cursorIndex,c=a?this.theme.fg(`accent`,`›`):` `,l=i.agent.runtime??`pi`,u=s(`${c} ${a?this.theme.bold(i.agent.name):i.agent.name}`,`${i.agent.source} · ${l}`,e),d=a?`selectedBg`:`userMessageBg`;n.push(this.theme.bg(d,o(u,e)))}return n.slice(0,t)}renderDetail(e,t){let n=this.inspectedEntry();if(!n){this.detailTotal=0,this.detailPageSize=Math.max(1,t),this.detailOffset=0;let n=[this.theme.bold(this.theme.fg(`accent`,`AGENT RESOURCES`)),``];return c(n,`Press Enter to inspect the cursor agent.`,e,`text`,this.theme),n.push(``),c(n,r,e,`dim`,this.theme),n.slice(0,t)}let i=n.agent.runtime??`pi`,a=[s(this.theme.bold(this.theme.fg(`accent`,`INSPECTING ${n.agent.name}`)),`${n.agent.source} · ${i}`,e)];c(a,n.agent.description,e,`text`,this.theme),c(a,n.resources.notice||r,e,n.resources.configuredOnly?`warning`:`dim`,this.theme),a.push(f(this.tab,e,this.theme),``);let o=d(n.resources,this.tab,e,this.theme);return this.detailPageSize=Math.max(0,t-a.length),this.detailTotal=o.length,this.detailOffset=Math.min(this.detailOffset,Math.max(0,o.length-this.detailPageSize)),[...a,...o.slice(this.detailOffset,this.detailOffset+this.detailPageSize)].slice(0,t)}};async function h(e,n){await e.ui.custom((e,t,r,i)=>new m(e,t,n,i),t.DOOM_FULLSCREEN_UI_OPTIONS)}exports.openAgentCatalog=h;
|
|
2
2
|
//# sourceMappingURL=agentCatalog.cjs.map
|