@alvin0/ai-agent-sdk-core 0.1.7 → 0.1.9

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.
Files changed (69) hide show
  1. package/README.md +6 -0
  2. package/dist/agent/define/session/config.js +1 -1
  3. package/dist/agent/define/session/config.js.map +1 -1
  4. package/dist/agent/define/session/types.d.ts +14 -0
  5. package/dist/agent/define/session/types.d.ts.map +1 -1
  6. package/dist/agent/define/session.d.ts.map +1 -1
  7. package/dist/agent/define/session.js +1 -1
  8. package/dist/agent/define/session.js.map +1 -1
  9. package/dist/agent/loop/events.d.ts +24 -1
  10. package/dist/agent/loop/events.d.ts.map +1 -1
  11. package/dist/agent/loop/run-turn.d.ts.map +1 -1
  12. package/dist/agent/loop/run-turn.js +1 -1
  13. package/dist/agent/loop/run-turn.js.map +1 -1
  14. package/dist/agent/loop/schedule.d.ts +5 -0
  15. package/dist/agent/loop/schedule.d.ts.map +1 -1
  16. package/dist/agent/loop/schedule.js +1 -1
  17. package/dist/agent/loop/schedule.js.map +1 -1
  18. package/dist/agent/loop/turn/config.js +1 -1
  19. package/dist/agent/loop/turn/config.js.map +1 -1
  20. package/dist/agent/loop/turn/model-request-boundary.js +1 -1
  21. package/dist/agent/loop/turn/model-request-boundary.js.map +1 -1
  22. package/dist/agent/loop/turn/model-round.js +1 -1
  23. package/dist/agent/loop/turn/model-round.js.map +1 -1
  24. package/dist/agent/loop/turn/types.d.ts +35 -2
  25. package/dist/agent/loop/turn/types.d.ts.map +1 -1
  26. package/dist/agent/loop/types.d.ts +16 -0
  27. package/dist/agent/loop/types.d.ts.map +1 -1
  28. package/dist/agent/mode/run-agent.d.ts +9 -0
  29. package/dist/agent/mode/run-agent.d.ts.map +1 -1
  30. package/dist/agent/mode/run-agent.js +2 -2
  31. package/dist/agent/mode/run-agent.js.map +1 -1
  32. package/dist/agent/mode/user-input.d.ts.map +1 -1
  33. package/dist/agent/mode/user-input.js +1 -1
  34. package/dist/agent/mode/user-input.js.map +1 -1
  35. package/dist/agent/team/managed.d.ts.map +1 -1
  36. package/dist/agent/team/managed.js +1 -1
  37. package/dist/agent/team/managed.js.map +1 -1
  38. package/dist/agent/tool/capture.js +1 -1
  39. package/dist/agent/tool/capture.js.map +1 -1
  40. package/dist/agent/tool/definition.d.ts +7 -0
  41. package/dist/agent/tool/definition.d.ts.map +1 -1
  42. package/dist/agent/tool/definition.js.map +1 -1
  43. package/dist/agent.js +1 -1
  44. package/dist/composition/agent/public-event.d.ts +19 -0
  45. package/dist/composition/agent/public-event.d.ts.map +1 -0
  46. package/dist/composition/agent/public-event.js +2 -0
  47. package/dist/composition/agent/public-event.js.map +1 -0
  48. package/dist/composition/agent/session.js +1 -1
  49. package/dist/composition/agent/session.js.map +1 -1
  50. package/dist/composition/agent/types.d.ts +11 -1
  51. package/dist/composition/agent/types.d.ts.map +1 -1
  52. package/dist/composition/embedding/retry.js +1 -1
  53. package/dist/composition/embedding/retry.js.map +1 -1
  54. package/dist/embedding/errors.d.ts +5 -1
  55. package/dist/embedding/errors.d.ts.map +1 -1
  56. package/dist/embedding/errors.js +1 -1
  57. package/dist/embedding/errors.js.map +1 -1
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.js +1 -1
  60. package/dist/observability/bus.js +1 -1
  61. package/dist/primitives/version.d.ts +1 -1
  62. package/dist/primitives/version.js +1 -1
  63. package/dist/primitives/version.js.map +1 -1
  64. package/dist/runtime/registry.js +1 -1
  65. package/dist/runtime/with-retry.d.ts +15 -0
  66. package/dist/runtime/with-retry.d.ts.map +1 -1
  67. package/dist/runtime/with-retry.js +1 -1
  68. package/dist/runtime/with-retry.js.map +1 -1
  69. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{waitForSettlement as e}from"../../async/settlement.js";import{timeoutValue as t}from"../../platform/config.js";import{createTextMessage as n,createUserMessage as r}from"../../message/message.js";import{defineTool as i}from"../tool/definition.js";import{ToolRegistry as a}from"../tool/registry.js";import{History as o}from"../history/history.js";import{managedTeamNoticeRequest as s}from"../history/input-work.js";import{cloneAgent as c}from"../define/definition.js";import"./common.js";import{AgentTeam as l}from"./team.js";const u=3e4,d=3e4,f=15e3,p=[`You have access to a managed team. Your task and coordination strategy are defined by the host instructions.`,`Return only the caller-requested result in the caller’s format; include explanation only when requested.`,`spawn_agent returns a worker lifecycle view, not its final result. list_agents exposes status and retained results; wait_agents waits within its timeout.`,`dependsOn references already registered producer instances. Pending dependents start after those producers settle and receive their results or failure status, even if a producer address is later closed or reused.`,`fresh starts from the assigned task; fork also copies the completed lead conversation.`,`writes declares relative scheduling scopes under the host conflict policy; it does not grant filesystem permissions. Omit it when no write scope is needed.`,`send_message is an update, not terminal completion. completed and failed are terminal worker states; pending and running are not.`,`Finished workers occupy slots until close_agent. Closing unfinished work requires cancelRunning: true and host authorization.`].join(` `);var m=class{team;lead;leadName;options;maxWorkers;maxTaskBytes;maxSpecialtyBytes;workerTimeoutMs;observerTimeoutMs;closeTimeoutMs;holdWaitMs;spawnTimeoutMs;workerRuntimes=new Map;drainingWrites=new Set;preparing=new Map;lifecycle=new AbortController;disposeTask;workerSequence=0;maxDependencyReportBytes;roles;constructor(e){if(this.options=e,this.maxWorkers=E(e.maxWorkers??7,`maxWorkers`),this.maxTaskBytes=E(e.maxTaskBytes??65536,`maxTaskBytes`),this.maxSpecialtyBytes=E(e.maxSpecialtyBytes??8192,`maxSpecialtyBytes`),this.workerTimeoutMs=t(e.workerTimeoutMs??6e5),this.observerTimeoutMs=t(e.observerTimeoutMs??1e3),this.closeTimeoutMs=t(e.closeTimeoutMs??3e4),this.holdWaitMs=t(e.holdWaitMs??15e3),this.spawnTimeoutMs=t(e.spawnTimeoutMs??3e4),this.maxDependencyReportBytes=E(e.maxDependencyReportBytes??8192,`maxDependencyReportBytes`),this.maxDependencyReportBytes<4)throw TypeError(`maxDependencyReportBytes must be at least 4`);if(this.roles=new Map((e.roles??[]).map(e=>[e.name,e])),this.roles.size!==(e.roles??[]).length)throw Error(`managed agent roles contain a duplicate name`);this.team=e.team instanceof l?e.team:new l({...e.team,maxMembers:e.team?.maxMembers??this.maxWorkers+1}),this.leadName=C(e.leadName??e.lead.id),this.lead=e.lead.createSession({...e.leadSessionOptions,hooks:this.leadHooks(e.leadSessionOptions?.hooks),registry:e.registry,tools:g(e.leadSessionOptions?.tools,this.controlTools()),team:{team:this.team,name:this.leadName,role:`lead`,instructions:p,...e.leadDescription===void 0?{}:{description:e.leadDescription}}})}leadHooks(e){return{...e,beforeStep:async t=>(this.unreadReports=!1,this.leadSteer=new AbortController,this.leadSignal=t.signal,await e?.beforeStep?.(t)??{kind:`proceed`}),onTurnEnd:async t=>{if(await e?.onTurnEnd?.(t),this.options.autoLeadCoordination===!1)return;if(!t.canContinue){if(this.unreadReports){this.unreadReports=!1;try{this.team.wake(this.leadName)}catch{}}return}let n=[...this.workerRuntimes.values()].filter(e=>e.status===`running`||e.status===`pending`);if(n.length===0)return;await this.awaitWorkerNews(n);let i=[...this.workerRuntimes.values()].filter(e=>e.status===`running`||e.status===`pending`).map(e=>e.request.name);if(i.length===0){this.lead.inject(r({source:{kind:`app`,producer:`managed-team`},content:[{type:`text`,text:`All outstanding managed workers have settled. Their statuses and retained results are available through list_agents.`}]}));return}this.lead.inject(r({source:{kind:`app`,producer:`managed-team`},content:[{type:`text`,text:`Outstanding managed workers: ${i.join(`, `)}. Their current lifecycle status is available through list_agents; wait_agents is bounded by its timeout.`}]}))}}}run(e,t={}){return this.lifecycle.signal.throwIfAborted(),this.lead.run(e,t)}steer(e){this.lifecycle.signal.throwIfAborted(),this.lead.inject(e),this.leadSteer.abort();try{this.team.notifySteer(this.leadName)}catch{}if(!this.lead.isRunning)try{this.team.wake(this.leadName)}catch{}return!0}async spawn(e,t){this.lifecycle.signal.throwIfAborted(),t?.throwIfAborted();let r={name:C(e.name??this.nextWorkerName()),task:T(e.task,`worker task`,this.maxTaskBytes),...e.specialty===void 0?{}:{specialty:T(e.specialty,`worker specialty`,this.maxSpecialtyBytes)},context:b(e.context??this.options.defaultSpawnContext??`fresh`),...e.role===void 0?{}:{role:this.requireRole(e.role)},dependsOn:this.resolveDependencies(e.dependsOn??[]),writes:[...new Set((e.writes??[]).map(N))]};Object.freeze(r.dependsOn),Object.freeze(r.writes),Object.freeze(r);let i=r.dependsOn.map(e=>this.workerRuntimes.get(e));if(this.workerRuntimes.size+this.preparing.size>=this.maxWorkers)throw Error(`managed agent team reached its ${this.maxWorkers}-worker limit`);if(this.preparing.has(r.name)||this.workerRuntimes.has(r.name)||this.team.members().some(e=>e.name===r.name))throw Error(`managed worker '${r.name}' already exists`);let a,o=new Promise(e=>{a=e});this.preparing.set(r.name,{request:r,dependencies:i,settled:o});let s;try{let e=this.checkWriteScopes(r,i),a=k(t,this.lifecycle.signal,AbortSignal.timeout(this.spawnTimeoutMs)),o=await O(this.workerDefinition(r),a);a.throwIfAborted();let c=this.options.workerSessionOptionsFactory===void 0?void 0:await O(Promise.resolve(this.options.workerSessionOptionsFactory(r)),a);a.throwIfAborted();let l={...this.options.workerSessionOptions,...c},u=this.options.workerTeamTools??`reporting`,d=o.createSession({...l,...i.length===0?{}:{tools:g(l.tools,[this.dependencyReadTool(i)])},...r.context===`fork`?{history:this.forkLeadHistory(l.historyLimits)}:{},registry:this.options.registry,team:{team:this.team,name:r.name,role:`peer`,tools:u,instructions:[`You are managed worker '${r.name}'; lead: '${this.leadName}'.`,`Return only the caller-requested result in the caller’s format; include explanation only when requested.`,`Your terminal result is delivered automatically.`,...u===!1?[]:[`send_message is context, not a substitute result; it cannot target yourself.`]].join(` `),...r.specialty===void 0?{}:{description:r.specialty}}}),f=new AbortController,p;s={request:r,session:d,dependencies:i,starting:!1,settledComplete:!1,closeTask:void 0,status:`pending`,leadDriven:this.lead.isRunning,closing:!1,deadline:void 0,controller:f,settled:new Promise(e=>{p=e}),markSettled:()=>{L(s),s.settledComplete=!0,p()},start:void 0,warnings:e,result:void 0,error:void 0,evidence:{status:`pending`,result:void 0,error:void 0}},this.workerRuntimes.set(r.name,s),this.preparing.delete(r.name);let m=k(a,f.signal);if(await O(this.team.sendMessage({from:this.leadName,target:r.name,message:r.task,delivery:`quiet`,signal:m}),m),m.throwIfAborted(),o.memory.autoCaptureObjective&&d.memory.captureOriginalObjective(n(r.task)),i.length>0&&!this.dependenciesSettled(i,r.writes)){let e=new Promise(e=>{s.start=e});this.team.markPending(r.name,e);for(let e of i)j.has(e.status)&&this.workerHasWork(e)&&this.team.whenIdle(e.request.name).then(()=>this.releaseDependents(e)).catch(()=>{});return this.workerView(s)}return await this.startWorker(s,m),this.workerView(s)}catch(e){if(s!==void 0&&this.workerRuntimes.get(r.name)===s&&!s.closing){s.status=`failed`,s.error=D(e),s.start=void 0,s.dependencies=[];try{this.team.markPending(r.name,void 0)}catch{}s.markSettled(),this.workerRuntimes.delete(r.name);try{this.team.detach(r.name)}catch{}await this.releaseDependents(s)}throw e}finally{this.preparing.delete(r.name),a()}}beginWorker(e){let t=e.request.name;if(e.status!==`pending`||e.closing||this.lifecycle.signal.aborted||this.workerRuntimes.get(t)!==e)return;e.start?.(),e.start=void 0,this.team.markPending(t,void 0),e.status=`running`;let n=AbortSignal.timeout(this.workerTimeoutMs);e.deadline=n;let r=e.session.runPending({signal:k(e.controller.signal,n),...this.options.onWorkerEvent===void 0?{}:{onEvent:e=>this.observeWorkerEvent(t,e)}});this.followWorker(e,r)}async startWorker(e,t){if(!(e.starting||e.status!==`pending`||e.closing||this.lifecycle.signal.aborted)){e.starting=!0;try{let n=this.dependencyReport(e.dependencies);if(n!==void 0){let r=k(t,e.controller.signal,this.lifecycle.signal,AbortSignal.timeout(this.spawnTimeoutMs));await O(this.team.sendMessage({from:this.leadName,target:e.request.name,message:n,delivery:`quiet`,signal:r}),r),r.throwIfAborted()}this.beginWorker(e)}catch(t){if(!e.closing&&!this.lifecycle.signal.aborted){e.status=`failed`,e.error=`dependency handoff failed: ${D(t)}`,L(e),e.start?.(),e.start=void 0;try{this.team.markPending(e.request.name,void 0),this.team.recordOutcome(e.request.name,{kind:`failed`,message:e.error})}catch{}await this.notifyLead(e,`failed: ${e.error}`),e.markSettled(),await this.releaseDependents(e)}}finally{e.dependencies=[]}}}roleSchema(){if(this.roles.size===0)return{};let e=[...this.roles.values()].map(e=>`- ${e.name}: ${e.description}`+(e.whenToUse===void 0?``:` Use when: ${e.whenToUse}`));return{role:{type:`string`,enum:[...this.roles.keys()],description:`Which kind of worker this is.\n${e.join(`
1
+ import{waitForSettlement as e}from"../../async/settlement.js";import{timeoutValue as t}from"../../platform/config.js";import{createTextMessage as n,createUserMessage as r}from"../../message/message.js";import{defineTool as i}from"../tool/definition.js";import{ToolRegistry as a}from"../tool/registry.js";import{History as o}from"../history/history.js";import{managedTeamNoticeRequest as s}from"../history/input-work.js";import{cloneAgent as c}from"../define/definition.js";import"./common.js";import{AgentTeam as l}from"./team.js";const u=3e4,d=3e4,f=15e3,p=[`You have access to a managed team. Your task and coordination strategy are defined by the host instructions.`,`Return only the caller-requested result in the caller’s format; include explanation only when requested.`,`spawn_agent returns a worker lifecycle view, not its final result. list_agents exposes status and retained results; wait_agents waits within its timeout.`,`dependsOn references already registered producer instances. Pending dependents start after those producers settle and receive their results or failure status, even if a producer address is later closed or reused.`,`fresh starts from the assigned task; fork also copies the completed lead conversation.`,`writes declares relative scheduling scopes under the host conflict policy; it does not grant filesystem permissions. Omit it when no write scope is needed.`,`send_message is an update, not terminal completion. completed and failed are terminal worker states; pending and running are not.`,`Finished workers occupy slots until close_agent. Closing unfinished work requires cancelRunning: true and host authorization.`].join(` `);var m=class{team;lead;leadName;options;maxWorkers;maxTaskBytes;maxSpecialtyBytes;workerTimeoutMs;observerTimeoutMs;closeTimeoutMs;holdWaitMs;spawnTimeoutMs;workerRuntimes=new Map;drainingWrites=new Set;preparing=new Map;lifecycle=new AbortController;disposeTask;workerSequence=0;maxDependencyReportBytes;roles;constructor(e){if(this.options=e,this.maxWorkers=E(e.maxWorkers??7,`maxWorkers`),this.maxTaskBytes=E(e.maxTaskBytes??65536,`maxTaskBytes`),this.maxSpecialtyBytes=E(e.maxSpecialtyBytes??8192,`maxSpecialtyBytes`),this.workerTimeoutMs=t(e.workerTimeoutMs??6e5),this.observerTimeoutMs=t(e.observerTimeoutMs??1e3),this.closeTimeoutMs=t(e.closeTimeoutMs??3e4),this.holdWaitMs=t(e.holdWaitMs??15e3),this.spawnTimeoutMs=t(e.spawnTimeoutMs??3e4),this.maxDependencyReportBytes=E(e.maxDependencyReportBytes??8192,`maxDependencyReportBytes`),this.maxDependencyReportBytes<4)throw TypeError(`maxDependencyReportBytes must be at least 4`);if(this.roles=new Map((e.roles??[]).map(e=>[e.name,e])),this.roles.size!==(e.roles??[]).length)throw Error(`managed agent roles contain a duplicate name`);this.team=e.team instanceof l?e.team:new l({...e.team,maxMembers:e.team?.maxMembers??this.maxWorkers+1}),this.leadName=C(e.leadName??e.lead.id),this.lead=e.lead.createSession({...e.leadSessionOptions,runtimeLimits:{...e.leadSessionOptions?.runtimeLimits,finalizeSteps:e.leadSessionOptions?.runtimeLimits?.finalizeSteps??0},hooks:this.leadHooks(e.leadSessionOptions?.hooks),registry:e.registry,tools:g(e.leadSessionOptions?.tools,this.controlTools()),team:{team:this.team,name:this.leadName,role:`lead`,instructions:p,...e.leadDescription===void 0?{}:{description:e.leadDescription}}})}leadHooks(e){return{...e,beforeStep:async t=>(this.unreadReports=!1,this.leadSteer=new AbortController,this.leadSignal=t.signal,await e?.beforeStep?.(t)??{kind:`proceed`}),onTurnEnd:async t=>{if(await e?.onTurnEnd?.(t),this.options.autoLeadCoordination===!1)return;if(!t.canContinue){if(this.unreadReports){this.unreadReports=!1;try{this.team.wake(this.leadName)}catch{}}return}let n=[...this.workerRuntimes.values()].filter(e=>e.status===`running`||e.status===`pending`);if(n.length===0)return;await this.awaitWorkerNews(n);let i=[...this.workerRuntimes.values()].filter(e=>e.status===`running`||e.status===`pending`).map(e=>e.request.name);if(i.length===0){this.lead.inject(r({source:{kind:`app`,producer:`managed-team`},content:[{type:`text`,text:`All outstanding managed workers have settled. Their statuses and retained results are available through list_agents.`}]}));return}this.lead.inject(r({source:{kind:`app`,producer:`managed-team`},content:[{type:`text`,text:`Outstanding managed workers: ${i.join(`, `)}. Their current lifecycle status is available through list_agents; wait_agents is bounded by its timeout.`}]}))}}}run(e,t={}){return this.lifecycle.signal.throwIfAborted(),this.lead.run(e,t)}steer(e){this.lifecycle.signal.throwIfAborted(),this.lead.inject(e),this.leadSteer.abort();try{this.team.notifySteer(this.leadName)}catch{}if(!this.lead.isRunning)try{this.team.wake(this.leadName)}catch{}return!0}async spawn(e,t){this.lifecycle.signal.throwIfAborted(),t?.throwIfAborted();let r={name:C(e.name??this.nextWorkerName()),task:T(e.task,`worker task`,this.maxTaskBytes),...e.specialty===void 0?{}:{specialty:T(e.specialty,`worker specialty`,this.maxSpecialtyBytes)},context:b(e.context??this.options.defaultSpawnContext??`fresh`),...e.role===void 0?{}:{role:this.requireRole(e.role)},dependsOn:this.resolveDependencies(e.dependsOn??[]),writes:[...new Set((e.writes??[]).map(N))]};Object.freeze(r.dependsOn),Object.freeze(r.writes),Object.freeze(r);let i=r.dependsOn.map(e=>this.workerRuntimes.get(e));if(this.workerRuntimes.size+this.preparing.size>=this.maxWorkers)throw Error(`managed agent team reached its ${this.maxWorkers}-worker limit`);if(this.preparing.has(r.name)||this.workerRuntimes.has(r.name)||this.team.members().some(e=>e.name===r.name))throw Error(`managed worker '${r.name}' already exists`);let a,o=new Promise(e=>{a=e});this.preparing.set(r.name,{request:r,dependencies:i,settled:o});let s;try{let e=this.checkWriteScopes(r,i),a=k(t,this.lifecycle.signal,AbortSignal.timeout(this.spawnTimeoutMs)),o=await O(this.workerDefinition(r),a);a.throwIfAborted();let c=this.options.workerSessionOptionsFactory===void 0?void 0:await O(Promise.resolve(this.options.workerSessionOptionsFactory(r)),a);a.throwIfAborted();let l={...this.options.workerSessionOptions,...c},u=this.options.workerTeamTools??`reporting`,d=o.createSession({...l,...i.length===0?{}:{tools:g(l.tools,[this.dependencyReadTool(i)])},...r.context===`fork`?{history:this.forkLeadHistory(l.historyLimits)}:{},registry:this.options.registry,team:{team:this.team,name:r.name,role:`peer`,tools:u,instructions:[`You are managed worker '${r.name}'; lead: '${this.leadName}'.`,`Return only the caller-requested result in the caller’s format; include explanation only when requested.`,`Your terminal result is delivered automatically.`,...u===!1?[]:[`send_message is context, not a substitute result; it cannot target yourself.`]].join(` `),...r.specialty===void 0?{}:{description:r.specialty}}}),f=new AbortController,p;s={request:r,session:d,dependencies:i,starting:!1,settledComplete:!1,closeTask:void 0,status:`pending`,leadDriven:this.lead.isRunning,closing:!1,deadline:void 0,controller:f,settled:new Promise(e=>{p=e}),markSettled:()=>{L(s),s.settledComplete=!0,p()},start:void 0,warnings:e,result:void 0,error:void 0,evidence:{status:`pending`,result:void 0,error:void 0}},this.workerRuntimes.set(r.name,s),this.preparing.delete(r.name);let m=k(a,f.signal);if(await O(this.team.sendMessage({from:this.leadName,target:r.name,message:r.task,delivery:`quiet`,signal:m}),m),m.throwIfAborted(),o.memory.autoCaptureObjective&&d.memory.captureOriginalObjective(n(r.task)),i.length>0&&!this.dependenciesSettled(i,r.writes)){let e=new Promise(e=>{s.start=e});this.team.markPending(r.name,e);for(let e of i)j.has(e.status)&&this.workerHasWork(e)&&this.team.whenIdle(e.request.name).then(()=>this.releaseDependents(e)).catch(()=>{});return this.workerView(s)}return await this.startWorker(s,m),this.workerView(s)}catch(e){if(s!==void 0&&this.workerRuntimes.get(r.name)===s&&!s.closing){s.status=`failed`,s.error=D(e),s.start=void 0,s.dependencies=[];try{this.team.markPending(r.name,void 0)}catch{}s.markSettled(),this.workerRuntimes.delete(r.name);try{this.team.detach(r.name)}catch{}await this.releaseDependents(s)}throw e}finally{this.preparing.delete(r.name),a()}}beginWorker(e){let t=e.request.name;if(e.status!==`pending`||e.closing||this.lifecycle.signal.aborted||this.workerRuntimes.get(t)!==e)return;e.start?.(),e.start=void 0,this.team.markPending(t,void 0),e.status=`running`;let n=AbortSignal.timeout(this.workerTimeoutMs);e.deadline=n;let r=e.session.runPending({signal:k(e.controller.signal,n),...this.options.onWorkerEvent===void 0?{}:{onEvent:e=>this.observeWorkerEvent(t,e)}});this.followWorker(e,r)}async startWorker(e,t){if(!(e.starting||e.status!==`pending`||e.closing||this.lifecycle.signal.aborted)){e.starting=!0;try{let n=this.dependencyReport(e.dependencies);if(n!==void 0){let r=k(t,e.controller.signal,this.lifecycle.signal,AbortSignal.timeout(this.spawnTimeoutMs));await O(this.team.sendMessage({from:this.leadName,target:e.request.name,message:n,delivery:`quiet`,signal:r}),r),r.throwIfAborted()}this.beginWorker(e)}catch(t){if(!e.closing&&!this.lifecycle.signal.aborted){e.status=`failed`,e.error=`dependency handoff failed: ${D(t)}`,L(e),e.start?.(),e.start=void 0;try{this.team.markPending(e.request.name,void 0),this.team.recordOutcome(e.request.name,{kind:`failed`,message:e.error})}catch{}await this.notifyLead(e,`failed: ${e.error}`),e.markSettled(),await this.releaseDependents(e)}}finally{e.dependencies=[]}}}roleSchema(){if(this.roles.size===0)return{};let e=[...this.roles.values()].map(e=>`- ${e.name}: ${e.description}`+(e.whenToUse===void 0?``:` Use when: ${e.whenToUse}`));return{role:{type:`string`,enum:[...this.roles.keys()],description:`Which kind of worker this is.\n${e.join(`
2
2
  `)}`}}}requireRole(e){let t=w(e,`worker role`);if(this.roles.size===0)throw Error(`this managed team declares no roles, so spawn_agent takes no role`);if(!this.roles.has(t))throw Error(`unknown worker role '${t}'; declared roles are ${[...this.roles.keys()].join(`, `)}`);return t}resolveDependencies(e){return[...new Set(e.map(e=>{let t=C(e);if(!this.workerRuntimes.has(t))throw Error(`unknown dependency '${t}'; a worker can only depend on one that already exists`);return t}))]}checkWriteScopes(e,t){let n=this.options.writeScopePolicy??`reject`;if(n===`off`||e.writes.length===0)return[];let r=this.ancestorsOf(t),i=[],a=new Set(this.team.members().filter(e=>e.status===`running`).map(e=>e.conversationId)),o=[...[...this.workerRuntimes.values()].filter(e=>e.status===`pending`||e.status===`running`||this.workerHasWork(e,a)).filter(e=>!r.has(e)),...this.drainingWrites,...[...this.preparing.values()].filter(t=>t.request.name!==e.name)];for(let t of o){let r=e.writes.filter(e=>t.request.writes.some(t=>P(e,t)));if(r.length===0)continue;let a=`'${t.request.name}' also writes ${r.join(`, `)}`;if(n===`reject`)throw Error(`worker '${e.name}' would write files another running worker writes: ${a}. Add '${t.request.name}' to dependsOn so it runs after, or narrow the scopes — or omit writes entirely if this worker only reads.`);i.push(a)}return i}describeWorkerFailure(e,t){if(t?.deadline?.aborted===!0)return this.deadlineFailure();let n=e?.name;return n===`TimeoutError`?this.deadlineFailure():n===`AbortError`?`its work was cancelled before it finished`:D(e)}deadlineFailure(){return`it ran past its ${String(this.workerTimeoutMs)}ms deadline without finishing. Narrow the task, or split it, before delegating it again`}async awaitWorkerNews(e){let t,n,r=new Promise(e=>{n=setTimeout(e,this.holdWaitMs),n.unref?.()});try{let n=this.leadSteer.signal,i=new Promise(e=>{n.aborted?e():n.addEventListener(`abort`,r,{once:!0});function r(){e()}t=()=>n.removeEventListener(`abort`,r)});await O(Promise.race([...e.map(e=>e.settled),r,i]),k(this.lifecycle.signal,this.leadSignal))}finally{n!==void 0&&clearTimeout(n),t?.()}}ancestorsOf(e,t=new Set){for(let n of e)t.has(n)||(t.add(n),this.ancestorsOf(n.dependencies,t));return t}workerHasWork(e,t){return e.session.isRunning||this.drainingWrites.has(e)||(t===void 0?this.team.members().some(t=>t.name===e.request.name&&t.conversationId===e.session.conversationId&&t.status===`running`):t.has(e.session.conversationId))}dependenciesSettled(e,t=[]){return e.every(e=>j.has(e.status)&&!((this.options.writeScopePolicy??`reject`)===`reject`&&t.some(t=>e.request.writes.some(e=>P(t,e)))&&this.workerHasWork(e)))}async releaseDependents(e){if(this.lifecycle.signal.aborted)return;let t=[...this.workerRuntimes.values()].filter(t=>t.status===`pending`&&!t.closing&&t.dependencies.includes(e)&&this.dependenciesSettled(t.dependencies,t.request.writes));for(let e of t)await this.startWorker(e)}dependencyReport(e){let t=!1,n=e.map(e=>{let n=e.request.name;if(e.error!==void 0){let r=e.result?.text,i=r?I(r,this.maxDependencyReportBytes):void 0;return t||=i!==void 0&&i!==r,`- worker address '${n}' FAILED: ${e.error}`+(r?``:`
3
3
  Result payload: absent. No result data was returned.`)+(i===void 0?``:`\nPartial findings (not a completed task): ${i}`)}if(e.result===void 0&&e.status===`closed`)return`- worker address '${n}': closed before reporting. Result payload: absent. No result data was returned.`;let r=e.result?.text??``,i=I(r,this.maxDependencyReportBytes);return t||=i!==r,`- worker address '${n}' finished. ${i===r?`Full`:`Truncated`} result payload:\n${i}`});if(n.length!==0)return[`Dependency result data: worker addresses are routing metadata. Preserve source identifiers supplied in payloads; an absent payload supplies no evidence identifiers.`,...n,...t?[`Read truncated results with read_dependency_result, the original worker address and nextOffset.`]:[]].join(`
4
4
  `)}dependencyReadTool(e){let t=new Map(e.map(e=>[e.request.name,e.evidence]));return i({name:`read_dependency_result`,description:`Read a bounded page from an original dependency result, including after closure. Full handoffs already contain the same result. Use nextOffset until null; partial/failed results are not completed work.`,parameters:{type:`object`,properties:{name:{type:`string`},offset:{type:`integer`,minimum:0}},required:[`name`],additionalProperties:!1},parse(e){if(typeof e!=`object`||!e)throw TypeError(`dependency name and offset required`);let t=Reflect.get(e,`name`),n=Reflect.get(e,`offset`)??0;if(typeof t!=`string`||!Number.isSafeInteger(n)||n<0)throw TypeError(`invalid dependency name or offset`);return{name:t,offset:n}},execute:({name:e,offset:n})=>{let r=t.get(e);if(r===void 0)throw Error(`this worker was not commissioned against that dependency`);let i=r.result?.text??``;if(n>i.length||n>0&&/[\uDC00-\uDFFF]/.test(i[n]))throw RangeError(`offset must be a valid character boundary`);let a=F(i.slice(n),this.maxDependencyReportBytes),o=n+a.length;return{name:e,status:r.status,succeeded:r.result?.succeeded??!1,...r.error===void 0?{}:{error:r.error},text:a,nextOffset:o<i.length?o:null}},isConcurrencySafe:()=>!0})}async followWorker(e,t){let n=e.request.name;try{let r=await t;if(e.status!==`closed`&&!e.closing){let t=e.deadline?.aborted===!0?this.deadlineFailure():M(r,this.options.requireWorkerText===!0);t===void 0?(e.status=`completed`,e.result=Object.freeze({worker:n,agentId:e.session.definition.id,conversationId:e.session.conversationId,text:r.text,succeeded:r.outcome.completed}),L(e),this.team.recordOutcome(n,{kind:`completed`,text:r.text}),await this.notifyLead(e,`finished: ${r.text}`)):(e.status=`failed`,e.error=t,r.text.trim()!==``&&(e.result=Object.freeze({worker:n,agentId:e.session.definition.id,conversationId:e.session.conversationId,text:r.text,succeeded:!1})),L(e),this.team.recordOutcome(n,{kind:`failed`,message:t}),await this.notifyLead(e,`failed: ${t}`+(e.result===void 0?``:`\nPartial findings (not a completed task): ${e.result.text}`)))}}catch(t){if(e.status!==`closed`&&!e.closing){e.status=`failed`,e.error=this.describeWorkerFailure(t,e),L(e);try{this.team.recordOutcome(n,{kind:`failed`,message:e.error})}catch{}await this.notifyLead(e,`failed: ${e.error}`)}}finally{e.markSettled(),await this.releaseDependents(e)}}async notifyLead(e,t){let n=e.request.name;if(e.closing||this.lifecycle.signal.aborted||this.workerRuntimes.get(n)!==e)return;let r=this.deliveryFor(n);r===`quiet`&&(this.unreadReports=!0);try{let i=k(e.controller.signal,this.lifecycle.signal,AbortSignal.timeout(this.spawnTimeoutMs));await O(this.team.sendMessage(s({from:n,target:this.leadName,message:`Worker '${n}' ${I(t,Math.min(this.maxDependencyReportBytes,Math.max(64,Math.floor(this.team.messageByteLimit/4))))}`,delivery:r,signal:i})),i)}catch{}}deliveryFor(e){return this.options.autoLeadCoordination===!1||this.lead.isRunning||this.workerRuntimes.get(e)?.leadDriven!==!0?`quiet`:`wakeup`}unreadReports=!1;leadSteer=new AbortController;leadSignal;async whenQuiet(e){for(;;){e?.throwIfAborted();let t=[...this.workerRuntimes.values()].filter(e=>!e.settledComplete),n=[...this.preparing.values()].map(e=>e.settled);if(t.length+n.length>0&&await O(Promise.all([...t.map(e=>e.settled),...n]),e),await this.team.whenIdle(this.leadName,e),!(this.preparing.size>0||[...this.workerRuntimes.values()].some(e=>!e.settledComplete)))return}}workers(){return Object.freeze([...this.workerRuntimes.values()].map(e=>this.workerView(e)))}workerView(e){return Object.freeze({name:e.request.name,agentId:e.session.definition.id,conversationId:e.session.conversationId,task:e.request.task,status:e.status,context:e.request.context,dependsOn:e.request.dependsOn,writes:e.request.writes,...e.request.role===void 0?{}:{role:e.request.role},...e.warnings.length===0?{}:{warnings:e.warnings},...e.request.specialty===void 0?{}:{specialty:e.request.specialty},...e.result===void 0?{}:{result:e.result},...e.error===void 0?{}:{error:e.error}})}async awaitWorker(e,n={}){let r=C(e),i=this.workerRuntimes.get(r);if(i===void 0)throw Error(`unknown managed worker '${r}'`);let a=t(n.timeoutMs??3e4),o,s=new Promise(e=>{o=setTimeout(e,a)});try{await O(Promise.race([i.settled,s]),n.signal)}finally{clearTimeout(o)}return n.signal?.throwIfAborted(),i.result}async closeWorker(e,t=Error(`managed worker closed`)){let n=C(e),r=this.workerRuntimes.get(n);if(r===void 0)throw Error(`unknown managed worker '${n}'`);return r.closing=!0,r.closeTask??=Promise.resolve().then(()=>this.closeRuntime(r,t)),r.closeTask}async closeRuntime(e,t){let n=e.request.name,r=e.status;e.closing=!0,e.controller.abort(t);let i=AbortSignal.timeout(this.closeTimeoutMs);try{await O(this.team.cancel(n,t),i)}catch{}if(r===`pending`)e.status=`closed`,e.start=void 0,this.team.markPending(n,void 0),e.markSettled();else{try{await O(e.settled,i)}catch{}e.status=`closed`,e.markSettled()}if(L(e),this.workerHasWork(e)&&(e.request.writes.length>0&&this.drainingWrites.add(e),this.team.whenIdle(n).then(async()=>{this.drainingWrites.delete(e);try{this.team.members().some(t=>t.name===n&&t.conversationId===e.session.conversationId)&&this.team.detach(n)}catch{}await this.releaseDependents(e)}).catch(()=>{})),this.workerRuntimes.get(n)===e){this.workerRuntimes.delete(n);try{this.team.detach(n)}catch{}}return e.dependencies=[],await this.releaseDependents(e),r}dispose(e=Error(`managed agent team disposed`)){if(this.disposeTask!==void 0)return this.disposeTask;this.lifecycle.abort(e);let t=[...this.workerRuntimes.keys()];return this.disposeTask=Promise.allSettled([...[...this.preparing.values()].map(e=>e.settled),...t.map(t=>this.closeWorker(t,e))]).then(()=>void 0),this.disposeTask}removeWorker(e){let t=C(e),n=this.workerRuntimes.get(t);if(n===void 0)throw Error(`unknown managed worker '${t}'`);if(n.status===`pending`||n.status===`running`||!n.settledComplete||n.session.isRunning)throw Error(`cannot remove running managed worker '${t}'`);this.team.detach(t),this.workerRuntimes.delete(t)}controlTools(){return Object.freeze([i({name:`spawn_agent`,description:[`Create a managed worker for the supplied task.`,`Returns a lifecycle view after setup; a dependent may still be pending.`,`Use list_agents for retained status/results and wait_agents for bounded waits.`,`dependsOn binds already registered producer instances; writes declares relative scheduling scopes under host policy.`].join(` `),parameters:{type:`object`,properties:{name:{type:`string`,description:`Optional unique worker address; omitted generates worker_N.`},task:{type:`string`,description:`Task and any output contract assigned to the worker.`},specialty:{type:`string`,description:`Optional worker role or domain specialization.`},context:{type:`string`,enum:[`fresh`,`fork`],description:`fresh starts from the task; fork also copies the completed lead conversation.`},dependsOn:{type:`array`,items:{type:`string`},description:`Names of workers that must finish before this one starts. The worker is created now and held until they do, then given what they produced. Register the producers first; a dependency cannot name a future or still-preparing worker. Failed producers also release dependents with failure status.`},writes:{type:`array`,items:{type:`string`},description:`Workspace-relative scheduling scopes. Overlaps are rejected, warned or allowed according to host writeScopePolicy. This is not filesystem authorization. Omit when no writes are declared; placeholder paths claim real scopes.`},...this.roleSchema()},required:[`task`],additionalProperties:!1},parse:v,execute:async(e,t)=>A(await this.spawn(e,t.signal)),timeoutMs:this.spawnTimeoutMs,isConcurrencySafe:()=>!0}),i({name:`close_agent`,budgetExempt:!0,description:[`Close a worker you no longer need and free its slot.`,`A finished worker still occupies one until closed, so close it once you have read its result.`,`A running or pending worker is kept alive by default so it can finish its final report.`,this.options.allowModelWorkerCancellation===!1?`The host requires worker reports: you cannot cancel unfinished workers. Wait for their result.`:`Set cancelRunning: true only to deliberately abandon unfinished work and cancel it.`,`Returns the status it held before closing.`].join(` `),parameters:{type:`object`,properties:{name:{type:`string`,description:`Worker address returned by spawn_agent.`},cancelRunning:{type:`boolean`,description:`Explicitly cancel an unfinished worker. Defaults to false.`}},required:[`name`],additionalProperties:!1},parse:_,execute:async({name:e,cancelRunning:t})=>{let n=this.workerRuntimes.get(e);return n!==void 0&&(!t||this.options.allowModelWorkerCancellation===!1)&&(n.status===`pending`||n.status===`running`||n.session.isRunning)?A({worker:e,closed:!1,status:n.status===`pending`?`pending`:`running`,instruction:`The worker has not finished its final report. Use wait_agents and read its completed result before closing.`+(this.options.allowModelWorkerCancellation===!1?` Model cancellation is disabled by the host.`:` To deliberately abandon this work, call close_agent with cancelRunning: true.`)}):A({worker:e,closed:!0,previousStatus:await this.closeWorker(e)})},timeoutMs:this.workerTimeoutMs})])}forkLeadHistory(e){let t=x(this.lead.snapshot().history);return o.fromSnapshot({version:1,entries:t},e??{})}async workerDefinition(e){if(this.options.workerFactory!==void 0)return this.options.workerFactory(e);let t=this.options.workerTemplate??this.options.lead,n=e.role===void 0?void 0:this.roles.get(e.role),r=n===void 0?``:` You are the '${n.name}' worker. ${n.instructions??n.description}`,i=e.specialty===void 0?``:` Your specialization is: ${e.specialty}.`;return c(t,{id:e.name,name:e.name,instructions:`${t.instructions}\n\nYou are dynamically assigned worker '${e.name}'.${r}${i}`})}nextWorkerName(){for(;;){let e=`worker_${++this.workerSequence}`;if(!this.preparing.has(e)&&!this.workerRuntimes.has(e)&&!this.team.members().some(t=>t.name===e))return e}}async observeWorkerEvent(t,n){let r=Promise.resolve().then(()=>this.options.onWorkerEvent?.(t,n));await e(r,this.observerTimeoutMs)}};function h(e){return new m(e)}function g(e,t){let n=new a;if(e!==void 0){let t=`names`in e?e.names().map(t=>e.get(t)).filter(e=>e!==void 0):e;for(let e of t)n.register(e)}for(let e of t)n.register(e);return n}function _(e){let t=S(e,`close_agent arguments`);if(Object.keys(t).some(e=>e!==`name`&&e!==`cancelRunning`))throw TypeError(`close_agent arguments contain unknown fields`);if(t.cancelRunning!==void 0&&typeof t.cancelRunning!=`boolean`)throw TypeError(`close_agent cancelRunning must be a boolean`);return{name:C(t.name),cancelRunning:t.cancelRunning===!0}}function v(e){let t=S(e,`spawn_agent arguments`),n=new Set([`name`,`task`,`specialty`,`context`,`role`,`dependsOn`,`writes`]);if(Object.keys(t).some(e=>!n.has(e)))throw TypeError(`spawn_agent arguments contain unknown fields`);return{task:w(t.task,`worker task`),...t.name===void 0?{}:{name:C(t.name)},...t.specialty===void 0?{}:{specialty:w(t.specialty,`worker specialty`)},...t.context===void 0?{}:{context:b(t.context)},...t.role===void 0?{}:{role:w(t.role,`worker role`)},...t.dependsOn===void 0?{}:{dependsOn:y(t.dependsOn,`dependsOn`)},...t.writes===void 0?{}:{writes:y(t.writes,`writes`)}}}function y(e,t){if(!Array.isArray(e))throw TypeError(`${t} must be an array of strings`);return e.map(e=>w(e,`${t} entry`))}function b(e){if(e!==`fresh`&&e!==`fork`)throw TypeError(`worker context must be 'fresh' or 'fork'`);return e}function x(e){let t=new Set,n=0;return e.entries.forEach((e,r)=>{let i=e.event;if(i.kind===`tool-call`)t.add(i.callId);else if(i.kind===`tool-result`)t.delete(i.callId);else if(i.kind===`assistant`)for(let e of i.message.content)e.type===`tool-call`&&t.add(e.id);t.size===0&&(i.kind!==`assistant`||i.interrupted!==!0)&&(n=r+1)}),e.entries.slice(0,n)}function S(e,t){if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(`${t} must be an object`);return e}function C(e){let t=w(e,`managed agent name`);if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t))throw TypeError(`managed agent name must start with a letter and contain only letters, digits, _ or -`);if(t.length>128)throw TypeError(`managed agent name must not exceed 128 characters`);return t}function w(e,t){if(typeof e!=`string`||e.trim().length===0)throw TypeError(`${t} must be a non-empty string`);return e}function T(e,t,n){let r=w(e,t);if(new TextEncoder().encode(r).byteLength>n)throw TypeError(`${t} exceeds the ${n}-byte limit`);return r}function E(e,t){if(!Number.isSafeInteger(e)||e<1)throw TypeError(`${t} must be a positive integer`);return e}function D(e){return e instanceof Error?e.message:String(e)}async function O(e,t){if(t===void 0)return e;if(t.aborted)throw e.catch(()=>void 0),t.reason??Error(`managed worker aborted`);return await new Promise((n,r)=>{let i=()=>{t.removeEventListener(`abort`,i),r(t.reason??Error(`managed worker aborted`))};t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function k(...e){let t=e.filter(e=>e!==void 0);return t.length===1?t[0]:AbortSignal.any(t)}function A(e){return e}const j=new Set([`completed`,`failed`,`closed`]);function M(e,t){let n=e.outcome.reason;if(n.kind===`error`)return n.failure.message;if(n.kind===`max-tokens`)return`the model stopped at its output limit`;if(n.kind===`usage-unavailable`)return`the provider reported no usage for a billed call`;if(n.kind===`aborted`)return`the run was aborted`;if(n.kind===`budget-exhausted`&&!e.outcome.completed)return`the run stopped at its ${n.budget} limit before completing the task`;if(t&&e.text.trim()===``)return`it produced no answer`}function N(e){let t=w(e,`worker write scope`).trim().split(`\\`).join(`/`);if(t.startsWith(`/`)||/^[a-zA-Z]:/.test(t))throw TypeError(`a worker write scope must be workspace-relative`);let n=[];for(let e of t.split(`/`))if(e!==``&&e!==`.`){if(e===`..`){if(n.length===0)throw TypeError(`a worker write scope must not escape the workspace`);n.pop()}else n.push(e)}if(n.length===0)throw TypeError(`a worker write scope must name a file or directory, not the whole workspace`);return n.join(`/`)}function P(e,t){return e===t||e.startsWith(`${t}/`)||t.startsWith(`${e}/`)}function F(e,t){return new TextDecoder(`utf-8`,{fatal:!1}).decode(new TextEncoder().encode(e).subarray(0,t),{stream:!0})}function I(e,t){let n=new TextEncoder().encode(e);if(n.byteLength<=t)return e;let r=`