@minpeter/pss-runtime 0.1.0-next.1 → 0.1.0-next.3

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 (133) hide show
  1. package/README.md +290 -61
  2. package/dist/agent-host-session-store.js +10 -0
  3. package/dist/agent-host-session-store.js.map +1 -0
  4. package/dist/agent-loop.js +57 -28
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/agent-namespace.js +6 -3
  7. package/dist/agent-namespace.js.map +1 -1
  8. package/dist/agent-options.d.ts +29 -0
  9. package/dist/agent-options.js +16 -0
  10. package/dist/agent-options.js.map +1 -0
  11. package/dist/agent-resume.js +63 -0
  12. package/dist/agent-resume.js.map +1 -0
  13. package/dist/agent-session-entry.d.ts +13 -0
  14. package/dist/agent.d.ts +8 -44
  15. package/dist/agent.js +61 -83
  16. package/dist/agent.js.map +1 -1
  17. package/dist/cloudflare/cloudflare-agent-context.d.ts +40 -0
  18. package/dist/cloudflare/cloudflare-agent-context.js +37 -0
  19. package/dist/cloudflare/cloudflare-agent-context.js.map +1 -0
  20. package/dist/cloudflare/cloudflare-alarm-budget.d.ts +18 -0
  21. package/dist/cloudflare/cloudflare-alarm-budget.js +77 -0
  22. package/dist/cloudflare/cloudflare-alarm-budget.js.map +1 -0
  23. package/dist/cloudflare/cloudflare-alarm-drainer.d.ts +45 -0
  24. package/dist/cloudflare/cloudflare-alarm-drainer.js +103 -0
  25. package/dist/cloudflare/cloudflare-alarm-drainer.js.map +1 -0
  26. package/dist/cloudflare/cloudflare-alarm-run-drain.d.ts +13 -0
  27. package/dist/cloudflare/cloudflare-alarm-run-drain.js +81 -0
  28. package/dist/cloudflare/cloudflare-alarm-run-drain.js.map +1 -0
  29. package/dist/cloudflare/cloudflare-alarm-work.js +110 -0
  30. package/dist/cloudflare/cloudflare-alarm-work.js.map +1 -0
  31. package/dist/cloudflare/cloudflare-checkpoint-store.js +39 -0
  32. package/dist/cloudflare/cloudflare-checkpoint-store.js.map +1 -0
  33. package/dist/cloudflare/cloudflare-durable-object-fetch.d.ts +21 -0
  34. package/dist/cloudflare/cloudflare-durable-object-fetch.js +11 -0
  35. package/dist/cloudflare/cloudflare-durable-object-fetch.js.map +1 -0
  36. package/dist/cloudflare/cloudflare-event-store.js +33 -0
  37. package/dist/cloudflare/cloudflare-event-store.js.map +1 -0
  38. package/dist/cloudflare/cloudflare-execution-session-store.js +40 -0
  39. package/dist/cloudflare/cloudflare-execution-session-store.js.map +1 -0
  40. package/dist/cloudflare/cloudflare-execution-store.js +35 -0
  41. package/dist/cloudflare/cloudflare-execution-store.js.map +1 -0
  42. package/dist/cloudflare/cloudflare-host.d.ts +61 -0
  43. package/dist/cloudflare/cloudflare-host.js +113 -0
  44. package/dist/cloudflare/cloudflare-host.js.map +1 -0
  45. package/dist/cloudflare/cloudflare-notification-store.js +59 -0
  46. package/dist/cloudflare/cloudflare-notification-store.js.map +1 -0
  47. package/dist/cloudflare/cloudflare-run-store.js +81 -0
  48. package/dist/cloudflare/cloudflare-run-store.js.map +1 -0
  49. package/dist/cloudflare/cloudflare-store-utils.js +43 -0
  50. package/dist/cloudflare/cloudflare-store-utils.js.map +1 -0
  51. package/dist/cloudflare/durable-object-storage.d.ts +20 -0
  52. package/dist/cloudflare/durable-object-storage.js +76 -0
  53. package/dist/cloudflare/durable-object-storage.js.map +1 -0
  54. package/dist/cloudflare/index.d.ts +7 -0
  55. package/dist/cloudflare/index.js +6 -0
  56. package/dist/execution/capabilities.d.ts +40 -0
  57. package/dist/execution/host.d.ts +9 -0
  58. package/dist/execution/host.js +62 -0
  59. package/dist/execution/host.js.map +1 -0
  60. package/dist/execution/index.d.ts +6 -0
  61. package/dist/execution/index.js +4 -0
  62. package/dist/execution/memory-notifications.js +54 -0
  63. package/dist/execution/memory-notifications.js.map +1 -0
  64. package/dist/execution/memory-state.js +34 -0
  65. package/dist/execution/memory-state.js.map +1 -0
  66. package/dist/execution/memory-store.js +203 -0
  67. package/dist/execution/memory-store.js.map +1 -0
  68. package/dist/execution/memory.d.ts +7 -0
  69. package/dist/execution/memory.js +28 -0
  70. package/dist/execution/memory.js.map +1 -0
  71. package/dist/execution/types.d.ts +150 -0
  72. package/dist/index.d.ts +13 -6
  73. package/dist/index.js +6 -1
  74. package/dist/llm-tool-execution.d.ts +35 -0
  75. package/dist/llm-tool-execution.js +126 -0
  76. package/dist/llm-tool-execution.js.map +1 -0
  77. package/dist/llm.d.ts +11 -15
  78. package/dist/llm.js +5 -3
  79. package/dist/llm.js.map +1 -1
  80. package/dist/plugins.d.ts +42 -0
  81. package/dist/plugins.js +43 -0
  82. package/dist/plugins.js.map +1 -0
  83. package/dist/session/delegate-input.d.ts +9 -0
  84. package/dist/session/delegate-input.js +16 -0
  85. package/dist/session/delegate-input.js.map +1 -0
  86. package/dist/session/events.d.ts +43 -22
  87. package/dist/session/events.js +41 -0
  88. package/dist/session/events.js.map +1 -0
  89. package/dist/session/input-meta-types.d.ts +10 -0
  90. package/dist/session/input-meta.d.ts +13 -0
  91. package/dist/session/input-meta.js +45 -0
  92. package/dist/session/input-meta.js.map +1 -0
  93. package/dist/session/input.d.ts +4 -0
  94. package/dist/session/mapping.js +4 -2
  95. package/dist/session/mapping.js.map +1 -1
  96. package/dist/session/runtime-input-emit.js +41 -0
  97. package/dist/session/runtime-input-emit.js.map +1 -0
  98. package/dist/session/runtime-input.js +10 -24
  99. package/dist/session/runtime-input.js.map +1 -1
  100. package/dist/session/session-errors.js +1 -6
  101. package/dist/session/session-errors.js.map +1 -1
  102. package/dist/session/session-events.js +73 -0
  103. package/dist/session/session-events.js.map +1 -0
  104. package/dist/session/session-execution.js +88 -0
  105. package/dist/session/session-execution.js.map +1 -0
  106. package/dist/session/session-notification.js +59 -0
  107. package/dist/session/session-notification.js.map +1 -0
  108. package/dist/session/session-runtime-drain.js +3 -9
  109. package/dist/session/session-runtime-drain.js.map +1 -1
  110. package/dist/session/session-turn-processor.js +125 -0
  111. package/dist/session/session-turn-processor.js.map +1 -0
  112. package/dist/session/session.js +81 -102
  113. package/dist/session/session.js.map +1 -1
  114. package/dist/session/snapshot.js.map +1 -1
  115. package/package.json +16 -1
  116. package/dist/agent-validation.js +0 -35
  117. package/dist/agent-validation.js.map +0 -1
  118. package/dist/child-session-cleanups.js +0 -61
  119. package/dist/child-session-cleanups.js.map +0 -1
  120. package/dist/hooks.d.ts +0 -32
  121. package/dist/subagent-job-cancel.js +0 -28
  122. package/dist/subagent-job-cancel.js.map +0 -1
  123. package/dist/subagent-job-output.js +0 -63
  124. package/dist/subagent-job-output.js.map +0 -1
  125. package/dist/subagent-jobs.js +0 -151
  126. package/dist/subagent-jobs.js.map +0 -1
  127. package/dist/subagent-prompt-schema.js +0 -114
  128. package/dist/subagent-prompt-schema.js.map +0 -1
  129. package/dist/subagent-run.js +0 -111
  130. package/dist/subagent-run.js.map +0 -1
  131. package/dist/subagents.js +0 -92
  132. package/dist/subagents.js.map +0 -1
  133. /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-turn-processor.js","names":[],"sources":["../../src/session/session-turn-processor.ts"],"sourcesContent":["import { runAgentLoop } from \"../agent-loop\";\nimport type { RuntimeLlm } from \"../llm\";\nimport { ToolExecutionNeedsRecoveryError } from \"../llm-tool-execution\";\nimport type { AgentEvent } from \"./events\";\nimport type { BufferedAgentRun } from \"./run\";\nimport {\n closeRuntimeInput,\n type QueuedInput,\n type RuntimeInputState,\n withRuntimeInputWindow,\n} from \"./runtime-input\";\nimport {\n commitPreUserRuntimeInputs,\n emitCommittedRuntimeInputs,\n} from \"./runtime-input-emit\";\nimport { errorMessage } from \"./session-errors\";\nimport type { SessionEventDispatcher } from \"./session-events\";\nimport {\n type SessionExecutionOptions,\n type SessionExecutionRun,\n type SessionExecutionTerminalStatus,\n startSessionExecutionRun,\n} from \"./session-execution\";\nimport { drainRuntimeInput } from \"./session-runtime-drain\";\n\nimport type { SessionState } from \"./session-state\";\nimport { emitTurnErrorAfterRecovery } from \"./session-turn-error\";\n\ninterface ActiveTurn {\n readonly abort: AbortController;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n readonly turnId: string;\n}\n\ninterface ProcessQueuedInputOptions {\n readonly activate: (turn: ActiveTurn) => void;\n readonly deactivateRun: () => void;\n readonly events: SessionEventDispatcher;\n readonly execution: SessionExecutionOptions;\n readonly item: QueuedInput;\n readonly llm: RuntimeLlm;\n readonly release: () => void;\n readonly sessionKey: string;\n readonly state: SessionState;\n}\n\nexport async function processQueuedInput({\n activate,\n deactivateRun,\n events,\n execution,\n item,\n llm,\n release,\n sessionKey,\n state,\n}: ProcessQueuedInputOptions): Promise<void> {\n const activeAbort = new AbortController();\n const { initialEvents, input, preUserRuntimeInputs, run, runtimeInput } =\n item;\n const turnId = crypto.randomUUID();\n activate({\n abort: activeAbort,\n run,\n runtimeInput,\n turnId,\n });\n const historySnapshot = state.modelSnapshot();\n let executionRun: SessionExecutionRun | undefined;\n\n try {\n executionRun = await startSessionExecutionRun({\n executionHost: execution.executionHost,\n sessionKey,\n state,\n turnId,\n });\n for (const event of initialEvents) {\n await events.emitRunEvent(run, event);\n }\n const committedPreUser = await commitPreUserRuntimeInputs(\n events,\n state,\n preUserRuntimeInputs\n );\n if (input) {\n state.appendUserInput(input);\n await state.commit();\n }\n await withRuntimeInputWindow(runtimeInput, \"turn-start\", async () => {\n await events.emitRunBoundaryEvent(run, { type: \"turn-start\" });\n });\n await emitCommittedRuntimeInputs(events, run, committedPreUser);\n await drainRuntimeInput({\n events,\n placement: \"turn-start\",\n run,\n runtimeInput,\n state,\n });\n\n const result = await runAgentLoop({\n emit: async (event) =>\n emitTurnEvent({\n event,\n events,\n run,\n runtimeInput,\n state,\n }),\n history: state.history,\n llm,\n captureObserverEvents: (callback) =>\n events.captureObserverEvents(run, callback),\n signal: activeAbort.signal,\n toolExecution: executionRun?.toolExecution,\n });\n\n await state.commit();\n await executionRun?.complete(executionStatusForResult(result));\n await closeSuccessfulTurn({\n deactivateRun,\n events,\n result,\n run,\n runtimeInput,\n });\n } catch (error) {\n const turnError = error instanceof Error ? error : new Error(String(error));\n await executionRun?.complete(executionStatusForError(turnError));\n await emitTurnErrorAfterRecovery({\n error: turnError,\n historySnapshot,\n run,\n runtimeInput,\n state,\n });\n } finally {\n closeRuntimeInput(runtimeInput);\n release();\n run.close(undefined, runtimeInput.closedReason);\n }\n}\n\nfunction executionStatusForResult(\n result: \"aborted\" | \"completed\"\n): SessionExecutionTerminalStatus {\n return result === \"aborted\" ? \"cancelled\" : \"completed\";\n}\n\nfunction executionStatusForError(error: Error): SessionExecutionTerminalStatus {\n return error instanceof ToolExecutionNeedsRecoveryError\n ? \"needs-recovery\"\n : \"error\";\n}\n\nasync function closeSuccessfulTurn({\n deactivateRun,\n events,\n result,\n run,\n runtimeInput,\n}: {\n readonly deactivateRun: () => void;\n readonly events: SessionEventDispatcher;\n readonly result: \"aborted\" | \"completed\";\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n}): Promise<void> {\n const terminalEvent = result === \"aborted\" ? \"turn-abort\" : \"turn-end\";\n closeRuntimeInput(runtimeInput, terminalEvent);\n deactivateRun();\n try {\n await events.emitRunEvent(run, { type: terminalEvent });\n } catch (terminalError) {\n run.emit({ type: \"turn-error\", message: errorMessage(terminalError) });\n closeRuntimeInput(runtimeInput, \"turn-error\");\n }\n}\n\nasync function emitTurnEvent({\n event,\n events,\n run,\n runtimeInput,\n state,\n}: {\n readonly event: AgentEvent;\n readonly events: SessionEventDispatcher;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n readonly state: SessionState;\n}): Promise<{ readonly runtimeInputAdded: boolean } | undefined> {\n if (event.type !== \"step-start\" && event.type !== \"step-end\") {\n await events.emitRunEvent(run, event);\n return;\n }\n\n await withRuntimeInputWindow(runtimeInput, event.type, async () => {\n await events.emitRunBoundaryEvent(run, event);\n });\n const runtimeInputAdded = await drainRuntimeInput({\n events,\n placement: event.type,\n run,\n runtimeInput,\n state,\n });\n return event.type === \"step-end\" ? { runtimeInputAdded } : undefined;\n}\n"],"mappings":";;;;;;;;;AA+CA,eAAsB,mBAAmB,EACvC,UACA,eACA,QACA,WACA,MACA,KACA,SACA,YACA,SAC2C;CAC3C,MAAM,cAAc,IAAI,gBAAgB;CACxC,MAAM,EAAE,eAAe,OAAO,sBAAsB,KAAK,iBACvD;CACF,MAAM,SAAS,OAAO,WAAW;CACjC,SAAS;EACP,OAAO;EACP;EACA;EACA;CACF,CAAC;CACD,MAAM,kBAAkB,MAAM,cAAc;CAC5C,IAAI;CAEJ,IAAI;EACF,eAAe,MAAM,yBAAyB;GAC5C,eAAe,UAAU;GACzB;GACA;GACA;EACF,CAAC;EACD,KAAK,MAAM,SAAS,eAClB,MAAM,OAAO,aAAa,KAAK,KAAK;EAEtC,MAAM,mBAAmB,MAAM,2BAC7B,QACA,OACA,oBACF;EACA,IAAI,OAAO;GACT,MAAM,gBAAgB,KAAK;GAC3B,MAAM,MAAM,OAAO;EACrB;EACA,MAAM,uBAAuB,cAAc,cAAc,YAAY;GACnE,MAAM,OAAO,qBAAqB,KAAK,EAAE,MAAM,aAAa,CAAC;EAC/D,CAAC;EACD,MAAM,2BAA2B,QAAQ,KAAK,gBAAgB;EAC9D,MAAM,kBAAkB;GACtB;GACA,WAAW;GACX;GACA;GACA;EACF,CAAC;EAED,MAAM,SAAS,MAAM,aAAa;GAChC,MAAM,OAAO,UACX,cAAc;IACZ;IACA;IACA;IACA;IACA;GACF,CAAC;GACH,SAAS,MAAM;GACf;GACA,wBAAwB,aACtB,OAAO,sBAAsB,KAAK,QAAQ;GAC5C,QAAQ,YAAY;GACpB,eAAe,cAAc;EAC/B,CAAC;EAED,MAAM,MAAM,OAAO;EACnB,MAAM,cAAc,SAAS,yBAAyB,MAAM,CAAC;EAC7D,MAAM,oBAAoB;GACxB;GACA;GACA;GACA;GACA;EACF,CAAC;CACH,SAAS,OAAO;EACd,MAAM,YAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;EAC1E,MAAM,cAAc,SAAS,wBAAwB,SAAS,CAAC;EAC/D,MAAM,2BAA2B;GAC/B,OAAO;GACP;GACA;GACA;GACA;EACF,CAAC;CACH,UAAU;EACR,kBAAkB,YAAY;EAC9B,QAAQ;EACR,IAAI,MAAM,KAAA,GAAW,aAAa,YAAY;CAChD;AACF;AAEA,SAAS,yBACP,QACgC;CAChC,OAAO,WAAW,YAAY,cAAc;AAC9C;AAEA,SAAS,wBAAwB,OAA8C;CAC7E,OAAO,iBAAiB,kCACpB,mBACA;AACN;AAEA,eAAe,oBAAoB,EACjC,eACA,QACA,QACA,KACA,gBAOgB;CAChB,MAAM,gBAAgB,WAAW,YAAY,eAAe;CAC5D,kBAAkB,cAAc,aAAa;CAC7C,cAAc;CACd,IAAI;EACF,MAAM,OAAO,aAAa,KAAK,EAAE,MAAM,cAAc,CAAC;CACxD,SAAS,eAAe;EACtB,IAAI,KAAK;GAAE,MAAM;GAAc,SAAS,aAAa,aAAa;EAAE,CAAC;EACrE,kBAAkB,cAAc,YAAY;CAC9C;AACF;AAEA,eAAe,cAAc,EAC3B,OACA,QACA,KACA,cACA,SAO+D;CAC/D,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,YAAY;EAC5D,MAAM,OAAO,aAAa,KAAK,KAAK;EACpC;CACF;CAEA,MAAM,uBAAuB,cAAc,MAAM,MAAM,YAAY;EACjE,MAAM,OAAO,qBAAqB,KAAK,KAAK;CAC9C,CAAC;CACD,MAAM,oBAAoB,MAAM,kBAAkB;EAChD;EACA,WAAW,MAAM;EACjB;EACA;EACA;CACF,CAAC;CACD,OAAO,MAAM,SAAS,aAAa,EAAE,kBAAkB,IAAI,KAAA;AAC7D"}
