@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
@@ -923,6 +923,10 @@ export declare const SESSION_RECORD_SCHEMAS: {
923
923
  } & {
924
924
  readonly width: Type.TInteger;
925
925
  readonly capabilities: Type.TOptional<Type.TArray<Type.TString>>;
926
+ readonly remoteOrigin: Type.TOptional<Type.TObject<{
927
+ deviceId: Type.TString;
928
+ deviceName: Type.TOptional<Type.TString>;
929
+ }>>;
926
930
  }>;
927
931
  };
928
932
  //# sourceMappingURL=method-classes-schema-session.d.ts.map
@@ -198,6 +198,7 @@ const SURFACE_AND_ACCOUNT_SCHEMAS = {
198
198
  set_client_info: session("set_client_info", {
199
199
  width: Type.Integer({ minimum: 1, maximum: 100_000 }),
200
200
  capabilities: Opt(Strings),
201
+ remoteOrigin: Opt(Type.Object({ deviceId: Id, deviceName: OptId }, { additionalProperties: false })),
201
202
  }),
202
203
  };
203
204
  export const SESSION_RECORD_SCHEMAS = {
@@ -1268,6 +1268,10 @@ export declare const RPC_INBOUND_SCHEMAS: {
1268
1268
  } & {
1269
1269
  readonly width: import("typebox").TInteger;
1270
1270
  readonly capabilities: import("typebox").TOptional<import("typebox").TArray<import("typebox").TString>>;
1271
+ readonly remoteOrigin: import("typebox").TOptional<import("typebox").TObject<{
1272
+ deviceId: import("typebox").TString;
1273
+ deviceName: import("typebox").TOptional<import("typebox").TString>;
1274
+ }>>;
1271
1275
  }>;
1272
1276
  };
1273
1277
  export type RpcInboundValidation = {
@@ -19,6 +19,7 @@ import { parseArgs, resolveSessionRuntime } from "../../cli/args.js";
19
19
  import { getAgentDir } from "../../config.js";
20
20
  import { engineBuildIdentity } from "../../core/engine-build-identity.js";
21
21
  import { HOST_GENERATION_ENV, HOST_INSTANCE_ID_ENV } from "./host-identity-env.js";
22
+ import { RPC_METHOD_CLASSES_DIGEST, RPC_METHOD_CLASSES_VERSION } from "./method-classes.js";
22
23
  export { HOST_GENERATION_ENV, HOST_INSTANCE_ID_ENV };
23
24
  /** Identity of THIS host process, fixed for its lifetime. */
24
25
  const INSTANCE_ID = resolveInstanceId(process.env[HOST_INSTANCE_ID_ENV]);
@@ -69,6 +70,7 @@ export function protocolIdentity(agentDir = resolve(getAgentDir())) {
69
70
  engineOrdinal: build.ordinal,
70
71
  launch_profile: cachedProfile,
71
72
  agentDir,
73
+ method_classes: { version: RPC_METHOD_CLASSES_VERSION, digest: RPC_METHOD_CLASSES_DIGEST },
72
74
  };
73
75
  }
74
76
  //# sourceMappingURL=protocol-identity.js.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The remote device a connection speaks for (senpi#5475, omo-relay-daemon#184 P5).
