@minpeter/pss-runtime 0.1.0-next.1 → 0.1.0-next.3

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 (133) hide show
  1. package/README.md +290 -61
  2. package/dist/agent-host-session-store.js +10 -0
  3. package/dist/agent-host-session-store.js.map +1 -0
  4. package/dist/agent-loop.js +57 -28
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/agent-namespace.js +6 -3
  7. package/dist/agent-namespace.js.map +1 -1
  8. package/dist/agent-options.d.ts +29 -0
  9. package/dist/agent-options.js +16 -0
  10. package/dist/agent-options.js.map +1 -0
  11. package/dist/agent-resume.js +63 -0
  12. package/dist/agent-resume.js.map +1 -0
  13. package/dist/agent-session-entry.d.ts +13 -0
  14. package/dist/agent.d.ts +8 -44
  15. package/dist/agent.js +61 -83
  16. package/dist/agent.js.map +1 -1
  17. package/dist/cloudflare/cloudflare-agent-context.d.ts +40 -0
  18. package/dist/cloudflare/cloudflare-agent-context.js +37 -0
  19. package/dist/cloudflare/cloudflare-agent-context.js.map +1 -0
  20. package/dist/cloudflare/cloudflare-alarm-budget.d.ts +18 -0
  21. package/dist/cloudflare/cloudflare-alarm-budget.js +77 -0
  22. package/dist/cloudflare/cloudflare-alarm-budget.js.map +1 -0
  23. package/dist/cloudflare/cloudflare-alarm-drainer.d.ts +45 -0
  24. package/dist/cloudflare/cloudflare-alarm-drainer.js +103 -0
  25. package/dist/cloudflare/cloudflare-alarm-drainer.js.map +1 -0
  26. package/dist/cloudflare/cloudflare-alarm-run-drain.d.ts +13 -0
  27. package/dist/cloudflare/cloudflare-alarm-run-drain.js +81 -0
  28. package/dist/cloudflare/cloudflare-alarm-run-drain.js.map +1 -0
  29. package/dist/cloudflare/cloudflare-alarm-work.js +110 -0
  30. package/dist/cloudflare/cloudflare-alarm-work.js.map +1 -0
  31. package/dist/cloudflare/cloudflare-checkpoint-store.js +39 -0
  32. package/dist/cloudflare/cloudflare-checkpoint-store.js.map +1 -0
  33. package/dist/cloudflare/cloudflare-durable-object-fetch.d.ts +21 -0
  34. package/dist/cloudflare/cloudflare-durable-object-fetch.js +11 -0
  35. package/dist/cloudflare/cloudflare-durable-object-fetch.js.map +1 -0
  36. package/dist/cloudflare/cloudflare-event-store.js +33 -0
  37. package/dist/cloudflare/cloudflare-event-store.js.map +1 -0
  38. package/dist/cloudflare/cloudflare-execution-session-store.js +40 -0
  39. package/dist/cloudflare/cloudflare-execution-session-store.js.map +1 -0
  40. package/dist/cloudflare/cloudflare-execution-store.js +35 -0
  41. package/dist/cloudflare/cloudflare-execution-store.js.map +1 -0
  42. package/dist/cloudflare/cloudflare-host.d.ts +61 -0
  43. package/dist/cloudflare/cloudflare-host.js +113 -0
  44. package/dist/cloudflare/cloudflare-host.js.map +1 -0
  45. package/dist/cloudflare/cloudflare-notification-store.js +59 -0
  46. package/dist/cloudflare/cloudflare-notification-store.js.map +1 -0
  47. package/dist/cloudflare/cloudflare-run-store.js +81 -0
  48. package/dist/cloudflare/cloudflare-run-store.js.map +1 -0
  49. package/dist/cloudflare/cloudflare-store-utils.js +43 -0
  50. package/dist/cloudflare/cloudflare-store-utils.js.map +1 -0
  51. package/dist/cloudflare/durable-object-storage.d.ts +20 -0
  52. package/dist/cloudflare/durable-object-storage.js +76 -0
  53. package/dist/cloudflare/durable-object-storage.js.map +1 -0
  54. package/dist/cloudflare/index.d.ts +7 -0
  55. package/dist/cloudflare/index.js +6 -0
  56. package/dist/execution/capabilities.d.ts +40 -0
  57. package/dist/execution/host.d.ts +9 -0
  58. package/dist/execution/host.js +62 -0
  59. package/dist/execution/host.js.map +1 -0
  60. package/dist/execution/index.d.ts +6 -0
  61. package/dist/execution/index.js +4 -0
  62. package/dist/execution/memory-notifications.js +54 -0
  63. package/dist/execution/memory-notifications.js.map +1 -0
  64. package/dist/execution/memory-state.js +34 -0
  65. package/dist/execution/memory-state.js.map +1 -0
  66. package/dist/execution/memory-store.js +203 -0
  67. package/dist/execution/memory-store.js.map +1 -0
  68. package/dist/execution/memory.d.ts +7 -0
  69. package/dist/execution/memory.js +28 -0
  70. package/dist/execution/memory.js.map +1 -0
  71. package/dist/execution/types.d.ts +150 -0
  72. package/dist/index.d.ts +13 -6
  73. package/dist/index.js +6 -1
  74. package/dist/llm-tool-execution.d.ts +35 -0
  75. package/dist/llm-tool-execution.js +126 -0
  76. package/dist/llm-tool-execution.js.map +1 -0
  77. package/dist/llm.d.ts +11 -15
  78. package/dist/llm.js +5 -3
  79. package/dist/llm.js.map +1 -1
  80. package/dist/plugins.d.ts +42 -0
  81. package/dist/plugins.js +43 -0
  82. package/dist/plugins.js.map +1 -0
  83. package/dist/session/delegate-input.d.ts +9 -0
  84. package/dist/session/delegate-input.js +16 -0
  85. package/dist/session/delegate-input.js.map +1 -0
  86. package/dist/session/events.d.ts +43 -22
  87. package/dist/session/events.js +41 -0
  88. package/dist/session/events.js.map +1 -0
  89. package/dist/session/input-meta-types.d.ts +10 -0
  90. package/dist/session/input-meta.d.ts +13 -0
  91. package/dist/session/input-meta.js +45 -0
  92. package/dist/session/input-meta.js.map +1 -0
  93. package/dist/session/input.d.ts +4 -0
  94. package/dist/session/mapping.js +4 -2
  95. package/dist/session/mapping.js.map +1 -1
  96. package/dist/session/runtime-input-emit.js +41 -0
  97. package/dist/session/runtime-input-emit.js.map +1 -0
  98. package/dist/session/runtime-input.js +10 -24
  99. package/dist/session/runtime-input.js.map +1 -1
  100. package/dist/session/session-errors.js +1 -6
  101. package/dist/session/session-errors.js.map +1 -1
  102. package/dist/session/session-events.js +73 -0
  103. package/dist/session/session-events.js.map +1 -0
  104. package/dist/session/session-execution.js +88 -0
  105. package/dist/session/session-execution.js.map +1 -0
  106. package/dist/session/session-notification.js +59 -0
  107. package/dist/session/session-notification.js.map +1 -0
  108. package/dist/session/session-runtime-drain.js +3 -9
  109. package/dist/session/session-runtime-drain.js.map +1 -1
  110. package/dist/session/session-turn-processor.js +125 -0
  111. package/dist/session/session-turn-processor.js.map +1 -0
  112. package/dist/session/session.js +81 -102
  113. package/dist/session/session.js.map +1 -1
  114. package/dist/session/snapshot.js.map +1 -1
  115. package/package.json +16 -1
  116. package/dist/agent-validation.js +0 -35
  117. package/dist/agent-validation.js.map +0 -1
  118. package/dist/child-session-cleanups.js +0 -61
  119. package/dist/child-session-cleanups.js.map +0 -1
  120. package/dist/hooks.d.ts +0 -32
  121. package/dist/subagent-job-cancel.js +0 -28
  122. package/dist/subagent-job-cancel.js.map +0 -1
  123. package/dist/subagent-job-output.js +0 -63
  124. package/dist/subagent-job-output.js.map +0 -1
  125. package/dist/subagent-jobs.js +0 -151
  126. package/dist/subagent-jobs.js.map +0 -1
  127. package/dist/subagent-prompt-schema.js +0 -114
  128. package/dist/subagent-prompt-schema.js.map +0 -1
  129. package/dist/subagent-run.js +0 -111
  130. package/dist/subagent-run.js.map +0 -1
  131. package/dist/subagents.js +0 -92
  132. package/dist/subagents.js.map +0 -1
  133. /package/dist/session/{runtime-input.d.ts → session-execution.d.ts} +0 -0
@@ -1,6 +1,9 @@
1
+ import { InputEventMeta } from "./input-meta-types.js";
2
+
1
3
  //#region src/session/input.d.ts
2
4
  type UserTextContent = string | readonly string[];
3
5
  interface UserText {
6
+ meta?: InputEventMeta;
4
7
  text: UserTextContent;
5
8
  type: "user-text";
6
9
  }
@@ -36,6 +39,7 @@ type UserMessageContentPart = UserMessageFilePart | UserMessageImagePart | UserM
36
39
  type UserMessageContent = readonly UserMessageContentPart[];
