@xopcai/xopc 0.0.222 → 0.0.224

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 (213) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/{activity-store-NItGQmvR.js → activity-store--GBciH10.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DsR_2U9-.js → agent-avatar-dicebear-K7V4XXt7.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-BsxTpXyq.js +68 -0
  7. package/dist/gateway/static/root/assets/{api-53ZXsuyr.js → api-HoIz_ija.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BCzVX09V.js → app-management-settings-panel-xQCmkAHh.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-DgSpwqQI.js → appearance-settings-BRoeA4kU.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-BXgpBA8w.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-D8o8CP9Y.js → archive-plugin-CteCVsBP.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-BQHcAR6J.js → attachment-load-D7xNA2jB.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-CswK3HFb.js → automations-page-BD1vK7r5.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-wrgf-z7D.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BlpyTJ1b.js → binary-plugins-C3DaJa0W.js} +1 -1
  16. package/dist/gateway/static/root/assets/block-editor-lTkcHTve.js +184 -0
  17. package/dist/gateway/static/root/assets/browser-settings-page-zhzNkeVG.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bi6RSSpD.js → browser-workflow-inputs-1UZ0vnIy.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-CZNOOQY4.js → browser-workflows-page-BHuJOF4M.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-DuCmg2Ej.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-pC2fno7r.js → capability-presets-api-yNqTIuyd.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DjiP3mQQ.js +3 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-B5Szgu_z.js → channel-recipient-api-krezGsKc.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-B4AtvQHk.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +1 -0
  26. package/dist/gateway/static/root/assets/{chat-terminal-dock-2fpzufzt.js → chat-terminal-dock-BRrL2iHA.js} +2 -2
  27. package/dist/gateway/static/root/assets/connectors-page-fmda2NEP.js +2 -0
  28. package/dist/gateway/static/root/assets/{cron-expression-VePLfPUR.js → cron-expression-Bl-2DzBQ.js} +1 -1
  29. package/dist/gateway/static/root/assets/{date-picker-CJegmPTJ.js → date-picker-CxTl6Wlz.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dependency-picker-B2o9unBk.js → dependency-picker-DSl0mOPa.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-BH4Np-ay.js → desktop-pet-DTeCmCdb.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-settings-Duu3ctxD.js → desktop-pet-settings-BNebxg0V.js} +1 -1
  33. package/dist/gateway/static/root/assets/{directory-picker-path-field-BBCUZOg2.js → directory-picker-path-field-Dn9XpmXY.js} +1 -1
  34. package/dist/gateway/static/root/assets/dist-DaxPZj9e.js +1 -0
  35. package/dist/gateway/static/root/assets/{dist-DY4Af0fY.js → dist-J_ySZvz0.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-debug-page-DS_o3F97.js → extension-debug-page-D-J-eOTb.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-BTLBZdCq.js → extension-page-CpST24nU.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-KTGrYbgk.js → extension-settings-page-4nQXFnFq.js} +1 -1
  39. package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-config-api-D3YJVfzY.js → gateway-config-api-BHWHduDi.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-config-swr-BzTbnu4O.js → gateway-config-swr-yUxMMVjK.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-settings-B8--s3yC.js → gateway-settings-BimMKmkM.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-startup-retry-B2zpkNvi.js → gateway-startup-retry-9mrsL84j.js} +1 -1
  44. package/dist/gateway/static/root/assets/heartbeat-settings-MUJ3mEC9.js +1 -0
  45. package/dist/gateway/static/root/assets/home-page-DSM6aPHF.js +1 -0
  46. package/dist/gateway/static/root/assets/{image-generation-api-BXRjz-iY.js → image-generation-api-CgFAGDi8.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-B3zYJBhK.js +74 -0
  48. package/dist/gateway/static/root/assets/index-D3_xSYKd.css +2 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D-Ib-suu.js → keyboard-shortcuts-settings-6Ar5rfX4.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-tzM0wTL8.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-Bsy1lvAc.js → local-apps-page-B5n-x544.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-iKjqemWG.js → locale-store-CPylQjH9.js} +1 -1
  53. package/dist/gateway/static/root/assets/logs-page-CgoQlera.js +2 -0
  54. package/dist/gateway/static/root/assets/{management-settings-D-akydG4.js → management-settings-CXBLyU-0.js} +1 -1
  55. package/dist/gateway/static/root/assets/{markdown-split-DHH4Cu2i.js → markdown-split-CtmQemJi.js} +1 -1
  56. package/dist/gateway/static/root/assets/markdown-view-CUsob4Pz.js +69 -0
  57. package/dist/gateway/static/root/assets/{media-plugins-BwHtUXkj.js → media-plugins-Dsd-IEOW.js} +1 -1
  58. package/dist/gateway/static/root/assets/messages-B82nsi9k.js +3 -0
  59. package/dist/gateway/static/root/assets/notes-api-CfKZYrBC.js +1 -0
  60. package/dist/gateway/static/root/assets/{notes-page-BxM1p6hz.js → notes-page-BKbOTE2n.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-BScELo01.js +4 -0
  62. package/dist/gateway/static/root/assets/oauth-authorization-window-Cdolr2wE.js +1 -0
  63. package/dist/gateway/static/root/assets/{popover-select-BzdnTy3h.js → popover-select-CccGri5Y.js} +1 -1
  64. package/dist/gateway/static/root/assets/{product-open-page-DrfWH1ir.js → product-open-page-DqB9bsDB.js} +1 -1
  65. package/dist/gateway/static/root/assets/project-detail-page-DUoyty8X.js +1 -0
  66. package/dist/gateway/static/root/assets/projects-page-PeXUdGdO.js +1 -0
  67. package/dist/gateway/static/root/assets/{registry-api-Cx3JxXSL.js → registry-api-B_5D8epF.js} +1 -1
  68. package/dist/gateway/static/root/assets/remote-access-hub-sHho-uXP.js +1 -0
  69. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DF7syQRd.js → runtime-tools-settings-panel-DBTH_t0O.js} +1 -1
  70. package/dist/gateway/static/root/assets/{schema-form-BQ_qRIsM.js → schema-form-CqMKAwV0.js} +1 -1
  71. package/dist/gateway/static/root/assets/sessions-page-DyvNgaP9.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-CnYf1R7z.js +1 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-BBHGOQHU.js → settings-form-section-dPriuuYq.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CiwjP2-b.js → settings-loading-skeleton-B-Mbm8Va.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-Rl9waapk.js → settings-page-Dyj3w-Ml.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-C4FxY5J3.js +1 -0
  77. package/dist/gateway/static/root/assets/share-preview-page-emEdx7YL.js +2 -0
  78. package/dist/gateway/static/root/assets/shares-settings-BQBVq-sN.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-BFoEpQ4I.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-YbtR_zEU.js → skills-page-BNtYnrRT.js} +1 -1
  81. package/dist/gateway/static/root/assets/{skills-page.utils-DTmx2Zza.js → skills-page.utils-DjnbNFs5.js} +1 -1
  82. package/dist/gateway/static/root/assets/{system-settings-panel-BZDJcKdS.js → system-settings-panel-DDStf-jZ.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-ZVwr8KbS.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-BOD2D0dJ.js → theme-store-BN-32Fz5.js} +1 -1
  85. package/dist/gateway/static/root/assets/{use-autosave-Be9aR9qA.js → use-autosave-C2mKZ-ua.js} +1 -1
  86. package/dist/gateway/static/root/assets/user-context-page-CHjIinCW.js +1 -0
  87. package/dist/gateway/static/root/assets/{voice-api-key-field-IMc3Ua6C.js → voice-api-key-field-D7OHeQby.js} +1 -1
  88. package/dist/gateway/static/root/assets/{work-discovery-overlay-TC-xQenr.js → work-discovery-overlay-CIiXie7F.js} +1 -1
  89. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-B2auxcRv.js → workflow-run-setup-panel-9_dAGW3_.js} +2 -2
  90. package/dist/gateway/static/root/assets/workflows-page-DXpYJxao.js +5 -0
  91. package/dist/gateway/static/root/index.html +15 -14
  92. package/dist/package.js +1 -1
  93. package/dist/src/agent/agent-instance-gateway.d.ts +3 -0
  94. package/dist/src/agent/agent-manager.d.ts +3 -0
  95. package/dist/src/agent/agent-manager.js +30 -24
  96. package/dist/src/agent/embedded/index.d.ts +1 -1
  97. package/dist/src/agent/embedded/index.js +2 -2
  98. package/dist/src/agent/embedded/run-for-session.js +101 -62
  99. package/dist/src/agent/embedded/run-turn.js +56 -28
  100. package/dist/src/agent/embedded/runs.d.ts +16 -29
  101. package/dist/src/agent/embedded/runs.js +44 -65
  102. package/dist/src/agent/embedded/types.d.ts +4 -0
  103. package/dist/src/agent/orchestration/agent-run-supervisor.d.ts +28 -0
  104. package/dist/src/agent/orchestration/agent-run-supervisor.js +49 -0
  105. package/dist/src/agent/orchestration/agent-turn-policy.d.ts +18 -0
  106. package/dist/src/agent/orchestration/agent-turn-policy.js +36 -0
  107. package/dist/src/agent/orchestration/llm-turn-retry.d.ts +5 -0
  108. package/dist/src/agent/orchestration/llm-turn-retry.js +34 -4
  109. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +10 -1
  110. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +25 -4
  111. package/dist/src/agent/service/async-queue.d.ts +16 -3
  112. package/dist/src/agent/service/async-queue.js +29 -11
  113. package/dist/src/agent/service/process-direct-streaming.js +27 -4
  114. package/dist/src/agent/service.js +1 -0
  115. package/dist/src/agent/tools/exec-command.d.ts +2 -0
  116. package/dist/src/agent/tools/exec-command.js +70 -7
  117. package/dist/src/auth/oauth/index.js +3 -3
  118. package/dist/src/auth/oauth/registry.d.ts +2 -0
  119. package/dist/src/auth/oauth/registry.js +20 -12
  120. package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
  121. package/dist/src/auth/oauth/xopc-cloud.js +32 -16
  122. package/dist/src/cli/commands/channels.js +1 -1
  123. package/dist/src/cli/commands/connectors.js +1 -1
  124. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  125. package/dist/src/cli/commands/models.js +1 -1
  126. package/dist/src/cli/commands/onboard.js +1 -1
  127. package/dist/src/cli/commands/tunnel.js +4 -5
  128. package/dist/src/config/agent-profile.js +1 -1
  129. package/dist/src/config/schema.d.ts +18 -0
  130. package/dist/src/config/schema.js +19 -1
  131. package/dist/src/extensions/sdk/index.js +1 -1
  132. package/dist/src/gateway/agents-admin.js +1 -1
  133. package/dist/src/gateway/hono/app.js +2 -1
  134. package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
  135. package/dist/src/gateway/hono/oauth-async.js +11 -4
  136. package/dist/src/gateway/hono/routes/config.js +10 -0
  137. package/dist/src/gateway/hono/routes/host-fs.js +40 -1
  138. package/dist/src/gateway/hono/routes/media.js +33 -1
  139. package/dist/src/gateway/hono/routes/notes.js +162 -7
  140. package/dist/src/gateway/hono/routes/shares.js +141 -6
  141. package/dist/src/gateway/hono/routes/tunnel.js +47 -10
  142. package/dist/src/gateway/hono/routes/voice.d.ts +2 -6
  143. package/dist/src/gateway/hono/routes/voice.js +20 -4
  144. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  145. package/dist/src/gateway/run-loop.js +3 -0
  146. package/dist/src/gateway/server.d.ts +3 -0
  147. package/dist/src/gateway/server.js +30 -5
  148. package/dist/src/gateway/service.js +4 -4
  149. package/dist/src/notes/service.d.ts +6 -2
  150. package/dist/src/notes/service.js +36 -4
  151. package/dist/src/providers/index.js +2 -2
  152. package/dist/src/share/note-share-service.d.ts +67 -0
  153. package/dist/src/share/note-share-service.js +283 -0
  154. package/dist/src/share/share-config.js +32 -3
  155. package/dist/src/share/share-landing.d.ts +5 -1
  156. package/dist/src/share/share-landing.js +28 -1
  157. package/dist/src/share/share-store.d.ts +34 -5
  158. package/dist/src/share/share-store.js +125 -19
  159. package/dist/src/share/share-thumbnail.js +4 -2
  160. package/dist/src/share/share-types.d.ts +52 -14
  161. package/dist/src/share/share-types.js +9 -0
  162. package/dist/src/share/share-zip.d.ts +2 -2
  163. package/dist/src/tui/backends/embedded-backend.js +1 -1
  164. package/dist/src/tunnel/env.d.ts +12 -6
  165. package/dist/src/tunnel/env.js +34 -26
  166. package/dist/src/tunnel/gateway-lifecycle.js +2 -13
  167. package/dist/src/tunnel/index.d.ts +1 -1
  168. package/dist/src/tunnel/index.js +2 -2
  169. package/dist/src/tunnel/tunnel-audit.d.ts +1 -1
  170. package/dist/src/tunnel/tunnel-config.d.ts +1 -1
  171. package/dist/src/tunnel/tunnel-config.js +9 -4
  172. package/dist/src/tunnel/tunnel-service.d.ts +1 -1
  173. package/dist/src/tunnel/tunnel-service.js +3 -0
  174. package/dist/src/tunnel/well-known.d.ts +1 -1
  175. package/dist/src/tunnel/well-known.js +1 -1
  176. package/dist/src/tunnel/xopc-cloud-registration.d.ts +9 -0
  177. package/dist/src/tunnel/xopc-cloud-registration.js +42 -0
  178. package/dist/src/voice/stt/transcribe-core.js +17 -1
  179. package/dist/src/voice/stt/types.d.ts +1 -1
  180. package/package.json +2 -2
  181. package/dist/gateway/static/root/assets/agents-DijFbC4G.js +0 -68
  182. package/dist/gateway/static/root/assets/apps-page-BFAmf9hq.js +0 -1
  183. package/dist/gateway/static/root/assets/automations-workspace-B8us5JBf.js +0 -6
  184. package/dist/gateway/static/root/assets/block-editor-C3mwGsms.js +0 -184
  185. package/dist/gateway/static/root/assets/browser-settings-page-BeBd17-3.js +0 -8
  186. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bv0z3KRq.js +0 -7
  187. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BczD-pWE.js +0 -3
  188. package/dist/gateway/static/root/assets/channels-settings-2KQYq6xl.js +0 -1
  189. package/dist/gateway/static/root/assets/channels-status-swr-ByRbxC6z.js +0 -1
  190. package/dist/gateway/static/root/assets/connectors-page-PB1boaNy.js +0 -2
  191. package/dist/gateway/static/root/assets/dist-C230izr8.js +0 -1
  192. package/dist/gateway/static/root/assets/heartbeat-settings-5YQ5BUwp.js +0 -1
  193. package/dist/gateway/static/root/assets/home-page-DfIVWJl3.js +0 -1
  194. package/dist/gateway/static/root/assets/index-BXGC3VFm.css +0 -2
  195. package/dist/gateway/static/root/assets/index-jqDCfet4.js +0 -74
  196. package/dist/gateway/static/root/assets/local-app-workbench-page-CAb0odzu.js +0 -2
  197. package/dist/gateway/static/root/assets/logs-page-CFxKbDZl.js +0 -2
  198. package/dist/gateway/static/root/assets/markdown-view-DYkxMtJA.js +0 -69
  199. package/dist/gateway/static/root/assets/messages-kx5W39dO.js +0 -3
  200. package/dist/gateway/static/root/assets/notes-api-DJizatxh.js +0 -1
  201. package/dist/gateway/static/root/assets/notes-workbench-BGjEC89c.js +0 -4
  202. package/dist/gateway/static/root/assets/project-detail-page-Dj9kEQwg.js +0 -1
  203. package/dist/gateway/static/root/assets/projects-page-CBRy5Ezz.js +0 -1
  204. package/dist/gateway/static/root/assets/remote-access-hub-DSwz9RBh.js +0 -1
  205. package/dist/gateway/static/root/assets/sessions-page-WtattyVX.js +0 -1
  206. package/dist/gateway/static/root/assets/settings-advanced-gate-CNAz_q1F.js +0 -1
  207. package/dist/gateway/static/root/assets/setup-status-panel-CNo4Ajhn.js +0 -1
  208. package/dist/gateway/static/root/assets/share-preview-page-B7PI3yZ6.js +0 -2
  209. package/dist/gateway/static/root/assets/shares-settings-DpOH0zWB.js +0 -1
  210. package/dist/gateway/static/root/assets/skill-reload-api-BOf4xCat.js +0 -1
  211. package/dist/gateway/static/root/assets/task-detail-page-DrMX5Yhj.js +0 -1
  212. package/dist/gateway/static/root/assets/user-context-page-ewIK2ddC.js +0 -1
  213. package/dist/gateway/static/root/assets/workflows-page-Bdn82kFQ.js +0 -5
