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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +223 -191
  2. package/dist/agent-child-runs.js +16 -0
  3. package/dist/agent-child-runs.js.map +1 -0
  4. package/dist/agent-host-capabilities.js +9 -0
  5. package/dist/agent-host-capabilities.js.map +1 -0
  6. package/dist/agent-host-session-store.js +12 -0
  7. package/dist/agent-host-session-store.js.map +1 -0
  8. package/dist/agent-loop.js +59 -35
  9. package/dist/agent-loop.js.map +1 -1
  10. package/dist/agent-namespace.js +24 -0
  11. package/dist/agent-namespace.js.map +1 -0
  12. package/dist/agent-options.d.ts +35 -0
  13. package/dist/agent-options.js +16 -0
  14. package/dist/agent-options.js.map +1 -0
  15. package/dist/agent-resume.js +143 -0
  16. package/dist/agent-resume.js.map +1 -0
  17. package/dist/agent-session-entry.d.ts +13 -0
  18. package/dist/agent-validation.js +35 -0
  19. package/dist/agent-validation.js.map +1 -0
  20. package/dist/agent.d.ts +8 -33
  21. package/dist/agent.js +131 -55
  22. package/dist/agent.js.map +1 -1
  23. package/dist/child-session-cleanups.js +61 -0
  24. package/dist/child-session-cleanups.js.map +1 -0
  25. package/dist/execution/host.js +14 -0
  26. package/dist/execution/host.js.map +1 -0
  27. package/dist/execution/index.d.ts +4 -0
  28. package/dist/execution/index.js +3 -0
  29. package/dist/execution/memory-notifications.js +54 -0
  30. package/dist/execution/memory-notifications.js.map +1 -0
  31. package/dist/execution/memory-state.js +34 -0
  32. package/dist/execution/memory-state.js.map +1 -0
  33. package/dist/execution/memory-store.js +203 -0
  34. package/dist/execution/memory-store.js.map +1 -0
  35. package/dist/execution/memory.d.ts +7 -0
  36. package/dist/execution/memory.js +28 -0
  37. package/dist/execution/memory.js.map +1 -0
  38. package/dist/execution/run.js +55 -0
  39. package/dist/execution/run.js.map +1 -0
  40. package/dist/execution/types.d.ts +155 -0
  41. package/dist/index.d.ts +9 -10
  42. package/dist/index.js +1 -6
  43. package/dist/llm-tool-execution.d.ts +35 -0
  44. package/dist/llm-tool-execution.js +126 -0
  45. package/dist/llm-tool-execution.js.map +1 -0
  46. package/dist/llm.d.ts +11 -15
  47. package/dist/llm.js +5 -9
  48. package/dist/llm.js.map +1 -1
  49. package/dist/plugins.d.ts +20 -0
  50. package/dist/plugins.js +14 -0
  51. package/dist/plugins.js.map +1 -0
  52. package/dist/session/events.d.ts +26 -20
  53. package/dist/session/input-normalization.js +66 -0
  54. package/dist/session/input-normalization.js.map +1 -0
  55. package/dist/session/input.d.ts +0 -4
  56. package/dist/session/mapping.js +1 -2
  57. package/dist/session/mapping.js.map +1 -1
  58. package/dist/session/run.js +1 -0
  59. package/dist/session/run.js.map +1 -1
  60. package/dist/session/runtime-input.js +20 -58
  61. package/dist/session/runtime-input.js.map +1 -1
  62. package/dist/session/session-errors.js +18 -0
  63. package/dist/session/session-errors.js.map +1 -0
  64. package/dist/session/session-events.js +59 -0
  65. package/dist/session/session-events.js.map +1 -0
  66. package/dist/session/session-execution.js +88 -0
  67. package/dist/session/session-execution.js.map +1 -0
  68. package/dist/session/session-kill.js +23 -0
  69. package/dist/session/session-kill.js.map +1 -0
  70. package/dist/session/session-notification.js +58 -0
  71. package/dist/session/session-notification.js.map +1 -0
  72. package/dist/session/session-runtime-drain.js +22 -0
  73. package/dist/session/session-runtime-drain.js.map +1 -0
  74. package/dist/session/session-state.js +102 -0
  75. package/dist/session/session-state.js.map +1 -0
  76. package/dist/session/session-turn-error.js +35 -0
  77. package/dist/session/session-turn-error.js.map +1 -0
  78. package/dist/session/session-turn-processor.js +135 -0
  79. package/dist/session/session-turn-processor.js.map +1 -0
  80. package/dist/session/session.js +125 -335
  81. package/dist/session/session.js.map +1 -1
  82. package/dist/session/snapshot.js +5 -31
  83. package/dist/session/snapshot.js.map +1 -1
  84. package/dist/session/store/file.d.ts +1 -0
  85. package/dist/session/store/file.js +14 -0
  86. package/dist/session/store/file.js.map +1 -1
  87. package/dist/session/store/memory.d.ts +1 -0
  88. package/dist/session/store/memory.js +5 -0
  89. package/dist/session/store/memory.js.map +1 -1
  90. package/dist/session/store/types.d.ts +1 -0
  91. package/dist/subagent-background-child-run-state.js +51 -0
  92. package/dist/subagent-background-child-run-state.js.map +1 -0
  93. package/dist/subagent-background-child-run.js +103 -0
  94. package/dist/subagent-background-child-run.js.map +1 -0
  95. package/dist/subagent-background-in-process.js +98 -0
  96. package/dist/subagent-background-in-process.js.map +1 -0
  97. package/dist/subagent-background-notification-inbox.js +106 -0
  98. package/dist/subagent-background-notification-inbox.js.map +1 -0
  99. package/dist/subagent-background-notify.js +136 -0
  100. package/dist/subagent-background-notify.js.map +1 -0
  101. package/dist/subagent-background-resume-group.js +99 -0
  102. package/dist/subagent-background-resume-group.js.map +1 -0
  103. package/dist/subagent-background-runner.js +115 -0
  104. package/dist/subagent-background-runner.js.map +1 -0
  105. package/dist/subagent-background-schedule.js +43 -0
  106. package/dist/subagent-background-schedule.js.map +1 -0
  107. package/dist/subagent-child-run.js +68 -0
  108. package/dist/subagent-child-run.js.map +1 -0
  109. package/dist/subagent-job-cancel.js +84 -0
  110. package/dist/subagent-job-cancel.js.map +1 -0
  111. package/dist/subagent-job-observer.js +19 -0
  112. package/dist/subagent-job-observer.js.map +1 -0
  113. package/dist/subagent-job-output.js +87 -0
  114. package/dist/subagent-job-output.js.map +1 -0
  115. package/dist/subagent-job-state.js +66 -0
  116. package/dist/subagent-job-state.js.map +1 -0
  117. package/dist/subagent-jobs.js +96 -0
  118. package/dist/subagent-jobs.js.map +1 -0
  119. package/dist/subagent-prompt-schema.js +114 -0
  120. package/dist/subagent-prompt-schema.js.map +1 -0
  121. package/dist/subagent-run.js +111 -0
  122. package/dist/subagent-run.js.map +1 -0
  123. package/dist/subagents.js +125 -0
  124. package/dist/subagents.js.map +1 -0
  125. package/package.json +11 -6
  126. package/dist/plugins/compaction.d.ts +0 -15
  127. package/dist/plugins/compaction.js +0 -98
  128. package/dist/plugins/compaction.js.map +0 -1
  129. package/dist/plugins/index.d.ts +0 -5
  130. package/dist/plugins/index.js +0 -5
  131. package/dist/plugins/memory.d.ts +0 -11
  132. package/dist/plugins/memory.js +0 -146
  133. package/dist/plugins/memory.js.map +0 -1
  134. package/dist/plugins/runner.d.ts +0 -1
  135. package/dist/plugins/runner.js +0 -83
  136. package/dist/plugins/runner.js.map +0 -1
  137. package/dist/plugins/scope.js +0 -13
  138. package/dist/plugins/scope.js.map +0 -1
  139. package/dist/plugins/sessions.d.ts +0 -12
  140. package/dist/plugins/sessions.js +0 -34
  141. package/dist/plugins/sessions.js.map +0 -1
  142. package/dist/plugins/tool-hook-handlers.js +0 -77
  143. package/dist/plugins/tool-hook-handlers.js.map +0 -1
  144. package/dist/plugins/tool-hook-results.js +0 -64
  145. package/dist/plugins/tool-hook-results.js.map +0 -1
  146. package/dist/plugins/tool-hooks.js +0 -111
  147. package/dist/plugins/tool-hooks.js.map +0 -1
  148. package/dist/plugins/types.d.ts +0 -105
  149. package/dist/plugins/types.js +0 -20
  150. package/dist/plugins/types.js.map +0 -1
  151. package/dist/session/lifecycle.d.ts +0 -12
  152. package/dist/session/lifecycle.js +0 -126
  153. package/dist/session/lifecycle.js.map +0 -1
  154. package/dist/session/overlay-anchor.js +0 -151
  155. package/dist/session/overlay-anchor.js.map +0 -1
  156. package/dist/session/overlay.js +0 -141
  157. package/dist/session/overlay.js.map +0 -1
  158. package/dist/session/snapshot.d.ts +0 -1
  159. /package/dist/{agent-loop.d.ts → session/history.d.ts} +0 -0
  160. /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
  161. /package/dist/{plugins/scope.d.ts → session/session-state.d.ts} +0 -0
