@code-yeongyu/senpi 2026.11.2-3 → 2026.11.3-2

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 (307) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/bundle/chunks/anthropic-messages-LJAKRKMX.js +11 -0
  3. package/dist/bundle/chunks/{args-AOI4NEA6.js → args-GQTXDYS3.js} +1 -1
  4. package/dist/bundle/chunks/{azure-openai-responses-YLBBQXI7.js → azure-openai-responses-HDEKTPMZ.js} +1 -1
  5. package/dist/bundle/chunks/chatgpt-subscription.js +10 -2
  6. package/dist/bundle/chunks/{chunk-ED7VJGL4.js → chunk-2PGSRQBF.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-LMIETUPG.js → chunk-3LDASCJN.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-PIAY636U.js → chunk-3QPE75AR.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-FQZZGSYH.js → chunk-4ZGQUOBV.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-S2M5D5GS.js → chunk-5BMIET5O.js} +2 -2
  11. package/dist/bundle/chunks/{chunk-XLLQJALL.js → chunk-67M7HKXO.js} +1 -1
  12. package/dist/bundle/chunks/chunk-6ISOXWH2.js +2 -0
  13. package/dist/bundle/chunks/{chunk-IWM5QRAE.js → chunk-6NPK2O3C.js} +2 -2
  14. package/dist/bundle/chunks/{chunk-FO56LSUK.js → chunk-7C4W5HMU.js} +1 -1
  15. package/dist/bundle/chunks/chunk-7KIHKE2T.js +2 -0
  16. package/dist/bundle/chunks/{chunk-BW4YXS7X.js → chunk-A4KOQUHT.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-FJSJUVQQ.js → chunk-A5PZGQCP.js} +3 -3
  18. package/dist/bundle/chunks/{chunk-TBARMJ75.js → chunk-AVP6DDBF.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-KVPRQ5KN.js → chunk-B3GTID4P.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-2XBKE2BZ.js → chunk-BIWFWGUA.js} +1 -1
  21. package/dist/bundle/chunks/{chunk-6LDUM5CL.js → chunk-DCI4QOUX.js} +1 -1
  22. package/dist/bundle/chunks/{chunk-2YFPDNNP.js → chunk-DNZKKG4V.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-W2V7RIBF.js → chunk-E7SA75PP.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-YWD54RHU.js → chunk-EBZ6IP4V.js} +1 -1
  25. package/dist/bundle/chunks/{chunk-N4TSAHRL.js → chunk-EVTTLPIY.js} +1 -1
  26. package/dist/bundle/chunks/{chunk-J2OBN7TI.js → chunk-G5XUGK4B.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-IHOQR7TU.js → chunk-GKP34H3C.js} +2 -2
  28. package/dist/bundle/chunks/{chunk-PP52OWBB.js → chunk-GLTOBXZY.js} +1 -1
  29. package/dist/bundle/chunks/{chunk-ZSVWKOAJ.js → chunk-IJGXAACA.js} +263 -237
  30. package/dist/bundle/chunks/{chunk-LGO25HPL.js → chunk-JCTODLUP.js} +1 -1
  31. package/dist/bundle/chunks/{chunk-3ESZE3DG.js → chunk-KHBCZ6TR.js} +1 -1
  32. package/dist/bundle/chunks/chunk-KJR3XXMI.js +2 -0
  33. package/dist/bundle/chunks/{chunk-TVMW2SUP.js → chunk-KY4V3TSO.js} +2 -2
  34. package/dist/bundle/chunks/{chunk-T5ZJ2Q4O.js → chunk-MCXOJHN2.js} +1 -1
  35. package/dist/bundle/chunks/{chunk-GIY7PGOH.js → chunk-NKI7L5UM.js} +3 -3
  36. package/dist/bundle/chunks/{chunk-L3V65XW7.js → chunk-OD7RT7G7.js} +1 -1
  37. package/dist/bundle/chunks/{chunk-NYXXKS6D.js → chunk-OOU3BRUY.js} +3 -2
  38. package/dist/bundle/chunks/{chunk-LPHUMR6R.js → chunk-OT6ALXSJ.js} +1 -1
  39. package/dist/bundle/chunks/{chunk-XGBRBCIQ.js → chunk-Q5CKFBQT.js} +1 -1
  40. package/dist/bundle/chunks/{chunk-F7GBSQRV.js → chunk-QPYDQ4QK.js} +1 -1
  41. package/dist/bundle/chunks/{chunk-7FUO655J.js → chunk-QSMT5KVJ.js} +1 -1
  42. package/dist/bundle/chunks/{chunk-SAZ6E74O.js → chunk-RUOTFZQR.js} +1 -1
  43. package/dist/bundle/chunks/chunk-RWF6IJQL.js +448 -0
  44. package/dist/bundle/chunks/{chunk-P4AT7SBE.js → chunk-S5Y7NEHB.js} +1 -1
  45. package/dist/bundle/chunks/{chunk-QLTQ3UUI.js → chunk-SCBTASM4.js} +1 -1
  46. package/dist/bundle/chunks/chunk-SJWTZ3Z2.js +2 -0
  47. package/dist/bundle/chunks/{chunk-ISZ4EWIS.js → chunk-SODMQEHO.js} +1 -1
  48. package/dist/bundle/chunks/{chunk-WEGTCUO3.js → chunk-SQAQEITV.js} +1 -1
  49. package/dist/bundle/chunks/{chunk-UFVZTQKN.js → chunk-TQQG5L4D.js} +1 -1
  50. package/dist/bundle/chunks/{chunk-662SCMTH.js → chunk-U6A4X3FV.js} +1 -1
  51. package/dist/bundle/chunks/{chunk-ACIFXWJ6.js → chunk-UHUM55TR.js} +1 -1
  52. package/dist/bundle/chunks/{chunk-L5OFGHDA.js → chunk-USKWGPA6.js} +1 -1
  53. package/dist/bundle/chunks/{chunk-7ORS33CE.js → chunk-VDDJADPV.js} +1 -1
  54. package/dist/bundle/chunks/{chunk-R65P6LAT.js → chunk-VIHXG53S.js} +1 -1
  55. package/dist/bundle/chunks/{chunk-SGS76663.js → chunk-VPVD5G32.js} +1 -1
  56. package/dist/bundle/chunks/chunk-WO6I5PRF.js +3 -0
  57. package/dist/bundle/chunks/{chunk-ETCYVVVO.js → chunk-WVEIJ437.js} +1 -1
  58. package/dist/bundle/chunks/{chunk-VRWJJMHO.js → chunk-XKFG4N3Z.js} +1 -1
  59. package/dist/bundle/chunks/{chunk-57MRFI6E.js → chunk-XMWPCJU6.js} +1 -1
  60. package/dist/bundle/chunks/{chunk-GDPWQJDQ.js → chunk-XPSXUKSD.js} +1 -1
  61. package/dist/bundle/chunks/{chunk-FNBEICAA.js → chunk-YI6KRJDC.js} +1 -1
  62. package/dist/bundle/chunks/{chunk-UURGXV5B.js → chunk-YP47G4YP.js} +1 -1
  63. package/dist/bundle/chunks/{chunk-TXOR5BQL.js → chunk-YRYDCKUI.js} +1 -1
  64. package/dist/bundle/chunks/{chunk-QAM6AXA2.js → chunk-YTKZSGMQ.js} +12 -9
  65. package/dist/bundle/chunks/{chunk-V36CXIIB.js → chunk-YXL3PNTL.js} +1 -1
  66. package/dist/bundle/chunks/chunk-Z7HTHT6K.js +2 -0
  67. package/dist/bundle/chunks/{chunk-27XEDYQA.js → chunk-ZTPG27EJ.js} +1 -1
  68. package/dist/bundle/chunks/{cli-main-534A3WSC.js → cli-main-RN7YB427.js} +1 -1
  69. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-FC7QLRU2.js → cloudflare-workers-ai-system-one-N5KFNKK4.js} +1 -1
  70. package/dist/bundle/chunks/credential-accounts-BJX55MTT.js +2 -0
  71. package/dist/bundle/chunks/devin.js +10 -2
  72. package/dist/bundle/chunks/{dispatch-UY6LBJJE.js → dispatch-M7UAPGVY.js} +1 -1
  73. package/dist/bundle/chunks/{google-generative-ai-7PQ4QRHJ.js → google-generative-ai-2TZSCSIS.js} +1 -1
  74. package/dist/bundle/chunks/{google-vertex-DY7EO4EJ.js → google-vertex-7NJJOI7V.js} +1 -1
  75. package/dist/bundle/chunks/{health-write-EB4CPHXN.js → health-write-YUSPVH7U.js} +1 -1
  76. package/dist/bundle/chunks/{help-fast-path-U2PSNNWO.js → help-fast-path-DWCA77QP.js} +1 -1
  77. package/dist/bundle/chunks/host-command-KJXUTSQ7.js +2 -0
  78. package/dist/bundle/chunks/{host-lifecycle-TGG7KGQH.js → host-lifecycle-QHIJ4G2K.js} +1 -1
  79. package/dist/bundle/chunks/host-lifecycle.js +1 -1
  80. package/dist/bundle/chunks/{host-session-command-PWVPQ2OV.js → host-session-command-IPH3WXSG.js} +1 -1
  81. package/dist/bundle/chunks/{host-socket-request-F2R5P34M.js → host-socket-request-XPXJV3CS.js} +1 -1
  82. package/dist/bundle/chunks/interactive-mode-XUXMDYLA.js +2 -0
  83. package/dist/bundle/chunks/{list-tips-3D3A6GFK.js → list-tips-XJY7EL5S.js} +1 -1
  84. package/dist/bundle/chunks/{login-health-7G2DZVOV.js → login-health-226NO44U.js} +1 -1
  85. package/dist/bundle/chunks/main-P7PKMJUG.js +2 -0
  86. package/dist/bundle/chunks/{mistral-conversations-6F2RAIB2.js → mistral-conversations-QMHMHSUF.js} +1 -1
  87. package/dist/bundle/chunks/{multi-session-host-7E26R5JF.js → multi-session-host-ZQY4AN46.js} +4 -4
  88. package/dist/bundle/chunks/{native-loader-NMDTMHMA.js → native-loader-A6DNMGCK.js} +1 -1
  89. package/dist/bundle/chunks/openai-chatgpt.js +11 -3
  90. package/dist/bundle/chunks/{openai-codex-responses-VNBMMIL3.js → openai-codex-responses-GUAHKQE2.js} +1 -1
  91. package/dist/bundle/chunks/{openai-completions-JLR32APM.js → openai-completions-UPRTFM54.js} +1 -1
  92. package/dist/bundle/chunks/{openai-images-LEBNERSM.js → openai-images-IKWNS6VB.js} +1 -1
  93. package/dist/bundle/chunks/{openai-responses-JCDUNMHA.js → openai-responses-AXN5NUHH.js} +1 -1
  94. package/dist/bundle/chunks/openrouter.js +10 -2
  95. package/dist/bundle/chunks/{package-manager-cli-CBSDV36M.js → package-manager-cli-PP7L2Q5M.js} +1 -1
  96. package/dist/bundle/chunks/radius.js +10 -2
  97. package/dist/bundle/chunks/{rg-engine-JDUYBM6L.js → rg-engine-VRSXT6HG.js} +1 -1
  98. package/dist/bundle/chunks/{role-LP6LVNCY.js → role-L5J7ZPCF.js} +1 -1
  99. package/dist/bundle/chunks/rotation-stream-6INZXQFC.js +2 -0
  100. package/dist/bundle/chunks/rpc-mode-W4UATRAT.js +2 -0
  101. package/dist/bundle/chunks/{rpc-monitor-source-5TUR27NY.js → rpc-monitor-source-RMMUPBMS.js} +1 -1
  102. package/dist/bundle/chunks/{run-attached-tui-PVLUHHJX.js → run-attached-tui-RLXFGCEP.js} +1 -1
  103. package/dist/bundle/chunks/{schedule-command-W45NYTTK.js → schedule-command-ZNFEJNTT.js} +1 -1
  104. package/dist/bundle/chunks/{session-control-endpoint-LFLUNALC.js → session-control-endpoint-TWTONJWF.js} +1 -1
  105. package/dist/bundle/chunks/{session-picker-OZUINLD7.js → session-picker-KRUVCHOV.js} +1 -1
  106. package/dist/bundle/chunks/session-slot-NJOZCOHQ.js +2 -0
  107. package/dist/bundle/chunks/session-worker.js +492 -461
  108. package/dist/bundle/chunks/{state-store-SZARKD36.js → state-store-ZAFZ4JOM.js} +1 -1
  109. package/dist/bundle/chunks/{typesafe-system-one-5JYDJK6S.js → typesafe-system-one-CICIRAYN.js} +1 -1
  110. package/dist/bundle/cli.js +2 -2
  111. package/dist/bundle/host-supervisor.js +1 -1
  112. package/dist/bundle/index.js +1 -1
  113. package/dist/bundle/rpc-entry.js +1 -1
  114. package/dist/bundle/runtime-manifest.json +1 -1
  115. package/dist/core/agent-session.d.ts +8 -0
  116. package/dist/core/agent-session.js +73 -63
  117. package/dist/core/auth-storage.d.ts +19 -0
  118. package/dist/core/auth-storage.js +99 -24
  119. package/dist/core/auth-store-load-error.d.ts +29 -0
  120. package/dist/core/auth-store-load-error.js +74 -0
  121. package/dist/core/brand.d.ts +2 -0
  122. package/dist/core/brand.js +1 -0
  123. package/dist/core/credential-pool/classify.d.ts +3 -2
  124. package/dist/core/credential-pool/classify.js +10 -3
  125. package/dist/core/credential-pool/failover.d.ts +8 -0
  126. package/dist/core/credential-pool/failover.js +18 -5
  127. package/dist/core/credential-pool/rotation-stream.d.ts +1 -1
  128. package/dist/core/credential-pool/rotation-stream.js +2 -7
  129. package/dist/core/credential-pool/session-slot.d.ts +20 -0
  130. package/dist/core/credential-pool/session-slot.js +26 -0
  131. package/dist/core/credential-recovery-revision.d.ts +10 -0
  132. package/dist/core/credential-recovery-revision.js +19 -0
  133. package/dist/core/dynamic-prompt/build.d.ts +2 -1
  134. package/dist/core/dynamic-prompt/build.js +1 -2
  135. package/dist/core/dynamic-prompt/handoff.d.ts +1 -1
  136. package/dist/core/dynamic-prompt/handoff.js +9 -9
  137. package/dist/core/dynamic-prompt/identity.js +1 -1
  138. package/dist/core/dynamic-prompt/intent-gate.d.ts +1 -1
  139. package/dist/core/dynamic-prompt/intent-gate.js +8 -8
  140. package/dist/core/dynamic-prompt/policies.d.ts +1 -1
  141. package/dist/core/dynamic-prompt/policies.js +5 -7
  142. package/dist/core/dynamic-prompt/style.js +5 -5
  143. package/dist/core/dynamic-prompt/tool-section.d.ts +5 -0
  144. package/dist/core/dynamic-prompt/tool-section.js +8 -6
  145. package/dist/core/dynamic-prompt/verification.d.ts +6 -6
  146. package/dist/core/dynamic-prompt/verification.js +12 -12
  147. package/dist/core/dynamic-prompt/working-task.d.ts +1 -1
  148. package/dist/core/dynamic-prompt/working-task.js +3 -3
  149. package/dist/core/dynamic-prompt/workstation.js +1 -1
  150. package/dist/core/execution/executor-body.d.ts +22 -0
  151. package/dist/core/execution/executor-body.js +73 -0
  152. package/dist/core/execution/executor-freeze.d.ts +17 -0
  153. package/dist/core/execution/executor-freeze.js +53 -0
  154. package/dist/core/execution/executor-pipeline.d.ts +9 -0
  155. package/dist/core/execution/executor-pipeline.js +25 -0
  156. package/dist/core/execution/executor-types.d.ts +82 -0
  157. package/dist/core/execution/executor-types.js +2 -0
  158. package/dist/core/execution/executor.d.ts +8 -0
  159. package/dist/core/execution/executor.js +216 -0
  160. package/dist/core/extensions/builtin/anthropic-subscription/account-block-log.d.ts +15 -0
  161. package/dist/core/extensions/builtin/anthropic-subscription/account-block-log.js +18 -0
  162. package/dist/core/extensions/builtin/anthropic-subscription/affinity.d.ts +9 -1
  163. package/dist/core/extensions/builtin/anthropic-subscription/affinity.js +15 -4
  164. package/dist/core/extensions/builtin/anthropic-subscription/failover.d.ts +7 -1
  165. package/dist/core/extensions/builtin/anthropic-subscription/failover.js +19 -2
  166. package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts +8 -2
  167. package/dist/core/extensions/builtin/anthropic-subscription/guidance.js +25 -1
  168. package/dist/core/extensions/builtin/anthropic-subscription/provider-diagnostic.d.ts +9 -0
  169. package/dist/core/extensions/builtin/anthropic-subscription/provider-diagnostic.js +59 -0
  170. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-pump.d.ts +13 -0
  171. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-pump.js +64 -2
  172. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-wiring.js +7 -0
  173. package/dist/core/extensions/builtin/anthropic-subscription/session-stream.js +5 -1
  174. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-attempt.d.ts +7 -0
  175. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-attempt.js +28 -1
  176. package/dist/core/extensions/builtin/anthropic-subscription/session-turn-types.d.ts +2 -0
  177. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +5 -3
  178. package/dist/core/extensions/builtin/anthropic-subscription/stream.js +4 -0
  179. package/dist/core/extensions/builtin/bash-timeout/index.d.ts +1 -1
  180. package/dist/core/extensions/builtin/bash-timeout/index.js +3 -28
  181. package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts +0 -11
  182. package/dist/core/extensions/builtin/bash-timeout/timeout.js +0 -11
  183. package/dist/core/extensions/builtin/btw/index.js +3 -1
  184. package/dist/core/extensions/builtin/cache-keepalive/index.js +3 -1
  185. package/dist/core/extensions/builtin/compaction/index.js +1 -1
  186. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -1
  187. package/dist/core/extensions/builtin/compaction/openai-remote.js +1 -1
  188. package/dist/core/extensions/builtin/compaction/speculative.js +3 -2
  189. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +3 -1
  190. package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.js +3 -1
  191. package/dist/core/extensions/builtin/imagegen/index.d.ts +0 -1
  192. package/dist/core/extensions/builtin/imagegen/index.js +0 -11
  193. package/dist/core/extensions/builtin/look-at/runner.js +3 -1
  194. package/dist/core/extensions/builtin/mcp/auth/callback.js +3 -4
  195. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +2 -1
  196. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +5 -5
  197. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +5 -5
  198. package/dist/core/extensions/builtin/prompt-preset/glm-5.d.ts +1 -1
  199. package/dist/core/extensions/builtin/prompt-preset/glm-5.js +1 -1
  200. package/dist/core/extensions/builtin/terminal/extension.js +8 -1
  201. package/dist/core/extensions/builtin/terminal/notify.js +9 -3
  202. package/dist/core/extensions/builtin/terminal/prompt.d.ts +7 -1
  203. package/dist/core/extensions/builtin/terminal/prompt.js +27 -60
  204. package/dist/core/extensions/builtin/terminal/tools/bash.js +10 -2
  205. package/dist/core/extensions/builtin/todotools/normalize.d.ts +20 -3
  206. package/dist/core/extensions/builtin/todotools/normalize.js +251 -5
  207. package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -2
  208. package/dist/core/extensions/builtin/todotools/prompt.js +5 -5
  209. package/dist/core/extensions/builtin/todotools/tools/todo.js +9 -8
  210. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +0 -5
  211. package/dist/core/extensions/builtin/websearch/index.js +9 -4
  212. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts +2 -0
  213. package/dist/core/extensions/builtin/websearch/websearch/tool.js +3 -1
  214. package/dist/core/model-registry.d.ts +10 -2
  215. package/dist/core/model-registry.js +12 -4
  216. package/dist/core/model-runtime.d.ts +8 -0
  217. package/dist/core/model-runtime.js +39 -1
  218. package/dist/core/provider-failure.d.ts +6 -0
  219. package/dist/core/provider-failure.js +6 -2
  220. package/dist/core/retry-fallback/controller-types.d.ts +7 -0
  221. package/dist/core/retry-fallback/controller.d.ts +2 -0
  222. package/dist/core/retry-fallback/controller.js +13 -4
  223. package/dist/core/retry-fallback/credential-recovery.d.ts +18 -0
  224. package/dist/core/retry-fallback/credential-recovery.js +32 -0
  225. package/dist/core/retry-fallback/exhaustion.d.ts +18 -0
  226. package/dist/core/retry-fallback/exhaustion.js +20 -0
  227. package/dist/core/retry-fallback/settings.d.ts +8 -1
  228. package/dist/core/retry-fallback/settings.js +12 -6
  229. package/dist/core/session-log.js +1 -1
  230. package/dist/core/settings-manager.js +4 -1
  231. package/dist/core/system-prompt.js +1 -1
  232. package/dist/core/tools/bash.d.ts +3 -1
  233. package/dist/core/tools/bash.js +14 -4
  234. package/dist/core/tools/edit.d.ts +1 -1
  235. package/dist/core/tools/edit.js +1 -6
  236. package/dist/core/tools/grep/index.js +2 -3
  237. package/dist/core/tools/powershell.d.ts +1 -1
  238. package/dist/core/tools/powershell.js +1 -1
  239. package/dist/core/tools/read.d.ts +1 -1
  240. package/dist/core/tools/read.js +1 -1
  241. package/dist/core/tools/write.d.ts +1 -1
  242. package/dist/core/tools/write.js +1 -1
  243. package/dist/engine-trust/shell-trust.d.ts +36 -0
  244. package/dist/engine-trust/shell-trust.js +44 -0
  245. package/dist/engine-trust/transport-failure.d.ts +12 -0
  246. package/dist/engine-trust/transport-failure.js +48 -0
  247. package/dist/modes/interactive/interactive-mode.js +9 -3
  248. package/dist/modes/print-mode.js +2 -1
  249. package/dist/modes/rpc/compact-catalog-families.d.ts +5 -2
  250. package/dist/modes/rpc/compact-catalog-families.js +5 -2
  251. package/dist/modes/rpc/compact-catalog-registry.d.ts +9 -1
  252. package/dist/modes/rpc/compact-catalog-registry.js +9 -2
  253. package/dist/modes/rpc/compact-recovery-manifest-kinds.d.ts +17 -0
  254. package/dist/modes/rpc/compact-recovery-manifest-kinds.js +21 -0
  255. package/dist/modes/rpc/compact-recovery-manifest-shape.d.ts +7 -0
  256. package/dist/modes/rpc/compact-recovery-manifest.js +11 -3
  257. package/dist/modes/rpc/compact-socket-commands.js +6 -0
  258. package/dist/modes/rpc/connection-handler.js +24 -6
  259. package/dist/modes/rpc/connection-question-bridge.d.ts +3 -1
  260. package/dist/modes/rpc/connection-question-bridge.js +4 -1
  261. package/dist/modes/rpc/connection-roles.d.ts +8 -0
  262. package/dist/modes/rpc/connection-roles.js +18 -0
  263. package/dist/modes/rpc/effect-commands.d.ts +1 -0
  264. package/dist/modes/rpc/loopless-execute-grant.d.ts +20 -0
  265. package/dist/modes/rpc/loopless-execute-grant.js +26 -0
  266. package/dist/modes/rpc/loopless-runtime-settings.d.ts +30 -0
  267. package/dist/modes/rpc/loopless-runtime-settings.js +69 -0
  268. package/dist/modes/rpc/loopless-tool-call.d.ts +12 -0
  269. package/dist/modes/rpc/loopless-tool-call.js +22 -0
  270. package/dist/modes/rpc/method-classes-schema-session.d.ts +4 -0
  271. package/dist/modes/rpc/method-classes-schema-session.js +1 -0
  272. package/dist/modes/rpc/method-classes-schema.d.ts +4 -0
  273. package/dist/modes/rpc/protocol-identity.js +2 -0
  274. package/dist/modes/rpc/remote-origin.d.ts +31 -0
  275. package/dist/modes/rpc/remote-origin.js +58 -0
  276. package/dist/modes/rpc/rpc-protocol-info-types.d.ts +8 -0
  277. package/dist/modes/rpc/rpc-question-types.d.ts +7 -0
  278. package/dist/modes/rpc/rpc-question-types.js +0 -3
  279. package/dist/modes/rpc/rpc-read-response-types.d.ts +2 -1
  280. package/dist/modes/rpc/rpc-session-command-types.d.ts +3 -0
  281. package/dist/modes/rpc/rpc-session-state-types.d.ts +10 -0
  282. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  283. package/dist/modes/rpc/runtime-factory-loopless.d.ts +57 -0
  284. package/dist/modes/rpc/runtime-factory-loopless.js +131 -0
  285. package/dist/modes/rpc/session-registry.js +12 -3
  286. package/dist/modes/rpc/session-worker-client.js +2 -0
  287. package/dist/modes/rpc/session-worker-protocol.d.ts +3 -0
  288. package/dist/modes/rpc/session-worker.js +2 -0
  289. package/docs/development.md +1 -1
  290. package/docs/engine-socket/fixtures/admission-routes/c-baseline.json +3 -3
  291. package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
  292. package/docs/engine-socket/fixtures/admission-routes/i-reset-stream.json +3 -3
  293. package/docs/engine-socket/fixtures/recovery-manifest/index.json +32 -0
  294. package/docs/engine-socket/fixtures/recovery-manifest/one-partial-family.json +118 -0
  295. package/docs/rpc.md +95 -3
  296. package/package.json +6 -6
  297. package/dist/bundle/chunks/anthropic-messages-WUPLDYD6.js +0 -10
  298. package/dist/bundle/chunks/chunk-7UC4W2T2.js +0 -2
  299. package/dist/bundle/chunks/chunk-O4GRBX4R.js +0 -3
  300. package/dist/bundle/chunks/chunk-R23WXN4L.js +0 -448
  301. package/dist/bundle/chunks/chunk-W5NLCRB3.js +0 -2
  302. package/dist/bundle/chunks/credential-accounts-OAK2E5O2.js +0 -2
  303. package/dist/bundle/chunks/host-command-WJIMRBGN.js +0 -2
  304. package/dist/bundle/chunks/interactive-mode-NPHFDPGH.js +0 -2
  305. package/dist/bundle/chunks/main-I6FJAFUP.js +0 -2
  306. package/dist/bundle/chunks/rotation-stream-ZDCNHIBE.js +0 -2
  307. package/dist/bundle/chunks/rpc-mode-GBBTN2WP.js +0 -2