37
40
  interface UserMessage {
38
41
  content: UserMessageContent;
42
+ meta?: InputEventMeta;
39
43
  type: "user-message";
40
44
  }
41
45
  type UserInput = UserMessage | UserText;
@@ -1,7 +1,9 @@
1
+ import { stripInputMeta } from "./input-meta.js";
1
2
  //#region src/session/mapping.ts
2
3
  function userInputToModelMessage(input) {
3
- if (input.type === "user-message") return userMessageToModelMessage(input);
4
- return userTextToModelMessage(input);
4
+ const stripped = stripInputMeta(input);
5
+ if (stripped.type === "user-message") return userMessageToModelMessage(stripped);
6
+ return userTextToModelMessage(stripped);
5
7
  }
6
8
  function userTextToModelMessage(input) {
7
9
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.js","names":[],"sources":["../../src/session/mapping.ts"],"sourcesContent":["import type {\n AssistantContent,\n AssistantModelMessage,\n ModelMessage,\n ToolModelMessage,\n UserModelMessage,\n} from \"ai\";\nimport type {\n AssistantReasoning,\n AssistantText,\n ToolCall,\n ToolResult,\n UserMessage,\n UserMessageContent,\n UserMessageContentPart,\n UserMessageFileData,\n UserText,\n UserTextContent,\n} from \"./events\";\nimport type { UserInput } from \"./input\";\n\ntype AssistantContentPart = Exclude<AssistantContent, string>[number];\ntype ToolContentPart = ToolModelMessage[\"content\"][number];\ntype ModelEvent = AssistantReasoning | AssistantText | ToolCall | ToolResult;\n\n// UserInput -> AI SDK UserModelMessage\nexport function userInputToModelMessage(input: UserInput): UserModelMessage {\n if (input.type === \"user-message\") {\n return userMessageToModelMessage(input);\n }\n\n return userTextToModelMessage(input);\n}\n\nexport function userTextToModelMessage(input: UserText): UserModelMessage {\n return { role: \"user\", content: userTextContentToUserContent(input.text) };\n}\n\nfunction userTextContentToUserContent(\n text: UserTextContent\n): UserModelMessage[\"content\"] {\n if (typeof text === \"string\") {\n return text;\n }\n\n return text.map((part) => ({ type: \"text\", text: part }));\n}\n\nexport function userMessageToModelMessage(\n input: UserMessage\n): UserModelMessage {\n return {\n role: \"user\",\n content: userMessageContentToUserContent(input.content),\n };\n}\n\nfunction userMessageContentToUserContent(\n content: UserMessageContent\n): Exclude<UserModelMessage[\"content\"], string> {\n return content.map(userMessageContentPartToUserContentPart);\n}\n\nfunction userMessageContentPartToUserContentPart(\n part: UserMessageContentPart\n): Exclude<UserModelMessage[\"content\"], string>[number] {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n\n if (part.type === \"image\") {\n return {\n type: \"file\",\n data: part.image,\n mediaType: part.mediaType ?? \"image\",\n };\n }\n\n return {\n type: \"file\",\n data: userMessageFileDataToFileData(part.data),\n mediaType: part.mediaType,\n ...(part.filename === undefined ? {} : { filename: part.filename }),\n };\n}\n\nfunction userMessageFileDataToFileData(\n data: UserMessageFileData\n): Extract<\n Exclude<UserModelMessage[\"content\"], string>[number],\n { type: \"file\" }\n>[\"data\"] {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data.type === \"url\") {\n return data.url;\n }\n\n if (data.type === \"data\") {\n return { type: \"data\", data: data.data };\n }\n\n if (data.type === \"reference\") {\n return { type: \"reference\", reference: { ...data.reference } };\n }\n\n return { type: \"text\", text: data.text };\n}\n\n// AI SDK ModelMessage -> public agent events\nexport function modelMessageToAgentEvents(message: ModelMessage): ModelEvent[] {\n if (message.role === \"assistant\") {\n return assistantReasoningFirstParts(assistantContentParts(message)).flatMap(\n assistantContentPartToEvents\n );\n }\n\n if (message.role === \"tool\") {\n return message.content.flatMap(toolContentPartToEvents);\n }\n\n return [];\n}\n\nfunction assistantContentParts(\n message: AssistantModelMessage\n): AssistantContentPart[] {\n return typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n}\n\nfunction assistantReasoningFirstParts(\n parts: AssistantContentPart[]\n): AssistantContentPart[] {\n return [\n ...parts.filter((part) => part.type === \"reasoning\"),\n ...parts.filter((part) => part.type !== \"reasoning\"),\n ];\n}\n\nfunction assistantContentPartToEvents(\n part: AssistantContentPart\n): ModelEvent[] {\n if (part.type === \"text\") {\n return part.text ? [{ type: \"assistant-text\", text: part.text }] : [];\n }\n\n if (part.type === \"reasoning\") {\n return part.text ? [{ type: \"assistant-reasoning\", text: part.text }] : [];\n }\n\n if (part.type === \"tool-call\") {\n return [\n {\n type: \"tool-call\",\n input: part.input,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n }\n\n return [];\n}\n\nfunction toolContentPartToEvents(part: ToolContentPart): ModelEvent[] {\n if (part.type === \"tool-result\") {\n return toolResultPartToEvents(part);\n }\n\n return [];\n}\n\nfunction toolResultPartToEvents(part: {\n output: unknown;\n toolCallId: string;\n toolName: string;\n type: \"tool-result\";\n}): ModelEvent[] {\n return [\n {\n type: \"tool-result\",\n output: part.output,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n}\n"],"mappings":";AA0BA,SAAgB,wBAAwB,OAAoC;CAC1E,IAAI,MAAM,SAAS,gBACjB,OAAO,0BAA0B,KAAK;CAGxC,OAAO,uBAAuB,KAAK;AACrC;AAEA,SAAgB,uBAAuB,OAAmC;CACxE,OAAO;EAAE,MAAM;EAAQ,SAAS,6BAA6B,MAAM,IAAI;CAAE;AAC3E;AAEA,SAAS,6BACP,MAC6B;CAC7B,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,OAAO,KAAK,KAAK,UAAU;EAAE,MAAM;EAAQ,MAAM;CAAK,EAAE;AAC1D;AAEA,SAAgB,0BACd,OACkB;CAClB,OAAO;EACL,MAAM;EACN,SAAS,gCAAgC,MAAM,OAAO;CACxD;AACF;AAEA,SAAS,gCACP,SAC8C;CAC9C,OAAO,QAAQ,IAAI,uCAAuC;AAC5D;AAEA,SAAS,wCACP,MACsD;CACtD,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,SAChB,OAAO;EACL,MAAM;EACN,MAAM,KAAK;EACX,WAAW,KAAK,aAAa;CAC/B;CAGF,OAAO;EACL,MAAM;EACN,MAAM,8BAA8B,KAAK,IAAI;EAC7C,WAAW,KAAK;EAChB,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;CACnE;AACF;AAEA,SAAS,8BACP,MAIQ;CACR,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,KAAK,SAAS,OAChB,OAAO,KAAK;CAGd,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,aAChB,OAAO;EAAE,MAAM;EAAa,WAAW,EAAE,GAAG,KAAK,UAAU;CAAE;CAG/D,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;AACzC;AAGA,SAAgB,0BAA0B,SAAqC;CAC7E,IAAI,QAAQ,SAAS,aACnB,OAAO,6BAA6B,sBAAsB,OAAO,CAAC,EAAE,QAClE,4BACF;CAGF,IAAI,QAAQ,SAAS,QACnB,OAAO,QAAQ,QAAQ,QAAQ,uBAAuB;CAGxD,OAAO,CAAC;AACV;AAEA,SAAS,sBACP,SACwB;CACxB,OAAO,OAAO,QAAQ,YAAY,WAC9B,CAAC;EAAE,MAAM;EAAQ,MAAM,QAAQ;CAAQ,CAAC,IACxC,QAAQ;AACd;AAEA,SAAS,6BACP,OACwB;CACxB,OAAO,CACL,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,GACnD,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,CACrD;AACF;AAEA,SAAS,6BACP,MACc;CACd,IAAI,KAAK,SAAS,QAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAkB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAGtE,IAAI,KAAK,SAAS,aAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAuB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAG3E,IAAI,KAAK,SAAS,aAChB,OAAO,CACL;EACE,MAAM;EACN,OAAO,KAAK;EACZ,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;CAGF,OAAO,CAAC;AACV;AAEA,SAAS,wBAAwB,MAAqC;CACpE,IAAI,KAAK,SAAS,eAChB,OAAO,uBAAuB,IAAI;CAGpC,OAAO,CAAC;AACV;AAEA,SAAS,uBAAuB,MAKf;CACf,OAAO,CACL;EACE,MAAM;EACN,QAAQ,KAAK;EACb,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;AACF"}
1
+ {"version":3,"file":"mapping.js","names":[],"sources":["../../src/session/mapping.ts"],"sourcesContent":["import type {\n AssistantContent,\n AssistantModelMessage,\n ModelMessage,\n ToolModelMessage,\n UserModelMessage,\n} from \"ai\";\nimport type {\n AssistantReasoning,\n AssistantText,\n ToolCall,\n ToolResult,\n UserMessage,\n UserMessageContent,\n UserMessageContentPart,\n UserMessageFileData,\n UserText,\n UserTextContent,\n} from \"./events\";\nimport type { UserInput } from \"./input\";\nimport { stripInputMeta } from \"./input-meta\";\n\ntype AssistantContentPart = Exclude<AssistantContent, string>[number];\ntype ToolContentPart = ToolModelMessage[\"content\"][number];\ntype ModelEvent = AssistantReasoning | AssistantText | ToolCall | ToolResult;\n\n// UserInput -> AI SDK UserModelMessage\nexport function userInputToModelMessage(input: UserInput): UserModelMessage {\n const stripped = stripInputMeta(input);\n if (stripped.type === \"user-message\") {\n return userMessageToModelMessage(stripped);\n }\n\n return userTextToModelMessage(stripped);\n}\n\nexport function userTextToModelMessage(input: UserText): UserModelMessage {\n return { role: \"user\", content: userTextContentToUserContent(input.text) };\n}\n\nfunction userTextContentToUserContent(\n text: UserTextContent\n): UserModelMessage[\"content\"] {\n if (typeof text === \"string\") {\n return text;\n }\n\n return text.map((part) => ({ type: \"text\", text: part }));\n}\n\nexport function userMessageToModelMessage(\n input: UserMessage\n): UserModelMessage {\n return {\n role: \"user\",\n content: userMessageContentToUserContent(input.content),\n };\n}\n\nfunction userMessageContentToUserContent(\n content: UserMessageContent\n): Exclude<UserModelMessage[\"content\"], string> {\n return content.map(userMessageContentPartToUserContentPart);\n}\n\nfunction userMessageContentPartToUserContentPart(\n part: UserMessageContentPart\n): Exclude<UserModelMessage[\"content\"], string>[number] {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n\n if (part.type === \"image\") {\n return {\n type: \"file\",\n data: part.image,\n mediaType: part.mediaType ?? \"image\",\n };\n }\n\n return {\n type: \"file\",\n data: userMessageFileDataToFileData(part.data),\n mediaType: part.mediaType,\n ...(part.filename === undefined ? {} : { filename: part.filename }),\n };\n}\n\nfunction userMessageFileDataToFileData(\n data: UserMessageFileData\n): Extract<\n Exclude<UserModelMessage[\"content\"], string>[number],\n { type: \"file\" }\n>[\"data\"] {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data.type === \"url\") {\n return data.url;\n }\n\n if (data.type === \"data\") {\n return { type: \"data\", data: data.data };\n }\n\n if (data.type === \"reference\") {\n return { type: \"reference\", reference: { ...data.reference } };\n }\n\n return { type: \"text\", text: data.text };\n}\n\n// AI SDK ModelMessage -> public agent events\nexport function modelMessageToAgentEvents(message: ModelMessage): ModelEvent[] {\n if (message.role === \"assistant\") {\n return assistantReasoningFirstParts(assistantContentParts(message)).flatMap(\n assistantContentPartToEvents\n );\n }\n\n if (message.role === \"tool\") {\n return message.content.flatMap(toolContentPartToEvents);\n }\n\n return [];\n}\n\nfunction assistantContentParts(\n message: AssistantModelMessage\n): AssistantContentPart[] {\n return typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n}\n\nfunction assistantReasoningFirstParts(\n parts: AssistantContentPart[]\n): AssistantContentPart[] {\n return [\n ...parts.filter((part) => part.type === \"reasoning\"),\n ...parts.filter((part) => part.type !== \"reasoning\"),\n ];\n}\n\nfunction assistantContentPartToEvents(\n part: AssistantContentPart\n): ModelEvent[] {\n if (part.type === \"text\") {\n return part.text ? [{ type: \"assistant-text\", text: part.text }] : [];\n }\n\n if (part.type === \"reasoning\") {\n return part.text ? [{ type: \"assistant-reasoning\", text: part.text }] : [];\n }\n\n if (part.type === \"tool-call\") {\n return [\n {\n type: \"tool-call\",\n input: part.input,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n }\n\n return [];\n}\n\nfunction toolContentPartToEvents(part: ToolContentPart): ModelEvent[] {\n if (part.type === \"tool-result\") {\n return toolResultPartToEvents(part);\n }\n\n return [];\n}\n\nfunction toolResultPartToEvents(part: {\n output: unknown;\n toolCallId: string;\n toolName: string;\n type: \"tool-result\";\n}): ModelEvent[] {\n return [\n {\n type: \"tool-result\",\n output: part.output,\n toolCallId: part.toolCallId,\n toolName: part.toolName,\n },\n ];\n}\n"],"mappings":";;AA2BA,SAAgB,wBAAwB,OAAoC;CAC1E,MAAM,WAAW,eAAe,KAAK;CACrC,IAAI,SAAS,SAAS,gBACpB,OAAO,0BAA0B,QAAQ;CAG3C,OAAO,uBAAuB,QAAQ;AACxC;AAEA,SAAgB,uBAAuB,OAAmC;CACxE,OAAO;EAAE,MAAM;EAAQ,SAAS,6BAA6B,MAAM,IAAI;CAAE;AAC3E;AAEA,SAAS,6BACP,MAC6B;CAC7B,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,OAAO,KAAK,KAAK,UAAU;EAAE,MAAM;EAAQ,MAAM;CAAK,EAAE;AAC1D;AAEA,SAAgB,0BACd,OACkB;CAClB,OAAO;EACL,MAAM;EACN,SAAS,gCAAgC,MAAM,OAAO;CACxD;AACF;AAEA,SAAS,gCACP,SAC8C;CAC9C,OAAO,QAAQ,IAAI,uCAAuC;AAC5D;AAEA,SAAS,wCACP,MACsD;CACtD,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,SAChB,OAAO;EACL,MAAM;EACN,MAAM,KAAK;EACX,WAAW,KAAK,aAAa;CAC/B;CAGF,OAAO;EACL,MAAM;EACN,MAAM,8BAA8B,KAAK,IAAI;EAC7C,WAAW,KAAK;EAChB,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;CACnE;AACF;AAEA,SAAS,8BACP,MAIQ;CACR,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,KAAK,SAAS,OAChB,OAAO,KAAK;CAGd,IAAI,KAAK,SAAS,QAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAGzC,IAAI,KAAK,SAAS,aAChB,OAAO;EAAE,MAAM;EAAa,WAAW,EAAE,GAAG,KAAK,UAAU;CAAE;CAG/D,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;AACzC;AAGA,SAAgB,0BAA0B,SAAqC;CAC7E,IAAI,QAAQ,SAAS,aACnB,OAAO,6BAA6B,sBAAsB,OAAO,CAAC,EAAE,QAClE,4BACF;CAGF,IAAI,QAAQ,SAAS,QACnB,OAAO,QAAQ,QAAQ,QAAQ,uBAAuB;CAGxD,OAAO,CAAC;AACV;AAEA,SAAS,sBACP,SACwB;CACxB,OAAO,OAAO,QAAQ,YAAY,WAC9B,CAAC;EAAE,MAAM;EAAQ,MAAM,QAAQ;CAAQ,CAAC,IACxC,QAAQ;AACd;AAEA,SAAS,6BACP,OACwB;CACxB,OAAO,CACL,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,GACnD,GAAG,MAAM,QAAQ,SAAS,KAAK,SAAS,WAAW,CACrD;AACF;AAEA,SAAS,6BACP,MACc;CACd,IAAI,KAAK,SAAS,QAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAkB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAGtE,IAAI,KAAK,SAAS,aAChB,OAAO,KAAK,OAAO,CAAC;EAAE,MAAM;EAAuB,MAAM,KAAK;CAAK,CAAC,IAAI,CAAC;CAG3E,IAAI,KAAK,SAAS,aAChB,OAAO,CACL;EACE,MAAM;EACN,OAAO,KAAK;EACZ,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;CAGF,OAAO,CAAC;AACV;AAEA,SAAS,wBAAwB,MAAqC;CACpE,IAAI,KAAK,SAAS,eAChB,OAAO,uBAAuB,IAAI;CAGpC,OAAO,CAAC;AACV;AAEA,SAAS,uBAAuB,MAKf;CACf,OAAO,CACL;EACE,MAAM;EACN,QAAQ,KAAK;EACb,YAAY,KAAK;EACjB,UAAU,KAAK;CACjB,CACF;AACF"}
@@ -0,0 +1,41 @@
1
+ import { stripInputMeta } from "./input-meta.js";
2
+ //#region src/session/runtime-input-emit.ts
3
+ function runtimeInputEventFromQueued(queued) {
4
+ return {
5
+ input: queued.input,
6
+ meta: queued.input.meta,
7
+ placement: queued.placement,
8
+ type: "runtime-input"
9
+ };
10
+ }
11
+ async function commitPreUserRuntimeInputs(events, state, runtimeInputs) {
12
+ const committed = [];
13
+ for (const queued of runtimeInputs) {
14
+ const processed = await events.interceptEvent(runtimeInputEventFromQueued(queued));
15
+ if (processed === "handled") continue;
16
+ committed.push(processed);
17
+ const input = runtimeInputHistoryFromEvent(processed, queued);
18
+ state.appendUserInput(input);
19
+ await state.commit();
20
+ }
21
+ return committed;
22
+ }
23
+ function emitCommittedRuntimeInputs(events, run, committed) {
24
+ for (const event of committed) events.emitProcessedEvent(run, event);
25
+ }
26
+ async function emitRuntimeInputEvent(events, run, state, queued) {
27
+ const processed = await events.interceptEvent(runtimeInputEventFromQueued(queued));
28
+ if (processed === "handled") return false;
29
+ events.emitProcessedEvent(run, processed);
30
+ state.appendUserInput(runtimeInputHistoryFromEvent(processed, queued));
31
+ await state.commit();
32
+ return true;
33
+ }
34
+ function runtimeInputHistoryFromEvent(processed, queued) {
35
+ if (processed.type === "runtime-input") return stripInputMeta(processed.input);
36
+ return stripInputMeta(queued.input);
37
+ }
38
+ //#endregion
39
+ export { commitPreUserRuntimeInputs, emitCommittedRuntimeInputs, emitRuntimeInputEvent };
40
+
41
+ //# sourceMappingURL=runtime-input-emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-input-emit.js","names":[],"sources":["../../src/session/runtime-input-emit.ts"],"sourcesContent":["import type { AgentEvent, RuntimeInput } from \"./events\";\nimport type { UserInput } from \"./input\";\nimport { stripInputMeta } from \"./input-meta\";\nimport type { BufferedAgentRun } from \"./run\";\nimport type { QueuedRuntimeInput } from \"./runtime-input\";\nimport type { SessionEventDispatcher } from \"./session-events\";\nimport type { SessionState } from \"./session-state\";\n\nexport function runtimeInputEventFromQueued(\n queued: QueuedRuntimeInput\n): RuntimeInput {\n return {\n input: queued.input,\n meta: queued.input.meta,\n placement: queued.placement,\n type: \"runtime-input\",\n };\n}\n\nexport async function commitPreUserRuntimeInputs(\n events: SessionEventDispatcher,\n state: SessionState,\n runtimeInputs: readonly QueuedRuntimeInput[]\n): Promise<readonly AgentEvent[]> {\n const committed: AgentEvent[] = [];\n for (const queued of runtimeInputs) {\n const processed = await events.interceptEvent(\n runtimeInputEventFromQueued(queued)\n );\n if (processed === \"handled\") {\n continue;\n }\n\n committed.push(processed);\n const input = runtimeInputHistoryFromEvent(processed, queued);\n state.appendUserInput(input);\n await state.commit();\n }\n\n return committed;\n}\n\nexport function emitCommittedRuntimeInputs(\n events: SessionEventDispatcher,\n run: BufferedAgentRun,\n committed: readonly AgentEvent[]\n): void {\n for (const event of committed) {\n events.emitProcessedEvent(run, event);\n }\n}\n\nexport async function emitRuntimeInputEvent(\n events: SessionEventDispatcher,\n run: BufferedAgentRun,\n state: SessionState,\n queued: QueuedRuntimeInput\n): Promise<boolean> {\n const processed = await events.interceptEvent(\n runtimeInputEventFromQueued(queued)\n );\n if (processed === \"handled\") {\n return false;\n }\n\n events.emitProcessedEvent(run, processed);\n state.appendUserInput(runtimeInputHistoryFromEvent(processed, queued));\n await state.commit();\n return true;\n}\n\nfunction runtimeInputHistoryFromEvent(\n processed: AgentEvent,\n queued: QueuedRuntimeInput\n): UserInput {\n if (processed.type === \"runtime-input\") {\n return stripInputMeta(processed.input);\n }\n\n return stripInputMeta(queued.input);\n}\n"],"mappings":";;AAQA,SAAgB,4BACd,QACc;CACd,OAAO;EACL,OAAO,OAAO;EACd,MAAM,OAAO,MAAM;EACnB,WAAW,OAAO;EAClB,MAAM;CACR;AACF;AAEA,eAAsB,2BACpB,QACA,OACA,eACgC;CAChC,MAAM,YAA0B,CAAC;CACjC,KAAK,MAAM,UAAU,eAAe;EAClC,MAAM,YAAY,MAAM,OAAO,eAC7B,4BAA4B,MAAM,CACpC;EACA,IAAI,cAAc,WAChB;EAGF,UAAU,KAAK,SAAS;EACxB,MAAM,QAAQ,6BAA6B,WAAW,MAAM;EAC5D,MAAM,gBAAgB,KAAK;EAC3B,MAAM,MAAM,OAAO;CACrB;CAEA,OAAO;AACT;AAEA,SAAgB,2BACd,QACA,KACA,WACM;CACN,KAAK,MAAM,SAAS,WAClB,OAAO,mBAAmB,KAAK,KAAK;AAExC;AAEA,eAAsB,sBACpB,QACA,KACA,OACA,QACkB;CAClB,MAAM,YAAY,MAAM,OAAO,eAC7B,4BAA4B,MAAM,CACpC;CACA,IAAI,cAAc,WAChB,OAAO;CAGT,OAAO,mBAAmB,KAAK,SAAS;CACxC,MAAM,gBAAgB,6BAA6B,WAAW,MAAM,CAAC;CACrE,MAAM,MAAM,OAAO;CACnB,OAAO;AACT;AAEA,SAAS,6BACP,WACA,QACW;CACX,IAAI,UAAU,SAAS,iBACrB,OAAO,eAAe,UAAU,KAAK;CAGvC,OAAO,eAAe,OAAO,KAAK;AACpC"}
@@ -1,3 +1,4 @@
1
+ import { attachInputMeta } from "./input-meta.js";
1
2
  import { normalizeAgentInput } from "./input-normalization.js";