3
+ *
4
+ * A relay forwarder opens one engine connection per remote sender and declares, through its own
5
+ * `set_client_info`, which device that connection speaks for. Every dialog a command of that connection raises
6
+ * then carries the value as `remoteOrigin`, so the host's desktop and TUI can label it "Requested from <device>".
7
+ * A connection that never declared one is local, and its dialogs carry no `remoteOrigin`. The engine copies only
8
+ * this declared value, never a free-form client name. `set_client_info` is `connection_local` in the method-class
9
+ * table, so a forwarded record can never set or change it.
10
+ */
11
+ export interface RpcRemoteOrigin {
12
+ readonly deviceId: string;
13
+ readonly deviceName?: string;
14
+ }
15
+ /**
16
+ * Validates a `set_client_info.remoteOrigin` against what the connection already declared, before anything of the
17
+ * declaration is committed: the origin to record (none when the field is absent), or the refusal to answer.
18
+ */
19
+ export declare function remoteOriginDeclaration(value: unknown, accepts: (origin: RpcRemoteOrigin) => boolean): {
20
+ readonly origin: RpcRemoteOrigin | undefined;
21
+ } | {
22
+ readonly refusal: string;
23
+ };
24
+ export declare function sameRemoteOrigin(a: RpcRemoteOrigin, b: RpcRemoteOrigin): boolean;
25
+ export declare function remoteOriginField(origin: RpcRemoteOrigin | undefined): {
26
+ remoteOrigin?: RpcRemoteOrigin;
27
+ };
28
+ export declare function originField(origin: RpcRemoteOrigin | undefined): {
29
+ origin?: RpcRemoteOrigin;
30
+ };
31
+ //# sourceMappingURL=remote-origin.d.ts.map
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The remote device a connection speaks for (senpi#5475, omo-relay-daemon#184 P5).
3
+ *
4
+ * A relay forwarder opens one engine connection per remote sender and declares, through its own
5
+ * `set_client_info`, which device that connection speaks for. Every dialog a command of that connection raises
6
+ * then carries the value as `remoteOrigin`, so the host's desktop and TUI can label it "Requested from <device>".
7
+ * A connection that never declared one is local, and its dialogs carry no `remoteOrigin`. The engine copies only
8
+ * this declared value, never a free-form client name. `set_client_info` is `connection_local` in the method-class
9
+ * table, so a forwarded record can never set or change it.
10
+ */
11
+ const MAX_DEVICE_ID_CHARACTERS = 256;
12
+ const MAX_DEVICE_NAME_CHARACTERS = 256;
13
+ const REMOTE_ORIGIN_INVALID = "remote_origin_invalid: remoteOrigin must be { deviceId: non-empty string, deviceName?: non-empty string }";
14
+ const REMOTE_ORIGIN_FIXED = "remote_origin_fixed: a connection's remoteOrigin cannot change after it is declared";
15
+ function boundedText(value, max) {
16
+ return typeof value === "string" && value.length > 0 && value.length <= max;
17
+ }
18
+ /** The declared origin, `undefined` when the field is absent, or `"invalid"` for any other shape. */
19
+ function parseRemoteOrigin(value) {
20
+ if (value === undefined)
21
+ return undefined;
22
+ if (typeof value !== "object" || value === null || Array.isArray(value))
23
+ return "invalid";
24
+ const deviceId = Reflect.get(value, "deviceId");
25
+ const deviceName = Reflect.get(value, "deviceName");
26
+ const keys = Object.keys(value);
27
+ if (keys.some((key) => key !== "deviceId" && key !== "deviceName"))
28
+ return "invalid";
29
+ if (!boundedText(deviceId, MAX_DEVICE_ID_CHARACTERS))
30
+ return "invalid";
31
+ if (deviceName === undefined)
32
+ return { deviceId };
33
+ if (!boundedText(deviceName, MAX_DEVICE_NAME_CHARACTERS))
34
+ return "invalid";
35
+ return { deviceId, deviceName };
36
+ }
37
+ /**
38
+ * Validates a `set_client_info.remoteOrigin` against what the connection already declared, before anything of the
39
+ * declaration is committed: the origin to record (none when the field is absent), or the refusal to answer.
40
+ */
41
+ export function remoteOriginDeclaration(value, accepts) {
42
+ const origin = parseRemoteOrigin(value);
43
+ if (origin === "invalid")
44
+ return { refusal: REMOTE_ORIGIN_INVALID };
45
+ if (origin !== undefined && !accepts(origin))
46
+ return { refusal: REMOTE_ORIGIN_FIXED };
47
+ return { origin };
48
+ }
49
+ export function sameRemoteOrigin(a, b) {
50
+ return a.deviceId === b.deviceId && a.deviceName === b.deviceName;
51
+ }
52
+ export function remoteOriginField(origin) {
53
+ return origin === undefined ? {} : { remoteOrigin: origin };
54
+ }
55
+ export function originField(origin) {
56
+ return origin === undefined ? {} : { origin };
57
+ }
58
+ //# sourceMappingURL=remote-origin.js.map
@@ -33,6 +33,14 @@ export interface RpcProtocolIdentity {
33
33
  readonly launch_profile: RpcLaunchProfile;
34
34
  /** Absolute agent directory this host reads and writes; a handoff from another agent dir is refused. */
35
35
  readonly agentDir: string;
36
+ /**
37
+ * The inbound method-class table this engine runs (`method-classes.ts`): a remote forwarder classifies with its
38
+ * own copy only while that copy's digest equals `digest`.
39
+ */
40
+ readonly method_classes: {
41
+ readonly version: number;
42
+ readonly digest: string;
43
+ };
36
44
  }
37
45
  export interface RpcProtocolInfo extends RpcProtocolIdentity {
38
46
  /** Present only on a public POSIX endpoint's answer to a challenge (wire contract v1.1). */
@@ -1,3 +1,4 @@
1
+ import type { RpcRemoteOrigin } from "./remote-origin.ts";
1
2
  /** One question in an RPC `question` UI request. Matches canonical QuestionRequest.questions. */
2
3
  export type RpcQuestionSpec = {
3
4
  id: string;
@@ -25,6 +26,8 @@ export type RpcQuestionUiRequest = {
25
26
  questions: RpcQuestionSpec[];
26
27
  /** The connection whose command raised the question, or `"agent"` when no connection's command was dispatching. */
27
28
  raisedBy?: string;
29
+ /** The remote device the raising connection speaks for (senpi#5475); absent for a local connection. */
30
+ remoteOrigin?: RpcRemoteOrigin;
28
31
  timeout: number;
29
32
  askedAtMs: number;
30
33
  deadlineAtMs: number;
@@ -35,6 +38,7 @@ export type RpcExtensionUIRequest = {
35
38
  type: "extension_ui_request";
36
39
  id: string;
37
40
  method: "select";
41
+ remoteOrigin?: RpcRemoteOrigin;
38
42
  /** Permanent MCP env grant; only a grant_select presentation may answer. */
39
43
  grantSelect?: boolean;
40
44
  title: string;
@@ -50,10 +54,12 @@ export type RpcExtensionUIRequest = {
50
54
  title: string;
51
55
  message: string;
52
56
  timeout?: number;
57
+ remoteOrigin?: RpcRemoteOrigin;
53
58
  } | {
54
59
  type: "extension_ui_request";
55
60
  id: string;
56
61
  method: "input";
62
+ remoteOrigin?: RpcRemoteOrigin;
57
63
  secret?: boolean;
58
64
  deadlineAtMs?: number;
59
65
  title: string;
@@ -67,6 +73,7 @@ export type RpcExtensionUIRequest = {
67
73
  method: "editor";
68
74
  title: string;
69
75
  prefill?: string;
76
+ remoteOrigin?: RpcRemoteOrigin;
70
77
  } | {
71
78
  type: "extension_ui_request";
72
79
  id: string;
@@ -1,5 +1,2 @@
1
- // ============================================================================
2
- // Extension UI Events (stdout)
3
- // ============================================================================
4
1
  export {};
5
2
  //# sourceMappingURL=rpc-question-types.js.map
@@ -11,7 +11,7 @@ import type { ThinkingLevelSource } from "../../core/session-thinking-memory.ts"
11
11
  import type { EffectStatus } from "./effect-record.ts";
12
12
  import type { RpcSlashCommand } from "./rpc-command-surface.ts";
13
13
  import type { RpcEvalCell, RpcEvalCellSnapshot } from "./rpc-result-types.ts";
14
- import type { RpcAuthProvider, RpcLoadedExtension, RpcLoadedMcpServer, RpcProviderAccount, RpcSessionState } from "./rpc-session-state-types.ts";
14
+ import type { RpcAuthProvider, RpcAuthStoreError, RpcLoadedExtension, RpcLoadedMcpServer, RpcProviderAccount, RpcSessionState } from "./rpc-session-state-types.ts";
15
15
  import type { RpcSnapshot } from "./snapshot-types.ts";
16
16
  export type RpcReadResponse = {
17
17
  id?: string;
@@ -215,6 +215,7 @@ export type RpcReadResponse = {
215
215
  success: true;
216
216
  data: {
217
217
  providers: RpcAuthProvider[];
218
+ storeError?: RpcAuthStoreError;
218
219
  };
219
220
  } | {
220
221
  id?: string;
@@ -6,6 +6,7 @@ import type { ClientMessageIdentity } from "../../core/client-message-identity.t
6
6
  import type { SessionEntry } from "../../core/session-manager.ts";
7
7
  import type { ToolBarrierSpec } from "../../core/tool-barrier.ts";
8
8
  import type { RpcRecoveryCommand } from "./rpc-recovery-command-types.ts";
9
+ import type { RpcRemoteOrigin } from "./remote-origin.ts";
9
10
  import type { RpcSessionModelEntry } from "./rpc-session-state-types.ts";
10
11
  export type RpcSessionCommand = {
11
12
  id?: string;
@@ -521,6 +522,8 @@ export type RpcSessionCommand = {
521
522
  type: "set_client_info";
522
523
  width: number;
523
524
  capabilities?: string[];
525
+ /** Declared by a relay forwarder for the remote device this connection speaks for (senpi#5475). */
526
+ remoteOrigin?: RpcRemoteOrigin;
524
527
  };
525
528
  /** What `steer`/`follow_up` do on an idle session: queue (default) or start a turn. */
526
529
  export type RpcWhenIdle = "queue" | "start";
@@ -27,6 +27,16 @@ export interface RpcAuthProvider {
27
27
  /** Where the provider is defined, so a client can name the file or extension to edit (senpi#4328). */
28
28
  origin?: ProviderOrigin;
29
29
  }
30
+ /**
31
+ * `get_auth_providers` `storeError`: auth.json exists but could not be loaded, so stored sign-ins read
32
+ * as unconfigured and every write is refused until it is repaired. `write_back_failed` is the exception:
33
+ * the file was read, so its sign-ins stay configured and writes are not refused (senpi#4413).
34
+ * Never a path or contents.
35
+ */
36
+ export interface RpcAuthStoreError {
37
+ kind: "malformed_json" | "invalid_format" | "unreadable" | "write_back_failed";
38
+ reason: string;
39
+ }
30
40
  /** Auth status mirror (no credential values), from getProviderAuthStatus. */
31
41
  export interface RpcAuthStatus {
32
42
  configured: boolean;
@@ -16,7 +16,7 @@ export type { EditAssistantMessageResult, EditUserMessageResult, NavigateTreeRes
16
16
  export type { RpcWhenIdle } from "./rpc-session-command-types.ts";
17
17
  export { STEER_WHEN_IDLE_CAPABILITY, USER_ACTIVITY_CAPABILITY } from "./rpc-session-command-types.ts";
18
18
  export type { RpcAccountFailoverEvent, RpcAuthAccountsChangedEvent, RpcExtensionEvent, RpcHighReasoningWarningEvent, RpcLoadedSurfacesChangedEvent, RpcModelChangedEvent, RpcOpenQueuedEvent, RpcPendingInputUpdateEvent, RpcServiceTierChangedEvent, RpcSessionClosedEvent, RpcSessionClosedReason, RpcSessionOpenedEvent, RpcSessionParkedEvent, RpcSessionReplacedEvent, RpcSettingsSourceSelectedEvent, RpcSkillInvocationEvent, RpcThinkingLevelChangedEvent, } from "./rpc-session-event-types.ts";
19
- export type { RpcAuthProvider, RpcAuthStatus, RpcLoadedExtension, RpcLoadedMcpServer, RpcMcpServerStatus, RpcProviderAccount, RpcSessionModelEntry, RpcSessionState, } from "./rpc-session-state-types.ts";
19
+ export type { RpcAuthProvider, RpcAuthStatus, RpcAuthStoreError, RpcLoadedExtension, RpcLoadedMcpServer, RpcMcpServerStatus, RpcProviderAccount, RpcSessionModelEntry, RpcSessionState, } from "./rpc-session-state-types.ts";
20
20
  export type { SessionEffectStatusRecord as RpcEffectStatusEvent } from "./session-effect-status.ts";
21
21
  export type { SessionStatusRecord as RpcSessionStatusEvent } from "./session-status.ts";
22
22
  //# sourceMappingURL=rpc-types.d.ts.map
@@ -0,0 +1,57 @@
1
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ import type { AgentSessionLaunchProfile } from "../../core/agent-session-runtime.ts";
3
+ import { type AgentSessionRuntimeDiagnostic } from "../../core/agent-session-services.ts";
4
+ import type { InlineExtension } from "../../core/extensions/types.ts";
5
+ import { type ToolDefinitionEntry } from "../../core/runtime/bootstrap.ts";
6
+ import { SettingsManager } from "../../core/settings-manager.ts";
7
+ import type { CliRuntimeConfiguration } from "../../main.ts";
8
+ import { type LooplessExecuteGrant } from "./loopless-execute-grant.ts";
9
+ /**
10
+ * A session worker's runtime with the agent loop removed (brain/hand split, senpi#5413): the same
11
+ * built-in and extension tools a full session serves, executed one call at a time, with no agent loop,
12
+ * no model binding and no transcript. Its extension runtime is never bound to a loop, so an extension
13
+ * that tries to drive one (`pi.sendUserMessage`, `pi.setModel`, ...) is refused.
14
+ */
15
+ export interface LooplessRuntime {
16
+ readonly cwd: string;
17
+ /** Every tool this runtime serves: built-ins first, then extension tools, a later name replacing an earlier one. */
18
+ readonly definitions: ReadonlyMap<string, ToolDefinitionEntry>;
19
+ /** What building the runtime reported: settings, extension load and `project_trust` handler diagnostics. */
20
+ readonly diagnostics: readonly AgentSessionRuntimeDiagnostic[];
21
+ /**
22
+ * Runs one tool call: argument preparation and schema validation as the loop does, then the tool. An unknown
23
+ * name is refused before anything runs; invalid arguments and a failing tool come back as an `isError` result.
24
+ *
25
+ * It does NOT run the extensions' `tool_call`/`tool_result` handlers (permission checks among them): where those
26
+ * run for a call that reaches a tool-execution-only process is decided by the remote tool executor that calls
27
+ * this runtime, including forwarding a two-sided extension's handlers to the process that owns the session.
28
+ * Until that executor exists, a runtime refuses every call unless it was built with a grant from the closed
29
+ * allowlist in `loopless-execute-grant.ts` (the in-process test harness only).
30
+ */
31
+ execute(name: string, toolCallId: string, params: unknown, signal?: AbortSignal): Promise<AgentToolResult<unknown>>;
32
+ /** Marks its extension contexts stale, then closes the tool work and the tool child it still runs. */
33
+ dispose(): Promise<void>;
34
+ }
35
+ export interface LooplessRuntimeProfile {
36
+ cwd: string;
37
+ launchProfile?: Readonly<AgentSessionLaunchProfile>;
38
+ }
39
+ export type LooplessRuntimeFactory = (profile: LooplessRuntimeProfile) => Promise<LooplessRuntime>;
40
+ export declare class LooplessToolNotFoundError extends Error {
41
+ readonly toolName: string;
42
+ constructor(toolName: string);
43
+ }
44
+ /**
45
+ * Builds loopless runtimes from the same launch configuration as `createCliRuntimeFactory`: the same
46
+ * cwd-bound services (settings, project trust, model registry, extensions and their flags), then the tool
47
+ * registry through `bootstrapRuntime()` / `buildToolRegistry()` (senpi#5222) on a runner without a session
48
+ * (senpi#5223), so nothing is ever written to a session file. Tools are placed by the same tool-child runtime
49
+ * a session builds (senpi#5227), so `--tool-runtime child` runs child-placed work on this runtime's own child.
50
+ */
51
+ export declare function createLooplessRuntimeFactory(configuration: CliRuntimeConfiguration, local?: {
52
+ extensionFactories?: InlineExtension[];
53
+ startupSettingsManager?: SettingsManager;
54
+ /** Required for `execute`; see `loopless-execute-grant.ts`. */
55
+ executeGrant?: LooplessExecuteGrant;
56
+ }): LooplessRuntimeFactory;
57
+ //# sourceMappingURL=runtime-factory-loopless.d.ts.map
@@ -0,0 +1,131 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { createAgentSessionServices } from "../../core/agent-session-services.js";
3
+ import { bootstrapRuntime, buildToolRegistry } from "../../core/runtime/bootstrap.js";
4
+ import { SettingsManager } from "../../core/settings-manager.js";
5
+ import { childModuleRoots } from "../../core/tool-dispatch/offload.js";
6
+ import { createToolChildRuntime } from "../../core/tool-dispatch/tool-child-runtime.js";
7
+ import { builtInExtensions } from "../../extensions/index.js";
8
+ import { looplessToolFilters, resolveCliPaths, resolveLooplessSettings } from "./loopless-runtime-settings.js";
9
+ import { isLooplessExecuteGranted, LooplessExecuteRefusedError, } from "./loopless-execute-grant.js";
10
+ import { runLooplessToolCall } from "./loopless-tool-call.js";
11
+ import { toolChildModuleRoots } from "./tool-child/session-child.js";
12
+ export class LooplessToolNotFoundError extends Error {
13
+ constructor(toolName) {
14
+ super(`loopless_tool_not_found: ${toolName}`);
15
+ this.toolName = toolName;
16
+ }
17
+ }
18
+ /**
19
+ * Builds loopless runtimes from the same launch configuration as `createCliRuntimeFactory`: the same
20
+ * cwd-bound services (settings, project trust, model registry, extensions and their flags), then the tool
21
+ * registry through `bootstrapRuntime()` / `buildToolRegistry()` (senpi#5222) on a runner without a session
22
+ * (senpi#5223), so nothing is ever written to a session file. Tools are placed by the same tool-child runtime
23
+ * a session builds (senpi#5227), so `--tool-runtime child` runs child-placed work on this runtime's own child.
24
+ */
25
+ export function createLooplessRuntimeFactory(configuration, local = {}) {
26
+ const { parsed, agentDir, toolRuntime } = configuration;
27
+ const extensionFactories = local.extensionFactories ?? builtInExtensions;
28
+ const startupSettingsManager = local.startupSettingsManager ?? SettingsManager.create(configuration.cwd, configuration.agentDir);
29
+ return async (profile) => {
30
+ const { cwd } = profile;
31
+ const diagnostics = [];
32
+ const { settingsManager, flagValues, reloadOptions } = await resolveLooplessSettings(configuration, startupSettingsManager, profile, diagnostics);
33
+ const services = await createAgentSessionServices({
34
+ cwd,
35
+ agentDir,
36
+ settingsManager,
37
+ modelRuntimeSignal: AbortSignal.timeout(15_000),
38
+ extensionFlagValues: flagValues,
39
+ ...(reloadOptions ? { resourceLoaderReloadOptions: reloadOptions } : {}),
40
+ resourceLoaderOptions: {
41
+ sessionKind: profile.launchProfile?.sessionKind,
42
+ sessionContext: profile.launchProfile?.sessionContext,
43
+ additionalExtensionPaths: resolveCliPaths(cwd, parsed.extensions),
44
+ additionalSkillPaths: resolveCliPaths(cwd, parsed.skills),
45
+ additionalPromptTemplatePaths: resolveCliPaths(cwd, parsed.promptTemplates),
46
+ additionalThemePaths: resolveCliPaths(cwd, parsed.themes),
47
+ noExtensions: parsed.noExtensions,
48
+ noSkills: parsed.noSkills,
49
+ noPromptTemplates: parsed.noPromptTemplates,
50
+ noThemes: parsed.noThemes,
51
+ noContextFiles: parsed.noContextFiles,
52
+ extensionFactories,
53
+ },
54
+ });
55
+ const extensionsResult = services.resourceLoader.getExtensions();
56
+ diagnostics.push(...services.diagnostics, ...extensionsResult.errors.map(({ path, error }) => ({
57
+ type: "warning",
58
+ message: `Failed to load extension "${path}": ${error}`,
59
+ })), ...(extensionsResult.warnings ?? []).map(({ path, warning }) => ({
60
+ type: "warning",
61
+ message: `Extension package "${path}": ${warning}`,
62
+ })));
63
+ let execute = () => Promise.reject(new Error("Loopless runtime is not ready"));
64
+ let toolNames = () => [];
65
+ const toolChildRuntime = createToolChildRuntime({
66
+ toolRuntime: toolRuntime ?? "in-process",
67
+ agentDir,
68
+ scopeId: `loopless-${randomUUID()}`,
69
+ cwd: services.cwd,
70
+ moduleRoots: () => [
71
+ ...toolChildModuleRoots(runtime.extensionRunner.getAllRegisteredTools()),
72
+ ...childModuleRoots(runtime.extensionRunner.getAllChildModules()),
73
+ ],
74
+ hostCallDeps: {
75
+ cwd: services.cwd,
76
+ executeNested: async (_parentToolCallId, name, args, signal) => {
77
+ const toolCall = { type: "toolCall", id: `nested-${randomUUID()}`, name, arguments: {} };
78
+ const result = await execute(name, toolCall.id, args, signal);
79
+ return { toolCall, result, isError: result.isError === true };
80
+ },
81
+ callableToolNames: () => toolNames(),
82
+ target: () => undefined,
83
+ filesystemPolicy: () => runtime.filesystemPolicy,
84
+ },
85
+ onRecord: () => { },
86
+ });
87
+ const { dispatcher, toolChild } = toolChildRuntime;
88
+ const runtime = bootstrapRuntime({
89
+ cwd: services.cwd,
90
+ settingsManager: services.settingsManager,
91
+ extensionsResult,
92
+ modelRegistry: services.modelRegistry,
93
+ toolDispatcher: dispatcher,
94
+ });
95
+ const registry = buildToolRegistry({
96
+ baseToolDefinitions: runtime.baseToolDefinitions,
97
+ runner: runtime.extensionRunner,
98
+ dispatcher,
99
+ ...looplessToolFilters(parsed, services.settingsManager),
100
+ });
101
+ toolNames = () => [...registry.toolRegistry.keys()];
102
+ execute = (name, toolCallId, params, signal) => {
103
+ if (!isLooplessExecuteGranted(local.executeGrant))
104
+ return Promise.reject(new LooplessExecuteRefusedError("no executor runs the tool_call/tool_result handlers for this runtime yet"));
105
+ const tool = registry.toolRegistry.get(name);
106
+ if (tool === undefined)
107
+ return Promise.reject(new LooplessToolNotFoundError(name));
108
+ return runLooplessToolCall(tool, {
109
+ toolCallId,
110
+ params,
111
+ ...(signal ? { signal } : {}),
112
+ });
113
+ };
114
+ return {
115
+ cwd: services.cwd,
116
+ definitions: registry.definitions,
117
+ diagnostics,
118
+ execute: (name, toolCallId, params, signal) => execute(name, toolCallId, params, signal),
119
+ dispose: async () => {
120
+ // Stale first, as a session disposes: a close that fails must not leave the contexts usable.
121
+ runtime.extensionRunner.invalidate("This loopless runtime was disposed.");
122
+ // Both closes run to the end; the first failure is then reported to the caller.
123
+ const closed = await Promise.allSettled([dispatcher.dispose(), toolChild?.close()]);
124
+ const failure = closed.find((outcome) => outcome.status === "rejected");
125
+ if (failure !== undefined)
126
+ throw failure.reason;
127
+ },
128
+ };
129
+ };
130
+ }
131
+ //# sourceMappingURL=runtime-factory-loopless.js.map
@@ -4,7 +4,7 @@ import { createRegistryWarm } from "./host-warm.js";
4
4
  import { refreshesSessionActivity } from "./session-command-activity.js";
5
5
  import { publishedSessionContext } from "./session-context-patch.js";
6
6
  import { attachLiveSession, markPathAttached } from "./session-live-attachment.js";
7
- import { syncRuntimeMetadata } from "./session-registry-claims.js";
7
+ import { beginPendingClaim, syncRuntimeMetadata } from "./session-registry-claims.js";
8
8
  import { openRegistrySession } from "./session-registry-open.js";
9
9
  import { RpcSessionRegistryError, } from "./session-registry-types.js";
10
10
  import { beginSessionClose, closeMarkedSession, closeSession } from "./session-teardown.js";
@@ -44,8 +44,17 @@ export class RpcSessionRegistry {
44
44
  return deleted;
45
45
  },
46
46
  releaseReservation: async (key) => {
47
- await this.options.pathReservations?.release(key);
48
- this.reservations.delete(key);
47
+ // Close may finish at its grace deadline before removal settles. Keep
48
+ // that work visible to reopen even after the closing entry is gone. A failed removal
49
+ // still gives the path back: no entry is left to ever release it later.
50
+ const settle = beginPendingClaim(this.pendingClaims, key);
51
+ try {
52
+ await this.options.pathReservations?.release(key);
53
+ }
54
+ finally {
55
+ this.reservations.delete(key);
56
+ settle();
57
+ }
49
58
  },
50
59
  markDetached: (key) => this.options.pathReservations?.setAttached(key, false),
51
60
  now: () => this.now(),
@@ -5,6 +5,7 @@ import { createWebViewBroker } from "../../core/webview/webview-broker.js";
5
5
  import { workerCapabilities } from "./worker-client-capabilities.js";
6
6
  import { captureAdmissionReply, withAdmissionReply } from "./compact-admission-reply.js";
7
7
  import { roleConnection } from "./connection-roles.js";
8
+ import { originField } from "./remote-origin.js";
8
9
  import { answeredUiRequestId, isGrantSelectRequest, refusedExtensionUiResponse } from "./extension-ui-response.js";
9
10
  import { enqueueLegacyRecord } from "./legacy-record-depth.js";
10
11
  import { SessionAcceptanceLane } from "./session-acceptance-lane.js";
@@ -199,6 +200,7 @@ export class SessionWorkerClient {
199
200
  command,
200
201
  connection,
201
202
  roles: options.connectionRoles?.rolesOf(roleConnection(connection)),
203
+ ...originField(options.connectionRoles?.originOf(connection)),
202
204
  ...(owner === undefined ? {} : { owner }),
203
205
  });
204
206
  },
@@ -1,3 +1,4 @@
1
+ import type { RpcRemoteOrigin } from "./remote-origin.ts";
1
2
  import type { BrowserEngine } from "../../core/browser-engine.ts";
2
3
  import type { McpFormInput, McpFormOutcome } from "../../core/mcp-form-types.ts";
3
4
  import type { RecoveryCarrier } from "../../core/session-recovery-identity.ts";
@@ -96,6 +97,8 @@ export type HostToSessionWorker = {
96
97
  command: object;
97
98
  connection?: string;
98
99
  roles?: readonly string[];
100
+ /** The remote device the connection declared on the host (senpi#5475); the isolate adopts it. */
101
+ origin?: RpcRemoteOrigin;
99
102
  /** The gate the host captured at ingress, before its first await (#4728). */
100
103
  owner?: ExtensionOwnerWire;
101
104
  }
@@ -338,6 +338,8 @@ async function handle(message) {
338
338
  throw new Error("session_closing");
339
339
  if (message.roles !== undefined)
340
340
  connectionRoles.adopt(roleConnection(message.connection), message.roles);
341
+ if (message.origin !== undefined)
342
+ connectionRoles.declareOrigin(roleConnection(message.connection), message.origin);
341
343
  const activeBinding = binding;
342
344
  const run = () => activeBinding.handle(message.command);
343
345
  await workerAdmissionCommand(message, writer, issuedOwners, run);
@@ -70,7 +70,7 @@ Never use `__dirname` directly for package assets.
70
70
  ```bash
71
71
  bun run test # Vitest across workspaces (skips live-API; default test runner)
72
72
  ./pi-test.sh # Launch the CLI from source via tsx for manual testing (--no-env unsets API keys)
73
- bun run check # oxlint + oxfmt + lint ratchet + tsc + browser-smoke check (pre-commit equivalent)
73
+ bun run check # oxlint + bun fmt + lint ratchet + tsc + browser-smoke check (pre-commit equivalent)
74
74
  ```
75
75
 
76
76
  Live-API tests are env-gated vitest tests. Set `PI_ENABLE_LIVE_API_TESTS=1` (or a per-provider flag from `packages/ai/test/live-api-gates.ts`) plus the provider API keys, then run `bun run test`.
@@ -43,9 +43,9 @@
43
43
  "hint": "restart_from_catalog",
44
44
  "retryAfterMs": 0
45
45
  },
46
- "length": 1000,
47
- "digest": "131dc6a4a4e49873ce5d5d0330f81816be72c8a12c25dec7d14d4fe2c9cc32e4",
48
- "bytes": "ewAiAGYAbwByAG0AYQB0ACIAOgAiAHMAZQBuAHAAaQAtAHIAZQBjAG8AdgBlAHIAeQAtAG0AYQBuAGkAZgBlAHMAdAAiACwAIgB2AGUAcgBzAGkAbwBuACIAOgAxACwAIgBzAG8AYwBrAGUAdABFAHAAbwBjAGgAIgA6AHsAIgBpAGQAIgA6ACIAcwBvAGMAawBlAHQALQAxACIAfQAsACIAYQBkAG0AaQBzAHMAaQBvAG4ASQBkACIAOgB7ACIAaQBkACIAOgAiAGcAbwBsAGQAZQBuAC0AYQAiAH0ALAAiAHIAbwB1AHQAZQBLAGkAbgBkACIAOgAiAG8AcgBkAGkAbgBhAHIAeQAiACwAIgBzAGUAcwBzAGkAbwBuACIAOgB7ACIAaQBkACIAOgAiAHIAcABjAC0AMQAiAH0ALAAiAHMAZQBzAHMAaQBvAG4ARQBwAG8AYwBoACIAOgB7ACIAaQBkACIAOgAiADAAMAAwADAAMAAwADAAMAAtADAAMAAwADAALQA0ADAAMAAwAC0AOAAwADAAMAAtADAAMAAwADAAMAAwADAAMAAwADAAMAAxACIAfQAsACIAZwBlAG4AZQByAGEAdABpAG8AbgAiADoAMQAsACIAcwBlAHEAdQBlAG4AYwBlACIAOgAwACwAIgBoAGkAcwB0AG8AcgB5AFYAZQByAHMAaQBvAG4AIgA6ADUALAAiAHQAbwBrAGUAbgAiADoAewAiAGkAZAAiADoAIgBzAG8AYwBrAGUAdAAtADEAOgAxACIAfQAsACIAbABlAGEAZgAiADoAewAiAGkAZAAiADoAIgAwADAAMAAwADAAMAAwADEAIgB9ACwAIgBhAGMAdABpAHYAZQBNAGUAcwBzAGEAZwBlACIAOgBuAHUAbABsACwAIgB0AHUAcgBuACIAOgBuAHUAbABsACwAIgBjAGgAZQBjAGsAcABvAGkAbgB0AEQAaQBnAGUAcwB0ACIAOgAiADEAYgBiAGMAYQBkADIAOQAzADIAMABmADIAMAA4ADQANwBhADUAMQA1AGMAYwA4ADUANAAwADYAMwBjAGQAYQAwAGQAZABhAGUAYQAyADAAYwBkAGMAZgBmADQANQBlAGIANgBiADUAZQAwAGUAOQBlAGUAMQA1AGYAYgBkADQAIgAsACIAYwBhAHQAYQBsAG8AZwBSAG8AbwB0ACIAOgAiAGMALQAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAxACIALAAiAGMAYQB0AGEAbABvAGcAUgBvAG8AdABMAGUAbgBnAHQAaAAiADoAMwA5ADQANgB9AA=="
46
+ "length": 1230,
47
+ "digest": "afc0506ef0b5e09ae70818c0b435b2fa633d3536d44f6e357950aad78d0102f9",
48
+ "bytes": "ewAiAGYAbwByAG0AYQB0ACIAOgAiAHMAZQBuAHAAaQAtAHIAZQBjAG8AdgBlAHIAeQAtAG0AYQBuAGkAZgBlAHMAdAAiACwAIgB2AGUAcgBzAGkAbwBuACIAOgAxACwAIgBzAG8AYwBrAGUAdABFAHAAbwBjAGgAIgA6AHsAIgBpAGQAIgA6ACIAcwBvAGMAawBlAHQALQAxACIAfQAsACIAYQBkAG0AaQBzAHMAaQBvAG4ASQBkACIAOgB7ACIAaQBkACIAOgAiAGcAbwBsAGQAZQBuAC0AYQAiAH0ALAAiAHIAbwB1AHQAZQBLAGkAbgBkACIAOgAiAG8AcgBkAGkAbgBhAHIAeQAiACwAIgBzAGUAcwBzAGkAbwBuACIAOgB7ACIAaQBkACIAOgAiAHIAcABjAC0AMQAiAH0ALAAiAHMAZQBzAHMAaQBvAG4ARQBwAG8AYwBoACIAOgB7ACIAaQBkACIAOgAiADAAMAAwADAAMAAwADAAMAAtADAAMAAwADAALQA0ADAAMAAwAC0AOAAwADAAMAAtADAAMAAwADAAMAAwADAAMAAwADAAMAAxACIAfQAsACIAZwBlAG4AZQByAGEAdABpAG8AbgAiADoAMQAsACIAcwBlAHEAdQBlAG4AYwBlACIAOgAwACwAIgBoAGkAcwB0AG8AcgB5AFYAZQByAHMAaQBvAG4AIgA6ADUALAAiAHQAbwBrAGUAbgAiADoAewAiAGkAZAAiADoAIgBzAG8AYwBrAGUAdAAtADEAOgAxACIAfQAsACIAbABlAGEAZgAiADoAewAiAGkAZAAiADoAIgAwADAAMAAwADAAMAAwADEAIgB9ACwAIgBhAGMAdABpAHYAZQBNAGUAcwBzAGEAZwBlACIAOgBuAHUAbABsACwAIgB0AHUAcgBuACIAOgBuAHUAbABsACwAIgBjAGgAZQBjAGsAcABvAGkAbgB0AEQAaQBnAGUAcwB0ACIAOgAiADEAYgBiAGMAYQBkADIAOQAzADIAMABmADIAMAA4ADQANwBhADUAMQA1AGMAYwA4ADUANAAwADYAMwBjAGQAYQAwAGQAZABhAGUAYQAyADAAYwBkAGMAZgBmADQANQBlAGIANgBiADUAZQAwAGUAOQBlAGUAMQA1AGYAYgBkADQAIgAsACIAYwBhAHQAYQBsAG8AZwBSAG8AbwB0ACIAOgAiAGMALQAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAxACIALAAiAGMAYQB0AGEAbABvAGcAUgBvAG8AdABMAGUAbgBnAHQAaAAiADoAMwA5ADQANgAsACIAcgBlAHEAdQBpAHIAZQBkAEsAaQBuAGQAcwAiADoAWwAiAGEAYwB0AGkAdgBlACIALAAiAGMAYQBsAGwAcwAiACwAIgBkAGkAYQBsAG8AZwBzACIALAAiAGkAZABlAG4AdABpAHQAeQAiACwAIgBsAGkAZgBlAGMAeQBjAGwAZQAiACwAIgBvAHAAYQBxAHUAZQAiACwAIgByAHUAbgAiACwAIgBzAGUAdAB0AGwAZQBkACIALAAiAHMAbwB1AHIAYwBlACIALAAiAHQAcgBhAG4AcwBjAHIAaQBwAHQAIgBdAH0A"
49
49
  }
50
50
  }
51
51
  }