@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
@@ -1,3 +1,4 @@
1
+ import { type FamilyRegistry } from "./compact-catalog-registry.ts";
1
2
  import type { CompactContentStore } from "./compact-content-store.ts";
2
3
  import type { CatalogComponent } from "./compact-recovery-catalog.ts";
3
4
  import type { SettledReader } from "./compact-settled-messages.ts";
@@ -16,8 +17,10 @@ interface CatalogCut {
16
17
  * the members it enumerated and never an explicit empty, so a reader can tell "no members" from "not enumerated"
17
18
  * (RULING-60 Q1, RULING-61 Q1). Members stream one at a time: a value goes through `walk` into bounded leaves, a
18
19
  * collection through `rows`, and each component's leaves are released once the catalog has placed it. The
19
- * completeness gate runs last: a complete producer that emitted nothing refuses the whole catalog (X03).
20
+ * completeness gate runs last: a complete producer that emitted nothing refuses the whole catalog (X03). Its return
21
+ * value is the registry it emitted as `families/families`, the one source the manifest copies `requiredKinds` from
22
+ * (RULING-128).
20
23
  */
21
- export declare function checkpointComponents(cut: CatalogCut, valid: () => void): AsyncGenerator<CatalogComponent>;
24
+ export declare function checkpointComponents(cut: CatalogCut, valid: () => void): AsyncGenerator<CatalogComponent, FamilyRegistry>;
22
25
  export {};
23
26
  //# sourceMappingURL=compact-catalog-families.d.ts.map
@@ -18,7 +18,9 @@ const DIALOGS = familyId("dialogs");
18
18
  * the members it enumerated and never an explicit empty, so a reader can tell "no members" from "not enumerated"
19
19
  * (RULING-60 Q1, RULING-61 Q1). Members stream one at a time: a value goes through `walk` into bounded leaves, a
20
20
  * collection through `rows`, and each component's leaves are released once the catalog has placed it. The
21
- * completeness gate runs last: a complete producer that emitted nothing refuses the whole catalog (X03).
21
+ * completeness gate runs last: a complete producer that emitted nothing refuses the whole catalog (X03). Its return
22
+ * value is the registry it emitted as `families/families`, the one source the manifest copies `requiredKinds` from
23
+ * (RULING-128).
22
24
  */
23
25
  export async function* checkpointComponents(cut, valid) {
24
26
  const { store, values, root, settled } = cut;
@@ -26,7 +28,7 @@ export async function* checkpointComponents(cut, valid) {
26
28
  if (!current)
27
29
  throw new CompactReadError("unavailable");
28
30
  const reader = { store, values, valid };
29
- const producers = familyProducers(root.transcript, root.refusedCorrelations);
31
+ const producers = familyProducers(root);
30
32
  const registry = familyRegistry(producers);
31
33
  yield* textComponent(store, FAMILIES, FAMILIES, JSON.stringify(registry));
32
34
  const family = (name) => {
@@ -66,6 +68,7 @@ export async function* checkpointComponents(cut, valid) {
66
68
  yield component;
67
69
  }
68
70
  assertCoverage(registry, emitted);
71
+ return registry;
69
72
  }
70
73
  async function* dialogComponents(reader, ref) {
71
74
  const dialogs = new CompactComponentRoots(reader.store, () => []);
@@ -26,7 +26,10 @@ export declare const FAMILY_PRODUCERS: FamilyProducers;
26
26
  * correlation refused at the protocol depth limit never became the lane's standing one, so `identity` is then
27
27
  * `partial` too: its member reports the count (RULING-67 (4)).
28
28
  */
29
- export declare function familyProducers(transcript: TranscriptRoot, refusedCorrelations: number): FamilyProducers;
29
+ export declare function familyProducers(root: {
30
+ readonly transcript: TranscriptRoot;
31
+ readonly refusedCorrelations: number;
32
+ }): FamilyProducers;
30
33
  /**
31
34
  * Every engine source kind (the session file's entry union) and the family that owns its data. The compiler refuses
32
35
  * a kind this map misses (TS2741), so a new engine entry type cannot ship uncataloged. A kind outside the union at
@@ -46,6 +49,11 @@ interface RegistryBase {
46
49
  readonly format: "senpi-recovery-families";
47
50
  readonly version: 1;
48
51
  readonly families: readonly FamilyRow[];
52
+ /**
53
+ * The families a root built from these producers requires (RULING-128): every `complete` one, in code-unit order,
54
+ * each once. The manifest carries this exact list, and this component's digest is inside `checkpointDigest`.
55
+ */
56
+ readonly requiredKinds: readonly CatalogFamily[];
49
57
  }
50
58
  /**
51
59
  * Set only by `familyRegistry`, which `readFamilyRegistry` decodes through and `completeAssembly` narrows to, so no other
@@ -46,7 +46,8 @@ export const FAMILY_PRODUCERS = {
46
46
  * correlation refused at the protocol depth limit never became the lane's standing one, so `identity` is then
47
47
  * `partial` too: its member reports the count (RULING-67 (4)).
48
48
  */
49
- export function familyProducers(transcript, refusedCorrelations) {
49
+ export function familyProducers(root) {
50
+ const { transcript, refusedCorrelations } = root;
50
51
  const exact = transcript.unavailable === null;
51
52
  const entries = exact
52
53
  ? {}
@@ -83,7 +84,11 @@ const COMPLETE = Symbol("complete family registry");
83
84
  export function familyRegistry(producers) {
84
85
  const families = CATALOG_FAMILIES.map((family) => ({ family, producer: producers[family] }));
85
86
  const incomplete = families.filter(({ producer }) => producer !== "complete").map(({ family }) => family);
86
- const base = { format: "senpi-recovery-families", version: 1, families };
87
+ const requiredKinds = families
88
+ .filter(({ producer }) => producer === "complete")
89
+ .map(({ family }) => family)
90
+ .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
91
+ const base = { format: "senpi-recovery-families", version: 1, families, requiredKinds };
87
92
  return incomplete.length === 0
88
93
  ? { ...base, assembly: "complete", [COMPLETE]: true }
89
94
  : { ...base, assembly: "incomplete", incomplete };
@@ -133,6 +138,8 @@ export function readFamilyRegistry(text) {
133
138
  const registry = familyRegistry({ ...FAMILY_PRODUCERS, ...producers });
134
139
  if (field(value, "assembly") !== registry.assembly)
135
140
  throw new RangeError("family registry assembly mismatch");
141
+ if (JSON.stringify(field(value, "requiredKinds")) !== JSON.stringify(registry.requiredKinds))
142
+ throw new RangeError("family registry requiredKinds mismatch");
136
143
  return registry;
137
144
  }
138
145
  //# sourceMappingURL=compact-catalog-registry.js.map
@@ -0,0 +1,17 @@
1
+ import { type CatalogFamily, type FamilyRegistry } from "./compact-catalog-registry.ts";
2
+ export type RequiredKindsRefusal = "manifest_missing_required_kinds" | "manifest_unknown_required_kind" | "manifest_required_kinds_mismatch";
3
+ export type RequiredKindsRead = {
4
+ readonly ok: true;
5
+ readonly requiredKinds: readonly CatalogFamily[];
6
+ } | {
7
+ readonly ok: false;
8
+ readonly code: RequiredKindsRefusal;
9
+ };
10
+ /**
11
+ * The families a client opens for one decoded manifest (RULING-128): its `requiredKinds`, read verbatim and never
12
+ * replaced by a built-in family list. `registry` is the cut's `families/families` component as `readFamilyRegistry`
13
+ * decodes it from bytes verified against the root entry that `checkpointDigest` covers. The digest covers that
14
+ * component, not the manifest field, so the list opens only when it equals the component's complete families.
15
+ */
16
+ export declare function readRequiredKinds(manifest: unknown, registry: FamilyRegistry): RequiredKindsRead;
17
+ //# sourceMappingURL=compact-recovery-manifest-kinds.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { CATALOG_FAMILIES } from "./compact-catalog-registry.js";
2
+ const KNOWN = new Set(CATALOG_FAMILIES);
3
+ const isKnown = (kind) => typeof kind === "string" && KNOWN.has(kind);
4
+ /**
5
+ * The families a client opens for one decoded manifest (RULING-128): its `requiredKinds`, read verbatim and never
6
+ * replaced by a built-in family list. `registry` is the cut's `families/families` component as `readFamilyRegistry`
7
+ * decodes it from bytes verified against the root entry that `checkpointDigest` covers. The digest covers that
8
+ * component, not the manifest field, so the list opens only when it equals the component's complete families.
9
+ */
10
+ export function readRequiredKinds(manifest, registry) {
11
+ const listed = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "requiredKinds") : undefined;
12
+ if (!Array.isArray(listed))
13
+ return { ok: false, code: "manifest_missing_required_kinds" };
14
+ if (!listed.every(isKnown))
15
+ return { ok: false, code: "manifest_unknown_required_kind" };
16
+ const complete = registry.requiredKinds;
17
+ if (listed.length !== complete.length || listed.some((kind, index) => kind !== complete[index]))
18
+ return { ok: false, code: "manifest_required_kinds_mismatch" };
19
+ return { ok: true, requiredKinds: complete };
20
+ }
21
+ //# sourceMappingURL=compact-recovery-manifest-kinds.js.map
@@ -1,3 +1,4 @@
1
+ import type { CatalogFamily } from "./compact-catalog-registry.ts";
1
2
  import type { BoundedId, ContentDigest, ContentRef } from "./compact-recovery-ids.ts";
2
3
  import type { RecoveryRouteKind } from "./compact-recovery-types.ts";
3
4
  /** A manifest string: inline when it is a bounded protocol id, otherwise a ref to its exact stored value. */
@@ -31,6 +32,12 @@ export interface RecoveryManifest {
31
32
  readonly checkpointDigest: ContentDigest;
32
33
  readonly catalogRoot: ContentRef;
33
34
  readonly catalogRootLength: number;
35
+ /**
36
+ * The catalog families this cut's root requires (RULING-128): its complete families only, sorted, each once. It is
37
+ * the `requiredKinds` of the cut's `families/families` registry, so `checkpointDigest` covers it; a client opens
38
+ * exactly these and never falls back to a built-in family list.
39
+ */
40
+ readonly requiredKinds: readonly CatalogFamily[];
34
41
  }
35
42
  export declare const TEXT_FIELDS: readonly ["socketEpoch", "admissionId", "session", "sessionEpoch", "token", "leaf", "activeMessage", "turn"];
36
43
  export type TextField = (typeof TEXT_FIELDS)[number];
@@ -128,12 +128,19 @@ export class RecoveryManifests {
128
128
  valid();
129
129
  };
130
130
  const cut = { store, values: new CompactValues(store), root, settled: lane.settledOf(root) };
131
+ const emitted = {};
131
132
  const components = async function* () {
132
133
  yield* oversized.map(({ component }) => component);
133
- yield* checkpointComponents(cut, check);
134
+ emitted.registry = yield* checkpointComponents(cut, check);
134
135
  };
135
136
  const built = await this.catalogs.build(store, ref, components(), check);
136
- return await this.assemble(store, token, ref, built, oversized, texts);
137
+ // The list is the cataloged registry's own (RULING-128): the bytes `checkpointDigest` covers, never a recompute.
138
+ const requiredKinds = emitted.registry?.requiredKinds;
139
+ if (!requiredKinds) {
140
+ this.catalogs.release(store, built);
141
+ throw new CompactReadError("ownership");
142
+ }
143
+ return await this.assemble(store, token, ref, built, oversized, texts, requiredKinds);
137
144
  }
138
145
  finally {
139
146
  for (const { component } of oversized)
@@ -144,7 +151,7 @@ export class RecoveryManifests {
144
151
  });
145
152
  }
146
153
  /** Owns `built` from here: a failure anywhere below releases the tree, so no owner outlives a refused build. */
147
- async assemble(store, token, ref, built, oversized, texts) {
154
+ async assemble(store, token, ref, built, oversized, texts, requiredKinds) {
148
155
  try {
149
156
  let leftmost = ref;
150
157
  for (let level = 1; level < built.depth; level++)
@@ -183,6 +190,7 @@ export class RecoveryManifests {
183
190
  checkpointDigest: built.digest,
184
191
  catalogRoot: ref,
185
192
  catalogRootLength: built.length,
193
+ requiredKinds,
186
194
  };
187
195
  return { manifest, root: built, store };
188
196
  }
@@ -1,11 +1,15 @@
1
1
  import { compactUpdatesEnabled } from "../../core/engine-socket-flag.js";
2
2
  import { CONNECTION_ROLE_FIXED, roleConnection } from "./connection-roles.js";
3
+ import { remoteOriginDeclaration } from "./remote-origin.js";
3
4
  import { error } from "./session-router-errors.js";
4
5
  /** Validate the full declaration before committing role, media, recovery or pending state. */
5
6
  export function declareSocketClient(host, command) {
6
7
  const peer = host.writer.currentConnection();
7
8
  const selection = peer === undefined ? undefined : host.writer.compactSelection(peer);
8
9
  const role = (caps) => host.connectionRoles.declare(roleConnection(peer), caps);
10
+ const origin = remoteOriginDeclaration(command.remoteOrigin, (declared) => host.connectionRoles.acceptsOrigin(roleConnection(peer), declared));
11
+ if ("refusal" in origin)
12
+ return error(command.id, command.type, origin.refusal);
9
13
  const reason = selection
10
14
  ? selection.declare(command.capabilities, host.registry.supportsCompact?.() === true, role)
11
15
  : command.capabilities !== undefined && !role(command.capabilities)
@@ -23,6 +27,8 @@ export function declareSocketClient(host, command) {
23
27
  }
24
28
  else if (command.capabilities !== undefined)
25
29
  host.writer.setSoleSecretCapabilities(command.capabilities);
30
+ if (origin.origin !== undefined)
31
+ host.connectionRoles.declareOrigin(roleConnection(peer), origin.origin);
26
32
  return {
27
33
  id: command.id,
28
34
  type: "response",
@@ -45,6 +45,7 @@ import { DURABLE_CLIENT_MESSAGE_ID_CAPABILITY } from "./client-admission-record.
45
45
  import { ClientAdmissions } from "./client-admissions.js";
46
46
  import { handleClientInput } from "./client-input-handler.js";
47
47
  import { ConnectionQuestionBridge, degradeQuestion, sessionQuestionBridges } from "./connection-question-bridge.js";
48
+ import { remoteOriginDeclaration, remoteOriginField } from "./remote-origin.js";
48
49
  import { advertisedCompactCapabilities, sessionDeclaration } from "./compact-negotiation.js";
49
50
  import { ConnectionRoles, roleConnection } from "./connection-roles.js";
50
51
  import { AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, buildCustomUnsupportedRequest, CONTINUE_FROM_LEAF_CAPABILITY, DEFAULT_CUSTOM_EXTENSION_LABEL, EVAL_CELLS_CAPABILITY, EXTENSION_EVENTS_CAPABILITY, ENTRIES_TAIL_CAPABILITY, INTERACTIVE_USER_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUESTION_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETRY_FALLBACK_COMMAND_CAPABILITY, SESSION_HELD_CAPABILITY, TOOL_BARRIER_CAPABILITY, TASK_PARENT_CAPABILITY, } from "./custom-capability.js";
@@ -339,7 +340,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
339
340
  const pendingExtensionRequests = new SessionExtensionUiRequests(uiRequestChanged);
340
341
  const grantRequests = new Map();
341
342
  sessionDialogRequests.set(session, pendingExtensionRequests);
342
- const questions = new ConnectionQuestionBridge(output, uiRequestChanged, () => options.clientInfo?.connectionId());
343
+ const raiserOrigin = () => connectionRoles.originOf(options.clientInfo?.connectionId());
344
+ const questions = new ConnectionQuestionBridge(output, uiRequestChanged, () => options.clientInfo?.connectionId(), raiserOrigin);
343
345
  let secretHandshake = false;
344
346
  const secretOwners = new Map();
345
347
  const secretCapable = (connection) => connectionRoles.has(connection, INTERACTIVE_USER_CAPABILITY) &&
@@ -381,6 +383,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
381
383
  if (opts?.signal?.aborted)
382
384
  return Promise.resolve(defaultValue);
383
385
  const id = crypto.randomUUID();
386
+ const raised = { ...request, ...remoteOriginField(raiserOrigin()) };
384
387
  return new Promise((resolve, reject) => {
385
388
  let timeoutId;
386
389
  const cleanup = () => {
@@ -403,7 +406,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
403
406
  }, opts.timeout);
404
407
  }
405
408
  pendingExtensionRequests.set(id, {
406
- frame: { type: "extension_ui_request", id, ...request },
409
+ frame: { type: "extension_ui_request", id, ...raised },
407
410
  resolve: (response) => {
408
411
  cleanup();
409
412
  resolve(parseResponse(response));
@@ -412,7 +415,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
412
415
  });
413
416
  if (request.grantSelect === true)
414
417
  grantRequests.set(id, options.clientInfo?.connectionId());
415
- output({ type: "extension_ui_request", id, ...request });
418
+ output({ type: "extension_ui_request", id, ...raised });
416
419
  });
417
420
  }
418
421
  const selectGrantDialog = (title, choices, opts) => createDialogPromise(opts, undefined, {
@@ -549,9 +552,17 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
549
552
  },
550
553
  async editor(title, prefill) {
551
554
  const id = crypto.randomUUID();
555
+ const frame = {
556
+ type: "extension_ui_request",
557
+ id,
558
+ method: "editor",
559
+ title,
560
+ prefill,
561
+ ...remoteOriginField(raiserOrigin()),
562
+ };
552
563
  return new Promise((resolve, reject) => {
553
564
  pendingExtensionRequests.set(id, {
554
- frame: { type: "extension_ui_request", id, method: "editor", title, prefill },
565
+ frame,
555
566
  resolve: (response) => {
556
567
  if ("cancelled" in response && response.cancelled) {
557
568
  resolve(undefined);
@@ -565,7 +576,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
565
576
  },
566
577
  reject,
567
578
  });
568
- output({ type: "extension_ui_request", id, method: "editor", title, prefill });
579
+ output(frame);
569
580
  });
570
581
  },
571
582
  addAutocompleteProvider() {
@@ -1164,9 +1175,14 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1164
1175
  // State
1165
1176
  // =================================================================
1166
1177
  case "set_client_info": {
1178
+ const origin = remoteOriginDeclaration(command.remoteOrigin, (declared) => connectionRoles.acceptsOrigin(currentConnectionId(), declared));
1179
+ if ("refusal" in origin)
1180
+ return error(id, "set_client_info", origin.refusal);
1167
1181
  const next = sessionDeclaration(options, command, clientCapabilities, (caps) => connectionRoles.declare(currentConnectionId(), caps), replaceClientCapabilities);
1168
1182
  if (next.refusal)
1169
1183
  return error(id, "set_client_info", next.refusal);
1184
+ if (origin.origin !== undefined)
1185
+ connectionRoles.declareOrigin(currentConnectionId(), origin.origin);
1170
1186
  clientCapabilities = next.capabilities;
1171
1187
  if (command.capabilities !== undefined) {
1172
1188
  secretHandshake = true;
@@ -1689,7 +1705,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1689
1705
  ...(origin === undefined ? {} : { origin }),
1690
1706
  };
1691
1707
  });
1692
- return success(id, "get_auth_providers", { providers });
1708
+ // Read after the rows: building them re-reads a store that failed to load (#4413).
1709
+ const storeError = modelRegistry.authStorage.getLoadError();
1710
+ return success(id, "get_auth_providers", { providers, ...(storeError ? { storeError } : {}) });
1693
1711
  }
1694
1712
  case "login_start": {
1695
1713
  // Respond IMMEDIATELY: success:true means the flow has started. The
@@ -1,5 +1,6 @@
1
1
  import type { ExtensionUIContext, QuestionRequest, QuestionResponse } from "../../core/extensions/types.ts";
2
2
  import type { UiRequestChange } from "./snapshot-types.ts";
3
+ import { type RpcRemoteOrigin } from "./remote-origin.ts";
3
4
  import type { RpcExtensionUIProgress, RpcExtensionUIResponse, RpcQuestionUiRequest } from "./rpc-types.ts";
4
5
  type Options = Parameters<NonNullable<ExtensionUIContext["question"]>>[1];
5
6
  export declare const sessionQuestionBridges: WeakMap<object, ConnectionQuestionBridge>;
@@ -9,7 +10,8 @@ export declare class ConnectionQuestionBridge {
9
10
  private readonly output;
10
11
  private readonly changed;
11
12
  private readonly raiser;
12
- constructor(output: (record: object) => void, changed?: (change?: UiRequestChange) => void, raiser?: () => string | undefined);
13
+ private readonly origin;
14
+ constructor(output: (record: object) => void, changed?: (change?: UiRequestChange) => void, raiser?: () => string | undefined, origin?: () => RpcRemoteOrigin | undefined);
13
15
  pendingQuestions(): RpcQuestionUiRequest[];
14
16
  ask(request: QuestionRequest, opts?: Options): Promise<QuestionResponse>;
15
17
  respond(response: RpcExtensionUIResponse, beforeAnswer?: () => void): boolean | "question_incomplete" | "question_already_resolved";
@@ -1,12 +1,14 @@
1
1
  import { settledQuestionStatus, unansweredQuestionIds } from "./extension-ui-response.js";
2
+ import { remoteOriginField } from "./remote-origin.js";
2
3
  export const sessionQuestionBridges = new WeakMap();
3
4
  export class ConnectionQuestionBridge {
4
- constructor(output, changed, raiser = () => undefined) {
5
+ constructor(output, changed, raiser = () => undefined, origin = () => undefined) {
5
6
  this.pending = new Map();
6
7
  this.resolved = new Set();
7
8
  this.output = output;
8
9
  this.changed = changed;
9
10
  this.raiser = raiser;
11
+ this.origin = origin;
10
12
  }
11
13
  pendingQuestions() {
12
14
  return [...this.pending.values()].map(({ frame }) => ({
@@ -27,6 +29,7 @@ export class ConnectionQuestionBridge {
27
29
  waitForAnswer: request.waitForAnswer,
28
30
  questions: request.questions,
29
31
  raisedBy: this.raiser() ?? "agent",
32
+ ...remoteOriginField(this.origin()),
30
33
  timeout,
31
34
  askedAtMs,
32
35
  deadlineAtMs: askedAtMs + timeout,
@@ -1,3 +1,4 @@
1
+ import { type RpcRemoteOrigin } from "./remote-origin.ts";
1
2
  /**
2
3
  * Connection roles (senpi#3811): the capabilities that say who a connection speaks for, which is what
3
4
  * authority checks read. A role belongs to one connection, never to a session: a shared host serves every
@@ -16,12 +17,19 @@ export declare function roleConnection(connectionId: string | undefined): string
16
17
  export declare const CONNECTION_ROLE_FIXED = "connection_role_fixed: interactive_user and task_parent cannot change after they are declared";
17
18
  export declare class ConnectionRoles {
18
19
  private readonly declared;
20
+ private readonly origins;
19
21
  /** Records the roles a `set_client_info` carries; false when this connection already declared other roles. */
20
22
  declare(connectionId: string, capabilities: readonly string[]): boolean;
21
23
  /** The roles this connection explicitly declared, or undefined while it has declared none (no id = a stdio client). */
22
24
  rolesOf(connectionId: string | undefined): readonly string[] | undefined;
23
25
  /** Takes a declaration made elsewhere (the host, for a worker isolate) unless this connection already declared. */
24
26
  adopt(connectionId: string, roles: readonly string[]): void;
27
+ /** Whether `origin` may be declared for this connection: none yet, or the same one again (senpi#5475). */
28
+ acceptsOrigin(connectionId: string, origin: RpcRemoteOrigin): boolean;
29
+ /** Records the remote device a connection speaks for; call only after `acceptsOrigin` allowed it. */
30
+ declareOrigin(connectionId: string, origin: RpcRemoteOrigin): void;
31
+ /** The remote device this connection declared it speaks for, or undefined for a local connection. */
32
+ originOf(connectionId: string | undefined): RpcRemoteOrigin | undefined;
25
33
  has(connectionId: string | undefined, role: string): boolean;
26
34
  release(connectionId: string): void;
27
35
  /** Forgets every connection, for a worker isolate whose session ends. */
@@ -1,4 +1,5 @@
1
1
  import { INTERACTIVE_USER_CAPABILITY, TASK_PARENT_CAPABILITY } from "./custom-capability.js";
2
+ import { sameRemoteOrigin } from "./remote-origin.js";
2
3
  /**
3
4
  * Connection roles (senpi#3811): the capabilities that say who a connection speaks for, which is what
4
5
  * authority checks read. A role belongs to one connection, never to a session: a shared host serves every
@@ -20,6 +21,7 @@ export const CONNECTION_ROLE_FIXED = "connection_role_fixed: interactive_user an
20
21
  export class ConnectionRoles {
21
22
  constructor() {
22
23
  this.declared = new Map();
24
+ this.origins = new Map();
23
25
  }
24
26
  /** Records the roles a `set_client_info` carries; false when this connection already declared other roles. */
25
27
  declare(connectionId, capabilities) {
@@ -39,15 +41,31 @@ export class ConnectionRoles {
39
41
  if (!this.declared.has(connectionId))
40
42
  this.declared.set(connectionId, [...roles]);
41
43
  }
44
+ /** Whether `origin` may be declared for this connection: none yet, or the same one again (senpi#5475). */
45
+ acceptsOrigin(connectionId, origin) {
46
+ const prior = this.origins.get(connectionId);
47
+ return prior === undefined || sameRemoteOrigin(prior, origin);
48
+ }
49
+ /** Records the remote device a connection speaks for; call only after `acceptsOrigin` allowed it. */
50
+ declareOrigin(connectionId, origin) {
51
+ if (this.acceptsOrigin(connectionId, origin))
52
+ this.origins.set(connectionId, origin);
53
+ }
54
+ /** The remote device this connection declared it speaks for, or undefined for a local connection. */
55
+ originOf(connectionId) {
56
+ return this.origins.get(roleConnection(connectionId));
57
+ }
42
58
  has(connectionId, role) {
43
59
  return this.declared.get(roleConnection(connectionId))?.includes(role) ?? false;
44
60
  }
45
61
  release(connectionId) {
46
62
  this.declared.delete(connectionId);
63
+ this.origins.delete(connectionId);
47
64
  }
48
65
  /** Forgets every connection, for a worker isolate whose session ends. */
49
66
  clear() {
50
67
  this.declared.clear();
68
+ this.origins.clear();
51
69
  }
52
70
  }
53
71
  //# sourceMappingURL=connection-roles.js.map
@@ -817,6 +817,7 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
817
817
  success: true;
818
818
  data: {
819
819
  providers: import("./rpc-session-state-types.ts").RpcAuthProvider[];
820
+ storeError?: import("./rpc-session-state-types.ts").RpcAuthStoreError;
820
821
  };
821
822
  } | {
822
823
  id?: string;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Who may run tool calls on a loopless runtime (senpi#5413). Until the remote tool executor runs the extensions'
3
+ * `tool_call`/`tool_result` handlers (permission checks among them) for a tool-execution-only process, nothing in the
4
+ * product may execute through a loopless runtime: the only allowed caller is the in-process test harness. Closed and
5
+ * fail-closed: a runtime built without a grant this module issued refuses every call.
6
+ */
7
+ declare const LOOPLESS_EXECUTE_CALLERS: readonly ["in-process-test-harness"];
8
+ export type LooplessExecuteCaller = (typeof LOOPLESS_EXECUTE_CALLERS)[number];
9
+ export interface LooplessExecuteGrant {
10
+ readonly caller: LooplessExecuteCaller;
11
+ }
12
+ export declare class LooplessExecuteRefusedError extends Error {
13
+ constructor(reason: string);
14
+ }
15
+ /** Issues the test harness's grant; anywhere but a Vitest run it refuses. */
16
+ export declare function grantLooplessExecuteToTestHarness(): LooplessExecuteGrant;
17
+ /** True only for a grant this module issued to an allowed caller. */
18
+ export declare function isLooplessExecuteGranted(grant: LooplessExecuteGrant | undefined): boolean;
19
+ export {};
20
+ //# sourceMappingURL=loopless-execute-grant.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Who may run tool calls on a loopless runtime (senpi#5413). Until the remote tool executor runs the extensions'
3
+ * `tool_call`/`tool_result` handlers (permission checks among them) for a tool-execution-only process, nothing in the
4
+ * product may execute through a loopless runtime: the only allowed caller is the in-process test harness. Closed and
5
+ * fail-closed: a runtime built without a grant this module issued refuses every call.
6
+ */
7
+ const LOOPLESS_EXECUTE_CALLERS = ["in-process-test-harness"];
8
+ const issued = new WeakSet();
9
+ export class LooplessExecuteRefusedError extends Error {
10
+ constructor(reason) {
11
+ super(`loopless_execute_refused: ${reason}`);
12
+ }
13
+ }
14
+ /** Issues the test harness's grant; anywhere but a Vitest run it refuses. */
15
+ export function grantLooplessExecuteToTestHarness() {
16
+ if (process.env.VITEST !== "true")
17
+ throw new LooplessExecuteRefusedError("only the in-process test harness may execute");
18
+ const grant = Object.freeze({ caller: "in-process-test-harness" });
19
+ issued.add(grant);
20
+ return grant;
21
+ }
22
+ /** True only for a grant this module issued to an allowed caller. */
23
+ export function isLooplessExecuteGranted(grant) {
24
+ return grant !== undefined && issued.has(grant) && LOOPLESS_EXECUTE_CALLERS.includes(grant.caller);
25
+ }
26
+ //# sourceMappingURL=loopless-execute-grant.js.map
@@ -0,0 +1,30 @@
1
+ import type { AgentSessionRuntimeDiagnostic } from "../../core/agent-session-services.ts";
2
+ import type { ResourceLoaderReloadOptions } from "../../core/resource-loader.ts";
3
+ import { SettingsManager } from "../../core/settings-manager.ts";
4
+ import type { Args } from "../../cli/args.ts";
5
+ import type { CliRuntimeConfiguration } from "../../main.ts";
6
+ import type { LooplessRuntimeProfile } from "./runtime-factory-loopless.ts";
7
+ export interface LooplessRuntimeSettings {
8
+ readonly settingsManager: SettingsManager;
9
+ readonly flagValues: Map<string, boolean | string>;
10
+ readonly reloadOptions: ResourceLoaderReloadOptions | undefined;
11
+ }
12
+ /**
13
+ * The project trust a session opened from this configuration would get, decided without a UI: a runtime without a
14
+ * loop has no one to ask, exactly like an RPC worker today (`createCliRuntimeFactory`, main.ts). A `project_trust`
15
+ * handler's error is reported to `diagnostics`, as the CLI factory reports it.
16
+ */
17
+ export declare function resolveLooplessSettings(configuration: CliRuntimeConfiguration, startupSettingsManager: SettingsManager, profile: LooplessRuntimeProfile, diagnostics: AgentSessionRuntimeDiagnostic[]): Promise<LooplessRuntimeSettings>;
18
+ export declare function resolveCliPaths(cwd: string, paths: string[] | undefined): string[] | undefined;
19
+ export interface LooplessToolFilters {
20
+ readonly defaultToolNames?: ReadonlySet<string>;
21
+ readonly allowedToolNames?: ReadonlySet<string>;
22
+ readonly excludedToolNames?: ReadonlySet<string>;
23
+ }
24
+ /**
25
+ * The CLI's tool filters (`--tools`, `--no-tools`, `--no-builtin-tools`, `--exclude-tools`, settings `defaultTools`),
26
+ * mapped as `main.ts` maps them and resolved as `createAgentSession` resolves them (sdk.ts), so a loopless runtime
27
+ * registers exactly the tools a session registers for the same flags and settings.
28
+ */
29
+ export declare function looplessToolFilters(parsed: Args, settingsManager: SettingsManager): LooplessToolFilters;
30
+ //# sourceMappingURL=loopless-runtime-settings.d.ts.map
@@ -0,0 +1,69 @@
1
+ import { presetTrustsProject, resolveProjectTrusted } from "../../core/project-trust.js";
2
+ import { sessionExtensionFlagValues } from "../../core/session-extension-flags.js";
3
+ import { SettingsManager } from "../../core/settings-manager.js";
4
+ import { getSavedProjectTrust, hasTrustRequiringProjectResources, ProjectTrustStore, } from "../../core/trust-manager.js";
5
+ import { createProjectTrustContext } from "../../cli/project-trust.js";
6
+ import { isLocalPath, resolvePath } from "../../utils/paths.js";
7
+ /**
8
+ * The project trust a session opened from this configuration would get, decided without a UI: a runtime without a
9
+ * loop has no one to ask, exactly like an RPC worker today (`createCliRuntimeFactory`, main.ts). A `project_trust`
10
+ * handler's error is reported to `diagnostics`, as the CLI factory reports it.
11
+ */
12
+ export async function resolveLooplessSettings(configuration, startupSettingsManager, profile, diagnostics) {
13
+ const { parsed, agentDir, appMode } = configuration;
14
+ const { cwd, launchProfile } = profile;
15
+ const trustStore = new ProjectTrustStore(agentDir);
16
+ const flagValues = sessionExtensionFlagValues(parsed.unknownFlags, launchProfile);
17
+ const hasTrustRequiringResources = hasTrustRequiringProjectResources(cwd);
18
+ const savedProjectTrust = await getSavedProjectTrust(trustStore, cwd);
19
+ const globalPreset = startupSettingsManager.getGlobalSettings()
20
+ .permissionPreset;
21
+ const fullAccessTrust = presetTrustsProject(flagValues.get("permission-preset"), globalPreset) && savedProjectTrust !== false;
22
+ const shouldResolveProjectTrust = parsed.projectTrustOverride === undefined && !fullAccessTrust && hasTrustRequiringResources;
23
+ const projectTrusted = shouldResolveProjectTrust
24
+ ? false
25
+ : (parsed.projectTrustOverride ?? (fullAccessTrust || !hasTrustRequiringResources || savedProjectTrust === true));
26
+ const trustFromFullAccess = fullAccessTrust &&
27
+ hasTrustRequiringResources &&
28
+ parsed.projectTrustOverride === undefined &&
29
+ savedProjectTrust !== true;
30
+ const settingsManager = SettingsManager.create(cwd, agentDir, { projectTrusted, trustFromFullAccess });
31
+ const reloadOptions = shouldResolveProjectTrust
32
+ ? {
33
+ resolveProjectTrust: ({ extensionsResult }) => resolveProjectTrusted({
34
+ cwd,
35
+ trustStore,
36
+ trustOverride: parsed.projectTrustOverride,
37
+ defaultProjectTrust: startupSettingsManager.getDefaultProjectTrust(),
38
+ extensionsResult,
39
+ projectTrustContext: createProjectTrustContext({
40
+ cwd,
41
+ mode: appMode,
42
+ settingsManager: startupSettingsManager,
43
+ hasUI: false,
44
+ }),
45
+ onExtensionError: (message) => diagnostics.push({ type: "warning", message }),
46
+ }),
47
+ }
48
+ : undefined;
49
+ return { settingsManager, flagValues, reloadOptions };
50
+ }
51
+ export function resolveCliPaths(cwd, paths) {
52
+ return paths?.map((value) => (isLocalPath(value) ? resolvePath(value, cwd) : value));
53
+ }
54
+ /**
55
+ * The CLI's tool filters (`--tools`, `--no-tools`, `--no-builtin-tools`, `--exclude-tools`, settings `defaultTools`),
56
+ * mapped as `main.ts` maps them and resolved as `createAgentSession` resolves them (sdk.ts), so a loopless runtime
57
+ * registers exactly the tools a session registers for the same flags and settings.
58
+ */
59
+ export function looplessToolFilters(parsed, settingsManager) {
60
+ const noTools = parsed.noTools ? "all" : parsed.noBuiltinTools ? "builtin" : undefined;
61
+ const defaultToolNames = parsed.tools === undefined && noTools === undefined ? settingsManager.getDefaultTools() : undefined;
62
+ const allowedToolNames = parsed.tools ?? (noTools === "all" ? [] : undefined);
63
+ return {
64
+ ...(defaultToolNames === undefined ? {} : { defaultToolNames: new Set(defaultToolNames) }),
65
+ ...(allowedToolNames === undefined ? {} : { allowedToolNames: new Set(allowedToolNames) }),
66
+ ...(parsed.excludeTools === undefined ? {} : { excludedToolNames: new Set(parsed.excludeTools) }),
67
+ };
68
+ }
69
+ //# sourceMappingURL=loopless-runtime-settings.js.map
@@ -0,0 +1,12 @@
1
+ import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ /**
3
+ * Runs one tool call the way the agent loop runs a model-issued one up to its hooks (`runToolCall`, agent-loop.ts):
4
+ * argument preparation and schema validation, then the tool. Invalid arguments and a failing tool come back as an
5
+ * `isError` result, never a rejection (senpi#5413).
6
+ */
7
+ export declare function runLooplessToolCall(tool: AgentTool, call: {
8
+ readonly toolCallId: string;
9
+ readonly params: unknown;
10
+ readonly signal?: AbortSignal;
11
+ }): Promise<AgentToolResult<unknown>>;
12
+ //# sourceMappingURL=loopless-tool-call.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { validateToolArguments } from "@earendil-works/pi-ai";
2
+ function errorResult(message) {
3
+ return { content: [{ type: "text", text: message }], details: undefined, isError: true };
4
+ }
5
+ /**
6
+ * Runs one tool call the way the agent loop runs a model-issued one up to its hooks (`runToolCall`, agent-loop.ts):
7
+ * argument preparation and schema validation, then the tool. Invalid arguments and a failing tool come back as an
8
+ * `isError` result, never a rejection (senpi#5413).
9
+ */
10
+ export async function runLooplessToolCall(tool, call) {
11
+ const { toolCallId, signal } = call;
12
+ try {
13
+ const prepared = tool.prepareArguments ? tool.prepareArguments(call.params) : call.params;
14
+ const toolCall = { type: "toolCall", id: toolCallId, name: tool.name, arguments: prepared };
15
+ const args = validateToolArguments(tool, toolCall);
16
+ return await tool.execute(toolCallId, args, signal, undefined);
17
+ }
18
+ catch (error) {
19
+ return errorResult(error instanceof Error ? error.message : String(error));
20
+ }
21
+ }
22
+ //# sourceMappingURL=loopless-tool-call.js.map