@@ -1,53 +1,77 @@
1
- import { runAgentLoop } from "../agent-loop.js";
1
+ import { attachInputMeta, userInputFromEvent } from "./input-meta.js";
2
2
  import { normalizeAgentInput } from "./input-normalization.js";
3
3
  import { BufferedAgentRun } from "./run.js";
4
- import { addSteeringInput, closeRuntimeInput, createRuntimeInputState, hooksForRuntimeInput, withRuntimeInputWindow, withSteeringPlacement } from "./runtime-input.js";
5
- import { errorMessage, runAfterTurnHook, sessionKilledError, sessionTerminalError } from "./session-errors.js";
4
+ import { addSteeringInput, createRuntimeInputState, queueRuntimeInput } from "./runtime-input.js";
5
+ import { sessionKilledError, sessionTerminalError } from "./session-errors.js";
6
+ import { SessionEventDispatcher } from "./session-events.js";
6
7
  import { closeKilledRuntimeInputs } from "./session-kill.js";
7
- import { drainRuntimeInput } from "./session-runtime-drain.js";
8
+ import { queueSessionNotification, startSessionQueueDrain } from "./session-notification.js";
8
9
  import { SessionState } from "./session-state.js";
9
- import { emitTurnErrorAfterRecovery } from "./session-turn-error.js";
10
+ import { processQueuedInput } from "./session-turn-processor.js";
10
11
  //#region src/session/session.ts
