@minpeter/pss-runtime 0.1.0-next.0 → 0.1.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +223 -191
  2. package/dist/agent-child-runs.js +16 -0
  3. package/dist/agent-child-runs.js.map +1 -0
  4. package/dist/agent-host-capabilities.js +9 -0
  5. package/dist/agent-host-capabilities.js.map +1 -0
  6. package/dist/agent-host-session-store.js +12 -0
  7. package/dist/agent-host-session-store.js.map +1 -0
  8. package/dist/agent-loop.js +59 -35
  9. package/dist/agent-loop.js.map +1 -1
  10. package/dist/agent-namespace.js +24 -0
  11. package/dist/agent-namespace.js.map +1 -0
  12. package/dist/agent-options.d.ts +35 -0
  13. package/dist/agent-options.js +16 -0
  14. package/dist/agent-options.js.map +1 -0
  15. package/dist/agent-resume.js +143 -0
  16. package/dist/agent-resume.js.map +1 -0
  17. package/dist/agent-session-entry.d.ts +13 -0
  18. package/dist/agent-validation.js +35 -0
  19. package/dist/agent-validation.js.map +1 -0
  20. package/dist/agent.d.ts +8 -33
  21. package/dist/agent.js +131 -55
  22. package/dist/agent.js.map +1 -1
  23. package/dist/child-session-cleanups.js +61 -0
  24. package/dist/child-session-cleanups.js.map +1 -0
  25. package/dist/execution/host.js +14 -0
  26. package/dist/execution/host.js.map +1 -0
  27. package/dist/execution/index.d.ts +4 -0
  28. package/dist/execution/index.js +3 -0
  29. package/dist/execution/memory-notifications.js +54 -0
  30. package/dist/execution/memory-notifications.js.map +1 -0
  31. package/dist/execution/memory-state.js +34 -0
  32. package/dist/execution/memory-state.js.map +1 -0
  33. package/dist/execution/memory-store.js +203 -0
  34. package/dist/execution/memory-store.js.map +1 -0
  35. package/dist/execution/memory.d.ts +7 -0
  36. package/dist/execution/memory.js +28 -0
  37. package/dist/execution/memory.js.map +1 -0
  38. package/dist/execution/run.js +55 -0
  39. package/dist/execution/run.js.map +1 -0
  40. package/dist/execution/types.d.ts +155 -0
  41. package/dist/index.d.ts +9 -10
  42. package/dist/index.js +1 -6
  43. package/dist/llm-tool-execution.d.ts +35 -0
  44. package/dist/llm-tool-execution.js +126 -0
  45. package/dist/llm-tool-execution.js.map +1 -0
  46. package/dist/llm.d.ts +11 -15
  47. package/dist/llm.js +5 -9
  48. package/dist/llm.js.map +1 -1
  49. package/dist/plugins.d.ts +20 -0
  50. package/dist/plugins.js +14 -0
  51. package/dist/plugins.js.map +1 -0
  52. package/dist/session/events.d.ts +26 -20
  53. package/dist/session/input-normalization.js +66 -0
  54. package/dist/session/input-normalization.js.map +1 -0
  55. package/dist/session/input.d.ts +0 -4
  56. package/dist/session/mapping.js +1 -2
  57. package/dist/session/mapping.js.map +1 -1
  58. package/dist/session/run.js +1 -0
  59. package/dist/session/run.js.map +1 -1
  60. package/dist/session/runtime-input.js +20 -58
  61. package/dist/session/runtime-input.js.map +1 -1
  62. package/dist/session/session-errors.js +18 -0
  63. package/dist/session/session-errors.js.map +1 -0
  64. package/dist/session/session-events.js +59 -0
  65. package/dist/session/session-events.js.map +1 -0
  66. package/dist/session/session-execution.js +88 -0
  67. package/dist/session/session-execution.js.map +1 -0
  68. package/dist/session/session-kill.js +23 -0
  69. package/dist/session/session-kill.js.map +1 -0
  70. package/dist/session/session-notification.js +58 -0
  71. package/dist/session/session-notification.js.map +1 -0
  72. package/dist/session/session-runtime-drain.js +22 -0
  73. package/dist/session/session-runtime-drain.js.map +1 -0
  74. package/dist/session/session-state.js +102 -0
  75. package/dist/session/session-state.js.map +1 -0
  76. package/dist/session/session-turn-error.js +35 -0
  77. package/dist/session/session-turn-error.js.map +1 -0
  78. package/dist/session/session-turn-processor.js +135 -0
  79. package/dist/session/session-turn-processor.js.map +1 -0
  80. package/dist/session/session.js +125 -335
  81. package/dist/session/session.js.map +1 -1
  82. package/dist/session/snapshot.js +5 -31
  83. package/dist/session/snapshot.js.map +1 -1
  84. package/dist/session/store/file.d.ts +1 -0
  85. package/dist/session/store/file.js +14 -0
  86. package/dist/session/store/file.js.map +1 -1
  87. package/dist/session/store/memory.d.ts +1 -0
  88. package/dist/session/store/memory.js +5 -0
  89. package/dist/session/store/memory.js.map +1 -1
  90. package/dist/session/store/types.d.ts +1 -0
  91. package/dist/subagent-background-child-run-state.js +51 -0
  92. package/dist/subagent-background-child-run-state.js.map +1 -0
  93. package/dist/subagent-background-child-run.js +103 -0
  94. package/dist/subagent-background-child-run.js.map +1 -0
  95. package/dist/subagent-background-in-process.js +98 -0
  96. package/dist/subagent-background-in-process.js.map +1 -0
  97. package/dist/subagent-background-notification-inbox.js +106 -0
  98. package/dist/subagent-background-notification-inbox.js.map +1 -0
  99. package/dist/subagent-background-notify.js +136 -0
  100. package/dist/subagent-background-notify.js.map +1 -0
  101. package/dist/subagent-background-resume-group.js +99 -0
  102. package/dist/subagent-background-resume-group.js.map +1 -0
  103. package/dist/subagent-background-runner.js +115 -0
  104. package/dist/subagent-background-runner.js.map +1 -0
  105. package/dist/subagent-background-schedule.js +43 -0
  106. package/dist/subagent-background-schedule.js.map +1 -0
  107. package/dist/subagent-child-run.js +68 -0
  108. package/dist/subagent-child-run.js.map +1 -0
  109. package/dist/subagent-job-cancel.js +84 -0
  110. package/dist/subagent-job-cancel.js.map +1 -0
  111. package/dist/subagent-job-observer.js +19 -0
  112. package/dist/subagent-job-observer.js.map +1 -0
  113. package/dist/subagent-job-output.js +87 -0
  114. package/dist/subagent-job-output.js.map +1 -0
  115. package/dist/subagent-job-state.js +66 -0
  116. package/dist/subagent-job-state.js.map +1 -0
  117. package/dist/subagent-jobs.js +96 -0
  118. package/dist/subagent-jobs.js.map +1 -0
  119. package/dist/subagent-prompt-schema.js +114 -0
  120. package/dist/subagent-prompt-schema.js.map +1 -0
  121. package/dist/subagent-run.js +111 -0
  122. package/dist/subagent-run.js.map +1 -0
  123. package/dist/subagents.js +125 -0
  124. package/dist/subagents.js.map +1 -0
  125. package/package.json +11 -6
  126. package/dist/plugins/compaction.d.ts +0 -15
  127. package/dist/plugins/compaction.js +0 -98
  128. package/dist/plugins/compaction.js.map +0 -1
  129. package/dist/plugins/index.d.ts +0 -5
  130. package/dist/plugins/index.js +0 -5
  131. package/dist/plugins/memory.d.ts +0 -11
  132. package/dist/plugins/memory.js +0 -146
  133. package/dist/plugins/memory.js.map +0 -1
  134. package/dist/plugins/runner.d.ts +0 -1
  135. package/dist/plugins/runner.js +0 -83
  136. package/dist/plugins/runner.js.map +0 -1
  137. package/dist/plugins/scope.js +0 -13
  138. package/dist/plugins/scope.js.map +0 -1
  139. package/dist/plugins/sessions.d.ts +0 -12
  140. package/dist/plugins/sessions.js +0 -34
  141. package/dist/plugins/sessions.js.map +0 -1
  142. package/dist/plugins/tool-hook-handlers.js +0 -77
  143. package/dist/plugins/tool-hook-handlers.js.map +0 -1
  144. package/dist/plugins/tool-hook-results.js +0 -64
  145. package/dist/plugins/tool-hook-results.js.map +0 -1
  146. package/dist/plugins/tool-hooks.js +0 -111
  147. package/dist/plugins/tool-hooks.js.map +0 -1
  148. package/dist/plugins/types.d.ts +0 -105
  149. package/dist/plugins/types.js +0 -20
  150. package/dist/plugins/types.js.map +0 -1
  151. package/dist/session/lifecycle.d.ts +0 -12
  152. package/dist/session/lifecycle.js +0 -126
  153. package/dist/session/lifecycle.js.map +0 -1
  154. package/dist/session/overlay-anchor.js +0 -151
  155. package/dist/session/overlay-anchor.js.map +0 -1
  156. package/dist/session/overlay.js +0 -141
  157. package/dist/session/overlay.js.map +0 -1
  158. package/dist/session/snapshot.d.ts +0 -1
  159. /package/dist/{agent-loop.d.ts → session/history.d.ts} +0 -0
  160. /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
  161. /package/dist/{plugins/scope.d.ts → session/session-state.d.ts} +0 -0