@@ -9,5 +9,5 @@ export { acquireEmbeddedSessionRunner, buildEmbeddedRunnerFingerprint, evictAllE
9
9
  export { DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, resolveLiveToolResultMaxChars, truncateToolResultMessage, } from './tool-result-truncation.js';
10
10
  export { runXopcEmbeddedTurn, abortEmbeddedRun, queueEmbeddedSteer } from './run-turn.js';
11
11
  export { runEmbeddedTurnForSession } from './run-for-session.js';
12
- export { registerEmbeddedRun, getEmbeddedRunBySessionKey } from './runs.js';
12
+ export { getEmbeddedRunBySessionKey } from './runs.js';
13
13
  export type { RunXopcEmbeddedTurnParams, RunXopcEmbeddedTurnResult, EmbeddedStreamEvent } from './types.js';
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, resolveLiveToolResultMaxChars, truncateToolResultMessage } from "./tool-result-truncation.js";
2
2
  import { getRawSessionAppendMessage, guardSessionManager, installSessionToolResultGuard } from "./session-tool-result-guard.js";
3
3
  import { acquireEmbeddedSessionRunner, buildEmbeddedRunnerFingerprint, evictAllEmbeddedSessionRunners, evictEmbeddedSessionRunner, getEmbeddedSessionRunnerIdleTtlMs, getEmbeddedSessionRunnerStats, isEmbeddedSessionRunnerEnabled, resetEmbeddedSessionRunnerForTest } from "./session-runner.js";