11
12
  var AgentSession = class {
12
- #hooks;
13
+ #events;
14
+ #execution;
13
15
  #inputQueue = [];
14
16
  #llm;
15
17
  #pendingRuntimeInputs = [];
18
+ #sessionKey;
16
19
  #state;
17
20
  #activeAbort;
18
21
  #activeRun;
19
22
  #activeRuntimeInput;
23
+ #activeTurnId;
20
24
  #deletePromise;
21
25
  #killed = false;
22
26
  #running = false;
23
27
  #runToCloseOnKill;
24
- constructor(llm, persistence, hooks) {
25
- this.#hooks = hooks;
28
+ constructor(llm, persistence, plugins = [], execution = {}) {
26
29
  this.#llm = llm;
30
+ this.#execution = execution;
31
+ this.#sessionKey = persistence.key;
27
32
  this.#state = new SessionState(persistence);
33
+ this.#events = new SessionEventDispatcher({
34
+ history: () => this.#state.modelSnapshot(),
35
+ plugins,
36
+ signal: () => this.#activeAbort?.signal
37
+ });
28
38
  }
29
39
  async send(input) {
30
40
  if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
31
41
  await this.#state.ensureLoaded();
32
42
  if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
33
43
  const runtimeInput = createRuntimeInputState(this.#pendingRuntimeInputs.splice(0));
34
- const acceptedInput = normalizeAgentInput(input);
44
+ const normalized = normalizeAgentInput(input);
45
+ const acceptedInput = normalized.meta === void 0 ? attachInputMeta(normalized, { source: "send" }) : normalized;
35
46
  const run = new BufferedAgentRun();
36
- run.emit(acceptedInput);
47
+ const emitted = await this.#events.emitRunEvent(run, acceptedInput);
48
+ if (emitted === "handled") {
49
+ run.close();
50
+ return run;
51
+ }
52
+ const queuedInput = userInputFromEvent(emitted.type === "user-text" || emitted.type === "user-message" ? emitted : acceptedInput);
37
53
  this.#inputQueue.push({
38
- input: structuredClone(acceptedInput),
54
+ initialEvents: [],
55
+ input: structuredClone(queuedInput),
56
+ preUserRuntimeInputs: [],
39
57
  run,
40
58
  runtimeInput
41
59
  });
42
- this.#drainInputQueue().catch((error) => {
43
- run.emit({
44
- type: "turn-error",
45
- message: errorMessage(error)
46
- });
47
- run.close();
48
- });
60
+ startSessionQueueDrain(run, () => this.#drainInputQueue());
49
61
  return run;
50
62
  }
63
+ async notify(input, options = {}) {
64
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
65
+ await this.#state.ensureLoaded();
66
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
67
+ return queueSessionNotification(input, options, {
68
+ activeRun: this.#activeRun,
69
+ activeRuntimeInput: this.#activeRuntimeInput,
70
+ drain: () => this.#drainInputQueue(),
71
+ inputQueue: this.#inputQueue,
72
+ pendingRuntimeInputs: this.#pendingRuntimeInputs
73
+ });
74
+ }
51
75
  async steer(input) {
52
76
  if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
53
77
  const runtimeInput = this.#activeRuntimeInput;
@@ -59,11 +83,17 @@ var AgentSession = class {
59
83
  interrupt() {
60
84
  this.#activeAbort?.abort();
61
85
  }
86
+ currentTurnId() {
87
+ return this.#activeTurnId;
88
+ }
62
89
  delete() {
63
- this.#deletePromise ??= this.#state.delete().then(() => this.kill(), (error) => {
64
- this.#deletePromise = void 0;
65
- throw error;
66
- });
90
+ if (!this.#deletePromise) {
91
+ this.kill();
92
+ this.#deletePromise = this.#state.delete().catch((error) => {
93
+ this.#deletePromise = void 0;
94
+ throw error;
95
+ });
96
+ }
67
97
  return this.#deletePromise;
68
98
  }
69
99
  enqueueRuntimeInput(input, placement = "turn-start") {
@@ -77,7 +107,7 @@ var AgentSession = class {
77
107
  });
78
108
  return;
79
109
  }
80
- runtimeInput.queue.push({
110
+ queueRuntimeInput(runtimeInput, {
81
111
  input,
82
112
  placement
83
113
  });
@@ -89,12 +119,12 @@ var AgentSession = class {
89
119
  });
90
120
  }
91
121
  emitObserverEvent(event) {
92
- this.#activeRun?.emit(event);
122
+ return this.#events.emitObserverEvent(this.#activeRun, event);
93
123
  }
94
124
  #enqueuePendingRuntimeInput(input) {
95
125
  const queuedTurn = this.#inputQueue[0];
96
126
  if (input.placement === "turn-start" && queuedTurn) {
97
- queuedTurn.runtimeInput.queue.push(input);
127
+ queueRuntimeInput(queuedTurn.runtimeInput, input);
98
128
  return;
99
129
  }
100
130
  this.#pendingRuntimeInputs.push(input);
@@ -118,88 +148,37 @@ var AgentSession = class {
118
148
  try {
119
149
  while (!this.#killed && this.#inputQueue.length > 0) {
120
150
  const item = this.#inputQueue.shift();
121
- if (item) await this.#processQueuedInput(item);
151
+ if (item) await processQueuedInput({
152
+ activate: ({ abort, run, runtimeInput, turnId }) => {
153
+ this.#activeAbort = abort;
154
+ this.#activeRun = run;
155
+ this.#activeRuntimeInput = runtimeInput;
156
+ this.#activeTurnId = turnId;
157
+ this.#runToCloseOnKill = run;
158
+ },
159
+ deactivateRun: () => {
160
+ this.#activeRun = void 0;
161
+ this.#activeRuntimeInput = void 0;
162
+ },
163
+ events: this.#events,
164
+ execution: this.#execution,
165
+ item,
166
+ llm: this.#llm,
167
+ release: () => {
168
+ this.#activeAbort = void 0;
169
+ this.#activeRun = void 0;
170
+ this.#activeRuntimeInput = void 0;
171
+ this.#activeTurnId = void 0;
172
+ this.#runToCloseOnKill = void 0;
173
+ },
174
+ sessionKey: this.#sessionKey,
175
+ state: this.#state
176
+ });
122
177
  }
123
178
  } finally {
124
179
  this.#running = false;
125
180
  }
126
181
  }