2
3
  //#region src/session/runtime-input.ts
3
4
  function createRuntimeInputState(queue) {
@@ -9,8 +10,11 @@ function createRuntimeInputState(queue) {
9
10
  function addSteeringInput(runtimeInput, input) {
10
11
  const next = runtimeInput.pending.then(() => {
11
12
  if (runtimeInput.closedReason) throw runtimeInputClosedError(runtimeInput.closedReason);
12
- runtimeInput.queue.push({
13
- input: normalizeAgentInput(input),
13
+ queueRuntimeInput(runtimeInput, {
14
+ input: attachInputMeta(normalizeAgentInput(input), {
15
+ source: "steer",
16
+ streaming: "steer"
17
+ }),
14
18
  placement: runtimeInput.steerPlacement ?? runtimeInput.placement ?? "step-end"
15
19
  });
16
20
  });
@@ -34,36 +38,18 @@ async function withRuntimeInputWindow(runtimeInput, placement, callback) {
34
38
  runtimeInput.steerPlacement = previousSteerPlacement;
35
39
  }
36
40
  }
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
- }
45
- }
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
- };
57
- }
58
41
  function shiftRuntimeInput(runtimeInput, placement) {
59
42
  const index = runtimeInput.queue.findIndex((input) => input.placement === placement);
60
43
  if (index === -1) return;
61
44
  return runtimeInput.queue.splice(index, 1)[0];
62
45
  }
