@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.
- package/README.md +169 -28
- package/dist/agent-child-runs.js +16 -0
- package/dist/agent-child-runs.js.map +1 -0
- package/dist/agent-host-capabilities.js +9 -0
- package/dist/agent-host-capabilities.js.map +1 -0
- package/dist/agent-host-session-store.js +12 -0
- package/dist/agent-host-session-store.js.map +1 -0
- package/dist/agent-loop.js +58 -28
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent-namespace.js +8 -1
- package/dist/agent-namespace.js.map +1 -1
- package/dist/agent-options.d.ts +35 -0
- package/dist/agent-options.js +16 -0
- package/dist/agent-options.js.map +1 -0
- package/dist/agent-resume.js +143 -0
- package/dist/agent-resume.js.map +1 -0
- package/dist/agent-session-entry.d.ts +13 -0
- package/dist/agent-validation.js +2 -2
- package/dist/agent-validation.js.map +1 -1
- package/dist/agent.d.ts +5 -41
- package/dist/agent.js +81 -49
- package/dist/agent.js.map +1 -1
- package/dist/execution/host.js +14 -0
- package/dist/execution/host.js.map +1 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +3 -0
- package/dist/execution/memory-notifications.js +54 -0
- package/dist/execution/memory-notifications.js.map +1 -0
- package/dist/execution/memory-state.js +34 -0
- package/dist/execution/memory-state.js.map +1 -0
- package/dist/execution/memory-store.js +203 -0
- package/dist/execution/memory-store.js.map +1 -0
- package/dist/execution/memory.d.ts +7 -0
- package/dist/execution/memory.js +28 -0
- package/dist/execution/memory.js.map +1 -0
- package/dist/execution/run.js +55 -0
- package/dist/execution/run.js.map +1 -0
- package/dist/execution/types.d.ts +155 -0
- package/dist/index.d.ts +8 -5
- package/dist/llm-tool-execution.d.ts +35 -0
- package/dist/llm-tool-execution.js +126 -0
- package/dist/llm-tool-execution.js.map +1 -0
- package/dist/llm.d.ts +11 -15
- package/dist/llm.js +5 -3
- package/dist/llm.js.map +1 -1
- package/dist/plugins.d.ts +20 -0
- package/dist/plugins.js +14 -0
- package/dist/plugins.js.map +1 -0
- package/dist/session/events.d.ts +3 -0
- package/dist/session/runtime-input.js +5 -23
- package/dist/session/runtime-input.js.map +1 -1
- package/dist/session/session-errors.js +1 -6
- package/dist/session/session-errors.js.map +1 -1
- package/dist/session/session-events.js +59 -0
- package/dist/session/session-events.js.map +1 -0
- package/dist/session/session-execution.js +88 -0
- package/dist/session/session-execution.js.map +1 -0
- package/dist/session/session-notification.js +58 -0
- package/dist/session/session-notification.js.map +1 -0
- package/dist/session/session-runtime-drain.js +2 -2
- package/dist/session/session-runtime-drain.js.map +1 -1
- package/dist/session/session-turn-processor.js +135 -0
- package/dist/session/session-turn-processor.js.map +1 -0
- package/dist/session/session.js +73 -101
- package/dist/session/session.js.map +1 -1
- package/dist/session/snapshot.js.map +1 -1
- package/dist/subagent-background-child-run-state.js +51 -0
- package/dist/subagent-background-child-run-state.js.map +1 -0
- package/dist/subagent-background-child-run.js +103 -0
- package/dist/subagent-background-child-run.js.map +1 -0
- package/dist/subagent-background-in-process.js +98 -0
- package/dist/subagent-background-in-process.js.map +1 -0
- package/dist/subagent-background-notification-inbox.js +106 -0
- package/dist/subagent-background-notification-inbox.js.map +1 -0
- package/dist/subagent-background-notify.js +136 -0
- package/dist/subagent-background-notify.js.map +1 -0
- package/dist/subagent-background-resume-group.js +99 -0
- package/dist/subagent-background-resume-group.js.map +1 -0
- package/dist/subagent-background-runner.js +115 -0
- package/dist/subagent-background-runner.js.map +1 -0
- package/dist/subagent-background-schedule.js +43 -0
- package/dist/subagent-background-schedule.js.map +1 -0
- package/dist/subagent-child-run.js +68 -0
- package/dist/subagent-child-run.js.map +1 -0
- package/dist/subagent-job-cancel.js +60 -4
- package/dist/subagent-job-cancel.js.map +1 -1
- package/dist/subagent-job-observer.js +19 -0
- package/dist/subagent-job-observer.js.map +1 -0
- package/dist/subagent-job-output.js +28 -4
- package/dist/subagent-job-output.js.map +1 -1
- package/dist/subagent-job-state.js +66 -0
- package/dist/subagent-job-state.js.map +1 -0
- package/dist/subagent-jobs.js +78 -133
- package/dist/subagent-jobs.js.map +1 -1
- package/dist/subagent-run.js +4 -4
- package/dist/subagent-run.js.map +1 -1
- package/dist/subagents.js +68 -35
- package/dist/subagents.js.map +1 -1
- package/package.json +11 -1
- package/dist/hooks.d.ts +0 -32
- /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({
|
|
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
|
-
|
|
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 {
|
|
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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"}
|
package/dist/session/session.js
CHANGED
|
@@ -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 {
|
|
5
|
-
import {
|
|
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 {
|
|
7
|
+
import { queueSessionNotification, startSessionQueueDrain } from "./session-notification.js";
|
|
8
8
|
import { SessionState } from "./session-state.js";
|
|
9
|
-
import {
|
|
9
|
+
import { processQueuedInput } from "./session-turn-processor.js";
|
|
10
10
|
//#region src/session/session.ts
|
|
11
11
|
var AgentSession = class {
|
|
12
|
-
#
|
|
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,
|
|
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
|
-
|
|
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()
|
|
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
|
|
64
|
-
this
|
|
65
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|