127
- async #processQueuedInput({ input, run, runtimeInput }) {
128
- const activeAbort = new AbortController();
129
- this.#activeAbort = activeAbort;
130
- this.#activeRun = run;
131
- this.#activeRuntimeInput = runtimeInput;
132
- this.#runToCloseOnKill = run;
133
- const historySnapshot = this.#state.modelSnapshot();
134
- try {
135
- await withSteeringPlacement(runtimeInput, "turn-start", async () => {
136
- await this.#hooks?.beforeTurn?.({
137
- history: this.#state.modelSnapshot(),
138
- input,
139
- signal: activeAbort.signal
140
- });
141
- });
142
- await withRuntimeInputWindow(runtimeInput, "turn-start", async () => {
143
- await run.emitBoundary({ type: "turn-start" });
144
- });
145
- this.#state.appendUserInput(input);
146
- await this.#state.commit();
147
- await drainRuntimeInput({
148
- placement: "turn-start",
149
- run,
150
- runtimeInput,
151
- state: this.#state
152
- });
153
- const result = await runAgentLoop({
154
- emit: async (event) => {
155
- if (event.type === "step-start" || event.type === "step-end") {
156
- await withRuntimeInputWindow(runtimeInput, event.type, async () => {
157
- await run.emitBoundary(event);
158
- });
159
- const runtimeInputAdded = await drainRuntimeInput({
160
- placement: event.type,
161
- run,
162
- runtimeInput,
163
- state: this.#state
164
- });
165
- return event.type === "step-end" ? { runtimeInputAdded } : void 0;
166
- }
167
- run.emit(event);
168
- },
169
- history: this.#state.history,
170
- hooks: hooksForRuntimeInput(this.#hooks, runtimeInput),
171
- llm: this.#llm,
172
- signal: activeAbort.signal
173
- });
174
- await this.#state.commit();
175
- const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
176
- closeRuntimeInput(runtimeInput, terminalEvent);
177
- this.#activeRuntimeInput = void 0;
178
- this.#activeRun = void 0;
179
- await runAfterTurnHook(this.#hooks, {
180
- history: this.#state.modelSnapshot(),
181
- input,
182
- result,
183
- signal: activeAbort.signal
184
- });
185
- run.emit({ type: terminalEvent });
186
- } catch (error) {
187
- await emitTurnErrorAfterRecovery({
188
- error: error instanceof Error ? error : new Error(String(error)),
189
- historySnapshot,
190
- run,
191
- runtimeInput,
192
- state: this.#state
193
- });
194
- } finally {
195
- closeRuntimeInput(runtimeInput);
196
- this.#activeAbort = void 0;
197
- this.#activeRun = void 0;
198
- this.#activeRuntimeInput = void 0;
199
- this.#runToCloseOnKill = void 0;
200
- run.close(void 0, runtimeInput.closedReason);
201
- }
202
- }
203
182
  };
204
183
  //#endregion