@@ -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,135 +1,139 @@
1
- import { runWithAgentPluginScope } from "../plugins/scope.js";
2
- import { runAgentLoop } from "../agent-loop.js";
3
- import { ModelMessageHistory } from "./history.js";
4
- import { createRuntimeInputStepLifecycle, runPluginAfterTurnHandlers, runPluginBeforeTurnHandlers } from "./lifecycle.js";
5
- import { addRuntimeInput, closeRuntimeInput, createRuntimeInputState, normalizeAgentInput, shiftRuntimeInput } from "./runtime-input.js";
6
- import { SessionOverlayState } from "./overlay.js";
7
1
  import { BufferedAgentRun } from "./run.js";
8
- import { decodeStoredSessionSnapshot, encodeSessionSnapshot } from "./snapshot.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
+ import { closeKilledRuntimeInputs } from "./session-kill.js";
7
+ import { queueSessionNotification, startSessionQueueDrain } from "./session-notification.js";
8
+ import { SessionState } from "./session-state.js";
9
+ import { processQueuedInput } from "./session-turn-processor.js";
9
10
  //#region src/session/session.ts
10
11
  var AgentSession = class {
12
+ #events;
13
+ #execution;
11
14
  #inputQueue = [];
12
- #internalLlm;
13
15
  #llm;
14
- #onPluginError;
15
- #persistence;
16
- #plugins;
16
+ #pendingRuntimeInputs = [];
17
+ #sessionKey;
18
+ #state;
17
19
  #activeAbort;
18
20
  #activeRun;
19
21
  #activeRuntimeInput;
20
- #history = new ModelMessageHistory();
22
+ #activeTurnId;
23
+ #deletePromise;
21
24
  #killed = false;
22
- #loadPromise;
23
- #loaded = false;
24
- #pluginState = {};
25
- #compactions = [];
26
- #overlays = new SessionOverlayState();
27
25
  #running = false;
28
- #storeVersion;
29
- constructor(llm, persistence, plugins, internalLlm = llm, onPluginError) {
30
- this.#internalLlm = internalLlm;
31
- this.#onPluginError = onPluginError;
32
- this.#persistence = persistence;
33
- this.#plugins = plugins;
26
+ #runToCloseOnKill;
27
+ constructor(llm, persistence, plugins = [], execution = {}) {
34
28
  this.#llm = llm;
29
+ this.#execution = execution;
30
+ this.#sessionKey = persistence.key;
31
+ this.#state = new SessionState(persistence);
32
+ this.#events = new SessionEventDispatcher({
33
+ history: () => this.#state.modelSnapshot(),
34
+ plugins,
35
+ signal: () => this.#activeAbort?.signal
36
+ });
35
37
  }
