@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.
Files changed (96) hide show
  1. package/README.md +85 -194
  2. package/dist/agent-loop.js +8 -14
  3. package/dist/agent-loop.js.map +1 -1
  4. package/dist/agent-namespace.js +17 -0
  5. package/dist/agent-namespace.js.map +1 -0
  6. package/dist/agent-validation.js +35 -0
  7. package/dist/agent-validation.js.map +1 -0
  8. package/dist/agent.d.ts +21 -10
  9. package/dist/agent.js +81 -37
  10. package/dist/agent.js.map +1 -1
  11. package/dist/child-session-cleanups.js +61 -0
  12. package/dist/child-session-cleanups.js.map +1 -0
  13. package/dist/hooks.d.ts +32 -0
  14. package/dist/index.d.ts +4 -8
  15. package/dist/index.js +1 -6
  16. package/dist/llm.js +1 -7
  17. package/dist/llm.js.map +1 -1
  18. package/dist/session/events.d.ts +23 -20
  19. package/dist/session/input-normalization.js +66 -0
  20. package/dist/session/input-normalization.js.map +1 -0
  21. package/dist/session/input.d.ts +0 -4
  22. package/dist/session/mapping.js +1 -2
  23. package/dist/session/mapping.js.map +1 -1
  24. package/dist/session/run.js +1 -0
  25. package/dist/session/run.js.map +1 -1
  26. package/dist/session/runtime-input.js +38 -58
  27. package/dist/session/runtime-input.js.map +1 -1
  28. package/dist/session/session-errors.js +23 -0
  29. package/dist/session/session-errors.js.map +1 -0
  30. package/dist/session/session-kill.js +23 -0
  31. package/dist/session/session-kill.js.map +1 -0
  32. package/dist/session/session-runtime-drain.js +22 -0
  33. package/dist/session/session-runtime-drain.js.map +1 -0
  34. package/dist/session/session-state.js +102 -0
  35. package/dist/session/session-state.js.map +1 -0
  36. package/dist/session/session-turn-error.js +35 -0
  37. package/dist/session/session-turn-error.js.map +1 -0
  38. package/dist/session/session.js +103 -285
  39. package/dist/session/session.js.map +1 -1
  40. package/dist/session/snapshot.js +5 -31
  41. package/dist/session/snapshot.js.map +1 -1
  42. package/dist/session/store/file.d.ts +1 -0
  43. package/dist/session/store/file.js +14 -0
  44. package/dist/session/store/file.js.map +1 -1
  45. package/dist/session/store/memory.d.ts +1 -0
  46. package/dist/session/store/memory.js +5 -0
  47. package/dist/session/store/memory.js.map +1 -1
  48. package/dist/session/store/types.d.ts +1 -0
  49. package/dist/subagent-job-cancel.js +28 -0
  50. package/dist/subagent-job-cancel.js.map +1 -0
  51. package/dist/subagent-job-output.js +63 -0
  52. package/dist/subagent-job-output.js.map +1 -0
  53. package/dist/subagent-jobs.js +151 -0
  54. package/dist/subagent-jobs.js.map +1 -0
  55. package/dist/subagent-prompt-schema.js +114 -0
  56. package/dist/subagent-prompt-schema.js.map +1 -0
  57. package/dist/subagent-run.js +111 -0
  58. package/dist/subagent-run.js.map +1 -0
  59. package/dist/subagents.js +92 -0
  60. package/dist/subagents.js.map +1 -0
  61. package/package.json +1 -6
  62. package/dist/plugins/compaction.d.ts +0 -15
  63. package/dist/plugins/compaction.js +0 -98
  64. package/dist/plugins/compaction.js.map +0 -1
  65. package/dist/plugins/index.d.ts +0 -5
  66. package/dist/plugins/index.js +0 -5
  67. package/dist/plugins/memory.d.ts +0 -11
  68. package/dist/plugins/memory.js +0 -146
  69. package/dist/plugins/memory.js.map +0 -1
  70. package/dist/plugins/runner.d.ts +0 -1
  71. package/dist/plugins/runner.js +0 -83
  72. package/dist/plugins/runner.js.map +0 -1
  73. package/dist/plugins/scope.js +0 -13
  74. package/dist/plugins/scope.js.map +0 -1
  75. package/dist/plugins/sessions.d.ts +0 -12
  76. package/dist/plugins/sessions.js +0 -34
  77. package/dist/plugins/sessions.js.map +0 -1
  78. package/dist/plugins/tool-hook-handlers.js +0 -77
  79. package/dist/plugins/tool-hook-handlers.js.map +0 -1
  80. package/dist/plugins/tool-hook-results.js +0 -64
  81. package/dist/plugins/tool-hook-results.js.map +0 -1
  82. package/dist/plugins/tool-hooks.js +0 -111
  83. package/dist/plugins/tool-hooks.js.map +0 -1
  84. package/dist/plugins/types.d.ts +0 -105
  85. package/dist/plugins/types.js +0 -20
  86. package/dist/plugins/types.js.map +0 -1
  87. package/dist/session/lifecycle.d.ts +0 -12
  88. package/dist/session/lifecycle.js +0 -126
  89. package/dist/session/lifecycle.js.map +0 -1
  90. package/dist/session/overlay-anchor.js +0 -151
  91. package/dist/session/overlay-anchor.js.map +0 -1
  92. package/dist/session/overlay.js +0 -141
  93. package/dist/session/overlay.js.map +0 -1
  94. package/dist/session/snapshot.d.ts +0 -1
  95. /package/dist/{agent-loop.d.ts → session/history.d.ts} +0 -0
  96. /package/dist/{plugins/scope.d.ts → session/session-state.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","names":["#events","#closed","#enqueue","#error","#settlePendingAck","#waiter","#eventsStarted","#next","#cancel","#settleQueuedAcks","#deliver","#resultPending","#pendingAck"],"sources":["../../src/session/run.ts"],"sourcesContent":["import type { AgentEvent } from \"./events\";\n\nexport interface AgentRun {\n events(): AsyncIterable<AgentEvent>;\n}\n\ninterface QueuedEvent {\n readonly ack?: () => void;\n readonly event: AgentEvent;\n}\n\ninterface NextWaiter {\n readonly reject: (error: unknown) => void;\n readonly resolve: (value: IteratorResult<AgentEvent>) => void;\n}\n\nexport class BufferedAgentRun implements AgentRun {\n readonly #events: QueuedEvent[] = [];\n #closed = false;\n #error: unknown;\n #pendingAck: (() => void) | undefined;\n #resultPending = false;\n #eventsStarted = false;\n #waiter: NextWaiter | undefined;\n\n emit(event: AgentEvent): void {\n if (this.#closed) {\n return;\n }\n\n this.#enqueue({ event: structuredClone(event) });\n }\n\n emitBoundary(event: AgentEvent): Promise<void> {\n if (this.#closed) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.#enqueue({ ack: resolve, event: structuredClone(event) });\n });\n }\n\n close(error?: unknown, _reason = \"the run is closed\"): void {\n if (this.#closed) {\n return;\n }\n\n this.#closed = true;\n this.#error = error;\n this.#settlePendingAck();\n\n if (!this.#waiter) {\n return;\n }\n\n const waiter = this.#waiter;\n this.#waiter = undefined;\n if (error) {\n waiter.reject(error);\n return;\n }\n waiter.resolve({ done: true, value: undefined });\n }\n\n events(): AsyncIterable<AgentEvent> {\n if (this.#eventsStarted) {\n throw new Error(\"AgentRun.events() can only be consumed once\");\n }\n this.#eventsStarted = true;\n\n const iterator: AsyncIterableIterator<AgentEvent> = {\n next: () => this.#next(),\n return: () => {\n this.#cancel();\n return Promise.resolve({ done: true, value: undefined });\n },\n [Symbol.asyncIterator]: () => iterator,\n };\n return iterator;\n }\n\n #cancel(): void {\n this.#settleQueuedAcks();\n this.#events.length = 0;\n this.close(undefined, \"events return\");\n }\n\n #enqueue(event: QueuedEvent): void {\n const waiter = this.#waiter;\n if (waiter) {\n this.#waiter = undefined;\n this.#deliver(waiter.resolve, event);\n return;\n }\n\n this.#events.push(event);\n }\n\n #next(): Promise<IteratorResult<AgentEvent>> {\n if (this.#resultPending || this.#waiter) {\n return Promise.reject(\n new Error(\"AgentRun.events() does not allow concurrent next() calls\")\n );\n }\n\n this.#settlePendingAck();\n\n const event = this.#events.shift();\n if (event) {\n return new Promise((resolve) => this.#deliver(resolve, event));\n }\n\n if (this.#closed) {\n if (this.#error) {\n return Promise.reject(this.#error);\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n\n return new Promise((resolve, reject) => {\n this.#waiter = { reject, resolve };\n });\n }\n\n #deliver(\n resolve: (value: IteratorResult<AgentEvent>) => void,\n { ack, event }: QueuedEvent\n ): void {\n this.#resultPending = true;\n queueMicrotask(() => {\n this.#resultPending = false;\n });\n this.#pendingAck = ack;\n resolve({ done: false, value: event });\n }\n\n #settlePendingAck(): void {\n const ack = this.#pendingAck;\n this.#pendingAck = undefined;\n ack?.();\n }\n\n #settleQueuedAcks(): void {\n for (const event of this.#events) {\n event.ack?.();\n }\n }\n}\n"],"mappings":";AAgBA,IAAa,mBAAb,MAAkD;CAChD,UAAkC,CAAC;CACnC,UAAU;CACV;CACA;CACA,iBAAiB;CACjB,iBAAiB;CACjB;CAEA,KAAK,OAAyB;EAC5B,IAAI,KAAKC,SACP;EAGF,KAAKC,SAAS,EAAE,OAAO,gBAAgB,KAAK,EAAE,CAAC;CACjD;CAEA,aAAa,OAAkC;EAC7C,IAAI,KAAKD,SACP,OAAO,QAAQ,QAAQ;EAGzB,OAAO,IAAI,SAAS,YAAY;GAC9B,KAAKC,SAAS;IAAE,KAAK;IAAS,OAAO,gBAAgB,KAAK;GAAE,CAAC;EAC/D,CAAC;CACH;CAEA,MAAM,OAAiB,UAAU,qBAA2B;EAC1D,IAAI,KAAKD,SACP;EAGF,KAAKA,UAAU;EACf,KAAKE,SAAS;EACd,KAAKC,kBAAkB;EAEvB,IAAI,CAAC,KAAKC,SACR;EAGF,MAAM,SAAS,KAAKA;EACpB,KAAKA,UAAU,KAAA;EACf,IAAI,OAAO;GACT,OAAO,OAAO,KAAK;GACnB;EACF;EACA,OAAO,QAAQ;GAAE,MAAM;GAAM,OAAO,KAAA;EAAU,CAAC;CACjD;CAEA,SAAoC;EAClC,IAAI,KAAKC,gBACP,MAAM,IAAI,MAAM,6CAA6C;EAE/D,KAAKA,iBAAiB;EAEtB,MAAM,WAA8C;GAClD,YAAY,KAAKC,MAAM;GACvB,cAAc;IACZ,KAAKC,QAAQ;IACb,OAAO,QAAQ,QAAQ;KAAE,MAAM;KAAM,OAAO,KAAA;IAAU,CAAC;GACzD;IACC,OAAO,sBAAsB;EAChC;EACA,OAAO;CACT;CAEA,UAAgB;EACd,KAAKC,kBAAkB;EACvB,KAAKT,QAAQ,SAAS;EACtB,KAAK,MAAM,KAAA,GAAW,eAAe;CACvC;CAEA,SAAS,OAA0B;EACjC,MAAM,SAAS,KAAKK;EACpB,IAAI,QAAQ;GACV,KAAKA,UAAU,KAAA;GACf,KAAKK,SAAS,OAAO,SAAS,KAAK;GACnC;EACF;EAEA,KAAKV,QAAQ,KAAK,KAAK;CACzB;CAEA,QAA6C;EAC3C,IAAI,KAAKW,kBAAkB,KAAKN,SAC9B,OAAO,QAAQ,uBACb,IAAI,MAAM,0DAA0D,CACtE;EAGF,KAAKD,kBAAkB;EAEvB,MAAM,QAAQ,KAAKJ,QAAQ,MAAM;EACjC,IAAI,OACF,OAAO,IAAI,SAAS,YAAY,KAAKU,SAAS,SAAS,KAAK,CAAC;EAG/D,IAAI,KAAKT,SAAS;GAChB,IAAI,KAAKE,QACP,OAAO,QAAQ,OAAO,KAAKA,MAAM;GAEnC,OAAO,QAAQ,QAAQ;IAAE,MAAM;IAAM,OAAO,KAAA;GAAU,CAAC;EACzD;EAEA,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAKE,UAAU;IAAE;IAAQ;GAAQ;EACnC,CAAC;CACH;CAEA,SACE,SACA,EAAE,KAAK,SACD;EACN,KAAKM,iBAAiB;EACtB,qBAAqB;GACnB,KAAKA,iBAAiB;EACxB,CAAC;EACD,KAAKC,cAAc;EACnB,QAAQ;GAAE,MAAM;GAAO,OAAO;EAAM,CAAC;CACvC;CAEA,oBAA0B;EACxB,MAAM,MAAM,KAAKA;EACjB,KAAKA,cAAc,KAAA;EACnB,MAAM;CACR;CAEA,oBAA0B;EACxB,KAAK,MAAM,SAAS,KAAKZ,SACvB,MAAM,MAAM;CAEhB;AACF"}
1
+ {"version":3,"file":"run.js","names":["#events","#closed","#enqueue","#error","#settlePendingAck","#settleQueuedAcks","#waiter","#eventsStarted","#next","#cancel","#deliver","#resultPending","#pendingAck"],"sources":["../../src/session/run.ts"],"sourcesContent":["import type { AgentEvent } from \"./events\";\n\nexport interface AgentRun {\n events(): AsyncIterable<AgentEvent>;\n}\n\ninterface QueuedEvent {\n readonly ack?: () => void;\n readonly event: AgentEvent;\n}\n\ninterface NextWaiter {\n readonly reject: (error: unknown) => void;\n readonly resolve: (value: IteratorResult<AgentEvent>) => void;\n}\n\nexport class BufferedAgentRun implements AgentRun {\n readonly #events: QueuedEvent[] = [];\n #closed = false;\n #error: unknown;\n #pendingAck: (() => void) | undefined;\n #resultPending = false;\n #eventsStarted = false;\n #waiter: NextWaiter | undefined;\n\n emit(event: AgentEvent): void {\n if (this.#closed) {\n return;\n }\n\n this.#enqueue({ event: structuredClone(event) });\n }\n\n emitBoundary(event: AgentEvent): Promise<void> {\n if (this.#closed) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.#enqueue({ ack: resolve, event: structuredClone(event) });\n });\n }\n\n close(error?: unknown, _reason = \"the run is closed\"): void {\n if (this.#closed) {\n return;\n }\n\n this.#closed = true;\n this.#error = error;\n this.#settlePendingAck();\n this.#settleQueuedAcks();\n\n if (!this.#waiter) {\n return;\n }\n\n const waiter = this.#waiter;\n this.#waiter = undefined;\n if (error) {\n waiter.reject(error);\n return;\n }\n waiter.resolve({ done: true, value: undefined });\n }\n\n events(): AsyncIterable<AgentEvent> {\n if (this.#eventsStarted) {\n throw new Error(\"AgentRun.events() can only be consumed once\");\n }\n this.#eventsStarted = true;\n\n const iterator: AsyncIterableIterator<AgentEvent> = {\n next: () => this.#next(),\n return: () => {\n this.#cancel();\n return Promise.resolve({ done: true, value: undefined });\n },\n [Symbol.asyncIterator]: () => iterator,\n };\n return iterator;\n }\n\n #cancel(): void {\n this.#settleQueuedAcks();\n this.#events.length = 0;\n this.close(undefined, \"events return\");\n }\n\n #enqueue(event: QueuedEvent): void {\n const waiter = this.#waiter;\n if (waiter) {\n this.#waiter = undefined;\n this.#deliver(waiter.resolve, event);\n return;\n }\n\n this.#events.push(event);\n }\n\n #next(): Promise<IteratorResult<AgentEvent>> {\n if (this.#resultPending || this.#waiter) {\n return Promise.reject(\n new Error(\"AgentRun.events() does not allow concurrent next() calls\")\n );\n }\n\n this.#settlePendingAck();\n\n const event = this.#events.shift();\n if (event) {\n return new Promise((resolve) => this.#deliver(resolve, event));\n }\n\n if (this.#closed) {\n if (this.#error) {\n return Promise.reject(this.#error);\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n\n return new Promise((resolve, reject) => {\n this.#waiter = { reject, resolve };\n });\n }\n\n #deliver(\n resolve: (value: IteratorResult<AgentEvent>) => void,\n { ack, event }: QueuedEvent\n ): void {\n this.#resultPending = true;\n queueMicrotask(() => {\n this.#resultPending = false;\n });\n this.#pendingAck = ack;\n resolve({ done: false, value: event });\n }\n\n #settlePendingAck(): void {\n const ack = this.#pendingAck;\n this.#pendingAck = undefined;\n ack?.();\n }\n\n #settleQueuedAcks(): void {\n for (const event of this.#events) {\n event.ack?.();\n }\n }\n}\n"],"mappings":";AAgBA,IAAa,mBAAb,MAAkD;CAChD,UAAkC,CAAC;CACnC,UAAU;CACV;CACA;CACA,iBAAiB;CACjB,iBAAiB;CACjB;CAEA,KAAK,OAAyB;EAC5B,IAAI,KAAKC,SACP;EAGF,KAAKC,SAAS,EAAE,OAAO,gBAAgB,KAAK,EAAE,CAAC;CACjD;CAEA,aAAa,OAAkC;EAC7C,IAAI,KAAKD,SACP,OAAO,QAAQ,QAAQ;EAGzB,OAAO,IAAI,SAAS,YAAY;GAC9B,KAAKC,SAAS;IAAE,KAAK;IAAS,OAAO,gBAAgB,KAAK;GAAE,CAAC;EAC/D,CAAC;CACH;CAEA,MAAM,OAAiB,UAAU,qBAA2B;EAC1D,IAAI,KAAKD,SACP;EAGF,KAAKA,UAAU;EACf,KAAKE,SAAS;EACd,KAAKC,kBAAkB;EACvB,KAAKC,kBAAkB;EAEvB,IAAI,CAAC,KAAKC,SACR;EAGF,MAAM,SAAS,KAAKA;EACpB,KAAKA,UAAU,KAAA;EACf,IAAI,OAAO;GACT,OAAO,OAAO,KAAK;GACnB;EACF;EACA,OAAO,QAAQ;GAAE,MAAM;GAAM,OAAO,KAAA;EAAU,CAAC;CACjD;CAEA,SAAoC;EAClC,IAAI,KAAKC,gBACP,MAAM,IAAI,MAAM,6CAA6C;EAE/D,KAAKA,iBAAiB;EAEtB,MAAM,WAA8C;GAClD,YAAY,KAAKC,MAAM;GACvB,cAAc;IACZ,KAAKC,QAAQ;IACb,OAAO,QAAQ,QAAQ;KAAE,MAAM;KAAM,OAAO,KAAA;IAAU,CAAC;GACzD;IACC,OAAO,sBAAsB;EAChC;EACA,OAAO;CACT;CAEA,UAAgB;EACd,KAAKJ,kBAAkB;EACvB,KAAKL,QAAQ,SAAS;EACtB,KAAK,MAAM,KAAA,GAAW,eAAe;CACvC;CAEA,SAAS,OAA0B;EACjC,MAAM,SAAS,KAAKM;EACpB,IAAI,QAAQ;GACV,KAAKA,UAAU,KAAA;GACf,KAAKI,SAAS,OAAO,SAAS,KAAK;GACnC;EACF;EAEA,KAAKV,QAAQ,KAAK,KAAK;CACzB;CAEA,QAA6C;EAC3C,IAAI,KAAKW,kBAAkB,KAAKL,SAC9B,OAAO,QAAQ,uBACb,IAAI,MAAM,0DAA0D,CACtE;EAGF,KAAKF,kBAAkB;EAEvB,MAAM,QAAQ,KAAKJ,QAAQ,MAAM;EACjC,IAAI,OACF,OAAO,IAAI,SAAS,YAAY,KAAKU,SAAS,SAAS,KAAK,CAAC;EAG/D,IAAI,KAAKT,SAAS;GAChB,IAAI,KAAKE,QACP,OAAO,QAAQ,OAAO,KAAKA,MAAM;GAEnC,OAAO,QAAQ,QAAQ;IAAE,MAAM;IAAM,OAAO,KAAA;GAAU,CAAC;EACzD;EAEA,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAKG,UAAU;IAAE;IAAQ;GAAQ;EACnC,CAAC;CACH;CAEA,SACE,SACA,EAAE,KAAK,SACD;EACN,KAAKK,iBAAiB;EACtB,qBAAqB;GACnB,KAAKA,iBAAiB;EACxB,CAAC;EACD,KAAKC,cAAc;EACnB,QAAQ;GAAE,MAAM;GAAO,OAAO;EAAM,CAAC;CACvC;CAEA,oBAA0B;EACxB,MAAM,MAAM,KAAKA;EACjB,KAAKA,cAAc,KAAA;EACnB,MAAM;CACR;CAEA,oBAA0B;EACxB,KAAK,MAAM,SAAS,KAAKZ,SACvB,MAAM,MAAM;CAEhB;AACF"}
@@ -1,11 +1,12 @@
1
+ import { normalizeAgentInput } from "./input-normalization.js";
1
2
  //#region src/session/runtime-input.ts
2
- function createRuntimeInputState() {
3
+ function createRuntimeInputState(queue) {
3
4
  return {
4
5
  pending: Promise.resolve(),
5
- queue: []
6
+ queue
6
7
  };
7
8
  }
8
- function addRuntimeInput(runtimeInput, input) {
9
+ function addSteeringInput(runtimeInput, input) {
9
10
  const next = runtimeInput.pending.then(() => {
10
11
  if (runtimeInput.closedReason) throw runtimeInputClosedError(runtimeInput.closedReason);
11
12
  runtimeInput.queue.push({
@@ -17,73 +18,52 @@ function addRuntimeInput(runtimeInput, input) {
17
18
  return next;
18
19
  }
19
20
  function closeRuntimeInput(runtimeInput, reason = "the run reached a terminal state") {
20
- if (!runtimeInput?.closedReason && runtimeInput) {
21
+ if (runtimeInput && !runtimeInput.closedReason) {
21
22
  runtimeInput.closedReason = reason;
22
23
  runtimeInput.placement = void 0;
23
24
  }
24
25
  }
25
- function shiftRuntimeInput(runtimeInput, placement) {
26
- const index = runtimeInput.queue.findIndex((input) => input.placement === placement);
27
- if (index === -1) return;
28
- return runtimeInput.queue.splice(index, 1)[0];
29
- }
30
- function normalizeAgentInput(input) {
31
- if (typeof input === "string") return {
32
- type: "user-text",
33
- text: input
34
- };
35
- if (isStringArrayInput(input)) return {
36
- type: "user-text",
37
- text: structuredClone(input)
38
- };
39
- if (isArrayInput(input)) {
40
- assertUserMessageContent(input);
41
- return {
42
- type: "user-message",
43
- content: structuredClone(input)
44
- };
45
- }
46
- if (isUserMessage(input)) {
47
- assertUserMessageContent(input.content);
48
- assertUserMessageMetadata(input.metadata);
26
+ async function withRuntimeInputWindow(runtimeInput, placement, callback) {
27
+ const previousSteerPlacement = runtimeInput.steerPlacement;
28
+ runtimeInput.placement = placement;
29
+ runtimeInput.steerPlacement = placement;
30
+ try {
31
+ return await callback();
32
+ } finally {
33
+ runtimeInput.placement = void 0;
34
+ runtimeInput.steerPlacement = previousSteerPlacement;
49
35
  }
50
- return structuredClone(input);
51
- }
52
- function isStringArrayInput(input) {
53
- return isArrayInput(input) && input.every((part) => typeof part === "string");
54
36
  }
55
- function isArrayInput(input) {
56
- return Array.isArray(input);
57
- }
58
- function isUserMessage(input) {
59
- return input.type === "user-message";
60
- }
61
- function assertUserMessageContent(input) {
62
- 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 }.");
63
- }
64
- function assertUserMessageMetadata(metadata) {
65
- if (metadata !== void 0 && (metadata === null || typeof metadata !== "object" || Array.isArray(metadata))) throw new TypeError("Agent input metadata must be an object when provided.");
37
+ async function withSteeringPlacement(runtimeInput, placement, callback) {
38
+ const previousSteerPlacement = runtimeInput.steerPlacement;
39
+ runtimeInput.steerPlacement = placement;
40
+ try {
41
+ return await callback();
42
+ } finally {
43
+ runtimeInput.steerPlacement = previousSteerPlacement;
44
+ }
66
45
  }
67
- function isUserMessageContentPart(part) {
68
- if (part === null || typeof part !== "object" || !("type" in part)) return false;
69
- if (part.type === "text") return "text" in part && typeof part.text === "string";
70
- if (part.type === "image") return "image" in part && typeof part.image === "string" && (!("mediaType" in part) || typeof part.mediaType === "string");
71
- 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");
72
- return false;
46
+ function hooksForRuntimeInput(hooks, runtimeInput) {
47
+ if (!hooks) return;
48
+ return {
49
+ ...hooks,
50
+ afterStep: (context) => withSteeringPlacement(runtimeInput, "step-end", async () => {
51
+ await hooks.afterStep?.(context);
52
+ }),
53
+ beforeStep: (context) => withSteeringPlacement(runtimeInput, "step-start", async () => {
54
+ await hooks.beforeStep?.(context);
55
+ })
56
+ };
73
57
  }
74
- function isUserMessageFileData(data) {
75
- if (typeof data === "string") return true;
76
- if (data === null || typeof data !== "object" || !("type" in data)) return false;
77
- if (data.type === "data") return "data" in data && typeof data.data === "string";
78
- if (data.type === "reference") return "reference" in data && data.reference !== null && typeof data.reference === "object" && Object.values(data.reference).every((value) => typeof value === "string");
79
- if (data.type === "text") return "text" in data && typeof data.text === "string";
80
- if (data.type === "url") return "url" in data && typeof data.url === "string";
81
- return false;
58
+ function shiftRuntimeInput(runtimeInput, placement) {
59
+ const index = runtimeInput.queue.findIndex((input) => input.placement === placement);
60
+ if (index === -1) return;
61
+ return runtimeInput.queue.splice(index, 1)[0];
82
62
  }
83
63
  function runtimeInputClosedError(reason) {
84
64
  return /* @__PURE__ */ new Error(`session.steer() cannot be used after ${reason}`);
85
65
  }
86
66
  //#endregion
87
- export { addRuntimeInput, closeRuntimeInput, createRuntimeInputState, normalizeAgentInput, shiftRuntimeInput };
67
+ export { addSteeringInput, closeRuntimeInput, createRuntimeInputState, hooksForRuntimeInput, shiftRuntimeInput, withRuntimeInputWindow, withSteeringPlacement };
88
68
 
89
69
  //# sourceMappingURL=runtime-input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-input.js","names":[],"sources":["../../src/session/runtime-input.ts"],"sourcesContent":["import type {\n RuntimeInput,\n UserMessage,\n UserMessageContentPart,\n} from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\n\nexport type RuntimeInputPlacement = RuntimeInput[\"placement\"];\n\nexport interface QueuedRuntimeInput {\n readonly input: UserInput;\n readonly placement: RuntimeInputPlacement;\n}\n\nexport interface RuntimeInputState {\n closedReason?: string;\n pending: Promise<void>;\n placement?: RuntimeInputPlacement;\n readonly queue: QueuedRuntimeInput[];\n steerPlacement?: RuntimeInputPlacement;\n}\n\nexport function createRuntimeInputState(): RuntimeInputState {\n return {\n pending: Promise.resolve(),\n queue: [],\n };\n}\n\nexport function addRuntimeInput(\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\nexport function 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\nexport function 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\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 assertUserMessageMetadata(input.metadata);\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 assertUserMessageMetadata(metadata: unknown): void {\n if (\n metadata !== undefined &&\n (metadata === null ||\n typeof metadata !== \"object\" ||\n Array.isArray(metadata))\n ) {\n throw new TypeError(\n \"Agent input metadata must be an object when provided.\"\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 runtimeInputClosedError(reason: string): Error {\n return new Error(`session.steer() cannot be used after ${reason}`);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runtime-input.js","names":[],"sources":["../../src/session/runtime-input.ts"],"sourcesContent":["import type { AgentHooks } from \"../hooks\";\nimport type { RuntimeInput } from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\nimport { normalizeAgentInput } from \"./input-normalization\";\nimport type { BufferedAgentRun } from \"./run\";\n\nexport type RuntimeInputPlacement = RuntimeInput[\"placement\"];\n\nexport interface QueuedRuntimeInput {\n readonly input: UserInput;\n readonly placement: RuntimeInputPlacement;\n}\n\nexport interface RuntimeInputState {\n closedReason?: string;\n pending: Promise<void>;\n placement?: RuntimeInputPlacement;\n readonly queue: QueuedRuntimeInput[];\n steerPlacement?: RuntimeInputPlacement;\n}\n\nexport interface QueuedInput {\n readonly input: UserInput;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n}\n\nexport function createRuntimeInputState(\n queue: QueuedRuntimeInput[]\n): RuntimeInputState {\n return {\n pending: Promise.resolve(),\n queue,\n };\n}\n\nexport function 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\nexport function closeRuntimeInput(\n runtimeInput: RuntimeInputState | undefined,\n reason = \"the run reached a terminal state\"\n): void {\n if (runtimeInput && !runtimeInput.closedReason) {\n runtimeInput.closedReason = reason;\n runtimeInput.placement = undefined;\n }\n}\n\nexport async function 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\nexport async function 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\nexport function hooksForRuntimeInput(\n hooks: AgentHooks | undefined,\n runtimeInput: RuntimeInputState\n): AgentHooks | undefined {\n if (!hooks) {\n return;\n }\n\n return {\n ...hooks,\n afterStep: (context) =>\n withSteeringPlacement(runtimeInput, \"step-end\", async () => {\n await hooks.afterStep?.(context);\n }),\n beforeStep: (context) =>\n withSteeringPlacement(runtimeInput, \"step-start\", async () => {\n await hooks.beforeStep?.(context);\n }),\n };\n}\n\nexport function 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\nfunction runtimeInputClosedError(reason: string): Error {\n return new Error(`session.steer() cannot be used after ${reason}`);\n}\n"],"mappings":";;AA2BA,SAAgB,wBACd,OACmB;CACnB,OAAO;EACL,SAAS,QAAQ,QAAQ;EACzB;CACF;AACF;AAEA,SAAgB,iBACd,cACA,OACe;CACf,MAAM,OAAO,aAAa,QAAQ,WAAW;EAC3C,IAAI,aAAa,cACf,MAAM,wBAAwB,aAAa,YAAY;EAGzD,aAAa,MAAM,KAAK;GACtB,OAAO,oBAAoB,KAAK;GAChC,WACE,aAAa,kBAAkB,aAAa,aAAa;EAC7D,CAAC;CACH,CAAC;CACD,aAAa,UAAU,KAAK,YAAY,KAAA,CAAS;CACjD,OAAO;AACT;AAEA,SAAgB,kBACd,cACA,SAAS,oCACH;CACN,IAAI,gBAAgB,CAAC,aAAa,cAAc;EAC9C,aAAa,eAAe;EAC5B,aAAa,YAAY,KAAA;CAC3B;AACF;AAEA,eAAsB,uBACpB,cACA,WACA,UACY;CACZ,MAAM,yBAAyB,aAAa;CAC5C,aAAa,YAAY;CACzB,aAAa,iBAAiB;CAC9B,IAAI;EACF,OAAO,MAAM,SAAS;CACxB,UAAU;EACR,aAAa,YAAY,KAAA;EACzB,aAAa,iBAAiB;CAChC;AACF;AAEA,eAAsB,sBACpB,cACA,WACA,UACY;CACZ,MAAM,yBAAyB,aAAa;CAC5C,aAAa,iBAAiB;CAC9B,IAAI;EACF,OAAO,MAAM,SAAS;CACxB,UAAU;EACR,aAAa,iBAAiB;CAChC;AACF;AAEA,SAAgB,qBACd,OACA,cACwB;CACxB,IAAI,CAAC,OACH;CAGF,OAAO;EACL,GAAG;EACH,YAAY,YACV,sBAAsB,cAAc,YAAY,YAAY;GAC1D,MAAM,MAAM,YAAY,OAAO;EACjC,CAAC;EACH,aAAa,YACX,sBAAsB,cAAc,cAAc,YAAY;GAC5D,MAAM,MAAM,aAAa,OAAO;EAClC,CAAC;CACL;AACF;AAEA,SAAgB,kBACd,cACA,WACgC;CAChC,MAAM,QAAQ,aAAa,MAAM,WAC9B,UAAU,MAAM,cAAc,SACjC;CACA,IAAI,UAAU,IACZ;CAGF,OAAO,aAAa,MAAM,OAAO,OAAO,CAAC,EAAE;AAC7C;AAEA,SAAS,wBAAwB,QAAuB;CACtD,uBAAO,IAAI,MAAM,wCAAwC,QAAQ;AACnE"}
@@ -0,0 +1,23 @@
1
+ //#region src/session/session-errors.ts
2
+ async function runAfterTurnHook(hooks, context) {
3
+ const hook = hooks?.afterTurn;
4
+ if (!hook) return;
5
+ await Promise.allSettled([Promise.resolve().then(() => hook(context))]);
6
+ }
7
+ function errorMessage(error) {
8
+ if (error instanceof Error) return error.message;
9
+ return String(error);
10
+ }
11
+ function sessionKilledError() {
12
+ return /* @__PURE__ */ new Error("Session killed");
13
+ }
14
+ function sessionDeleteInProgressError() {
15
+ return /* @__PURE__ */ new Error("Session delete in progress");
16
+ }
17
+ function sessionTerminalError(killed) {
18
+ return killed ? sessionKilledError() : sessionDeleteInProgressError();
19
+ }
20
+ //#endregion
21
+ export { errorMessage, runAfterTurnHook, sessionKilledError, sessionTerminalError };
22
+
23
+ //# sourceMappingURL=session-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-errors.js","names":[],"sources":["../../src/session/session-errors.ts"],"sourcesContent":["import type { AgentHooks } from \"../hooks\";\n\nexport async 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 errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\nexport function sessionKilledError(): Error {\n return new Error(\"Session killed\");\n}\n\nexport function sessionDeleteInProgressError(): Error {\n return new Error(\"Session delete in progress\");\n}\n\nexport function sessionTerminalError(killed: boolean): Error {\n return killed ? sessionKilledError() : sessionDeleteInProgressError();\n}\n"],"mappings":";AAEA,eAAsB,iBACpB,OACA,SACe;CACf,MAAM,OAAO,OAAO;CACpB,IAAI,CAAC,MACH;CAGF,MAAM,QAAQ,WAAW,CAAC,QAAQ,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;AACxE;AAEA,SAAgB,aAAa,OAAwB;CACnD,IAAI,iBAAiB,OACnB,OAAO,MAAM;CAGf,OAAO,OAAO,KAAK;AACrB;AAEA,SAAgB,qBAA4B;CAC1C,uBAAO,IAAI,MAAM,gBAAgB;AACnC;AAEA,SAAgB,+BAAsC;CACpD,uBAAO,IAAI,MAAM,4BAA4B;AAC/C;AAEA,SAAgB,qBAAqB,QAAwB;CAC3D,OAAO,SAAS,mBAAmB,IAAI,6BAA6B;AACtE"}
@@ -0,0 +1,23 @@
1
+ import { closeRuntimeInput } from "./runtime-input.js";
2
+ //#region src/session/session-kill.ts
3
+ function closeKilledRuntimeInputs({ activeRuntimeInput, inputQueue, message, runToClose }) {
4
+ closeRuntimeInput(activeRuntimeInput, message);
5
+ runToClose?.emit({
6
+ type: "turn-error",
7
+ message
8
+ });
9
+ runToClose?.close(void 0, message);
10
+ while (inputQueue.length > 0) {
11
+ const item = inputQueue.shift();
12
+ closeRuntimeInput(item?.runtimeInput, message);
13
+ item?.run.emit({
14
+ type: "turn-error",
15
+ message
16
+ });
17
+ item?.run.close(void 0, message);
18
+ }
19
+ }
20
+ //#endregion
21
+ export { closeKilledRuntimeInputs };
22
+
23
+ //# sourceMappingURL=session-kill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-kill.js","names":[],"sources":["../../src/session/session-kill.ts"],"sourcesContent":["import type { BufferedAgentRun } from \"./run\";\nimport {\n closeRuntimeInput,\n type QueuedInput,\n type RuntimeInputState,\n} from \"./runtime-input\";\n\ninterface CloseKilledRuntimeInputsOptions {\n readonly activeRuntimeInput: RuntimeInputState | undefined;\n readonly inputQueue: QueuedInput[];\n readonly message: string;\n readonly runToClose: BufferedAgentRun | undefined;\n}\n\nexport function closeKilledRuntimeInputs({\n activeRuntimeInput,\n inputQueue,\n message,\n runToClose,\n}: CloseKilledRuntimeInputsOptions): void {\n closeRuntimeInput(activeRuntimeInput, message);\n runToClose?.emit({ type: \"turn-error\", message });\n runToClose?.close(undefined, message);\n\n while (inputQueue.length > 0) {\n const item = inputQueue.shift();\n closeRuntimeInput(item?.runtimeInput, message);\n item?.run.emit({ type: \"turn-error\", message });\n item?.run.close(undefined, message);\n }\n}\n"],"mappings":";;AAcA,SAAgB,yBAAyB,EACvC,oBACA,YACA,SACA,cACwC;CACxC,kBAAkB,oBAAoB,OAAO;CAC7C,YAAY,KAAK;EAAE,MAAM;EAAc;CAAQ,CAAC;CAChD,YAAY,MAAM,KAAA,GAAW,OAAO;CAEpC,OAAO,WAAW,SAAS,GAAG;EAC5B,MAAM,OAAO,WAAW,MAAM;EAC9B,kBAAkB,MAAM,cAAc,OAAO;EAC7C,MAAM,IAAI,KAAK;GAAE,MAAM;GAAc;EAAQ,CAAC;EAC9C,MAAM,IAAI,MAAM,KAAA,GAAW,OAAO;CACpC;AACF"}
@@ -0,0 +1,22 @@
1
+ import { shiftRuntimeInput } from "./runtime-input.js";
2
+ //#region src/session/session-runtime-drain.ts
3
+ async function drainRuntimeInput({ placement, run, runtimeInput, state }) {
4
+ let added = false;
5
+ let next = shiftRuntimeInput(runtimeInput, placement);
6
+ while (next) {
7
+ added = true;
8
+ run.emit({
9
+ type: "runtime-input",
10
+ input: next.input,
11
+ placement
12
+ });
13
+ state.appendUserInput(next.input);
14
+ await state.commit();
15
+ next = shiftRuntimeInput(runtimeInput, placement);
16
+ }
17
+ return added;
18
+ }
19
+ //#endregion
20
+ export { drainRuntimeInput };
21
+
22
+ //# sourceMappingURL=session-runtime-drain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-runtime-drain.js","names":[],"sources":["../../src/session/session-runtime-drain.ts"],"sourcesContent":["import type { BufferedAgentRun } from \"./run\";\nimport {\n type RuntimeInputPlacement,\n type RuntimeInputState,\n shiftRuntimeInput,\n} from \"./runtime-input\";\nimport type { SessionState } from \"./session-state\";\n\nexport async function drainRuntimeInput({\n placement,\n run,\n runtimeInput,\n state,\n}: {\n readonly placement: RuntimeInputPlacement;\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n readonly state: SessionState;\n}): Promise<boolean> {\n let added = false;\n let next = shiftRuntimeInput(runtimeInput, placement);\n while (next) {\n added = true;\n run.emit({ type: \"runtime-input\", input: next.input, placement });\n state.appendUserInput(next.input);\n await state.commit();\n next = shiftRuntimeInput(runtimeInput, placement);\n }\n\n return added;\n}\n"],"mappings":";;AAQA,eAAsB,kBAAkB,EACtC,WACA,KACA,cACA,SAMmB;CACnB,IAAI,QAAQ;CACZ,IAAI,OAAO,kBAAkB,cAAc,SAAS;CACpD,OAAO,MAAM;EACX,QAAQ;EACR,IAAI,KAAK;GAAE,MAAM;GAAiB,OAAO,KAAK;GAAO;EAAU,CAAC;EAChE,MAAM,gBAAgB,KAAK,KAAK;EAChC,MAAM,MAAM,OAAO;EACnB,OAAO,kBAAkB,cAAc,SAAS;CAClD;CAEA,OAAO;AACT"}
@@ -0,0 +1,102 @@
1
+ import { ModelMessageHistory } from "./history.js";
2
+ import { decodeStoredSessionSnapshot, encodeSessionSnapshot } from "./snapshot.js";
3
+ //#region src/session/session-state.ts
4
+ var SessionCommitConflictError = class extends Error {
5
+ constructor(key) {
6
+ super(`Session ${JSON.stringify(key)} commit conflict`);
7
+ }
8
+ };
9
+ var SessionState = class {
10
+ #persistence;
11
+ #deleteRequested = false;
12
+ #history = new ModelMessageHistory();
13
+ #deleted = false;
14
+ #loadPromise;
15
+ #loaded = false;
16
+ #storeVersion;
17
+ #writeQueue = Promise.resolve();
18
+ constructor(persistence) {
19
+ this.#persistence = persistence;
20
+ }
21
+ get history() {
22
+ return this.#history;
23
+ }
24
+ async ensureLoaded() {
25
+ if (this.#deleteRequested || this.#deleted) return;
26
+ if (this.#loaded) return;
27
+ this.#loadPromise ??= this.#loadSessionState();
28
+ try {
29
+ await this.#loadPromise;
30
+ } catch (error) {
31
+ this.#loadPromise = void 0;
32
+ throw error;
33
+ }
34
+ }
35
+ modelSnapshot() {
36
+ return this.#history.modelSnapshot();
37
+ }
38
+ appendUserInput(input) {
39
+ this.#history.appendUserInput(input);
40
+ }
41
+ rollback(snapshot) {
42
+ this.#history.rollback(snapshot);
43
+ }
44
+ async commit() {
45
+ if (this.#deleteRequested || this.#deleted) return;
46
+ const snapshot = this.#history.modelSnapshot();
47
+ await this.#enqueueWrite(async () => {
48
+ if (this.#deleteRequested || this.#deleted) return;
49
+ const result = await this.#persistence.store.commit(this.#persistence.key, { state: encodeSessionSnapshot(snapshot) }, { expectedVersion: this.#storeVersion ?? null });
50
+ if (!result.ok) {
51
+ await this.#replaceWithStoredSession();
52
+ throw new SessionCommitConflictError(this.#persistence.key);
53
+ }
54
+ this.#storeVersion = result.version;
55
+ });
56
+ }
57
+ async delete() {
58
+ if (this.#deleted) return;
59
+ const previous = {
60
+ history: this.#history.modelSnapshot(),
61
+ loaded: this.#loaded,
62
+ storeVersion: this.#storeVersion
63
+ };
64
+ this.#deleteRequested = true;
65
+ this.#loadPromise = void 0;
66
+ await this.#enqueueWrite(async () => {
67
+ try {
68
+ await this.#persistence.store.delete(this.#persistence.key);
69
+ } catch (error) {
70
+ this.#deleteRequested = false;
71
+ this.#loaded = previous.loaded;
72
+ this.#storeVersion = previous.storeVersion;
73
+ this.#history = new ModelMessageHistory(previous.history);
74
+ throw error;
75
+ }
76
+ this.#deleted = true;
77
+ this.#loadPromise = void 0;
78
+ this.#loaded = true;
79
+ this.#storeVersion = void 0;
80
+ this.#history = new ModelMessageHistory();
81
+ });
82
+ }
83
+ #enqueueWrite(operation) {
84
+ const next = this.#writeQueue.then(operation, operation);
85
+ this.#writeQueue = next.catch(() => void 0);
86
+ return next;
87
+ }
88
+ async #loadSessionState() {
89
+ if (this.#loaded) return;
90
+ await this.#replaceWithStoredSession();
91
+ this.#loaded = true;
92
+ }
93
+ async #replaceWithStoredSession() {
94
+ const stored = await this.#persistence.store.load(this.#persistence.key);
95
+ this.#storeVersion = stored?.version;
96
+ this.#history = new ModelMessageHistory(decodeStoredSessionSnapshot(stored));
97
+ }
98
+ };
99
+ //#endregion
100
+ export { SessionCommitConflictError, SessionState };
101
+
102
+ //# sourceMappingURL=session-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-state.js","names":["#persistence","#history","#deleteRequested","#deleted","#loaded","#loadPromise","#loadSessionState","#enqueueWrite","#storeVersion","#replaceWithStoredSession","#writeQueue"],"sources":["../../src/session/session-state.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport { ModelMessageHistory } from \"./history\";\nimport { decodeStoredSessionSnapshot, encodeSessionSnapshot } from \"./snapshot\";\nimport type { SessionStore } from \"./store/types\";\n\nexport interface SessionPersistenceOptions {\n readonly key: string;\n readonly store: SessionStore;\n}\n\nexport class SessionCommitConflictError extends Error {\n constructor(key: string) {\n super(`Session ${JSON.stringify(key)} commit conflict`);\n }\n}\n\nexport class SessionState {\n readonly #persistence: SessionPersistenceOptions;\n #deleteRequested = false;\n #history = new ModelMessageHistory();\n #deleted = false;\n #loadPromise?: Promise<void>;\n #loaded = false;\n #storeVersion: string | undefined;\n #writeQueue: Promise<void> = Promise.resolve();\n\n constructor(persistence: SessionPersistenceOptions) {\n this.#persistence = persistence;\n }\n\n get history(): ModelMessageHistory {\n return this.#history;\n }\n\n async ensureLoaded(): Promise<void> {\n if (this.#deleteRequested || this.#deleted) {\n return;\n }\n\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 modelSnapshot(): ModelMessage[] {\n return this.#history.modelSnapshot();\n }\n\n appendUserInput(\n input: Parameters<ModelMessageHistory[\"appendUserInput\"]>[0]\n ) {\n this.#history.appendUserInput(input);\n }\n\n rollback(snapshot: ModelMessage[]): void {\n this.#history.rollback(snapshot);\n }\n\n async commit(): Promise<void> {\n if (this.#deleteRequested || this.#deleted) {\n return;\n }\n\n const snapshot = this.#history.modelSnapshot();\n await this.#enqueueWrite(async () => {\n if (this.#deleteRequested || this.#deleted) {\n return;\n }\n\n const result = await this.#persistence.store.commit(\n this.#persistence.key,\n { state: encodeSessionSnapshot(snapshot) },\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\n async delete(): Promise<void> {\n if (this.#deleted) {\n return;\n }\n\n const previous = {\n history: this.#history.modelSnapshot(),\n loaded: this.#loaded,\n storeVersion: this.#storeVersion,\n };\n this.#deleteRequested = true;\n this.#loadPromise = undefined;\n\n await this.#enqueueWrite(async () => {\n try {\n await this.#persistence.store.delete(this.#persistence.key);\n } catch (error) {\n this.#deleteRequested = false;\n this.#loaded = previous.loaded;\n this.#storeVersion = previous.storeVersion;\n this.#history = new ModelMessageHistory(previous.history);\n throw error;\n }\n\n this.#deleted = true;\n this.#loadPromise = undefined;\n this.#loaded = true;\n this.#storeVersion = undefined;\n this.#history = new ModelMessageHistory();\n });\n }\n\n #enqueueWrite(operation: () => Promise<void>): Promise<void> {\n const next = this.#writeQueue.then(operation, operation);\n this.#writeQueue = next.catch(() => undefined);\n return next;\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"],"mappings":";;;AAUA,IAAa,6BAAb,cAAgD,MAAM;CACpD,YAAY,KAAa;EACvB,MAAM,WAAW,KAAK,UAAU,GAAG,EAAE,iBAAiB;CACxD;AACF;AAEA,IAAa,eAAb,MAA0B;CACxB;CACA,mBAAmB;CACnB,WAAW,IAAI,oBAAoB;CACnC,WAAW;CACX;CACA,UAAU;CACV;CACA,cAA6B,QAAQ,QAAQ;CAE7C,YAAY,aAAwC;EAClD,KAAKA,eAAe;CACtB;CAEA,IAAI,UAA+B;EACjC,OAAO,KAAKC;CACd;CAEA,MAAM,eAA8B;EAClC,IAAI,KAAKC,oBAAoB,KAAKC,UAChC;EAGF,IAAI,KAAKC,SACP;EAGF,KAAKC,iBAAiB,KAAKC,kBAAkB;EAC7C,IAAI;GACF,MAAM,KAAKD;EACb,SAAS,OAAO;GACd,KAAKA,eAAe,KAAA;GACpB,MAAM;EACR;CACF;CAEA,gBAAgC;EAC9B,OAAO,KAAKJ,SAAS,cAAc;CACrC;CAEA,gBACE,OACA;EACA,KAAKA,SAAS,gBAAgB,KAAK;CACrC;CAEA,SAAS,UAAgC;EACvC,KAAKA,SAAS,SAAS,QAAQ;CACjC;CAEA,MAAM,SAAwB;EAC5B,IAAI,KAAKC,oBAAoB,KAAKC,UAChC;EAGF,MAAM,WAAW,KAAKF,SAAS,cAAc;EAC7C,MAAM,KAAKM,cAAc,YAAY;GACnC,IAAI,KAAKL,oBAAoB,KAAKC,UAChC;GAGF,MAAM,SAAS,MAAM,KAAKH,aAAa,MAAM,OAC3C,KAAKA,aAAa,KAClB,EAAE,OAAO,sBAAsB,QAAQ,EAAE,GACzC,EAAE,iBAAiB,KAAKQ,iBAAiB,KAAK,CAChD;GAEA,IAAI,CAAC,OAAO,IAAI;IACd,MAAM,KAAKC,0BAA0B;IACrC,MAAM,IAAI,2BAA2B,KAAKT,aAAa,GAAG;GAC5D;GAEA,KAAKQ,gBAAgB,OAAO;EAC9B,CAAC;CACH;CAEA,MAAM,SAAwB;EAC5B,IAAI,KAAKL,UACP;EAGF,MAAM,WAAW;GACf,SAAS,KAAKF,SAAS,cAAc;GACrC,QAAQ,KAAKG;GACb,cAAc,KAAKI;EACrB;EACA,KAAKN,mBAAmB;EACxB,KAAKG,eAAe,KAAA;EAEpB,MAAM,KAAKE,cAAc,YAAY;GACnC,IAAI;IACF,MAAM,KAAKP,aAAa,MAAM,OAAO,KAAKA,aAAa,GAAG;GAC5D,SAAS,OAAO;IACd,KAAKE,mBAAmB;IACxB,KAAKE,UAAU,SAAS;IACxB,KAAKI,gBAAgB,SAAS;IAC9B,KAAKP,WAAW,IAAI,oBAAoB,SAAS,OAAO;IACxD,MAAM;GACR;GAEA,KAAKE,WAAW;GAChB,KAAKE,eAAe,KAAA;GACpB,KAAKD,UAAU;GACf,KAAKI,gBAAgB,KAAA;GACrB,KAAKP,WAAW,IAAI,oBAAoB;EAC1C,CAAC;CACH;CAEA,cAAc,WAA+C;EAC3D,MAAM,OAAO,KAAKS,YAAY,KAAK,WAAW,SAAS;EACvD,KAAKA,cAAc,KAAK,YAAY,KAAA,CAAS;EAC7C,OAAO;CACT;CAEA,MAAMJ,oBAAmC;EACvC,IAAI,KAAKF,SACP;EAGF,MAAM,KAAKK,0BAA0B;EACrC,KAAKL,UAAU;CACjB;CAEA,MAAMK,4BAA2C;EAC/C,MAAM,SAAS,MAAM,KAAKT,aAAa,MAAM,KAAK,KAAKA,aAAa,GAAG;EACvE,KAAKQ,gBAAgB,QAAQ;EAC7B,KAAKP,WAAW,IAAI,oBAClB,4BAA4B,MAAM,CACpC;CACF;AACF"}
@@ -0,0 +1,35 @@
1
+ import { closeRuntimeInput } from "./runtime-input.js";
2
+ import { errorMessage } from "./session-errors.js";
3
+ import { SessionCommitConflictError } from "./session-state.js";
4
+ //#region src/session/session-turn-error.ts
5
+ async function emitTurnErrorAfterRecovery({ error, historySnapshot, run, runtimeInput, state }) {
6
+ if (error instanceof SessionCommitConflictError) {
7
+ run.emit({
8
+ type: "turn-error",
9
+ message: error.message
10
+ });
11
+ closeRuntimeInput(runtimeInput, "a session commit conflict");
12
+ return;
13
+ }
14
+ state.rollback(historySnapshot);
15
+ try {
16
+ await state.commit();
17
+ } catch (rollbackError) {
18
+ const rollbackMessage = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
19
+ run.emit({
20
+ type: "turn-error",
21
+ message: `${errorMessage(error)}; history rollback persistence failed: ${rollbackMessage}`
22
+ });
23
+ closeRuntimeInput(runtimeInput, "turn-error");
24
+ return;
25
+ }
26
+ run.emit({
27
+ type: "turn-error",
28
+ message: errorMessage(error)
29
+ });
30
+ closeRuntimeInput(runtimeInput, "turn-error");
31
+ }
32
+ //#endregion
33
+ export { emitTurnErrorAfterRecovery };
34
+
35
+ //# sourceMappingURL=session-turn-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-turn-error.js","names":[],"sources":["../../src/session/session-turn-error.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\nimport type { BufferedAgentRun } from \"./run\";\nimport { closeRuntimeInput, type RuntimeInputState } from \"./runtime-input\";\nimport { errorMessage } from \"./session-errors\";\nimport { SessionCommitConflictError, type SessionState } from \"./session-state\";\n\nexport async function emitTurnErrorAfterRecovery({\n error,\n historySnapshot,\n run,\n runtimeInput,\n state,\n}: {\n readonly error: unknown;\n readonly historySnapshot: ModelMessage[];\n readonly run: BufferedAgentRun;\n readonly runtimeInput: RuntimeInputState;\n readonly state: SessionState;\n}): Promise<void> {\n if (error instanceof SessionCommitConflictError) {\n run.emit({ type: \"turn-error\", message: error.message });\n closeRuntimeInput(runtimeInput, \"a session commit conflict\");\n return;\n }\n\n state.rollback(historySnapshot);\n try {\n await state.commit();\n } catch (rollbackError) {\n const rollbackMessage =\n rollbackError instanceof Error\n ? rollbackError.message\n : String(rollbackError);\n run.emit({\n type: \"turn-error\",\n message: `${errorMessage(error)}; history rollback persistence failed: ${rollbackMessage}`,\n });\n closeRuntimeInput(runtimeInput, \"turn-error\");\n return;\n }\n\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n closeRuntimeInput(runtimeInput, \"turn-error\");\n}\n"],"mappings":";;;;AAMA,eAAsB,2BAA2B,EAC/C,OACA,iBACA,KACA,cACA,SAOgB;CAChB,IAAI,iBAAiB,4BAA4B;EAC/C,IAAI,KAAK;GAAE,MAAM;GAAc,SAAS,MAAM;EAAQ,CAAC;EACvD,kBAAkB,cAAc,2BAA2B;EAC3D;CACF;CAEA,MAAM,SAAS,eAAe;CAC9B,IAAI;EACF,MAAM,MAAM,OAAO;CACrB,SAAS,eAAe;EACtB,MAAM,kBACJ,yBAAyB,QACrB,cAAc,UACd,OAAO,aAAa;EAC1B,IAAI,KAAK;GACP,MAAM;GACN,SAAS,GAAG,aAAa,KAAK,EAAE,yCAAyC;EAC3E,CAAC;EACD,kBAAkB,cAAc,YAAY;EAC5C;CACF;CAEA,IAAI,KAAK;EAAE,MAAM;EAAc,SAAS,aAAa,KAAK;CAAE,CAAC;CAC7D,kBAAkB,cAAc,YAAY;AAC9C"}