205
184
  export { AgentSession };
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":["#hooks","#inputQueue","#llm","#pendingRuntimeInputs","#state","#killed","#deletePromise","#drainInputQueue","#activeRuntimeInput","#activeRun","#activeAbort","#enqueuePendingRuntimeInput","#runToCloseOnKill","#running","#processQueuedInput"],"sources":["../../src/session/session.ts"],"sourcesContent":["import { runAgentLoop } from \"../agent-loop\";\nimport type { AgentHooks } from \"../hooks\";\nimport type { Llm } from \"../llm\";\nimport type { AgentEvent } from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\nimport { normalizeAgentInput } from \"./input-normalization\";\nimport { type AgentRun, BufferedAgentRun } from \"./run\";\nimport {\n addSteeringInput,\n closeRuntimeInput,\n createRuntimeInputState,\n hooksForRuntimeInput,\n type QueuedInput,\n type QueuedRuntimeInput,\n type RuntimeInputPlacement,\n type RuntimeInputState,\n withRuntimeInputWindow,\n withSteeringPlacement,\n} from \"./runtime-input\";\nimport {\n errorMessage,\n runAfterTurnHook,\n sessionKilledError,\n sessionTerminalError,\n} from \"./session-errors\";\nimport { closeKilledRuntimeInputs } from \"./session-kill\";\nimport { drainRuntimeInput } from \"./session-runtime-drain\";\nimport { type SessionPersistenceOptions, SessionState } from \"./session-state\";\nimport { emitTurnErrorAfterRecovery } from \"./session-turn-error\";\n\nexport type { AgentInput, SessionInput, UserInput } from \"./input\";\nexport type { AgentRun } from \"./run\";\n\nexport class AgentSession {\n readonly #hooks?: AgentHooks;\n readonly #inputQueue: QueuedInput[] = [];\n readonly #llm: Llm;\n readonly #pendingRuntimeInputs: QueuedRuntimeInput[] = [];\n readonly #state: SessionState;\n #activeAbort?: AbortController;\n #activeRun?: BufferedAgentRun;\n #activeRuntimeInput?: RuntimeInputState;\n #deletePromise?: Promise<void>;\n #killed = false;\n #running = false;\n #runToCloseOnKill?: BufferedAgentRun;\n\n constructor(\n llm: Llm,\n persistence: SessionPersistenceOptions,\n hooks?: AgentHooks\n ) {\n this.#hooks = hooks;\n this.#llm = llm;\n this.#state = new SessionState(persistence);\n }\n\n async send(input: AgentInput): Promise<AgentRun> {\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n await this.#state.ensureLoaded();\n\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n const runtimeInput = createRuntimeInputState(\n this.#pendingRuntimeInputs.splice(0)\n );\n const acceptedInput = normalizeAgentInput(input);\n const run = new BufferedAgentRun();\n run.emit(acceptedInput);\n this.#inputQueue.push({\n input: structuredClone(acceptedInput),\n run,\n runtimeInput,\n });\n this.#drainInputQueue().catch((error: unknown) => {\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n run.close();\n });\n return run;\n }\n\n async steer(input: AgentInput): Promise<AgentRun> {\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n const runtimeInput = this.#activeRuntimeInput;\n const run = this.#activeRun;\n if (!(runtimeInput && run)) {\n return this.send(input);\n }\n\n await addSteeringInput(runtimeInput, input);\n return run;\n }\n\n interrupt(): void {\n this.#activeAbort?.abort();\n }\n\n delete(): Promise<void> {\n this.#deletePromise ??= this.#state.delete().then(\n () => this.kill(),\n (error: unknown) => {\n this.#deletePromise = undefined;\n throw error;\n }\n );\n return this.#deletePromise;\n }\n\n enqueueRuntimeInput(\n input: UserInput,\n placement: RuntimeInputPlacement = \"turn-start\"\n ): void {\n if (this.#killed) {\n return;\n }\n\n const runtimeInput = this.#activeRuntimeInput;\n if (runtimeInput && !runtimeInput.closedReason) {\n if (placement === \"turn-start\" && runtimeInput.placement !== placement) {\n this.#enqueuePendingRuntimeInput({ input, placement });\n return;\n }\n\n runtimeInput.queue.push({ input, placement });\n return;\n }\n\n this.#enqueuePendingRuntimeInput({ input, placement });\n }\n\n emitObserverEvent(event: AgentEvent): void {\n this.#activeRun?.emit(event);\n }\n\n #enqueuePendingRuntimeInput(input: QueuedRuntimeInput): void {\n const queuedTurn = this.#inputQueue[0];\n if (input.placement === \"turn-start\" && queuedTurn) {\n queuedTurn.runtimeInput.queue.push(input);\n return;\n }\n\n this.#pendingRuntimeInputs.push(input);\n }\n\n kill(): void {\n if (this.#killed) {\n return;\n }\n\n this.#killed = true;\n const killedError = sessionKilledError();\n this.#pendingRuntimeInputs.length = 0;\n this.#activeAbort?.abort();\n closeKilledRuntimeInputs({\n activeRuntimeInput: this.#activeRuntimeInput,\n inputQueue: this.#inputQueue,\n message: killedError.message,\n runToClose: this.#runToCloseOnKill ?? this.#activeRun,\n });\n }\n\n async #drainInputQueue(): Promise<void> {\n if (this.#running) {\n return;\n }\n\n this.#running = true;\n try {\n while (!this.#killed && this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n if (item) {\n await this.#processQueuedInput(item);\n }\n }\n } finally {\n this.#running = false;\n }\n }\n\n async #processQueuedInput({\n input,\n run,\n runtimeInput,\n }: QueuedInput): Promise<void> {\n const activeAbort = new AbortController();\n this.#activeAbort = activeAbort;\n this.#activeRun = run;\n this.#activeRuntimeInput = runtimeInput;\n this.#runToCloseOnKill = run;\n const historySnapshot = this.#state.modelSnapshot();\n\n try {\n await withSteeringPlacement(runtimeInput, \"turn-start\", async () => {\n await this.#hooks?.beforeTurn?.({\n history: this.#state.modelSnapshot(),\n input,\n signal: activeAbort.signal,\n });\n });\n await withRuntimeInputWindow(runtimeInput, \"turn-start\", async () => {\n await run.emitBoundary({ type: \"turn-start\" });\n });\n this.#state.appendUserInput(input);\n await this.#state.commit();\n await drainRuntimeInput({\n placement: \"turn-start\",\n run,\n runtimeInput,\n state: this.#state,\n });\n\n const result = await runAgentLoop({\n emit: async (event) => {\n if (event.type === \"step-start\" || event.type === \"step-end\") {\n await withRuntimeInputWindow(runtimeInput, event.type, async () => {\n await run.emitBoundary(event);\n });\n const runtimeInputAdded = await drainRuntimeInput({\n placement: event.type,\n run,\n runtimeInput,\n state: this.#state,\n });\n\n return event.type === \"step-end\"\n ? { runtimeInputAdded }\n : undefined;\n }\n\n run.emit(event);\n },\n history: this.#state.history,\n hooks: hooksForRuntimeInput(this.#hooks, runtimeInput),\n llm: this.#llm,\n signal: activeAbort.signal,\n });\n\n await this.#state.commit();\n const terminalEvent = result === \"aborted\" ? \"turn-abort\" : \"turn-end\";\n closeRuntimeInput(runtimeInput, terminalEvent);\n this.#activeRuntimeInput = undefined;\n this.#activeRun = undefined;\n await runAfterTurnHook(this.#hooks, {\n history: this.#state.modelSnapshot(),\n input,\n result,\n signal: activeAbort.signal,\n });\n run.emit({ type: terminalEvent });\n } catch (error) {\n const turnError =\n error instanceof Error ? error : new Error(String(error));\n await emitTurnErrorAfterRecovery({\n error: turnError,\n historySnapshot,\n run,\n runtimeInput,\n state: this.#state,\n });\n } finally {\n closeRuntimeInput(runtimeInput);\n this.#activeAbort = undefined;\n this.#activeRun = undefined;\n this.#activeRuntimeInput = undefined;\n this.#runToCloseOnKill = undefined;\n run.close(undefined, runtimeInput.closedReason);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session.js","names":["#events","#execution","#inputQueue","#llm","#pendingRuntimeInputs","#sessionKey","#state","#activeAbort","#killed","#deletePromise","#drainInputQueue","#activeRun","#activeRuntimeInput","#activeTurnId","#enqueuePendingRuntimeInput","#runToCloseOnKill","#running"],"sources":["../../src/session/session.ts"],"sourcesContent":["import type { RuntimeLlm } from \"../llm\";\nimport type { AgentPlugin } from \"../plugins\";\nimport type { AgentEvent } from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\nimport { attachInputMeta, userInputFromEvent } from \"./input-meta\";\nimport { normalizeAgentInput } from \"./input-normalization\";\nimport { type AgentRun, BufferedAgentRun } from \"./run\";\nimport {\n addSteeringInput,\n createRuntimeInputState,\n type QueuedInput,\n type QueuedRuntimeInput,\n queueRuntimeInput,\n type RuntimeInputPlacement,\n type RuntimeInputState,\n} from \"./runtime-input\";\nimport { sessionKilledError, sessionTerminalError } from \"./session-errors\";\nimport { SessionEventDispatcher } from \"./session-events\";\nimport type { SessionExecutionOptions } from \"./session-execution\";\nimport { closeKilledRuntimeInputs } from \"./session-kill\";\nimport {\n type NotifyOptions,\n queueSessionNotification,\n startSessionQueueDrain,\n} from \"./session-notification\";\nimport { type SessionPersistenceOptions, SessionState } from \"./session-state\";\nimport { processQueuedInput } from \"./session-turn-processor\";\n\nexport type { AgentInput, SessionInput, UserInput } from \"./input\";\nexport type { AgentRun } from \"./run\";\nexport type { NotifyOptions } from \"./session-notification\";\n\nexport class AgentSession {\n readonly #events: SessionEventDispatcher;\n readonly #execution: SessionExecutionOptions;\n readonly #inputQueue: QueuedInput[] = [];\n readonly #llm: RuntimeLlm;\n readonly #pendingRuntimeInputs: QueuedRuntimeInput[] = [];\n readonly #sessionKey: string;\n readonly #state: SessionState;\n #activeAbort?: AbortController;\n #activeRun?: BufferedAgentRun;\n #activeRuntimeInput?: RuntimeInputState;\n #activeTurnId?: string;\n #deletePromise?: Promise<void>;\n #killed = false;\n #running = false;\n #runToCloseOnKill?: BufferedAgentRun;\n\n constructor(\n llm: RuntimeLlm,\n persistence: SessionPersistenceOptions,\n plugins: readonly AgentPlugin[] = [],\n execution: SessionExecutionOptions = {}\n ) {\n this.#llm = llm;\n this.#execution = execution;\n this.#sessionKey = persistence.key;\n this.#state = new SessionState(persistence);\n this.#events = new SessionEventDispatcher({\n history: () => this.#state.modelSnapshot(),\n plugins,\n signal: () => this.#activeAbort?.signal,\n });\n }\n\n async send(input: AgentInput): Promise<AgentRun> {\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n await this.#state.ensureLoaded();\n\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n const runtimeInput = createRuntimeInputState(\n this.#pendingRuntimeInputs.splice(0)\n );\n const normalized = normalizeAgentInput(input);\n const acceptedInput =\n normalized.meta === undefined\n ? attachInputMeta(normalized, { source: \"send\" })\n : normalized;\n const run = new BufferedAgentRun();\n const emitted = await this.#events.emitRunEvent(run, acceptedInput);\n if (emitted === \"handled\") {\n run.close();\n return run;\n }\n\n const queuedInput = userInputFromEvent(\n emitted.type === \"user-text\" || emitted.type === \"user-message\"\n ? emitted\n : acceptedInput\n );\n this.#inputQueue.push({\n initialEvents: [],\n input: structuredClone(queuedInput),\n preUserRuntimeInputs: [],\n run,\n runtimeInput,\n });\n startSessionQueueDrain(run, () => this.#drainInputQueue());\n return run;\n }\n\n async notify(\n input: AgentInput,\n options: NotifyOptions = {}\n ): Promise<AgentRun> {\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n await this.#state.ensureLoaded();\n\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n return queueSessionNotification(input, options, {\n activeRun: this.#activeRun,\n activeRuntimeInput: this.#activeRuntimeInput,\n drain: () => this.#drainInputQueue(),\n inputQueue: this.#inputQueue,\n pendingRuntimeInputs: this.#pendingRuntimeInputs,\n });\n }\n\n async steer(input: AgentInput): Promise<AgentRun> {\n if (this.#killed || this.#deletePromise) {\n throw sessionTerminalError(this.#killed);\n }\n\n const runtimeInput = this.#activeRuntimeInput;\n const run = this.#activeRun;\n if (!(runtimeInput && run)) {\n return this.send(input);\n }\n\n await addSteeringInput(runtimeInput, input);\n return run;\n }\n\n interrupt(): void {\n this.#activeAbort?.abort();\n }\n\n currentTurnId(): string | undefined {\n return this.#activeTurnId;\n }\n\n delete(): Promise<void> {\n if (!this.#deletePromise) {\n this.kill();\n this.#deletePromise = this.#state.delete().catch((error: unknown) => {\n this.#deletePromise = undefined;\n throw error;\n });\n }\n return this.#deletePromise;\n }\n\n enqueueRuntimeInput(\n input: UserInput,\n placement: RuntimeInputPlacement = \"turn-start\"\n ): void {\n if (this.#killed) {\n return;\n }\n\n const runtimeInput = this.#activeRuntimeInput;\n if (runtimeInput && !runtimeInput.closedReason) {\n if (placement === \"turn-start\" && runtimeInput.placement !== placement) {\n this.#enqueuePendingRuntimeInput({ input, placement });\n return;\n }\n\n queueRuntimeInput(runtimeInput, { input, placement });\n return;\n }\n\n this.#enqueuePendingRuntimeInput({ input, placement });\n }\n\n emitObserverEvent(event: AgentEvent): Promise<void> {\n return this.#events.emitObserverEvent(this.#activeRun, event);\n }\n\n #enqueuePendingRuntimeInput(input: QueuedRuntimeInput): void {\n const queuedTurn = this.#inputQueue[0];\n if (input.placement === \"turn-start\" && queuedTurn) {\n queueRuntimeInput(queuedTurn.runtimeInput, input);\n return;\n }\n\n this.#pendingRuntimeInputs.push(input);\n }\n\n kill(): void {\n if (this.#killed) {\n return;\n }\n\n this.#killed = true;\n const killedError = sessionKilledError();\n this.#pendingRuntimeInputs.length = 0;\n this.#activeAbort?.abort();\n closeKilledRuntimeInputs({\n activeRuntimeInput: this.#activeRuntimeInput,\n inputQueue: this.#inputQueue,\n message: killedError.message,\n runToClose: this.#runToCloseOnKill ?? this.#activeRun,\n });\n }\n\n async #drainInputQueue(): Promise<void> {\n if (this.#running) {\n return;\n }\n\n this.#running = true;\n try {\n while (!this.#killed && this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n if (item) {\n await processQueuedInput({\n activate: ({ abort, run, runtimeInput, turnId }) => {\n this.#activeAbort = abort;\n this.#activeRun = run;\n this.#activeRuntimeInput = runtimeInput;\n this.#activeTurnId = turnId;\n this.#runToCloseOnKill = run;\n },\n deactivateRun: () => {\n this.#activeRun = undefined;\n this.#activeRuntimeInput = undefined;\n },\n events: this.#events,\n execution: this.#execution,\n item,\n llm: this.#llm,\n release: () => {\n this.#activeAbort = undefined;\n this.#activeRun = undefined;\n this.#activeRuntimeInput = undefined;\n this.#activeTurnId = undefined;\n this.#runToCloseOnKill = undefined;\n },\n sessionKey: this.#sessionKey,\n state: this.#state,\n });\n }\n }\n } finally {\n this.#running = false;\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/session/snapshot.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { StoredSession } from \"./store/types\";\n\nexport interface AgentSessionSnapshotV1 {\n readonly history: ModelMessage[];\n readonly schemaVersion: 1;\n}\n\nexport type AgentSessionSnapshot = AgentSessionSnapshotV1;\n\nexport function encodeSessionSnapshot(\n history: ModelMessage[]\n): AgentSessionSnapshot {\n return { schemaVersion: 1, history: structuredClone(history) };\n}\n\nexport function decodeStoredSessionSnapshot(\n stored: StoredSession | null\n): ModelMessage[] {\n if (!stored) {\n return [];\n }\n\n const snapshot = stored.state;\n if (isSessionSnapshotV1(snapshot)) {\n return structuredClone(snapshot.history);\n }\n\n throw new Error(\"Unsupported stored session state\");\n}\n\nfunction isSessionSnapshotV1(value: unknown): value is AgentSessionSnapshotV1 {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"schemaVersion\" in value &&\n value.schemaVersion === 1 &&\n \"history\" in value &&\n Array.isArray(value.history)\n );\n}\n"],"mappings":";AAUA,SAAgB,sBACd,SACsB;CACtB,OAAO;EAAE,eAAe;EAAG,SAAS,gBAAgB,OAAO;CAAE;AAC/D;AAEA,SAAgB,4BACd,QACgB;CAChB,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,WAAW,OAAO;CACxB,IAAI,oBAAoB,QAAQ,GAC9B,OAAO,gBAAgB,SAAS,OAAO;CAGzC,MAAM,IAAI,MAAM,kCAAkC;AACpD;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/session/snapshot.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { StoredSession } from \"./store/types\";\n\nexport interface AgentSessionSnapshotV1 {\n readonly history: ModelMessage[];\n readonly schemaVersion: 1;\n}\n\nexport function encodeSessionSnapshot(\n history: ModelMessage[]\n): AgentSessionSnapshotV1 {\n return { schemaVersion: 1, history: structuredClone(history) };\n}\n\nexport function decodeStoredSessionSnapshot(\n stored: StoredSession | null\n): ModelMessage[] {\n if (!stored) {\n return [];\n }\n\n const snapshot = stored.state;\n if (isSessionSnapshotV1(snapshot)) {\n return structuredClone(snapshot.history);\n }\n\n throw new Error(\"Unsupported stored session state\");\n}\n\nfunction isSessionSnapshotV1(value: unknown): value is AgentSessionSnapshotV1 {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"schemaVersion\" in value &&\n value.schemaVersion === 1 &&\n \"history\" in value &&\n Array.isArray(value.history)\n );\n}\n"],"mappings":";AAQA,SAAgB,sBACd,SACwB;CACxB,OAAO;EAAE,eAAe;EAAG,SAAS,gBAAgB,OAAO;CAAE;AAC/D;AAEA,SAAgB,4BACd,QACgB;CAChB,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,WAAW,OAAO;CACxB,IAAI,oBAAoB,QAAQ,GAC9B,OAAO,gBAAgB,SAAS,OAAO;CAGzC,MAAM,IAAI,MAAM,kCAAkC;AACpD;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minpeter/pss-runtime",
3
- "version": "0.1.0-next.1",
3
+ "version": "0.1.0-next.3",
4
4
  "description": "Generic agent runtime for sessions, model loops, and synchronized run events.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,6 +20,21 @@
