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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +191 -20
  2. package/dist/agent-loop.d.ts +1 -0
  3. package/dist/agent-loop.js +14 -8
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/agent.d.ts +8 -10
  6. package/dist/agent.js +34 -13
  7. package/dist/agent.js.map +1 -1
  8. package/dist/index.d.ts +8 -4
  9. package/dist/index.js +6 -1
  10. package/dist/llm.js +7 -1
  11. package/dist/llm.js.map +1 -1
  12. package/dist/plugins/compaction.d.ts +15 -0
  13. package/dist/plugins/compaction.js +98 -0
  14. package/dist/plugins/compaction.js.map +1 -0
  15. package/dist/plugins/index.d.ts +5 -0
  16. package/dist/plugins/index.js +5 -0
  17. package/dist/plugins/memory.d.ts +11 -0
  18. package/dist/plugins/memory.js +146 -0
  19. package/dist/plugins/memory.js.map +1 -0
  20. package/dist/plugins/runner.d.ts +1 -0
  21. package/dist/plugins/runner.js +83 -0
  22. package/dist/plugins/runner.js.map +1 -0
  23. package/dist/plugins/scope.d.ts +1 -0
  24. package/dist/plugins/scope.js +13 -0
  25. package/dist/plugins/scope.js.map +1 -0
  26. package/dist/plugins/sessions.d.ts +12 -0
  27. package/dist/plugins/sessions.js +34 -0
  28. package/dist/plugins/sessions.js.map +1 -0
  29. package/dist/plugins/tool-hook-handlers.js +77 -0
  30. package/dist/plugins/tool-hook-handlers.js.map +1 -0
  31. package/dist/plugins/tool-hook-results.js +64 -0
  32. package/dist/plugins/tool-hook-results.js.map +1 -0
  33. package/dist/plugins/tool-hooks.js +111 -0
  34. package/dist/plugins/tool-hooks.js.map +1 -0
  35. package/dist/plugins/types.d.ts +105 -0
  36. package/dist/plugins/types.js +20 -0
  37. package/dist/plugins/types.js.map +1 -0
  38. package/dist/session/events.d.ts +19 -2
  39. package/dist/session/input.d.ts +4 -0
  40. package/dist/session/lifecycle.d.ts +12 -0
  41. package/dist/session/lifecycle.js +126 -0
  42. package/dist/session/lifecycle.js.map +1 -0
  43. package/dist/session/mapping.js +2 -1
  44. package/dist/session/mapping.js.map +1 -1
  45. package/dist/session/overlay-anchor.js +151 -0
  46. package/dist/session/overlay-anchor.js.map +1 -0
  47. package/dist/session/overlay.js +141 -0
  48. package/dist/session/overlay.js.map +1 -0
  49. package/dist/session/runtime-input.d.ts +1 -0
  50. package/dist/session/runtime-input.js +89 -0
  51. package/dist/session/runtime-input.js.map +1 -0
  52. package/dist/session/session.js +164 -117
  53. package/dist/session/session.js.map +1 -1
  54. package/dist/session/snapshot.d.ts +1 -0
  55. package/dist/session/snapshot.js +31 -5
  56. package/dist/session/snapshot.js.map +1 -1
  57. package/package.json +6 -1
  58. package/dist/hooks.d.ts +0 -32
@@ -1,13 +1,19 @@
1
+ import { runWithAgentPluginScope } from "../plugins/scope.js";
1
2
  import { runAgentLoop } from "../agent-loop.js";
2
3
  import { ModelMessageHistory } from "./history.js";
4
+ import { createRuntimeInputStepLifecycle, runPluginAfterTurnHandlers, runPluginBeforeTurnHandlers } from "./lifecycle.js";
5
+ import { addRuntimeInput, closeRuntimeInput, createRuntimeInputState, normalizeAgentInput, shiftRuntimeInput } from "./runtime-input.js";
6
+ import { SessionOverlayState } from "./overlay.js";
3
7
  import { BufferedAgentRun } from "./run.js";
4
8
  import { decodeStoredSessionSnapshot, encodeSessionSnapshot } from "./snapshot.js";
5
9
  //#region src/session/session.ts
