@minpeter/pss-runtime 0.1.0-next.1 → 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 (101) hide show
  1. package/README.md +169 -28
  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 +58 -28
  9. package/dist/agent-loop.js.map +1 -1
  10. package/dist/agent-namespace.js +8 -1
  11. package/dist/agent-namespace.js.map +1 -1
  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 +2 -2
  19. package/dist/agent-validation.js.map +1 -1
  20. package/dist/agent.d.ts +5 -41
  21. package/dist/agent.js +81 -49
  22. package/dist/agent.js.map +1 -1
  23. package/dist/execution/host.js +14 -0
  24. package/dist/execution/host.js.map +1 -0
  25. package/dist/execution/index.d.ts +4 -0
  26. package/dist/execution/index.js +3 -0
  27. package/dist/execution/memory-notifications.js +54 -0
  28. package/dist/execution/memory-notifications.js.map +1 -0
  29. package/dist/execution/memory-state.js +34 -0
  30. package/dist/execution/memory-state.js.map +1 -0
  31. package/dist/execution/memory-store.js +203 -0
  32. package/dist/execution/memory-store.js.map +1 -0
  33. package/dist/execution/memory.d.ts +7 -0
  34. package/dist/execution/memory.js +28 -0
  35. package/dist/execution/memory.js.map +1 -0
  36. package/dist/execution/run.js +55 -0
  37. package/dist/execution/run.js.map +1 -0
  38. package/dist/execution/types.d.ts +155 -0
  39. package/dist/index.d.ts +8 -5
  40. package/dist/llm-tool-execution.d.ts +35 -0
  41. package/dist/llm-tool-execution.js +126 -0
  42. package/dist/llm-tool-execution.js.map +1 -0
  43. package/dist/llm.d.ts +11 -15
  44. package/dist/llm.js +5 -3
  45. package/dist/llm.js.map +1 -1
  46. package/dist/plugins.d.ts +20 -0
  47. package/dist/plugins.js +14 -0
  48. package/dist/plugins.js.map +1 -0
  49. package/dist/session/events.d.ts +3 -0
  50. package/dist/session/runtime-input.js +5 -23
  51. package/dist/session/runtime-input.js.map +1 -1
  52. package/dist/session/session-errors.js +1 -6
  53. package/dist/session/session-errors.js.map +1 -1
  54. package/dist/session/session-events.js +59 -0
  55. package/dist/session/session-events.js.map +1 -0
  56. package/dist/session/session-execution.js +88 -0
  57. package/dist/session/session-execution.js.map +1 -0
  58. package/dist/session/session-notification.js +58 -0
  59. package/dist/session/session-notification.js.map +1 -0
  60. package/dist/session/session-runtime-drain.js +2 -2
  61. package/dist/session/session-runtime-drain.js.map +1 -1
  62. package/dist/session/session-turn-processor.js +135 -0
  63. package/dist/session/session-turn-processor.js.map +1 -0
  64. package/dist/session/session.js +73 -101
  65. package/dist/session/session.js.map +1 -1
  66. package/dist/session/snapshot.js.map +1 -1
  67. package/dist/subagent-background-child-run-state.js +51 -0
  68. package/dist/subagent-background-child-run-state.js.map +1 -0
  69. package/dist/subagent-background-child-run.js +103 -0
  70. package/dist/subagent-background-child-run.js.map +1 -0
  71. package/dist/subagent-background-in-process.js +98 -0
  72. package/dist/subagent-background-in-process.js.map +1 -0
  73. package/dist/subagent-background-notification-inbox.js +106 -0
  74. package/dist/subagent-background-notification-inbox.js.map +1 -0
  75. package/dist/subagent-background-notify.js +136 -0
  76. package/dist/subagent-background-notify.js.map +1 -0
  77. package/dist/subagent-background-resume-group.js +99 -0
  78. package/dist/subagent-background-resume-group.js.map +1 -0
  79. package/dist/subagent-background-runner.js +115 -0
  80. package/dist/subagent-background-runner.js.map +1 -0
  81. package/dist/subagent-background-schedule.js +43 -0
  82. package/dist/subagent-background-schedule.js.map +1 -0
  83. package/dist/subagent-child-run.js +68 -0
  84. package/dist/subagent-child-run.js.map +1 -0
  85. package/dist/subagent-job-cancel.js +60 -4
  86. package/dist/subagent-job-cancel.js.map +1 -1
  87. package/dist/subagent-job-observer.js +19 -0
  88. package/dist/subagent-job-observer.js.map +1 -0
  89. package/dist/subagent-job-output.js +28 -4
  90. package/dist/subagent-job-output.js.map +1 -1
  91. package/dist/subagent-job-state.js +66 -0
  92. package/dist/subagent-job-state.js.map +1 -0
  93. package/dist/subagent-jobs.js +78 -133
  94. package/dist/subagent-jobs.js.map +1 -1
  95. package/dist/subagent-run.js +4 -4
  96. package/dist/subagent-run.js.map +1 -1
  97. package/dist/subagents.js +68 -35
  98. package/dist/subagents.js.map +1 -1
  99. package/package.json +11 -1
  100. package/dist/hooks.d.ts +0 -32
  101. /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