20
20
  "@minpeter/pss-source": "./src/session/store/file.ts",
21
21
  "types": "./dist/session/store/file.d.ts",
22
22
  "import": "./dist/session/store/file.js"
23
+ },
24
+ "./cloudflare": {
25
+ "@minpeter/pss-source": "./src/cloudflare/index.ts",
26
+ "types": "./dist/cloudflare/index.d.ts",
27
+ "import": "./dist/cloudflare/index.js"
28
+ },
29
+ "./execution": {
30
+ "@minpeter/pss-source": "./src/execution/index.ts",
31
+ "types": "./dist/execution/index.d.ts",
32
+ "import": "./dist/execution/index.js"
33
+ },
34
+ "./execution/memory": {
35
+ "@minpeter/pss-source": "./src/execution/memory.ts",
36
+ "types": "./dist/execution/memory.d.ts",
37
+ "import": "./dist/execution/memory.js"
23
38
  }
24
39
  },
25
40
  "files": [
@@ -1,35 +0,0 @@
1
- //#region src/agent-validation.ts
2
- const subagentNamePattern = /^[a-z][a-z0-9_-]{0,51}$/;
3
- function assertSubagents(options, agentClass, hasCustomLlm) {
4
- if (!("subagents" in options) || options.subagents === void 0) return;
5
- if (hasCustomLlm) throw new TypeError("Agent: subagents require options.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
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-validation.js","names":[],"sources":["../src/agent-validation.ts"],"sourcesContent":["import type { ToolSet } from \"ai\";\nimport type { Agent, AgentOptions } from \"./agent\";\n\nconst subagentNamePattern = /^[a-z][a-z0-9_-]{0,51}$/;\n\nexport function assertSubagents(\n options: AgentOptions,\n agentClass: new (options: AgentOptions) => Agent,\n hasCustomLlm: boolean\n): void {\n if (!(\"subagents\" in options) || options.subagents === undefined) {\n return;\n }\n\n if (hasCustomLlm) {\n throw new TypeError(\"Agent: subagents require options.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":";AAGA,MAAM,sBAAsB;AAE5B,SAAgB,gBACd,SACA,YACA,cACM;CACN,IAAI,EAAE,eAAe,YAAY,QAAQ,cAAc,KAAA,GACrD;CAGF,IAAI,cACF,MAAM,IAAI,UAAU,yCAAyC;CAG/D,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"}
@@ -1,61 +0,0 @@
1
- //#region src/child-session-cleanups.ts
2
- var ChildSessionCleanups = class {
3
- #byParentSession = /* @__PURE__ */ new Map();
4
- async delete(parentSessionKey) {
5
- const cleanups = this.#byParentSession.get(parentSessionKey);
6
- if (!cleanups) return;
7
- this.#byParentSession.delete(parentSessionKey);
8
- const results = await Promise.all([...cleanups].map(runCleanup));
9
- const failedCleanups = [];
10
- let firstError;
11
- for (const result of results) {
12
- if (result.ok) continue;
13
- firstError ??= result.error;
14
- failedCleanups.push(result.cleanup);
15
- }
16
- if (failedCleanups.length === 0) return;
17
- this.#restore(parentSessionKey, failedCleanups);
18
- throw firstError instanceof Error ? firstError : new Error(String(firstError));
19
- }
20
- register(parentSessionKey, cleanup) {
21
- const existing = this.#byParentSession.get(parentSessionKey);
22
- if (existing) {
23
- existing.add(cleanup);
24
- return () => this.#unregister(parentSessionKey, existing, cleanup);
25
- }
26
- const cleanups = new Set([cleanup]);
27
- this.#byParentSession.set(parentSessionKey, cleanups);
28
- return () => this.#unregister(parentSessionKey, cleanups, cleanup);
29
- }
30
- #unregister(parentSessionKey, cleanups, cleanup) {
31
- cleanups.delete(cleanup);
32
- if (cleanups.size === 0 && this.#byParentSession.get(parentSessionKey) === cleanups) this.#byParentSession.delete(parentSessionKey);
33
- }
34
- #restore(parentSessionKey, failedCleanups) {
35
- const current = this.#byParentSession.get(parentSessionKey);
36
- if (current) {
37
- for (const cleanup of failedCleanups) current.add(cleanup);
38
- return;
39
- }
40
- this.#byParentSession.set(parentSessionKey, new Set(failedCleanups));
41
- }
42
- };
43
- async function runCleanup(cleanup) {
44
- try {
45
- await cleanup();
46
- return {
47
- cleanup,
48
- ok: true
49
- };
50
- } catch (error) {
51
- return {
52
- cleanup,
53
- error,
54
- ok: false
55
- };
56
- }
57
- }
58
- //#endregion
59
- export { ChildSessionCleanups };
60
-
61
- //# sourceMappingURL=child-session-cleanups.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"child-session-cleanups.js","names":["#byParentSession","#restore","#unregister"],"sources":["../src/child-session-cleanups.ts"],"sourcesContent":["type ChildSessionCleanup = () => Promise<void>;\n\ntype CleanupResult =\n | { readonly cleanup: ChildSessionCleanup; readonly ok: true }\n | {\n readonly cleanup: ChildSessionCleanup;\n readonly error: unknown;\n readonly ok: false;\n };\n\nexport class ChildSessionCleanups {\n readonly #byParentSession = new Map<string, Set<ChildSessionCleanup>>();\n\n async delete(parentSessionKey: string): Promise<void> {\n const cleanups = this.#byParentSession.get(parentSessionKey);\n if (!cleanups) {\n return;\n }\n\n this.#byParentSession.delete(parentSessionKey);\n const results = await Promise.all([...cleanups].map(runCleanup));\n const failedCleanups: ChildSessionCleanup[] = [];\n let firstError: unknown;\n for (const result of results) {\n if (result.ok) {\n continue;\n }\n\n firstError ??= result.error;\n failedCleanups.push(result.cleanup);\n }\n\n if (failedCleanups.length === 0) {\n return;\n }\n\n this.#restore(parentSessionKey, failedCleanups);\n throw firstError instanceof Error\n ? firstError\n : new Error(String(firstError));\n }\n\n register(parentSessionKey: string, cleanup: ChildSessionCleanup): () => void {\n const existing = this.#byParentSession.get(parentSessionKey);\n if (existing) {\n existing.add(cleanup);\n return () => this.#unregister(parentSessionKey, existing, cleanup);\n }\n\n const cleanups = new Set([cleanup]);\n this.#byParentSession.set(parentSessionKey, cleanups);\n return () => this.#unregister(parentSessionKey, cleanups, cleanup);\n }\n\n #unregister(\n parentSessionKey: string,\n cleanups: Set<ChildSessionCleanup>,\n cleanup: ChildSessionCleanup\n ): void {\n cleanups.delete(cleanup);\n if (\n cleanups.size === 0 &&\n this.#byParentSession.get(parentSessionKey) === cleanups\n ) {\n this.#byParentSession.delete(parentSessionKey);\n }\n }\n\n #restore(\n parentSessionKey: string,\n failedCleanups: readonly ChildSessionCleanup[]\n ): void {\n const current = this.#byParentSession.get(parentSessionKey);\n if (current) {\n for (const cleanup of failedCleanups) {\n current.add(cleanup);\n }\n return;\n }\n\n this.#byParentSession.set(parentSessionKey, new Set(failedCleanups));\n }\n}\n\nasync function runCleanup(\n cleanup: ChildSessionCleanup\n): Promise<CleanupResult> {\n try {\n await cleanup();\n return { cleanup, ok: true };\n } catch (error) {\n return { cleanup, error, ok: false };\n }\n}\n"],"mappings":";AAUA,IAAa,uBAAb,MAAkC;CAChC,mCAA4B,IAAI,IAAsC;CAEtE,MAAM,OAAO,kBAAyC;EACpD,MAAM,WAAW,KAAKA,iBAAiB,IAAI,gBAAgB;EAC3D,IAAI,CAAC,UACH;EAGF,KAAKA,iBAAiB,OAAO,gBAAgB;EAC7C,MAAM,UAAU,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ,EAAE,IAAI,UAAU,CAAC;EAC/D,MAAM,iBAAwC,CAAC;EAC/C,IAAI;EACJ,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,OAAO,IACT;GAGF,eAAe,OAAO;GACtB,eAAe,KAAK,OAAO,OAAO;EACpC;EAEA,IAAI,eAAe,WAAW,GAC5B;EAGF,KAAKC,SAAS,kBAAkB,cAAc;EAC9C,MAAM,sBAAsB,QACxB,aACA,IAAI,MAAM,OAAO,UAAU,CAAC;CAClC;CAEA,SAAS,kBAA0B,SAA0C;EAC3E,MAAM,WAAW,KAAKD,iBAAiB,IAAI,gBAAgB;EAC3D,IAAI,UAAU;GACZ,SAAS,IAAI,OAAO;GACpB,aAAa,KAAKE,YAAY,kBAAkB,UAAU,OAAO;EACnE;EAEA,MAAM,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC;EAClC,KAAKF,iBAAiB,IAAI,kBAAkB,QAAQ;EACpD,aAAa,KAAKE,YAAY,kBAAkB,UAAU,OAAO;CACnE;CAEA,YACE,kBACA,UACA,SACM;EACN,SAAS,OAAO,OAAO;EACvB,IACE,SAAS,SAAS,KAClB,KAAKF,iBAAiB,IAAI,gBAAgB,MAAM,UAEhD,KAAKA,iBAAiB,OAAO,gBAAgB;CAEjD;CAEA,SACE,kBACA,gBACM;EACN,MAAM,UAAU,KAAKA,iBAAiB,IAAI,gBAAgB;EAC1D,IAAI,SAAS;GACX,KAAK,MAAM,WAAW,gBACpB,QAAQ,IAAI,OAAO;GAErB;EACF;EAEA,KAAKA,iBAAiB,IAAI,kBAAkB,IAAI,IAAI,cAAc,CAAC;CACrE;AACF;AAEA,eAAe,WACb,SACwB;CACxB,IAAI;EACF,MAAM,QAAQ;EACd,OAAO;GAAE;GAAS,IAAI;EAAK;CAC7B,SAAS,OAAO;EACd,OAAO;GAAE;GAAS;GAAO,IAAI;EAAM;CACrC;AACF"}
package/dist/hooks.d.ts DELETED
@@ -1,32 +0,0 @@
1
- import { RuntimeLlmContext } from "./llm.js";
2
- import { UserInput } from "./session/input.js";
3
-
4
- //#region src/hooks.d.ts
5
- type AgentTurnResult = "aborted" | "completed";
6
- type AgentStepResult = "completed" | "continue";
7
- type MaybePromise<T> = PromiseLike<T> | T;
8
- interface AgentBeforeTurnContext {
9
- readonly history: RuntimeLlmContext["history"];
10
- readonly input: UserInput;
11
- readonly signal: AbortSignal;
12
- }
13
- interface AgentAfterTurnContext extends AgentBeforeTurnContext {
14
- readonly result: AgentTurnResult;
15
- }
16
- interface AgentBeforeStepContext {
17
- readonly history: RuntimeLlmContext["history"];
18
- readonly signal: AbortSignal;
19
- readonly stepIndex: number;
20
- }
21
- interface AgentAfterStepContext extends AgentBeforeStepContext {
22
- readonly result: AgentStepResult;
23
- }
24
- interface AgentHooks {
25
- afterStep?(context: AgentAfterStepContext): MaybePromise<void>;
26
- afterTurn?(context: AgentAfterTurnContext): MaybePromise<void>;
27
- beforeStep?(context: AgentBeforeStepContext): MaybePromise<void>;
28
- beforeTurn?(context: AgentBeforeTurnContext): MaybePromise<void>;
29
- }
30
- //#endregion
31
- export { AgentAfterStepContext, AgentAfterTurnContext, AgentBeforeStepContext, AgentBeforeTurnContext, AgentHooks, AgentStepResult, AgentTurnResult };
32
- //# sourceMappingURL=hooks.d.ts.map
@@ -1,28 +0,0 @@
1
- import { assertBackgroundTaskId, cancelJob, isActiveJob } from "./subagent-jobs.js";
2
- import { jsonSchema, tool } from "ai";
3
- //#region src/subagent-job-cancel.ts
4
- function createBackgroundCancelTool(jobs) {
5
- return tool({
6
- description: "Cancel an active background subagent job.",
7
- execute: (input) => {
8
- assertBackgroundTaskId(input.task_id, "background_cancel");
9
- const job = jobs.get(input.task_id);
10
- if (!job) throw new Error(`Unknown background subagent task ${input.task_id}.`);
11
- if (isActiveJob(job.status)) cancelJob(job);
12
- return {
13
- status: job.status,
14
- task_id: job.id
15
- };
16
- },
17
- inputSchema: jsonSchema({
18
- additionalProperties: false,
19
- properties: { task_id: { type: "string" } },
20
- required: ["task_id"],
21
- type: "object"
22
- })
23
- });
24
- }
25
- //#endregion
26
- export { createBackgroundCancelTool };
27
-
28
- //# sourceMappingURL=subagent-job-cancel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-job-cancel.js","names":[],"sources":["../src/subagent-job-cancel.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport {\n assertBackgroundTaskId,\n cancelJob,\n isActiveJob,\n} from \"./subagent-jobs\";\nimport type { BackgroundCancelInput, SubagentJob } from \"./subagent-types\";\n\nexport function createBackgroundCancelTool(jobs: Map<string, SubagentJob>) {\n return tool<BackgroundCancelInput, unknown, Record<string, unknown>>({\n description: \"Cancel an active background subagent job.\",\n execute: (input: BackgroundCancelInput) => {\n assertBackgroundTaskId(input.task_id, \"background_cancel\");\n const job = jobs.get(input.task_id);\n if (!job) {\n throw new Error(`Unknown background subagent task ${input.task_id}.`);\n }\n\n if (isActiveJob(job.status)) {\n cancelJob(job);\n }\n\n return {\n status: job.status,\n task_id: job.id,\n };\n },\n inputSchema: jsonSchema<BackgroundCancelInput>({\n additionalProperties: false,\n properties: {\n task_id: { type: \"string\" },\n },\n required: [\"task_id\"],\n type: \"object\",\n }),\n });\n}\n"],"mappings":";;;AAQA,SAAgB,2BAA2B,MAAgC;CACzE,OAAO,KAA8D;EACnE,aAAa;EACb,UAAU,UAAiC;GACzC,uBAAuB,MAAM,SAAS,mBAAmB;GACzD,MAAM,MAAM,KAAK,IAAI,MAAM,OAAO;GAClC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,oCAAoC,MAAM,QAAQ,EAAE;GAGtE,IAAI,YAAY,IAAI,MAAM,GACxB,UAAU,GAAG;GAGf,OAAO;IACL,QAAQ,IAAI;IACZ,SAAS,IAAI;GACf;EACF;EACA,aAAa,WAAkC;GAC7C,sBAAsB;GACtB,YAAY,EACV,SAAS,EAAE,MAAM,SAAS,EAC5B;GACA,UAAU,CAAC,SAAS;GACpB,MAAM;EACR,CAAC;CACH,CAAC;AACH"}
@@ -1,63 +0,0 @@
1
- import { assertBackgroundTaskId, cleanupJob, isActiveJob } from "./subagent-jobs.js";
2
- import { jsonSchema, tool } from "ai";
3
- //#region src/subagent-job-output.ts
4
- function createBackgroundOutputTool(jobs) {
5
- return tool({
6
- description: "Retrieve compact output for a background subagent job.",
7
- execute: async (input, { abortSignal }) => {
8
- assertBackgroundTaskId(input.task_id, "background_output");
9
- const job = jobs.get(input.task_id);
10
- if (!job) throw new Error(`Unknown background subagent task ${input.task_id}.`);
11
- if (input.block === true && isActiveJob(job.status)) await waitForJob(job, input.timeout, abortSignal);
12
- const output = {
13
- result: job.result,
14
- status: job.status,
15
- subagent: job.subagent,
16
- task_id: job.id
17
- };
18
- if (!(isActiveJob(job.status) || !job.settled)) {
19
- if (await cleanupJob(job).then(() => true, () => false)) jobs.delete(job.id);
20
- }
21
- return output;
22
- },
23
- inputSchema: jsonSchema({
24
- additionalProperties: false,
25
- properties: {
26
- block: { type: "boolean" },
27
- task_id: { type: "string" },
28
- timeout: {
29
- minimum: 0,
30
- type: "number"
31
- }
32
- },
33
- required: ["task_id"],
34
- type: "object"
35
- })
36
- });
37
- }
38
- async function waitForJob(job, timeout, abortSignal) {
39
- if (abortSignal?.aborted) return;
40
- const timeoutMs = Math.min(timeout ?? 6e4, 6e5);
41
- let timeoutId;
42
- let abortListener;
43
- const abortPromise = abortSignal ? new Promise((resolve) => {
44
- abortListener = resolve;
45
- abortSignal.addEventListener("abort", abortListener, { once: true });
46
- }) : void 0;
47
- try {
48
- await Promise.race([
49
- job.promise,
50
- ...abortPromise ? [abortPromise] : [],
51
- new Promise((resolve) => {
52
- timeoutId = setTimeout(resolve, timeoutMs);
53
- })
54
- ]);
55
- } finally {
56
- if (timeoutId) clearTimeout(timeoutId);
57
- if (abortListener) abortSignal?.removeEventListener("abort", abortListener);
58
- }
59
- }
60
- //#endregion
61
- export { createBackgroundOutputTool };
62
-
63
- //# sourceMappingURL=subagent-job-output.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-job-output.js","names":[],"sources":["../src/subagent-job-output.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport {\n assertBackgroundTaskId,\n cleanupJob,\n isActiveJob,\n} from \"./subagent-jobs\";\nimport type { BackgroundOutputInput, SubagentJob } from \"./subagent-types\";\n\nexport function createBackgroundOutputTool(jobs: Map<string, SubagentJob>) {\n return tool<BackgroundOutputInput, unknown, Record<string, unknown>>({\n description: \"Retrieve compact output for a background subagent job.\",\n execute: async (input: BackgroundOutputInput, { abortSignal }) => {\n assertBackgroundTaskId(input.task_id, \"background_output\");\n const job = jobs.get(input.task_id);\n if (!job) {\n throw new Error(`Unknown background subagent task ${input.task_id}.`);\n }\n\n if (input.block === true && isActiveJob(job.status)) {\n await waitForJob(job, input.timeout, abortSignal);\n }\n\n const output = {\n result: job.result,\n status: job.status,\n subagent: job.subagent,\n task_id: job.id,\n };\n if (!(isActiveJob(job.status) || !job.settled)) {\n const cleaned = await cleanupJob(job).then(\n () => true,\n () => false\n );\n if (cleaned) {\n jobs.delete(job.id);\n }\n }\n\n return output;\n },\n inputSchema: jsonSchema<BackgroundOutputInput>({\n additionalProperties: false,\n properties: {\n block: { type: \"boolean\" },\n task_id: { type: \"string\" },\n timeout: { minimum: 0, type: \"number\" },\n },\n required: [\"task_id\"],\n type: \"object\",\n }),\n });\n}\n\nasync function waitForJob(\n job: SubagentJob,\n timeout: number | undefined,\n abortSignal: AbortSignal | undefined\n) {\n if (abortSignal?.aborted) {\n return;\n }\n\n const timeoutMs = Math.min(timeout ?? 60_000, 600_000);\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let abortListener: (() => void) | undefined;\n const abortPromise = abortSignal\n ? new Promise<void>((resolve) => {\n abortListener = resolve;\n abortSignal.addEventListener(\"abort\", abortListener, { once: true });\n })\n : undefined;\n try {\n await Promise.race([\n job.promise,\n ...(abortPromise ? [abortPromise] : []),\n new Promise<void>((resolve) => {\n timeoutId = setTimeout(resolve, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n if (abortListener) {\n abortSignal?.removeEventListener(\"abort\", abortListener);\n }\n }\n}\n"],"mappings":";;;AAQA,SAAgB,2BAA2B,MAAgC;CACzE,OAAO,KAA8D;EACnE,aAAa;EACb,SAAS,OAAO,OAA8B,EAAE,kBAAkB;GAChE,uBAAuB,MAAM,SAAS,mBAAmB;GACzD,MAAM,MAAM,KAAK,IAAI,MAAM,OAAO;GAClC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,oCAAoC,MAAM,QAAQ,EAAE;GAGtE,IAAI,MAAM,UAAU,QAAQ,YAAY,IAAI,MAAM,GAChD,MAAM,WAAW,KAAK,MAAM,SAAS,WAAW;GAGlD,MAAM,SAAS;IACb,QAAQ,IAAI;IACZ,QAAQ,IAAI;IACZ,UAAU,IAAI;IACd,SAAS,IAAI;GACf;GACA,IAAI,EAAE,YAAY,IAAI,MAAM,KAAK,CAAC,IAAI;QAKhC,MAJkB,WAAW,GAAG,EAAE,WAC9B,YACA,KACR,GAEE,KAAK,OAAO,IAAI,EAAE;GAAA;GAItB,OAAO;EACT;EACA,aAAa,WAAkC;GAC7C,sBAAsB;GACtB,YAAY;IACV,OAAO,EAAE,MAAM,UAAU;IACzB,SAAS,EAAE,MAAM,SAAS;IAC1B,SAAS;KAAE,SAAS;KAAG,MAAM;IAAS;GACxC;GACA,UAAU,CAAC,SAAS;GACpB,MAAM;EACR,CAAC;CACH,CAAC;AACH;AAEA,eAAe,WACb,KACA,SACA,aACA;CACA,IAAI,aAAa,SACf;CAGF,MAAM,YAAY,KAAK,IAAI,WAAW,KAAQ,GAAO;CACrD,IAAI;CACJ,IAAI;CACJ,MAAM,eAAe,cACjB,IAAI,SAAe,YAAY;EAC7B,gBAAgB;EAChB,YAAY,iBAAiB,SAAS,eAAe,EAAE,MAAM,KAAK,CAAC;CACrE,CAAC,IACD,KAAA;CACJ,IAAI;EACF,MAAM,QAAQ,KAAK;GACjB,IAAI;GACJ,GAAI,eAAe,CAAC,YAAY,IAAI,CAAC;GACrC,IAAI,SAAe,YAAY;IAC7B,YAAY,WAAW,SAAS,SAAS;GAC3C,CAAC;EACH,CAAC;CACH,UAAU;EACR,IAAI,WACF,aAAa,SAAS;EAExB,IAAI,eACF,aAAa,oBAAoB,SAAS,aAAa;CAE3D;AACF"}