4
- import { abortEmbeddedRun, getEmbeddedRunBySessionKey, queueEmbeddedSteer, registerEmbeddedRun } from "./runs.js";
4
+ import { abortEmbeddedRun, getEmbeddedRunBySessionKey, queueEmbeddedSteer } from "./runs.js";
5
5
  import { repairAssistantUsageInSessionManager } from "./session-manager-init.js";
6
6
  import { openSqliteHydratingSessionManager } from "./sqlite-hydrating-session-manager.js";
7
7
  import { InMemoryTranscriptRuntime, createSqliteTranscriptRuntime } from "./transcript-runtime.js";
@@ -9,4 +9,4 @@ import { runXopcEmbeddedTurn } from "./run-turn.js";
9
9
  import { getEmbeddedExecutionSession, runWithEmbeddedExecutionSession } from "./execution-context.js";
10
10
  import { runEmbeddedTurnForSession } from "./run-for-session.js";
11
11
  import { CURRENT_SESSION_VERSION, PiTranscriptManager } from "./pi-transcript.js";
12
- export { CURRENT_SESSION_VERSION, DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, InMemoryTranscriptRuntime, PiTranscriptManager, abortEmbeddedRun, acquireEmbeddedSessionRunner, buildEmbeddedRunnerFingerprint, createSqliteTranscriptRuntime, evictAllEmbeddedSessionRunners, evictEmbeddedSessionRunner, getEmbeddedExecutionSession, getEmbeddedRunBySessionKey, getEmbeddedSessionRunnerIdleTtlMs, getEmbeddedSessionRunnerStats, getRawSessionAppendMessage, guardSessionManager, installSessionToolResultGuard, isEmbeddedSessionRunnerEnabled, openSqliteHydratingSessionManager, queueEmbeddedSteer, registerEmbeddedRun, repairAssistantUsageInSessionManager, resetEmbeddedSessionRunnerForTest, resolveLiveToolResultMaxChars, runEmbeddedTurnForSession, runWithEmbeddedExecutionSession, runXopcEmbeddedTurn, truncateToolResultMessage };
12
+ export { CURRENT_SESSION_VERSION, DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, InMemoryTranscriptRuntime, PiTranscriptManager, abortEmbeddedRun, acquireEmbeddedSessionRunner, buildEmbeddedRunnerFingerprint, createSqliteTranscriptRuntime, evictAllEmbeddedSessionRunners, evictEmbeddedSessionRunner, getEmbeddedExecutionSession, getEmbeddedRunBySessionKey, getEmbeddedSessionRunnerIdleTtlMs, getEmbeddedSessionRunnerStats, getRawSessionAppendMessage, guardSessionManager, installSessionToolResultGuard, isEmbeddedSessionRunnerEnabled, openSqliteHydratingSessionManager, queueEmbeddedSteer, repairAssistantUsageInSessionManager, resetEmbeddedSessionRunnerForTest, resolveLiveToolResultMaxChars, runEmbeddedTurnForSession, runWithEmbeddedExecutionSession, runXopcEmbeddedTurn, truncateToolResultMessage };
@@ -8,6 +8,7 @@ import { evaluateContextBudget } from "../memory/context-budget.js";
8
8
  import { resolveCompactionPolicy } from "../memory/compaction-policy.js";