46
+ function queueRuntimeInput(runtimeInput, input) {
47
+ runtimeInput.queue.push(input);
48
+ }
63
49
  function runtimeInputClosedError(reason) {
64
50
  return /* @__PURE__ */ new Error(`session.steer() cannot be used after ${reason}`);
65
51
  }
66
52
  //#endregion
67
- export { addSteeringInput, closeRuntimeInput, createRuntimeInputState, hooksForRuntimeInput, shiftRuntimeInput, withRuntimeInputWindow, withSteeringPlacement };
53
+ export { addSteeringInput, closeRuntimeInput, createRuntimeInputState, queueRuntimeInput, shiftRuntimeInput, withRuntimeInputWindow };
68
54
 
69
55
  //# sourceMappingURL=runtime-input.js.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"runtime-input.js","names":[],"sources":["../../src/session/runtime-input.ts"],"sourcesContent":["import type { AgentEvent, RuntimeInput } from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\nimport { attachInputMeta } from \"./input-meta\";\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 initialEvents: AgentEvent[];\n readonly input?: UserInput;\n readonly preUserRuntimeInputs: QueuedRuntimeInput[];\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 queueRuntimeInput(runtimeInput, {\n input: attachInputMeta(normalizeAgentInput(input), {\n source: \"steer\",\n streaming: \"steer\",\n }),\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 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 queueRuntimeInput(\n runtimeInput: RuntimeInputState,\n input: QueuedRuntimeInput\n): void {\n runtimeInput.queue.push(input);\n}\n\nfunction runtimeInputClosedError(reason: string): Error {\n return new Error(`session.steer() cannot be used after ${reason}`);\n}\n"],"mappings":";;;AA6BA,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,kBAAkB,cAAc;GAC9B,OAAO,gBAAgB,oBAAoB,KAAK,GAAG;IACjD,QAAQ;IACR,WAAW;GACb,CAAC;GACD,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;AAgBA,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,SAAgB,kBACd,cACA,OACM;CACN,aAAa,MAAM,KAAK,KAAK;AAC/B;AAEA,SAAS,wBAAwB,QAAuB;CACtD,uBAAO,IAAI,MAAM,wCAAwC,QAAQ;AACnE"}
