@minpeter/pss-runtime 0.1.0-next.0 → 0.1.0-next.1
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 +85 -194
- package/dist/agent-loop.js +8 -14
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent-namespace.js +17 -0
- package/dist/agent-namespace.js.map +1 -0
- package/dist/agent-validation.js +35 -0
- package/dist/agent-validation.js.map +1 -0
- package/dist/agent.d.ts +21 -10
- package/dist/agent.js +81 -37
- package/dist/agent.js.map +1 -1
- package/dist/child-session-cleanups.js +61 -0
- package/dist/child-session-cleanups.js.map +1 -0
- package/dist/hooks.d.ts +32 -0
- package/dist/index.d.ts +4 -8
- package/dist/index.js +1 -6
- package/dist/llm.js +1 -7
- package/dist/llm.js.map +1 -1
- package/dist/session/events.d.ts +23 -20
- package/dist/session/input-normalization.js +66 -0
- package/dist/session/input-normalization.js.map +1 -0
- package/dist/session/input.d.ts +0 -4
- package/dist/session/mapping.js +1 -2
- package/dist/session/mapping.js.map +1 -1
- package/dist/session/run.js +1 -0
- package/dist/session/run.js.map +1 -1
- package/dist/session/runtime-input.js +38 -58
- package/dist/session/runtime-input.js.map +1 -1
- package/dist/session/session-errors.js +23 -0
- package/dist/session/session-errors.js.map +1 -0
- package/dist/session/session-kill.js +23 -0
- package/dist/session/session-kill.js.map +1 -0
- package/dist/session/session-runtime-drain.js +22 -0
- package/dist/session/session-runtime-drain.js.map +1 -0
- package/dist/session/session-state.js +102 -0
- package/dist/session/session-state.js.map +1 -0
- package/dist/session/session-turn-error.js +35 -0
- package/dist/session/session-turn-error.js.map +1 -0
- package/dist/session/session.js +103 -285
- package/dist/session/session.js.map +1 -1
- package/dist/session/snapshot.js +5 -31
- package/dist/session/snapshot.js.map +1 -1
- package/dist/session/store/file.d.ts +1 -0
- package/dist/session/store/file.js +14 -0
- package/dist/session/store/file.js.map +1 -1
- package/dist/session/store/memory.d.ts +1 -0
- package/dist/session/store/memory.js +5 -0
- package/dist/session/store/memory.js.map +1 -1
- package/dist/session/store/types.d.ts +1 -0
- package/dist/subagent-job-cancel.js +28 -0
- package/dist/subagent-job-cancel.js.map +1 -0
- package/dist/subagent-job-output.js +63 -0
- package/dist/subagent-job-output.js.map +1 -0
- package/dist/subagent-jobs.js +151 -0
- package/dist/subagent-jobs.js.map +1 -0
- package/dist/subagent-prompt-schema.js +114 -0
- package/dist/subagent-prompt-schema.js.map +1 -0
- package/dist/subagent-run.js +111 -0
- package/dist/subagent-run.js.map +1 -0
- package/dist/subagents.js +92 -0
- package/dist/subagents.js.map +1 -0
- package/package.json +1 -6
- package/dist/plugins/compaction.d.ts +0 -15
- package/dist/plugins/compaction.js +0 -98
- package/dist/plugins/compaction.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -5
- package/dist/plugins/index.js +0 -5
- package/dist/plugins/memory.d.ts +0 -11
- package/dist/plugins/memory.js +0 -146
- package/dist/plugins/memory.js.map +0 -1
- package/dist/plugins/runner.d.ts +0 -1
- package/dist/plugins/runner.js +0 -83
- package/dist/plugins/runner.js.map +0 -1
- package/dist/plugins/scope.js +0 -13
- package/dist/plugins/scope.js.map +0 -1
- package/dist/plugins/sessions.d.ts +0 -12
- package/dist/plugins/sessions.js +0 -34
- package/dist/plugins/sessions.js.map +0 -1
- package/dist/plugins/tool-hook-handlers.js +0 -77
- package/dist/plugins/tool-hook-handlers.js.map +0 -1
- package/dist/plugins/tool-hook-results.js +0 -64
- package/dist/plugins/tool-hook-results.js.map +0 -1
- package/dist/plugins/tool-hooks.js +0 -111
- package/dist/plugins/tool-hooks.js.map +0 -1
- package/dist/plugins/types.d.ts +0 -105
- package/dist/plugins/types.js +0 -20
- package/dist/plugins/types.js.map +0 -1
- package/dist/session/lifecycle.d.ts +0 -12
- package/dist/session/lifecycle.js +0 -126
- package/dist/session/lifecycle.js.map +0 -1
- package/dist/session/overlay-anchor.js +0 -151
- package/dist/session/overlay-anchor.js.map +0 -1
- package/dist/session/overlay.js +0 -141
- package/dist/session/overlay.js.map +0 -1
- package/dist/session/snapshot.d.ts +0 -1
- /package/dist/{agent-loop.d.ts → session/history.d.ts} +0 -0
- /package/dist/{plugins/scope.d.ts → session/session-state.d.ts} +0 -0
package/dist/session/session.js
CHANGED
|
@@ -1,43 +1,36 @@
|
|
|
1
|
-
import { runWithAgentPluginScope } from "../plugins/scope.js";
|
|
2
1
|
import { runAgentLoop } from "../agent-loop.js";
|
|
3
|
-
import {
|
|
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";
|
|
2
|
+
import { normalizeAgentInput } from "./input-normalization.js";
|
|
7
3
|
import { BufferedAgentRun } from "./run.js";
|
|
8
|
-
import {
|
|
4
|
+
import { addSteeringInput, closeRuntimeInput, createRuntimeInputState, hooksForRuntimeInput, withRuntimeInputWindow, withSteeringPlacement } from "./runtime-input.js";
|
|
5
|
+
import { errorMessage, runAfterTurnHook, sessionKilledError, sessionTerminalError } from "./session-errors.js";
|
|
6
|
+
import { closeKilledRuntimeInputs } from "./session-kill.js";
|
|
7
|
+
import { drainRuntimeInput } from "./session-runtime-drain.js";
|
|
8
|
+
import { SessionState } from "./session-state.js";
|
|
9
|
+
import { emitTurnErrorAfterRecovery } from "./session-turn-error.js";
|
|
9
10
|
//#region src/session/session.ts
|
|
10
11
|
var AgentSession = class {
|
|
12
|
+
#hooks;
|
|
11
13
|
#inputQueue = [];
|
|
12
|
-
#internalLlm;
|
|
13
14
|
#llm;
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#plugins;
|
|
15
|
+
#pendingRuntimeInputs = [];
|
|
16
|
+
#state;
|
|
17
17
|
#activeAbort;
|
|
18
18
|
#activeRun;
|
|
19
19
|
#activeRuntimeInput;
|
|
20
|
-
#
|
|
20
|
+
#deletePromise;
|
|
21
21
|
#killed = false;
|
|
22
|
-
#loadPromise;
|
|
23
|
-
#loaded = false;
|
|
24
|
-
#pluginState = {};
|
|
25
|
-
#compactions = [];
|
|
26
|
-
#overlays = new SessionOverlayState();
|
|
27
22
|
#running = false;
|
|
28
|
-
#
|
|
29
|
-
constructor(llm, persistence,
|
|
30
|
-
this.#
|
|
31
|
-
this.#onPluginError = onPluginError;
|
|
32
|
-
this.#persistence = persistence;
|
|
33
|
-
this.#plugins = plugins;
|
|
23
|
+
#runToCloseOnKill;
|
|
24
|
+
constructor(llm, persistence, hooks) {
|
|
25
|
+
this.#hooks = hooks;
|
|
34
26
|
this.#llm = llm;
|
|
27
|
+
this.#state = new SessionState(persistence);
|
|
35
28
|
}
|
|
36
29
|
async send(input) {
|
|
37
|
-
if (this.#killed) throw
|
|
38
|
-
await this.#ensureLoaded();
|
|
39
|
-
if (this.#killed) throw
|
|
40
|
-
const runtimeInput = createRuntimeInputState();
|
|
30
|
+
if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
|
|
31
|
+
await this.#state.ensureLoaded();
|
|
32
|
+
if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
|
|
33
|
+
const runtimeInput = createRuntimeInputState(this.#pendingRuntimeInputs.splice(0));
|
|
41
34
|
const acceptedInput = normalizeAgentInput(input);
|
|
42
35
|
const run = new BufferedAgentRun();
|
|
43
36
|
run.emit(acceptedInput);
|
|
@@ -56,80 +49,68 @@ var AgentSession = class {
|
|
|
56
49
|
return run;
|
|
57
50
|
}
|
|
58
51
|
async steer(input) {
|
|
59
|
-
if (this.#killed) throw
|
|
52
|
+
if (this.#killed || this.#deletePromise) throw sessionTerminalError(this.#killed);
|
|
60
53
|
const runtimeInput = this.#activeRuntimeInput;
|
|
61
54
|
const run = this.#activeRun;
|
|
62
55
|
if (!(runtimeInput && run)) return this.send(input);
|
|
63
|
-
await
|
|
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();
|
|
56
|
+
await addSteeringInput(runtimeInput, input);
|
|
90
57
|
return run;
|
|
91
58
|
}
|
|
92
59
|
interrupt() {
|
|
93
60
|
this.#activeAbort?.abort();
|
|
94
61
|
}
|
|
95
|
-
|
|
62
|
+
delete() {
|
|
63
|
+
this.#deletePromise ??= this.#state.delete().then(() => this.kill(), (error) => {
|
|
64
|
+
this.#deletePromise = void 0;
|
|
65
|
+
throw error;
|
|
66
|
+
});
|
|
67
|
+
return this.#deletePromise;
|
|
68
|
+
}
|
|
69
|
+
enqueueRuntimeInput(input, placement = "turn-start") {
|
|
96
70
|
if (this.#killed) return;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
71
|
+
const runtimeInput = this.#activeRuntimeInput;
|
|
72
|
+
if (runtimeInput && !runtimeInput.closedReason) {
|
|
73
|
+
if (placement === "turn-start" && runtimeInput.placement !== placement) {
|
|
74
|
+
this.#enqueuePendingRuntimeInput({
|
|
75
|
+
input,
|
|
76
|
+
placement
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
runtimeInput.queue.push({
|
|
81
|
+
input,
|
|
82
|
+
placement
|
|
107
83
|
});
|
|
108
|
-
|
|
84
|
+
return;
|
|
109
85
|
}
|
|
86
|
+
this.#enqueuePendingRuntimeInput({
|
|
87
|
+
input,
|
|
88
|
+
placement
|
|
89
|
+
});
|
|
110
90
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this.#loadPromise ??= this.#loadSessionState();
|
|
114
|
-
try {
|
|
115
|
-
await this.#loadPromise;
|
|
116
|
-
} catch (error) {
|
|
117
|
-
this.#loadPromise = void 0;
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
91
|
+
emitObserverEvent(event) {
|
|
92
|
+
this.#activeRun?.emit(event);
|
|
120
93
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
94
|
+
#enqueuePendingRuntimeInput(input) {
|
|
95
|
+
const queuedTurn = this.#inputQueue[0];
|
|
96
|
+
if (input.placement === "turn-start" && queuedTurn) {
|
|
97
|
+
queuedTurn.runtimeInput.queue.push(input);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.#pendingRuntimeInputs.push(input);
|
|
125
101
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this.#
|
|
129
|
-
const
|
|
130
|
-
this.#
|
|
131
|
-
this.#
|
|
132
|
-
|
|
102
|
+
kill() {
|
|
103
|
+
if (this.#killed) return;
|
|
104
|
+
this.#killed = true;
|
|
105
|
+
const killedError = sessionKilledError();
|
|
106
|
+
this.#pendingRuntimeInputs.length = 0;
|
|
107
|
+
this.#activeAbort?.abort();
|
|
108
|
+
closeKilledRuntimeInputs({
|
|
109
|
+
activeRuntimeInput: this.#activeRuntimeInput,
|
|
110
|
+
inputQueue: this.#inputQueue,
|
|
111
|
+
message: killedError.message,
|
|
112
|
+
runToClose: this.#runToCloseOnKill ?? this.#activeRun
|
|
113
|
+
});
|
|
133
114
|
}
|
|
134
115
|
async #drainInputQueue() {
|
|
135
116
|
if (this.#running) return;
|
|
@@ -146,242 +127,79 @@ var AgentSession = class {
|
|
|
146
127
|
async #processQueuedInput({ input, run, runtimeInput }) {
|
|
147
128
|
const activeAbort = new AbortController();
|
|
148
129
|
this.#activeAbort = activeAbort;
|
|
149
|
-
const historySnapshot = this.#history.modelSnapshot();
|
|
150
|
-
this.#overlays.startTurn(input, historySnapshot);
|
|
151
130
|
this.#activeRun = run;
|
|
152
131
|
this.#activeRuntimeInput = runtimeInput;
|
|
132
|
+
this.#runToCloseOnKill = run;
|
|
133
|
+
const historySnapshot = this.#state.modelSnapshot();
|
|
153
134
|
try {
|
|
154
|
-
await
|
|
155
|
-
await
|
|
135
|
+
await withSteeringPlacement(runtimeInput, "turn-start", async () => {
|
|
136
|
+
await this.#hooks?.beforeTurn?.({
|
|
137
|
+
history: this.#state.modelSnapshot(),
|
|
156
138
|
input,
|
|
157
|
-
runtimeInput,
|
|
158
139
|
signal: activeAbort.signal
|
|
159
140
|
});
|
|
160
141
|
});
|
|
161
|
-
await
|
|
142
|
+
await withRuntimeInputWindow(runtimeInput, "turn-start", async () => {
|
|
162
143
|
await run.emitBoundary({ type: "turn-start" });
|
|
163
144
|
});
|
|
164
|
-
this.#
|
|
165
|
-
await this.#
|
|
166
|
-
await
|
|
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
|
+
});
|
|
167
153
|
const result = await runAgentLoop({
|
|
168
154
|
emit: async (event) => {
|
|
169
155
|
if (event.type === "step-start" || event.type === "step-end") {
|
|
170
|
-
await
|
|
156
|
+
await withRuntimeInputWindow(runtimeInput, event.type, async () => {
|
|
171
157
|
await run.emitBoundary(event);
|
|
172
158
|
});
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
};
|
|
179
|
-
return;
|
|
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;
|
|
180
166
|
}
|
|
181
167
|
run.emit(event);
|
|
182
168
|
},
|
|
183
|
-
history: this.#history,
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
runtimeInput,
|
|
187
|
-
withSteeringPlacement: (placement, callback) => this.#withSteeringPlacement(runtimeInput, placement, callback)
|
|
188
|
-
}),
|
|
189
|
-
llm: (context) => this.#invokeLlm(context),
|
|
169
|
+
history: this.#state.history,
|
|
170
|
+
hooks: hooksForRuntimeInput(this.#hooks, runtimeInput),
|
|
171
|
+
llm: this.#llm,
|
|
190
172
|
signal: activeAbort.signal
|
|
191
173
|
});
|
|
192
|
-
await this.#
|
|
174
|
+
await this.#state.commit();
|
|
193
175
|
const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
|
|
194
176
|
closeRuntimeInput(runtimeInput, terminalEvent);
|
|
195
|
-
this.#expireActiveOverlays(terminalEvent);
|
|
196
177
|
this.#activeRuntimeInput = void 0;
|
|
197
178
|
this.#activeRun = void 0;
|
|
198
|
-
|
|
179
|
+
await runAfterTurnHook(this.#hooks, {
|
|
180
|
+
history: this.#state.modelSnapshot(),
|
|
199
181
|
input,
|
|
200
182
|
result,
|
|
201
183
|
signal: activeAbort.signal
|
|
202
|
-
})
|
|
184
|
+
});
|
|
203
185
|
run.emit({ type: terminalEvent });
|
|
204
186
|
} catch (error) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
this.#expireActiveOverlays("turn-error");
|
|
212
|
-
this.#activeAbort = void 0;
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
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)
|
|
187
|
+
await emitTurnErrorAfterRecovery({
|
|
188
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
189
|
+
historySnapshot,
|
|
190
|
+
run,
|
|
191
|
+
runtimeInput,
|
|
192
|
+
state: this.#state
|
|
231
193
|
});
|
|
232
|
-
closeRuntimeInput(runtimeInput, "turn-error");
|
|
233
|
-
this.#expireActiveOverlays("turn-error");
|
|
234
194
|
} finally {
|
|
235
195
|
closeRuntimeInput(runtimeInput);
|
|
236
196
|
this.#activeAbort = void 0;
|
|
237
197
|
this.#activeRun = void 0;
|
|
238
198
|
this.#activeRuntimeInput = void 0;
|
|
239
|
-
this.#
|
|
199
|
+
this.#runToCloseOnKill = void 0;
|
|
240
200
|
run.close(void 0, runtimeInput.closedReason);
|
|
241
201
|
}
|
|
242
202
|
}
|
|
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
|
-
} 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;
|
|
373
|
-
}
|
|
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
|
-
}
|
|
385
203
|
};
|
|
386
204
|
//#endregion
|
|
387
205
|
export { AgentSession };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":["#inputQueue","#internalLlm","#llm","#onPluginError","#persistence","#plugins","#overlays","#killed","#ensureLoaded","#drainInputQueue","#activeRuntimeInput","#activeRun","#activeAbort","#expireActiveOverlays","#loaded","#loadPromise","#loadSessionState","#replaceWithStoredSession","#storeVersion","#history","#pluginState","#compactions","#running","#processQueuedInput","#withSteeringPlacement","#pluginLifecycle","#withRuntimeInputWindow","#commitHistory","#drainRuntimeInput","#invokeLlm","#summarizeForPlugins","#createPluginScope"],"sources":["../../src/session/session.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport { runAgentLoop } from \"../agent-loop\";\nimport type { Llm, LlmOutput } from \"../llm\";\nimport type { ResolvedAgentPlugins } from \"../plugins/runner\";\nimport {\n type AgentPluginScope,\n runWithAgentPluginScope,\n} from \"../plugins/scope\";\nimport type { UserInput } from \"./events\";\nimport { ModelMessageHistory } from \"./history\";\nimport type { AgentInput } from \"./input\";\nimport {\n type AgentPluginErrorHandler,\n type AgentSessionLifecycle,\n createRuntimeInputStepLifecycle,\n runPluginAfterTurnHandlers,\n runPluginBeforeTurnHandlers,\n} from \"./lifecycle\";\nimport { SessionOverlayState } from \"./overlay\";\nimport type { AgentRun } from \"./run\";\nimport { BufferedAgentRun } from \"./run\";\nimport {\n addRuntimeInput,\n closeRuntimeInput,\n createRuntimeInputState,\n normalizeAgentInput,\n type RuntimeInputPlacement,\n type RuntimeInputState,\n shiftRuntimeInput,\n} from \"./runtime-input\";\nimport {\n type AgentCompactionOverlay,\n decodeStoredSessionSnapshot,\n encodeSessionSnapshot,\n} from \"./snapshot\";\nimport type { SessionStore } from \"./store/types\";\n\nexport type { AgentInput, SessionInput, UserInput } from \"./input\";\nexport type { AgentRun } from \"./run\";\n\ninterface SessionPersistenceOptions {\n readonly key: string;\n readonly store: SessionStore;\n}\n\ninterface QueuedInput {\n readonly input: UserInput;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n}\n\nexport class AgentSession {\n readonly #inputQueue: QueuedInput[] = [];\n readonly #internalLlm: Llm;\n readonly #llm: Llm;\n readonly #onPluginError?: AgentPluginErrorHandler;\n readonly #persistence: SessionPersistenceOptions;\n readonly #plugins?: ResolvedAgentPlugins;\n #activeAbort?: AbortController;\n #activeRun?: BufferedAgentRun;\n #activeRuntimeInput?: RuntimeInputState;\n #history = new ModelMessageHistory();\n #killed = false;\n #loadPromise?: Promise<void>;\n #loaded = false;\n #pluginState: Record<string, unknown> = {};\n #compactions: AgentCompactionOverlay[] = [];\n readonly #overlays = new SessionOverlayState();\n #running = false;\n #storeVersion: string | undefined;\n\n constructor(\n llm: Llm,\n persistence: SessionPersistenceOptions,\n plugins?: ResolvedAgentPlugins,\n internalLlm: Llm = llm,\n onPluginError?: AgentPluginErrorHandler\n ) {\n this.#internalLlm = internalLlm;\n this.#onPluginError = onPluginError;\n this.#persistence = persistence;\n this.#plugins = plugins;\n this.#llm = llm;\n }\n\n async send(input: AgentInput): Promise<AgentRun> {\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n await this.#ensureLoaded();\n\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n const runtimeInput = createRuntimeInputState();\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) {\n throw sessionKilledError();\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 addRuntimeInput(runtimeInput, input);\n return run;\n }\n\n async overlay(input: AgentInput): Promise<AgentRun> {\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n await this.#ensureLoaded();\n\n if (this.#killed) {\n throw sessionKilledError();\n }\n\n const activeRun = this.#activeRun;\n if (activeRun) {\n const placement =\n this.#activeRuntimeInput?.steerPlacement ??\n this.#activeRuntimeInput?.placement ??\n \"step-end\";\n const entry = this.#overlays.appendActiveOverlay(input, placement);\n if (!entry) {\n throw new Error(\"Active overlay frame is unavailable.\");\n }\n activeRun.emit({\n input: entry.summary,\n placement: entry.placement,\n type: \"overlay-accepted\",\n });\n return activeRun;\n }\n\n const entry = this.#overlays.appendPendingOverlay(input);\n const run = new BufferedAgentRun();\n run.emit({\n input: entry.summary,\n placement: entry.placement,\n type: \"overlay-accepted\",\n });\n run.close();\n return run;\n }\n\n interrupt(): void {\n this.#activeAbort?.abort();\n }\n\n kill(): void {\n if (this.#killed) {\n return;\n }\n\n this.#killed = true;\n this.#expireActiveOverlays(\"kill\");\n this.#activeAbort?.abort();\n closeRuntimeInput(this.#activeRuntimeInput, sessionKilledError().message);\n\n while (this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n closeRuntimeInput(item?.runtimeInput, sessionKilledError().message);\n item?.run.emit({\n type: \"turn-error\",\n message: sessionKilledError().message,\n });\n item?.run.close(undefined, sessionKilledError().message);\n }\n }\n\n async #ensureLoaded(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n this.#loadPromise ??= this.#loadSessionState();\n try {\n await this.#loadPromise;\n } catch (error) {\n this.#loadPromise = undefined;\n throw error;\n }\n }\n\n async #loadSessionState(): Promise<void> {\n if (this.#loaded) {\n return;\n }\n\n await this.#replaceWithStoredSession();\n this.#loaded = true;\n }\n\n async #replaceWithStoredSession(): Promise<void> {\n const stored = await this.#persistence.store.load(this.#persistence.key);\n this.#storeVersion = stored?.version;\n const snapshot = decodeStoredSessionSnapshot(stored);\n this.#history = new ModelMessageHistory(snapshot.history);\n this.#pluginState = structuredClone(snapshot.pluginState);\n this.#compactions = structuredClone(snapshot.compactions);\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 const historySnapshot = this.#history.modelSnapshot();\n this.#overlays.startTurn(input, historySnapshot);\n this.#activeRun = run;\n this.#activeRuntimeInput = runtimeInput;\n\n try {\n await this.#withSteeringPlacement(\n runtimeInput,\n \"turn-start\",\n async () => {\n await runPluginBeforeTurnHandlers(this.#pluginLifecycle(), {\n input,\n runtimeInput,\n signal: activeAbort.signal,\n });\n }\n );\n await this.#withRuntimeInputWindow(\n runtimeInput,\n \"turn-start\",\n async () => {\n await run.emitBoundary({ type: \"turn-start\" });\n }\n );\n this.#history.appendUserInput(input);\n await this.#commitHistory();\n await this.#drainRuntimeInput(run, runtimeInput, \"turn-start\");\n\n const result = await runAgentLoop({\n emit: async (event) => {\n if (event.type === \"step-start\" || event.type === \"step-end\") {\n await this.#withRuntimeInputWindow(\n runtimeInput,\n event.type,\n async () => {\n await run.emitBoundary(event);\n }\n );\n const overlayInputAdded =\n event.type === \"step-end\" &&\n this.#overlays.consumeStepEndOverlayInputAdded();\n const runtimeInputAdded = await this.#drainRuntimeInput(\n run,\n runtimeInput,\n event.type\n );\n\n if (event.type === \"step-end\") {\n return {\n overlayInputAdded,\n runtimeInputAdded,\n };\n }\n return;\n }\n\n run.emit(event);\n },\n history: this.#history,\n stepLifecycle: createRuntimeInputStepLifecycle({\n lifecycle: this.#pluginLifecycle(),\n runtimeInput,\n withSteeringPlacement: (placement, callback) =>\n this.#withSteeringPlacement(runtimeInput, placement, callback),\n }),\n llm: (context) => this.#invokeLlm(context),\n signal: activeAbort.signal,\n });\n\n await this.#commitHistory();\n const terminalEvent = result === \"aborted\" ? \"turn-abort\" : \"turn-end\";\n closeRuntimeInput(runtimeInput, terminalEvent);\n this.#expireActiveOverlays(terminalEvent);\n this.#activeRuntimeInput = undefined;\n this.#activeRun = undefined;\n const pluginHandlersRan = await runPluginAfterTurnHandlers(\n this.#pluginLifecycle(),\n {\n input,\n result,\n signal: activeAbort.signal,\n }\n );\n if (pluginHandlersRan) {\n await this.#commitHistory();\n }\n run.emit({ type: terminalEvent });\n } catch (error) {\n if (error instanceof SessionCommitConflictError) {\n run.emit({ type: \"turn-error\", message: error.message });\n closeRuntimeInput(runtimeInput, \"a session commit conflict\");\n this.#expireActiveOverlays(\"turn-error\");\n this.#activeAbort = undefined;\n return;\n }\n\n this.#history.rollback(historySnapshot);\n try {\n await this.#commitHistory();\n } catch (rollbackError) {\n run.emit({\n type: \"turn-error\",\n message: `${errorMessage(error)}; history rollback persistence failed: ${errorMessage(\n rollbackError\n )}`,\n });\n closeRuntimeInput(runtimeInput, \"turn-error\");\n this.#expireActiveOverlays(\"turn-error\");\n this.#activeAbort = undefined;\n return;\n }\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n closeRuntimeInput(runtimeInput, \"turn-error\");\n this.#expireActiveOverlays(\"turn-error\");\n } finally {\n closeRuntimeInput(runtimeInput);\n this.#activeAbort = undefined;\n this.#activeRun = undefined;\n this.#activeRuntimeInput = undefined;\n this.#overlays.resetActiveTurn();\n run.close(undefined, runtimeInput.closedReason);\n }\n }\n\n async #commitHistory(): Promise<void> {\n const result = await this.#persistence.store.commit(\n this.#persistence.key,\n {\n state: encodeSessionSnapshot({\n compactions: this.#compactions,\n history: this.#history.modelSnapshot(),\n pluginState: this.#pluginState,\n }),\n },\n { expectedVersion: this.#storeVersion ?? null }\n );\n\n if (!result.ok) {\n await this.#replaceWithStoredSession();\n throw new SessionCommitConflictError(this.#persistence.key);\n }\n\n this.#storeVersion = result.version;\n }\n\n #createPluginScope(signal: AbortSignal): AgentPluginScope {\n return {\n eventHandlers: this.#plugins?.eventHandlers,\n getCompactions: () => structuredClone(this.#compactions),\n getPluginState: (pluginName) => this.#pluginState[pluginName],\n history: () => this.#history.modelSnapshot(),\n sessionKey: this.#persistence.key,\n overlay: (input) => this.overlay(input),\n setCompactions: (compactions) => {\n this.#compactions = structuredClone([...compactions]);\n },\n setPluginState: (pluginName, state) => {\n this.#pluginState = {\n ...this.#pluginState,\n [pluginName]: structuredClone(state),\n };\n },\n signal,\n steer: (input) => this.steer(input),\n summarize: (messages) => this.#summarizeForPlugins(messages, signal),\n };\n }\n\n #pluginLifecycle(): AgentSessionLifecycle {\n return {\n createScope: (signal) => this.#createPluginScope(signal),\n history: () => this.#history.modelSnapshot(),\n onPluginError: this.#onPluginError,\n plugins: this.#plugins,\n sessionKey: this.#persistence.key,\n overlaySession: (input) => this.overlay(input),\n steerCurrentRun: async (runtimeInput, input) => {\n await addRuntimeInput(runtimeInput, input);\n if (!this.#activeRun) {\n throw new Error(\"Agent plugin steering requires an active run.\");\n }\n return this.#activeRun;\n },\n steerSession: (input) => this.steer(input),\n };\n }\n\n #invokeLlm({\n history,\n signal,\n }: {\n readonly history: readonly ModelMessage[];\n readonly signal?: AbortSignal;\n }): Promise<LlmOutput> {\n const activeSignal = signal ?? new AbortController().signal;\n const invoke = async () => {\n let transformedHistory = history;\n for (const transform of this.#plugins?.contextTransforms ?? []) {\n transformedHistory = await transform({\n history: transformedHistory,\n sessionKey: this.#persistence.key,\n signal: activeSignal,\n });\n }\n\n const modelHistory = this.#overlays.compose(transformedHistory, history);\n this.#overlays.markInferenceStarted();\n return this.#llm({\n history: modelHistory,\n signal: activeSignal,\n });\n };\n\n return runWithAgentPluginScope(\n this.#createPluginScope(activeSignal),\n invoke\n );\n }\n\n async #summarizeForPlugins(\n messages: readonly ModelMessage[],\n signal: AbortSignal\n ): Promise<string> {\n const output = await this.#internalLlm({\n history: [\n {\n content:\n \"Summarize these earlier session messages for future model context.\",\n role: \"system\",\n },\n ...messages,\n ],\n signal,\n });\n return outputToText(output) || `Summarized ${messages.length} messages.`;\n }\n\n async #withRuntimeInputWindow<T>(\n runtimeInput: RuntimeInputState,\n placement: RuntimeInputPlacement,\n callback: () => Promise<T>\n ): Promise<T> {\n const previousSteerPlacement = runtimeInput.steerPlacement;\n runtimeInput.placement = placement;\n runtimeInput.steerPlacement = placement;\n try {\n return await callback();\n } finally {\n runtimeInput.placement = undefined;\n runtimeInput.steerPlacement = previousSteerPlacement;\n }\n }\n\n async #withSteeringPlacement<T>(\n runtimeInput: RuntimeInputState,\n placement: RuntimeInputPlacement,\n callback: () => Promise<T>\n ): Promise<T> {\n const previousSteerPlacement = runtimeInput.steerPlacement;\n runtimeInput.steerPlacement = placement;\n try {\n return await callback();\n } finally {\n runtimeInput.steerPlacement = previousSteerPlacement;\n }\n }\n\n async #drainRuntimeInput(\n run: BufferedAgentRun,\n runtimeInput: RuntimeInputState,\n placement: RuntimeInputPlacement\n ): Promise<boolean> {\n let added = false;\n let next = shiftRuntimeInput(runtimeInput, placement);\n while (next) {\n added = true;\n run.emit({ type: \"runtime-input\", input: next.input, placement });\n this.#history.appendUserInput(next.input);\n await this.#commitHistory();\n next = shiftRuntimeInput(runtimeInput, placement);\n }\n\n return added;\n }\n\n #expireActiveOverlays(\n reason: \"kill\" | \"turn-abort\" | \"turn-end\" | \"turn-error\"\n ): void {\n const event = this.#overlays.expireActiveFrame(reason);\n if (!event) {\n return;\n }\n\n this.#activeRun?.emit(event);\n }\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\nfunction outputToText(output: LlmOutput): string {\n const parts: string[] = [];\n for (const message of output) {\n if (message.role !== \"assistant\") {\n continue;\n }\n\n if (typeof message.content === \"string\") {\n parts.push(message.content);\n continue;\n }\n\n for (const part of message.content) {\n if (part.type === \"text\") {\n parts.push(part.text);\n }\n }\n }\n\n return parts.join(\"\\n\").trim();\n}\n\nfunction sessionKilledError(): Error {\n return new Error(\"Session killed\");\n}\n\nclass SessionCommitConflictError extends Error {\n constructor(key: string) {\n super(`Session ${JSON.stringify(key)} commit conflict`);\n }\n}\n"],"mappings":"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"}
|
|
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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"}
|
package/dist/session/snapshot.js
CHANGED
|
@@ -1,45 +1,19 @@
|
|
|
1
1
|
//#region src/session/snapshot.ts
|
|
2
|
-
function encodeSessionSnapshot(
|
|
2
|
+
function encodeSessionSnapshot(history) {
|
|
3
3
|
return {
|
|
4
|
-
|
|
5
|
-
history: structuredClone(
|
|
6
|
-
pluginState: structuredClone({ ...state.pluginState ?? {} }),
|
|
7
|
-
schemaVersion: 2
|
|
4
|
+
schemaVersion: 1,
|
|
5
|
+
history: structuredClone(history)
|
|
8
6
|
};
|
|
9
7
|
}
|
|
10
8
|
function decodeStoredSessionSnapshot(stored) {
|
|
11
|
-
if (!stored) return
|
|
9
|
+
if (!stored) return [];
|
|
12
10
|
const snapshot = stored.state;
|
|
13
|
-
if (isSessionSnapshotV1(snapshot)) return
|
|
14
|
-
...emptySnapshotState(),
|
|
15
|
-
history: structuredClone(snapshot.history)
|
|
16
|
-
};
|
|
17
|
-
if (isSessionSnapshotV2(snapshot)) return {
|
|
18
|
-
compactions: structuredClone(snapshot.compactions),
|
|
19
|
-
history: structuredClone(snapshot.history),
|
|
20
|
-
pluginState: structuredClone(snapshot.pluginState)
|
|
21
|
-
};
|
|
11
|
+
if (isSessionSnapshotV1(snapshot)) return structuredClone(snapshot.history);
|
|
22
12
|
throw new Error("Unsupported stored session state");
|
|
23
13
|
}
|
|
24
|
-
function emptySnapshotState() {
|
|
25
|
-
return {
|
|
26
|
-
compactions: [],
|
|
27
|
-
history: [],
|
|
28
|
-
pluginState: {}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
14
|
function isSessionSnapshotV1(value) {
|
|
32
15
|
return value !== null && typeof value === "object" && "schemaVersion" in value && value.schemaVersion === 1 && "history" in value && Array.isArray(value.history);
|
|
33
16
|
}
|
|
34
|
-
function isSessionSnapshotV2(value) {
|
|
35
|
-
return value !== null && typeof value === "object" && "schemaVersion" in value && value.schemaVersion === 2 && "history" in value && Array.isArray(value.history) && "pluginState" in value && isRecord(value.pluginState) && "compactions" in value && Array.isArray(value.compactions) && value.compactions.every(isCompactionOverlay);
|
|
36
|
-
}
|
|
37
|
-
function isCompactionOverlay(value) {
|
|
38
|
-
return value !== null && typeof value === "object" && "createdAt" in value && typeof value.createdAt === "string" && "endIndex" in value && typeof value.endIndex === "number" && "id" in value && typeof value.id === "string" && "startIndex" in value && typeof value.startIndex === "number" && "summary" in value && typeof value.summary === "string";
|
|
39
|
-
}
|
|
40
|
-
function isRecord(value) {
|
|
41
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
42
|
-
}
|
|
43
17
|
//#endregion
|
|
44
18
|
export { decodeStoredSessionSnapshot, encodeSessionSnapshot };
|
|
45
19
|
|
|
@@ -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 type AgentSessionSnapshot = AgentSessionSnapshotV1;\n\nexport function encodeSessionSnapshot(\n history: ModelMessage[]\n): AgentSessionSnapshot {\n return { schemaVersion: 1, history: structuredClone(history) };\n}\n\nexport function decodeStoredSessionSnapshot(\n stored: StoredSession | null\n): ModelMessage[] {\n if (!stored) {\n return [];\n }\n\n const snapshot = stored.state;\n if (isSessionSnapshotV1(snapshot)) {\n return structuredClone(snapshot.history);\n }\n\n throw new Error(\"Unsupported stored session state\");\n}\n\nfunction isSessionSnapshotV1(value: unknown): value is AgentSessionSnapshotV1 {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"schemaVersion\" in value &&\n value.schemaVersion === 1 &&\n \"history\" in value &&\n Array.isArray(value.history)\n );\n}\n"],"mappings":";AAUA,SAAgB,sBACd,SACsB;CACtB,OAAO;EAAE,eAAe;EAAG,SAAS,gBAAgB,OAAO;CAAE;AAC/D;AAEA,SAAgB,4BACd,QACgB;CAChB,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,WAAW,OAAO;CACxB,IAAI,oBAAoB,QAAQ,GAC9B,OAAO,gBAAgB,SAAS,OAAO;CAGzC,MAAM,IAAI,MAAM,kCAAkC;AACpD;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B"}
|
|
@@ -8,6 +8,7 @@ declare class FileSessionStore implements SessionStore {
|
|
|
8
8
|
commit(key: string, next: SessionStoreCommit, options: {
|
|
9
9
|
expectedVersion: string | null;
|
|
10
10
|
}): Promise<CommitResult>;
|
|
11
|
+
delete(key: string): Promise<void>;
|
|
11
12
|
}
|
|
12
13
|
//#endregion
|
|
13
14
|
export { FileSessionStore };
|
|
@@ -57,6 +57,20 @@ var FileSessionStore = class {
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
async delete(key) {
|
|
61
|
+
const file = this.#fileForKey(key);
|
|
62
|
+
const lockDirectory = `${file}.lock`;
|
|
63
|
+
await mkdir(dirname(file), { recursive: true });
|
|
64
|
+
await acquireFileLock(lockDirectory);
|
|
65
|
+
try {
|
|
66
|
+
await rm(file, { force: true });
|
|
67
|
+
} finally {
|
|
68
|
+
await rm(lockDirectory, {
|
|
69
|
+
force: true,
|
|
70
|
+
recursive: true
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
60
74
|
#fileForKey(key) {
|
|
61
75
|
return join(this.#directory, `${Buffer.from(key).toString("base64url")}.json`);
|
|
62
76
|
}
|