9
9
  import { runXopcEmbeddedTurn } from "./run-turn.js";
10
10
  import { applyStartupContextToUserMessage } from "../reply/apply-turn-user-enrichment.js";
11
+ import { AgentRunSupervisor } from "../orchestration/agent-run-supervisor.js";
11
12
  import crypto from "node:crypto";
12
13
  //#region src/agent/embedded/run-for-session.ts
13
14
  init_logger();
@@ -16,67 +17,93 @@ const log = createLogger("EmbeddedTurnForSession");
16
17
  async function runEmbeddedTurnForSession(params) {
17
18
  const { sessionKey, agentManager, modelManager, sessionStore, userMessage } = params;
18
19
  const runId = params.runId ?? crypto.randomUUID();
19
- await params.beforeTurn?.();
20
- const agent = agentManager.getOrCreateAgent(sessionKey);
21
- const mm = modelManager;
22
- const configuredModelRef = String(mm.getModelForSession(sessionKey));
23
- const candidates = typeof mm.getFallbackCandidatesForSession === "function" ? mm.getFallbackCandidatesForSession(sessionKey) : [];
24
- const candidateModelRefs = candidates.length > 0 ? candidates.map((candidate) => `${candidate.provider}/${candidate.model}`) : [configuredModelRef];
25
- const resolvedCandidates = [];
26
- for (const [index, ref] of candidateModelRefs.entries()) try {
27
- const resolved = index === 0 && typeof mm.getResolvedModelForSession === "function" ? mm.getResolvedModelForSession(sessionKey) : resolveModel(ref);
28
- resolvedCandidates.push({
29
- ref,
30
- model: resolved
31
- });
32
- } catch (err) {
33
- log.warn({
34
- err,
35
- sessionKey,
36
- runId,
37
- modelRef: ref
38
- }, "Skipping unavailable model candidate");
39
- }
40
- const primary = resolvedCandidates[0];
41
- if (!primary) throw new Error(`No available model candidates for '${configuredModelRef}'`);
42
- const modelRef = primary.ref;
43
- const model = primary.model;
44
- if (typeof mm.applyResolvedModel === "function") mm.applyResolvedModel(agent, model, modelRef);
45
- else await mm.applyModelForSession(agent, sessionKey);
46
- agentManager.setModelForSession(sessionKey, modelRef);
47
- const tools = agent.state.tools;
48
- const systemPrompt = agent.state.systemPrompt ?? "";
49
- const thinkingLevel = params.thinkingOverride ?? agent.state.thinkingLevel;
50
- const workspaceDir = agentManager.getResolvedWorkspaceForSession(sessionKey);
51
20
  const config = params.getConfig?.();
52
- const promptCachePolicy = resolvePromptCachePolicy(config ? resolveEffectiveAgentProfileForSession(config, sessionKey).manifest.runtime?.promptCache : void 0);
53
- const configuredTurnTimeoutMs = resolveAgentTurnTimeoutMs(config, sessionKey);
54
- const turnTimeoutMs = params.deadlineAtMs === void 0 ? configuredTurnTimeoutMs : Math.max(1, Math.min(configuredTurnTimeoutMs, params.deadlineAtMs - Date.now()));
55
- let userMessageForTurn = userMessage;
56
- if (params.applyStartupContext !== false) userMessageForTurn = await applyStartupContextToUserMessage({
57
- userMessage,
58
- sessionKey,
59
- workspaceDir,
60
- cfg: config,
61
- sessionStore,
62
- startupAction: params.startupAction,
63
- force: params.forceStartupContext
21
+ const supervisor = new AgentRunSupervisor({
22
+ timeoutMs: resolveAgentTurnTimeoutMs(config, sessionKey),
23
+ deadlineAtMs: params.deadlineAtMs,
24
+ parentSignal: params.abortSignal
64
25
  });
65
- return await (async () => {
66
- await maybeAutoCompactBeforeTurn({
67
- sessionKey,
68
- sessionStore,
69
- agentManager,
70
- model,
71
- config,
72
- systemPrompt,
73
- userMessage: userMessageForTurn,
74
- tools,
75
- imageCount: params.llmImages?.length ?? 0,
76
- fallbackModels: resolvedCandidates.slice(1).map((candidate) => candidate.model),
77
- abortSignal: params.abortSignal,
78
- onEvent: params.onEvent
79
- });
26
+ try {
27
+ await params.beforeTurn?.();
28
+ if (supervisor.signal.aborted) return {
29
+ ok: false,
30
+ errorMessage: "aborted"
31
+ };
32
+ const agent = agentManager.getOrCreateAgent(sessionKey);
33
+ const mm = modelManager;
34
+ const configuredModelRef = String(mm.getModelForSession(sessionKey));
35
+ const candidates = typeof mm.getFallbackCandidatesForSession === "function" ? mm.getFallbackCandidatesForSession(sessionKey) : [];
36
+ const candidateModelRefs = candidates.length > 0 ? candidates.map((candidate) => `${candidate.provider}/${candidate.model}`) : [configuredModelRef];
37
+ const resolvedCandidates = [];
38
+ for (const [index, ref] of candidateModelRefs.entries()) try {
39
+ const resolved = index === 0 && typeof mm.getResolvedModelForSession === "function" ? mm.getResolvedModelForSession(sessionKey) : resolveModel(ref);
40
+ resolvedCandidates.push({
41
+ ref,
42
+ model: resolved
43
+ });
44
+ } catch (err) {
45
+ log.warn({
46
+ err,
47
+ sessionKey,
48
+ runId,
49
+ modelRef: ref
50
+ }, "Skipping unavailable model candidate");
51
+ }
52
+ const primary = resolvedCandidates[0];
53
+ if (!primary) throw new Error(`No available model candidates for '${configuredModelRef}'`);
54
+ const modelRef = primary.ref;
55
+ const model = primary.model;
56
+ if (typeof mm.applyResolvedModel === "function") mm.applyResolvedModel(agent, model, modelRef);
57
+ else await mm.applyModelForSession(agent, sessionKey);
58
+ agentManager.setModelForSession(sessionKey, modelRef);
59
+ const tools = agent.state.tools;
60
+ const turnPolicy = agentManager.createAgentTurnPolicy(sessionKey);
61
+ const systemPrompt = agent.state.systemPrompt ?? "";
62
+ const thinkingLevel = params.thinkingOverride ?? agent.state.thinkingLevel;
63
+ const workspaceDir = agentManager.getResolvedWorkspaceForSession(sessionKey);
64
+ const promptCachePolicy = resolvePromptCachePolicy(config ? resolveEffectiveAgentProfileForSession(config, sessionKey).manifest.runtime?.promptCache : void 0);
65
+ let userMessageForTurn = userMessage;
66
+ if (params.applyStartupContext !== false) {
67
+ userMessageForTurn = await applyStartupContextToUserMessage({
68
+ userMessage,
69
+ sessionKey,
70
+ workspaceDir,
71
+ cfg: config,
72
+ sessionStore,
73
+ startupAction: params.startupAction,
74
+ force: params.forceStartupContext
75
+ });
76
+ if (supervisor.signal.aborted) return {
77
+ ok: false,
78
+ errorMessage: "aborted"
79
+ };
80
+ }
81
+ try {
82
+ await maybeAutoCompactBeforeTurn({
83
+ sessionKey,
84
+ sessionStore,
85
+ agentManager,
86
+ model,
87
+ config,
88
+ systemPrompt,
89
+ userMessage: userMessageForTurn,
90
+ tools,
91
+ imageCount: params.llmImages?.length ?? 0,
92
+ fallbackModels: resolvedCandidates.slice(1).map((candidate) => candidate.model),
93
+ abortSignal: supervisor.signal,
94
+ onEvent: params.onEvent
95
+ });
96
+ } catch (err) {
97
+ if (supervisor.signal.aborted) return {
98
+ ok: false,
99
+ errorMessage: "aborted"
100
+ };
101
+ throw err;
102
+ }
103
+ if (supervisor.signal.aborted) return {
104
+ ok: false,
105
+ errorMessage: "aborted"
106
+ };
80
107
  log.info({
81
108
  sessionKey,
82
109
  runId,
@@ -94,6 +121,14 @@ async function runEmbeddedTurnForSession(params) {
94
121
  const isFallbackAttempt = i > 0;
95
122
  const candidateModel = candidate.model;
96
123
  const hasNextCandidate = i + 1 < resolvedCandidates.length;
124
+ const attemptPlan = supervisor.planModelAttempt(isFallbackAttempt);
125
+ if (attemptPlan.ok === false) {
126
+ lastResult = {
127
+ ok: false,
128
+ errorMessage: attemptPlan.reason
129
+ };
130
+ break;
131
+ }
97
132
  const rowsBeforeAttempt = hasNextCandidate ? await sessionStore.loadTranscriptRows(sessionKey) : void 0;
98
133
  if (typeof mm.applyResolvedModel === "function") mm.applyResolvedModel(agent, candidateModel, candidateModelRef);
99
134
  agentManager.setModelForSession(sessionKey, candidateModelRef);
@@ -119,8 +154,9 @@ async function runEmbeddedTurnForSession(params) {
119
154
  promptCachePolicy,
120
155
  workspaceDir,
121
156
  sessionStore,
122
- timeoutMs: turnTimeoutMs,
123
- abortSignal: params.abortSignal,
157
+ timeoutMs: attemptPlan.timeoutMs,
158
+ turnPolicy,
159
+ abortSignal: supervisor.signal,
124
160
  onEvent: params.onEvent,
125
161
  resumeLastUserMessage
126
162
  });
@@ -136,6 +172,7 @@ async function runEmbeddedTurnForSession(params) {
136
172
  return turnResult;
137
173
  }
138
174
  lastResult = turnResult;
175
+ if (supervisor.signal.aborted || turnResult.retryable === false) break;
139
176
  log.warn({
140
177
  sessionKey,
141
178
  runId,
@@ -179,7 +216,9 @@ async function runEmbeddedTurnForSession(params) {
179
216
  ok: false,
180
217
  errorMessage: "No model candidates available"
181
218
  };
182
- })();
219
+ } finally {
220
+ supervisor.dispose();
221
+ }
183
222
  }
184
223
  function serializedTranscriptBytes(messages) {
185
224
  return Buffer.byteLength(JSON.stringify(messages), "utf8");
@@ -1,17 +1,17 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
3
+ import { isAgentTurnUnsettledError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
4
4
  import { resolvePromptCachePolicy } from "../../providers/prompt-cache-plan.js";
5
5
  import { wrapStreamFnForXopcExtensions } from "./xopc-stream-bridge.js";
6
- import { acquireEmbeddedSessionRunner } from "./session-runner.js";
6
+ import { acquireEmbeddedSessionRunner, evictEmbeddedSessionRunner } from "./session-runner.js";
7
+ import { isContextOverflowError } from "../orchestration/context-overflow.js";
7
8
  import { getAssistantTurnErrorMessage, isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages } from "../orchestration/llm-turn-retry.js";
8
9
  import { projectContextForModel } from "../memory/context-budget.js";
9
- import { abortEmbeddedRun, queueEmbeddedSteer, registerEmbeddedRun, unregisterEmbeddedRun } from "./runs.js";
10
+ import { EmbeddedRunConflictError, abortEmbeddedRun, acquireEmbeddedRunLease, queueEmbeddedSteer } from "./runs.js";
10
11
  import { lastAssistantPlainText, subscribeEmbeddedSessionEvents } from "./subscribe-session.js";
11
12
  import { detectToolLoops } from "../orchestration/loop-guard.js";
12
13
  import { tryApplySessionTranscriptHygiene } from "../transcript/transcript-hygiene.js";
13
14
  import { createSqliteTranscriptRuntime } from "./transcript-runtime.js";
14
- import { isContextOverflowError } from "../orchestration/context-overflow.js";
15
15
  import { buildPromptCacheSnapshot, observePromptCacheSnapshot } from "../../providers/prompt-cache-observability.js";
16
16
  import { isPromptCacheExpired, recordPromptCacheTouch } from "../../providers/prompt-cache-lifecycle.js";
17
17
  //#region src/agent/embedded/run-turn.ts
@@ -83,9 +83,10 @@ async function maybeRecoverContextOverflow(params) {
83
83
  type: "compaction",
84
84
  status: "started"
85
85
  });
86
- const result = await params.transcriptRuntime.compact(messages, params.model, "Preserve the current pending user request verbatim and retain every fact needed to answer it.", true);
86
+ const result = await params.transcriptRuntime.compact(messages, params.model, "Preserve the current pending user request verbatim and retain every fact needed to answer it.", true, { signal: params.abortSignal });
87
87
  if (!result.compacted) throw new Error(`Context overflow recovery could not find a safe compaction range: ${errorMessage}`);
88
88
  params.agent.state.messages = await params.transcriptRuntime.loadMessages();
89
+ params.abortSignal?.throwIfAborted();
89
90
  params.onEvent?.({
90
91
  type: "compaction",
91
92
  status: "completed",
@@ -109,7 +110,14 @@ async function runXopcEmbeddedTurn(params) {
109
110
  if (!transcriptRuntime) throw new Error("Embedded run requires a transcript runtime");
110
111
  let runner;
111
112
  let unsubscribe;
113
+ let quarantineRunner = false;
114
+ let runLease;
112
115
  try {
116
+ runLease = acquireEmbeddedRunLease({
117
+ sessionKey,
118
+ sessionId: transcriptRuntime.sessionId,
119
+ runId
120
+ });
113
121
  runner = await acquireEmbeddedSessionRunner({
114
122
  runtimeId: transcriptRuntime.runtimeId,
115
123
  sessionId: transcriptRuntime.sessionId,
@@ -122,6 +130,15 @@ async function runXopcEmbeddedTurn(params) {
122
130
  transcriptRuntime
123
131
  });
124
132
  const { session, reused } = runner;
133
+ await runLease.attach(session, async () => session.abort());
134
+ const runAbortSignal = params.abortSignal ? AbortSignal.any([runLease.signal, params.abortSignal]) : runLease.signal;
135
+ if (runAbortSignal.aborted) {
136
+ await session.abort();
137
+ return {
138
+ ok: false,
139
+ errorMessage: "aborted"
140
+ };
141
+ }
125
142
  runner.piSm.setActiveTurnId?.(runId);
126
143
  const streamFnWithXopcExtensions = wrapStreamFnForXopcExtensions(session.agent.streamFunction, params.promptCachePolicy);
127
144
  const loggingStreamFn = (streamModel, context, options) => {
@@ -197,6 +214,10 @@ async function runXopcEmbeddedTurn(params) {
197
214
  return streamFnWithXopcExtensions(streamModel, effectiveContext, { ...options });
198
215
  };
199
216
  session.agent.streamFunction = loggingStreamFn;
217
+ params.turnPolicy?.reset();
218
+ session.agent.beforeToolCall = params.turnPolicy?.beforeToolCall;
219
+ session.agent.afterToolCall = params.turnPolicy?.afterToolCall;
220
+ session.agent.shouldStopAfterTurn = params.turnPolicy?.shouldStopAfterTurn;
200
221
  unsubscribe = subscribeEmbeddedSessionEvents(session, (event) => {
201
222
  if (event.type === "message_end" && event.message.role === "assistant") recordPromptCacheTouch(sessionKey, resolvedModel, event.message.usage);
202
223
  onEvent?.({
@@ -204,29 +225,10 @@ async function runXopcEmbeddedTurn(params) {
204
225
  runId
205
226
  });
206
227
  });
207
- const handle = {
208
- sessionKey,
209
- sessionId: transcriptRuntime.sessionId,
210
- runId,
211
- session,
212
- abort: async () => {
213
- await session.abort();
214
- }
215
- };
216
- registerEmbeddedRun(handle);
217
228
  const abortListener = () => {
218
229
  session.abort();
219
230
  };
220
- if (params.abortSignal) {
221
- if (params.abortSignal.aborted) {
222
- await session.abort();
223
- return {
224
- ok: false,
225
- errorMessage: "aborted"
226
- };
227
- }
228
- params.abortSignal.addEventListener("abort", abortListener, { once: true });
229
- }
231
+ runAbortSignal.addEventListener("abort", abortListener, { once: true });
230
232
  try {
231
233
  await runAgentTurnWithTimeout(session.agent, async () => {
232
234
  if (params.resumeLastUserMessage) await session.agent.continue();
@@ -238,16 +240,22 @@ async function runXopcEmbeddedTurn(params) {
238
240
  await session.agent.waitForIdle();
239
241
  await maybeRetryTurnAfterTransientLlmFailure(session.agent, {
240
242
  sessionKey,
241
- log
243
+ log,
244
+ signal: runAbortSignal
242
245
  });
243
246
  await maybeRecoverContextOverflow({
244
247
  agent: session.agent,
245
248
  model: resolvedModel,
246
249
  sessionKey,
247
250
  transcriptRuntime,
251
+ abortSignal: runAbortSignal,
248
252
  onEvent
249
253
  });
250
254
  }, timeoutMs);
255
+ if (runAbortSignal.aborted) return {
256
+ ok: false,
257
+ errorMessage: "aborted"
258
+ };
251
259
  if (isAssistantTurnAborted(session.agent)) return {
252
260
  ok: true,
253
261
  lastAssistantText: lastAssistantPlainText(session)
@@ -262,10 +270,28 @@ async function runXopcEmbeddedTurn(params) {
262
270
  lastAssistantText: lastAssistantPlainText(session)
263
271
  };
264
272
  } finally {
265
- params.abortSignal?.removeEventListener("abort", abortListener);
266
- unregisterEmbeddedRun(handle);
273
+ runAbortSignal.removeEventListener("abort", abortListener);
267
274
  }
268
275
  } catch (err) {
276
+ if (err instanceof EmbeddedRunConflictError) {
277
+ const em = err.message;
278
+ log.warn({
279
+ sessionKey,
280
+ runId,
281
+ activeRunId: err.activeRunId
282
+ }, `Embedded run rejected: ${em}`);
283
+ onEvent?.({
284
+ type: "error",
285
+ content: em,
286
+ runId
287
+ });
288
+ return {
289
+ ok: false,
290
+ retryable: false,
291
+ errorMessage: em
292
+ };
293
+ }
294
+ quarantineRunner = isAgentTurnUnsettledError(err);
269
295
  const em = err instanceof Error ? err.message : String(err);
270
296
  log.error({
271
297
  err,
@@ -282,11 +308,13 @@ async function runXopcEmbeddedTurn(params) {
282
308
  errorMessage: em
283
309
  };
284
310
  } finally {
311
+ runLease?.release();
285
312
  unsubscribe?.();
286
313
  try {
287
314
  runner?.piSm.flushPendingToolResults?.();
288
315
  } catch {}
289
316
  runner?.piSm.setActiveTurnId?.(null);
317
+ if (quarantineRunner) evictEmbeddedSessionRunner(transcriptRuntime.runtimeId, "unsettled_after_timeout");
290
318
  runner?.release();
291
319
  }
292
320
  }
@@ -1,46 +1,33 @@
1
1
  import type { AgentSession } from '@earendil-works/pi-coding-agent';
2
- export type EmbeddedRunHandle = {
2
+ export type EmbeddedRunIdentity = {
3
3
  sessionKey: string;
4
4
  sessionId: string;
5
5
  runId: string;
6
+ };
7
+ export type EmbeddedRunHandle = EmbeddedRunIdentity & {
6
8
  session: AgentSession;
7
9
  abort: () => Promise<void>;
8
10
  };
9
- /**
10
- * Tracks in-flight embedded agent turns so we can abort/steer them by sessionKey or runId.
11
- *
12
- * The previous implementation used two module-level Maps; this class is the supported
13
- * single-instance state, while {@link defaultEmbeddedRunRegistry} preserves the previous
14
- * free-function API for callers that have not yet been moved to dependency injection.
15
- */
11
+ export declare class EmbeddedRunConflictError extends Error {
12
+ readonly sessionKey: string;
13
+ readonly activeRunId: string;
14
+ constructor(sessionKey: string, activeRunId: string);
15
+ }
16
+ export type EmbeddedRunLease = {
17
+ signal: AbortSignal;
18
+ attach(session: AgentSession, abort: () => Promise<void>): Promise<void>;
19
+ release(): void;
20
+ };
21
+ /** Owns one process-local execution lease per session while leaving steer/abort on the control plane. */
16
22
  export declare class EmbeddedRunRegistry {
17
23
  private readonly bySessionKey;
18
- private readonly byRunId;
19
- /**
20
- * Register a new in-flight run. If a run is already registered for the same
21
- * sessionKey we drop the stale handle (the new run takes ownership). The caller
22
- * is responsible for aborting the previous run before re-registering if needed —
23
- * we warn loudly so this does not happen silently.
24
- */
25
- register(handle: EmbeddedRunHandle): void;
26
- unregister(handle: EmbeddedRunHandle): void;
24
+ acquire(identity: EmbeddedRunIdentity): EmbeddedRunLease;
27
25
  getBySessionKey(sessionKey: string): EmbeddedRunHandle | undefined;
28
- getByRunId(runId: string): EmbeddedRunHandle | undefined;
29
26
  abortBySessionKey(sessionKey: string): Promise<boolean>;
30
27
  steerBySessionKey(sessionKey: string, text: string): Promise<boolean>;
31
- /** Test-only helper to drop all registrations without touching live sessions. */
32
- resetForTest(): void;
33
28
  size(): number;
34
29
  }
35
- /**
36
- * Process-wide default registry. Prefer constructing a dedicated `EmbeddedRunRegistry`
37
- * and injecting it; the module-level singleton stays so the existing free functions
38
- * keep working until every caller has been migrated.
39
- */
40
- export declare const defaultEmbeddedRunRegistry: EmbeddedRunRegistry;
41
- export declare function registerEmbeddedRun(handle: EmbeddedRunHandle): void;
42
- export declare function unregisterEmbeddedRun(handle: EmbeddedRunHandle): void;
30
+ export declare function acquireEmbeddedRunLease(identity: EmbeddedRunIdentity): EmbeddedRunLease;
43
31
  export declare function getEmbeddedRunBySessionKey(sessionKey: string): EmbeddedRunHandle | undefined;
44
- export declare function getEmbeddedRunByRunId(runId: string): EmbeddedRunHandle | undefined;
45
32
  export declare function abortEmbeddedRun(sessionKey: string): Promise<boolean>;
46
33
  export declare function queueEmbeddedSteer(sessionKey: string, text: string): Promise<boolean>;
@@ -1,91 +1,70 @@
1
- import { createLogger } from "../../utils/logger/index.js";
2
- import { init_logger } from "../../utils/logger.js";
3
1
  //#region src/agent/embedded/runs.ts
4
- init_logger();
5
- const log = createLogger("EmbeddedRunRegistry");
6
- /**
7
- * Tracks in-flight embedded agent turns so we can abort/steer them by sessionKey or runId.
8
- *
9
- * The previous implementation used two module-level Maps; this class is the supported
10
- * single-instance state, while {@link defaultEmbeddedRunRegistry} preserves the previous
11
- * free-function API for callers that have not yet been moved to dependency injection.
12
- */
2
+ var EmbeddedRunConflictError = class extends Error {
3
+ constructor(sessionKey, activeRunId) {
4
+ super(`Session '${sessionKey}' already has active embedded run '${activeRunId}'`);
5
+ this.sessionKey = sessionKey;
6
+ this.activeRunId = activeRunId;
7
+ this.name = "EmbeddedRunConflictError";
8
+ }
9
+ };
10
+ /** Owns one process-local execution lease per session while leaving steer/abort on the control plane. */
13
11
  var EmbeddedRunRegistry = class {
14
12
  bySessionKey = /* @__PURE__ */ new Map();
15
- byRunId = /* @__PURE__ */ new Map();
16
- /**
17
- * Register a new in-flight run. If a run is already registered for the same
18
- * sessionKey we drop the stale handle (the new run takes ownership). The caller
19
- * is responsible for aborting the previous run before re-registering if needed —
20
- * we warn loudly so this does not happen silently.
21
- */
22
- register(handle) {
23
- const previous = this.bySessionKey.get(handle.sessionKey);
24
- if (previous && previous !== handle) {
25
- log.warn({
26
- sessionKey: handle.sessionKey,
27
- previousRunId: previous.runId,
28
- newRunId: handle.runId
29
- }, "Replacing already-registered embedded run for sessionKey (caller did not unregister first)");
30
- this.byRunId.delete(previous.runId);
31
- }
32
- this.bySessionKey.set(handle.sessionKey, handle);
33
- this.byRunId.set(handle.runId, handle);
34
- }
35
- unregister(handle) {
36
- if (this.bySessionKey.get(handle.sessionKey) === handle) this.bySessionKey.delete(handle.sessionKey);
37
- this.byRunId.delete(handle.runId);
13
+ acquire(identity) {
14
+ const active = this.bySessionKey.get(identity.sessionKey);
15
+ if (active) throw new EmbeddedRunConflictError(identity.sessionKey, active.runId);
16
+ const entry = {
17
+ ...identity,
18
+ abortController: new AbortController()
19
+ };
20
+ this.bySessionKey.set(identity.sessionKey, entry);
21
+ return {
22
+ signal: entry.abortController.signal,
23
+ attach: async (session, abort) => {
24
+ entry.handle = {
25
+ ...identity,
26
+ session,
27
+ abort
28
+ };
29
+ if (entry.abortController.signal.aborted) await abort();
30
+ },
31
+ release: () => {
32
+ if (this.bySessionKey.get(identity.sessionKey) === entry) this.bySessionKey.delete(identity.sessionKey);
33
+ }
34
+ };
38
35
  }
39
36
  getBySessionKey(sessionKey) {
40
- return this.bySessionKey.get(sessionKey);
41
- }
42
- getByRunId(runId) {
43
- return this.byRunId.get(runId);
37
+ return this.bySessionKey.get(sessionKey)?.handle;
44
38
  }
45
39
  async abortBySessionKey(sessionKey) {
46
- const handle = this.bySessionKey.get(sessionKey);
47
- if (!handle) return false;
48
- await handle.abort();
40
+ const entry = this.bySessionKey.get(sessionKey);
41
+ if (!entry) return false;
42
+ entry.abortController.abort(/* @__PURE__ */ new Error("Embedded run aborted"));
43
+ if (entry.handle) await entry.handle.abort();
49
44
  return true;
50
45
  }
51
46
  async steerBySessionKey(sessionKey, text) {
52
- const handle = this.bySessionKey.get(sessionKey);
47
+ const handle = this.getBySessionKey(sessionKey);
53
48
  if (!handle) return false;
54
49
  await handle.session.steer(text);
55
50
  return true;
56
51
  }
57
- /** Test-only helper to drop all registrations without touching live sessions. */
58
- resetForTest() {
59
- this.bySessionKey.clear();
60
- this.byRunId.clear();
61
- }
62
52
  size() {
63
53
  return this.bySessionKey.size;
64
54
  }
65
55
  };
66
- /**
67
- * Process-wide default registry. Prefer constructing a dedicated `EmbeddedRunRegistry`
68
- * and injecting it; the module-level singleton stays so the existing free functions
69
- * keep working until every caller has been migrated.
70
- */
71
- const defaultEmbeddedRunRegistry = new EmbeddedRunRegistry();
72
- function registerEmbeddedRun(handle) {
73
- defaultEmbeddedRunRegistry.register(handle);
74
- }
75
- function unregisterEmbeddedRun(handle) {
76
- defaultEmbeddedRunRegistry.unregister(handle);
56
+ const embeddedRunRegistry = new EmbeddedRunRegistry();
57
+ function acquireEmbeddedRunLease(identity) {
58
+ return embeddedRunRegistry.acquire(identity);
77
59
  }
78
60
  function getEmbeddedRunBySessionKey(sessionKey) {
79
- return defaultEmbeddedRunRegistry.getBySessionKey(sessionKey);
80
- }
81
- function getEmbeddedRunByRunId(runId) {
82
- return defaultEmbeddedRunRegistry.getByRunId(runId);
61
+ return embeddedRunRegistry.getBySessionKey(sessionKey);
83
62
  }
84
63
  function abortEmbeddedRun(sessionKey) {
85
- return defaultEmbeddedRunRegistry.abortBySessionKey(sessionKey);
64
+ return embeddedRunRegistry.abortBySessionKey(sessionKey);
86
65
  }
87
66
  function queueEmbeddedSteer(sessionKey, text) {
88
- return defaultEmbeddedRunRegistry.steerBySessionKey(sessionKey, text);
67
+ return embeddedRunRegistry.steerBySessionKey(sessionKey, text);
89
68
  }
90
69
  //#endregion
91
- export { EmbeddedRunRegistry, abortEmbeddedRun, defaultEmbeddedRunRegistry, getEmbeddedRunByRunId, getEmbeddedRunBySessionKey, queueEmbeddedSteer, registerEmbeddedRun, unregisterEmbeddedRun };
70
+ export { EmbeddedRunConflictError, EmbeddedRunRegistry, abortEmbeddedRun, acquireEmbeddedRunLease, getEmbeddedRunBySessionKey, queueEmbeddedSteer };
@@ -2,6 +2,7 @@ import type { AgentMessage, AgentToolResult, ThinkingLevel } from '@earendil-wor
2
2
  import type { AssistantMessageEvent, Model, Api, ImageContent } from '@earendil-works/pi-ai';
3
3
  import type { SessionStore } from '../../session/store.js';
4
4
  import type { EmbeddedTranscriptRuntime } from './transcript-runtime.js';
5
+ import type { AgentTurnPolicy } from '../orchestration/agent-turn-policy.js';
5
6
  export type EmbeddedStreamEvent = {
6
7
  type: 'agent_start';
7
8
  runId?: string;
@@ -97,6 +98,7 @@ export type RunXopcEmbeddedTurnParams = {
97
98
  sessionStore?: SessionStore;
98
99
  transcriptRuntime?: EmbeddedTranscriptRuntime;
99
100
  timeoutMs: number;
101
+ turnPolicy?: AgentTurnPolicy;
100
102
  abortSignal?: AbortSignal;
101
103
  onEvent?: (event: EmbeddedStreamEvent) => void;
102
104
  images?: ImageContent[];
@@ -105,6 +107,8 @@ export type RunXopcEmbeddedTurnParams = {
105
107
  };
106
108
  export type RunXopcEmbeddedTurnResult = {
107
109
  ok: boolean;
110
+ /** False for harness failures that must not trigger another model attempt. */
111
+ retryable?: boolean;
108
112
  errorMessage?: string;
109
113
  lastAssistantText?: string;
110
114
  };
@@ -0,0 +1,28 @@
1
+ export type ModelAttemptPlan = {
2
+ ok: true;
3
+ timeoutMs: number;
4
+ remainingMs: number;
5
+ } | {
6
+ ok: false;
7
+ reason: string;
8
+ };
9
+ export interface AgentRunSupervisorOptions {
10
+ timeoutMs: number;
11
+ deadlineAtMs?: number;
12
+ parentSignal?: AbortSignal;
13
+ minimumFallbackMs?: number;
14
+ }
15
+ /** Minimal run-level coordination: root cancellation and per-attempt deadline planning. */
16
+ export declare class AgentRunSupervisor {
17
+ readonly deadlineAtMs: number;
18
+ readonly signal: AbortSignal;
19
+ private readonly controller;
20
+ private readonly timeout;
21
+ private readonly forwardParentAbort;
22
+ private readonly timeoutMs;
23
+ private readonly minimumFallbackMs;
24
+ private readonly parentSignal?;
25
+ constructor(options: AgentRunSupervisorOptions);
26
+ planModelAttempt(isFallback: boolean): ModelAttemptPlan;
27
+ dispose(): void;
28
+ }