6
10
  var AgentSession = class {
7
- #hooks;
8
11
  #inputQueue = [];
12
+ #internalLlm;
9
13
  #llm;
14
+ #onPluginError;
10
15
  #persistence;
16
+ #plugins;
11
17
  #activeAbort;
12
18
  #activeRun;
13
19
  #activeRuntimeInput;
@@ -15,21 +21,23 @@ var AgentSession = class {
15
21
  #killed = false;
16
22
  #loadPromise;
17
23
  #loaded = false;
24
+ #pluginState = {};
25
+ #compactions = [];
26
+ #overlays = new SessionOverlayState();
18
27
  #running = false;
19
28
  #storeVersion;
20
- constructor(llm, persistence, hooks) {
21
- this.#hooks = hooks;
22
- this.#llm = llm;
29
+ constructor(llm, persistence, plugins, internalLlm = llm, onPluginError) {
30
+ this.#internalLlm = internalLlm;
31
+ this.#onPluginError = onPluginError;
23
32
  this.#persistence = persistence;
33
+ this.#plugins = plugins;
34
+ this.#llm = llm;
24
35
  }
25
36
  async send(input) {
26
37
  if (this.#killed) throw sessionKilledError();
27
38
  await this.#ensureLoaded();
28
39
  if (this.#killed) throw sessionKilledError();
29
- const runtimeInput = {
30
- pending: Promise.resolve(),
31
- queue: []
32
- };
40
+ const runtimeInput = createRuntimeInputState();
33
41
  const acceptedInput = normalizeAgentInput(input);
34
42
  const run = new BufferedAgentRun();
35
43
  run.emit(acceptedInput);
@@ -52,7 +60,33 @@ var AgentSession = class {
52
60
  const runtimeInput = this.#activeRuntimeInput;
53
61
  const run = this.#activeRun;
54
62
  if (!(runtimeInput && run)) return this.send(input);
55
- await this.#addSteeringInput(runtimeInput, input);
63
+ await addRuntimeInput(runtimeInput, input);
64
+ return run;
65
+ }
66
+ async overlay(input) {
67
+ if (this.#killed) throw sessionKilledError();
68
+ await this.#ensureLoaded();
69
+ if (this.#killed) throw sessionKilledError();
70
+ const activeRun = this.#activeRun;
71
+ if (activeRun) {
72
+ const placement = this.#activeRuntimeInput?.steerPlacement ?? this.#activeRuntimeInput?.placement ?? "step-end";
73
+ const entry = this.#overlays.appendActiveOverlay(input, placement);
74
+ if (!entry) throw new Error("Active overlay frame is unavailable.");
75
+ activeRun.emit({
76
+ input: entry.summary,
77
+ placement: entry.placement,
78
+ type: "overlay-accepted"
79
+ });
80
+ return activeRun;
81
+ }
82
+ const entry = this.#overlays.appendPendingOverlay(input);
83
+ const run = new BufferedAgentRun();
84
+ run.emit({
85
+ input: entry.summary,
86
+ placement: entry.placement,
87
+ type: "overlay-accepted"
88
+ });
89
+ run.close();
56
90
  return run;
57
91
  }
58
92
  interrupt() {
@@ -61,11 +95,12 @@ var AgentSession = class {
61
95
  kill() {
62
96
  if (this.#killed) return;
63
97
  this.#killed = true;
98
+ this.#expireActiveOverlays("kill");
64
99
  this.#activeAbort?.abort();
65
- this.#closeRuntimeInput(this.#activeRuntimeInput, sessionKilledError().message);
100
+ closeRuntimeInput(this.#activeRuntimeInput, sessionKilledError().message);
66
101
  while (this.#inputQueue.length > 0) {
67
102
  const item = this.#inputQueue.shift();
68
- this.#closeRuntimeInput(item?.runtimeInput, sessionKilledError().message);
103
+ closeRuntimeInput(item?.runtimeInput, sessionKilledError().message);
69
104
  item?.run.emit({
70
105
  type: "turn-error",
71
106
  message: sessionKilledError().message
@@ -91,7 +126,10 @@ var AgentSession = class {
91
126
  async #replaceWithStoredSession() {
92
127
  const stored = await this.#persistence.store.load(this.#persistence.key);
93
128
  this.#storeVersion = stored?.version;
94
- this.#history = new ModelMessageHistory(decodeStoredSessionSnapshot(stored));
129
+ const snapshot = decodeStoredSessionSnapshot(stored);
130
+ this.#history = new ModelMessageHistory(snapshot.history);
131
+ this.#pluginState = structuredClone(snapshot.pluginState);
132
+ this.#compactions = structuredClone(snapshot.compactions);
95
133
  }
96
134
  async #drainInputQueue() {
97
135
  if (this.#running) return;
@@ -108,14 +146,15 @@ var AgentSession = class {
108
146
  async #processQueuedInput({ input, run, runtimeInput }) {
109
147
  const activeAbort = new AbortController();
110
148
  this.#activeAbort = activeAbort;
149
+ const historySnapshot = this.#history.modelSnapshot();
150
+ this.#overlays.startTurn(input, historySnapshot);
111
151
  this.#activeRun = run;
112
152
  this.#activeRuntimeInput = runtimeInput;
113
- const historySnapshot = this.#history.modelSnapshot();
114
153
  try {
115
154
  await this.#withSteeringPlacement(runtimeInput, "turn-start", async () => {
116
- await this.#hooks?.beforeTurn?.({
117
- history: this.#history.modelSnapshot(),
155
+ await runPluginBeforeTurnHandlers(this.#pluginLifecycle(), {
118
156
  input,
157
+ runtimeInput,
119
158
  signal: activeAbort.signal
120
159
  });
121
160
  });
@@ -131,28 +170,36 @@ var AgentSession = class {
131
170
  await this.#withRuntimeInputWindow(runtimeInput, event.type, async () => {
132
171
  await run.emitBoundary(event);
133
172
  });
173
+ const overlayInputAdded = event.type === "step-end" && this.#overlays.consumeStepEndOverlayInputAdded();
134
174
  const runtimeInputAdded = await this.#drainRuntimeInput(run, runtimeInput, event.type);
135
- if (event.type === "step-end") return { runtimeInputAdded };
175
+ if (event.type === "step-end") return {
176
+ overlayInputAdded,
177
+ runtimeInputAdded
178
+ };
136
179
  return;
137
180
  }
138
181
  run.emit(event);
139
182
  },
140
183
  history: this.#history,
141
- hooks: this.#hooksForRuntimeInput(runtimeInput),
142
- llm: this.#llm,
184
+ stepLifecycle: createRuntimeInputStepLifecycle({
185
+ lifecycle: this.#pluginLifecycle(),
186
+ runtimeInput,
187
+ withSteeringPlacement: (placement, callback) => this.#withSteeringPlacement(runtimeInput, placement, callback)
188
+ }),
189
+ llm: (context) => this.#invokeLlm(context),
143
190
  signal: activeAbort.signal
144
191
  });
145
192
  await this.#commitHistory();
146
193
  const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
147
- this.#closeRuntimeInput(runtimeInput, terminalEvent);
194
+ closeRuntimeInput(runtimeInput, terminalEvent);
195
+ this.#expireActiveOverlays(terminalEvent);
148
196
  this.#activeRuntimeInput = void 0;
149
197
  this.#activeRun = void 0;
150
- await runAfterTurnHook(this.#hooks, {
151
- history: this.#history.modelSnapshot(),
198
+ if (await runPluginAfterTurnHandlers(this.#pluginLifecycle(), {
152
199
  input,
153
200
  result,
154
201
  signal: activeAbort.signal
155
- });
202
+ })) await this.#commitHistory();
156
203
  run.emit({ type: terminalEvent });
157
204
  } catch (error) {
158
205
  if (error instanceof SessionCommitConflictError) {
@@ -160,7 +207,8 @@ var AgentSession = class {
160
207
  type: "turn-error",
161
208
  message: error.message
162
209
  });
163
- this.#closeRuntimeInput(runtimeInput, "a session commit conflict");
210
+ closeRuntimeInput(runtimeInput, "a session commit conflict");
211
+ this.#expireActiveOverlays("turn-error");
164
212
  this.#activeAbort = void 0;
165
213
  return;
166
214
  }
@@ -172,7 +220,8 @@ var AgentSession = class {
172
220
  type: "turn-error",
173
221
  message: `${errorMessage(error)}; history rollback persistence failed: ${errorMessage(rollbackError)}`
174
222
  });
175
- this.#closeRuntimeInput(runtimeInput, "turn-error");
223
+ closeRuntimeInput(runtimeInput, "turn-error");
224
+ this.#expireActiveOverlays("turn-error");
176
225
  this.#activeAbort = void 0;
177
226
  return;
178
227
  }
@@ -180,40 +229,94 @@ var AgentSession = class {
180
229
  type: "turn-error",
181
230
  message: errorMessage(error)
182
231
  });
183
- this.#closeRuntimeInput(runtimeInput, "turn-error");
232
+ closeRuntimeInput(runtimeInput, "turn-error");
233
+ this.#expireActiveOverlays("turn-error");
184
234
  } finally {
185
- this.#closeRuntimeInput(runtimeInput);
235
+ closeRuntimeInput(runtimeInput);
186
236
  this.#activeAbort = void 0;
187
237
  this.#activeRun = void 0;
188
238
  this.#activeRuntimeInput = void 0;
239
+ this.#overlays.resetActiveTurn();
189
240
  run.close(void 0, runtimeInput.closedReason);
190
241
  }
191
242
  }
192
- #addSteeringInput(runtimeInput, input) {
193
- const next = runtimeInput.pending.then(() => {
194
- if (runtimeInput.closedReason) throw runtimeInputClosedError(runtimeInput.closedReason);
195
- runtimeInput.queue.push({
196
- input: normalizeAgentInput(input),
197
- placement: runtimeInput.steerPlacement ?? runtimeInput.placement ?? "step-end"
198
- });
199
- });
200
- runtimeInput.pending = next.catch(() => void 0);
201
- return next;
202
- }
203
- #closeRuntimeInput(runtimeInput, reason = "the run reached a terminal state") {
204
- if (!runtimeInput?.closedReason && runtimeInput) {
205
- runtimeInput.closedReason = reason;
206
- runtimeInput.placement = void 0;
207
- }
208
- }
209
243
  async #commitHistory() {
210
- const result = await this.#persistence.store.commit(this.#persistence.key, { state: encodeSessionSnapshot(this.#history.modelSnapshot()) }, { expectedVersion: this.#storeVersion ?? null });
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 });
211
249
  if (!result.ok) {
212
250
  await this.#replaceWithStoredSession();
213
251
  throw new SessionCommitConflictError(this.#persistence.key);
214
252
  }
215
253
  this.#storeVersion = result.version;
216
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
+ }
217
320
  async #withRuntimeInputWindow(runtimeInput, placement, callback) {