@@ -1,11 +1,11 @@
1
1
  import { shiftRuntimeInput } from "./runtime-input.js";
2
2
  //#region src/session/session-runtime-drain.ts
3
- async function drainRuntimeInput({ placement, run, runtimeInput, state }) {
3
+ async function drainRuntimeInput({ emit, placement, runtimeInput, state }) {
4
4
  let added = false;
5
5
  let next = shiftRuntimeInput(runtimeInput, placement);
6
6
  while (next) {
7
7
  added = true;
8
- run.emit({
8
+ await emit({
9
9
  type: "runtime-input",
10
10
  input: next.input,
11
11
  placement
@@ -1 +1 @@
1
- {"version":3,"file":"session-runtime-drain.js","names":[],"sources":["../../src/session/session-runtime-drain.ts"],"sourcesContent":["import type { BufferedAgentRun } from \"./run\";\nimport {\n type RuntimeInputPlacement,\n type RuntimeInputState,\n shiftRuntimeInput,\n} from \"./runtime-input\";\nimport type { SessionState } from \"./session-state\";\n\nexport async function drainRuntimeInput({\n placement,\n run,\n runtimeInput,\n state,\n}: {\n readonly placement: RuntimeInputPlacement;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n readonly state: SessionState;\n}): Promise<boolean> {\n let added = false;\n let next = shiftRuntimeInput(runtimeInput, placement);\n while (next) {\n added = true;\n run.emit({ type: \"runtime-input\", input: next.input, placement });\n state.appendUserInput(next.input);\n await state.commit();\n next = shiftRuntimeInput(runtimeInput, placement);\n }\n\n return added;\n}\n"],"mappings":";;AAQA,eAAsB,kBAAkB,EACtC,WACA,KACA,cACA,SAMmB;CACnB,IAAI,QAAQ;CACZ,IAAI,OAAO,kBAAkB,cAAc,SAAS;CACpD,OAAO,MAAM;EACX,QAAQ;EACR,IAAI,KAAK;GAAE,MAAM;GAAiB,OAAO,KAAK;GAAO;EAAU,CAAC;EAChE,MAAM,gBAAgB,KAAK,KAAK;EAChC,MAAM,MAAM,OAAO;EACnB,OAAO,kBAAkB,cAAc,SAAS;CAClD;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"session-runtime-drain.js","names":[],"sources":["../../src/session/session-runtime-drain.ts"],"sourcesContent":["import type { RuntimeInput } from \"./events\";\nimport {\n type RuntimeInputPlacement,\n type RuntimeInputState,\n shiftRuntimeInput,\n} from \"./runtime-input\";\nimport type { SessionState } from \"./session-state\";\n\nexport async function drainRuntimeInput({\n emit,\n placement,\n runtimeInput,\n state,\n}: {\n readonly emit: (event: RuntimeInput) => Promise<void>;\n readonly placement: RuntimeInputPlacement;\n readonly runtimeInput: RuntimeInputState;\n readonly state: SessionState;\n}): Promise<boolean> {\n let added = false;\n let next = shiftRuntimeInput(runtimeInput, placement);\n while (next) {\n added = true;\n await emit({ type: \"runtime-input\", input: next.input, placement });\n state.appendUserInput(next.input);\n await state.commit();\n next = shiftRuntimeInput(runtimeInput, placement);\n }\n\n return added;\n}\n"],"mappings":";;AAQA,eAAsB,kBAAkB,EACtC,MACA,WACA,cACA,SAMmB;CACnB,IAAI,QAAQ;CACZ,IAAI,OAAO,kBAAkB,cAAc,SAAS;CACpD,OAAO,MAAM;EACX,QAAQ;EACR,MAAM,KAAK;GAAE,MAAM;GAAiB,OAAO,KAAK;GAAO;EAAU,CAAC;EAClE,MAAM,gBAAgB,KAAK,KAAK;EAChC,MAAM,MAAM,OAAO;EACnB,OAAO,kBAAkB,cAAc,SAAS;CAClD;CAEA,OAAO;AACT"}
@@ -0,0 +1,135 @@
1
+ import { ToolExecutionNeedsRecoveryError } from "../llm-tool-execution.js";
2
+ import { closeRuntimeInput, withRuntimeInputWindow } from "./runtime-input.js";
3
+ import { errorMessage } from "./session-errors.js";
4
+ import { runAgentLoop } from "../agent-loop.js";
5
+ import { startSessionExecutionRun } from "./session-execution.js";
6
+ import { drainRuntimeInput } from "./session-runtime-drain.js";
7
+ import { emitTurnErrorAfterRecovery } from "./session-turn-error.js";
8
+ //#region src/session/session-turn-processor.ts
9
+ async function processQueuedInput({ activate, deactivateRun, events, execution, item, llm, release, sessionKey, state }) {
10
+ const activeAbort = new AbortController();
11
+ const { initialEvents, input, preUserRuntimeInputs, run, runtimeInput } = item;
12
+ const turnId = crypto.randomUUID();
13
+ activate({
14
+ abort: activeAbort,
15
+ run,
16
+ runtimeInput,
17
+ turnId
18
+ });
19
+ const historySnapshot = state.modelSnapshot();
20
+ let executionRun;
21
+ try {
22
+ executionRun = await startSessionExecutionRun({
23
+ executionHost: execution.executionHost,
24
+ sessionKey,
25
+ state,
26
+ turnId
27
+ });
28
+ for (const event of initialEvents) await events.emitRunEvent(run, event);
29
+ await appendRuntimeInputsToHistory(state, preUserRuntimeInputs);
30
+ if (input) {
31
+ state.appendUserInput(input);
32
+ await state.commit();
33
+ }
34
+ await withRuntimeInputWindow(runtimeInput, "turn-start", async () => {
35
+ await events.emitRunBoundaryEvent(run, { type: "turn-start" });
36
+ });
37
+ await emitPreUserRuntimeInputs(events, run, preUserRuntimeInputs);
38
+ await drainRuntimeInput({
39
+ emit: (event) => events.emitRunEvent(run, event),
40
+ placement: "turn-start",
41
+ runtimeInput,
42
+ state
43
+ });
44
+ const result = await runAgentLoop({
45
+ emit: async (event) => emitTurnEvent({
46
+ event,
47
+ events,
48
+ run,
49
+ runtimeInput,
50
+ state
51
+ }),
52
+ history: state.history,
53
+ llm,
54
+ captureObserverEvents: (callback) => events.captureObserverEvents(run, callback),
55
+ signal: activeAbort.signal,
56
+ toolExecution: executionRun?.toolExecution
57
+ });
58
+ await state.commit();
59
+ await executionRun?.complete(executionStatusForResult(result));
60
+ await closeSuccessfulTurn({
61
+ deactivateRun,
62
+ events,
63
+ result,
64
+ run,
65
+ runtimeInput
66
+ });
67
+ } catch (error) {
68
+ const turnError = error instanceof Error ? error : new Error(String(error));
69
+ await executionRun?.complete(executionStatusForError(turnError));
70
+ await emitTurnErrorAfterRecovery({
71
+ error: turnError,
72
+ historySnapshot,
73
+ run,
74
+ runtimeInput,
75
+ state
76
+ });
77
+ } finally {
78
+ closeRuntimeInput(runtimeInput);
79
+ release();
80
+ run.close(void 0, runtimeInput.closedReason);
81
+ }
82
+ }
83
+ function executionStatusForResult(result) {
84
+ return result === "aborted" ? "cancelled" : "completed";
85
+ }
86
+ function executionStatusForError(error) {
87
+ return error instanceof ToolExecutionNeedsRecoveryError ? "needs-recovery" : "error";
88
+ }
89
+ async function appendRuntimeInputsToHistory(state, runtimeInputs) {
90
+ for (const runtimeInput of runtimeInputs) {
91
+ state.appendUserInput(runtimeInput.input);
92
+ await state.commit();
93
+ }
94
+ }
95
+ async function closeSuccessfulTurn({ deactivateRun, events, result, run, runtimeInput }) {
96
+ const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
97
+ closeRuntimeInput(runtimeInput, terminalEvent);
98
+ deactivateRun();
99
+ try {
100
+ await events.emitRunEvent(run, { type: terminalEvent });
101
+ } catch (terminalError) {
102
+ run.emit({
103
+ type: "turn-error",
104
+ message: errorMessage(terminalError)
105
+ });
106
+ closeRuntimeInput(runtimeInput, "turn-error");
107
+ }
108
+ }
109
+ async function emitPreUserRuntimeInputs(events, run, runtimeInputs) {
110
+ for (const runtimeInput of runtimeInputs) await events.emitRunEvent(run, {
111
+ input: runtimeInput.input,
112
+ placement: runtimeInput.placement,
113
+ type: "runtime-input"
114
+ });
115
+ }
116
+ async function emitTurnEvent({ event, events, run, runtimeInput, state }) {
117
+ if (event.type !== "step-start" && event.type !== "step-end") {
118
+ await events.emitRunEvent(run, event);
119
+ return;
120
+ }
121
+ await withRuntimeInputWindow(runtimeInput, event.type, async () => {
122
+ await events.emitRunBoundaryEvent(run, event);
123
+ });
124
+ const runtimeInputAdded = await drainRuntimeInput({
125
+ emit: (runtimeInputEvent) => events.emitRunEvent(run, runtimeInputEvent),
126
+ placement: event.type,
127
+ runtimeInput,
128
+ state
129
+ });
130
+ return event.type === "step-end" ? { runtimeInputAdded } : void 0;
131
+ }
132
+ //#endregion
133
+ export { processQueuedInput };
134
+
135
+ //# sourceMappingURL=session-turn-processor.js.map
@@ -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 QueuedRuntimeInput,\n type RuntimeInputState,\n withRuntimeInputWindow,\n} from \"./runtime-input\";\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\";\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 await appendRuntimeInputsToHistory(state, preUserRuntimeInputs);\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 emitPreUserRuntimeInputs(events, run, preUserRuntimeInputs);\n await drainRuntimeInput({\n emit: (event) => events.emitRunEvent(run, event),\n placement: \"turn-start\",\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 appendRuntimeInputsToHistory(\n state: SessionState,\n runtimeInputs: readonly QueuedRuntimeInput[]\n): Promise<void> {\n for (const runtimeInput of runtimeInputs) {\n state.appendUserInput(runtimeInput.input);\n await state.commit();\n }\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 emitPreUserRuntimeInputs(\n events: SessionEventDispatcher,\n run: BufferedAgentRun,\n runtimeInputs: readonly QueuedRuntimeInput[]\n): Promise<void> {\n for (const runtimeInput of runtimeInputs) {\n await events.emitRunEvent(run, {\n input: runtimeInput.input,\n placement: runtimeInput.placement,\n type: \"runtime-input\",\n });\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 emit: (runtimeInputEvent) => events.emitRunEvent(run, runtimeInputEvent),\n placement: event.type,\n runtimeInput,\n state,\n });\n return event.type === \"step-end\" ? { runtimeInputAdded } : undefined;\n}\n"],"mappings":"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"}
@@ -1,30 +1,39 @@
1
- import { runAgentLoop } from "../agent-loop.js";
2
- import { normalizeAgentInput } from "./input-normalization.js";
3
1
  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";
2
+ import { normalizeAgentInput } from "./input-normalization.js";
3
+ import { addSteeringInput, createRuntimeInputState, queueRuntimeInput } from "./runtime-input.js";
4
+ import { sessionKilledError, sessionTerminalError } from "./session-errors.js";
5
+ import { SessionEventDispatcher } from "./session-events.js";
6
6
  import { closeKilledRuntimeInputs } from "./session-kill.js";
7
- import { drainRuntimeInput } from "./session-runtime-drain.js";
7
+ import { queueSessionNotification, startSessionQueueDrain } from "./session-notification.js";
8
8
  import { SessionState } from "./session-state.js";
9
- import { emitTurnErrorAfterRecovery } from "./session-turn-error.js";
9
+ import { processQueuedInput } from "./session-turn-processor.js";
10
10
  //#region src/session/session.ts
11
11
  var AgentSession = class {
12
- #hooks;
12
+ #events;
13
+ #execution;
13
14
  #inputQueue = [];
14
15
  #llm;
15
16
  #pendingRuntimeInputs = [];
17
+ #sessionKey;
16
18
  #state;
17
19
  #activeAbort;
18
20
  #activeRun;
19
21
  #activeRuntimeInput;
22
+ #activeTurnId;
20
23
  #deletePromise;
21
24
  #killed = false;
22
25
  #running = false;
23
26
  #runToCloseOnKill;
24
- constructor(llm, persistence, hooks) {
25
- this.#hooks = hooks;
27
+ constructor(llm, persistence, plugins = [], execution = {}) {
26
28
  this.#llm = llm;
29
+ this.#execution = execution;
30
+ this.#sessionKey = persistence.key;
27
31
  this.#state = new SessionState(persistence);
32
+ this.#events = new SessionEventDispatcher({
33
+ history: () => this.#state.modelSnapshot(),
34
+ plugins,
35
+ signal: () => this.#activeAbort?.signal
36
+ });
28
37
  }
29
38
  async send(input) {
30
39
  if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
@@ -33,21 +42,29 @@ var AgentSession = class {
33
42
  const runtimeInput = createRuntimeInputState(this.#pendingRuntimeInputs.splice(0));
34
43
  const acceptedInput = normalizeAgentInput(input);
35
44
  const run = new BufferedAgentRun();
36
- run.emit(acceptedInput);
45
+ await this.#events.emitRunEvent(run, acceptedInput);
37
46
  this.#inputQueue.push({
47
+ initialEvents: [],
38
48
  input: structuredClone(acceptedInput),
49
+ preUserRuntimeInputs: [],
39
50
  run,
40
51
  runtimeInput
41
52
  });
42
- this.#drainInputQueue().catch((error) => {
43
- run.emit({
44
- type: "turn-error",
45
- message: errorMessage(error)
46
- });
47
- run.close();
48
- });
53
+ startSessionQueueDrain(run, () => this.#drainInputQueue());
49
54
  return run;
50
55
  }
56
+ async notify(input, options = {}) {
57
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
58
+ await this.#state.ensureLoaded();
59
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
60
+ return queueSessionNotification(input, options, {
61
+ activeRun: this.#activeRun,
62
+ activeRuntimeInput: this.#activeRuntimeInput,
63
+ drain: () => this.#drainInputQueue(),
64
+ inputQueue: this.#inputQueue,
65
+ pendingRuntimeInputs: this.#pendingRuntimeInputs
66
+ });
67
+ }
51
68
  async steer(input) {
52
69
  if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
53
70
  const runtimeInput = this.#activeRuntimeInput;
@@ -59,11 +76,17 @@ var AgentSession = class {
59
76
  interrupt() {
60
77
  this.#activeAbort?.abort();
61
78
  }
79
+ currentTurnId() {
80
+ return this.#activeTurnId;
81
+ }
62
82
  delete() {
63
- this.#deletePromise ??= this.#state.delete().then(() => this.kill(), (error) => {
64
- this.#deletePromise = void 0;
65
- throw error;
66
- });
83
+ if (!this.#deletePromise) {
84
+ this.kill();
85
+ this.#deletePromise = this.#state.delete().catch((error) => {
86
+ this.#deletePromise = void 0;
87
+ throw error;
88
+ });
89
+ }
67
90
  return this.#deletePromise;
68
91
  }