@@ -1,9 +1,4 @@
1
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
2
  function errorMessage(error) {
8
3
  if (error instanceof Error) return error.message;
9
4
  return String(error);
@@ -18,6 +13,6 @@ function sessionTerminalError(killed) {
18
13
  return killed ? sessionKilledError() : sessionDeleteInProgressError();
19
14
  }
20
15
  //#endregion
21
- export { errorMessage, runAfterTurnHook, sessionKilledError, sessionTerminalError };
16
+ export { errorMessage, sessionKilledError, sessionTerminalError };
22
17
 
23
18
  //# sourceMappingURL=session-errors.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"session-errors.js","names":[],"sources":["../../src/session/session-errors.ts"],"sourcesContent":["export 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":";AAAA,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,73 @@
1
+ import { runPluginsForEvent } from "../plugins.js";
2
+ //#region src/session/session-events.ts
3
+ var SessionEventDispatcher = class {
4
+ #history;
5
+ #observerEventBuffer;
6
+ #plugins;
7
+ #signal;
8
+ constructor(options) {
9
+ this.#history = options.history;
10
+ this.#plugins = options.plugins;
11
+ this.#signal = options.signal;
12
+ }
13
+ async captureObserverEvents(run, callback) {
14
+ const previousBuffer = this.#observerEventBuffer;
15
+ const buffer = [];
16
+ this.#observerEventBuffer = buffer;
17
+ try {
18
+ return {
19
+ events: buffer,
20
+ release: () => {
21
+ if (this.#observerEventBuffer === buffer) this.#observerEventBuffer = previousBuffer;
22
+ },
23
+ value: await callback()
24
+ };
25
+ } catch (error) {
26
+ for (const event of buffer.splice(0)) await this.emitRunEvent(run, event);
27
+ this.#observerEventBuffer = previousBuffer;
28
+ throw error;
29
+ }
30
+ }
31
+ emitObserverEvent(activeRun, event) {
32
+ const observerEventBuffer = this.#observerEventBuffer;
33
+ if (observerEventBuffer) {
34
+ observerEventBuffer.push(structuredClone(event));
35
+ return Promise.resolve();
36
+ }
37
+ if (!activeRun) return Promise.resolve();
38
+ return this.emitRunEvent(activeRun, event).then(() => void 0);
39
+ }
40
+ async emitRunBoundaryEvent(run, event) {
41
+ await runPluginsForEvent(this.#plugins, {
42
+ event,
43
+ history: this.#history(),
44
+ signal: this.#signal()
45
+ }, { observeOnly: true });
46
+ await run.emitBoundary(event);
47
+ }
48
+ async emitRunEvent(run, event) {
49
+ const processed = await this.interceptEvent(event);
50
+ if (processed === "handled") return "handled";
51
+ run.emit(processed);
52
+ return processed;
53
+ }
54
+ async interceptEvent(event) {
55
+ const pipeline = await this.#runInterceptPipeline(event);
56
+ if (pipeline.kind === "handled") return "handled";
57
+ return pipeline.event;
58
+ }
59
+ emitProcessedEvent(run, event) {
60
+ run.emit(event);
61
+ }
62
+ #runInterceptPipeline(event) {
63
+ return runPluginsForEvent(this.#plugins, {
64
+ event,
65
+ history: this.#history(),
66
+ signal: this.#signal()
67
+ });
68
+ }
69
+ };
70
+ //#endregion
71
+ export { SessionEventDispatcher };
72
+
73
+ //# sourceMappingURL=session-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-events.js","names":["#history","#plugins","#signal","#observerEventBuffer","#runInterceptPipeline"],"sources":["../../src/session/session-events.ts"],"sourcesContent":["import type { RuntimeLlmContext } from \"../llm\";\nimport {\n type AgentPlugin,\n type PluginPipelineResult,\n runPluginsForEvent,\n} from \"../plugins\";\nimport type { AgentEvent } from \"./events\";\nimport type { BufferedAgentRun } from \"./run\";\n\ninterface SessionEventDispatcherOptions {\n readonly history: () => RuntimeLlmContext[\"history\"];\n readonly plugins: readonly AgentPlugin[];\n readonly signal: () => AbortSignal | undefined;\n}\n\nexport class SessionEventDispatcher {\n readonly #history: () => RuntimeLlmContext[\"history\"];\n #observerEventBuffer?: AgentEvent[];\n readonly #plugins: readonly AgentPlugin[];\n readonly #signal: () => AbortSignal | undefined;\n\n constructor(options: SessionEventDispatcherOptions) {\n this.#history = options.history;\n this.#plugins = options.plugins;\n this.#signal = options.signal;\n }\n\n async captureObserverEvents<T>(\n run: BufferedAgentRun,\n callback: () => Promise<T>\n ): Promise<{\n readonly events: AgentEvent[];\n readonly release: () => void;\n readonly value: T;\n }> {\n const previousBuffer = this.#observerEventBuffer;\n const buffer: AgentEvent[] = [];\n this.#observerEventBuffer = buffer;\n try {\n const value = await callback();\n return {\n events: buffer,\n release: () => {\n if (this.#observerEventBuffer === buffer) {\n this.#observerEventBuffer = previousBuffer;\n }\n },\n value,\n };\n } catch (error) {\n for (const event of buffer.splice(0)) {\n await this.emitRunEvent(run, event);\n }\n this.#observerEventBuffer = previousBuffer;\n throw error;\n }\n }\n\n emitObserverEvent(\n activeRun: BufferedAgentRun | undefined,\n event: AgentEvent\n ): Promise<void> {\n const observerEventBuffer = this.#observerEventBuffer;\n if (observerEventBuffer) {\n observerEventBuffer.push(structuredClone(event));\n return Promise.resolve();\n }\n\n if (!activeRun) {\n return Promise.resolve();\n }\n\n return this.emitRunEvent(activeRun, event).then(() => undefined);\n }\n\n async emitRunBoundaryEvent(\n run: BufferedAgentRun,\n event: AgentEvent\n ): Promise<void> {\n await runPluginsForEvent(\n this.#plugins,\n {\n event,\n history: this.#history(),\n signal: this.#signal(),\n },\n { observeOnly: true }\n );\n await run.emitBoundary(event);\n }\n\n async emitRunEvent(\n run: BufferedAgentRun,\n event: AgentEvent\n ): Promise<AgentEvent | \"handled\"> {\n const processed = await this.interceptEvent(event);\n if (processed === \"handled\") {\n return \"handled\";\n }\n\n run.emit(processed);\n return processed;\n }\n\n async interceptEvent(event: AgentEvent): Promise<AgentEvent | \"handled\"> {\n const pipeline = await this.#runInterceptPipeline(event);\n if (pipeline.kind === \"handled\") {\n return \"handled\";\n }\n\n return pipeline.event;\n }\n\n emitProcessedEvent(run: BufferedAgentRun, event: AgentEvent): void {\n run.emit(event);\n }\n\n #runInterceptPipeline(event: AgentEvent): Promise<PluginPipelineResult> {\n return runPluginsForEvent(this.#plugins, {\n event,\n history: this.#history(),\n signal: this.#signal(),\n });\n }\n}\n"],"mappings":";;AAeA,IAAa,yBAAb,MAAoC;CAClC;CACA;CACA;CACA;CAEA,YAAY,SAAwC;EAClD,KAAKA,WAAW,QAAQ;EACxB,KAAKC,WAAW,QAAQ;EACxB,KAAKC,UAAU,QAAQ;CACzB;CAEA,MAAM,sBACJ,KACA,UAKC;EACD,MAAM,iBAAiB,KAAKC;EAC5B,MAAM,SAAuB,CAAC;EAC9B,KAAKA,uBAAuB;EAC5B,IAAI;GAEF,OAAO;IACL,QAAQ;IACR,eAAe;KACb,IAAI,KAAKA,yBAAyB,QAChC,KAAKA,uBAAuB;IAEhC;IACA,OAAA,MARkB,SAAS;GAS7B;EACF,SAAS,OAAO;GACd,KAAK,MAAM,SAAS,OAAO,OAAO,CAAC,GACjC,MAAM,KAAK,aAAa,KAAK,KAAK;GAEpC,KAAKA,uBAAuB;GAC5B,MAAM;EACR;CACF;CAEA,kBACE,WACA,OACe;EACf,MAAM,sBAAsB,KAAKA;EACjC,IAAI,qBAAqB;GACvB,oBAAoB,KAAK,gBAAgB,KAAK,CAAC;GAC/C,OAAO,QAAQ,QAAQ;EACzB;EAEA,IAAI,CAAC,WACH,OAAO,QAAQ,QAAQ;EAGzB,OAAO,KAAK,aAAa,WAAW,KAAK,EAAE,WAAW,KAAA,CAAS;CACjE;CAEA,MAAM,qBACJ,KACA,OACe;EACf,MAAM,mBACJ,KAAKF,UACL;GACE;GACA,SAAS,KAAKD,SAAS;GACvB,QAAQ,KAAKE,QAAQ;EACvB,GACA,EAAE,aAAa,KAAK,CACtB;EACA,MAAM,IAAI,aAAa,KAAK;CAC9B;CAEA,MAAM,aACJ,KACA,OACiC;EACjC,MAAM,YAAY,MAAM,KAAK,eAAe,KAAK;EACjD,IAAI,cAAc,WAChB,OAAO;EAGT,IAAI,KAAK,SAAS;EAClB,OAAO;CACT;CAEA,MAAM,eAAe,OAAoD;EACvE,MAAM,WAAW,MAAM,KAAKE,sBAAsB,KAAK;EACvD,IAAI,SAAS,SAAS,WACpB,OAAO;EAGT,OAAO,SAAS;CAClB;CAEA,mBAAmB,KAAuB,OAAyB;EACjE,IAAI,KAAK,KAAK;CAChB;CAEA,sBAAsB,OAAkD;EACtE,OAAO,mBAAmB,KAAKH,UAAU;GACvC;GACA,SAAS,KAAKD,SAAS;GACvB,QAAQ,KAAKE,QAAQ;EACvB,CAAC;CACH;AACF"}
@@ -0,0 +1,88 @@
1
+ import { persistedToolExecutionCheckpoint } from "../llm-tool-execution.js";
2
+ //#region src/session/session-execution.ts
3
+ const maxCheckpointWriteAttempts = 5;
4
+ var SessionExecutionCheckpointError = class extends Error {
5
+ constructor(runId, expectedVersion, currentVersion) {
6
+ super(`Session execution run ${runId} checkpoint conflict: expected ${expectedVersion}, got ${currentVersion}`);
7
+ this.name = "SessionExecutionCheckpointError";
8
+ }
9
+ };
10
+ async function startSessionExecutionRun({ executionHost, sessionKey, state, turnId }) {
11
+ if (!executionHost) return;
12
+ const runId = `turn:${sessionKey}:${turnId}`;
13
+ const run = {
14
+ checkpointVersion: 0,
15
+ dedupeKey: runId,
16
+ kind: "user-turn",
17
+ rootRunId: runId,
18
+ runId,
19
+ sessionKey,
20
+ status: "running"
21
+ };
22
+ await executionHost.store.runs.create(run);
23
+ return {
24
+ complete: (status) => completeSessionExecutionRun({
25
+ executionHost,
26
+ runId,
27
+ status
28
+ }),
29
+ runId,
30
+ toolExecution: {
31
+ attempt: 1,
32
+ afterTool: (checkpoint) => appendToolExecutionCheckpoint({
33
+ executionHost,
34
+ phase: "after-tool",
35
+ runId,
36
+ state,
37
+ toolCall: checkpoint
38
+ }),
39
+ beforeTool: async (checkpoint) => {
40
+ await appendToolExecutionCheckpoint({
41
+ executionHost,
42
+ phase: "before-tool",
43
+ runId,
44
+ state,
45
+ toolCall: checkpoint
46
+ });
47
+ },
48
+ runId
49
+ }
50
+ };
51
+ }
52
+ async function appendToolExecutionCheckpoint({ executionHost, phase, runId, state, toolCall }) {
53
+ let lastConflict;
54
+ for (let attempt = 0; attempt < maxCheckpointWriteAttempts; attempt += 1) {
55
+ const run = await executionHost.store.runs.get(runId);
56
+ if (!run) throw new Error(`Session execution run ${runId} is missing.`);
57
+ const result = await executionHost.store.checkpoints.append({
58
+ checkpointId: crypto.randomUUID(),
59
+ pendingToolCall: persistedToolExecutionCheckpoint(toolCall),
60
+ phase,
61
+ runId,
62
+ runtimeState: {
63
+ toolCallId: toolCall.toolCallId,
64
+ toolName: toolCall.toolName
65
+ },
66
+ sessionSnapshot: { history: state.modelSnapshot() },
67
+ version: run.checkpointVersion + 1
68
+ }, { expectedVersion: run.checkpointVersion });
69
+ if (result.ok) return;
70
+ lastConflict = {
71
+ current: result.currentVersion,
72
+ expected: run.checkpointVersion
73
+ };
74
+ }
75
+ throw new SessionExecutionCheckpointError(runId, lastConflict?.expected ?? 0, lastConflict?.current ?? 0);
76
+ }
77
+ async function completeSessionExecutionRun({ executionHost, runId, status }) {
78
+ const run = await executionHost.store.runs.get(runId);
79
+ if (!run) return;
80
+ await executionHost.store.runs.update({
81
+ ...run,
82
+ status
83
+ });
84
+ }
85
+ //#endregion
86
+ export { startSessionExecutionRun };
87
+
88
+ //# sourceMappingURL=session-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-execution.js","names":[],"sources":["../../src/session/session-execution.ts"],"sourcesContent":["import type {\n CheckpointPhase,\n ExecutionHost,\n RunRecord,\n RunStatus,\n} from \"../execution/types\";\nimport type {\n RuntimeToolExecutionCheckpoint,\n RuntimeToolExecutionContext,\n} from \"../llm\";\nimport { persistedToolExecutionCheckpoint } from \"../llm-tool-execution\";\nimport type { SessionState } from \"./session-state\";\n\nconst maxCheckpointWriteAttempts = 5;\n\nexport interface SessionExecutionOptions {\n readonly executionHost?: ExecutionHost;\n}\n\nexport interface SessionExecutionRun {\n complete(status: SessionExecutionTerminalStatus): Promise<void>;\n readonly runId: string;\n readonly toolExecution: RuntimeToolExecutionContext;\n}\n\nexport type SessionExecutionTerminalStatus = Extract<\n RunStatus,\n \"cancelled\" | \"completed\" | \"error\" | \"needs-recovery\"\n>;\n\nexport class SessionExecutionCheckpointError extends Error {\n constructor(runId: string, expectedVersion: number, currentVersion: number) {\n super(\n `Session execution run ${runId} checkpoint conflict: expected ${expectedVersion}, got ${currentVersion}`\n );\n this.name = \"SessionExecutionCheckpointError\";\n }\n}\n\nexport async function startSessionExecutionRun({\n executionHost,\n sessionKey,\n state,\n turnId,\n}: {\n readonly executionHost?: ExecutionHost;\n readonly sessionKey: string;\n readonly state: SessionState;\n readonly turnId: string;\n}): Promise<SessionExecutionRun | undefined> {\n if (!executionHost) {\n return;\n }\n\n const runId = `turn:${sessionKey}:${turnId}`;\n const run: RunRecord = {\n checkpointVersion: 0,\n dedupeKey: runId,\n kind: \"user-turn\",\n rootRunId: runId,\n runId,\n sessionKey,\n status: \"running\",\n };\n await executionHost.store.runs.create(run);\n\n return {\n complete: (status) =>\n completeSessionExecutionRun({ executionHost, runId, status }),\n runId,\n toolExecution: {\n attempt: 1,\n afterTool: (checkpoint) =>\n appendToolExecutionCheckpoint({\n executionHost,\n phase: \"after-tool\",\n runId,\n state,\n toolCall: checkpoint,\n }),\n beforeTool: async (checkpoint) => {\n await appendToolExecutionCheckpoint({\n executionHost,\n phase: \"before-tool\",\n runId,\n state,\n toolCall: checkpoint,\n });\n return;\n },\n runId,\n },\n };\n}\n\nasync function appendToolExecutionCheckpoint({\n executionHost,\n phase,\n runId,\n state,\n toolCall,\n}: {\n readonly executionHost: ExecutionHost;\n readonly phase: Extract<CheckpointPhase, \"after-tool\" | \"before-tool\">;\n readonly runId: string;\n readonly state: SessionState;\n readonly toolCall: RuntimeToolExecutionCheckpoint & {\n readonly output?: unknown;\n };\n}): Promise<void> {\n let lastConflict:\n | { readonly current: number; readonly expected: number }\n | undefined;\n for (let attempt = 0; attempt < maxCheckpointWriteAttempts; attempt += 1) {\n const run = await executionHost.store.runs.get(runId);\n if (!run) {\n throw new Error(`Session execution run ${runId} is missing.`);\n }\n\n const result = await executionHost.store.checkpoints.append(\n {\n checkpointId: crypto.randomUUID(),\n pendingToolCall: persistedToolExecutionCheckpoint(toolCall),\n phase,\n runId,\n runtimeState: {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n },\n sessionSnapshot: { history: state.modelSnapshot() },\n version: run.checkpointVersion + 1,\n },\n { expectedVersion: run.checkpointVersion }\n );\n\n if (result.ok) {\n return;\n }\n\n lastConflict = {\n current: result.currentVersion,\n expected: run.checkpointVersion,\n };\n }\n\n throw new SessionExecutionCheckpointError(\n runId,\n lastConflict?.expected ?? 0,\n lastConflict?.current ?? 0\n );\n}\n\nasync function completeSessionExecutionRun({\n executionHost,\n runId,\n status,\n}: {\n readonly executionHost: ExecutionHost;\n readonly runId: string;\n readonly status: SessionExecutionTerminalStatus;\n}): Promise<void> {\n const run = await executionHost.store.runs.get(runId);\n if (!run) {\n return;\n }\n\n await executionHost.store.runs.update({ ...run, status });\n}\n"],"mappings":";;AAaA,MAAM,6BAA6B;AAiBnC,IAAa,kCAAb,cAAqD,MAAM;CACzD,YAAY,OAAe,iBAAyB,gBAAwB;EAC1E,MACE,yBAAyB,MAAM,iCAAiC,gBAAgB,QAAQ,gBAC1F;EACA,KAAK,OAAO;CACd;AACF;AAEA,eAAsB,yBAAyB,EAC7C,eACA,YACA,OACA,UAM2C;CAC3C,IAAI,CAAC,eACH;CAGF,MAAM,QAAQ,QAAQ,WAAW,GAAG;CACpC,MAAM,MAAiB;EACrB,mBAAmB;EACnB,WAAW;EACX,MAAM;EACN,WAAW;EACX;EACA;EACA,QAAQ;CACV;CACA,MAAM,cAAc,MAAM,KAAK,OAAO,GAAG;CAEzC,OAAO;EACL,WAAW,WACT,4BAA4B;GAAE;GAAe;GAAO;EAAO,CAAC;EAC9D;EACA,eAAe;GACb,SAAS;GACT,YAAY,eACV,8BAA8B;IAC5B;IACA,OAAO;IACP;IACA;IACA,UAAU;GACZ,CAAC;GACH,YAAY,OAAO,eAAe;IAChC,MAAM,8BAA8B;KAClC;KACA,OAAO;KACP;KACA;KACA,UAAU;IACZ,CAAC;GAEH;GACA;EACF;CACF;AACF;AAEA,eAAe,8BAA8B,EAC3C,eACA,OACA,OACA,OACA,YASgB;CAChB,IAAI;CAGJ,KAAK,IAAI,UAAU,GAAG,UAAU,4BAA4B,WAAW,GAAG;EACxE,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,IAAI,KAAK;EACpD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,yBAAyB,MAAM,aAAa;EAG9D,MAAM,SAAS,MAAM,cAAc,MAAM,YAAY,OACnD;GACE,cAAc,OAAO,WAAW;GAChC,iBAAiB,iCAAiC,QAAQ;GAC1D;GACA;GACA,cAAc;IACZ,YAAY,SAAS;IACrB,UAAU,SAAS;GACrB;GACA,iBAAiB,EAAE,SAAS,MAAM,cAAc,EAAE;GAClD,SAAS,IAAI,oBAAoB;EACnC,GACA,EAAE,iBAAiB,IAAI,kBAAkB,CAC3C;EAEA,IAAI,OAAO,IACT;EAGF,eAAe;GACb,SAAS,OAAO;GAChB,UAAU,IAAI;EAChB;CACF;CAEA,MAAM,IAAI,gCACR,OACA,cAAc,YAAY,GAC1B,cAAc,WAAW,CAC3B;AACF;AAEA,eAAe,4BAA4B,EACzC,eACA,OACA,UAKgB;CAChB,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,IAAI,KAAK;CACpD,IAAI,CAAC,KACH;CAGF,MAAM,cAAc,MAAM,KAAK,OAAO;EAAE,GAAG;EAAK;CAAO,CAAC;AAC1D"}
@@ -0,0 +1,59 @@
1
+ import { attachInputMeta } from "./input-meta.js";
2
+ import { normalizeAgentInput } from "./input-normalization.js";
3
+ import { BufferedAgentRun } from "./run.js";
4
+ import { createRuntimeInputState, queueRuntimeInput } from "./runtime-input.js";
5
+ import { errorMessage } from "./session-errors.js";
6
+ //#region src/session/session-notification.ts
7
+ function queueSessionNotification(input, options, state) {
8
+ const queuedRuntimeInput = {
9
+ input: attachInputMeta(normalizeAgentInput(input), { source: "notify" }),
10
+ placement: "turn-start"
11
+ };
12
+ const observerEvents = cloneObserverEvents(options.observerEvents ?? []);
13
+ const queuedTurn = state.inputQueue[0];
14
+ if (queuedTurn) {
15
+ queuedTurn.initialEvents.push(...observerEvents);
16
+ queuedTurn.preUserRuntimeInputs.push(queuedRuntimeInput);
17
+ return queuedTurn.run;
18
+ }
19
+ const activeRun = state.activeRun;
20
+ const runtimeInput = state.activeRuntimeInput;
21
+ if (runtimeInput && activeRun && !runtimeInput.closedReason) {
22
+ queueRuntimeInput(runtimeInput, {
23
+ input: structuredClone(queuedRuntimeInput.input),
24
+ placement: "step-end"
25
+ });
26
+ return activeRun;
27
+ }
28
+ if (options.deferWhenUnobserved === true) {
29
+ state.pendingRuntimeInputs.push(queuedRuntimeInput);
30
+ const deferredRun = new BufferedAgentRun();
31
+ deferredRun.close();
32
+ return deferredRun;
33
+ }
34
+ const run = new BufferedAgentRun();
35
+ state.inputQueue.push({
36
+ initialEvents: observerEvents,
37
+ preUserRuntimeInputs: [],
38
+ run,
39
+ runtimeInput: createRuntimeInputState([queuedRuntimeInput])
40
+ });
41
+ startSessionQueueDrain(run, state.drain);
42
+ return run;
43
+ }
44
+ function startSessionQueueDrain(run, drain) {
45
+ drain().catch((error) => {
46
+ run.emit({
47
+ type: "turn-error",
48
+ message: errorMessage(error)
49
+ });
50
+ run.close();
51
+ });
52
+ }
53
+ function cloneObserverEvents(events) {
54
+ return events.map((event) => structuredClone(event));
55
+ }
56
+ //#endregion
57
+ export { queueSessionNotification, startSessionQueueDrain };
58
+
59
+ //# sourceMappingURL=session-notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-notification.js","names":[],"sources":["../../src/session/session-notification.ts"],"sourcesContent":["import type { AgentEvent } from \"./events\";\nimport type { AgentInput } from \"./input\";\nimport { attachInputMeta } from \"./input-meta\";\nimport { normalizeAgentInput } from \"./input-normalization\";\nimport { type AgentRun, BufferedAgentRun } from \"./run\";\nimport {\n createRuntimeInputState,\n type QueuedInput,\n type QueuedRuntimeInput,\n queueRuntimeInput,\n type RuntimeInputState,\n} from \"./runtime-input\";\nimport { errorMessage } from \"./session-errors\";\n\nexport interface NotifyOptions {\n readonly deferWhenUnobserved?: boolean;\n readonly observerEvents?: readonly AgentEvent[];\n}\n\ninterface QueueSessionNotificationOptions {\n readonly activeRun: BufferedAgentRun | undefined;\n readonly activeRuntimeInput: RuntimeInputState | undefined;\n readonly drain: () => Promise<void>;\n readonly inputQueue: QueuedInput[];\n readonly pendingRuntimeInputs: QueuedRuntimeInput[];\n}\n\nexport function queueSessionNotification(\n input: AgentInput,\n options: NotifyOptions,\n state: QueueSessionNotificationOptions\n): AgentRun {\n const queuedRuntimeInput: QueuedRuntimeInput = {\n input: attachInputMeta(normalizeAgentInput(input), { source: \"notify\" }),\n placement: \"turn-start\",\n };\n const observerEvents = cloneObserverEvents(options.observerEvents ?? []);\n const queuedTurn = state.inputQueue[0];\n if (queuedTurn) {\n queuedTurn.initialEvents.push(...observerEvents);\n queuedTurn.preUserRuntimeInputs.push(queuedRuntimeInput);\n return queuedTurn.run;\n }\n\n const activeRun = state.activeRun;\n const runtimeInput = state.activeRuntimeInput;\n if (runtimeInput && activeRun && !runtimeInput.closedReason) {\n queueRuntimeInput(runtimeInput, {\n input: structuredClone(queuedRuntimeInput.input),\n placement: \"step-end\",\n });\n return activeRun;\n }\n\n if (options.deferWhenUnobserved === true) {\n state.pendingRuntimeInputs.push(queuedRuntimeInput);\n const deferredRun = new BufferedAgentRun();\n deferredRun.close();\n return deferredRun;\n }\n\n const run = new BufferedAgentRun();\n state.inputQueue.push({\n initialEvents: observerEvents,\n preUserRuntimeInputs: [],\n run,\n runtimeInput: createRuntimeInputState([queuedRuntimeInput]),\n });\n startSessionQueueDrain(run, state.drain);\n return run;\n}\n\nexport function startSessionQueueDrain(\n run: BufferedAgentRun,\n drain: () => Promise<void>\n): void {\n drain().catch((error: unknown) => {\n run.emit({ type: \"turn-error\", message: errorMessage(error) });\n run.close();\n });\n}\n\nfunction cloneObserverEvents(events: readonly AgentEvent[]): AgentEvent[] {\n return events.map((event) => structuredClone(event));\n}\n"],"mappings":";;;;;;AA2BA,SAAgB,yBACd,OACA,SACA,OACU;CACV,MAAM,qBAAyC;EAC7C,OAAO,gBAAgB,oBAAoB,KAAK,GAAG,EAAE,QAAQ,SAAS,CAAC;EACvE,WAAW;CACb;CACA,MAAM,iBAAiB,oBAAoB,QAAQ,kBAAkB,CAAC,CAAC;CACvE,MAAM,aAAa,MAAM,WAAW;CACpC,IAAI,YAAY;EACd,WAAW,cAAc,KAAK,GAAG,cAAc;EAC/C,WAAW,qBAAqB,KAAK,kBAAkB;EACvD,OAAO,WAAW;CACpB;CAEA,MAAM,YAAY,MAAM;CACxB,MAAM,eAAe,MAAM;CAC3B,IAAI,gBAAgB,aAAa,CAAC,aAAa,cAAc;EAC3D,kBAAkB,cAAc;GAC9B,OAAO,gBAAgB,mBAAmB,KAAK;GAC/C,WAAW;EACb,CAAC;EACD,OAAO;CACT;CAEA,IAAI,QAAQ,wBAAwB,MAAM;EACxC,MAAM,qBAAqB,KAAK,kBAAkB;EAClD,MAAM,cAAc,IAAI,iBAAiB;EACzC,YAAY,MAAM;EAClB,OAAO;CACT;CAEA,MAAM,MAAM,IAAI,iBAAiB;CACjC,MAAM,WAAW,KAAK;EACpB,eAAe;EACf,sBAAsB,CAAC;EACvB;EACA,cAAc,wBAAwB,CAAC,kBAAkB,CAAC;CAC5D,CAAC;CACD,uBAAuB,KAAK,MAAM,KAAK;CACvC,OAAO;AACT;AAEA,SAAgB,uBACd,KACA,OACM;CACN,MAAM,EAAE,OAAO,UAAmB;EAChC,IAAI,KAAK;GAAE,MAAM;GAAc,SAAS,aAAa,KAAK;EAAE,CAAC;EAC7D,IAAI,MAAM;CACZ,CAAC;AACH;AAEA,SAAS,oBAAoB,QAA6C;CACxE,OAAO,OAAO,KAAK,UAAU,gBAAgB,KAAK,CAAC;AACrD"}
@@ -1,17 +1,11 @@
1
1
  import { shiftRuntimeInput } from "./runtime-input.js";