218
321
  const previousSteerPlacement = runtimeInput.steerPlacement;
219
322
  runtimeInput.placement = placement;
@@ -234,19 +337,6 @@ var AgentSession = class {
234
337
  runtimeInput.steerPlacement = previousSteerPlacement;
235
338
  }
236
339
  }
237
- #hooksForRuntimeInput(runtimeInput) {
238
- const hooks = this.#hooks;
239
- if (!hooks) return;
240
- return {
241
- ...hooks,
242
- afterStep: (context) => this.#withSteeringPlacement(runtimeInput, "step-end", async () => {
243
- await hooks.afterStep?.(context);
244
- }),
245
- beforeStep: (context) => this.#withSteeringPlacement(runtimeInput, "step-start", async () => {
246
- await hooks.beforeStep?.(context);
247
- })
248
- };
249
- }
250
340
  async #drainRuntimeInput(run, runtimeInput, placement) {
251
341
  let added = false;
252
342
  let next = shiftRuntimeInput(runtimeInput, placement);
@@ -263,74 +353,31 @@ var AgentSession = class {
263
353
  }
264
354
  return added;
265
355
  }
266
- };
267
- function shiftRuntimeInput(runtimeInput, placement) {
268
- const index = runtimeInput.queue.findIndex((input) => input.placement === placement);
269
- if (index === -1) return;
270
- return runtimeInput.queue.splice(index, 1)[0];
271
- }
272
- async function runAfterTurnHook(hooks, context) {
273
- const hook = hooks?.afterTurn;
274
- if (!hook) return;
275
- await Promise.allSettled([Promise.resolve().then(() => hook(context))]);
276
- }
277
- function normalizeAgentInput(input) {
278
- if (typeof input === "string") return {
279
- type: "user-text",
280
- text: input
281
- };
282
- if (isStringArrayInput(input)) return {
283
- type: "user-text",
284
- text: structuredClone(input)
285
- };
286
- if (isArrayInput(input)) {
287
- assertUserMessageContent(input);
288
- return {
289
- type: "user-message",
290
- content: structuredClone(input)
291
- };
356
+ #expireActiveOverlays(reason) {
357
+ const event = this.#overlays.expireActiveFrame(reason);
358
+ if (!event) return;
359
+ this.#activeRun?.emit(event);
292
360
  }
293
- if (isUserMessage(input)) assertUserMessageContent(input.content);
294
- return structuredClone(input);
295
- }
296
- function isStringArrayInput(input) {
297
- return isArrayInput(input) && input.every((part) => typeof part === "string");
298
- }
299
- function isArrayInput(input) {
300
- return Array.isArray(input);
301
- }
302
- function isUserMessage(input) {
303
- return input.type === "user-message";
304
- }
305
- function assertUserMessageContent(input) {
306
- for (const part of input) if (!isUserMessageContentPart(part)) throw new TypeError("Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.");
307
- }
308
- function isUserMessageContentPart(part) {
309
- if (part === null || typeof part !== "object" || !("type" in part)) return false;
310
- if (part.type === "text") return "text" in part && typeof part.text === "string";
311
- if (part.type === "image") return "image" in part && typeof part.image === "string" && (!("mediaType" in part) || typeof part.mediaType === "string");
312
- if (part.type === "file") return "data" in part && isUserMessageFileData(part.data) && "mediaType" in part && typeof part.mediaType === "string" && (!("filename" in part) || typeof part.filename === "string");
313
- return false;
314
- }
315
- function isUserMessageFileData(data) {
316
- if (typeof data === "string") return true;
317
- if (data === null || typeof data !== "object" || !("type" in data)) return false;
318
- if (data.type === "data") return "data" in data && typeof data.data === "string";
319
- if (data.type === "reference") return "reference" in data && data.reference !== null && typeof data.reference === "object" && Object.values(data.reference).every((value) => typeof value === "string");
320
- if (data.type === "text") return "text" in data && typeof data.text === "string";
321
- if (data.type === "url") return "url" in data && typeof data.url === "string";
322
- return false;
323
- }
361
+ };
324
362
  function errorMessage(error) {
325
363
  if (error instanceof Error) return error.message;
326
364
  return String(error);
327
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
+ }
328
378
  function sessionKilledError() {
329
379
  return /* @__PURE__ */ new Error("Session killed");
330
380
  }