69
92
  enqueueRuntimeInput(input, placement = "turn-start") {
@@ -77,7 +100,7 @@ var AgentSession = class {
77
100
  });
78
101
  return;
79
102
  }
80
- runtimeInput.queue.push({
103
+ queueRuntimeInput(runtimeInput, {
81
104
  input,
82
105
  placement
83
106
  });
@@ -89,12 +112,12 @@ var AgentSession = class {
89
112
  });
90
113
  }
91
114
  emitObserverEvent(event) {
92
- this.#activeRun?.emit(event);
115
+ return this.#events.emitObserverEvent(this.#activeRun, event);
93
116
  }
94
117
  #enqueuePendingRuntimeInput(input) {
95
118
  const queuedTurn = this.#inputQueue[0];
96
119
  if (input.placement === "turn-start" && queuedTurn) {
97
- queuedTurn.runtimeInput.queue.push(input);
120
+ queueRuntimeInput(queuedTurn.runtimeInput, input);
98
121
  return;
99
122
  }
100
123
  this.#pendingRuntimeInputs.push(input);
@@ -118,88 +141,37 @@ var AgentSession = class {
118
141
  try {
119
142
  while (!this.#killed && this.#inputQueue.length > 0) {
120
143
  const item = this.#inputQueue.shift();
121
- if (item) await this.#processQueuedInput(item);
144
+ if (item) await processQueuedInput({
145
+ activate: ({ abort, run, runtimeInput, turnId }) => {
146
+ this.#activeAbort = abort;
147
+ this.#activeRun = run;
148
+ this.#activeRuntimeInput = runtimeInput;
149
+ this.#activeTurnId = turnId;
150
+ this.#runToCloseOnKill = run;
151
+ },
152
+ deactivateRun: () => {
153
+ this.#activeRun = void 0;
154
+ this.#activeRuntimeInput = void 0;
155
+ },
156
+ events: this.#events,
157
+ execution: this.#execution,
158
+ item,
159
+ llm: this.#llm,
160
+ release: () => {
161
+ this.#activeAbort = void 0;
162
+ this.#activeRun = void 0;
163
+ this.#activeRuntimeInput = void 0;
164
+ this.#activeTurnId = void 0;
165
+ this.#runToCloseOnKill = void 0;
166
+ },
167
+ sessionKey: this.#sessionKey,
168
+ state: this.#state
169
+ });
122
170
  }
123
171
  } finally {
124
172
  this.#running = false;
125
173
  }
126
174
  }
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
175
  };
