@code-yeongyu/senpi 2026.11.10 → 2026.11.11

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 (320) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/dist/bundle/{SKILL-B4R7BVOT.md → SKILL-R7FEIQKG.md} +1 -1
  3. package/dist/bundle/chunks/{SKILL-AZ6ONO52.js → SKILL-5O2UKORG.js} +1 -1
  4. package/dist/bundle/chunks/{SKILL-B4R7BVOT.md → SKILL-R7FEIQKG.md} +1 -1
  5. package/dist/bundle/chunks/{args-77GYOPEO.js → args-HFYB6URH.js} +1 -1
  6. package/dist/bundle/chunks/{azure-openai-responses-YFZ734T3.js → azure-openai-responses-MNN2TINI.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-ZUQCYIRY.js → chunk-2ODGHBUD.js} +1 -1
  8. package/dist/bundle/chunks/chunk-3IYEGHBI.js +2 -0
  9. package/dist/bundle/chunks/{chunk-I5ASHSLZ.js → chunk-4JMGWVRH.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-YKYWL2NO.js → chunk-5F2XC6UC.js} +3 -3
  11. package/dist/bundle/chunks/{chunk-MSDBBOB2.js → chunk-5H43O4MA.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-R3OP7IA4.js → chunk-5PIZWSNG.js} +4 -4
  13. package/dist/bundle/chunks/{chunk-33MZJTQ3.js → chunk-B4WD5XHP.js} +1 -1
  14. package/dist/bundle/chunks/{chunk-Q63YLZMN.js → chunk-BPEA5SWW.js} +2 -2
  15. package/dist/bundle/chunks/{chunk-MOVJQVMC.js → chunk-BUDJLVMF.js} +3 -3
  16. package/dist/bundle/chunks/{chunk-V5FSENW6.js → chunk-COKX65TE.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-2EJ4BGBM.js → chunk-DHORIIVQ.js} +1 -1
  18. package/dist/bundle/chunks/{chunk-NH7SYIGN.js → chunk-DLPV4B3R.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-RCHIMH7N.js → chunk-DQY26AX3.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-Y7Z7XPUF.js → chunk-DZQA5LVN.js} +1 -1
  21. package/dist/bundle/chunks/{chunk-2CNSCMYC.js → chunk-E5O4SP5I.js} +1 -1
  22. package/dist/bundle/chunks/{chunk-3Q5ZENSD.js → chunk-E6ZBTSC6.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-GVPZPVVO.js → chunk-IBDAV2AL.js} +3 -3
  24. package/dist/bundle/chunks/chunk-IREUIMFE.js +11 -0
  25. package/dist/bundle/chunks/{chunk-KU7OCWJF.js → chunk-J4ADZ2OK.js} +1 -1
  26. package/dist/bundle/chunks/{chunk-T2SMQPRE.js → chunk-K3GAGIPX.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-BELNOPAI.js → chunk-L3KVP7VJ.js} +3 -3
  28. package/dist/bundle/chunks/{chunk-IYSJFQUU.js → chunk-L6DF5G6K.js} +1 -1
  29. package/dist/bundle/chunks/{chunk-7MN7YNO5.js → chunk-L7DGTA3L.js} +1 -1
  30. package/dist/bundle/chunks/chunk-LJFQYCFH.js +2 -0
  31. package/dist/bundle/chunks/{chunk-J2NGJKXL.js → chunk-LXINMDMX.js} +1 -1
  32. package/dist/bundle/chunks/{chunk-H33A33M4.js → chunk-M2VJVJMK.js} +1 -1
  33. package/dist/bundle/chunks/{chunk-2U6HXWXS.js → chunk-NNQ34ZDW.js} +1 -1
  34. package/dist/bundle/chunks/chunk-NQKCJQHB.js +2 -0
  35. package/dist/bundle/chunks/{chunk-EJB5E2JK.js → chunk-NRZAJUUO.js} +2 -2
  36. package/dist/bundle/chunks/{chunk-R2Z7CX77.js → chunk-OSNR3IRD.js} +1 -1
  37. package/dist/bundle/chunks/{chunk-O3FG6HML.js → chunk-PJI5GT7U.js} +1 -1
  38. package/dist/bundle/chunks/{chunk-FDNM2DAE.js → chunk-PUZDKFRT.js} +164 -164
  39. package/dist/bundle/chunks/{chunk-BPNSOZ2C.js → chunk-QUVSIW2R.js} +1 -1
  40. package/dist/bundle/chunks/{chunk-WXYMAUFX.js → chunk-QX7WD3IM.js} +1 -1
  41. package/dist/bundle/chunks/{chunk-Y4ONXQMR.js → chunk-RGHVPUUX.js} +1 -1
  42. package/dist/bundle/chunks/{chunk-RYPM5BZQ.js → chunk-S7NAJQB3.js} +1 -1
  43. package/dist/bundle/chunks/{chunk-2BH54YQR.js → chunk-SANWO37B.js} +1 -1
  44. package/dist/bundle/chunks/{chunk-YQZNARTX.js → chunk-SS5VTBAV.js} +1 -1
  45. package/dist/bundle/chunks/{chunk-LT353NSF.js → chunk-T4CUD7RF.js} +1 -1
  46. package/dist/bundle/chunks/{chunk-J7FW7MED.js → chunk-TCZORL3V.js} +1 -1
  47. package/dist/bundle/chunks/{chunk-KU72IKV5.js → chunk-VGSWOLIY.js} +1 -1
  48. package/dist/bundle/chunks/{chunk-DBQBJTMF.js → chunk-VUY4BZDI.js} +1 -1
  49. package/dist/bundle/chunks/chunk-XI6THO4F.js +2 -0
  50. package/dist/bundle/chunks/{chunk-FAFIGBUD.js → chunk-XUDKT4UH.js} +3 -3
  51. package/dist/bundle/chunks/{cli-main-BX5AFWJQ.js → cli-main-7II7GCIR.js} +1 -1
  52. package/dist/bundle/chunks/{credential-accounts-LVVPKFEY.js → credential-accounts-N3B5YJS7.js} +1 -1
  53. package/dist/bundle/chunks/{dispatch-EP35KKJ3.js → dispatch-YUYZQXRP.js} +1 -1
  54. package/dist/bundle/chunks/github-copilot.js +1 -1
  55. package/dist/bundle/chunks/{hand-entry-F6PWKNPJ.js → hand-entry-ONOLRMVB.js} +3 -3
  56. package/dist/bundle/chunks/{headless-host-HKGNJGYT.js → headless-host-53UMJMM6.js} +1 -1
  57. package/dist/bundle/chunks/{health-write-FBF74QJ7.js → health-write-JLSF5EVV.js} +1 -1
  58. package/dist/bundle/chunks/{help-fast-path-5SCPY3OH.js → help-fast-path-552QLMWT.js} +1 -1
  59. package/dist/bundle/chunks/{host-command-47QQKJEY.js → host-command-KWMJLPBS.js} +1 -1
  60. package/dist/bundle/chunks/{host-lifecycle-VSAH4M3R.js → host-lifecycle-4WQDCN3Y.js} +1 -1
  61. package/dist/bundle/chunks/host-lifecycle.js +5 -5
  62. package/dist/bundle/chunks/{host-session-command-SL4AN5WD.js → host-session-command-ZDYEKCUB.js} +1 -1
  63. package/dist/bundle/chunks/{host-socket-request-DMYXC56U.js → host-socket-request-QN4Q2P5E.js} +1 -1
  64. package/dist/bundle/chunks/{interactive-mode-JDMIHJMQ.js → interactive-mode-EPE4M32G.js} +1 -1
  65. package/dist/bundle/chunks/{login-health-EVXVLHB2.js → login-health-TOSQT5RG.js} +1 -1
  66. package/dist/bundle/chunks/{main-4RITUAQF.js → main-OM7BKVZG.js} +1 -1
  67. package/dist/bundle/chunks/{multi-session-host-SKDD4OWM.js → multi-session-host-DB6XMY53.js} +11 -8
  68. package/dist/bundle/chunks/openai-codex-responses-VRGOAFEG.js +10 -0
  69. package/dist/bundle/chunks/{openai-responses-NIVBWE2H.js → openai-responses-I7PXRWCM.js} +2 -2
  70. package/dist/bundle/chunks/{package-manager-cli-B5VA4KFO.js → package-manager-cli-GLU5Q2KV.js} +1 -1
  71. package/dist/bundle/chunks/{role-HQUN4XXK.js → role-AEOLJRTP.js} +1 -1
  72. package/dist/bundle/chunks/{rotation-stream-F3BEMXBE.js → rotation-stream-E3FJFHXJ.js} +1 -1
  73. package/dist/bundle/chunks/rpc-mode-SDJVBT36.js +2 -0
  74. package/dist/bundle/chunks/{rpc-monitor-source-C6VQ3BC4.js → rpc-monitor-source-PGTDSGWP.js} +1 -1
  75. package/dist/bundle/chunks/{run-attached-tui-R3RB5P7G.js → run-attached-tui-4AENRP7P.js} +1 -1
  76. package/dist/bundle/chunks/{schedule-command-FPEQCX33.js → schedule-command-5SQD7M5N.js} +1 -1
  77. package/dist/bundle/chunks/session-control-endpoint-R25A2QGS.js +3 -0
  78. package/dist/bundle/chunks/{session-picker-2FZSNFS7.js → session-picker-GZM5CVQL.js} +1 -1
  79. package/dist/bundle/chunks/{session-slot-CZGQQCOC.js → session-slot-RH7JLO3F.js} +1 -1
  80. package/dist/bundle/chunks/session-worker.js +335 -332
  81. package/dist/bundle/chunks/{state-store-S7QAESIF.js → state-store-IECVTYXC.js} +1 -1
  82. package/dist/bundle/cli.js +2 -2
  83. package/dist/bundle/host-supervisor.js +5 -5
  84. package/dist/bundle/index.js +1 -1
  85. package/dist/bundle/rpc-entry.js +1 -1
  86. package/dist/bundle/runtime-manifest.json +1 -1
  87. package/dist/cli.js +9 -3
  88. package/dist/core/agent-session-runtime.d.ts +2 -0
  89. package/dist/core/agent-session-runtime.js +5 -0
  90. package/dist/core/agent-session.d.ts +15 -3
  91. package/dist/core/agent-session.js +91 -18
  92. package/dist/core/assistant-error-redaction.d.ts +9 -0
  93. package/dist/core/assistant-error-redaction.js +27 -0
  94. package/dist/core/config-reference-redaction.js +90 -10
  95. package/dist/core/context-files.d.ts +10 -0
  96. package/dist/core/context-files.js +58 -12
  97. package/dist/core/credential-accounts.d.ts +2 -0
  98. package/dist/core/credential-accounts.js +10 -1
  99. package/dist/core/dynamic-prompt/intent-gate.js +2 -2
  100. package/dist/core/dynamic-prompt/style.js +2 -2
  101. package/dist/core/dynamic-prompt/verification.js +2 -2
  102. package/dist/core/egress/wire.d.ts +13 -0
  103. package/dist/core/extensions/builtin/anthropic-subscription/accounts.d.ts +3 -0
  104. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +3 -2
  105. package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-account-test.js +3 -1
  106. package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-connection-test.d.ts +3 -1
  107. package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-connection-test.js +47 -16
  108. package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-login-slots.d.ts +1 -1
  109. package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-login-slots.js +4 -2
  110. package/dist/core/extensions/builtin/anthropic-subscription/claude-settings-env.d.ts +20 -0
  111. package/dist/core/extensions/builtin/anthropic-subscription/claude-settings-env.js +39 -0
  112. package/dist/core/extensions/builtin/anthropic-subscription/context-window.d.ts +17 -0
  113. package/dist/core/extensions/builtin/anthropic-subscription/context-window.js +23 -0
  114. package/dist/core/extensions/builtin/anthropic-subscription/errors.d.ts +1 -0
  115. package/dist/core/extensions/builtin/anthropic-subscription/errors.js +14 -5
  116. package/dist/core/extensions/builtin/anthropic-subscription/oauth-login.js +3 -3
  117. package/dist/core/extensions/builtin/anthropic-subscription/prompt-cache-ttl.d.ts +10 -4
  118. package/dist/core/extensions/builtin/anthropic-subscription/prompt-cache-ttl.js +14 -5
  119. package/dist/core/extensions/builtin/anthropic-subscription/query-environment.d.ts +3 -2
  120. package/dist/core/extensions/builtin/anthropic-subscription/query-environment.js +5 -4
  121. package/dist/core/extensions/builtin/anthropic-subscription/sdk-boundary.lazy.d.ts +2 -1
  122. package/dist/core/extensions/builtin/anthropic-subscription/sdk-boundary.lazy.js +1 -0
  123. package/dist/core/extensions/builtin/anthropic-subscription/stream.js +11 -1
  124. package/dist/core/extensions/builtin/config-reload/change-groups.js +6 -2
  125. package/dist/core/extensions/builtin/goal/continuation.d.ts +6 -0
  126. package/dist/core/extensions/builtin/goal/continuation.js +3 -2
  127. package/dist/core/extensions/builtin/goal/index.js +14 -26
  128. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +8 -6
  129. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +77 -39
  130. package/dist/core/extensions/builtin/goal/monitor-continuation.js +66 -7
  131. package/dist/core/extensions/builtin/goal/persistence.js +20 -0
  132. package/dist/core/extensions/builtin/goal/provider-retry.d.ts +9 -0
  133. package/dist/core/extensions/builtin/goal/provider-retry.js +16 -0
  134. package/dist/core/extensions/builtin/goal/reload-reengagement.d.ts +3 -2
  135. package/dist/core/extensions/builtin/goal/reload-reengagement.js +4 -4
  136. package/dist/core/extensions/builtin/goal/session-start-continuation.d.ts +28 -0
  137. package/dist/core/extensions/builtin/goal/session-start-continuation.js +75 -0
  138. package/dist/core/extensions/builtin/goal/store.d.ts +3 -2
  139. package/dist/core/extensions/builtin/goal/store.js +9 -2
  140. package/dist/core/extensions/builtin/goal/types.d.ts +9 -0
  141. package/dist/core/extensions/builtin/handoff-hint/index.js +15 -11
  142. package/dist/core/extensions/builtin/handoff-hint/replacement-relay.d.ts +16 -0
  143. package/dist/core/extensions/builtin/handoff-hint/replacement-relay.js +17 -0
  144. package/dist/core/extensions/builtin/html-render/tool.js +13 -3
  145. package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +1 -1
  146. package/dist/core/extensions/builtin/imagegen/tool.js +4 -14
  147. package/dist/core/extensions/builtin/mcp/auth/catalog-identity.js +32 -8
  148. package/dist/core/extensions/builtin/mcp/auth/commands-auth.js +2 -1
  149. package/dist/core/extensions/builtin/mcp/auth/context.js +3 -0
  150. package/dist/core/extensions/builtin/mcp/auth/oauth-grant.d.ts +43 -0
  151. package/dist/core/extensions/builtin/mcp/auth/oauth-grant.js +196 -0
  152. package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +7 -1
  153. package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +13 -0
  154. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +6 -17
  155. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +67 -88
  156. package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.d.ts +1 -1
  157. package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +25 -4
  158. package/dist/core/extensions/builtin/mcp/auth/oauth.js +10 -7
  159. package/dist/core/extensions/builtin/mcp/auth/registered-redirect.d.ts +19 -0
  160. package/dist/core/extensions/builtin/mcp/auth/registered-redirect.js +55 -0
  161. package/dist/core/extensions/builtin/mcp/auth/token-store.d.ts +23 -1
  162. package/dist/core/extensions/builtin/mcp/auth/token-store.js +3 -0
  163. package/dist/core/extensions/builtin/mcp/catalog-cache.js +7 -6
  164. package/dist/core/extensions/builtin/mcp/catalog.js +3 -2
  165. package/dist/core/extensions/builtin/mcp/invocation.js +6 -0
  166. package/dist/core/extensions/builtin/mcp/service-register.js +16 -2
  167. package/dist/core/extensions/builtin/mcp/service-tools-changed.js +61 -54
  168. package/dist/core/extensions/builtin/mcp/startup-race.d.ts +2 -0
  169. package/dist/core/extensions/builtin/mcp/startup-race.js +25 -7
  170. package/dist/core/extensions/builtin/permission-system/parsers.js +1 -0
  171. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +3 -3
  172. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-2.js +9 -8
  173. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +3 -3
  174. package/dist/core/extensions/builtin/prompt-preset/claude-haiku-5-5.js +3 -3
  175. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.js +3 -3
  176. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +4 -4
  177. package/dist/core/extensions/builtin/prompt-preset/claude-sonnet-5-5.js +3 -3
  178. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js +3 -3
  179. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +3 -3
  180. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -2
  181. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +3 -3
  182. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +1 -1
  183. package/dist/core/extensions/builtin/prompt-preset/grok-4.6.js +4 -4
  184. package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js +5 -5
  185. package/dist/core/extensions/builtin/prompt-preset/kimi-k3-1.js +4 -4
  186. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +7 -6
  187. package/dist/core/extensions/loader.js +24 -4
  188. package/dist/core/extensions/runner.d.ts +9 -1
  189. package/dist/core/extensions/runner.js +9 -4
  190. package/dist/core/extensions/types.d.ts +19 -3
  191. package/dist/core/hand/hook-advertise.d.ts +41 -0
  192. package/dist/core/hand/hook-advertise.js +98 -0
  193. package/dist/core/hand/hook-contract.d.ts +66 -0
  194. package/dist/core/hand/hook-contract.js +138 -0
  195. package/dist/core/open-timing.d.ts +2 -0
  196. package/dist/core/open-timing.js +7 -1
  197. package/dist/core/resource-loader.js +21 -3
  198. package/dist/core/retry-fallback/controller-types.d.ts +2 -0
  199. package/dist/core/retry-fallback/controller.js +9 -2
  200. package/dist/core/retry-fallback/cooldown.d.ts +7 -0
  201. package/dist/core/retry-fallback/cooldown.js +13 -1
  202. package/dist/core/retry-fallback/credential-recovery.d.ts +7 -0
  203. package/dist/core/retry-fallback/credential-recovery.js +24 -0
  204. package/dist/core/retry-fallback/log.d.ts +7 -1
  205. package/dist/core/retry-fallback/log.js +82 -5
  206. package/dist/core/retry-fallback/model-config-error.js +2 -1
  207. package/dist/core/retry-fallback/settings.d.ts +8 -5
  208. package/dist/core/retry-fallback/settings.js +9 -6
  209. package/dist/core/session-manager.d.ts +2 -0
  210. package/dist/core/session-manager.js +15 -1
  211. package/dist/core/settings-manager.d.ts +6 -0
  212. package/dist/core/settings-manager.js +8 -0
  213. package/dist/core/turn-origin.d.ts +18 -10
  214. package/dist/core/turn-origin.js +34 -30
  215. package/dist/core/ultrafast-lanes.d.ts +1 -0
  216. package/dist/core/ultrafast-lanes.js +4 -2
  217. package/dist/modes/interactive/components/footer.d.ts +23 -5
  218. package/dist/modes/interactive/components/footer.js +45 -16
  219. package/dist/modes/interactive/interactive-mode.js +9 -1
  220. package/dist/modes/interactive/session-control-rpc-commands.d.ts +1 -1
  221. package/dist/modes/interactive/session-control-rpc-commands.js +5 -0
  222. package/dist/modes/rpc/admit-external-message-command.d.ts +2 -0
  223. package/dist/modes/rpc/admit-external-message-command.js +5 -1
  224. package/dist/modes/rpc/compact-admission-validation.js +4 -1
  225. package/dist/modes/rpc/connection-authority.d.ts +2 -1
  226. package/dist/modes/rpc/connection-authority.js +11 -9
  227. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  228. package/dist/modes/rpc/connection-handler.js +33 -7
  229. package/dist/modes/rpc/connection-roles.d.ts +7 -0
  230. package/dist/modes/rpc/connection-roles.js +15 -0
  231. package/dist/modes/rpc/custom-capability.d.ts +6 -0
  232. package/dist/modes/rpc/custom-capability.js +6 -0
  233. package/dist/modes/rpc/delegated-drive-origin.d.ts +6 -6
  234. package/dist/modes/rpc/delegated-drive-origin.js +7 -8
  235. package/dist/modes/rpc/delegation-declaration.d.ts +2 -0
  236. package/dist/modes/rpc/delegation-declaration.js +7 -3
  237. package/dist/modes/rpc/effect-commands.d.ts +33 -0
  238. package/dist/modes/rpc/host-capabilities.d.ts +1 -0
  239. package/dist/modes/rpc/host-capabilities.js +7 -1
  240. package/dist/modes/rpc/host-gc-evidence.d.ts +1 -1
  241. package/dist/modes/rpc/host-gc-evidence.js +9 -3
  242. package/dist/modes/rpc/host-gc.js +4 -1
  243. package/dist/modes/rpc/host-observe-request.d.ts +2 -0
  244. package/dist/modes/rpc/host-observe-request.js +6 -1
  245. package/dist/modes/rpc/host-park-ledger.d.ts +19 -0
  246. package/dist/modes/rpc/host-park-ledger.js +110 -0
  247. package/dist/modes/rpc/lifecycle-delivery.js +4 -1
  248. package/dist/modes/rpc/loopless-tool-handlers.d.ts +6 -0
  249. package/dist/modes/rpc/loopless-tool-handlers.js +14 -1
  250. package/dist/modes/rpc/media-placeholders.js +1 -0
  251. package/dist/modes/rpc/method-classes-schema-host.d.ts +42 -1
  252. package/dist/modes/rpc/method-classes-schema-host.js +24 -21
  253. package/dist/modes/rpc/method-classes-schema-session.d.ts +20 -0
  254. package/dist/modes/rpc/method-classes-schema-session.js +6 -0
  255. package/dist/modes/rpc/method-classes-schema.d.ts +62 -1
  256. package/dist/modes/rpc/method-classes-schema.js +5 -2
  257. package/dist/modes/rpc/method-classes.d.ts +4 -0
  258. package/dist/modes/rpc/method-classes.js +6 -0
  259. package/dist/modes/rpc/multi-session-host.js +1 -1
  260. package/dist/modes/rpc/project-file-commands.d.ts +32 -0
  261. package/dist/modes/rpc/project-file-commands.js +195 -0
  262. package/dist/modes/rpc/project-file-path.d.ts +34 -0
  263. package/dist/modes/rpc/project-file-path.js +93 -0
  264. package/dist/modes/rpc/rpc-error-types.d.ts +9 -1
  265. package/dist/modes/rpc/rpc-error-types.js +8 -0
  266. package/dist/modes/rpc/rpc-host-command-types.d.ts +14 -1
  267. package/dist/modes/rpc/rpc-host-response-types.d.ts +21 -0
  268. package/dist/modes/rpc/rpc-mutation-response-types.d.ts +7 -0
  269. package/dist/modes/rpc/rpc-read-response-types.d.ts +7 -0
  270. package/dist/modes/rpc/rpc-session-command-types.d.ts +10 -0
  271. package/dist/modes/rpc/rpc-session-state-types.d.ts +2 -0
  272. package/dist/modes/rpc/session-attachment-gate.js +6 -0
  273. package/dist/modes/rpc/session-binding.d.ts +1 -0
  274. package/dist/modes/rpc/session-binding.js +6 -1
  275. package/dist/modes/rpc/session-command-activity.js +1 -0
  276. package/dist/modes/rpc/session-connection-context.d.ts +2 -0
  277. package/dist/modes/rpc/session-connection-context.js +4 -0
  278. package/dist/modes/rpc/session-registry-attach.d.ts +2 -0
  279. package/dist/modes/rpc/session-registry-attach.js +15 -11
  280. package/dist/modes/rpc/session-registry-claims.js +2 -0
  281. package/dist/modes/rpc/session-registry-open.js +13 -7
  282. package/dist/modes/rpc/session-registry-opening.js +2 -1
  283. package/dist/modes/rpc/session-registry-types.d.ts +4 -0
  284. package/dist/modes/rpc/session-registry.d.ts +3 -0
  285. package/dist/modes/rpc/session-registry.js +27 -3
  286. package/dist/modes/rpc/session-router-close.js +1 -0
  287. package/dist/modes/rpc/session-router-context.d.ts +4 -2
  288. package/dist/modes/rpc/session-router-context.js +3 -0
  289. package/dist/modes/rpc/session-router-host-reads.js +1 -0
  290. package/dist/modes/rpc/session-router-occupancy.js +10 -1
  291. package/dist/modes/rpc/session-router-open-result.d.ts +12 -0
  292. package/dist/modes/rpc/session-router-open-result.js +63 -0
  293. package/dist/modes/rpc/session-router-open.d.ts +3 -0
  294. package/dist/modes/rpc/session-router-open.js +15 -63
  295. package/dist/modes/rpc/session-router-park.d.ts +15 -0
  296. package/dist/modes/rpc/session-router-park.js +176 -0
  297. package/dist/modes/rpc/session-router-routing.d.ts +1 -1
  298. package/dist/modes/rpc/session-router-routing.js +7 -0
  299. package/dist/modes/rpc/session-status-source.js +2 -2
  300. package/dist/private-fd-startup-fillers.d.ts +2 -2
  301. package/dist/private-fd-startup-fillers.js +34 -4
  302. package/dist/senpi +9 -3
  303. package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
  304. package/docs/engine-socket/fixtures/rpc-inbound-samples.json +44 -2
  305. package/docs/extensions.md +11 -1
  306. package/docs/rpc.md +106 -2
  307. package/docs/settings.md +5 -3
  308. package/docs/skills.md +1 -1
  309. package/docs/usage.md +1 -1
  310. package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
  311. package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
  312. package/package.json +6 -6
  313. package/dist/bundle/chunks/chunk-436DNN4Z.js +0 -2
  314. package/dist/bundle/chunks/chunk-DLAY7CIU.js +0 -2
  315. package/dist/bundle/chunks/chunk-SJI6UB23.js +0 -2
  316. package/dist/bundle/chunks/chunk-XH2MWTXA.js +0 -11
  317. package/dist/bundle/chunks/chunk-YK3ZZCHI.js +0 -2
  318. package/dist/bundle/chunks/openai-codex-responses-ABB2J43U.js +0 -10
  319. package/dist/bundle/chunks/rpc-mode-ZDUGW2IM.js +0 -2
  320. package/dist/bundle/chunks/session-control-endpoint-MEDV66PS.js +0 -3