331
- function runtimeInputClosedError(reason) {
332
- return /* @__PURE__ */ new Error(`session.steer() cannot be used after ${reason}`);
333
- }
334
381
  var SessionCommitConflictError = class extends Error {
335
382
  constructor(key) {
336
383
  super(`Session ${JSON.stringify(key)} commit conflict`);
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":["#hooks","#inputQueue","#llm","#persistence","#killed","#ensureLoaded","#drainInputQueue","#activeRuntimeInput","#activeRun","#addSteeringInput","#activeAbort","#closeRuntimeInput","#loaded","#loadPromise","#loadSessionState","#replaceWithStoredSession","#storeVersion","#history","#running","#processQueuedInput","#withSteeringPlacement","#withRuntimeInputWindow","#commitHistory","#drainRuntimeInput","#hooksForRuntimeInput"],"sources":["../../src/session/session.ts"],"sourcesContent":["import { runAgentLoop } from \"../agent-loop\";\nimport type { AgentHooks } from \"../hooks\";\nimport type { Llm } from \"../llm\";\nimport type {\n RuntimeInput,\n UserMessage,\n UserMessageContentPart,\n} from \"./events\";\nimport { ModelMessageHistory } from \"./history\";\nimport type { AgentInput, UserInput } from \"./input\";\nimport type { AgentRun } from \"./run\";\nimport { BufferedAgentRun } from \"./run\";\nimport { decodeStoredSessionSnapshot, encodeSessionSnapshot } 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\ntype RuntimeInputPlacement = RuntimeInput[\"placement\"];\nconst noBoundaryDecision = undefined;\n\ninterface QueuedRuntimeInput {\n readonly input: UserInput;\n readonly placement: RuntimeInputPlacement;\n}\n\ninterface RuntimeInputState {\n closedReason?: string;\n pending: Promise<void>;\n placement?: RuntimeInputPlacement;\n readonly queue: QueuedRuntimeInput[];\n steerPlacement?: RuntimeInputPlacement;\n}\n\nexport class AgentSession {\n readonly #hooks?: AgentHooks;\n readonly #inputQueue: QueuedInput[] = [];\n readonly #llm: Llm;\n readonly #persistence: SessionPersistenceOptions;\n #activeAbort?: AbortController;\n #activeRun?: BufferedAgentRun;\n #activeRuntimeInput?: RuntimeInputState;\n #history = new ModelMessageHistory();\n #killed = false;\n #loadPromise?: Promise<void>;\n #loaded = false;\n #running = false;\n #storeVersion: string | undefined;\n\n constructor(\n llm: Llm,\n persistence: SessionPersistenceOptions,\n hooks?: AgentHooks\n ) {\n this.#hooks = hooks;\n this.#llm = llm;\n this.#persistence = persistence;\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: RuntimeInputState = {\n pending: Promise.resolve(),\n queue: [],\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) {\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 this.#addSteeringInput(runtimeInput, input);\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.#activeAbort?.abort();\n this.#closeRuntimeInput(\n this.#activeRuntimeInput,\n sessionKilledError().message\n );\n\n while (this.#inputQueue.length > 0) {\n const item = this.#inputQueue.shift();\n this.#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 this.#history = new ModelMessageHistory(\n decodeStoredSessionSnapshot(stored)\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 const historySnapshot = this.#history.modelSnapshot();\n\n try {\n await this.#withSteeringPlacement(\n runtimeInput,\n \"turn-start\",\n async () => {\n await this.#hooks?.beforeTurn?.({\n history: this.#history.modelSnapshot(),\n input,\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 runtimeInputAdded = await this.#drainRuntimeInput(\n run,\n runtimeInput,\n event.type\n );\n\n if (event.type === \"step-end\") {\n return { runtimeInputAdded };\n }\n return noBoundaryDecision;\n }\n\n run.emit(event);\n },\n history: this.#history,\n hooks: this.#hooksForRuntimeInput(runtimeInput),\n llm: this.#llm,\n signal: activeAbort.signal,\n });\n\n await this.#commitHistory();\n const terminalEvent = result === \"aborted\" ? \"turn-abort\" : \"turn-end\";\n this.#closeRuntimeInput(runtimeInput, terminalEvent);\n this.#activeRuntimeInput = undefined;\n this.#activeRun = undefined;\n await runAfterTurnHook(this.#hooks, {\n history: this.#history.modelSnapshot(),\n input,\n result,\n signal: activeAbort.signal,\n });\n run.emit({ type: terminalEvent });\n } catch (error) {\n if (error instanceof SessionCommitConflictError) {\n run.emit({ type: \"turn-error\", message: error.message });\n this.#closeRuntimeInput(runtimeInput, \"a session commit conflict\");\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 this.#closeRuntimeInput(runtimeInput, \"turn-error\");\n this.#activeAbort = undefined;\n return;\n }\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n this.#closeRuntimeInput(runtimeInput, \"turn-error\");\n } finally {\n this.#closeRuntimeInput(runtimeInput);\n this.#activeAbort = undefined;\n this.#activeRun = undefined;\n this.#activeRuntimeInput = undefined;\n run.close(undefined, runtimeInput.closedReason);\n }\n }\n\n #addSteeringInput(\n runtimeInput: RuntimeInputState,\n input: AgentInput\n ): Promise<void> {\n const next = runtimeInput.pending.then(() => {\n if (runtimeInput.closedReason) {\n throw runtimeInputClosedError(runtimeInput.closedReason);\n }\n\n runtimeInput.queue.push({\n input: normalizeAgentInput(input),\n placement:\n runtimeInput.steerPlacement ?? runtimeInput.placement ?? \"step-end\",\n });\n });\n runtimeInput.pending = next.catch(() => undefined);\n return next;\n }\n\n #closeRuntimeInput(\n runtimeInput: RuntimeInputState | undefined,\n reason = \"the run reached a terminal state\"\n ): void {\n if (!runtimeInput?.closedReason && runtimeInput) {\n runtimeInput.closedReason = reason;\n runtimeInput.placement = undefined;\n }\n }\n\n async #commitHistory(): Promise<void> {\n const result = await this.#persistence.store.commit(\n this.#persistence.key,\n {\n state: encodeSessionSnapshot(this.#history.modelSnapshot()),\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 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 #hooksForRuntimeInput(\n runtimeInput: RuntimeInputState\n ): AgentHooks | undefined {\n const hooks = this.#hooks;\n if (!hooks) {\n return;\n }\n\n return {\n ...hooks,\n afterStep: (context) =>\n this.#withSteeringPlacement(runtimeInput, \"step-end\", async () => {\n await hooks.afterStep?.(context);\n }),\n beforeStep: (context) =>\n this.#withSteeringPlacement(runtimeInput, \"step-start\", async () => {\n await hooks.beforeStep?.(context);\n }),\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\nfunction shiftRuntimeInput(\n runtimeInput: RuntimeInputState,\n placement: RuntimeInputPlacement\n): QueuedRuntimeInput | undefined {\n const index = runtimeInput.queue.findIndex(\n (input) => input.placement === placement\n );\n if (index === -1) {\n return;\n }\n\n return runtimeInput.queue.splice(index, 1)[0];\n}\n\nasync function runAfterTurnHook(\n hooks: AgentHooks | undefined,\n context: Parameters<NonNullable<AgentHooks[\"afterTurn\"]>>[0]\n): Promise<void> {\n const hook = hooks?.afterTurn;\n if (!hook) {\n return;\n }\n\n await Promise.allSettled([Promise.resolve().then(() => hook(context))]);\n}\n\nexport function normalizeAgentInput(input: AgentInput): UserInput {\n if (typeof input === \"string\") {\n return {\n type: \"user-text\",\n text: input,\n };\n }\n\n if (isStringArrayInput(input)) {\n return {\n type: \"user-text\",\n text: structuredClone(input) as readonly string[],\n };\n }\n\n if (isArrayInput(input)) {\n assertUserMessageContent(input);\n return {\n type: \"user-message\",\n content: structuredClone(input) as readonly UserMessageContentPart[],\n };\n }\n\n if (isUserMessage(input)) {\n assertUserMessageContent(input.content);\n }\n\n return structuredClone(input);\n}\n\nfunction isStringArrayInput(input: AgentInput): input is readonly string[] {\n return isArrayInput(input) && input.every((part) => typeof part === \"string\");\n}\n\nfunction isArrayInput(\n input: AgentInput\n): input is readonly string[] | readonly UserMessageContentPart[] {\n return Array.isArray(input);\n}\n\nfunction isUserMessage(input: UserInput): input is UserMessage {\n return input.type === \"user-message\";\n}\n\nfunction assertUserMessageContent(\n input: readonly unknown[]\n): asserts input is readonly UserMessageContentPart[] {\n for (const part of input) {\n if (!isUserMessageContentPart(part)) {\n throw new TypeError(\n 'Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.'\n );\n }\n }\n}\n\nfunction isUserMessageContentPart(\n part: unknown\n): part is UserMessageContentPart {\n if (part === null || typeof part !== \"object\" || !(\"type\" in part)) {\n return false;\n }\n\n if (part.type === \"text\") {\n return \"text\" in part && typeof part.text === \"string\";\n }\n\n if (part.type === \"image\") {\n return (\n \"image\" in part &&\n typeof part.image === \"string\" &&\n (!(\"mediaType\" in part) || typeof part.mediaType === \"string\")\n );\n }\n\n if (part.type === \"file\") {\n return (\n \"data\" in part &&\n isUserMessageFileData(part.data) &&\n \"mediaType\" in part &&\n typeof part.mediaType === \"string\" &&\n (!(\"filename\" in part) || typeof part.filename === \"string\")\n );\n }\n\n return false;\n}\n\nfunction isUserMessageFileData(data: unknown): boolean {\n if (typeof data === \"string\") {\n return true;\n }\n\n if (data === null || typeof data !== \"object\" || !(\"type\" in data)) {\n return false;\n }\n\n if (data.type === \"data\") {\n return \"data\" in data && typeof data.data === \"string\";\n }\n\n if (data.type === \"reference\") {\n return (\n \"reference\" in data &&\n data.reference !== null &&\n typeof data.reference === \"object\" &&\n Object.values(data.reference).every((value) => typeof value === \"string\")\n );\n }\n\n if (data.type === \"text\") {\n return \"text\" in data && typeof data.text === \"string\";\n }\n\n if (data.type === \"url\") {\n return \"url\" in data && typeof data.url === \"string\";\n }\n\n return false;\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 sessionKilledError(): Error {\n return new Error(\"Session killed\");\n}\n\nfunction runtimeInputClosedError(reason: string): Error {\n return new Error(`session.steer() cannot be used after ${reason}`);\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":["#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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"}
@@ -0,0 +1 @@
1
+ import { ModelMessage } from "ai";
@@ -1,19 +1,45 @@
1
1
  //#region src/session/snapshot.ts
2
- function encodeSessionSnapshot(history) {
2
+ function encodeSessionSnapshot(state) {
3
3
  return {
4
- schemaVersion: 1,
5
- history: structuredClone(history)
4
+ compactions: structuredClone([...state.compactions ?? []]),
5
+ history: structuredClone([...state.history]),
6
+ pluginState: structuredClone({ ...state.pluginState ?? {} }),
7
+ schemaVersion: 2
6
8
  };
7
9
  }
8
10
  function decodeStoredSessionSnapshot(stored) {
9
- if (!stored) return [];
11
+ if (!stored) return emptySnapshotState();
10
12
  const snapshot = stored.state;
11
- if (isSessionSnapshotV1(snapshot)) return structuredClone(snapshot.history);
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
+ };
12
22
  throw new Error("Unsupported stored session state");
13
23
  }
24
+ function emptySnapshotState() {
25
+ return {
26
+ compactions: [],
27
+ history: [],
28
+ pluginState: {}
29
+ };
30
+ }
14
31
  function isSessionSnapshotV1(value) {
15
32
  return value !== null && typeof value === "object" && "schemaVersion" in value && value.schemaVersion === 1 && "history" in value && Array.isArray(value.history);
16
33
  }
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
+ }
17
43
  //#endregion
18
44
  export { decodeStoredSessionSnapshot, encodeSessionSnapshot };
19
45
 
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/session/snapshot.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { StoredSession } from \"./store/types\";\n\nexport interface AgentSessionSnapshotV1 {\n readonly history: ModelMessage[];\n readonly schemaVersion: 1;\n}\n\nexport type AgentSessionSnapshot = AgentSessionSnapshotV1;\n\nexport function encodeSessionSnapshot(\n history: ModelMessage[]\n): AgentSessionSnapshot {\n return { schemaVersion: 1, history: structuredClone(history) };\n}\n\nexport function decodeStoredSessionSnapshot(\n stored: StoredSession | null\n): ModelMessage[] {\n if (!stored) {\n return [];\n }\n\n const snapshot = stored.state;\n if (isSessionSnapshotV1(snapshot)) {\n return structuredClone(snapshot.history);\n }\n\n throw new Error(\"Unsupported stored session state\");\n}\n\nfunction isSessionSnapshotV1(value: unknown): value is AgentSessionSnapshotV1 {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"schemaVersion\" in value &&\n value.schemaVersion === 1 &&\n \"history\" in value &&\n Array.isArray(value.history)\n );\n}\n"],"mappings":";AAUA,SAAgB,sBACd,SACsB;CACtB,OAAO;EAAE,eAAe;EAAG,SAAS,gBAAgB,OAAO;CAAE;AAC/D;AAEA,SAAgB,4BACd,QACgB;CAChB,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,WAAW,OAAO;CACxB,IAAI,oBAAoB,QAAQ,GAC9B,OAAO,gBAAgB,SAAS,OAAO;CAGzC,MAAM,IAAI,MAAM,kCAAkC;AACpD;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/session/snapshot.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { StoredSession } from \"./store/types\";\n\nexport interface AgentSessionSnapshotV1 {\n readonly history: ModelMessage[];\n readonly schemaVersion: 1;\n}\n\nexport interface AgentCompactionOverlay {\n readonly createdAt: string;\n readonly endIndex: number;\n readonly id: string;\n readonly startIndex: number;\n readonly summary: string;\n}\n\nexport interface AgentSessionSnapshotV2 {\n readonly compactions: AgentCompactionOverlay[];\n readonly history: ModelMessage[];\n readonly pluginState: Record<string, unknown>;\n readonly schemaVersion: 2;\n}\n\nexport interface AgentSessionSnapshotState {\n readonly compactions?: readonly AgentCompactionOverlay[];\n readonly history: readonly ModelMessage[];\n readonly pluginState?: Readonly<Record<string, unknown>>;\n}\n\nexport type AgentSessionSnapshot = AgentSessionSnapshotV2;\n\nexport interface DecodedSessionSnapshot {\n readonly compactions: AgentCompactionOverlay[];\n readonly history: ModelMessage[];\n readonly pluginState: Record<string, unknown>;\n}\n\nexport function encodeSessionSnapshot(\n state: AgentSessionSnapshotState\n): AgentSessionSnapshot {\n return {\n compactions: structuredClone([...(state.compactions ?? [])]),\n history: structuredClone([...state.history]),\n pluginState: structuredClone({ ...(state.pluginState ?? {}) }),\n schemaVersion: 2,\n };\n}\n\nexport function decodeStoredSessionSnapshot(\n stored: StoredSession | null\n): DecodedSessionSnapshot {\n if (!stored) {\n return emptySnapshotState();\n }\n\n const snapshot = stored.state;\n if (isSessionSnapshotV1(snapshot)) {\n return {\n ...emptySnapshotState(),\n history: structuredClone(snapshot.history),\n };\n }\n\n if (isSessionSnapshotV2(snapshot)) {\n return {\n compactions: structuredClone(snapshot.compactions),\n history: structuredClone(snapshot.history),\n pluginState: structuredClone(snapshot.pluginState),\n };\n }\n\n throw new Error(\"Unsupported stored session state\");\n}\n\nfunction emptySnapshotState(): DecodedSessionSnapshot {\n return { compactions: [], history: [], pluginState: {} };\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\nfunction isSessionSnapshotV2(value: unknown): value is AgentSessionSnapshotV2 {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"schemaVersion\" in value &&\n value.schemaVersion === 2 &&\n \"history\" in value &&\n Array.isArray(value.history) &&\n \"pluginState\" in value &&\n isRecord(value.pluginState) &&\n \"compactions\" in value &&\n Array.isArray(value.compactions) &&\n value.compactions.every(isCompactionOverlay)\n );\n}\n\nfunction isCompactionOverlay(value: unknown): value is AgentCompactionOverlay {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"createdAt\" in value &&\n typeof value.createdAt === \"string\" &&\n \"endIndex\" in value &&\n typeof value.endIndex === \"number\" &&\n \"id\" in value &&\n typeof value.id === \"string\" &&\n \"startIndex\" in value &&\n typeof value.startIndex === \"number\" &&\n \"summary\" in value &&\n typeof value.summary === \"string\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"mappings":";AAqCA,SAAgB,sBACd,OACsB;CACtB,OAAO;EACL,aAAa,gBAAgB,CAAC,GAAI,MAAM,eAAe,CAAC,CAAE,CAAC;EAC3D,SAAS,gBAAgB,CAAC,GAAG,MAAM,OAAO,CAAC;EAC3C,aAAa,gBAAgB,EAAE,GAAI,MAAM,eAAe,CAAC,EAAG,CAAC;EAC7D,eAAe;CACjB;AACF;AAEA,SAAgB,4BACd,QACwB;CACxB,IAAI,CAAC,QACH,OAAO,mBAAmB;CAG5B,MAAM,WAAW,OAAO;CACxB,IAAI,oBAAoB,QAAQ,GAC9B,OAAO;EACL,GAAG,mBAAmB;EACtB,SAAS,gBAAgB,SAAS,OAAO;CAC3C;CAGF,IAAI,oBAAoB,QAAQ,GAC9B,OAAO;EACL,aAAa,gBAAgB,SAAS,WAAW;EACjD,SAAS,gBAAgB,SAAS,OAAO;EACzC,aAAa,gBAAgB,SAAS,WAAW;CACnD;CAGF,MAAM,IAAI,MAAM,kCAAkC;AACpD;AAEA,SAAS,qBAA6C;CACpD,OAAO;EAAE,aAAa,CAAC;EAAG,SAAS,CAAC;EAAG,aAAa,CAAC;CAAE;AACzD;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO;AAE/B;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,mBAAmB,SACnB,MAAM,kBAAkB,KACxB,aAAa,SACb,MAAM,QAAQ,MAAM,OAAO,KAC3B,iBAAiB,SACjB,SAAS,MAAM,WAAW,KAC1B,iBAAiB,SACjB,MAAM,QAAQ,MAAM,WAAW,KAC/B,MAAM,YAAY,MAAM,mBAAmB;AAE/C;AAEA,SAAS,oBAAoB,OAAiD;CAC5E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,eAAe,SACf,OAAO,MAAM,cAAc,YAC3B,cAAc,SACd,OAAO,MAAM,aAAa,YAC1B,QAAQ,SACR,OAAO,MAAM,OAAO,YACpB,gBAAgB,SAChB,OAAO,MAAM,eAAe,YAC5B,aAAa,SACb,OAAO,MAAM,YAAY;AAE7B;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minpeter/pss-runtime",
3
- "version": "0.0.10",
3
+ "version": "0.1.0-next.0",
4
4
  "description": "Generic agent runtime for sessions, model loops, and synchronized run events.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,6 +11,11 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js"
13
13
  },
14
+ "./plugins": {
15
+ "@minpeter/pss-source": "./src/plugins/index.ts",
16
+ "types": "./dist/plugins/index.d.ts",
17
+ "import": "./dist/plugins/index.js"
18
+ },
14
19
  "./session-store/memory": {
15
20
  "@minpeter/pss-source": "./src/session/store/memory.ts",
16
21
  "types": "./dist/session/store/memory.d.ts",