204
176
  //#endregion
205
177
  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 { 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 acceptedInput = normalizeAgentInput(input);\n const run = new BufferedAgentRun();\n await this.#events.emitRunEvent(run, acceptedInput);\n this.#inputQueue.push({\n initialEvents: [],\n input: structuredClone(acceptedInput),\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"}
@@ -0,0 +1,51 @@
1
+ //#region src/subagent-background-child-run-state.ts
2
+ function durableBackgroundChildRunState({ delegateToolCallId, description, groupId, parentSessionKey, prompt, subagent }) {
3
+ return {
4
+ ...delegateToolCallId ? { delegateToolCallId } : {},
5
+ ...description ? { description } : {},
6
+ ...groupId ? { groupId } : {},
7
+ kind: "background-subagent",
8
+ ...parentSessionKey ? { parentSessionKey } : {},
9
+ prompt: structuredClone(prompt),
10
+ subagent: subagent ?? "subagent"
11
+ };
12
+ }
13
+ function readDurableBackgroundChildRunState(checkpoint) {
14
+ const state = checkpoint?.runtimeState;
15
+ if (!isRecord(state) || state.kind !== "background-subagent") return null;
16
+ if (!isAgentInput(state.prompt) || typeof state.subagent !== "string") return null;
17
+ return {
18
+ ...typeof state.delegateToolCallId === "string" ? { delegateToolCallId: state.delegateToolCallId } : {},
19
+ ...typeof state.description === "string" ? { description: state.description } : {},
20
+ ...typeof state.groupId === "string" ? { groupId: state.groupId } : {},
21
+ kind: "background-subagent",
22
+ ...typeof state.parentSessionKey === "string" ? { parentSessionKey: state.parentSessionKey } : {},
23
+ prompt: state.prompt,
24
+ subagent: state.subagent
25
+ };
26
+ }
27
+ function isAgentInput(value) {
28
+ return typeof value === "string" || isStringArray(value) || isUserInput(value) || isMessageContent(value);
29
+ }
30
+ function isUserInput(value) {
31
+ if (!isRecord(value)) return false;
32
+ if (value.type === "user-text") return typeof value.text === "string" || isStringArray(value.text);
33
+ return value.type === "user-message" && isMessageContent(value.content);
34
+ }
35
+ function isMessageContent(value) {
36
+ return Array.isArray(value) && value.every(isMessageContentPart);
37
+ }
38
+ function isMessageContentPart(value) {
39
+ if (!isRecord(value) || typeof value.type !== "string") return false;
40
+ return value.type === "text" || value.type === "image" || value.type === "file";
41
+ }
42
+ function isRecord(value) {
43
+ return typeof value === "object" && value !== null;
44
+ }
45
+ function isStringArray(value) {
46
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
47
+ }
48
+ //#endregion
49
+ export { durableBackgroundChildRunState, readDurableBackgroundChildRunState };
50
+
51
+ //# sourceMappingURL=subagent-background-child-run-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-background-child-run-state.js","names":[],"sources":["../src/subagent-background-child-run-state.ts"],"sourcesContent":["import type { RunCheckpoint } from \"./execution/types\";\nimport type { AgentInput } from \"./session/input\";\n\nexport interface DurableBackgroundChildRunState {\n readonly delegateToolCallId?: string;\n readonly description?: string;\n readonly groupId?: string;\n readonly kind: \"background-subagent\";\n readonly parentSessionKey?: string;\n readonly prompt: AgentInput;\n readonly subagent: string;\n}\n\nexport function durableBackgroundChildRunState({\n delegateToolCallId,\n description,\n groupId,\n parentSessionKey,\n prompt,\n subagent,\n}: {\n readonly delegateToolCallId?: string;\n readonly description?: string;\n readonly groupId?: string;\n readonly parentSessionKey?: string;\n readonly prompt: AgentInput;\n readonly subagent?: string;\n}): DurableBackgroundChildRunState {\n return {\n ...(delegateToolCallId ? { delegateToolCallId } : {}),\n ...(description ? { description } : {}),\n ...(groupId ? { groupId } : {}),\n kind: \"background-subagent\",\n ...(parentSessionKey ? { parentSessionKey } : {}),\n prompt: structuredClone(prompt),\n subagent: subagent ?? \"subagent\",\n };\n}\n\nexport function readDurableBackgroundChildRunState(\n checkpoint: RunCheckpoint | null\n): DurableBackgroundChildRunState | null {\n const state = checkpoint?.runtimeState;\n if (!isRecord(state) || state.kind !== \"background-subagent\") {\n return null;\n }\n\n if (!isAgentInput(state.prompt) || typeof state.subagent !== \"string\") {\n return null;\n }\n\n return {\n ...(typeof state.delegateToolCallId === \"string\"\n ? { delegateToolCallId: state.delegateToolCallId }\n : {}),\n ...(typeof state.description === \"string\"\n ? { description: state.description }\n : {}),\n ...(typeof state.groupId === \"string\" ? { groupId: state.groupId } : {}),\n kind: \"background-subagent\",\n ...(typeof state.parentSessionKey === \"string\"\n ? { parentSessionKey: state.parentSessionKey }\n : {}),\n prompt: state.prompt,\n subagent: state.subagent,\n };\n}\n\nfunction isAgentInput(value: unknown): value is AgentInput {\n return (\n typeof value === \"string\" ||\n isStringArray(value) ||\n isUserInput(value) ||\n isMessageContent(value)\n );\n}\n\nfunction isUserInput(value: unknown): boolean {\n if (!isRecord(value)) {\n return false;\n }\n\n if (value.type === \"user-text\") {\n return typeof value.text === \"string\" || isStringArray(value.text);\n }\n\n return value.type === \"user-message\" && isMessageContent(value.content);\n}\n\nfunction isMessageContent(value: unknown): boolean {\n return Array.isArray(value) && value.every(isMessageContentPart);\n}\n\nfunction isMessageContentPart(value: unknown): boolean {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n\n return (\n value.type === \"text\" || value.type === \"image\" || value.type === \"file\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n return (\n Array.isArray(value) && value.every((item) => typeof item === \"string\")\n );\n}\n"],"mappings":";AAaA,SAAgB,+BAA+B,EAC7C,oBACA,aACA,SACA,kBACA,QACA,YAQiC;CACjC,OAAO;EACL,GAAI,qBAAqB,EAAE,mBAAmB,IAAI,CAAC;EACnD,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;EACrC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC7B,MAAM;EACN,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EAC/C,QAAQ,gBAAgB,MAAM;EAC9B,UAAU,YAAY;CACxB;AACF;AAEA,SAAgB,mCACd,YACuC;CACvC,MAAM,QAAQ,YAAY;CAC1B,IAAI,CAAC,SAAS,KAAK,KAAK,MAAM,SAAS,uBACrC,OAAO;CAGT,IAAI,CAAC,aAAa,MAAM,MAAM,KAAK,OAAO,MAAM,aAAa,UAC3D,OAAO;CAGT,OAAO;EACL,GAAI,OAAO,MAAM,uBAAuB,WACpC,EAAE,oBAAoB,MAAM,mBAAmB,IAC/C,CAAC;EACL,GAAI,OAAO,MAAM,gBAAgB,WAC7B,EAAE,aAAa,MAAM,YAAY,IACjC,CAAC;EACL,GAAI,OAAO,MAAM,YAAY,WAAW,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;EACtE,MAAM;EACN,GAAI,OAAO,MAAM,qBAAqB,WAClC,EAAE,kBAAkB,MAAM,iBAAiB,IAC3C,CAAC;EACL,QAAQ,MAAM;EACd,UAAU,MAAM;CAClB;AACF;AAEA,SAAS,aAAa,OAAqC;CACzD,OACE,OAAO,UAAU,YACjB,cAAc,KAAK,KACnB,YAAY,KAAK,KACjB,iBAAiB,KAAK;AAE1B;AAEA,SAAS,YAAY,OAAyB;CAC5C,IAAI,CAAC,SAAS,KAAK,GACjB,OAAO;CAGT,IAAI,MAAM,SAAS,aACjB,OAAO,OAAO,MAAM,SAAS,YAAY,cAAc,MAAM,IAAI;CAGnE,OAAO,MAAM,SAAS,kBAAkB,iBAAiB,MAAM,OAAO;AACxE;AAEA,SAAS,iBAAiB,OAAyB;CACjD,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,oBAAoB;AACjE;AAEA,SAAS,qBAAqB,OAAyB;CACrD,IAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,UAC5C,OAAO;CAGT,OACE,MAAM,SAAS,UAAU,MAAM,SAAS,WAAW,MAAM,SAAS;AAEtE;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,cAAc,OAA4C;CACjE,OACE,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,SAAS,OAAO,SAAS,QAAQ;AAE1E"}
@@ -0,0 +1,103 @@
1
+ import { durableBackgroundChildRunState } from "./subagent-background-child-run-state.js";
2
+ //#region src/subagent-background-child-run.ts
3
+ function createBackgroundTaskId() {
4
+ return `bg_${crypto.randomUUID().replaceAll("-", "")}`;
5
+ }
6
+ async function createDurableBackgroundTaskId({ delegateToolCallId, prompt, sessionKey }) {
7
+ const digestInput = backgroundSubagentDedupeKey({
8
+ delegateToolCallId,
9
+ prompt,
10
+ sessionKey
11
+ });
12
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(digestInput));
13
+ return `bg_${[...new Uint8Array(digest.slice(0, 16))].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
14
+ }
15
+ async function getBackgroundChildRun({ delegateToolCallId, executionHost, prompt, sessionKey }) {
16
+ if (!executionHost) return;
17
+ const dedupeKey = backgroundSubagentDedupeKey({
18
+ delegateToolCallId,
19
+ prompt,
20
+ sessionKey
21
+ });
22
+ return await executionHost.store.runs.getByDedupeKey(dedupeKey) ?? void 0;
23
+ }
24
+ async function getOrCreateBackgroundChildRun(input) {
25
+ if (!input.executionHost) return;
26
+ const id = input.publicTaskId ?? createBackgroundTaskId();
27
+ const dedupeKey = backgroundSubagentDedupeKey(input);
28
+ return await input.executionHost.store.transaction(async (tx) => {
29
+ const existing = await tx.runs.getByDedupeKey(dedupeKey);
30
+ if (existing) return existing;
31
+ const parentRunId = input.parentRunId ?? input.parentSessionKey ?? input.sessionKey;
32
+ const runtimeState = durableBackgroundChildRunState(input);
33
+ const run = {
34
+ checkpointVersion: 0,
35
+ dedupeKey,
36
+ kind: "background-subagent",
37
+ ...input.ownerNamespace ? { ownerNamespace: input.ownerNamespace } : {},
38
+ parentRunId,
39
+ publicTaskId: id,
40
+ rootRunId: parentRunId,
41
+ runId: `background:${id}`,
42
+ sessionKey: `${input.sessionKey}:task:${id}`,
43
+ status: "queued"
44
+ };
45
+ await tx.runs.create(run);
46
+ await tx.checkpoints.append({
47
+ checkpointId: crypto.randomUUID(),
48
+ phase: "before-child-run",
49
+ runId: run.runId,
50
+ runtimeState,
51
+ sessionSnapshot: {},
52
+ version: 1
53
+ }, { expectedVersion: 0 });
54
+ await tx.checkpoints.append({
55
+ checkpointId: crypto.randomUUID(),
56
+ childRunId: run.runId,
57
+ phase: "child-linked",
58
+ runId: run.runId,
59
+ runtimeState,
60
+ sessionSnapshot: {},
61
+ version: 2
62
+ }, { expectedVersion: 1 });
63
+ return await tx.runs.get(run.runId) ?? run;
64
+ });
65
+ }
66
+ async function updateBackgroundRunStatus(job, status) {
67
+ if (!(job.executionHost && job.childRunId)) return true;
68
+ return await job.executionHost.store.transaction(async (tx) => {
69
+ const run = await tx.runs.get(job.childRunId ?? "");
70
+ if (!run || isTerminalBackgroundRunStatus(run.status)) return false;
71
+ if (job.childRunLeaseId && run.lease?.leaseId !== job.childRunLeaseId) return false;
72
+ await tx.runs.update({
73
+ ...run,
74
+ output: job.result ?? run.output,
75
+ status
76
+ });
77
+ return true;
78
+ });
79
+ }
80
+ async function cancelBackgroundChildRun({ executionHost, runId }) {
81
+ return await executionHost.store.transaction(async (tx) => {
82
+ const run = await tx.runs.get(runId);
83
+ if (!run || isTerminalBackgroundRunStatus(run.status)) return run;
84
+ return await tx.runs.update({
85
+ ...run,
86
+ status: "cancelled"
87
+ });
88
+ });
89
+ }
90
+ function childRunStatus(result) {
91
+ if (result === "aborted") return "cancelled";
92
+ return result;
93
+ }
94
+ function backgroundSubagentDedupeKey({ delegateToolCallId, prompt, sessionKey }) {
95
+ return `background-subagent:${sessionKey}:${delegateToolCallId ?? "unknown"}:${JSON.stringify(prompt)}`;
96
+ }
97
+ function isTerminalBackgroundRunStatus(status) {
98
+ return status === "cancelled" || status === "completed" || status === "error";
99
+ }
100
+ //#endregion
101
+ export { cancelBackgroundChildRun, childRunStatus, createBackgroundTaskId, createDurableBackgroundTaskId, getBackgroundChildRun, getOrCreateBackgroundChildRun, updateBackgroundRunStatus };
102
+
103
+ //# sourceMappingURL=subagent-background-child-run.js.map