@@ -3,32 +3,32 @@ export const TEST_DISCIPLINE_RULES = [
3
3
  {
4
4
  id: "deterministic-tests",
5
5
  concern: "test-determinism",
6
- directive: "When you read or edit test code, treat nondeterminism as a bug; tests must not pass by timing luck.",
6
+ directive: "Reading/editing test code: nondeterminism = bug; no passing by timing luck.",
7
7
  },
8
8
  {
9
9
  id: "fixed-wait-ban",
10
10
  concern: "async-test-orchestration",
11
- directive: "Unless time itself is the behavior under test, fixed sleeps, polling delays, and wait-for-time patterns are forbidden.",
11
+ directive: "Fixed sleeps, polling delays, wait-for-time: forbidden unless time itself is under test.",
12
12
  },
13
13
  {
14
14
  id: "event-timeout-pattern",
15
15
  concern: "async-test-orchestration",
16
- directive: "For async behavior, subscribe to the exact event or state change before triggering the action, then await that signal with a bounded timeout.",
16
+ directive: "Async: subscribe to the exact event/state change before triggering, then await it with a bounded timeout.",
17
17
  },
18
18
  {
19
19
  id: "mock-contract-integrity",
20
20
  concern: "mock-contracts",
21
- directive: "Mocks must preserve the behavior being asserted; do not isolate so heavily that the integration under test cannot fail.",
21
+ directive: "Mocks keep the asserted behavior; never isolate so hard the integration cannot fail.",
22
22
  },
23
23
  {
24
24
  id: "prompt-behavior-coverage",
25
25
  concern: "prompt-tests",
26
- directive: "Never pin prose, prompt wording, or doc text with a test; test only machine-consumed values (parsed fields, sentinel tokens, shipped-copy equality). A pure-prose change ships with no new test.",
26
+ directive: "Never pin prose, prompt wording, or doc text with a test; test machine-consumed values only (parsed fields, sentinel tokens, shipped-copy equality). Pure-prose change = no new test.",
27
27
  },
28
28
  {
29
29
  id: "single-pass-runner",
30
30
  concern: "test-runner",
31
- directive: "Run the relevant test command once and make that pass reliable; for Bun test targets, bun test must pass in a single run.",
31
+ directive: "Run the relevant test command once, make that pass reliable; Bun targets: bun test passes in a single run.",
32
32
  },
33
33
  ];