@@ -1,53 +1,36 @@
1
1
  import { modelMessageToAgentEvents } from "./session/mapping.js";
2
2
  //#region src/agent-loop.ts
3
- async function runAgentLoop({ emit, history, llm, signal = new AbortController().signal, stepLifecycle }) {
4
- let stepIndex = 0;
3
+ async function runAgentLoop({ captureObserverEvents = captureNoObserverEvents, emit, history, llm, signal = new AbortController().signal, toolExecution }) {
5
4
  while (true) {
6
- if (signal.aborted) return "aborted";
7
- await stepLifecycle?.beforeStep?.({
8
- history: history.modelSnapshot(),
9
- signal,
10
- stepIndex
11
- });
12
5
  if (signal.aborted) return "aborted";
13
6
  if (await emitBoundary({
14
7
  emit,
15
8
  event: { type: "step-start" },
16
9
  signal
17
10
  }) === "aborted") return "aborted";
18
- await stepLifecycle?.beforeInference?.({
19
- history: history.modelSnapshot(),
20
- signal,
21
- stepIndex
22
- });
23
- if (signal.aborted) return "aborted";
24
- const output = await readLlmOutput({
11
+ const capturedOutput = await captureObserverEvents(() => readLlmOutput({
25
12
  history,
26
13
  llm,
27
- signal
28
- });
14
+ signal,
15
+ toolExecution
16
+ }));
17
+ const output = capturedOutput.value;
29
18
  if (output === "aborted") return "aborted";
30
- const result = appendStepOutput({
19
+ const result = await appendCapturedStepOutput({
20
+ capturedOutput,
31
21
  emit,
32
22
  history,
33
23
  output,
34
24
  signal
35
25
  });
36
26
  if (result === "aborted") return "aborted";
37
- await runAfterStepLifecycle(stepLifecycle, {
38
- history: history.modelSnapshot(),
39
- result,
40
- signal,
41
- stepIndex
42
- });
43
27
  const stepEndDecision = await emitBoundary({
44
28
  emit,
45
29
  event: { type: "step-end" },
46
30
  signal
47
31
  });
48
32
  if (stepEndDecision === "aborted") return "aborted";
49
- if (result === "completed" && !stepEndDecision?.runtimeInputAdded && !stepEndDecision?.overlayInputAdded) return "completed";
50
- stepIndex += 1;
33
+ if (result === "completed" && !stepEndDecision?.runtimeInputAdded) return "completed";
51
34
  }
52
35
  }
53
36
  async function emitBoundary({ emit, event, signal }) {
@@ -74,34 +57,75 @@ function createAbortBoundary(signal) {
74
57
  promise
75
58
  };
76
59
  }
77
- async function runAfterStepLifecycle(stepLifecycle, context) {
78
- const afterStep = stepLifecycle?.afterStep;
79
- if (!afterStep) return;
80
- await Promise.allSettled([Promise.resolve().then(() => afterStep(context))]);
60
+ async function captureNoObserverEvents(callback) {
61
+ return {
62
+ events: [],
63
+ release: releaseNoObserverEvents,
64
+ value: await callback()
65
+ };
81
66
  }
82
- async function readLlmOutput({ history, llm, signal }) {
67
+ function releaseNoObserverEvents() {}
68
+ async function readLlmOutput({ history, llm, signal, toolExecution }) {
83
69
  try {
84
70
  return await llm({
85
71
  history: history.modelSnapshot(),
86
- signal
72
+ signal,
73
+ toolExecution
87
74
  });
88
75
  } catch (error) {
89
76
  if (signal.aborted) return "aborted";
90
77
  throw error;
91
78
  }
92
79
  }
93
- function appendStepOutput({ emit, history, output, signal }) {
80
+ async function appendCapturedStepOutput({ capturedOutput, emit, history, output, signal }) {
81
+ try {
82
+ return await appendStepOutput({
83
+ emit,
84
+ history,
85
+ observerEvents: capturedOutput.events,
86
+ output,
87
+ signal
88
+ });
89
+ } finally {
90
+ capturedOutput.release();
91
+ }
92
+ }
93
+ async function appendStepOutput({ emit, history, observerEvents, output, signal }) {
94
94
  if (signal.aborted) return "aborted";
95
95
  let shouldContinue = false;
96
+ const pendingObserverEvents = observerEvents;
97
+ const flushObserverEvents = async (shouldFlush = () => true) => {
98
+ for (let index = 0; index < pendingObserverEvents.length;) {
99
+ const event = pendingObserverEvents[index];
100
+ if (!(event && shouldFlush(event))) {
101
+ index += 1;
102
+ continue;
103
+ }
104
+ pendingObserverEvents.splice(index, 1);
105
+ await emit(event);
106
+ }
107
+ };
96
108
  for (const message of output) {
97
109
  if (signal.aborted) return "aborted";
98
110
  history.appendModelMessage(message);
99
111
  const events = modelMessageToAgentEvents(message);
100
- for (const event of events) emit(event);
101
- if (events.some((event) => event.type === "tool-call")) shouldContinue = true;
112
+ const hasToolResult = events.some((event) => event.type === "tool-result");
113
+ for (const event of events) {
114
+ await emit(event);
115
+ if (event.type === "tool-call") {
116
+ shouldContinue = true;
117
+ await flushObserverEvents(isLaunchOrBlockingObserverEvent);
118
+ }
119
+ }
120
+ if (hasToolResult) await flushObserverEvents();
102
121
  }
122
+ await flushObserverEvents();
103
123
  return shouldContinue ? "continue" : "completed";
104
124
  }
125
+ function isLaunchOrBlockingObserverEvent(event) {
126
+ if (event.type === "subagent-job-update") return false;
127
+ return !(event.type === "subagent-job-end" && event.task_id);
128
+ }
105
129
  //#endregion
106
130
  export { runAgentLoop };
107
131
 
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { Llm, LlmOutput } from \"./llm\";\nimport type { AgentEvent, AgentEventListener } from \"./session/events\";\nimport { modelMessageToAgentEvents } from \"./session/mapping\";\n\ntype MaybePromise<T> = Promise<T> | T;\n\ninterface ModelHistory {\n appendModelMessage(message: ModelMessage): void;\n modelSnapshot(): ModelMessage[];\n}\n\ninterface RunAgentLoopOptions {\n emit: AgentLoopEventListener;\n history: ModelHistory;\n llm: Llm;\n signal?: AbortSignal;\n stepLifecycle?: AgentStepLifecycle;\n}\n\nexport type AgentLoopResult = \"completed\" | \"aborted\";\nexport type AgentStepResult = \"completed\" | \"continue\";\nexport interface AgentBeforeStepContext {\n readonly history: readonly ModelMessage[];\n readonly signal: AbortSignal;\n readonly stepIndex: number;\n}\nexport interface AgentAfterStepContext extends AgentBeforeStepContext {\n readonly result: AgentStepResult;\n}\nexport interface AgentStepLifecycle {\n afterStep?(context: AgentAfterStepContext): MaybePromise<void>;\n beforeInference?(context: AgentBeforeStepContext): MaybePromise<void>;\n beforeStep?(context: AgentBeforeStepContext): MaybePromise<void>;\n}\ntype AgentLoopBoundaryEvent = Extract<\n AgentEvent,\n { type: \"step-end\" } | { type: \"step-start\" }\n>;\ninterface AgentLoopBoundaryDecision {\n readonly overlayInputAdded?: boolean;\n readonly runtimeInputAdded?: boolean;\n}\ntype AgentLoopEventListener = (\n event: AgentEvent\n) =>\n | AgentLoopBoundaryDecision\n | Promise<AgentLoopBoundaryDecision | undefined>\n | undefined;\ntype StepOutputResult = AgentStepResult | \"aborted\";\n\nexport async function runAgentLoop({\n emit,\n history,\n llm,\n signal = new AbortController().signal,\n stepLifecycle,\n}: RunAgentLoopOptions): Promise<AgentLoopResult> {\n let stepIndex = 0;\n\n while (true) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n await stepLifecycle?.beforeStep?.({\n history: history.modelSnapshot(),\n signal,\n stepIndex,\n });\n\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const stepStartDecision = await emitBoundary({\n emit,\n event: { type: \"step-start\" },\n signal,\n });\n\n if (stepStartDecision === \"aborted\") {\n return \"aborted\";\n }\n\n await stepLifecycle?.beforeInference?.({\n history: history.modelSnapshot(),\n signal,\n stepIndex,\n });\n\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const output = await readLlmOutput({ history, llm, signal });\n\n if (output === \"aborted\") {\n return \"aborted\";\n }\n\n const result = appendStepOutput({ emit, history, output, signal });\n\n if (result === \"aborted\") {\n return \"aborted\";\n }\n\n await runAfterStepLifecycle(stepLifecycle, {\n history: history.modelSnapshot(),\n result,\n signal,\n stepIndex,\n });\n\n const stepEndDecision = await emitBoundary({\n emit,\n event: { type: \"step-end\" },\n signal,\n });\n\n if (stepEndDecision === \"aborted\") {\n return \"aborted\";\n }\n\n // Runtime input after step-end intentionally forces another inference step,\n // even after final-looking assistant text. Unconditional insertion on every\n // step-end can create an unbounded loop.\n if (\n result === \"completed\" &&\n !stepEndDecision?.runtimeInputAdded &&\n !stepEndDecision?.overlayInputAdded\n ) {\n return \"completed\";\n }\n\n stepIndex += 1;\n }\n}\n\nasync function emitBoundary({\n emit,\n event,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & {\n event: AgentLoopBoundaryEvent;\n signal: AbortSignal;\n}): Promise<AgentLoopBoundaryDecision | \"aborted\" | undefined> {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const abort = createAbortBoundary(signal);\n try {\n return await Promise.race([Promise.resolve(emit(event)), abort.promise]);\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n } finally {\n abort.dispose();\n }\n}\n\nfunction createAbortBoundary(signal: AbortSignal): {\n dispose: () => void;\n promise: Promise<\"aborted\">;\n} {\n let dispose: () => void = () => undefined;\n\n const promise = new Promise<\"aborted\">((resolve) => {\n const onAbort = () => resolve(\"aborted\");\n dispose = () => signal.removeEventListener(\"abort\", onAbort);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n return { dispose, promise };\n}\n\nasync function runAfterStepLifecycle(\n stepLifecycle: AgentStepLifecycle | undefined,\n context: AgentAfterStepContext\n): Promise<void> {\n const afterStep = stepLifecycle?.afterStep;\n if (!afterStep) {\n return;\n }\n\n await Promise.allSettled([Promise.resolve().then(() => afterStep(context))]);\n}\n\nasync function readLlmOutput({\n history,\n llm,\n signal,\n}: Pick<RunAgentLoopOptions, \"history\" | \"llm\"> & {\n signal: AbortSignal;\n}): Promise<LlmOutput | \"aborted\"> {\n try {\n return await llm({ history: history.modelSnapshot(), signal });\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n }\n}\n\nfunction appendStepOutput({\n emit,\n history,\n output,\n signal,\n}: { emit: AgentEventListener; history: ModelHistory } & {\n output: LlmOutput;\n signal: AbortSignal;\n}): StepOutputResult {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n let shouldContinue = false;\n\n for (const message of output) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n history.appendModelMessage(message);\n const events = modelMessageToAgentEvents(message);\n\n for (const event of events) {\n emit(event);\n }\n\n if (events.some((event) => event.type === \"tool-call\")) {\n shouldContinue = true;\n }\n }\n\n return shouldContinue ? \"continue\" : \"completed\";\n}\n"],"mappings":";;AAmDA,eAAsB,aAAa,EACjC,MACA,SACA,KACA,SAAS,IAAI,gBAAgB,EAAE,QAC/B,iBACgD;CAChD,IAAI,YAAY;CAEhB,OAAO,MAAM;EACX,IAAI,OAAO,SACT,OAAO;EAGT,MAAM,eAAe,aAAa;GAChC,SAAS,QAAQ,cAAc;GAC/B;GACA;EACF,CAAC;EAED,IAAI,OAAO,SACT,OAAO;EAST,IAAI,MAN4B,aAAa;GAC3C;GACA,OAAO,EAAE,MAAM,aAAa;GAC5B;EACF,CAAC,MAEyB,WACxB,OAAO;EAGT,MAAM,eAAe,kBAAkB;GACrC,SAAS,QAAQ,cAAc;GAC/B;GACA;EACF,CAAC;EAED,IAAI,OAAO,SACT,OAAO;EAGT,MAAM,SAAS,MAAM,cAAc;GAAE;GAAS;GAAK;EAAO,CAAC;EAE3D,IAAI,WAAW,WACb,OAAO;EAGT,MAAM,SAAS,iBAAiB;GAAE;GAAM;GAAS;GAAQ;EAAO,CAAC;EAEjE,IAAI,WAAW,WACb,OAAO;EAGT,MAAM,sBAAsB,eAAe;GACzC,SAAS,QAAQ,cAAc;GAC/B;GACA;GACA;EACF,CAAC;EAED,MAAM,kBAAkB,MAAM,aAAa;GACzC;GACA,OAAO,EAAE,MAAM,WAAW;GAC1B;EACF,CAAC;EAED,IAAI,oBAAoB,WACtB,OAAO;EAMT,IACE,WAAW,eACX,CAAC,iBAAiB,qBAClB,CAAC,iBAAiB,mBAElB,OAAO;EAGT,aAAa;CACf;AACF;AAEA,eAAe,aAAa,EAC1B,MACA,OACA,UAI6D;CAC7D,IAAI,OAAO,SACT,OAAO;CAGT,MAAM,QAAQ,oBAAoB,MAAM;CACxC,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,QAAQ,QAAQ,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC;CACzE,SAAS,OAAO;EACd,IAAI,OAAO,SACT,OAAO;EAGT,MAAM;CACR,UAAU;EACR,MAAM,QAAQ;CAChB;AACF;AAEA,SAAS,oBAAoB,QAG3B;CACA,IAAI,gBAA4B,KAAA;CAEhC,MAAM,UAAU,IAAI,SAAoB,YAAY;EAClD,MAAM,gBAAgB,QAAQ,SAAS;EACvC,gBAAgB,OAAO,oBAAoB,SAAS,OAAO;EAC3D,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC1D,CAAC;CAED,OAAO;EAAE;EAAS;CAAQ;AAC5B;AAEA,eAAe,sBACb,eACA,SACe;CACf,MAAM,YAAY,eAAe;CACjC,IAAI,CAAC,WACH;CAGF,MAAM,QAAQ,WAAW,CAAC,QAAQ,QAAQ,EAAE,WAAW,UAAU,OAAO,CAAC,CAAC,CAAC;AAC7E;AAEA,eAAe,cAAc,EAC3B,SACA,KACA,UAGiC;CACjC,IAAI;EACF,OAAO,MAAM,IAAI;GAAE,SAAS,QAAQ,cAAc;GAAG;EAAO,CAAC;CAC/D,SAAS,OAAO;EACd,IAAI,OAAO,SACT,OAAO;EAGT,MAAM;CACR;AACF;AAEA,SAAS,iBAAiB,EACxB,MACA,SACA,QACA,UAImB;CACnB,IAAI,OAAO,SACT,OAAO;CAGT,IAAI,iBAAiB;CAErB,KAAK,MAAM,WAAW,QAAQ;EAC5B,IAAI,OAAO,SACT,OAAO;EAGT,QAAQ,mBAAmB,OAAO;EAClC,MAAM,SAAS,0BAA0B,OAAO;EAEhD,KAAK,MAAM,SAAS,QAClB,KAAK,KAAK;EAGZ,IAAI,OAAO,MAAM,UAAU,MAAM,SAAS,WAAW,GACnD,iBAAiB;CAErB;CAEA,OAAO,iBAAiB,aAAa;AACvC"}
1
+ {"version":3,"file":"agent-loop.js","names":[],"sources":["../src/agent-loop.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { RuntimeLlm, RuntimeLlmOutput } from \"./llm\";\nimport type { RuntimeToolExecutionContext } from \"./llm-tool-execution\";\nimport type { AgentEvent } from \"./session/events\";\nimport { modelMessageToAgentEvents } from \"./session/mapping\";\n\ninterface ModelHistory {\n appendModelMessage(message: ModelMessage): void;\n modelSnapshot(): ModelMessage[];\n}\n\ninterface RunAgentLoopOptions {\n captureObserverEvents?: ObserverEventCapture;\n emit: AgentLoopEventListener;\n history: ModelHistory;\n llm: RuntimeLlm;\n signal?: AbortSignal;\n toolExecution?: RuntimeToolExecutionContext;\n}\n\ntype AgentLoopResult = \"completed\" | \"aborted\";\ntype AgentLoopBoundaryEvent = Extract<\n AgentEvent,\n { type: \"step-end\" } | { type: \"step-start\" }\n>;\ninterface AgentLoopBoundaryDecision {\n readonly runtimeInputAdded?: boolean;\n}\ntype AgentLoopEventListener = (\n event: AgentEvent\n) =>\n | AgentLoopBoundaryDecision\n | Promise<AgentLoopBoundaryDecision | undefined>\n | undefined;\ntype StepOutputResult = \"aborted\" | \"completed\" | \"continue\";\ninterface ObserverEventCaptureResult<T> {\n readonly events: AgentEvent[];\n readonly release: () => void;\n readonly value: T;\n}\ntype ObserverEventCapture = <T>(\n callback: () => Promise<T>\n) => Promise<ObserverEventCaptureResult<T>>;\n\nexport async function runAgentLoop({\n captureObserverEvents = captureNoObserverEvents,\n emit,\n history,\n llm,\n signal = new AbortController().signal,\n toolExecution,\n}: RunAgentLoopOptions): Promise<AgentLoopResult> {\n while (true) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const stepStartDecision = await emitBoundary({\n emit,\n event: { type: \"step-start\" },\n signal,\n });\n\n if (stepStartDecision === \"aborted\") {\n return \"aborted\";\n }\n\n const capturedOutput = await captureObserverEvents(() =>\n readLlmOutput({ history, llm, signal, toolExecution })\n );\n const output = capturedOutput.value;\n\n if (output === \"aborted\") {\n return \"aborted\";\n }\n\n const result = await appendCapturedStepOutput({\n capturedOutput,\n emit,\n history,\n output,\n signal,\n });\n\n if (result === \"aborted\") {\n return \"aborted\";\n }\n\n const stepEndDecision = await emitBoundary({\n emit,\n event: { type: \"step-end\" },\n signal,\n });\n\n if (stepEndDecision === \"aborted\") {\n return \"aborted\";\n }\n\n // Runtime input after step-end intentionally forces another inference step,\n // even after final-looking assistant text. Unconditional insertion on every\n // step-end can create an unbounded loop.\n if (result === \"completed\" && !stepEndDecision?.runtimeInputAdded) {\n return \"completed\";\n }\n }\n}\n\nasync function emitBoundary({\n emit,\n event,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & {\n event: AgentLoopBoundaryEvent;\n signal: AbortSignal;\n}): Promise<AgentLoopBoundaryDecision | \"aborted\" | undefined> {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n const abort = createAbortBoundary(signal);\n try {\n return await Promise.race([Promise.resolve(emit(event)), abort.promise]);\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n } finally {\n abort.dispose();\n }\n}\n\nfunction createAbortBoundary(signal: AbortSignal): {\n dispose: () => void;\n promise: Promise<\"aborted\">;\n} {\n let dispose: () => void = () => undefined;\n\n const promise = new Promise<\"aborted\">((resolve) => {\n const onAbort = () => resolve(\"aborted\");\n dispose = () => signal.removeEventListener(\"abort\", onAbort);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n return { dispose, promise };\n}\n\nasync function captureNoObserverEvents<T>(callback: () => Promise<T>): Promise<{\n readonly events: AgentEvent[];\n readonly release: () => void;\n readonly value: T;\n}> {\n return {\n events: [],\n release: releaseNoObserverEvents,\n value: await callback(),\n };\n}\n\nfunction releaseNoObserverEvents(): void {\n return;\n}\n\nasync function readLlmOutput({\n history,\n llm,\n signal,\n toolExecution,\n}: Pick<RunAgentLoopOptions, \"history\" | \"llm\"> & {\n signal: AbortSignal;\n toolExecution?: RuntimeToolExecutionContext;\n}): Promise<RuntimeLlmOutput | \"aborted\"> {\n try {\n return await llm({\n history: history.modelSnapshot(),\n signal,\n toolExecution,\n });\n } catch (error) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n throw error;\n }\n}\n\nasync function appendCapturedStepOutput({\n capturedOutput,\n emit,\n history,\n output,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & { history: ModelHistory } & {\n capturedOutput: ObserverEventCaptureResult<RuntimeLlmOutput | \"aborted\">;\n output: RuntimeLlmOutput;\n signal: AbortSignal;\n}): Promise<StepOutputResult> {\n try {\n return await appendStepOutput({\n emit,\n history,\n observerEvents: capturedOutput.events,\n output,\n signal,\n });\n } finally {\n capturedOutput.release();\n }\n}\n\nasync function appendStepOutput({\n emit,\n history,\n observerEvents,\n output,\n signal,\n}: Pick<RunAgentLoopOptions, \"emit\"> & { history: ModelHistory } & {\n observerEvents: AgentEvent[];\n output: RuntimeLlmOutput;\n signal: AbortSignal;\n}): Promise<StepOutputResult> {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n let shouldContinue = false;\n const pendingObserverEvents = observerEvents;\n const flushObserverEvents = async (\n shouldFlush: (event: AgentEvent) => boolean = () => true\n ) => {\n for (let index = 0; index < pendingObserverEvents.length; ) {\n const event = pendingObserverEvents[index];\n if (!(event && shouldFlush(event))) {\n index += 1;\n continue;\n }\n pendingObserverEvents.splice(index, 1);\n await emit(event);\n }\n };\n\n for (const message of output) {\n if (signal.aborted) {\n return \"aborted\";\n }\n\n history.appendModelMessage(message);\n const events = modelMessageToAgentEvents(message);\n const hasToolResult = events.some((event) => event.type === \"tool-result\");\n\n for (const event of events) {\n await emit(event);\n if (event.type === \"tool-call\") {\n shouldContinue = true;\n await flushObserverEvents(isLaunchOrBlockingObserverEvent);\n }\n }\n\n if (hasToolResult) {\n await flushObserverEvents();\n }\n }\n\n await flushObserverEvents();\n\n return shouldContinue ? \"continue\" : \"completed\";\n}\n\nfunction isLaunchOrBlockingObserverEvent(event: AgentEvent): boolean {\n if (event.type === \"subagent-job-update\") {\n return false;\n }\n\n return !(event.type === \"subagent-job-end\" && event.task_id);\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ //#region src/agent-namespace.ts
2
+ function randomAgentNamespace() {
3
+ return agentNamespace(crypto.randomUUID());
4
+ }
5
+ function agentNamespace(namespace) {
6
+ return `agent:${namespacePart(namespace)}`;
7
+ }
8
+ function namespacePart(value) {
9
+ return encodeURIComponent(value);
10
+ }
11
+ function parentSessionNamespace({ generation, sessionKey, sessionNamespace }) {
12
+ return `${sessionNamespace}:session:${namespacePart(sessionKey)}:generation:${generation}`;
13
+ }
14
+ function ownsAgentNamespace(ownerNamespace, sessionNamespace) {
15
+ return ownerNamespace === sessionNamespace || ownerNamespace?.startsWith(`${sessionNamespace}:session:`) === true;
16
+ }
17
+ function stableAgentNamespace({ name, namespace }) {
18
+ const stableNamespace = namespace ?? name;
19
+ return stableNamespace ? agentNamespace(stableNamespace) : randomAgentNamespace();
20
+ }
21
+ //#endregion
22
+ export { ownsAgentNamespace, parentSessionNamespace, stableAgentNamespace };
23
+
24
+ //# sourceMappingURL=agent-namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-namespace.js","names":[],"sources":["../src/agent-namespace.ts"],"sourcesContent":["export function randomAgentNamespace(): string {\n return agentNamespace(crypto.randomUUID());\n}\n\nexport function agentNamespace(namespace: string): string {\n return `agent:${namespacePart(namespace)}`;\n}\n\nexport function namespacePart(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function parentSessionNamespace({\n generation,\n sessionKey,\n sessionNamespace,\n}: {\n readonly generation: number;\n readonly sessionKey: string;\n readonly sessionNamespace: string;\n}): string {\n return `${sessionNamespace}:session:${namespacePart(\n sessionKey\n )}:generation:${generation}`;\n}\n\nexport function ownsAgentNamespace(\n ownerNamespace: string | undefined,\n sessionNamespace: string\n): boolean {\n return (\n ownerNamespace === sessionNamespace ||\n ownerNamespace?.startsWith(`${sessionNamespace}:session:`) === true\n );\n}\n\nexport function stableAgentNamespace({\n name,\n namespace,\n}: {\n readonly name?: string;\n readonly namespace?: string;\n}): string {\n const stableNamespace = namespace ?? name;\n return stableNamespace\n ? agentNamespace(stableNamespace)\n : randomAgentNamespace();\n}\n"],"mappings":";AAAA,SAAgB,uBAA+B;CAC7C,OAAO,eAAe,OAAO,WAAW,CAAC;AAC3C;AAEA,SAAgB,eAAe,WAA2B;CACxD,OAAO,SAAS,cAAc,SAAS;AACzC;AAEA,SAAgB,cAAc,OAAuB;CACnD,OAAO,mBAAmB,KAAK;AACjC;AAEA,SAAgB,uBAAuB,EACrC,YACA,YACA,oBAKS;CACT,OAAO,GAAG,iBAAiB,WAAW,cACpC,UACF,EAAE,cAAc;AAClB;AAEA,SAAgB,mBACd,gBACA,kBACS;CACT,OACE,mBAAmB,oBACnB,gBAAgB,WAAW,GAAG,iBAAiB,UAAU,MAAM;AAEnE;AAEA,SAAgB,qBAAqB,EACnC,MACA,aAIS;CACT,MAAM,kBAAkB,aAAa;CACrC,OAAO,kBACH,eAAe,eAAe,IAC9B,qBAAqB;AAC3B"}
@@ -0,0 +1,35 @@
1
+ import { AgentToolChoice, RuntimeLlm } from "./llm.js";
2
+ import { AgentHost } from "./execution/types.js";
3
+ import { AgentPlugin } from "./plugins.js";
4
+ import { Agent } from "./agent.js";
5
+ import { LanguageModel, ToolSet } from "ai";
6
+
7
+ //#region src/agent-options.d.ts
8
+ interface AgentLanguageModelOptions {
9
+ readonly description?: string;
10
+ readonly host?: AgentHost;
11
+ readonly instructions?: string;
12
+ readonly model: LanguageModel;
13
+ readonly name?: string;
14
+ readonly namespace?: string;
15
+ readonly plugins?: readonly AgentPlugin[];
16
+ readonly subagents?: readonly Agent[];
17
+ readonly toolChoice?: AgentToolChoice;
18
+ readonly tools?: ToolSet;
19
+ }
20
+ interface AgentRuntimeModelOptions {
21
+ readonly description?: string;
22
+ readonly host?: AgentHost;
23
+ readonly instructions?: never;
24
+ readonly model: RuntimeLlm;
25
+ readonly name?: string;
26
+ readonly namespace?: string;
27
+ readonly plugins?: readonly AgentPlugin[];
28
+ readonly subagents?: never;
29
+ readonly toolChoice?: never;
30
+ readonly tools?: never;
31
+ }
32
+ type AgentOptions = AgentLanguageModelOptions | AgentRuntimeModelOptions;
33
+ //#endregion
34
+ export { AgentOptions };
35
+ //# sourceMappingURL=agent-options.d.ts.map
@@ -0,0 +1,16 @@
1
+ //#region src/agent-options.ts
2
+ function assertAgentOptions(options) {
3
+ if (options === null || typeof options !== "object") throw new TypeError("Agent options are required. Provide { model }.");
4
+ if ("sessions" in options) throw new TypeError("Agent: unsupported options.sessions. Use host: { sessionStore } and namespace instead.");
5
+ if ("runtime" in options) throw new TypeError("Agent: unsupported options.runtime. Use host.");
6
+ if ("llm" in options) throw new TypeError("Agent: unsupported options.llm. Use model for both AI SDK models and custom RuntimeLlm functions.");
7
+ if (!("model" in options && options.model != null)) throw new TypeError("Agent: missing options.model.");
8
+ if (typeof options.model !== "function" && (typeof options.model !== "object" || options.model === null)) throw new TypeError("Agent: invalid options.model.");
9
+ }
10
+ function hasRuntimeModel(options) {
11
+ return typeof options.model === "function";
12
+ }
13
+ //#endregion
14
+ export { assertAgentOptions, hasRuntimeModel };
15
+
16
+ //# sourceMappingURL=agent-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-options.js","names":[],"sources":["../src/agent-options.ts"],"sourcesContent":["import type { LanguageModel, ToolSet } from \"ai\";\nimport type { Agent } from \"./agent\";\nimport type { AgentHost } from \"./execution/types\";\nimport type { AgentToolChoice, RuntimeLlm } from \"./llm\";\nimport type { AgentPlugin } from \"./plugins\";\n\ninterface AgentLanguageModelOptions {\n readonly description?: string;\n readonly host?: AgentHost;\n readonly instructions?: string;\n readonly model: LanguageModel;\n readonly name?: string;\n readonly namespace?: string;\n readonly plugins?: readonly AgentPlugin[];\n readonly subagents?: readonly Agent[];\n readonly toolChoice?: AgentToolChoice;\n readonly tools?: ToolSet;\n}\n\ninterface AgentRuntimeModelOptions {\n readonly description?: string;\n readonly host?: AgentHost;\n readonly instructions?: never;\n readonly model: RuntimeLlm;\n readonly name?: string;\n readonly namespace?: string;\n readonly plugins?: readonly AgentPlugin[];\n readonly subagents?: never;\n readonly toolChoice?: never;\n readonly tools?: never;\n}\n\nexport type AgentModelOptions = Pick<\n AgentLanguageModelOptions,\n \"instructions\" | \"model\" | \"toolChoice\"\n>;\nexport type AgentOptions = AgentLanguageModelOptions | AgentRuntimeModelOptions;\n\nexport function assertAgentOptions(\n options: unknown\n): asserts options is AgentOptions {\n if (options === null || typeof options !== \"object\") {\n throw new TypeError(\"Agent options are required. Provide { model }.\");\n }\n\n if (\"sessions\" in options) {\n throw new TypeError(\n \"Agent: unsupported options.sessions. Use host: { sessionStore } and namespace instead.\"\n );\n }\n\n if (\"runtime\" in options) {\n throw new TypeError(\"Agent: unsupported options.runtime. Use host.\");\n }\n\n if (\"llm\" in options) {\n throw new TypeError(\n \"Agent: unsupported options.llm. Use model for both AI SDK models and custom RuntimeLlm functions.\"\n );\n }\n\n const hasModel = \"model\" in options && options.model != null;\n\n if (!hasModel) {\n throw new TypeError(\"Agent: missing options.model.\");\n }\n\n if (\n typeof options.model !== \"function\" &&\n (typeof options.model !== \"object\" || options.model === null)\n ) {\n throw new TypeError(\"Agent: invalid options.model.\");\n }\n}\n\nexport function hasRuntimeModel(\n options: AgentOptions\n): options is AgentRuntimeModelOptions {\n return typeof options.model === \"function\";\n}\n"],"mappings":";AAsCA,SAAgB,mBACd,SACiC;CACjC,IAAI,YAAY,QAAQ,OAAO,YAAY,UACzC,MAAM,IAAI,UAAU,gDAAgD;CAGtE,IAAI,cAAc,SAChB,MAAM,IAAI,UACR,wFACF;CAGF,IAAI,aAAa,SACf,MAAM,IAAI,UAAU,+CAA+C;CAGrE,IAAI,SAAS,SACX,MAAM,IAAI,UACR,mGACF;CAKF,IAAI,EAFa,WAAW,WAAW,QAAQ,SAAS,OAGtD,MAAM,IAAI,UAAU,+BAA+B;CAGrD,IACE,OAAO,QAAQ,UAAU,eACxB,OAAO,QAAQ,UAAU,YAAY,QAAQ,UAAU,OAExD,MAAM,IAAI,UAAU,+BAA+B;AAEvD;AAEA,SAAgB,gBACd,SACqC;CACrC,OAAO,OAAO,QAAQ,UAAU;AAClC"}
@@ -0,0 +1,143 @@
1
+ import { readDurableBackgroundChildRunState } from "./subagent-background-child-run-state.js";
2
+ import { ownsAgentNamespace } from "./agent-namespace.js";
3
+ import { StoredAgentRun } from "./execution/run.js";
4
+ import { BufferedAgentRun } from "./session/run.js";
5
+ import { buildDurableResumeGroups } from "./subagent-background-resume-group.js";
6
+ import { runBackgroundJob } from "./subagent-background-runner.js";
7
+ //#region src/agent-resume.ts
8
+ const defaultResumeLeaseMs = 3e5;
9
+ async function resumeAgentRun({ host, ownerNamespace, resumeNotification, runId, subagents }) {
10
+ const run = await host.store.runs.get(runId);
11
+ if (!run) return null;
12
+ if (!canAccessRun(run, ownerNamespace)) return null;
13
+ if (run.kind === "background-subagent") return await resumeBackgroundSubagentRun({
14
+ host,
15
+ run,
16
+ subagents
17
+ });
18
+ if (run.kind === "notification" && run.dedupeKey) {
19
+ const idempotencyKey = run.dedupeKey;
20
+ const claimed = await claimRun(host, run);
21
+ if (!claimed) return null;
22
+ const notification = await claimNotificationForRun({
23
+ host,
24
+ idempotencyKey,
25
+ ownerNamespace
26
+ });
27
+ if (!notification) return null;
28
+ try {
29
+ const notificationRun = await resumeNotification(notification);
30
+ await completeNotificationRun(host, claimed.runId);
31
+ return notificationRun;
32
+ } catch (error) {
33
+ await host.store.notifications.releaseByIdempotencyKey(idempotencyKey);
34
+ throw error;
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ async function claimNotificationForRun({ host, idempotencyKey, ownerNamespace }) {
40
+ if (!ownsAgentNamespace((await host.store.notifications.getByIdempotencyKey(idempotencyKey))?.ownerNamespace, ownerNamespace)) return null;
41
+ const claim = await host.store.notifications.claimByIdempotencyKey(idempotencyKey);
42
+ if (claim.ok) {
43
+ if (ownsAgentNamespace(claim.record.ownerNamespace, ownerNamespace)) return claim.record;
44
+ await host.store.notifications.releaseByIdempotencyKey(idempotencyKey);
45
+ return null;
46
+ }
47
+ if (claim.reason === "already-claimed" && ownsAgentNamespace(claim.record?.ownerNamespace, ownerNamespace)) return claim.record ?? null;
48
+ return null;
49
+ }
50
+ function canAccessRun(run, ownerNamespace) {
51
+ if (run.ownerNamespace) return ownsAgentNamespace(run.ownerNamespace, ownerNamespace);
52
+ return run.sessionKey.startsWith(`parent:${ownerNamespace}:`) || run.parentRunId?.startsWith(`${ownerNamespace}:session:`) === true;
53
+ }
54
+ async function completeNotificationRun(host, runId) {
55
+ const run = await host.store.runs.get(runId);
56
+ if (run?.kind !== "notification" || run.status === "completed") return;
57
+ await host.store.runs.update({
58
+ ...run,
59
+ status: "completed"
60
+ });
61
+ }
62
+ async function resumeBackgroundSubagentRun({ host, run, subagents }) {
63
+ const claimed = await claimRun(host, run);
64
+ if (!claimed) return null;
65
+ const state = readDurableBackgroundChildRunState(await host.store.checkpoints.latest(run.runId));
66
+ if (!state) throw new AgentResumeError(run.runId, "missing background run state");
67
+ const subagent = subagents.find((candidate) => candidate.name === state.subagent);
68
+ if (!subagent) throw new AgentResumeError(run.runId, `missing subagent ${JSON.stringify(state.subagent)}`);
69
+ const childSession = subagent.session(claimed.sessionKey);
70
+ const job = {
71
+ abort: () => childSession.interrupt(),
72
+ childRunId: claimed.runId,
73
+ childRunLeaseId: claimed.lease?.leaseId,
74
+ cleanup: () => Promise.resolve(),
75
+ dedupeKey: claimed.dedupeKey,
76
+ delegateToolCallId: state.delegateToolCallId,
77
+ description: state.description,
78
+ executionHost: host,
79
+ groupId: state.groupId,
80
+ id: claimed.publicTaskId ?? claimed.runId,
81
+ ownerNamespace: claimed.ownerNamespace,
82
+ parentRunId: claimed.parentRunId,
83
+ parentSessionKey: state.parentSessionKey,
84
+ promise: Promise.resolve(),
85
+ sessionKey: claimed.sessionKey,
86
+ settled: false,
87
+ status: "running",
88
+ subagent: state.subagent
89
+ };
90
+ const jobs = new Map([[job.id, job]]);
91
+ job.promise = runBackgroundJob({
92
+ childSession,
93
+ groups: await buildDurableResumeGroups({
94
+ currentJob: job,
95
+ host,
96
+ run: claimed,
97
+ state,
98
+ jobs
99
+ }),
100
+ jobs,
101
+ job,
102
+ parentSession: durableParentSession(host, run.runId),
103
+ prompt: state.prompt
104
+ }).finally(() => {
105
+ job.settled = true;
106
+ });
107
+ await job.promise;
108
+ return new StoredAgentRun({
109
+ eventStore: host.store.events,
110
+ runId: run.runId
111
+ });
112
+ }
113
+ async function claimRun(host, run) {
114
+ const claim = await host.store.runs.claim(run.runId, {
115
+ attempt: (run.lease?.attempt ?? 0) + 1,
116
+ leaseId: crypto.randomUUID(),
117
+ leaseMs: defaultResumeLeaseMs,
118
+ nowMs: Date.now()
119
+ });
120
+ return claim.ok ? claim.record : null;
121
+ }
122
+ function durableParentSession(host, runId) {
123
+ return {
124
+ emitObserverEvent: (event) => host.store.events.append(runId, event).then(),
125
+ enqueueRuntimeInput: () => void 0,
126
+ notify: () => Promise.resolve(emptyRun())
127
+ };
128
+ }
129
+ function emptyRun() {
130
+ const run = new BufferedAgentRun();
131
+ run.close();
132
+ return run;
133
+ }
134
+ var AgentResumeError = class extends Error {
135
+ constructor(runId, reason) {
136
+ super(`Cannot resume agent run ${runId}: ${reason}`);
137
+ this.name = "AgentResumeError";
138
+ }
139
+ };
140
+ //#endregion
141
+ export { resumeAgentRun };
142
+
143
+ //# sourceMappingURL=agent-resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-resume.js","names":[],"sources":["../src/agent-resume.ts"],"sourcesContent":["import { ownsAgentNamespace } from \"./agent-namespace\";\nimport { StoredAgentRun } from \"./execution/run\";\nimport type {\n ExecutionHost,\n NotificationRecord,\n RunRecord,\n} from \"./execution/types\";\nimport { type AgentRun, BufferedAgentRun } from \"./session/run\";\nimport { readDurableBackgroundChildRunState } from \"./subagent-background-child-run-state\";\nimport { buildDurableResumeGroups } from \"./subagent-background-resume-group\";\nimport { runBackgroundJob } from \"./subagent-background-runner\";\nimport type { RuntimeInputSink, Subagent, SubagentJob } from \"./subagent-types\";\n\nconst defaultResumeLeaseMs = 300_000;\n\ninterface ResumeAgentRunInput {\n readonly host: ExecutionHost;\n readonly ownerNamespace: string;\n resumeNotification(notification: NotificationRecord): Promise<AgentRun>;\n readonly runId: string;\n readonly subagents: readonly Subagent[];\n}\n\nexport async function resumeAgentRun({\n host,\n ownerNamespace,\n resumeNotification,\n runId,\n subagents,\n}: ResumeAgentRunInput): Promise<AgentRun | null> {\n const run = await host.store.runs.get(runId);\n if (!run) {\n return null;\n }\n if (!canAccessRun(run, ownerNamespace)) {\n return null;\n }\n\n if (run.kind === \"background-subagent\") {\n return await resumeBackgroundSubagentRun({ host, run, subagents });\n }\n\n if (run.kind === \"notification\" && run.dedupeKey) {\n const idempotencyKey = run.dedupeKey;\n const claimed = await claimRun(host, run);\n if (!claimed) {\n return null;\n }\n\n const notification = await claimNotificationForRun({\n host,\n idempotencyKey,\n ownerNamespace,\n });\n if (!notification) {\n return null;\n }\n\n try {\n const notificationRun = await resumeNotification(notification);\n await completeNotificationRun(host, claimed.runId);\n return notificationRun;\n } catch (error) {\n await host.store.notifications.releaseByIdempotencyKey(idempotencyKey);\n throw error;\n }\n }\n\n return null;\n}\n\nasync function claimNotificationForRun({\n host,\n idempotencyKey,\n ownerNamespace,\n}: {\n readonly host: ExecutionHost;\n readonly idempotencyKey: string;\n readonly ownerNamespace: string;\n}): Promise<NotificationRecord | null> {\n const current =\n await host.store.notifications.getByIdempotencyKey(idempotencyKey);\n if (!ownsAgentNamespace(current?.ownerNamespace, ownerNamespace)) {\n return null;\n }\n\n const claim =\n await host.store.notifications.claimByIdempotencyKey(idempotencyKey);\n if (claim.ok) {\n if (ownsAgentNamespace(claim.record.ownerNamespace, ownerNamespace)) {\n return claim.record;\n }\n await host.store.notifications.releaseByIdempotencyKey(idempotencyKey);\n return null;\n }\n\n if (\n claim.reason === \"already-claimed\" &&\n ownsAgentNamespace(claim.record?.ownerNamespace, ownerNamespace)\n ) {\n return claim.record ?? null;\n }\n\n return null;\n}\n\nfunction canAccessRun(run: RunRecord, ownerNamespace: string): boolean {\n if (run.ownerNamespace) {\n return ownsAgentNamespace(run.ownerNamespace, ownerNamespace);\n }\n\n return (\n run.sessionKey.startsWith(`parent:${ownerNamespace}:`) ||\n run.parentRunId?.startsWith(`${ownerNamespace}:session:`) === true\n );\n}\n\nexport async function completeNotificationRun(\n host: ExecutionHost,\n runId: string\n): Promise<void> {\n const run = await host.store.runs.get(runId);\n if (run?.kind !== \"notification\" || run.status === \"completed\") {\n return;\n }\n\n await host.store.runs.update({ ...run, status: \"completed\" });\n}\n\nasync function resumeBackgroundSubagentRun({\n host,\n run,\n subagents,\n}: {\n readonly host: ExecutionHost;\n readonly run: RunRecord;\n readonly subagents: readonly Subagent[];\n}): Promise<AgentRun | null> {\n const claimed = await claimRun(host, run);\n if (!claimed) {\n return null;\n }\n\n const checkpoint = await host.store.checkpoints.latest(run.runId);\n const state = readDurableBackgroundChildRunState(checkpoint);\n if (!state) {\n throw new AgentResumeError(run.runId, \"missing background run state\");\n }\n\n const subagent = subagents.find(\n (candidate) => candidate.name === state.subagent\n );\n if (!subagent) {\n throw new AgentResumeError(\n run.runId,\n `missing subagent ${JSON.stringify(state.subagent)}`\n );\n }\n\n const childSession = subagent.session(claimed.sessionKey);\n const job: SubagentJob = {\n abort: () => childSession.interrupt(),\n childRunId: claimed.runId,\n childRunLeaseId: claimed.lease?.leaseId,\n cleanup: () => Promise.resolve(),\n dedupeKey: claimed.dedupeKey,\n delegateToolCallId: state.delegateToolCallId,\n description: state.description,\n executionHost: host,\n groupId: state.groupId,\n id: claimed.publicTaskId ?? claimed.runId,\n ownerNamespace: claimed.ownerNamespace,\n parentRunId: claimed.parentRunId,\n parentSessionKey: state.parentSessionKey,\n promise: Promise.resolve(),\n sessionKey: claimed.sessionKey,\n settled: false,\n status: \"running\",\n subagent: state.subagent,\n };\n const jobs = new Map([[job.id, job]]);\n const groups = await buildDurableResumeGroups({\n currentJob: job,\n host,\n run: claimed,\n state,\n jobs,\n });\n const parentSession = durableParentSession(host, run.runId);\n\n job.promise = runBackgroundJob({\n childSession,\n groups,\n jobs,\n job,\n parentSession,\n prompt: state.prompt,\n }).finally(() => {\n job.settled = true;\n });\n await job.promise;\n\n return new StoredAgentRun({\n eventStore: host.store.events,\n runId: run.runId,\n });\n}\n\nasync function claimRun(\n host: ExecutionHost,\n run: RunRecord\n): Promise<RunRecord | null> {\n const claim = await host.store.runs.claim(run.runId, {\n attempt: (run.lease?.attempt ?? 0) + 1,\n leaseId: crypto.randomUUID(),\n leaseMs: defaultResumeLeaseMs,\n nowMs: Date.now(),\n });\n return claim.ok ? claim.record : null;\n}\n\nfunction durableParentSession(\n host: ExecutionHost,\n runId: string\n): RuntimeInputSink {\n return {\n emitObserverEvent: (event) => host.store.events.append(runId, event).then(),\n enqueueRuntimeInput: () => undefined,\n notify: () => Promise.resolve(emptyRun()),\n };\n}\n\nfunction emptyRun(): AgentRun {\n const run = new BufferedAgentRun();\n run.close();\n return run;\n}\n\nclass AgentResumeError extends Error {\n constructor(runId: string, reason: string) {\n super(`Cannot resume agent run ${runId}: ${reason}`);\n this.name = \"AgentResumeError\";\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { AgentInput } from "./session/input.js";
2
+ import { AgentRun } from "./session/run.js";
3
+ //#region src/agent-session-entry.d.ts
4
+ interface SessionHandle {
5
+ delete(): Promise<void>;
6
+ interrupt(): void;
7
+ kill(): Promise<void>;
8
+ send(input: AgentInput): Promise<AgentRun>;
9
+ steer(input: AgentInput): Promise<AgentRun>;
10
+ }
11
+ //#endregion
12
+ export { SessionHandle };
13
+ //# sourceMappingURL=agent-session-entry.d.ts.map
@@ -0,0 +1,35 @@
1
+ //#region src/agent-validation.ts
2
+ const subagentNamePattern = /^[a-z][a-z0-9_-]{0,51}$/;
3
+ function assertSubagents(options, agentClass, hasRuntimeModel) {
4
+ if (!("subagents" in options) || options.subagents === void 0) return;
5
+ if (hasRuntimeModel) throw new TypeError("Agent: subagents require an AI SDK model.");
6
+ if (!Array.isArray(options.subagents)) throw new TypeError("Agent: subagents must be an array.");
7
+ assertSubagentTools(options.subagents, agentClass, options.tools ?? {});
8
+ }
9
+ function assertSubagentTools(subagents, agentClass, tools) {
10
+ const toolNames = new Set(Object.keys(tools));
11
+ const generatedToolNames = /* @__PURE__ */ new Set();
12
+ for (const [index, subagent] of subagents.entries()) {
13
+ const toolName = `delegate_to_${assertSubagentMetadata(subagent, index, agentClass).replaceAll("-", "_")}`;
14
+ if (toolNames.has(toolName)) throw new TypeError(`Agent: subagent tool ${toolName} collides with an existing tool.`);
15
+ if (generatedToolNames.has(toolName)) throw new TypeError(`Agent: duplicate subagent tool name ${toolName}.`);
16
+ generatedToolNames.add(toolName);
17
+ }
18
+ for (const reservedToolName of ["background_output", "background_cancel"]) if (toolNames.has(reservedToolName)) throw new TypeError(`Agent: ${reservedToolName} collides with a reserved subagent tool.`);
19
+ }
20
+ function assertSubagentMetadata(subagent, index, agentClass) {
21
+ if (!(subagent instanceof agentClass)) throw new TypeError(`Agent: subagents[${index}] must be an Agent.`);
22
+ if (!isValidSubagentName(subagent.name)) throw new TypeError(`Agent: subagents[${index}].name is required or too long.`);
23
+ if (!isNonEmptyText(subagent.description)) throw new TypeError(`Agent: subagents[${index}].description is required.`);
24
+ return subagent.name;
25
+ }
26
+ function isNonEmptyText(value) {
27
+ return typeof value === "string" && value.trim().length > 0;
28
+ }
29
+ function isValidSubagentName(value) {
30
+ return typeof value === "string" && subagentNamePattern.test(value);
31
+ }
32
+ //#endregion
33
+ export { assertSubagents };
34
+
35
+ //# sourceMappingURL=agent-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-validation.js","names":[],"sources":["../src/agent-validation.ts"],"sourcesContent":["import type { ToolSet } from \"ai\";\nimport type { Agent } from \"./agent\";\nimport type { AgentOptions } from \"./agent-options\";\n\nconst subagentNamePattern = /^[a-z][a-z0-9_-]{0,51}$/;\n\nexport function assertSubagents(\n options: AgentOptions,\n agentClass: new (options: AgentOptions) => Agent,\n hasRuntimeModel: boolean\n): void {\n if (!(\"subagents\" in options) || options.subagents === undefined) {\n return;\n }\n\n if (hasRuntimeModel) {\n throw new TypeError(\"Agent: subagents require an AI SDK model.\");\n }\n\n if (!Array.isArray(options.subagents)) {\n throw new TypeError(\"Agent: subagents must be an array.\");\n }\n\n assertSubagentTools(options.subagents, agentClass, options.tools ?? {});\n}\n\nfunction assertSubagentTools(\n subagents: readonly Agent[],\n agentClass: new (options: AgentOptions) => Agent,\n tools: ToolSet\n): void {\n const toolNames = new Set(Object.keys(tools));\n const generatedToolNames = new Set<string>();\n for (const [index, subagent] of subagents.entries()) {\n const name = assertSubagentMetadata(subagent, index, agentClass);\n const toolName = `delegate_to_${name.replaceAll(\"-\", \"_\")}`;\n if (toolNames.has(toolName)) {\n throw new TypeError(\n `Agent: subagent tool ${toolName} collides with an existing tool.`\n );\n }\n\n if (generatedToolNames.has(toolName)) {\n throw new TypeError(`Agent: duplicate subagent tool name ${toolName}.`);\n }\n\n generatedToolNames.add(toolName);\n }\n\n for (const reservedToolName of [\"background_output\", \"background_cancel\"]) {\n if (toolNames.has(reservedToolName)) {\n throw new TypeError(\n `Agent: ${reservedToolName} collides with a reserved subagent tool.`\n );\n }\n }\n}\n\nfunction assertSubagentMetadata(\n subagent: Agent,\n index: number,\n agentClass: new (options: AgentOptions) => Agent\n): string {\n if (!(subagent instanceof agentClass)) {\n throw new TypeError(`Agent: subagents[${index}] must be an Agent.`);\n }\n\n if (!isValidSubagentName(subagent.name)) {\n throw new TypeError(\n `Agent: subagents[${index}].name is required or too long.`\n );\n }\n\n if (!isNonEmptyText(subagent.description)) {\n throw new TypeError(`Agent: subagents[${index}].description is required.`);\n }\n\n return subagent.name;\n}\n\nfunction isNonEmptyText(value: string | undefined): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nfunction isValidSubagentName(value: string | undefined): value is string {\n return typeof value === \"string\" && subagentNamePattern.test(value);\n}\n"],"mappings":";AAIA,MAAM,sBAAsB;AAE5B,SAAgB,gBACd,SACA,YACA,iBACM;CACN,IAAI,EAAE,eAAe,YAAY,QAAQ,cAAc,KAAA,GACrD;CAGF,IAAI,iBACF,MAAM,IAAI,UAAU,2CAA2C;CAGjE,IAAI,CAAC,MAAM,QAAQ,QAAQ,SAAS,GAClC,MAAM,IAAI,UAAU,oCAAoC;CAG1D,oBAAoB,QAAQ,WAAW,YAAY,QAAQ,SAAS,CAAC,CAAC;AACxE;AAEA,SAAS,oBACP,WACA,YACA,OACM;CACN,MAAM,YAAY,IAAI,IAAI,OAAO,KAAK,KAAK,CAAC;CAC5C,MAAM,qCAAqB,IAAI,IAAY;CAC3C,KAAK,MAAM,CAAC,OAAO,aAAa,UAAU,QAAQ,GAAG;EAEnD,MAAM,WAAW,eADJ,uBAAuB,UAAU,OAAO,UAClB,EAAE,WAAW,KAAK,GAAG;EACxD,IAAI,UAAU,IAAI,QAAQ,GACxB,MAAM,IAAI,UACR,wBAAwB,SAAS,iCACnC;EAGF,IAAI,mBAAmB,IAAI,QAAQ,GACjC,MAAM,IAAI,UAAU,uCAAuC,SAAS,EAAE;EAGxE,mBAAmB,IAAI,QAAQ;CACjC;CAEA,KAAK,MAAM,oBAAoB,CAAC,qBAAqB,mBAAmB,GACtE,IAAI,UAAU,IAAI,gBAAgB,GAChC,MAAM,IAAI,UACR,UAAU,iBAAiB,yCAC7B;AAGN;AAEA,SAAS,uBACP,UACA,OACA,YACQ;CACR,IAAI,EAAE,oBAAoB,aACxB,MAAM,IAAI,UAAU,oBAAoB,MAAM,oBAAoB;CAGpE,IAAI,CAAC,oBAAoB,SAAS,IAAI,GACpC,MAAM,IAAI,UACR,oBAAoB,MAAM,gCAC5B;CAGF,IAAI,CAAC,eAAe,SAAS,WAAW,GACtC,MAAM,IAAI,UAAU,oBAAoB,MAAM,2BAA2B;CAG3E,OAAO,SAAS;AAClB;AAEA,SAAS,eAAe,OAA4C;CAClE,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAEA,SAAS,oBAAoB,OAA4C;CACvE,OAAO,OAAO,UAAU,YAAY,oBAAoB,KAAK,KAAK;AACpE"}
package/dist/agent.d.ts CHANGED
@@ -1,44 +1,19 @@
1
- import { AgentToolChoice, Llm } from "./llm.js";
2
1
  import { AgentInput } from "./session/input.js";
2
+ import { AgentHost } from "./execution/types.js";
3
+ import { AgentOptions } from "./agent-options.js";
3
4
  import { AgentRun } from "./session/run.js";
4
- import { AgentPlugin } from "./plugins/types.js";
5
- import { AgentPluginErrorHandler } from "./session/lifecycle.js";
6
- import { LanguageModel, ToolSet } from "ai";
5
+ import { SessionHandle } from "./agent-session-entry.js";
7
6
 
8
7
  //#region src/agent.d.ts
9
- interface AgentLanguageModelOptions {
10
- instructions?: string;
11
- llm?: never;
12
- model: LanguageModel;
13
- onPluginError?: AgentPluginErrorHandler;
14
- plugins?: readonly AgentPlugin[];
15
- toolChoice?: AgentToolChoice;
16
- tools?: ToolSet;
17
- }
18
- interface AgentLlmOptions {
19
- instructions?: never;
20
- llm: Llm;
21
- model?: never;
22
- onPluginError?: AgentPluginErrorHandler;
23
- plugins?: readonly AgentPlugin[];
24
- toolChoice?: never;
25
- tools?: never;
26
- }
27
- interface SessionHandle {
28
- interrupt(): void;
29
- kill(): void;
30
- overlay(input: AgentInput): Promise<AgentRun>;
31
- send(input: AgentInput): Promise<AgentRun>;
32
- steer(input: AgentInput): Promise<AgentRun>;
33
- }
34
- type AgentOptions = AgentLanguageModelOptions | AgentLlmOptions;
35
8
  declare class Agent {
36
9
  #private;
37
- private constructor();
38
- static create(options: AgentOptions): Promise<Agent>;
10
+ readonly description?: string;
11
+ readonly name?: string;
12
+ constructor(options: AgentOptions);
39
13
  send(input: AgentInput): Promise<AgentRun>;
14
+ resume(runId: string): Promise<AgentRun | null>;
40
15
  session(key: string): SessionHandle;
41
16
  }
42
17
  //#endregion
43
- export { Agent, AgentOptions, SessionHandle };
18
+ export { Agent };
44
19
  //# sourceMappingURL=agent.d.ts.map