@@ -26,6 +26,8 @@ import { failure, success } from "./session-control-server.js";
26
26
  import { TERMINAL_PRESENTER_COMMANDS } from "./terminal-presenter-surface.js";
27
27
  export const TUI_RPC_COMMANDS = [
28
28
  "open_session",
29
+ "park_session",
30
+ "claim_session",
29
31
  "get_snapshot",
30
32
  "subscribe_sessions",
31
33
  "unsubscribe_sessions",
@@ -64,6 +66,9 @@ export async function runTuiRpcCommand(context, connection, command) {
64
66
  }
65
67
  case "open_session":
66
68
  return openSession(context, connection, command);
69
+ case "park_session":
70
+ case "claim_session":
71
+ return failure(idOf(command), command.type, "multi_session_disabled");
67
72
  case "subscribe_sessions":
68
73
  return subscribe(context, connection, frame(command));
69
74
  case "unsubscribe_sessions":
@@ -20,6 +20,8 @@ export interface DeliveryPeer {
20
20
  /** The remote device the connection speaks for (`ConnectionRoles.originOf`); absent on a plain local connection. */
21
21
  readonly origin: RpcRemoteOrigin | undefined;
22
22
  readonly connectionOrigin: ConnectionOrigin;
23
+ /** The origin the turn this delivery opens counts as (senpi#6342); the connection's origin when absent. */
24
+ readonly turnOrigin?: ConnectionOrigin;
23
25
  }
24
26
  export type AdmitExternalMessageAnswer = {
25
27
  readonly ok: true;
@@ -9,6 +9,10 @@ function ledgerId(deliveryId, origin) {
9
9
  ? `rpc:local/${deliveryId}`
10
10
  : `device:${encodeURIComponent(origin.deviceId)}/${deliveryId}`;
11
11
  }
12
+ /** The turn a delivery opens: a steer joins the running turn; anything else counts as the connection's turn origin. */
13
+ function deliveryTurnMark(command, peer) {
14
+ return command.deliverAs === "steer" ? "join" : (peer.turnOrigin ?? peer.connectionOrigin);
15
+ }
12
16
  export function admitExternalMessage(session, command, peer) {
13
17
  const chain = admitInputChain(command.chainCount, session.settingsManager);
14
18
  if (chain.kind === "refused")
@@ -54,7 +58,7 @@ export function admitExternalMessage(session, command, peer) {
54
58
  }, {
55
59
  ...(origin === undefined ? {} : { remoteOrigin: origin }),
56
60
  ...(chain.chainCount === undefined ? {} : { chainCount: chain.chainCount }),
57
- turnMark: command.deliverAs === "steer" ? "join" : peer.connectionOrigin,
61
+ turnMark: deliveryTurnMark(command, peer),
58
62
  });
59
63
  return answer(result.kind, result.turn_epoch);
60
64
  }
@@ -22,7 +22,10 @@ export function unknownCompactAdmission(host, command) {
22
22
  if (!host.admissions || command.admissionId === undefined)
23
23
  return undefined;
24
24
  // These commands introduce client IDs; their bounded attempt index owns retry/conflict/retirement.
25
- if (command.type === "open_session" || command.type === "attach_session" || command.type === "subscribe_sessions")
25
+ if (command.type === "open_session" ||
26
+ command.type === "claim_session" ||
27
+ command.type === "attach_session" ||
28
+ command.type === "subscribe_sessions")
26
29
  return undefined;
27
30
  // RULING-96: recovery IDs select token/lease authority, not the ordinary attempt ledger.
28
31
  if (command.type === "get_recovery_page" || command.type === "release_recovery")
@@ -2,7 +2,8 @@
2
2
  * The authority word of a host-mode delegated connection (omo-relay-daemon#307).
3
3
  *
4
4
  * One `Int32Array(SharedArrayBuffer(8))` per incarnation of a delegated socket: index 0 packs
5
- * `epoch << 3 | retired << 2 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent), index 1 is the incarnation,
5
+ * `epoch << 4 | retired << 3 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent, bit 2 = peer_agent), index 1 is
6
+ * the incarnation,
6
7
  * stamped once before the buffer is shared. The host thread is the only writer, and every write is monotone within a
7
8
  * word: mask bits are only cleared, retired is only set, the epoch only grows and changes only on a real transition.
8
9
  * Host and worker threads read the same memory with one `Atomics.load` per command, so the load at a command's first
@@ -2,7 +2,8 @@
2
2
  * The authority word of a host-mode delegated connection (omo-relay-daemon#307).
3
3
  *
4
4
  * One `Int32Array(SharedArrayBuffer(8))` per incarnation of a delegated socket: index 0 packs
5
- * `epoch << 3 | retired << 2 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent), index 1 is the incarnation,
5
+ * `epoch << 4 | retired << 3 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent, bit 2 = peer_agent), index 1 is
6
+ * the incarnation,
6
7
  * stamped once before the buffer is shared. The host thread is the only writer, and every write is monotone within a
7
8
  * word: mask bits are only cleared, retired is only set, the epoch only grows and changes only on a real transition.
8
9
  * Host and worker threads read the same memory with one `Atomics.load` per command, so the load at a command's first
@@ -10,12 +11,13 @@
10
11
  *
11
12
  * This module has no package imports on purpose: worker-thread tests load it directly.
12
13
  */
13
- /** The two roles a word can carry, in bit order. */
14
- const WORD_ROLES = ["interactive_user", "task_parent"];
15
- const RETIRED_BIT = 4;
16
- const EPOCH_SHIFT = 3;
17
- /** The epoch field holds 29 bits; within one incarnation it never passes 4, so this bound is an invariant check. */
18
- const EPOCH_LIMIT = 2 ** 29;
14
+ /** The roles a word can carry, in bit order. */
15
+ const WORD_ROLES = ["interactive_user", "task_parent", "peer_agent"];
16
+ const MASK_BITS = 7;
17
+ const RETIRED_BIT = 8;
18
+ const EPOCH_SHIFT = 4;
19
+ /** The epoch field holds 28 bits; within one incarnation it never passes 4, so this bound is an invariant check. */
20
+ const EPOCH_LIMIT = 2 ** 28;
19
21
  /** The largest incarnation slot [1] holds unchanged. */
20
22
  export const INCARNATION_MAX = 0x7fffffff;
21
23
  export function maskOfRoles(roles) {
@@ -31,7 +33,7 @@ export function rolesOfMask(mask) {
31
33
  return WORD_ROLES.filter((_role, bit) => (mask & (1 << bit)) !== 0);
32
34
  }
33
35
  export function decodeWord(word) {
34
- const mask = word & 3;
36
+ const mask = word & MASK_BITS;
35
37
  return { epoch: word >>> EPOCH_SHIFT, retired: (word & RETIRED_BIT) !== 0, mask, roles: rolesOfMask(mask) };
36
38
  }
37
39
  function packWord(epoch, retired, mask) {
@@ -45,7 +47,7 @@ export function createAuthority(incarnation, mask) {
45
47
  throw new Error("authority_incarnation_invalid");
46
48
  const buffer = new SharedArrayBuffer(8);
47
49
  const view = new Int32Array(buffer);
48
- view[0] = packWord(1, false, mask & 3);
50
+ view[0] = packWord(1, false, mask & MASK_BITS);
49
51
  view[1] = incarnation;
50
52
  return buffer;
51
53
  }
@@ -73,6 +73,8 @@ export interface RpcConnectionHandler {
73
73
  * extension UI context is installed (used by tests that drive ctx.ui directly).
74
74
  */
75
75
  readonly ready: Promise<void>;
76
+ /** Complete a prebuilt binding with the capabilities its opener supplied. */
77
+ setClientCapabilities(capabilities: readonly string[]): void;
76
78
  /** Feed one inbound JSONL line (command or extension_ui_response). */
77
79
  handleInputLine(line: string): Promise<void>;
78
80
  /**
@@ -52,7 +52,8 @@ import { ConnectionQuestionBridge, degradeQuestion, sessionQuestionBridges } fro
52
52
  import { remoteOriginDeclaration, remoteOriginField } from "./remote-origin.js";
53
53
  import { advertisedCompactCapabilities, sessionDeclaration } from "./compact-negotiation.js";
54
54
  import { commandAuthority } from "./command-authority.js";
55
- import { noteDelegatedRecord } from "./delegated-drive-origin.js";
55
+ import { runInRecordScope } from "../../core/turn-origin.js";
56
+ import { recordTurnOrigin } from "./delegated-drive-origin.js";
56
57
  import { ConnectionRoles, DELEGATION_INCARNATION_STALE, roleConnection } from "./connection-roles.js";
57
58
  import { ACCOUNT_RESET_CAPABILITY, 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";
58
59
  import { runAbort, runGetEffectStatus, runQueuedInputChange, runSetThinkingLevel, } from "./effect-commands.js";
@@ -72,6 +73,7 @@ import { HostSessionControl } from "./host-session-control.js";
72
73
  import { createRpcLoginPromptCallbacks } from "./login-prompts.js";
73
74
  import { answerMemoryReport } from "./memory-report-command.js";
74
75
  import { readProjectSettings, readProjectTrust, writeProjectSetting, writeProjectTrust, } from "./project-workspace-commands.js";
76
+ import { readProjectFile, writeProjectFile } from "./project-file-commands.js";
75
77
  import { protocolIdentity } from "./protocol-identity.js";
76
78
  import { buildRpcCommandsForSession, createCommandsChangedEvent, rpcCommandListDigest } from "./rpc-command-surface.js";
77
79
  import { rpcCommandPayloadError, rpcCommandShapeError, rpcMessageLengthError, sessionRetryFallbackError, } from "./rpc-input-validation.js";
@@ -208,6 +210,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
208
210
  const currentConnectionId = () => roleConnection(options.clientInfo?.connectionId());
209
211
  const hasRole = (role) => connectionRoles.has(currentConnectionId(), role);
210
212
  const connectionOrigin = () => connectionRoles.isDelegated(currentConnectionId()) ? "delegated" : "local";
213
+ // senpi#6342: a turn follows this machine's own setting; only a device the forwarder did not state is the same account
214
+ // counts as delegated for the permission rule.
215
+ const turnOrigin = () => connectionOrigin() === "delegated" && !connectionRoles.sameAccount(currentConnectionId()) ? "delegated" : "local";
211
216
  const routingSessionId = options.sessionId;
212
217
  // True only while THIS connection's own command drives a replacement; the issuer
213
218
  // already learns the new identity from its command response.
@@ -1008,7 +1013,6 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1008
1013
  // Handle a single command
1009
1014
  const handleCommand = async (command, requestContext) => {
1010
1015
  const id = command.id;
1011
- noteDelegatedRecord(command, connectionOrigin(), session.sessionManager);
1012
1016
  switch (command.type) {
1013
1017
  case "get_protocol_info":
1014
1018
  return {
@@ -1046,7 +1050,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1046
1050
  ...(options.retryFallbackCommand ? [RETRY_FALLBACK_COMMAND_CAPABILITY] : []),
1047
1051
  ...(options.toolRuntime ? toolRuntimeCapabilities(options.toolRuntime) : []),
1048
1052
  // Client flags cannot advertise a host guard this classic binding does not run, nor a tool runtime.
1049
- ...advertisedCompactCapabilities(options.capabilities ?? [], false).filter((capability) => capability !== SESSION_HELD_CAPABILITY && !isHostOwnedToolRuntimeCapability(capability)),
1053
+ ...advertisedCompactCapabilities(options.capabilities ?? [], false).filter((capability) => capability !== SESSION_HELD_CAPABILITY &&
1054
+ capability !== "park_claim" &&
1055
+ !isHostOwnedToolRuntimeCapability(capability)),
1050
1056
  ]),
1051
1057
  ],
1052
1058
  mode: "classic",
@@ -1054,7 +1060,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1054
1060
  },
1055
1061
  };
1056
1062
  case "open_session":
1057
- return error(id, "open_session", "multi_session_disabled");
1063
+ case "park_session":
1064
+ case "claim_session":
1065
+ return error(id, command.type, "multi_session_disabled");
1058
1066
  // =================================================================
1059
1067
  // Prompting
1060
1068
  // =================================================================
@@ -1065,7 +1073,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1065
1073
  if (holdAutomaticInput(session, command, hasRole(INTERACTIVE_USER_CAPABILITY)))
1066
1074
  return success(id, "prompt", { disposition: "handled", heldAsNotice: true });
1067
1075
  turnRequested = true;
1068
- const admission = handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: connectionOrigin() });
1076
+ const admission = handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: turnOrigin() });
1069
1077
  promptCalls.add(admission);
1070
1078
  void admission.finally(() => promptCalls.delete(admission));
1071
1079
  return undefined;
@@ -1135,7 +1143,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1135
1143
  if (holdAutomaticInput(session, command, hasRole(INTERACTIVE_USER_CAPABILITY)))
1136
1144
  return success(id, command.type, { disposition: "handled", heldAsNotice: true });
1137
1145
  turnRequested = true;
1138
- await handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: connectionOrigin() });
1146
+ await handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: turnOrigin() });
1139
1147
  return undefined;
1140
1148
  }
1141
1149
  case "abort":
@@ -1237,6 +1245,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1237
1245
  const peer = {
1238
1246
  origin: connectionRoles.originOf(currentConnectionId()),
1239
1247
  connectionOrigin: connectionOrigin(),
1248
+ turnOrigin: turnOrigin(),
1240
1249
  };
1241
1250
  const answer = admitExternalMessage(session, command, peer);
1242
1251
  if (!answer.ok) {
@@ -1750,6 +1759,18 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1750
1759
  ? success(id, "set_project_setting", result.data)
1751
1760
  : error(id, "set_project_setting", result.message, result.errorCode);
1752
1761
  }
1762
+ case "read_project_file": {
1763
+ const result = await readProjectFile(session, command.path);
1764
+ return result.ok
1765
+ ? success(id, "read_project_file", result.data)
1766
+ : error(id, "read_project_file", result.message, result.errorCode, result.errorData);
1767
+ }
1768
+ case "write_project_file": {
1769
+ const result = await writeProjectFile(session, command.path, command.content, command.ifEtag);
1770
+ return result.ok
1771
+ ? success(id, "write_project_file", result.data)
1772
+ : error(id, "write_project_file", result.message, result.errorCode, result.errorData);
1773
+ }
1753
1774
  case "extension_request":
1754
1775
  case "eval_cells.list":
1755
1776
  case "eval_cells.peek":
@@ -1977,7 +1998,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1977
1998
  return;
1978
1999
  }
1979
2000
  try {
1980
- const response = await handleCommand(command, requestContext);
2001
+ // senpi#6342: the record's own handling, and the first run it starts, run under the record's origin.
2002
+ const response = await runInRecordScope(recordTurnOrigin(command, turnOrigin()), () => handleCommand(command, requestContext));
1981
2003
  if (response) {
1982
2004
  output(response);
1983
2005
  await waitForRpcBackpressure();
@@ -2038,6 +2060,10 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
2038
2060
  pendingPrompts() {
2039
2061
  return [...promptCalls];
2040
2062
  },
2063
+ setClientCapabilities(capabilities) {
2064
+ replaceClientCapabilities([...capabilities]);
2065
+ refreshGrantPresentation();
2066
+ },
2041
2067
  isShutdownRequested() {
2042
2068
  return shutdownRequested;
2043
2069
  },
@@ -59,10 +59,17 @@ export declare class ConnectionRoles {
59
59
  acceptsOrigin(connectionId: string, origin: RpcRemoteOrigin): boolean;
60
60
  /** Records the remote device a local connection speaks for; a delegated connection's origin is never declared. */
61
61
  declareOrigin(connectionId: string, origin: RpcRemoteOrigin): void;
62
+ /** Whether the forwarder stated this delegated connection's device is the host's own account (senpi#6342). */
63
+ sameAccount(connectionId: string | undefined): boolean;
62
64
  /** The remote device this connection speaks for: a delegated connection's principal, else its declared origin. */
63
65
  originOf(connectionId: string | undefined): RpcRemoteOrigin | undefined;
64
66
  /** Whether the connection is delegated (a remote device's): on the host, retained by a worker, or carried to one. */
65
67
  isDelegated(connectionId: string | undefined): boolean;
68
+ /**
69
+ * Whether the forwarder itself granted `role` to this connection (senpi#6305): only a host-mode delegation's live,
70
+ * unretired authority word counts. No client claim, legacy-mode delegation or local connection can satisfy it.
71
+ */
72
+ grantedByForwarder(connectionId: string | undefined, role: string): boolean;
66
73
  has(connectionId: string | undefined, role: string): boolean;
67
74
  /** A logical detach: drops claims of earlier incarnations of a delegated socket, and everything of a local one. */
68
75
  release(connectionId: string): void;
@@ -117,6 +117,10 @@ export class ConnectionRoles {
117
117
  if (this.acceptsOrigin(connectionId, origin))
118
118
  this.origins.set(connectionId, origin);
119
119
  }
120
+ /** Whether the forwarder stated this delegated connection's device is the host's own account (senpi#6342). */
121
+ sameAccount(connectionId) {
122
+ return this.viewOf(roleConnection(connectionId))?.descriptor.principal.sameAccount === true;
123
+ }
120
124
  /** The remote device this connection speaks for: a delegated connection's principal, else its declared origin. */
121
125
  originOf(connectionId) {
122
126
  const key = roleConnection(connectionId);
@@ -132,6 +136,17 @@ export class ConnectionRoles {
132
136
  const key = roleConnection(connectionId);
133
137
  return this.viewOf(key) !== undefined || this.carried.has(key);
134
138
  }
139
+ /**
140
+ * Whether the forwarder itself granted `role` to this connection (senpi#6305): only a host-mode delegation's live,
141
+ * unretired authority word counts. No client claim, legacy-mode delegation or local connection can satisfy it.
142
+ */
143
+ grantedByForwarder(connectionId, role) {
144
+ const descriptor = this.viewOf(roleConnection(connectionId))?.descriptor;
145
+ if (descriptor?.mode !== "host" || descriptor.authority === undefined)
146
+ return false;
147
+ const state = readAuthority(descriptor.authority);
148
+ return !state.retired && state.roles.includes(role);
149
+ }
135
150
  has(connectionId, role) {
136
151
  const key = roleConnection(connectionId);
137
152
  const store = commandAuthority.getStore();
@@ -63,6 +63,10 @@ export declare const DELEGATED_CONNECTION_CAPABILITY = "delegated_connection_v1"
63
63
  * incarnation, `relayExec` and the `authority` receipt.
64
64
  */
65
65
  export declare const DELEGATION_ROLES_CAPABILITY = "delegation_roles_v1";
66
+ /** A host-mode delegation may carry the forwarder-granted `peer_agent` role (senpi#6305). */
67
+ export declare const PEER_AGENT_ROLE_CAPABILITY = "peer_agent_role_v1";
68
+ /** A delegation may state `principal.sameAccount`, so that device's turns follow this host's own setting (senpi#6342). */
69
+ export declare const SAME_ACCOUNT_DELEGATION_CAPABILITY = "same_account_delegation_v1";
66
70
  /**
67
71
  * Client opt-in (D11 S3-5): the connection renders the value-free `secret_input_notice` and `grant_select_notice` of a
68
72
  * raiser-only dialog another connection presents, and their `*_notice_settled` records. It never answers them.
@@ -115,6 +119,8 @@ export declare const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session
115
119
  * cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
116
120
  */
117
121
  export declare const WARM_CAPABILITY = "warm";
122
+ /** HOST capability: invisible speculative sessions and single-use claim, in-process registries only. */
123
+ export declare const PARK_CLAIM_CAPABILITY = "park_claim";
118
124
  /**
119
125
  * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
120
126
  * owns a stable record id for the conversation can CREATE the session under that id and keep
@@ -63,6 +63,10 @@ export const DELEGATED_CONNECTION_CAPABILITY = "delegated_connection_v1";
63
63
  * incarnation, `relayExec` and the `authority` receipt.
64
64
  */
65
65
  export const DELEGATION_ROLES_CAPABILITY = "delegation_roles_v1";
66
+ /** A host-mode delegation may carry the forwarder-granted `peer_agent` role (senpi#6305). */
67
+ export const PEER_AGENT_ROLE_CAPABILITY = "peer_agent_role_v1";
68
+ /** A delegation may state `principal.sameAccount`, so that device's turns follow this host's own setting (senpi#6342). */
69
+ export const SAME_ACCOUNT_DELEGATION_CAPABILITY = "same_account_delegation_v1";
66
70
  /**
67
71
  * Client opt-in (D11 S3-5): the connection renders the value-free `secret_input_notice` and `grant_select_notice` of a
68
72
  * raiser-only dialog another connection presents, and their `*_notice_settled` records. It never answers them.
@@ -115,6 +119,8 @@ export const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session";
115
119
  * cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
116
120
  */
117
121
  export const WARM_CAPABILITY = "warm";
122
+ /** HOST capability: invisible speculative sessions and single-use claim, in-process registries only. */
123
+ export const PARK_CLAIM_CAPABILITY = "park_claim";
118
124
  /**
119
125
  * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
120
126
  * owns a stable record id for the conversation can CREATE the session under that id and keep
@@ -1,9 +1,9 @@
1
- import type { SessionManager } from "../../core/session-manager.ts";
2
- import { type ConnectionOrigin } from "../../core/turn-origin.ts";
1
+ import type { ConnectionOrigin } from "../../core/turn-origin.ts";
3
2
  /**
4
- * Marks a session as remote-driven when a delegated connection sends it any record that can act on its work, decided
5
- * by the engine's own method-class table (`drive`, and `device_admin`, which grants more), never by a hand-kept list of
6
- * commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...) cannot slip past the rule.
3
+ * The origin a record's own handling runs under (senpi#6342): delegated for a cross-account record that can act on the
4
+ * session's work, decided by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
5
+ * never by a hand-kept list of commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
6
+ * cannot slip past the rule. Any other record runs as local.
7
7
  */
8
- export declare function noteDelegatedRecord(command: object, origin: ConnectionOrigin, sessionManager: Pick<SessionManager, "getEntries" | "appendCustomEntry">): void;
8
+ export declare function recordTurnOrigin(command: object, origin: ConnectionOrigin): ConnectionOrigin;
9
9
  //# sourceMappingURL=delegated-drive-origin.d.ts.map
@@ -1,16 +1,15 @@
1
- import { recordDelegatedOrigin } from "../../core/turn-origin.js";
2
1
  import { classifyRpcMethod } from "./method-classes.js";
3
2
  const ACTING_CLASSES = new Set(["drive", "device_admin"]);
4
3
  /**
5
- * Marks a session as remote-driven when a delegated connection sends it any record that can act on its work, decided
6
- * by the engine's own method-class table (`drive`, and `device_admin`, which grants more), never by a hand-kept list of
7
- * commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...) cannot slip past the rule.
4
+ * The origin a record's own handling runs under (senpi#6342): delegated for a cross-account record that can act on the
5
+ * session's work, decided by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
6
+ * never by a hand-kept list of commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
7
+ * cannot slip past the rule. Any other record runs as local.
8
8
  */
9
- export function noteDelegatedRecord(command, origin, sessionManager) {
9
+ export function recordTurnOrigin(command, origin) {
10
10
  if (origin !== "delegated")
11
- return;
11
+ return "local";
12
12
  const methodClass = classifyRpcMethod(command);
13
- if (methodClass !== undefined && ACTING_CLASSES.has(methodClass))
14
- recordDelegatedOrigin(sessionManager);
13
+ return methodClass !== undefined && ACTING_CLASSES.has(methodClass) ? "delegated" : "local";
15
14
  }
16
15
  //# sourceMappingURL=delegated-drive-origin.js.map
@@ -4,6 +4,8 @@ export interface Principal {
4
4
  readonly deviceId: string;
5
5
  readonly deviceName?: string;
6
6
  readonly conn?: string;
7
+ /** The forwarder states this device is the host's own account (senpi#6342); fixed for the record's life. */
8
+ readonly sameAccount?: true;
7
9
  }
8
10
  export interface Declaration {
9
11
  readonly principal: Principal;
@@ -8,7 +8,7 @@ const FORWARDABLE_CLASSES = new Set([
8
8
  const MAX_PRINCIPAL_FIELD = 256;
9
9
  const MAX_CONN_FIELD = 64;
10
10
  /** The connection roles a host-mode declaration may carry (omo-relay-daemon#307). */
11
- const DECLARABLE_ROLES = new Set(["interactive_user", "task_parent"]);
11
+ const DECLARABLE_ROLES = new Set(["interactive_user", "task_parent", "peer_agent"]);
12
12
  export function parseDeclaration(record) {
13
13
  const principal = Reflect.get(record, "principal");
14
14
  if (typeof principal !== "object" || principal === null || Array.isArray(principal))
@@ -22,6 +22,9 @@ export function parseDeclaration(record) {
22
22
  return "principal.deviceName must be 1-256 characters";
23
23
  if (conn !== undefined && !boundedString(conn, MAX_CONN_FIELD))
24
24
  return "principal.conn must be 1-64 characters";
25
+ const sameAccount = Reflect.get(principal, "sameAccount");
26
+ if (sameAccount !== undefined && sameAccount !== true)
27
+ return "principal.sameAccount must be true when present";
25
28
  const granted = Reflect.get(record, "granted");
26
29
  if (!Array.isArray(granted))
27
30
  return "granted must be an array of method classes";
@@ -40,17 +43,18 @@ export function parseDeclaration(record) {
40
43
  deviceId: deviceId,
41
44
  ...(deviceName === undefined ? {} : { deviceName: deviceName }),
42
45
  ...(conn === undefined ? {} : { conn: conn }),
46
+ ...(sameAccount === true ? { sameAccount: true } : {}),
43
47
  },
44
48
  granted: classes,
45
49
  };
46
50
  }
47
51
  export function samePrincipal(a, b) {
48
- return a.deviceId === b.deviceId && a.deviceName === b.deviceName && a.conn === b.conn;
52
+ return (a.deviceId === b.deviceId && a.deviceName === b.deviceName && a.conn === b.conn && a.sameAccount === b.sameAccount);
49
53
  }
50
54
  function parseRoles(value) {
51
55
  if (value === undefined)
52
56
  return undefined;
53
- const invalid = "roles holds each of interactive_user, task_parent at most once";
57
+ const invalid = "roles holds each of interactive_user, task_parent, peer_agent at most once";
54
58
  if (!Array.isArray(value))
55
59
  return invalid;
56
60
  const roles = new Set();
@@ -66,6 +66,27 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
66
66
  readonly reclaimed: true;
67
67
  readonly sessionId: string;
68
68
  };
69
+ } | {
70
+ id?: string;
71
+ type: "response";
72
+ command: "park_session";
73
+ success: true;
74
+ data: {
75
+ state: "parked" | "already_parked" | "full";
76
+ };
77
+ } | {
78
+ id?: string;
79
+ type: "response";
80
+ command: "claim_session";
81
+ success: true;
82
+ data: {
83
+ claimed: false;
84
+ } | {
85
+ sessionId: string;
86
+ state: import("./rpc-session-state-types.ts").RpcSessionState;
87
+ attached?: boolean;
88
+ presence?: import("./rpc-host-response-types.ts").RpcSessionPresence;
89
+ };
69
90
  } | {
70
91
  id?: string;
71
92
  type: "response";
@@ -414,6 +435,12 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
414
435
  command: "set_project_setting";
415
436
  success: true;
416
437
  data: import("./project-workspace-commands.ts").RpcProjectSettings;
438
+ } | {
439
+ id?: string;
440
+ type: "response";
441
+ command: "write_project_file";
442
+ success: true;
443
+ data: import("./project-file-commands.ts").RpcProjectFile;
417
444
  } | {
418
445
  id?: string;
419
446
  type: "response";
@@ -871,6 +898,12 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
871
898
  command: "get_project_settings";
872
899
  success: true;
873
900
  data: import("./project-workspace-commands.ts").RpcProjectSettings;
901
+ } | {
902
+ id?: string;
903
+ type: "response";
904
+ command: "read_project_file";
905
+ success: true;
906
+ data: import("./project-file-commands.ts").RpcProjectFile;
874
907
  } | {
875
908
  id?: string;
876
909
  type: "response";
@@ -14,6 +14,7 @@ export declare const SET_PERMISSION_PRESET_CAPABILITY = "set_permission_preset_v
14
14
  */
15
15
  export declare function multiSessionHostCapabilities(options: {
16
16
  readonly warm: boolean;
17
+ readonly parkClaim?: boolean;
17
18
  readonly toolRuntime: ToolRuntimeKind;
18
19
  readonly negotiated: readonly string[];
19
20
  readonly mcpPresenters?: boolean;
@@ -2,7 +2,7 @@ import { compactUpdatesEnabled } from "../../core/engine-socket-flag.js";
2
2
  import { isHostOwnedToolRuntimeCapability, toolRuntimeCapabilities, } from "../../cli/tool-runtime.js";
3
3
  import { ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY, AUTO_PERMISSION_PRESET_CAPABILITY, } from "../../core/extensions/builtin/permission-system/config.js";
4
4
  import { DURABLE_CLIENT_MESSAGE_ID_CAPABILITY } from "./client-admission-record.js";
5
- import { ACCOUNT_RESET_CAPABILITY, ATTENDED_CAPABILITY, AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_PER_SESSION_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, BROWSER_ENGINE_CAPABILITY, CONTINUE_FROM_LEAF_CAPABILITY, DELEGATED_CONNECTION_CAPABILITY, DELEGATION_ROLES_CAPABILITY, DETACH_CONNECTION_CAPABILITY, DURABLE_SESSION_ID_CAPABILITY, ENTRIES_TAIL_CAPABILITY, EVAL_CELLS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, MOVED_PATH_GUARD_CAPABILITY, OBSERVE_READS_CAPABILITY, PROMPT_SURFACE_CAPABILITY, PROMPT_SURFACE_CHAT_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETAIN_ON_DISCONNECT_CAPABILITY, RETRY_FALLBACK_PROFILE_CAPABILITY, SESSION_CONTEXT_CAPABILITY, SESSION_ENV_CAPABILITY, SESSION_HELD_CAPABILITY, SESSION_KIND_CAPABILITY, SESSION_RELOCATION_CAPABILITY, SESSION_STATUS_CAPABILITY, TOOL_BARRIER_CAPABILITY, WARM_CAPABILITY, } from "./custom-capability.js";
5
+ import { ACCOUNT_RESET_CAPABILITY, ATTENDED_CAPABILITY, AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_PER_SESSION_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, BROWSER_ENGINE_CAPABILITY, CONTINUE_FROM_LEAF_CAPABILITY, DELEGATED_CONNECTION_CAPABILITY, DELEGATION_ROLES_CAPABILITY, DETACH_CONNECTION_CAPABILITY, DURABLE_SESSION_ID_CAPABILITY, PEER_AGENT_ROLE_CAPABILITY, SAME_ACCOUNT_DELEGATION_CAPABILITY, ENTRIES_TAIL_CAPABILITY, EVAL_CELLS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, MOVED_PATH_GUARD_CAPABILITY, OBSERVE_READS_CAPABILITY, PROMPT_SURFACE_CAPABILITY, PROMPT_SURFACE_CHAT_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETAIN_ON_DISCONNECT_CAPABILITY, RETRY_FALLBACK_PROFILE_CAPABILITY, SESSION_CONTEXT_CAPABILITY, SESSION_ENV_CAPABILITY, SESSION_HELD_CAPABILITY, SESSION_KIND_CAPABILITY, SESSION_RELOCATION_CAPABILITY, SESSION_STATUS_CAPABILITY, TOOL_BARRIER_CAPABILITY, WARM_CAPABILITY, PARK_CLAIM_CAPABILITY, } from "./custom-capability.js";
6
6
  import { EFFECT_LEDGER_CAPABILITY } from "./effect-record.js";
7
7
  import { SESSION_MODEL_SCOPE_CAPABILITY } from "./rpc-session-command-types.js";
8
8
  import { STEER_WHEN_IDLE_CAPABILITY, USER_ACTIVITY_CAPABILITY } from "./rpc-types.js";
@@ -70,6 +70,10 @@ export function multiSessionHostCapabilities(options) {
70
70
  DELEGATED_CONNECTION_CAPABILITY,
71
71
  // ...and decides a host-mode connection's roles per incarnation, with receipts (omo-relay-daemon#307).
72
72
  DELEGATION_ROLES_CAPABILITY,
73
+ // ...and may carry the forwarder-granted `peer_agent` role on such a connection (senpi#6305).
74
+ PEER_AGENT_ROLE_CAPABILITY,
75
+ // ...and lets the forwarder state a device is the host's own account, whose turns then ask nothing extra.
76
+ SAME_ACCOUNT_DELEGATION_CAPABILITY,
73
77
  // Only a multi-session host keeps sessions loaded that a client can ask it to free.
74
78
  UNLOAD_SESSION_CAPABILITY,
75
79
  // Only a multi-session host owns a move ledger and the hosted-session list export checks against.
@@ -101,9 +105,11 @@ export function multiSessionHostCapabilities(options) {
101
105
  AUTO_PERMISSION_PRESET_CAPABILITY,
102
106
  // Only an in-process runtime shares the loop a warm loads into (senpi#2314).
103
107
  ...(options.warm ? [WARM_CAPABILITY] : []),
108
+ ...(options.parkClaim ? [PARK_CLAIM_CAPABILITY] : []),
104
109
  ...toolRuntimeCapabilities(options.toolRuntime),
105
110
  // The host alone says where tool work runs; a negotiated copy would make two answers.
106
111
  ...options.negotiated.filter((capability) => capability !== "mcp_form_presenter_v1" &&
112
+ capability !== PARK_CLAIM_CAPABILITY &&
107
113
  // RULING-111 (LEAK-E): only the compact negotiation owns these names; flag off echoes them as main does.
108
114
  (!compactUpdatesEnabled() ||
109
115
  (capability !== "compact_message_updates_v1" && capability !== "compact_events")) &&
@@ -1,5 +1,5 @@
1
1
  import { type HostDaemonDirectory } from "./host-daemon-paths.ts";
2
- export type EndpointInUse = "live_generation" | "live_claim" | "reachable";
2
+ export type EndpointInUse = "live_generation" | "live_claim" | "reachable" | "credential_unavailable";
3
3
  export type SocketSilence = "socket_refused" | "socket_absent";
4
4
  /**
5
5
  * The three-part test, in the order its answers are reported: (a) no generation pidfile names a live
@@ -33,12 +33,17 @@ export async function endpointInUse(paths, socket) {
33
33
  return { inUse: "live_claim" };
34
34
  }
35
35
  const silence = await socketSilence(socket);
36
+ if (silence === "credential_unavailable")
37
+ return { inUse: silence };
36
38
  if (silence === undefined)
37
39
  return { inUse: "reachable" };
38
40
  // A successor mid-handoff listens on `<socket>.next-<gen>` before it registers anywhere.
39
41
  const successors = (await socketSiblings(socket)).filter((name) => name.startsWith(`${basename(socket)}.next-`) && !isBindScratchName(name));
40
42
  for (const successor of successors) {
41
- if ((await socketSilence(join(dirname(socket), successor))) === undefined)
43
+ const successorSilence = await socketSilence(join(dirname(socket), successor));
44
+ if (successorSilence === "credential_unavailable")
45
+ return { inUse: successorSilence };
46
+ if (successorSilence === undefined)
42
47
  return { inUse: "reachable" };
43
48
  }
44
49
  return { inUse: undefined, silence };
@@ -101,10 +106,11 @@ async function recordIsLive(record) {
101
106
  async function socketSilence(socket) {
102
107
  let secret;
103
108
  if (process.platform === "win32") {
104
- // The pipe name includes the secret; without one no client can reach the pipe either.
109
+ // The pipe name includes the secret, so without a readable one nothing proves the pipe silent: a
110
+ // live host may still serve it under the key whose file was lost (sisyphuslabs/omo-desktop-app#4199).
105
111
  secret = await readSocketSecret(socketSecretPath(socket)).catch(() => undefined);
106
112
  if (secret === undefined)
107
- return "socket_absent";
113
+ return "credential_unavailable";
108
114
  }
109
115
  return new Promise((resolveProbe) => {
110
116
  const connection = createConnection(resolveSocketTransportAddress(socket, process.platform, secret));
@@ -14,6 +14,7 @@
14
14
  * live_generation a generation pidfile (any, the pointer's included) names a live process
15
15
  * live_claim a session-path claim in `reservations/` has a live owner
16
16
  * reachable the socket (or a `.next-*` successor bind) did not refuse the connection
17
+ * credential_unavailable win32: the socket secret cannot be read, so its pipe cannot be proven silent
17
18
  * locked the ensure lock was not free within 2 s
18
19
  * legacy_layout the agent dir predates layout 2; its flat files belong to a legacy host
19
20
  * unknown_identity nothing in the directory names its socket, so its lock cannot be taken
@@ -94,7 +95,9 @@ export async function gcEndpoint(socket, dir, options) {
94
95
  try {
95
96
  await options._test?.afterLockAcquired?.(socket);
96
97
  const evidence = await endpointInUse(hostDaemonDirectoryPaths(dir), socket);
97
- if (evidence.inUse === "live_claim" || (evidence.inUse !== undefined && options.staleEngine === undefined)) {
98
+ if (evidence.inUse === "live_claim" ||
99
+ evidence.inUse === "credential_unavailable" ||
100
+ (evidence.inUse !== undefined && options.staleEngine === undefined)) {
98
101
  return { removed: false, reason: evidence.inUse };
99
102
  }
100
103
  if (evidence.inUse !== undefined)
@@ -12,6 +12,8 @@
12
12
  * and the connection attaches, so a client cannot hold a session while its host idles out under it.
13
13
  * `warm` never attaches, marked or not: it opens nothing, so a host that only received it idles out
14
14
  * on its normal deadline (senpi#2314).
15
+ * `park_session` likewise holds no client attachment: its speculative runtime is discarded at host exit.
16
+ * `claim_session` takes an ordinary opener attachment and is never observing.
15
17
  * Hosts that predate the field ignore it (commands are parsed by `type`), so a marked read works
16
18
  * against every generation.
17
19
  *