2
+ import { emitRuntimeInputEvent } from "./runtime-input-emit.js";
2
3
  //#region src/session/session-runtime-drain.ts
3
- async function drainRuntimeInput({ placement, run, runtimeInput, state }) {
4
+ async function drainRuntimeInput({ events, placement, run, runtimeInput, state }) {
4
5
  let added = false;
5
6
  let next = shiftRuntimeInput(runtimeInput, placement);
6
7
  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();
8
+ if (await emitRuntimeInputEvent(events, run, state, next)) added = true;
15
9
  next = shiftRuntimeInput(runtimeInput, placement);
16
10
  }
17
11
  return added;
@@ -1 +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"}
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 { emitRuntimeInputEvent } from \"./runtime-input-emit\";\nimport type { SessionEventDispatcher } from \"./session-events\";\nimport type { SessionState } from \"./session-state\";\n\nexport async function drainRuntimeInput({\n events,\n placement,\n run,\n runtimeInput,\n state,\n}: {\n readonly events: SessionEventDispatcher;\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 if (await emitRuntimeInputEvent(events, run, state, next)) {\n added = true;\n }\n next = shiftRuntimeInput(runtimeInput, placement);\n }\n\n return added;\n}\n"],"mappings":";;;AAUA,eAAsB,kBAAkB,EACtC,QACA,WACA,KACA,cACA,SAOmB;CACnB,IAAI,QAAQ;CACZ,IAAI,OAAO,kBAAkB,cAAc,SAAS;CACpD,OAAO,MAAM;EACX,IAAI,MAAM,sBAAsB,QAAQ,KAAK,OAAO,IAAI,GACtD,QAAQ;EAEV,OAAO,kBAAkB,cAAc,SAAS;CAClD;CAEA,OAAO;AACT"}
@@ -0,0 +1,125 @@
1
+ import { ToolExecutionNeedsRecoveryError } from "../llm-tool-execution.js";
2
+ import { closeRuntimeInput, withRuntimeInputWindow } from "./runtime-input.js";
3
+ import { errorMessage } from "./session-errors.js";
4
+ import { runAgentLoop } from "../agent-loop.js";
5
+ import { commitPreUserRuntimeInputs, emitCommittedRuntimeInputs } from "./runtime-input-emit.js";
6
+ import { startSessionExecutionRun } from "./session-execution.js";
7
+ import { drainRuntimeInput } from "./session-runtime-drain.js";
8
+ import { emitTurnErrorAfterRecovery } from "./session-turn-error.js";
9
+ //#region src/session/session-turn-processor.ts
10
+ async function processQueuedInput({ activate, deactivateRun, events, execution, item, llm, release, sessionKey, state }) {
11
+ const activeAbort = new AbortController();
12
+ const { initialEvents, input, preUserRuntimeInputs, run, runtimeInput } = item;
13
+ const turnId = crypto.randomUUID();
14
+ activate({
15
+ abort: activeAbort,
16
+ run,
17
+ runtimeInput,
18
+ turnId
19
+ });
20
+ const historySnapshot = state.modelSnapshot();
21
+ let executionRun;
22
+ try {
23
+ executionRun = await startSessionExecutionRun({
24
+ executionHost: execution.executionHost,
25
+ sessionKey,
26
+ state,
27
+ turnId
28
+ });
29
+ for (const event of initialEvents) await events.emitRunEvent(run, event);
30
+ const committedPreUser = await commitPreUserRuntimeInputs(events, state, preUserRuntimeInputs);
31
+ if (input) {
32
+ state.appendUserInput(input);
33
+ await state.commit();
34
+ }
35
+ await withRuntimeInputWindow(runtimeInput, "turn-start", async () => {
36
+ await events.emitRunBoundaryEvent(run, { type: "turn-start" });
37
+ });
38
+ await emitCommittedRuntimeInputs(events, run, committedPreUser);
39
+ await drainRuntimeInput({
40
+ events,
41
+ placement: "turn-start",
42
+ run,
43
+ runtimeInput,
44
+ state
45
+ });
46
+ const result = await runAgentLoop({
47
+ emit: async (event) => emitTurnEvent({
48
+ event,
49
+ events,
50
+ run,
51
+ runtimeInput,
52
+ state
53
+ }),
54
+ history: state.history,
55
+ llm,
56
+ captureObserverEvents: (callback) => events.captureObserverEvents(run, callback),
57
+ signal: activeAbort.signal,
58
+ toolExecution: executionRun?.toolExecution
59
+ });
60
+ await state.commit();
61
+ await executionRun?.complete(executionStatusForResult(result));
62
+ await closeSuccessfulTurn({
63
+ deactivateRun,
64
+ events,
65
+ result,
66
+ run,
67
+ runtimeInput
68
+ });
69
+ } catch (error) {
70
+ const turnError = error instanceof Error ? error : new Error(String(error));
71
+ await executionRun?.complete(executionStatusForError(turnError));
72
+ await emitTurnErrorAfterRecovery({
73
+ error: turnError,
74
+ historySnapshot,
75
+ run,
76
+ runtimeInput,
77
+ state
78
+ });
79
+ } finally {
80
+ closeRuntimeInput(runtimeInput);
81
+ release();
82
+ run.close(void 0, runtimeInput.closedReason);
83
+ }
84
+ }
85
+ function executionStatusForResult(result) {
86
+ return result === "aborted" ? "cancelled" : "completed";
87
+ }
88
+ function executionStatusForError(error) {
89
+ return error instanceof ToolExecutionNeedsRecoveryError ? "needs-recovery" : "error";
90
+ }
91
+ async function closeSuccessfulTurn({ deactivateRun, events, result, run, runtimeInput }) {
92
+ const terminalEvent = result === "aborted" ? "turn-abort" : "turn-end";
93
+ closeRuntimeInput(runtimeInput, terminalEvent);
94
+ deactivateRun();
95
+ try {
96
+ await events.emitRunEvent(run, { type: terminalEvent });
97
+ } catch (terminalError) {
98
+ run.emit({
99
+ type: "turn-error",
100
+ message: errorMessage(terminalError)
101
+ });
102
+ closeRuntimeInput(runtimeInput, "turn-error");
103
+ }
104
+ }
105
+ async function emitTurnEvent({ event, events, run, runtimeInput, state }) {
106
+ if (event.type !== "step-start" && event.type !== "step-end") {
107
+ await events.emitRunEvent(run, event);
108
+ return;
109
+ }
110
+ await withRuntimeInputWindow(runtimeInput, event.type, async () => {
111
+ await events.emitRunBoundaryEvent(run, event);
112
+ });
113
+ const runtimeInputAdded = await drainRuntimeInput({
114
+ events,
115
+ placement: event.type,
116
+ run,
117
+ runtimeInput,
118
+ state
119
+ });
120
+ return event.type === "step-end" ? { runtimeInputAdded } : void 0;
121
+ }
122
+ //#endregion
123
+ export { processQueuedInput };
124
+
125
+ //# sourceMappingURL=session-turn-processor.js.map