36
38
  async send(input) {
37
- if (this.#killed) throw sessionKilledError();
38
- await this.#ensureLoaded();
39
- if (this.#killed) throw sessionKilledError();
40
- const runtimeInput = createRuntimeInputState();
39
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
40
+ await this.#state.ensureLoaded();
41
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
42
+ const runtimeInput = createRuntimeInputState(this.#pendingRuntimeInputs.splice(0));
41
43
  const acceptedInput = normalizeAgentInput(input);
42
44
  const run = new BufferedAgentRun();
43
- run.emit(acceptedInput);
45
+ await this.#events.emitRunEvent(run, acceptedInput);
44
46
  this.#inputQueue.push({
47
+ initialEvents: [],
45
48
  input: structuredClone(acceptedInput),
49
+ preUserRuntimeInputs: [],
46
50
  run,
47
51
  runtimeInput
48
52
  });
49
- this.#drainInputQueue().catch((error) => {
50
- run.emit({
51
- type: "turn-error",
52
- message: errorMessage(error)
53
- });
54
- run.close();
55
- });
53
+ startSessionQueueDrain(run, () => this.#drainInputQueue());
56
54
  return run;
57
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
+ }
58
68
  async steer(input) {
59
- if (this.#killed) throw sessionKilledError();
69
+ if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
60
70
  const runtimeInput = this.#activeRuntimeInput;
61
71
  const run = this.#activeRun;
62
72
  if (!(runtimeInput && run)) return this.send(input);
63
- await addRuntimeInput(runtimeInput, input);
64
- return run;
65
- }
66
- async overlay(input) {
67
- if (this.#killed) throw sessionKilledError();
68
- await this.#ensureLoaded();
69
- if (this.#killed) throw sessionKilledError();
70
- const activeRun = this.#activeRun;
71
- if (activeRun) {
72
- const placement = this.#activeRuntimeInput?.steerPlacement ?? this.#activeRuntimeInput?.placement ?? "step-end";
73
- const entry = this.#overlays.appendActiveOverlay(input, placement);
74
- if (!entry) throw new Error("Active overlay frame is unavailable.");
75
- activeRun.emit({
76
- input: entry.summary,
77
- placement: entry.placement,
78
- type: "overlay-accepted"
79
- });
80
- return activeRun;
81
- }
82
- const entry = this.#overlays.appendPendingOverlay(input);
83
- const run = new BufferedAgentRun();
84
- run.emit({
85
- input: entry.summary,
86
- placement: entry.placement,
87
- type: "overlay-accepted"
88
- });
89
- run.close();
73
+ await addSteeringInput(runtimeInput, input);
90
74
  return run;
91
75
  }
92
76
  interrupt() {
93
77
  this.#activeAbort?.abort();
94
78
  }
95
- kill() {
96
- if (this.#killed) return;
97
- this.#killed = true;
98
- this.#expireActiveOverlays("kill");
99
- this.#activeAbort?.abort();
100
- closeRuntimeInput(this.#activeRuntimeInput, sessionKilledError().message);
101
- while (this.#inputQueue.length > 0) {
102
- const item = this.#inputQueue.shift();
103
- closeRuntimeInput(item?.runtimeInput, sessionKilledError().message);
104
- item?.run.emit({
105
- type: "turn-error",
106
- message: sessionKilledError().message
79
+ currentTurnId() {
80
+ return this.#activeTurnId;
81
+ }
82
+ delete() {
83
+ if (!this.#deletePromise) {
84
+ this.kill();
85
+ this.#deletePromise = this.#state.delete().catch((error) => {
86
+ this.#deletePromise = void 0;
87
+ throw error;
107
88
  });
108
- item?.run.close(void 0, sessionKilledError().message);
109
89
  }
90
+ return this.#deletePromise;
110
91
  }
111
- async #ensureLoaded() {
112
- if (this.#loaded) return;
113
- this.#loadPromise ??= this.#loadSessionState();
114
- try {
115
- await this.#loadPromise;
116
- } catch (error) {
117
- this.#loadPromise = void 0;
118
- throw error;
92
+ enqueueRuntimeInput(input, placement = "turn-start") {
93
+ if (this.#killed) return;
94
+ const runtimeInput = this.#activeRuntimeInput;
95
+ if (runtimeInput && !runtimeInput.closedReason) {
96
+ if (placement === "turn-start" && runtimeInput.placement !== placement) {
97
+ this.#enqueuePendingRuntimeInput({
98
+ input,
99
+ placement
100
+ });
101
+ return;
102
+ }
103
+ queueRuntimeInput(runtimeInput, {
104
+ input,
105
+ placement
106
+ });
107
+ return;
119
108
  }
109
+ this.#enqueuePendingRuntimeInput({
110
+ input,
111
+ placement
112
+ });
120
113
  }
121
- async #loadSessionState() {
122
- if (this.#loaded) return;
123
- await this.#replaceWithStoredSession();
124
- this.#loaded = true;
114
+ emitObserverEvent(event) {
115
+ return this.#events.emitObserverEvent(this.#activeRun, event);
125
116
  }
126
- async #replaceWithStoredSession() {
127
- const stored = await this.#persistence.store.load(this.#persistence.key);
128
- this.#storeVersion = stored?.version;
129
- const snapshot = decodeStoredSessionSnapshot(stored);
130
- this.#history = new ModelMessageHistory(snapshot.history);
131
- this.#pluginState = structuredClone(snapshot.pluginState);
132
- this.#compactions = structuredClone(snapshot.compactions);
117
+ #enqueuePendingRuntimeInput(input) {
118
+ const queuedTurn = this.#inputQueue[0];
119
+ if (input.placement === "turn-start" && queuedTurn) {
120
+ queueRuntimeInput(queuedTurn.runtimeInput, input);
121
+ return;
122
+ }
123
+ this.#pendingRuntimeInputs.push(input);
124
+ }
125
+ kill() {
126
+ if (this.#killed) return;
127
+ this.#killed = true;
128
+ const killedError = sessionKilledError();
129
+ this.#pendingRuntimeInputs.length = 0;
130
+ this.#activeAbort?.abort();
131
+ closeKilledRuntimeInputs({
132
+ activeRuntimeInput: this.#activeRuntimeInput,
133
+ inputQueue: this.#inputQueue,
134
+ message: killedError.message,
135
+ runToClose: this.#runToCloseOnKill ?? this.#activeRun
136
+ });
133
137
  }
134
138
  async #drainInputQueue() {
135
139
  if (this.#running) return;
@@ -137,250 +141,36 @@ var AgentSession = class {
137
141
  try {
138
142
  while (!this.#killed && this.#inputQueue.length > 0) {
139
143
  const item = this.#inputQueue.shift();
140
- if (item) await this.#processQueuedInput(item);
141
- }
142
- } finally {
143
- this.#running = false;
144
- }
145
- }
146
- async #processQueuedInput({ input, run, runtimeInput }) {
147
- const activeAbort = new AbortController();
148
- this.#activeAbort = activeAbort;
149
- const historySnapshot = this.#history.modelSnapshot();
150
- this.#overlays.startTurn(input, historySnapshot);
151
- this.#activeRun = run;
152
- this.#activeRuntimeInput = runtimeInput;
153
- try {
154
- await this.#withSteeringPlacement(runtimeInput, "turn-start", async () => {
155
- await runPluginBeforeTurnHandlers(this.#pluginLifecycle(), {
156
- input,
157
- runtimeInput,
158
- signal: activeAbort.signal
159
- });
160
- });
161
- await this.#withRuntimeInputWindow(runtimeInput, "turn-start", async () => {
162
- await run.emitBoundary({ type: "turn-start" });
163
- });
164
- this.#history.appendUserInput(input);
165
- await this.#commitHistory();
166
- await this.#drainRuntimeInput(run, runtimeInput, "turn-start");
167
- const result = await runAgentLoop({
168
- emit: async (event) => {
169
- if (event.type === "step-start" || event.type === "step-end") {
170
- await this.#withRuntimeInputWindow(runtimeInput, event.type, async () => {
171
- await run.emitBoundary(event);
172
- });
173
- const overlayInputAdded = event.type === "step-end" && this.#overlays.consumeStepEndOverlayInputAdded();
174
- const runtimeInputAdded = await this.#drainRuntimeInput(run, runtimeInput, event.type);
175
- if (event.type === "step-end") return {
176
- overlayInputAdded,
177
- runtimeInputAdded
178
- };
179
- return;
180
- }
181
- run.emit(event);
182
- },
183
- history: this.#history,
184
- stepLifecycle: createRuntimeInputStepLifecycle({
185
- lifecycle: this.#pluginLifecycle(),
186
- runtimeInput,
187
- withSteeringPlacement: (placement, callback) => this.#withSteeringPlacement(runtimeInput, placement, callback)
188
- }),
189
- llm: (context) => this.#invokeLlm(context),
190
- signal: activeAbort.signal
191
- });
192
- await this.#commitHistory();
193
- const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
194
- closeRuntimeInput(runtimeInput, terminalEvent);
195
- this.#expireActiveOverlays(terminalEvent);
196
- this.#activeRuntimeInput = void 0;
197
- this.#activeRun = void 0;
198
- if (await runPluginAfterTurnHandlers(this.#pluginLifecycle(), {
199
- input,
200
- result,
201
- signal: activeAbort.signal
202
- })) await this.#commitHistory();
203
- run.emit({ type: terminalEvent });
204
- } catch (error) {
205
- if (error instanceof SessionCommitConflictError) {
206
- run.emit({
207
- type: "turn-error",
208
- message: error.message
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
209
169
  });
210
- closeRuntimeInput(runtimeInput, "a session commit conflict");
211
- this.#expireActiveOverlays("turn-error");
212
- this.#activeAbort = void 0;
213
- return;
214
170
  }
215
- this.#history.rollback(historySnapshot);
216
- try {
217
- await this.#commitHistory();
218
- } catch (rollbackError) {
219
- run.emit({
220
- type: "turn-error",
221
- message: `${errorMessage(error)}; history rollback persistence failed: ${errorMessage(rollbackError)}`
222
- });
223
- closeRuntimeInput(runtimeInput, "turn-error");
224
- this.#expireActiveOverlays("turn-error");
225
- this.#activeAbort = void 0;
226
- return;
227
- }
228
- run.emit({
229
- type: "turn-error",
230
- message: errorMessage(error)
231
- });
232
- closeRuntimeInput(runtimeInput, "turn-error");
233
- this.#expireActiveOverlays("turn-error");
234
- } finally {
235
- closeRuntimeInput(runtimeInput);
236
- this.#activeAbort = void 0;
237
- this.#activeRun = void 0;
238
- this.#activeRuntimeInput = void 0;
239
- this.#overlays.resetActiveTurn();
240
- run.close(void 0, runtimeInput.closedReason);
241
- }
242
- }
243
- async #commitHistory() {
244
- const result = await this.#persistence.store.commit(this.#persistence.key, { state: encodeSessionSnapshot({
245
- compactions: this.#compactions,
246
- history: this.#history.modelSnapshot(),
247
- pluginState: this.#pluginState
248
- }) }, { expectedVersion: this.#storeVersion ?? null });
249
- if (!result.ok) {
250
- await this.#replaceWithStoredSession();
251
- throw new SessionCommitConflictError(this.#persistence.key);
252
- }
253
- this.#storeVersion = result.version;
254
- }
255
- #createPluginScope(signal) {
256
- return {
257
- eventHandlers: this.#plugins?.eventHandlers,
258
- getCompactions: () => structuredClone(this.#compactions),
259
- getPluginState: (pluginName) => this.#pluginState[pluginName],
260
- history: () => this.#history.modelSnapshot(),
261
- sessionKey: this.#persistence.key,
262
- overlay: (input) => this.overlay(input),
263
- setCompactions: (compactions) => {
264
- this.#compactions = structuredClone([...compactions]);
265
- },
266
- setPluginState: (pluginName, state) => {
267
- this.#pluginState = {
268
- ...this.#pluginState,
269
- [pluginName]: structuredClone(state)
270
- };
271
- },
272
- signal,
273
- steer: (input) => this.steer(input),
274
- summarize: (messages) => this.#summarizeForPlugins(messages, signal)
275
- };
276
- }
277
- #pluginLifecycle() {
278
- return {
279
- createScope: (signal) => this.#createPluginScope(signal),
280
- history: () => this.#history.modelSnapshot(),
281
- onPluginError: this.#onPluginError,
282
- plugins: this.#plugins,
283
- sessionKey: this.#persistence.key,
284
- overlaySession: (input) => this.overlay(input),
285
- steerCurrentRun: async (runtimeInput, input) => {
286
- await addRuntimeInput(runtimeInput, input);
287
- if (!this.#activeRun) throw new Error("Agent plugin steering requires an active run.");
288
- return this.#activeRun;
289
- },
290
- steerSession: (input) => this.steer(input)
291
- };
292
- }
293
- #invokeLlm({ history, signal }) {
294
- const activeSignal = signal ?? new AbortController().signal;
295
- const invoke = async () => {
296
- let transformedHistory = history;
297
- for (const transform of this.#plugins?.contextTransforms ?? []) transformedHistory = await transform({
298
- history: transformedHistory,
299
- sessionKey: this.#persistence.key,
300
- signal: activeSignal
301
- });
302
- const modelHistory = this.#overlays.compose(transformedHistory, history);
303
- this.#overlays.markInferenceStarted();
304
- return this.#llm({
305
- history: modelHistory,
306
- signal: activeSignal
307
- });
308
- };
309
- return runWithAgentPluginScope(this.#createPluginScope(activeSignal), invoke);
310
- }
311
- async #summarizeForPlugins(messages, signal) {
312
- return outputToText(await this.#internalLlm({
313
- history: [{
314
- content: "Summarize these earlier session messages for future model context.",
315
- role: "system"
316
- }, ...messages],
317
- signal
318
- })) || `Summarized ${messages.length} messages.`;
319
- }
320
- async #withRuntimeInputWindow(runtimeInput, placement, callback) {
321
- const previousSteerPlacement = runtimeInput.steerPlacement;
322
- runtimeInput.placement = placement;
323
- runtimeInput.steerPlacement = placement;
324
- try {
325
- return await callback();
326
171
  } finally {
327
- runtimeInput.placement = void 0;
328
- runtimeInput.steerPlacement = previousSteerPlacement;
329
- }
330
- }
331
- async #withSteeringPlacement(runtimeInput, placement, callback) {
332
- const previousSteerPlacement = runtimeInput.steerPlacement;
333
- runtimeInput.steerPlacement = placement;
334
- try {
335
- return await callback();
336
- } finally {
337
- runtimeInput.steerPlacement = previousSteerPlacement;
338
- }
339
- }
340
- async #drainRuntimeInput(run, runtimeInput, placement) {
341
- let added = false;
342
- let next = shiftRuntimeInput(runtimeInput, placement);
343
- while (next) {
344
- added = true;
345
- run.emit({
346
- type: "runtime-input",
347
- input: next.input,
348
- placement
349
- });
350
- this.#history.appendUserInput(next.input);
351
- await this.#commitHistory();
352
- next = shiftRuntimeInput(runtimeInput, placement);
353
- }
354
- return added;
355
- }
356
- #expireActiveOverlays(reason) {
357
- const event = this.#overlays.expireActiveFrame(reason);
358
- if (!event) return;
359
- this.#activeRun?.emit(event);
360
- }
361
- };
362
- function errorMessage(error) {
363
- if (error instanceof Error) return error.message;
364
- return String(error);
365
- }
366
- function outputToText(output) {
367
- const parts = [];
368
- for (const message of output) {
369
- if (message.role !== "assistant") continue;
370
- if (typeof message.content === "string") {
371
- parts.push(message.content);
372
- continue;
172
+ this.#running = false;
373
173
  }
374
- for (const part of message.content) if (part.type === "text") parts.push(part.text);
375
- }
376
- return parts.join("\n").trim();
377
- }
378
- function sessionKilledError() {
379
- return /* @__PURE__ */ new Error("Session killed");
380
- }
381
- var SessionCommitConflictError = class extends Error {
382
- constructor(key) {
383
- super(`Session ${JSON.stringify(key)} commit conflict`);
384
174
  }
385
175
  };
386
176
  //#endregion