34
34
  export function buildTestDisciplineSection() {
@@ -44,20 +44,20 @@ export function buildTestDisciplineSection() {
44
44
  */
45
45
  export const APP_UNRUN_CHECK_RULE = "A check that did not run is covered by the evidence that did run; name it only when no other evidence supports the claim. Replies render in an app, so tool and hook feedback (comment-checker findings, language-server availability, internal notices) is for you to act on: it reaches the user only when it changes what they get, and an unavailable tool or hook never does by itself.";
46
46
  const CLAIM_AUDIT = {
47
- terminal: "report only evidence-backed work, flag the unverified explicitly, and report failing tests with the output.",
48
- app: `report only evidence-backed work and report failing tests with the output. ${APP_UNRUN_CHECK_RULE}`,
47
+ terminal: "evidence-backed work only, flag unverified explicitly, failing tests with output.",
48
+ app: `evidence-backed work only, failing tests with output. ${APP_UNRUN_CHECK_RULE}`,
49
49
  };
50
50
  export function buildVerificationSection(options = {}) {
51
51
  return `## Verification
52
52
 
53
53
  Tier the scope, never the rigor.
54
54
 
55
- - V1 (single-file non-behavioral edits): diagnostics on that file. Done.
56
- - V2 (single-domain behavioral edits): diagnostics on changed files in parallel, related tests, one execution of the affected runnable entry point when one exists.
57
- - V3 (multi-file or cross-cutting work): diagnostics on every changed file, related tests, build, manual exercise of user-visible behavior through its real surface.
55
+ - V1 single-file non-behavioral edit: diagnostics on that file. Done.
56
+ - V2 single-domain behavioral edit: diagnostics on changed files in parallel + related tests + one run of affected runnable entry point if any.
57
+ - V3 multi-file / cross-cutting: diagnostics on every changed file + related tests + build + manual exercise of user-visible behavior through its real surface.
58
58
 
59
59
  ${buildTestDisciplineSection()}
60
60
 
61
- "Should pass" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: ${CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix only issues your changes caused; note pre-existing failures separately.`;
61
+ Before reporting progress: audit each claim against a tool result from this session; ${CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix only issues your changes caused; note pre-existing failures separately.`;
62
62
  }
63
63
  //# sourceMappingURL=verification.js.map
@@ -1,4 +1,4 @@
1
- export declare const DEFAULT_WORKING_TASK_OPENING = "Fire independent tool calls as one parallel wave - reads, searches, listings, diagnostics - and bias toward breadth when context is thin: pull in anything even loosely relevant now instead of serially later. Wasted reads cost almost nothing; stale assumptions cost the turn. Edits and result-dependent calls go one at a time, each compared with the state you meant to produce; when the result must be seen rather than read, render after each change and look before the next. Never fill missing parameters with placeholders.";
1
+ export declare const DEFAULT_WORKING_TASK_OPENING = "Independent calls (reads, searches, listings, diagnostics) -> one parallel wave; thin context -> go wide now, pull anything loosely relevant, not serially later. Edits + result-dependent calls -> one at a time, each compared with intended state; result must be seen -> render after each change, look before next. Never fill missing parameters with placeholders.";
2
2
  export declare function buildWorkingTaskSection(options?: {
3
3
  opening?: string;
4
4
  }): string;
@@ -1,11 +1,11 @@
1
- export const DEFAULT_WORKING_TASK_OPENING = "Fire independent tool calls as one parallel wave - reads, searches, listings, diagnostics - and bias toward breadth when context is thin: pull in anything even loosely relevant now instead of serially later. Wasted reads cost almost nothing; stale assumptions cost the turn. Edits and result-dependent calls go one at a time, each compared with the state you meant to produce; when the result must be seen rather than read, render after each change and look before the next. Never fill missing parameters with placeholders.";
1
+ export const DEFAULT_WORKING_TASK_OPENING = "Independent calls (reads, searches, listings, diagnostics) -> one parallel wave; thin context -> go wide now, pull anything loosely relevant, not serially later. Edits + result-dependent calls -> one at a time, each compared with intended state; result must be seen -> render after each change, look before next. Never fill missing parameters with placeholders.";
2
2
  export function buildWorkingTaskSection(options = {}) {
3
3
  return `## Working the Task
4
4
 
5
5
  ${options.opening ?? DEFAULT_WORKING_TASK_OPENING}
6
6
 
7
- Memory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a "just to be sure" sweep.
7
+ Memory of file contents unreliable: read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact appears twice independently, or two waves add nothing; resume only for a genuinely new unknown, never a "just to be sure" sweep.
8
8
 
9
- Make one reasonable plan and execute it; reopen it only when new evidence contradicts it. Do not re-derive facts already established in the conversation or re-litigate decisions the user has made. When weighing a choice, give a recommendation, not a survey. When a delegation tool is available, hand sizeable independent tracks to subagents and keep working while they run; keep work you can finish in a few calls yourself.`;
9
+ One reasonable plan, execute; reopen only when new evidence contradicts it. Don't re-derive established facts or re-litigate user decisions. Weighing a choice -> recommendation, not survey. Delegation tool available: hand sizeable independent tracks to subagents, keep working meanwhile; few-call work -> yourself.`;
10
10
  }
11
11
  //# sourceMappingURL=working-task.js.map
@@ -131,7 +131,7 @@ ${executors} on THIS workstation. Match commands, paths, package managers, and p
131
131
  codex: (executors) => `${executors} on this workstation; match commands, paths, and parallelism to it. Written code may target other platforms: executed code runs here.`,
132
132
  kimi: (executors) => `${executors} on this workstation: choose commands, paths, and parallelism that fit it. When writing code for another target platform, keep the code portable; only the execution happens here.`,
133
133
  gemini: (executors) => `${executors} on this workstation; match commands, paths, package managers, and parallel pool sizes to it. Code you write may target another machine; code you run always runs here.`,
134
- default: (executors) => `**EXECUTION HAPPENS HERE.** ${executors} on THIS machine: you MUST match commands, paths, package managers, and parallel pool sizes to the workstation above. Code you WRITE may target a different machine; anything you RUN executes HERE.`,
134
+ default: (executors) => `**EXECUTION HAPPENS HERE.** ${executors} on THIS machine: match commands, paths, package managers, parallel pool sizes to the workstation above. Code you WRITE may target another machine; anything you RUN executes HERE.`,
135
135
  };
136
136
  /** Render the `<workstation>` facts block plus the dialect-tuned execution-context instruction. */
137
137
  export function buildWorkstationSection(options) {
@@ -0,0 +1,22 @@
1
+ import type { AgentContext, AgentTool, AgentToolCall, AgentToolResult, AgentToolUpdateCallback } from "@earendil-works/pi-agent-core";
2
+ import type { AssistantMessage } from "@earendil-works/pi-ai";
3
+ import type { PreparationPipeline } from "./executor-types.ts";
4
+ /** What release needs from preparation; it lives in memory with the executor that prepared the call. */
5
+ export interface PreparedBody {
6
+ readonly tool: AgentTool;
7
+ readonly toolCall: AgentToolCall;
8
+ readonly args: unknown;
9
+ readonly assistantMessage: AssistantMessage;
10
+ readonly context: AgentContext;
11
+ /** The model's own name when it resolved to another tool; today's result carries a correction notice for it. */
12
+ readonly requestedName?: string;
13
+ }
14
+ export interface BodyOutcome {
15
+ readonly result: AgentToolResult<unknown>;
16
+ readonly isError: boolean;
17
+ }
18
+ export declare function errorResult(message: string): AgentToolResult<unknown>;
19
+ export declare function messageOf(error: unknown): string;
20
+ export declare function runBody(body: PreparedBody, signal: AbortSignal | undefined, onUpdate: AgentToolUpdateCallback<unknown>): Promise<BodyOutcome>;
21
+ export declare function finalizeBody(body: PreparedBody, executed: BodyOutcome, pipeline: PreparationPipeline, signal: AbortSignal | undefined): Promise<BodyOutcome>;
22
+ //# sourceMappingURL=executor-body.d.ts.map
@@ -0,0 +1,73 @@
1
+ export function errorResult(message) {
2
+ return { content: [{ type: "text", text: message }], details: {} };
3
+ }
4
+ export function messageOf(error) {
5
+ return error instanceof Error ? error.message : String(error);
6
+ }
7
+ const ABORTED = Symbol("aborted");
8
+ // Today's body semantics (agent-loop `executePreparedToolCall`): an abort releases the wait even when the tool never
9
+ // settles, and updates stop at settlement.
10
+ export async function runBody(body, signal, onUpdate) {
11
+ const updates = [];
12
+ let accepting = true;
13
+ try {
14
+ const execution = body.tool.execute(body.toolCall.id, body.args, signal, (partial) => {
15
+ if (accepting)
16
+ updates.push(Promise.resolve(onUpdate(partial)));
17
+ });
18
+ const aborted = signal === undefined
19
+ ? undefined
20
+ : new Promise((resolve) => {
21
+ if (signal.aborted)
22
+ resolve(ABORTED);
23
+ else
24
+ signal.addEventListener("abort", () => resolve(ABORTED), { once: true });
25
+ });
26
+ const settled = aborted ? await Promise.race([execution, aborted]) : await execution;
27
+ accepting = false;
28
+ await Promise.all(updates);
29
+ if (settled === ABORTED) {
30
+ void Promise.resolve(execution).catch(() => undefined);
31
+ return { result: errorResult("Tool execution aborted"), isError: true };
32
+ }
33
+ return { result: settled, isError: settled.isError === true };
34
+ }
35
+ catch (error) {
36
+ accepting = false;
37
+ await Promise.all(updates);
38
+ return { result: errorResult(messageOf(error)), isError: true };
39
+ }
40
+ }
41
+ // Today's after-hook merge (agent-loop `finalizeExecutedToolCall`), field by field.
42
+ export async function finalizeBody(body, executed, pipeline, signal) {
43
+ const { result, isError } = executed;
44
+ try {
45
+ const after = await pipeline.afterToolCall({
46
+ assistantMessage: body.assistantMessage,
47
+ toolCall: body.toolCall,
48
+ args: body.args,
49
+ result,
50
+ isError,
51
+ context: body.context,
52
+ }, signal);
53
+ if (!after)
54
+ return executed;
55
+ const structuredContent = after.structuredContent ?? (after.content ? undefined : result.structuredContent);
56
+ const merged = {
57
+ ...result,
58
+ content: after.content ?? result.content,
59
+ details: after.details ?? result.details,
60
+ usage: after.usage ?? result.usage,
61
+ terminate: after.terminate ?? result.terminate,
62
+ };
63
+ if (structuredContent === undefined)
64
+ delete merged.structuredContent;
65
+ else
66
+ merged.structuredContent = structuredContent;
67
+ return { result: merged, isError: after.isError ?? isError };
68
+ }
69
+ catch (error) {
70
+ return { result: errorResult(messageOf(error)), isError: true };
71
+ }
72
+ }
73
+ //# sourceMappingURL=executor-body.js.map
@@ -0,0 +1,17 @@
1
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ import type { FrozenCall, StoreValue } from "@earendil-works/pi-agent-core/conformance";
3
+ import type { PrepareReply } from "./executor-types.ts";
4
+ /** Tool arguments and results are JSON on every model and wire path; a round trip drops what JSON cannot carry. */
5
+ export declare function toStoreValue(value: unknown): StoreValue;
6
+ export declare function digestOf(value: StoreValue): string;
7
+ /** The call after the whole `tool_call` chain, detached from every object a handler or caller still holds. */
8
+ export declare function freezeCall(name: string, args: unknown): FrozenCall;
9
+ /** The durable record of a settled body: what the issuer commits before ACK. Details stay in the in-process reply. */
10
+ export declare function resultValue(result: AgentToolResult<unknown>, isError: boolean, requestedName?: string): StoreValue;
11
+ export type StoppedReply = Extract<PrepareReply, {
12
+ readonly kind: "blocked" | "batch_abort";
13
+ }>;
14
+ /** A preparation that ended without a frozen call, as the ledger's durable `blocked` outcome value. */
15
+ export declare function stoppedValue(reply: StoppedReply): StoreValue;
16
+ export declare function stoppedReply(value: StoreValue): StoppedReply | undefined;
17
+ //# sourceMappingURL=executor-freeze.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { createHash } from "node:crypto";
2
+ import { errorResult } from "./executor-body.js";
3
+ function canonical(value) {
4
+ if (value === null || typeof value !== "object")
5
+ return JSON.stringify(value);
6
+ if (Array.isArray(value))
7
+ return `[${value.map(canonical).join(",")}]`;
8
+ const entries = Object.entries(value).sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));
9
+ return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${canonical(entry)}`).join(",")}}`;
10
+ }
11
+ /** Tool arguments and results are JSON on every model and wire path; a round trip drops what JSON cannot carry. */
12
+ export function toStoreValue(value) {
13
+ const json = JSON.stringify(value);
14
+ return json === undefined ? null : JSON.parse(json);
15
+ }
16
+ export function digestOf(value) {
17
+ return createHash("sha256").update(canonical(value)).digest("hex");
18
+ }
19
+ /** The call after the whole `tool_call` chain, detached from every object a handler or caller still holds. */
20
+ export function freezeCall(name, args) {
21
+ const frozenArgs = toStoreValue(args);
22
+ return { name, args: frozenArgs, digest: digestOf({ name, args: frozenArgs }) };
23
+ }
24
+ /** The durable record of a settled body: what the issuer commits before ACK. Details stay in the in-process reply. */
25
+ export function resultValue(result, isError, requestedName) {
26
+ return toStoreValue({ content: result.content ?? [], isError, requestedName });
27
+ }
28
+ /** A preparation that ended without a frozen call, as the ledger's durable `blocked` outcome value. */
29
+ export function stoppedValue(reply) {
30
+ const text = (reply.result.content ?? []).map((part) => (part.type === "text" ? part.text : "")).join("");
31
+ const requestedName = reply.kind === "blocked" ? reply.requestedName : undefined;
32
+ return toStoreValue({ kind: reply.kind, text, terminate: reply.result.terminate === true, requestedName });
33
+ }
34
+ /** The reply a re-sent prepare gets back from a durable `blocked` outcome; undefined for a value this module never wrote. */
35
+ function isRecord(value) {
36
+ return value !== null && typeof value === "object" && !Array.isArray(value);
37
+ }
38
+ export function stoppedReply(value) {
39
+ if (!isRecord(value))
40
+ return undefined;
41
+ const { kind, text, terminate, requestedName } = value;
42
+ if (typeof text !== "string" || typeof terminate !== "boolean")
43
+ return undefined;
44
+ const result = errorResult(text);
45
+ if (terminate)
46
+ result.terminate = true;
47
+ if (kind === "batch_abort")
48
+ return { kind, result };
49
+ if (kind !== "blocked")
50
+ return undefined;
51
+ return typeof requestedName === "string" ? { kind, result, requestedName } : { kind, result };
52
+ }
53
+ //# sourceMappingURL=executor-freeze.js.map
@@ -0,0 +1,9 @@
1
+ import { type Agent } from "@earendil-works/pi-agent-core";
2
+ import type { PreparationPipeline } from "./executor-types.ts";
3
+ /**
4
+ * The preparation steps an agent's loop runs today, read from the agent at call time: its resolver (lazy activation),
5
+ * its `beforeToolCall` / `afterToolCall` (the session's `tool_call` and `tool_result` chains) and its removed-tool
6
+ * hints. Building this pipeline installs nothing on the agent.
7
+ */
8
+ export declare function agentPreparationPipeline(agent: Agent): PreparationPipeline;
9
+ //# sourceMappingURL=executor-pipeline.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { resolveToolNameAlias } from "@earendil-works/pi-agent-core";
2
+ /**
3
+ * The preparation steps an agent's loop runs today, read from the agent at call time: its resolver (lazy activation),
4
+ * its `beforeToolCall` / `afterToolCall` (the session's `tool_call` and `tool_result` chains) and its removed-tool
5
+ * hints. Building this pipeline installs nothing on the agent.
6
+ */
7
+ export function agentPreparationPipeline(agent) {
8
+ return {
9
+ resolve: async (call, context) => {
10
+ const tools = context.tools ?? [];
11
+ const exact = tools.find((tool) => tool.name === call.name);
12
+ if (exact)
13
+ return exact;
14
+ const resolved = await agent.resolveUnknownToolCall?.(call.name, context);
15
+ if (resolved)
16
+ return resolved;
17
+ const aliased = resolveToolNameAlias(call.name, tools.map((tool) => tool.name));
18
+ return tools.find((tool) => tool.name === aliased);
19
+ },
20
+ beforeToolCall: async (context, signal) => agent.beforeToolCall?.(context, signal),
21
+ afterToolCall: async (context, signal) => agent.afterToolCall?.(context, signal),
22
+ removedToolHint: (name) => agent.removedToolHints?.[name],
23
+ };
24
+ }
25
+ //# sourceMappingURL=executor-pipeline.js.map
@@ -0,0 +1,82 @@
1
+ import type { AfterToolCallContext, AfterToolCallResult, AgentContext, AgentTool, AgentToolCall, AgentToolResult, AgentToolUpdateCallback, BeforeToolCallContext, BeforeToolCallResult } from "@earendil-works/pi-agent-core";
2
+ import type { ExecutionEntry, ExecutionKey, ExecutionLedger, FrozenCall } from "@earendil-works/pi-agent-core/conformance";
3
+ import type { AssistantMessage } from "@earendil-works/pi-ai";
4
+ /** Today's per-call steps, as the executor runs them; the executor owns their order and the ledger around them. */
5
+ export interface PreparationPipeline {
6
+ /** Exact name, then the host resolver (which may activate a lazy tool), then the alias rule. */
7
+ resolve(call: AgentToolCall, context: AgentContext): Promise<AgentTool | undefined>;
8
+ /** The ordered `tool_call` chain; PreToolUse is one handler in it. */
9
+ beforeToolCall(context: BeforeToolCallContext, signal?: AbortSignal): Promise<BeforeToolCallResult | undefined>;
10
+ afterToolCall(context: AfterToolCallContext, signal?: AbortSignal): Promise<AfterToolCallResult | undefined>;
11
+ removedToolHint(name: string): string | undefined;
12
+ }
13
+ export interface PreparedExecutorOptions {
14
+ readonly ledger: ExecutionLedger;
15
+ /** The executor's authenticated identity: the actor of every executor-side ledger event. */
16
+ readonly executor: string;
17
+ readonly pipeline: PreparationPipeline;
18
+ readonly clock?: () => number;
19
+ }
20
+ export interface PrepareRequest {
21
+ readonly issuer: string;
22
+ readonly generation: number;
23
+ readonly workspace: string;
24
+ readonly scope: string;
25
+ /** The model's raw call; its id is the execution's command id. */
26
+ readonly call: AgentToolCall;
27
+ readonly assistantMessage: AssistantMessage;
28
+ readonly context: AgentContext;
29
+ /** Issuer-minted with the call, so a re-sent prepare matches its admission exactly. */
30
+ readonly admittedAt: number;
31
+ readonly leaseUntil: number;
32
+ readonly reconcilable?: boolean;
33
+ readonly signal?: AbortSignal;
34
+ }
35
+ /** `requestedName` is set when the model's name resolved to another tool; the caller adds today's notice. */
36
+ export type PrepareReply = {
37
+ readonly kind: "prepared";
38
+ readonly call: FrozenCall;
39
+ readonly requestedName?: string;
40
+ } | {
41
+ readonly kind: "blocked";
42
+ readonly result: AgentToolResult<unknown>;
43
+ readonly requestedName?: string;
44
+ } | {
45
+ readonly kind: "batch_abort";
46
+ readonly result: AgentToolResult<unknown>;
47
+ } | {
48
+ readonly kind: "refused";
49
+ readonly reason: string;
50
+ };
51
+ export interface ReleaseRequest {
52
+ readonly key: ExecutionKey;
53
+ readonly generation: number;
54
+ /** Verified identity of the releasing issuer, supplied by the endpoint. */
55
+ readonly actor: {
56
+ readonly id: string;
57
+ };
58
+ readonly signal?: AbortSignal;
59
+ readonly onUpdate?: AgentToolUpdateCallback<unknown>;
60
+ }
61
+ export type ReleaseReply = {
62
+ readonly kind: "settled";
63
+ readonly toolCall: AgentToolCall;
64
+ readonly result: AgentToolResult<unknown>;
65
+ readonly isError: boolean;
66
+ /** Set when the model's name resolved to another tool; the caller adds today's correction notice. */
67
+ readonly requestedName?: string;
68
+ } | {
69
+ readonly kind: "aborted";
70
+ readonly result: AgentToolResult<unknown>;
71
+ } | {
72
+ readonly kind: "replayed";
73
+ readonly entry: ExecutionEntry;
74
+ } | {
75
+ readonly kind: "refused";
76
+ readonly reason: string;
77
+ };
78
+ export interface PreparedExecutor {
79
+ prepare(request: PrepareRequest): Promise<PrepareReply>;
80
+ release(request: ReleaseRequest): Promise<ReleaseReply>;
81
+ }
82
+ //# sourceMappingURL=executor-types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=executor-types.js.map
@@ -0,0 +1,8 @@
1
+ import type { PreparedExecutor, PreparedExecutorOptions } from "./executor-types.ts";
2
+ /**
3
+ * The prepared executor (design 5.6.1): PREPARE persists effect_possible, runs today's resolution, shim, validation
4
+ * and `tool_call` chain once, and freezes the result; RELEASE dispatches the frozen call at most once and runs the
5
+ * after-hook once. Nothing here is installed on a session; a caller builds one and drives it.
6
+ */
7
+ export declare function createPreparedExecutor(options: PreparedExecutorOptions): PreparedExecutor;
8
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1,216 @@
1
+ import { prepareAgentToolCall } from "@earendil-works/pi-agent-core";
2
+ import { errorResult, finalizeBody, messageOf, runBody } from "./executor-body.js";
3
+ import { digestOf, freezeCall, resultValue, stoppedReply, stoppedValue, toStoreValue, } from "./executor-freeze.js";
4
+ const keyId = ({ issuer, commandId }) => JSON.stringify([issuer, commandId]);
5
+ function refusal(reply) {
6
+ return { kind: "refused", reason: reply.status === "refused" ? reply.reason : reply.status };
7
+ }
8
+ // Today's message for a call the response cut off (agent-loop `createIncompleteToolCallErrorMessage`).
9
+ function incompleteMessage(name, errorMessage) {
10
+ if (errorMessage !== undefined) {
11
+ return `${errorMessage}${errorMessage.endsWith(".") ? "" : "."} Re-issue the tool call with complete arguments.`;
12
+ }
13
+ return `Tool call "${name}" was not executed: the response ended before the tool call was complete because it hit the output token limit. Re-issue the tool call with complete arguments.`;
14
+ }
15
+ /** A durable row that already passed admission: answer from it and never run preparation again. */
16
+ function fromRow(entry) {
17
+ const progress = entry.progress;
18
+ if ("call" in progress)
19
+ return { kind: "prepared", call: progress.call };
20
+ if (progress.state !== "settled")
21
+ return { kind: "refused", reason: progress.state };
22
+ const outcome = progress.outcome;
23
+ if (outcome.reason !== "blocked")
24
+ return { kind: "refused", reason: "terminal" };
25
+ return stoppedReply(outcome.value) ?? { kind: "refused", reason: "corrupt_blocked_outcome" };
26
+ }
27
+ /**
28
+ * The prepared executor (design 5.6.1): PREPARE persists effect_possible, runs today's resolution, shim, validation
29
+ * and `tool_call` chain once, and freezes the result; RELEASE dispatches the frozen call at most once and runs the
30
+ * after-hook once. Nothing here is installed on a session; a caller builds one and drives it.
31
+ */
32
+ export function createPreparedExecutor(options) {
33
+ const { ledger, executor, pipeline } = options;
34
+ const clock = options.clock ?? Date.now;
35
+ const preparations = new Map();
36
+ const bodies = new Map();
37
+ const releases = new Map();
38
+ const step = (key, generation, event) => ledger.apply({ key, generation, actor: { id: executor }, now: clock(), event });
39
+ // A preparation that ends without a frozen call is terminal and durable, so a re-sent prepare (also from a new
40
+ // executor process after restart) gets this reply back instead of a restart-recovered `hand_restarted`.
41
+ async function stop(key, generation, reply) {
42
+ const recorded = await step(key, generation, { kind: "block", value: stoppedValue(reply) });
43
+ if (recorded.status === "applied")
44
+ return reply;
45
+ return recorded.status === "replayed" ? fromRow(recorded.entry) : refusal(recorded);
46
+ }
47
+ async function prepareOnce(request, requestDigest) {
48
+ const { call, generation, signal } = request;
49
+ const key = { issuer: request.issuer, commandId: call.id };
50
+ const admitted = await ledger.admit({
51
+ ...key,
52
+ executor,
53
+ workspace: request.workspace,
54
+ scope: request.scope,
55
+ generation,
56
+ requestDigest,
57
+ admittedAt: request.admittedAt,
58
+ leaseUntil: request.leaseUntil,
59
+ reconcilable: request.reconcilable ?? false,
60
+ });
61
+ if (admitted.status === "replayed")
62
+ return fromRow(admitted.entry);
63
+ if (admitted.status !== "applied")
64
+ return refusal(admitted);
65
+ const preparing = await step(key, generation, { kind: "prepare" });
66
+ if (preparing.status !== "applied")
67
+ return refusal(preparing);
68
+ if (call.incomplete === true) {
69
+ return stop(key, generation, {
70
+ kind: "blocked",
71
+ result: errorResult(incompleteMessage(call.name, call.errorMessage)),
72
+ });
73
+ }
74
+ const effect = await step(key, generation, { kind: "effect" });
75
+ if (effect.status !== "applied")
76
+ return refusal(effect);
77
+ let tool;
78
+ try {
79
+ tool = await pipeline.resolve(call, request.context);
80
+ }
81
+ catch (error) {
82
+ return stop(key, generation, { kind: "blocked", result: errorResult(messageOf(error)) });
83
+ }
84
+ if (!tool) {
85
+ const hint = pipeline.removedToolHint(call.name);
86
+ const text = hint === undefined ? `Tool ${call.name} not found` : `Tool ${call.name} not found. ${hint}`;
87
+ return stop(key, generation, { kind: "blocked", result: errorResult(text) });
88
+ }
89
+ const requestedName = tool.name === call.name ? undefined : call.name;
90
+ const named = requestedName === undefined ? {} : { requestedName };
91
+ try {
92
+ const prepared = prepareAgentToolCall(tool, requestedName === undefined ? call : { ...call, name: tool.name });
93
+ const before = await pipeline.beforeToolCall({
94
+ assistantMessage: request.assistantMessage,
95
+ toolCall: prepared.toolCall,
96
+ args: prepared.args,
97
+ context: request.context,
98
+ }, signal);
99
+ if (signal?.aborted)
100
+ return stop(key, generation, { kind: "batch_abort", result: errorResult("Operation aborted") });
101
+ if (before?.block) {
102
+ const result = errorResult(before.reason || "Tool execution was blocked");
103
+ if (before.terminate === true)
104
+ result.terminate = true;
105
+ return stop(key, generation, { kind: "blocked", result, ...named });
106
+ }
107
+ const frozen = freezeCall(tool.name, prepared.args);
108
+ const freeze = await step(key, generation, { kind: "freeze", call: frozen, awaitingConsent: false });
109
+ if (freeze.status !== "applied")
110
+ return refusal(freeze);
111
+ bodies.set(keyId(key), {
112
+ ...named,
113
+ tool,
114
+ toolCall: prepared.toolCall,
115
+ args: frozen.args,
116
+ assistantMessage: request.assistantMessage,
117
+ context: request.context,
118
+ });
119
+ return { kind: "prepared", call: frozen, ...named };
120
+ }
121
+ catch (error) {
122
+ return stop(key, generation, { kind: "blocked", result: errorResult(messageOf(error)), ...named });
123
+ }
124
+ }
125
+ async function terminalRow(key) {
126
+ const entry = await ledger.read(key);
127
+ if (entry === undefined)
128
+ return { kind: "refused", reason: "not_found" };
129
+ const progress = entry.progress;
130
+ // A blocked call never had a body: release on it is refused, not replayed.
131
+ if (progress.state === "settled" && progress.outcome.reason === "blocked")
132
+ return { kind: "refused", reason: "blocked" };
133
+ return { kind: "replayed", entry };
134
+ }
135
+ async function runReleased(request, body) {
136
+ const { key, generation, signal } = request;
137
+ const dispatched = await step(key, generation, { kind: "dispatch" });
138
+ if (dispatched.status === "replayed")
139
+ return { kind: "replayed", entry: dispatched.entry };
140
+ if (dispatched.status !== "applied" || dispatched.entry.progress.state !== "dispatched") {
141
+ return refusal(dispatched);
142
+ }
143
+ const executed = await runBody(body, signal, request.onUpdate ?? (() => { }));
144
+ const { result, isError } = await finalizeBody(body, executed, pipeline, signal);
145
+ const value = resultValue(result, isError, body.requestedName);
146
+ const recorded = await step(key, generation, { kind: "result", value });
147
+ for (const memo of [bodies, preparations, releases])
148
+ memo.delete(keyId(key));
149
+ // A cancel or lease expiry that settled first stays terminal; the late body result is audit only.
150
+ if (recorded.status === "replayed")
151
+ return { kind: "replayed", entry: recorded.entry };
152
+ if (recorded.status !== "applied")
153
+ return refusal(recorded);
154
+ const named = body.requestedName === undefined ? {} : { requestedName: body.requestedName };
155
+ return { kind: "settled", toolCall: body.toolCall, result, isError, ...named };
156
+ }
157
+ // Every release reaches the ledger with its own actor and generation before any memo is read or written, so a
158
+ // wrong actor or an old generation is refused there and can never answer, or block, the issuer's own release.
159
+ async function release(request) {
160
+ const { key, generation } = request;
161
+ const released = await ledger.apply({
162
+ key,
163
+ generation,
164
+ actor: request.actor,
165
+ now: clock(),
166
+ event: { kind: "release" },
167
+ });
168
+ if (released.status === "refused")
169
+ return released.reason === "terminal" ? terminalRow(key) : refusal(released);
170
+ if (released.status === "result_expired")
171
+ return refusal(released);
172
+ const id = keyId(key);
173
+ const pending = releases.get(id);
174
+ if (pending !== undefined)
175
+ return pending;
176
+ const body = bodies.get(id);
177
+ if (body === undefined)
178
+ return { kind: "refused", reason: "not_prepared" };
179
+ // Today's loop never starts a body once the run is aborted; the call stays released for the issuer's abort.
180
+ if (request.signal?.aborted)
181
+ return { kind: "aborted", result: errorResult("Operation aborted") };
182
+ const reply = runReleased(request, body);
183
+ releases.set(id, reply);
184
+ void reply.catch(() => releases.get(id) === reply && releases.delete(id));
185
+ return reply;
186
+ }
187
+ return {
188
+ prepare: (request) => {
189
+ const { name, arguments: args, incomplete, errorMessage } = request.call;
190
+ const requestDigest = digestOf(toStoreValue({ name, args, incomplete, errorMessage }));
191
+ const admission = JSON.stringify([
192
+ request.generation,
193
+ request.workspace,
194
+ request.scope,
195
+ requestDigest,
196
+ request.admittedAt,
197
+ request.leaseUntil,
198
+ request.reconcilable ?? false,
199
+ ]);
200
+ const id = keyId({ issuer: request.issuer, commandId: request.call.id });
201
+ const pending = preparations.get(id);
202
+ if (pending !== undefined && pending.admission === admission)
203
+ return pending.reply;
204
+ if (pending !== undefined)
205
+ return Promise.resolve({ kind: "refused", reason: "identity_conflict" });
206
+ const reply = prepareOnce(request, requestDigest);
207
+ preparations.set(id, { admission, reply });
208
+ // Only a prepared call keeps its memo (release needs it); every other reply is durable or retryable.
209
+ const forget = () => preparations.get(id)?.reply === reply && preparations.delete(id);
210
+ void reply.then((settled) => settled.kind === "prepared" || forget(), forget);
211
+ return reply;
212
+ },
213
+ release,
214
+ };
215
+ }
216
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1,15 @@
1
+ export type AccountBlockRecord = {
2
+ readonly account: string;
3
+ readonly reason: string;
4
+ readonly until: number | undefined;
5
+ /** Whether the block was written to the credential store for every session, or held for this session only. */
6
+ readonly shared: boolean;
7
+ readonly detail: string;
8
+ };
9
+ /**
10
+ * Writes one `account_blocked` line to session.log for every block that is saved, so a pool that later
11
+ * refuses a request locally has a recorded cause (senpi#4671). The account is named by its seat digest,
12
+ * never its name (Desktop#4753); an unknown end time is left out rather than guessed.
13
+ */
14
+ export declare function logAccountBlocked(record: AccountBlockRecord): void;
15
+ //# sourceMappingURL=account-block-log.d.ts.map