@code-yeongyu/senpi 2026.9.2 → 2026.9.3-3

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 (351) hide show
  1. package/CHANGELOG.md +188 -2
  2. package/dist/beta/omo-local-update-fingerprint.d.ts.map +1 -1
  3. package/dist/beta/omo-local-update-fingerprint.js +0 -1
  4. package/dist/beta/omo-local-update-fingerprint.js.map +1 -1
  5. package/dist/core/agent-session.d.ts +3 -5
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +39 -33
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
  10. package/dist/core/dynamic-prompt/build.js +2 -5
  11. package/dist/core/dynamic-prompt/build.js.map +1 -1
  12. package/dist/core/dynamic-prompt/index.d.ts +1 -2
  13. package/dist/core/dynamic-prompt/index.d.ts.map +1 -1
  14. package/dist/core/dynamic-prompt/index.js +1 -2
  15. package/dist/core/dynamic-prompt/index.js.map +1 -1
  16. package/dist/core/dynamic-prompt/intent-gate.d.ts.map +1 -1
  17. package/dist/core/dynamic-prompt/intent-gate.js +9 -24
  18. package/dist/core/dynamic-prompt/intent-gate.js.map +1 -1
  19. package/dist/core/dynamic-prompt/policies.d.ts.map +1 -1
  20. package/dist/core/dynamic-prompt/policies.js +3 -7
  21. package/dist/core/dynamic-prompt/policies.js.map +1 -1
  22. package/dist/core/dynamic-prompt/style.d.ts.map +1 -1
  23. package/dist/core/dynamic-prompt/style.js +6 -8
  24. package/dist/core/dynamic-prompt/style.js.map +1 -1
  25. package/dist/core/dynamic-prompt/verification.js +1 -1
  26. package/dist/core/dynamic-prompt/verification.js.map +1 -1
  27. package/dist/core/dynamic-prompt/working-task.d.ts +2 -0
  28. package/dist/core/dynamic-prompt/working-task.d.ts.map +1 -0
  29. package/dist/core/dynamic-prompt/working-task.js +10 -0
  30. package/dist/core/dynamic-prompt/working-task.js.map +1 -0
  31. package/dist/core/extensions/builtin/bash-timeout/index.d.ts +1 -1
  32. package/dist/core/extensions/builtin/bash-timeout/index.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/bash-timeout/index.js +7 -1
  34. package/dist/core/extensions/builtin/bash-timeout/index.js.map +1 -1
  35. package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts +11 -7
  36. package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/bash-timeout/timeout.js +4 -8
  38. package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.js +15 -18
  41. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.js.map +1 -1
  42. package/dist/core/extensions/builtin/claude-sdk-oauth/content-blocks.d.ts +3 -0
  43. package/dist/core/extensions/builtin/claude-sdk-oauth/content-blocks.d.ts.map +1 -0
  44. package/dist/core/extensions/builtin/claude-sdk-oauth/content-blocks.js +80 -0
  45. package/dist/core/extensions/builtin/claude-sdk-oauth/content-blocks.js.map +1 -0
  46. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.d.ts +18 -1
  47. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.js +57 -1
  49. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.js.map +1 -1
  50. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.d.ts +1 -0
  51. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.js +13 -0
  53. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.js.map +1 -1
  54. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts.map +1 -1
  55. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js +6 -1
  56. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js.map +1 -1
  57. package/dist/core/extensions/builtin/claude-sdk-oauth/options.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/claude-sdk-oauth/options.js +6 -2
  59. package/dist/core/extensions/builtin/claude-sdk-oauth/options.js.map +1 -1
  60. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-bridge.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-bridge.js +2 -23
  62. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-bridge.js.map +1 -1
  63. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts +2 -2
  64. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +30 -24
  66. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  67. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +2 -0
  68. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +15 -1
  70. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
  71. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts +1 -1
  72. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts.map +1 -1
  73. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js +1 -0
  74. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js.map +1 -1
  75. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts +6 -1
  76. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
  77. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +1 -0
  78. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
  79. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-pump.d.ts.map +1 -1
  80. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-pump.js +19 -3
  81. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-pump.js.map +1 -1
  82. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.d.ts.map +1 -1
  83. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js +31 -13
  84. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js.map +1 -1
  85. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +1 -0
  86. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +1 -0
  88. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  89. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.d.ts.map +1 -1
  90. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js +8 -14
  91. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js.map +1 -1
  92. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
  93. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +23 -6
  94. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js.map +1 -1
  95. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-guidance.d.ts.map +1 -1
  96. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-guidance.js +4 -2
  97. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-guidance.js.map +1 -1
  98. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-protocol.d.ts +1 -1
  99. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-protocol.d.ts.map +1 -1
  100. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.d.ts.map +1 -1
  101. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js +15 -7
  102. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js.map +1 -1
  103. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts +11 -3
  104. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts.map +1 -1
  105. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js +12 -3
  106. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js.map +1 -1
  107. package/dist/core/extensions/builtin/compaction/extension-wiring.js +1 -1
  108. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -1
  109. package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts +1 -1
  110. package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts.map +1 -1
  111. package/dist/core/extensions/builtin/config-reload/watch-event-source.js +27 -9
  112. package/dist/core/extensions/builtin/config-reload/watch-event-source.js.map +1 -1
  113. package/dist/core/extensions/builtin/eval-only-routing.d.ts +10 -0
  114. package/dist/core/extensions/builtin/eval-only-routing.d.ts.map +1 -0
  115. package/dist/core/extensions/builtin/eval-only-routing.js +16 -0
  116. package/dist/core/extensions/builtin/eval-only-routing.js.map +1 -0
  117. package/dist/core/extensions/builtin/gpt-account.d.ts +3 -0
  118. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -0
  119. package/dist/core/extensions/builtin/gpt-account.js +115 -0
  120. package/dist/core/extensions/builtin/gpt-account.js.map +1 -0
  121. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  122. package/dist/core/extensions/builtin/index.js +2 -0
  123. package/dist/core/extensions/builtin/index.js.map +1 -1
  124. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -1
  125. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +52 -50
  126. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -1
  127. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +2 -1
  129. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  130. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js +8 -4
  132. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js.map +1 -1
  133. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.d.ts.map +1 -1
  134. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js +2 -6
  135. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js.map +1 -1
  136. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.d.ts.map +1 -1
  137. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js +9 -3
  138. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js.map +1 -1
  139. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js +10 -4
  141. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js.map +1 -1
  142. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +57 -43
  144. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
  145. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +39 -0
  146. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts.map +1 -0
  147. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +57 -0
  148. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js.map +1 -0
  149. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.d.ts +1 -1
  150. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.d.ts.map +1 -1
  151. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js +2 -11
  152. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js.map +1 -1
  153. package/dist/core/extensions/builtin/prompt-preset/glm-5-3.d.ts +1 -1
  154. package/dist/core/extensions/builtin/prompt-preset/glm-5-3.d.ts.map +1 -1
  155. package/dist/core/extensions/builtin/prompt-preset/glm-5-3.js +2 -11
  156. package/dist/core/extensions/builtin/prompt-preset/glm-5-3.js.map +1 -1
  157. package/dist/core/extensions/builtin/prompt-preset/glm-5.d.ts +4 -0
  158. package/dist/core/extensions/builtin/prompt-preset/glm-5.d.ts.map +1 -0
  159. package/dist/core/extensions/builtin/prompt-preset/glm-5.js +16 -0
  160. package/dist/core/extensions/builtin/prompt-preset/glm-5.js.map +1 -0
  161. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.d.ts.map +1 -1
  162. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js +11 -1
  163. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js.map +1 -1
  164. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.d.ts.map +1 -1
  165. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js +11 -1
  166. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js.map +1 -1
  167. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  168. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +61 -76
  169. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  170. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  171. package/dist/core/extensions/builtin/prompt-preset/presets.js +8 -2
  172. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  173. package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
  174. package/dist/core/extensions/builtin/terminal/extension.js +13 -5
  175. package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
  176. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts +4 -3
  177. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  178. package/dist/core/extensions/builtin/terminal/monitor-notify.js +18 -18
  179. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  180. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +7 -0
  181. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
  182. package/dist/core/extensions/builtin/terminal/monitor-registry.js +37 -8
  183. package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
  184. package/dist/core/extensions/builtin/terminal/monitor-status.js +1 -1
  185. package/dist/core/extensions/builtin/terminal/monitor-status.js.map +1 -1
  186. package/dist/core/extensions/builtin/terminal/prompt.d.ts +13 -2
  187. package/dist/core/extensions/builtin/terminal/prompt.d.ts.map +1 -1
  188. package/dist/core/extensions/builtin/terminal/prompt.js +31 -16
  189. package/dist/core/extensions/builtin/terminal/prompt.js.map +1 -1
  190. package/dist/core/extensions/builtin/terminal/tools/bash-output.d.ts.map +1 -1
  191. package/dist/core/extensions/builtin/terminal/tools/bash-output.js +14 -2
  192. package/dist/core/extensions/builtin/terminal/tools/bash-output.js.map +1 -1
  193. package/dist/core/extensions/builtin/terminal/tools/context.d.ts +2 -0
  194. package/dist/core/extensions/builtin/terminal/tools/context.d.ts.map +1 -1
  195. package/dist/core/extensions/builtin/terminal/tools/context.js.map +1 -1
  196. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
  197. package/dist/core/extensions/builtin/terminal/tools/monitor.js +27 -10
  198. package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
  199. package/dist/core/provider-composer.d.ts.map +1 -1
  200. package/dist/core/provider-composer.js +17 -8
  201. package/dist/core/provider-composer.js.map +1 -1
  202. package/dist/core/settings-manager.d.ts +2 -6
  203. package/dist/core/settings-manager.d.ts.map +1 -1
  204. package/dist/core/settings-manager.js +5 -9
  205. package/dist/core/settings-manager.js.map +1 -1
  206. package/dist/index.d.ts +1 -1
  207. package/dist/index.d.ts.map +1 -1
  208. package/dist/index.js +1 -1
  209. package/dist/index.js.map +1 -1
  210. package/dist/modes/index.d.ts +1 -1
  211. package/dist/modes/index.d.ts.map +1 -1
  212. package/dist/modes/index.js +1 -1
  213. package/dist/modes/index.js.map +1 -1
  214. package/dist/modes/print-mode.d.ts.map +1 -1
  215. package/dist/modes/print-mode.js +9 -0
  216. package/dist/modes/print-mode.js.map +1 -1
  217. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  218. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  219. package/dist/modes/rpc/connection-handler.js +71 -12
  220. package/dist/modes/rpc/connection-handler.js.map +1 -1
  221. package/dist/modes/rpc/custom-capability.d.ts +5 -0
  222. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  223. package/dist/modes/rpc/custom-capability.js +5 -0
  224. package/dist/modes/rpc/custom-capability.js.map +1 -1
  225. package/dist/modes/rpc/host-ensure.d.ts +6 -0
  226. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  227. package/dist/modes/rpc/host-ensure.js +36 -9
  228. package/dist/modes/rpc/host-ensure.js.map +1 -1
  229. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  230. package/dist/modes/rpc/host-lifecycle.js +16 -4
  231. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  232. package/dist/modes/rpc/login-prompts.d.ts +24 -0
  233. package/dist/modes/rpc/login-prompts.d.ts.map +1 -0
  234. package/dist/modes/rpc/login-prompts.js +44 -0
  235. package/dist/modes/rpc/login-prompts.js.map +1 -0
  236. package/dist/modes/rpc/media-placeholders.d.ts +49 -0
  237. package/dist/modes/rpc/media-placeholders.d.ts.map +1 -0
  238. package/dist/modes/rpc/media-placeholders.js +151 -0
  239. package/dist/modes/rpc/media-placeholders.js.map +1 -0
  240. package/dist/modes/rpc/multi-session-host.d.ts +7 -4
  241. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  242. package/dist/modes/rpc/multi-session-host.js +10 -4
  243. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  244. package/dist/modes/rpc/rpc-client.d.ts +16 -0
  245. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  246. package/dist/modes/rpc/rpc-client.js +73 -7
  247. package/dist/modes/rpc/rpc-client.js.map +1 -1
  248. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  249. package/dist/modes/rpc/rpc-mode.js +1 -1
  250. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  251. package/dist/modes/rpc/rpc-types.d.ts +23 -1
  252. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  253. package/dist/modes/rpc/rpc-types.js +1 -0
  254. package/dist/modes/rpc/rpc-types.js.map +1 -1
  255. package/dist/modes/rpc/session-command-router.d.ts +22 -0
  256. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  257. package/dist/modes/rpc/session-command-router.js +134 -95
  258. package/dist/modes/rpc/session-command-router.js.map +1 -1
  259. package/dist/modes/rpc/session-event-fanout.d.ts +51 -0
  260. package/dist/modes/rpc/session-event-fanout.d.ts.map +1 -0
  261. package/dist/modes/rpc/session-event-fanout.js +170 -0
  262. package/dist/modes/rpc/session-event-fanout.js.map +1 -0
  263. package/dist/modes/rpc/session-event-writer.d.ts +9 -14
  264. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  265. package/dist/modes/rpc/session-event-writer.js +68 -106
  266. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  267. package/dist/modes/rpc/session-registry.d.ts +9 -8
  268. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  269. package/dist/modes/rpc/session-registry.js +14 -42
  270. package/dist/modes/rpc/session-registry.js.map +1 -1
  271. package/dist/modes/rpc/session-teardown.d.ts +12 -0
  272. package/dist/modes/rpc/session-teardown.d.ts.map +1 -0
  273. package/dist/modes/rpc/session-teardown.js +117 -0
  274. package/dist/modes/rpc/session-teardown.js.map +1 -0
  275. package/dist/modes/rpc/socket-event-fanout.d.ts +8 -1
  276. package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -1
  277. package/dist/modes/rpc/socket-event-fanout.js +32 -9
  278. package/dist/modes/rpc/socket-event-fanout.js.map +1 -1
  279. package/docs/rpc.md +114 -6
  280. package/docs/settings.md +8 -30
  281. package/docs/terminal-tools.md +26 -6
  282. package/docs/windows.md +1 -1
  283. package/node_modules/@anthropic-ai/claude-agent-sdk/bridge.d.ts +18 -1
  284. package/node_modules/@anthropic-ai/claude-agent-sdk/bridge.mjs +155 -106
  285. package/node_modules/@anthropic-ai/claude-agent-sdk/browser-sdk.js +144 -83
  286. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.json +21 -32
  287. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.zst.json +25 -36
  288. package/node_modules/@anthropic-ai/claude-agent-sdk/package.json +2 -2
  289. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk-tools.d.ts +93 -31
  290. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.d.ts +473 -31
  291. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +140 -93
  292. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +83 -0
  293. package/node_modules/@code-yeongyu/senpi-codemode/README.md +4 -2
  294. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  295. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +43 -9
  296. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +21 -1
  297. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +6 -0
  298. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.d.ts +10 -0
  299. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.js +126 -0
  300. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +24 -7
  301. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +1 -1
  302. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +1 -1
  303. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool-options.ts +5 -1
  304. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +3 -0
  305. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts +3 -0
  306. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  307. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
  308. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  309. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  310. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +1 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts +5 -0
  313. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js +26 -4
  315. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +16 -3
  317. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
  318. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +40 -6
  319. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
  320. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts +8 -0
  321. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts.map +1 -1
  322. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.js.map +1 -1
  323. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  324. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  325. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -1
  326. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  327. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  328. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  329. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  330. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  331. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts.map +1 -1
  335. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js +3 -1
  336. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js.map +1 -1
  337. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -1
  338. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  339. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  340. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  341. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  342. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  343. package/package.json +16 -16
  344. package/dist/core/dynamic-prompt/exploration.d.ts +0 -2
  345. package/dist/core/dynamic-prompt/exploration.d.ts.map +0 -1
  346. package/dist/core/dynamic-prompt/exploration.js +0 -6
  347. package/dist/core/dynamic-prompt/exploration.js.map +0 -1
  348. package/dist/core/dynamic-prompt/parallel-tools.d.ts +0 -2
  349. package/dist/core/dynamic-prompt/parallel-tools.d.ts.map +0 -1
  350. package/dist/core/dynamic-prompt/parallel-tools.js +0 -8
  351. package/dist/core/dynamic-prompt/parallel-tools.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-types.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwJH,iDAAiD;AACjD,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAC3D,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AACnE,MAAM,CAAC,MAAM,4BAA4B,GAAG,oBAAoB,CAAC;AACjE,MAAM,CAAC,MAAM,gCAAgC,GAAG,wBAAwB,CAAC;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,2BAA2B,GAAG,mBAAmB,CAAC","sourcesContent":["/**\n * RPC protocol types for headless operation.\n *\n * Commands are sent as JSON lines on stdin.\n * Responses and events are emitted as JSON lines on stdout.\n */\n\nimport type { AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, Model, ThinkingSelection } from \"@earendil-works/pi-ai\";\nimport type { AgentAbortSource } from \"../../core/agent-abort-provenance.ts\";\nimport type { PromptDisposition, SessionStats } from \"../../core/agent-session.ts\";\nimport type { BashResult } from \"../../core/bash-executor.ts\";\nimport type { CompactionResult } from \"../../core/compaction/index.ts\";\nimport type { ServiceTier } from \"../../core/extensions/builtin/service-tier.ts\";\nimport type { ContextUsage } from \"../../core/extensions/types.ts\";\nimport type { SessionEntry, SessionTreeNode, UsageTotals } from \"../../core/session-manager.ts\";\nimport type { SourceInfo } from \"../../core/source-info.ts\";\nimport type { RpcSlashCommand } from \"./rpc-command-surface.ts\";\n\nexport type { RpcCommandInvocationEvent } from \"./rpc-command-invocation.ts\";\nexport type { RpcCommandsChangedEvent, RpcSlashCommand } from \"./rpc-command-surface.ts\";\n\n// ============================================================================\n// RPC Commands (stdin)\n// ============================================================================\n\ntype RpcSessionCommand =\n\t// Prompting\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"prompt\";\n\t\t\tmessage: string;\n\t\t\timages?: ImageContent[];\n\t\t\tstreamingBehavior?: \"steer\" | \"followUp\";\n\t\t\tthinkingLevel?: ThinkingLevel;\n\t\t\tsessionTitlePrompt?: string | false;\n\t\t\texpandPromptTemplates?: boolean;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"send_custom_message\";\n\t\t\tcustomType: string;\n\t\t\tcontent: unknown;\n\t\t\tdisplay: boolean;\n\t\t\tdetails?: unknown;\n\t\t\ttriggerTurn?: boolean;\n\t\t\tdeliverAs?: \"steer\" | \"followUp\" | \"nextTurn\";\n\t }\n\t| { id?: string; type: \"append_user_message\"; content: unknown }\n\t| { id?: string; type: \"append_session_entry\"; entry: SessionEntry }\n\t| { id?: string; type: \"steer\"; message: string; images?: ImageContent[]; enqueueOrder?: number }\n\t| { id?: string; type: \"follow_up\"; message: string; images?: ImageContent[]; enqueueOrder?: number }\n\t| { id?: string; type: \"abort\" }\n\t| { id?: string; type: \"abort_compaction\" }\n\t| { id?: string; type: \"reload\" }\n\t| { id?: string; type: \"check_reload_veto\" }\n\t| { id?: string; type: \"clear_queue\"; abortWillFollow?: boolean }\n\t| { id?: string; type: \"get_steering_messages\" }\n\t| { id?: string; type: \"get_follow_up_messages\" }\n\t| { id?: string; type: \"abort_branch_summary\" }\n\t| { id?: string; type: \"new_session\"; parentSession?: string }\n\n\t// State\n\t| { id?: string; type: \"get_state\" }\n\n\t// Model\n\t| { id?: string; type: \"set_model\"; provider: string; modelId: string }\n\t| { id?: string; type: \"set_favorite_models\"; models: RpcSessionModelEntry[] }\n\t| { id?: string; type: \"set_scoped_models\"; models: RpcSessionModelEntry[] }\n\t| { id?: string; type: \"cycle_model\"; direction?: \"forward\" | \"backward\" }\n\t| { id?: string; type: \"get_available_models\" }\n\n\t// Thinking\n\t| { id?: string; type: \"set_thinking_level\"; level: ThinkingLevel; scope?: \"turn\" }\n\t| { id?: string; type: \"cycle_thinking_level\" }\n\t| { id?: string; type: \"get_available_thinking_levels\" }\n\n\t// Fast mode (OpenAI Codex priority service tier)\n\t| { id?: string; type: \"set_fast_mode\"; enabled: boolean }\n\t| { id?: string; type: \"get_fast_mode\" }\n\n\t// Queue modes\n\t| { id?: string; type: \"set_steering_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\t| { id?: string; type: \"set_follow_up_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\n\t// Compaction\n\t| { id?: string; type: \"compact\"; customInstructions?: string }\n\t| { id?: string; type: \"set_auto_compaction\"; enabled: boolean }\n\n\t// Retry\n\t| { id?: string; type: \"set_auto_retry\"; enabled: boolean }\n\t| { id?: string; type: \"abort_retry\" }\n\n\t// Bash\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"bash\";\n\t\t\tcommand: string;\n\t\t\t/** Identifies output chunks to the requesting client. */\n\t\t\tbashId?: string;\n\t\t\texcludeFromContext?: boolean;\n\t\t\texecutionId?: string;\n\t\t\toperations?: Record<string, unknown>;\n\t }\n\t| { id?: string; type: \"record_bash_result\"; command: string; result: BashResult; excludeFromContext?: boolean }\n\t| { id?: string; type: \"abort_bash\" }\n\t| { id?: string; type: \"cleanup_bash_output\"; path: string }\n\t| { id?: string; type: \"set_label\"; entryId: string; label?: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"navigate_tree\";\n\t\t\ttargetId: string;\n\t\t\tsummarize?: boolean;\n\t\t\tcustomInstructions?: string;\n\t\t\treplaceInstructions?: boolean;\n\t\t\tlabel?: string;\n\t }\n\n\t// Session\n\t| { id?: string; type: \"get_session_stats\" }\n\t| { id?: string; type: \"export_html\"; outputPath?: string; themeName?: string }\n\t| { id?: string; type: \"export_jsonl\"; outputPath?: string }\n\t| { id?: string; type: \"switch_session\"; sessionPath: string; cwdOverride?: string }\n\t| { id?: string; type: \"fork\"; entryId: string; position?: \"before\" | \"at\" }\n\t| { id?: string; type: \"clone\" }\n\t| { id?: string; type: \"get_fork_messages\" }\n\t| { id?: string; type: \"get_entries\"; since?: string }\n\t| { id?: string; type: \"get_tree\" }\n\t| { id?: string; type: \"get_last_assistant_text\" }\n\t| { id?: string; type: \"set_session_name\"; name: string }\n\t| { id?: string; type: \"import_jsonl\"; inputPath: string; cwdOverride?: string }\n\n\t// Messages\n\t| { id?: string; type: \"get_messages\" }\n\n\t// Commands and loaded runtime surfaces\n\t| { id?: string; type: \"get_commands\" }\n\t| { id?: string; type: \"get_loaded_surfaces\" }\n\t| { id?: string; type: \"extension_request\"; name: string; data?: unknown }\n\n\t// Auth (task 13) is additive. get_auth_providers, login_api_key and logout\n\t// answer synchronously. login_start responds immediately (flow-started) and\n\t// completion is delivered via auth_login_url / auth_login_end EVENTS, because\n\t// an interactive OAuth round-trip cannot fit the 30s request timeout.\n\t| { id?: string; type: \"get_auth_providers\" }\n\t| { id?: string; type: \"login_start\"; provider: string }\n\t| { id?: string; type: \"login_cancel\"; provider: string }\n\t| { id?: string; type: \"login_api_key\"; provider: string; key: string }\n\t| { id?: string; type: \"logout\"; provider: string }\n\n\t// Provider accounts (task 13) are additive. The desktop consumer contract\n\t// lives in ../omo-desktop-app/packages/contracts/src/rpc.ts and is updated separately.\n\t| { id?: string; type: \"get_provider_accounts\"; provider: string }\n\t| { id?: string; type: \"account_pin\"; provider: string; name: string | null }\n\t| { id?: string; type: \"account_remove\"; provider: string; name: string }\n\t| { id?: string; type: \"set_client_info\"; width: number; capabilities?: string[] };\n\n/** Stable multi-session protocol error codes. */\nexport const RPC_ERROR_UNKNOWN_SESSION = \"unknown_session\";\nexport const RPC_ERROR_SESSION_CLOSING = \"session_closing\";\nexport const RPC_ERROR_SESSION_PATH_IN_USE = \"session_path_in_use\";\nexport const RPC_ERROR_MISSING_SESSION_ID = \"missing_session_id\";\nexport const RPC_ERROR_MULTI_SESSION_DISABLED = \"multi_session_disabled\";\nexport const RPC_ERROR_INVALID_PATH = \"invalid_path\";\nexport const RPC_ERROR_OPEN_FAILED = \"open_failed\";\nexport const RPC_ERROR_TOO_MANY_SESSIONS = \"too_many_sessions\";\n\nexport type RpcErrorCode =\n\t| typeof RPC_ERROR_UNKNOWN_SESSION\n\t| typeof RPC_ERROR_SESSION_CLOSING\n\t| typeof RPC_ERROR_SESSION_PATH_IN_USE\n\t| typeof RPC_ERROR_MISSING_SESSION_ID\n\t| typeof RPC_ERROR_MULTI_SESSION_DISABLED\n\t| typeof RPC_ERROR_INVALID_PATH\n\t| typeof RPC_ERROR_OPEN_FAILED\n\t| typeof RPC_ERROR_TOO_MANY_SESSIONS;\n\n/** Every established command accepts an additive routing envelope. */\nexport type RpcCommand =\n\t| (RpcSessionCommand & { sessionId?: string })\n\t| { id?: string; type: \"get_protocol_info\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"open_session\";\n\t\t\tsessionPath?: string;\n\t\t\tcwd?: string;\n\t\t\tprovider?: string;\n\t\t\tmodelId?: string;\n\t\t\tthinkingLevel?: ThinkingLevel;\n\t\t\tpermissionPreset?: string;\n\t }\n\t| { id?: string; type: \"close_session\"; sessionId: string }\n\t| { id?: string; type: \"list_sessions\" };\n\n// ============================================================================\n// Auth provider info (get_auth_providers response)\n// ============================================================================\n\n/** One provider row for the /login and /logout selectors. */\nexport interface RpcAuthProvider {\n\t/** Provider id (e.g. \"anthropic\", \"openai\"). */\n\tid: string;\n\t/** Human-readable display name. */\n\tname: string;\n\t/** How this provider authenticates. */\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Auth status without exposing or refreshing any credential. */\n\tstatus: RpcAuthStatus;\n}\n\n/** Auth status mirror (no credential values), from getProviderAuthStatus. */\nexport interface RpcAuthStatus {\n\tconfigured: boolean;\n\tsource?:\n\t\t| \"stored\"\n\t\t| \"runtime\"\n\t\t| \"environment\"\n\t\t| \"fallback\"\n\t\t| \"models_json_key\"\n\t\t| \"models_json_command\"\n\t\t| \"models_json_headers\"\n\t\t| \"extension_headers\";\n\tlabel?: string;\n}\n\n/** Account-slot metadata safe to send to desktop clients. */\nexport interface RpcProviderAccount {\n\tname: string;\n\tsource: \"login\" | \"import\" | \"env\";\n\tblocked: boolean;\n\tpinned: boolean;\n}\n\n// ============================================================================\n// RPC Slash Command (for get_commands response)\n// ============================================================================\n\n/** One extension module loaded by the session resource loader. */\nexport interface RpcLoadedExtension {\n\tname: string;\n\tpath: string;\n\tsourceInfo: SourceInfo;\n\tenabled: boolean;\n}\n\nexport type RpcMcpServerStatus =\n\t| \"enabled\"\n\t| \"disabled\"\n\t| \"untrusted\"\n\t| \"idle\"\n\t| \"connecting\"\n\t| \"connected\"\n\t| \"degraded\"\n\t| \"suspended\"\n\t| \"needs_auth\"\n\t| \"needs_client_registration\";\n\n/** Runtime MCP server state projected from the session-owned MCP service. */\nexport interface RpcLoadedMcpServer {\n\tname: string;\n\ttoolCount: number;\n\tstatus: RpcMcpServerStatus;\n\tauthStatus: \"unsupported\" | \"notLoggedIn\" | \"bearerToken\" | \"oAuth\";\n}\n\n// ============================================================================\n// RPC State\n// ============================================================================\n\nexport interface RpcSessionModelEntry {\n\tmodel: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tthinkingSelection?: ThinkingSelection;\n\tserviceTier?: ServiceTier;\n}\n\nexport interface RpcSessionState {\n\tmodel?: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\t/**\n\t * Explicit selector provenance for `thinkingLevel`, absent for SDK-defaulted\n\t * effective levels. An attached client cannot distinguish \"the user chose high\"\n\t * from \"high is simply the effective level\" without it.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n\t/**\n\t * Abort owner of the most recent aborted turn, or the in-flight one while it is\n\t * still settling. Retained after settle: the live session getter is transient, so a\n\t * client that snapshots state after the turn ends would otherwise see nothing and\n\t * fall back to generic wording instead of \"Operation aborted\".\n\t */\n\tlastAbortSource?: AgentAbortSource;\n\t/** Service tier the session resolved for the active model, if any. */\n\tserviceTier?: ServiceTier;\n\t/** True when the active model is served at the priority (\"fast\") tier. */\n\tfastMode: boolean;\n\tisStreaming: boolean;\n\tisCompacting: boolean;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\tsessionFile?: string;\n\tsessionId: string;\n\tsessionName?: string;\n\tcwd: string;\n\t/** Whether project-scoped settings and resources are trusted by the host. */\n\tprojectTrusted: boolean;\n\t/** Authoritative entries for setup-only sessions whose deferred file does not exist yet. */\n\tentries?: SessionEntry[];\n\tfavoriteModels: RpcSessionModelEntry[];\n\tscopedModels: RpcSessionModelEntry[];\n\tsteering: string[];\n\tfollowUp: string[];\n\tordered: Array<{ text: string; mode: \"steer\" | \"followUp\"; enqueueOrder: number }>;\n\tautoCompactionEnabled: boolean;\n\tmessageCount: number;\n\tpendingMessageCount: number;\n\tusageTotals: UsageTotals;\n\tcontextUsage?: ContextUsage;\n\tretryAttempt: number;\n\tisBashRunning: boolean;\n}\n\n// ============================================================================\n// RPC Responses (stdout)\n// ============================================================================\n\n// Success responses with data\nexport type RpcResponse =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_protocol_info\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tprotocolVersion: 1;\n\t\t\t\tserverVersion: string;\n\t\t\t\tcapabilities: string[];\n\t\t\t\tmode: \"classic\" | \"multi\";\n\t\t\t};\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"open_session\";\n\t\t\tsuccess: true;\n\t\t\tdata: { sessionId: string; state: RpcSessionState; attached?: boolean };\n\t }\n\t| { id?: string; type: \"response\"; command: \"close_session\"; success: true; data: Record<string, never> }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"list_sessions\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tsessions: Array<{\n\t\t\t\t\tsessionId: string;\n\t\t\t\t\tdurableSessionId?: string;\n\t\t\t\t\tsessionPath?: string;\n\t\t\t\t\tcwd: string;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tstatus: \"opening\" | \"open\" | \"closing\" | \"closed\";\n\t\t\t\t}>;\n\t\t\t};\n\t }\n\t// Prompting (async - events follow)\n\t// data.disposition reports how the host disposed the prompt (started/queued/handled)\n\t// so proxied optimistic-echo contracts resolve exactly like the local path; older\n\t// hosts omit it and clients must degrade to canonical-only rendering.\n\t| { id?: string; type: \"response\"; command: \"prompt\"; success: true; data?: { disposition?: PromptDisposition } }\n\t| { id?: string; type: \"response\"; command: \"send_custom_message\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"append_user_message\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"append_session_entry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"steer\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"follow_up\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_compaction\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"reload\"; success: true; data: { cancelled: boolean; reason?: string } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"check_reload_veto\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; reason?: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"clear_queue\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tsteering: string[];\n\t\t\t\tfollowUp: string[];\n\t\t\t\tordered: Array<{ text: string; mode: \"steer\" | \"followUp\"; enqueueOrder: number }>;\n\t\t\t};\n\t }\n\t| { id?: string; type: \"response\"; command: \"new_session\"; success: true; data: { cancelled: boolean } }\n\n\t// State\n\t| { id?: string; type: \"response\"; command: \"get_state\"; success: true; data: RpcSessionState }\n\n\t// Model\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: Model<any> & { systemPromptName?: string };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_favorite_models\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_scoped_models\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: { model: Model<any>; thinkingLevel: ThinkingLevel; isScoped: boolean } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: { models: Array<Model<any> & { supportedThinkingLevels: ThinkingLevel[] }> };\n\t }\n\n\t// Thinking\n\t| { id?: string; type: \"response\"; command: \"set_thinking_level\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_thinking_levels\";\n\t\t\tsuccess: true;\n\t\t\tdata: { levels: ThinkingLevel[] };\n\t }\n\n\t// Fast mode\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_fast_mode\";\n\t\t\tsuccess: true;\n\t\t\tdata: { enabled: boolean; serviceTier: ServiceTier; provider: string; modelId: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fast_mode\";\n\t\t\tsuccess: true;\n\t\t\tdata: { enabled: boolean; serviceTier: ServiceTier | null };\n\t }\n\n\t// Queue modes\n\t| { id?: string; type: \"response\"; command: \"set_steering_mode\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_follow_up_mode\"; success: true }\n\n\t// Compaction\n\t| { id?: string; type: \"response\"; command: \"compact\"; success: true; data: CompactionResult }\n\t| { id?: string; type: \"response\"; command: \"set_auto_compaction\"; success: true }\n\n\t// Retry\n\t| { id?: string; type: \"response\"; command: \"set_auto_retry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_retry\"; success: true }\n\n\t// Bash\n\t| { id?: string; type: \"response\"; command: \"bash\"; success: true; data: BashResult }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"navigate_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; editorText?: string; aborted?: boolean; summaryEntry?: unknown };\n\t }\n\t| { id?: string; type: \"response\"; command: \"abort_bash\"; success: true }\n\n\t// Session\n\t| { id?: string; type: \"response\"; command: \"get_session_stats\"; success: true; data: SessionStats }\n\t| { id?: string; type: \"response\"; command: \"export_html\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"export_jsonl\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"switch_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"fork\"; success: true; data: { text: string; cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"clone\"; success: true; data: { cancelled: boolean } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fork_messages\";\n\t\t\tsuccess: true;\n\t\t\tdata: { messages: Array<{ entryId: string; text: string }> };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_entries\";\n\t\t\tsuccess: true;\n\t\t\tdata: { entries: SessionEntry[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { tree: SessionTreeNode[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_last_assistant_text\";\n\t\t\tsuccess: true;\n\t\t\tdata: { text: string | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_session_name\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"import_jsonl\"; success: true; data: { cancelled: boolean } }\n\n\t// Messages\n\t| { id?: string; type: \"response\"; command: \"get_messages\"; success: true; data: { messages: AgentMessage[] } }\n\n\t// Commands and loaded runtime surfaces\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_commands\";\n\t\t\tsuccess: true;\n\t\t\tdata: { commands: RpcSlashCommand[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_loaded_surfaces\";\n\t\t\tsuccess: true;\n\t\t\tdata: { extensions: RpcLoadedExtension[]; mcpServers: RpcLoadedMcpServer[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"extension_request\";\n\t\t\tsuccess: true;\n\t\t\tdata: unknown;\n\t }\n\n\t// Auth (task 13)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_auth_providers\";\n\t\t\tsuccess: true;\n\t\t\tdata: { providers: RpcAuthProvider[] };\n\t }\n\t// login_start returns immediately: success:true means the flow has started.\n\t// The URL and completion arrive as auth_login_url / auth_login_end events.\n\t| { id?: string; type: \"response\"; command: \"login_start\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"login_cancel\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"login_api_key\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"logout\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_provider_accounts\";\n\t\t\tsuccess: true;\n\t\t\tdata: { accounts: RpcProviderAccount[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"account_pin\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"account_remove\"; success: true }\n\n\t// Error response (any command can fail)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: string;\n\t\t\tsuccess: false;\n\t\t\terror: string;\n\t\t\terrorCode?: string;\n\t\t\terrorData?: unknown;\n\t };\n\n// ============================================================================\n// Extension UI Events (stdout)\n// ============================================================================\n\n/** Emitted when an extension needs user input */\nexport type RpcExtensionUIRequest =\n\t| { type: \"extension_ui_request\"; id: string; method: \"select\"; title: string; options: string[]; timeout?: number }\n\t| { type: \"extension_ui_request\"; id: string; method: \"confirm\"; title: string; message: string; timeout?: number }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"input\";\n\t\t\ttitle: string;\n\t\t\tplaceholder?: string;\n\t\t\ttimeout?: number;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"editor\"; title: string; prefill?: string }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"notify\";\n\t\t\tmessage: string;\n\t\t\tnotifyType?: \"info\" | \"warning\" | \"error\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setStatus\";\n\t\t\tstatusKey: string;\n\t\t\tstatusText: string | undefined;\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setWidget\";\n\t\t\twidgetKey: string;\n\t\t\twidgetLines: string[] | undefined;\n\t\t\twidgetPlacement?: \"aboveEditor\" | \"belowEditor\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setHeader\" | \"setFooter\";\n\t\t\twidgetLines: string[] | undefined;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"setTitle\"; title: string }\n\t| { type: \"extension_ui_request\"; id: string; method: \"set_editor_text\"; text: string }\n\t// Additive (task 13/14): emitted ONLY when the client advertised the\n\t// \"custom_unsupported\" capability. ctx.ui.custom cannot render a third-party\n\t// component in RPC mode, so a flagged client gets this notice before custom()\n\t// returns undefined. Default clients never see it (byte-identical behavior).\n\t| { type: \"extension_ui_request\"; id: string; method: \"custom_unsupported\"; extensionName: string };\n\nexport type RpcExtensionEvent = {\n\ttype: \"extension_event\";\n\tname: string;\n\tdata: unknown;\n};\n\n// ============================================================================\n// Extension UI Commands (stdin)\n// ============================================================================\n\n/** Response to an extension UI request */\nexport type RpcExtensionUIResponse =\n\t| { type: \"extension_ui_response\"; id: string; value: string }\n\t| { type: \"extension_ui_response\"; id: string; confirmed: boolean }\n\t| { type: \"extension_ui_response\"; id: string; cancelled: true };\n\n/** Emitted when the effective session thinking level changes. */\nexport interface RpcThinkingLevelChangedEvent {\n\ttype: \"thinking_level_changed\";\n\tlevel: ThinkingLevel;\n\t/**\n\t * Selector provenance in force after the change; absent when the level is an\n\t * SDK-defaulted effective level rather than an explicit choice. Additive: an old\n\t * client that does not know the field ignores it.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n}\n\nexport interface RpcHighReasoningWarningEvent {\n\ttype: \"high_reasoning_warning\";\n\tmodelId: string;\n\tprovider: string;\n\tthinkingLevel: ThinkingLevel;\n}\n\n/** Emitted after explicit skill tokens are expanded for a user-authored request. */\nexport interface RpcSkillInvocationEvent {\n\ttype: \"skill_invocation\";\n\tskills: readonly {\n\t\tname: string;\n\t\tpath: string;\n\t\tsyntax: \"dollar\" | \"slash\";\n\t}[];\n}\n\n/** Emitted when startup or reload selects an existing settings file. */\nexport interface RpcSettingsSourceSelectedEvent {\n\ttype: \"settings_source_selected\";\n\tpath: string;\n\tformat: \"jsonc\" | \"json\";\n\treason: \"explicit-jsonc\" | \"json-only\";\n\tscope: \"global\" | \"project\";\n}\n\n/**\n * Emitted after the session's active model changed, with the thinking level in force AFTER\n * the switch (per-model memory, a favorite's pinned level, or the clamped previous level).\n *\n * Clients that tracked the model by inferring it from `entry_appended` can consume this\n * instead. Additive: an old client that does not know the type filters it out.\n */\nexport interface RpcModelChangedEvent {\n\ttype: \"model_changed\";\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\t/** Why the model changed: \"set\", \"cycle\", \"restore\", \"fallback\", or \"fallback-revert\". */\n\tsource: string;\n\t/** Selector provenance for `thinkingLevel` after the switch, when one was explicit. */\n\tthinkingSelection?: ThinkingSelection;\n}\n\n/** Emitted when the effective service tier or fast-mode state of the session changes. */\nexport interface RpcServiceTierChangedEvent {\n\ttype: \"service_tier_changed\";\n\ttier?: ServiceTier;\n\tfastMode: boolean;\n}\n/**\n * Emitted after the host swapped the live session behind this connection (new session,\n * fork, or switch), carrying the new authoritative identity.\n *\n * A replacement can be initiated by ANY attached client. Without this event the other\n * attached clients keep their stale identity and keep routing replacement-dependent\n * actions at the session that no longer exists. Additive: an old client that does not\n * know the type filters it out.\n */\nexport interface RpcSessionReplacedEvent {\n\ttype: \"session_replaced\";\n\t/**\n\t * Durable session id of the session now bound to this connection.\n\t *\n\t * Deliberately NOT `sessionId`: top-level `sessionId` is reserved for the\n\t * per-connection routing handle that multi-session hosts tag every record\n\t * with, and that tag is applied last - it would overwrite this value and\n\t * leave the event carrying no identity at all.\n\t */\n\tdurableSessionId: string;\n\t/** Session file backing the new session, absent for a deferred setup-only session. */\n\tsessionFile?: string;\n\tcwd: string;\n\tsessionName?: string;\n}\n\n/** Emitted after the loaded skill, extension, or MCP inventory changes. */\nexport interface RpcLoadedSurfacesChangedEvent {\n\ttype: \"loaded_surfaces_changed\";\n}\n\n/** Emitted after an account is added, removed, pinned, or blocked by refresh failure. */\nexport interface RpcAuthAccountsChangedEvent {\n\ttype: \"auth_accounts_changed\";\n\tprovider: string;\n}\n\n/** Emitted when the SDK failover engine advances to a different account slot. */\nexport interface RpcAccountFailoverEvent {\n\ttype: \"account_failover\";\n\tprovider: string;\n\tfrom: string;\n\tto: string;\n\treason: string;\n}\n"]}
1
+ {"version":3,"file":"rpc-types.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8JH,iDAAiD;AACjD,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAC3D,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AACnE,MAAM,CAAC,MAAM,4BAA4B,GAAG,oBAAoB,CAAC;AACjE,MAAM,CAAC,MAAM,gCAAgC,GAAG,wBAAwB,CAAC;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,2BAA2B,GAAG,mBAAmB,CAAC;AAC/D,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC","sourcesContent":["/**\n * RPC protocol types for headless operation.\n *\n * Commands are sent as JSON lines on stdin.\n * Responses and events are emitted as JSON lines on stdout.\n */\n\nimport type { AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, Model, ThinkingSelection } from \"@earendil-works/pi-ai\";\nimport type { AgentAbortSource } from \"../../core/agent-abort-provenance.ts\";\nimport type { PromptDisposition, SessionStats } from \"../../core/agent-session.ts\";\nimport type { BashResult } from \"../../core/bash-executor.ts\";\nimport type { CompactionResult } from \"../../core/compaction/index.ts\";\nimport type { ServiceTier } from \"../../core/extensions/builtin/service-tier.ts\";\nimport type { ContextUsage } from \"../../core/extensions/types.ts\";\nimport type { SessionEntry, SessionTreeNode, UsageTotals } from \"../../core/session-manager.ts\";\nimport type { SourceInfo } from \"../../core/source-info.ts\";\nimport type { RpcSlashCommand } from \"./rpc-command-surface.ts\";\n\nexport type { RpcCommandInvocationEvent } from \"./rpc-command-invocation.ts\";\nexport type { RpcCommandsChangedEvent, RpcSlashCommand } from \"./rpc-command-surface.ts\";\n\n// ============================================================================\n// RPC Commands (stdin)\n// ============================================================================\n\ntype RpcSessionCommand =\n\t// Prompting\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"prompt\";\n\t\t\tmessage: string;\n\t\t\timages?: ImageContent[];\n\t\t\tstreamingBehavior?: \"steer\" | \"followUp\";\n\t\t\tthinkingLevel?: ThinkingLevel;\n\t\t\tsessionTitlePrompt?: string | false;\n\t\t\texpandPromptTemplates?: boolean;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"send_custom_message\";\n\t\t\tcustomType: string;\n\t\t\tcontent: unknown;\n\t\t\tdisplay: boolean;\n\t\t\tdetails?: unknown;\n\t\t\ttriggerTurn?: boolean;\n\t\t\tdeliverAs?: \"steer\" | \"followUp\" | \"nextTurn\";\n\t }\n\t| { id?: string; type: \"append_user_message\"; content: unknown }\n\t| { id?: string; type: \"append_session_entry\"; entry: SessionEntry }\n\t| { id?: string; type: \"steer\"; message: string; images?: ImageContent[]; enqueueOrder?: number }\n\t| { id?: string; type: \"follow_up\"; message: string; images?: ImageContent[]; enqueueOrder?: number }\n\t| { id?: string; type: \"abort\" }\n\t| { id?: string; type: \"abort_compaction\" }\n\t| { id?: string; type: \"reload\" }\n\t| { id?: string; type: \"check_reload_veto\" }\n\t| { id?: string; type: \"clear_queue\"; abortWillFollow?: boolean }\n\t| { id?: string; type: \"get_steering_messages\" }\n\t| { id?: string; type: \"get_follow_up_messages\" }\n\t| { id?: string; type: \"abort_branch_summary\" }\n\t| { id?: string; type: \"new_session\"; parentSession?: string }\n\n\t// State\n\t| { id?: string; type: \"get_state\" }\n\n\t// Model\n\t| { id?: string; type: \"set_model\"; provider: string; modelId: string }\n\t| { id?: string; type: \"set_favorite_models\"; models: RpcSessionModelEntry[] }\n\t| { id?: string; type: \"set_scoped_models\"; models: RpcSessionModelEntry[] }\n\t| { id?: string; type: \"cycle_model\"; direction?: \"forward\" | \"backward\" }\n\t| { id?: string; type: \"get_available_models\" }\n\n\t// Thinking\n\t| { id?: string; type: \"set_thinking_level\"; level: ThinkingLevel; scope?: \"turn\" }\n\t| { id?: string; type: \"cycle_thinking_level\" }\n\t| { id?: string; type: \"get_available_thinking_levels\" }\n\n\t// Fast mode (OpenAI Codex priority service tier)\n\t| { id?: string; type: \"set_fast_mode\"; enabled: boolean }\n\t| { id?: string; type: \"get_fast_mode\" }\n\n\t// Queue modes\n\t| { id?: string; type: \"set_steering_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\t| { id?: string; type: \"set_follow_up_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\n\t// Compaction\n\t| { id?: string; type: \"compact\"; customInstructions?: string }\n\t| { id?: string; type: \"set_auto_compaction\"; enabled: boolean }\n\n\t// Retry\n\t| { id?: string; type: \"set_auto_retry\"; enabled: boolean }\n\t| { id?: string; type: \"abort_retry\" }\n\n\t// Bash\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"bash\";\n\t\t\tcommand: string;\n\t\t\t/** Identifies output chunks to the requesting client. */\n\t\t\tbashId?: string;\n\t\t\texcludeFromContext?: boolean;\n\t\t\texecutionId?: string;\n\t\t\toperations?: Record<string, unknown>;\n\t }\n\t| { id?: string; type: \"record_bash_result\"; command: string; result: BashResult; excludeFromContext?: boolean }\n\t| { id?: string; type: \"abort_bash\" }\n\t| { id?: string; type: \"cleanup_bash_output\"; path: string }\n\t| { id?: string; type: \"set_label\"; entryId: string; label?: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"navigate_tree\";\n\t\t\ttargetId: string;\n\t\t\tsummarize?: boolean;\n\t\t\tcustomInstructions?: string;\n\t\t\treplaceInstructions?: boolean;\n\t\t\tlabel?: string;\n\t }\n\n\t// Session\n\t| { id?: string; type: \"get_session_stats\" }\n\t| { id?: string; type: \"export_html\"; outputPath?: string; themeName?: string }\n\t| { id?: string; type: \"export_jsonl\"; outputPath?: string }\n\t| { id?: string; type: \"switch_session\"; sessionPath: string; cwdOverride?: string }\n\t| { id?: string; type: \"fork\"; entryId: string; position?: \"before\" | \"at\" }\n\t| { id?: string; type: \"clone\" }\n\t| { id?: string; type: \"get_fork_messages\" }\n\t| { id?: string; type: \"get_entries\"; since?: string }\n\t| { id?: string; type: \"get_tree\" }\n\t| { id?: string; type: \"get_last_assistant_text\" }\n\t| { id?: string; type: \"set_session_name\"; name: string }\n\t| { id?: string; type: \"import_jsonl\"; inputPath: string; cwdOverride?: string }\n\n\t// Messages\n\t| { id?: string; type: \"get_messages\" }\n\t/**\n\t * Fetch one media block a `media_placeholders` client received as an `image_ref`\n\t * stub. `contentIndex` indexes the toolResult's `content` array and must point at\n\t * an image block; anything else answers `media_not_found`.\n\t */\n\t| { id?: string; type: \"get_media\"; toolCallId: string; contentIndex: number }\n\n\t// Commands and loaded runtime surfaces\n\t| { id?: string; type: \"get_commands\" }\n\t| { id?: string; type: \"get_loaded_surfaces\" }\n\t| { id?: string; type: \"extension_request\"; name: string; data?: unknown }\n\n\t// Auth (task 13) is additive. get_auth_providers, login_api_key and logout\n\t// answer synchronously. login_start responds immediately (flow-started) and\n\t// completion is delivered via auth_login_url / auth_login_end EVENTS, because\n\t// an interactive OAuth round-trip cannot fit the 30s request timeout.\n\t| { id?: string; type: \"get_auth_providers\" }\n\t| { id?: string; type: \"login_start\"; provider: string }\n\t| { id?: string; type: \"login_cancel\"; provider: string }\n\t| { id?: string; type: \"login_api_key\"; provider: string; key: string }\n\t| { id?: string; type: \"logout\"; provider: string }\n\n\t// Provider accounts (task 13) are additive. The desktop consumer contract\n\t// lives in ../omo-desktop-app/packages/contracts/src/rpc.ts and is updated separately.\n\t| { id?: string; type: \"get_provider_accounts\"; provider: string }\n\t| { id?: string; type: \"account_pin\"; provider: string; name: string | null }\n\t| { id?: string; type: \"account_remove\"; provider: string; name: string }\n\t| { id?: string; type: \"set_client_info\"; width: number; capabilities?: string[] };\n\n/** Stable multi-session protocol error codes. */\nexport const RPC_ERROR_UNKNOWN_SESSION = \"unknown_session\";\nexport const RPC_ERROR_SESSION_CLOSING = \"session_closing\";\nexport const RPC_ERROR_SESSION_PATH_IN_USE = \"session_path_in_use\";\nexport const RPC_ERROR_MISSING_SESSION_ID = \"missing_session_id\";\nexport const RPC_ERROR_MULTI_SESSION_DISABLED = \"multi_session_disabled\";\nexport const RPC_ERROR_INVALID_PATH = \"invalid_path\";\nexport const RPC_ERROR_OPEN_FAILED = \"open_failed\";\nexport const RPC_ERROR_TOO_MANY_SESSIONS = \"too_many_sessions\";\nexport const RPC_ERROR_MEDIA_NOT_FOUND = \"media_not_found\";\n\nexport type RpcErrorCode =\n\t| typeof RPC_ERROR_UNKNOWN_SESSION\n\t| typeof RPC_ERROR_SESSION_CLOSING\n\t| typeof RPC_ERROR_SESSION_PATH_IN_USE\n\t| typeof RPC_ERROR_MISSING_SESSION_ID\n\t| typeof RPC_ERROR_MULTI_SESSION_DISABLED\n\t| typeof RPC_ERROR_INVALID_PATH\n\t| typeof RPC_ERROR_OPEN_FAILED\n\t| typeof RPC_ERROR_TOO_MANY_SESSIONS\n\t| typeof RPC_ERROR_MEDIA_NOT_FOUND;\n\n/** Every established command accepts an additive routing envelope. */\nexport type RpcCommand =\n\t| (RpcSessionCommand & { sessionId?: string })\n\t| { id?: string; type: \"get_protocol_info\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"open_session\";\n\t\t\tsessionPath?: string;\n\t\t\tcwd?: string;\n\t\t\tprovider?: string;\n\t\t\tmodelId?: string;\n\t\t\tthinkingLevel?: ThinkingLevel;\n\t\t\tpermissionPreset?: string;\n\t }\n\t| { id?: string; type: \"close_session\"; sessionId: string }\n\t| { id?: string; type: \"list_sessions\" };\n\n// ============================================================================\n// Auth provider info (get_auth_providers response)\n// ============================================================================\n\n/** One provider row for the /login and /logout selectors. */\nexport interface RpcAuthProvider {\n\t/** Provider id (e.g. \"anthropic\", \"openai\"). */\n\tid: string;\n\t/** Human-readable display name. */\n\tname: string;\n\t/** How this provider authenticates. */\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Auth status without exposing or refreshing any credential. */\n\tstatus: RpcAuthStatus;\n}\n\n/** Auth status mirror (no credential values), from getProviderAuthStatus. */\nexport interface RpcAuthStatus {\n\tconfigured: boolean;\n\tsource?:\n\t\t| \"stored\"\n\t\t| \"runtime\"\n\t\t| \"environment\"\n\t\t| \"fallback\"\n\t\t| \"models_json_key\"\n\t\t| \"models_json_command\"\n\t\t| \"models_json_headers\"\n\t\t| \"extension_headers\";\n\tlabel?: string;\n}\n\n/** Account-slot metadata safe to send to desktop clients. */\nexport interface RpcProviderAccount {\n\tname: string;\n\tsource: \"login\" | \"import\" | \"env\";\n\tblocked: boolean;\n\tpinned: boolean;\n}\n\n// ============================================================================\n// RPC Slash Command (for get_commands response)\n// ============================================================================\n\n/** One extension module loaded by the session resource loader. */\nexport interface RpcLoadedExtension {\n\tname: string;\n\tpath: string;\n\tsourceInfo: SourceInfo;\n\tenabled: boolean;\n}\n\nexport type RpcMcpServerStatus =\n\t| \"enabled\"\n\t| \"disabled\"\n\t| \"untrusted\"\n\t| \"idle\"\n\t| \"connecting\"\n\t| \"connected\"\n\t| \"degraded\"\n\t| \"suspended\"\n\t| \"needs_auth\"\n\t| \"needs_client_registration\";\n\n/** Runtime MCP server state projected from the session-owned MCP service. */\nexport interface RpcLoadedMcpServer {\n\tname: string;\n\ttoolCount: number;\n\tstatus: RpcMcpServerStatus;\n\tauthStatus: \"unsupported\" | \"notLoggedIn\" | \"bearerToken\" | \"oAuth\";\n}\n\n// ============================================================================\n// RPC State\n// ============================================================================\n\nexport interface RpcSessionModelEntry {\n\tmodel: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tthinkingSelection?: ThinkingSelection;\n\tserviceTier?: ServiceTier;\n}\n\nexport interface RpcSessionState {\n\tmodel?: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\t/**\n\t * Explicit selector provenance for `thinkingLevel`, absent for SDK-defaulted\n\t * effective levels. An attached client cannot distinguish \"the user chose high\"\n\t * from \"high is simply the effective level\" without it.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n\t/**\n\t * Abort owner of the most recent aborted turn, or the in-flight one while it is\n\t * still settling. Retained after settle: the live session getter is transient, so a\n\t * client that snapshots state after the turn ends would otherwise see nothing and\n\t * fall back to generic wording instead of \"Operation aborted\".\n\t */\n\tlastAbortSource?: AgentAbortSource;\n\t/** Service tier the session resolved for the active model, if any. */\n\tserviceTier?: ServiceTier;\n\t/** True when the active model is served at the priority (\"fast\") tier. */\n\tfastMode: boolean;\n\tisStreaming: boolean;\n\tisCompacting: boolean;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\tsessionFile?: string;\n\tsessionId: string;\n\tsessionName?: string;\n\tcwd: string;\n\t/** Whether project-scoped settings and resources are trusted by the host. */\n\tprojectTrusted: boolean;\n\t/** Authoritative entries for setup-only sessions whose deferred file does not exist yet. */\n\tentries?: SessionEntry[];\n\tfavoriteModels: RpcSessionModelEntry[];\n\tscopedModels: RpcSessionModelEntry[];\n\tsteering: string[];\n\tfollowUp: string[];\n\tordered: Array<{ text: string; mode: \"steer\" | \"followUp\"; enqueueOrder: number }>;\n\tautoCompactionEnabled: boolean;\n\tmessageCount: number;\n\tpendingMessageCount: number;\n\tusageTotals: UsageTotals;\n\tcontextUsage?: ContextUsage;\n\tretryAttempt: number;\n\tisBashRunning: boolean;\n}\n\n// ============================================================================\n// RPC Responses (stdout)\n// ============================================================================\n\n// Success responses with data\nexport type RpcResponse =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_protocol_info\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tprotocolVersion: 1;\n\t\t\t\tserverVersion: string;\n\t\t\t\tcapabilities: string[];\n\t\t\t\tmode: \"classic\" | \"multi\";\n\t\t\t};\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"open_session\";\n\t\t\tsuccess: true;\n\t\t\tdata: { sessionId: string; state: RpcSessionState; attached?: boolean };\n\t }\n\t| { id?: string; type: \"response\"; command: \"close_session\"; success: true; data: Record<string, never> }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"list_sessions\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tsessions: Array<{\n\t\t\t\t\tsessionId: string;\n\t\t\t\t\tdurableSessionId?: string;\n\t\t\t\t\tsessionPath?: string;\n\t\t\t\t\tcwd: string;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tstatus: \"opening\" | \"open\" | \"closing\" | \"closed\";\n\t\t\t\t}>;\n\t\t\t};\n\t }\n\t// Prompting (async - events follow)\n\t// data.disposition reports how the host disposed the prompt (started/queued/handled)\n\t// so proxied optimistic-echo contracts resolve exactly like the local path; older\n\t// hosts omit it and clients must degrade to canonical-only rendering.\n\t| { id?: string; type: \"response\"; command: \"prompt\"; success: true; data?: { disposition?: PromptDisposition } }\n\t| { id?: string; type: \"response\"; command: \"send_custom_message\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"append_user_message\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"append_session_entry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"steer\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"follow_up\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_compaction\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"reload\"; success: true; data: { cancelled: boolean; reason?: string } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"check_reload_veto\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; reason?: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"clear_queue\";\n\t\t\tsuccess: true;\n\t\t\tdata: {\n\t\t\t\tsteering: string[];\n\t\t\t\tfollowUp: string[];\n\t\t\t\tordered: Array<{ text: string; mode: \"steer\" | \"followUp\"; enqueueOrder: number }>;\n\t\t\t};\n\t }\n\t| { id?: string; type: \"response\"; command: \"new_session\"; success: true; data: { cancelled: boolean } }\n\n\t// State\n\t| { id?: string; type: \"response\"; command: \"get_state\"; success: true; data: RpcSessionState }\n\n\t// Model\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: Model<any> & { systemPromptName?: string };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_favorite_models\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_scoped_models\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: { model: Model<any>; thinkingLevel: ThinkingLevel; isScoped: boolean } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: { models: Array<Model<any> & { supportedThinkingLevels: ThinkingLevel[] }> };\n\t }\n\n\t// Thinking\n\t| { id?: string; type: \"response\"; command: \"set_thinking_level\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_thinking_levels\";\n\t\t\tsuccess: true;\n\t\t\tdata: { levels: ThinkingLevel[] };\n\t }\n\n\t// Fast mode\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_fast_mode\";\n\t\t\tsuccess: true;\n\t\t\tdata: { enabled: boolean; serviceTier: ServiceTier; provider: string; modelId: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fast_mode\";\n\t\t\tsuccess: true;\n\t\t\tdata: { enabled: boolean; serviceTier: ServiceTier | null };\n\t }\n\n\t// Queue modes\n\t| { id?: string; type: \"response\"; command: \"set_steering_mode\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_follow_up_mode\"; success: true }\n\n\t// Compaction\n\t| { id?: string; type: \"response\"; command: \"compact\"; success: true; data: CompactionResult }\n\t| { id?: string; type: \"response\"; command: \"set_auto_compaction\"; success: true }\n\n\t// Retry\n\t| { id?: string; type: \"response\"; command: \"set_auto_retry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_retry\"; success: true }\n\n\t// Bash\n\t| { id?: string; type: \"response\"; command: \"bash\"; success: true; data: BashResult }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"navigate_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; editorText?: string; aborted?: boolean; summaryEntry?: unknown };\n\t }\n\t| { id?: string; type: \"response\"; command: \"abort_bash\"; success: true }\n\n\t// Session\n\t| { id?: string; type: \"response\"; command: \"get_session_stats\"; success: true; data: SessionStats }\n\t| { id?: string; type: \"response\"; command: \"export_html\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"export_jsonl\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"switch_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"fork\"; success: true; data: { text: string; cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"clone\"; success: true; data: { cancelled: boolean } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fork_messages\";\n\t\t\tsuccess: true;\n\t\t\tdata: { messages: Array<{ entryId: string; text: string }> };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_entries\";\n\t\t\tsuccess: true;\n\t\t\tdata: { entries: SessionEntry[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { tree: SessionTreeNode[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_last_assistant_text\";\n\t\t\tsuccess: true;\n\t\t\tdata: { text: string | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_session_name\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"import_jsonl\"; success: true; data: { cancelled: boolean } }\n\n\t// Messages\n\t| { id?: string; type: \"response\"; command: \"get_messages\"; success: true; data: { messages: AgentMessage[] } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_media\";\n\t\t\tsuccess: true;\n\t\t\tdata: { toolCallId: string; contentIndex: number; content: ImageContent };\n\t }\n\n\t// Commands and loaded runtime surfaces\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_commands\";\n\t\t\tsuccess: true;\n\t\t\tdata: { commands: RpcSlashCommand[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_loaded_surfaces\";\n\t\t\tsuccess: true;\n\t\t\tdata: { extensions: RpcLoadedExtension[]; mcpServers: RpcLoadedMcpServer[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"extension_request\";\n\t\t\tsuccess: true;\n\t\t\tdata: unknown;\n\t }\n\n\t// Auth (task 13)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_auth_providers\";\n\t\t\tsuccess: true;\n\t\t\tdata: { providers: RpcAuthProvider[] };\n\t }\n\t// login_start returns immediately: success:true means the flow has started.\n\t// The URL and completion arrive as auth_login_url / auth_login_end events.\n\t| { id?: string; type: \"response\"; command: \"login_start\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"login_cancel\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"login_api_key\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"logout\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_provider_accounts\";\n\t\t\tsuccess: true;\n\t\t\tdata: { accounts: RpcProviderAccount[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"account_pin\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"account_remove\"; success: true }\n\n\t// Error response (any command can fail)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: string;\n\t\t\tsuccess: false;\n\t\t\terror: string;\n\t\t\terrorCode?: string;\n\t\t\terrorData?: unknown;\n\t };\n\n// ============================================================================\n// Extension UI Events (stdout)\n// ============================================================================\n\n/** Emitted when an extension needs user input */\nexport type RpcExtensionUIRequest =\n\t| { type: \"extension_ui_request\"; id: string; method: \"select\"; title: string; options: string[]; timeout?: number }\n\t| { type: \"extension_ui_request\"; id: string; method: \"confirm\"; title: string; message: string; timeout?: number }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"input\";\n\t\t\ttitle: string;\n\t\t\tplaceholder?: string;\n\t\t\ttimeout?: number;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"editor\"; title: string; prefill?: string }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"notify\";\n\t\t\tmessage: string;\n\t\t\tnotifyType?: \"info\" | \"warning\" | \"error\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setStatus\";\n\t\t\tstatusKey: string;\n\t\t\tstatusText: string | undefined;\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setWidget\";\n\t\t\twidgetKey: string;\n\t\t\twidgetLines: string[] | undefined;\n\t\t\twidgetPlacement?: \"aboveEditor\" | \"belowEditor\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setHeader\" | \"setFooter\";\n\t\t\twidgetLines: string[] | undefined;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"setTitle\"; title: string }\n\t| { type: \"extension_ui_request\"; id: string; method: \"set_editor_text\"; text: string }\n\t// Additive (task 13/14): emitted ONLY when the client advertised the\n\t// \"custom_unsupported\" capability. ctx.ui.custom cannot render a third-party\n\t// component in RPC mode, so a flagged client gets this notice before custom()\n\t// returns undefined. Default clients never see it (byte-identical behavior).\n\t| { type: \"extension_ui_request\"; id: string; method: \"custom_unsupported\"; extensionName: string };\n\nexport type RpcExtensionEvent = {\n\ttype: \"extension_event\";\n\tname: string;\n\tdata: unknown;\n};\n\n// ============================================================================\n// Extension UI Commands (stdin)\n// ============================================================================\n\n/** Response to an extension UI request */\nexport type RpcExtensionUIResponse =\n\t| { type: \"extension_ui_response\"; id: string; value: string }\n\t| { type: \"extension_ui_response\"; id: string; confirmed: boolean }\n\t| { type: \"extension_ui_response\"; id: string; cancelled: true };\n\n/** Emitted when the effective session thinking level changes. */\nexport interface RpcThinkingLevelChangedEvent {\n\ttype: \"thinking_level_changed\";\n\tlevel: ThinkingLevel;\n\t/**\n\t * Selector provenance in force after the change; absent when the level is an\n\t * SDK-defaulted effective level rather than an explicit choice. Additive: an old\n\t * client that does not know the field ignores it.\n\t */\n\tthinkingSelection?: ThinkingSelection;\n}\n\nexport interface RpcHighReasoningWarningEvent {\n\ttype: \"high_reasoning_warning\";\n\tmodelId: string;\n\tprovider: string;\n\tthinkingLevel: ThinkingLevel;\n}\n\n/** Emitted after explicit skill tokens are expanded for a user-authored request. */\nexport interface RpcSkillInvocationEvent {\n\ttype: \"skill_invocation\";\n\tskills: readonly {\n\t\tname: string;\n\t\tpath: string;\n\t\tsyntax: \"dollar\" | \"slash\";\n\t}[];\n}\n\n/** Emitted when startup or reload selects an existing settings file. */\nexport interface RpcSettingsSourceSelectedEvent {\n\ttype: \"settings_source_selected\";\n\tpath: string;\n\tformat: \"jsonc\" | \"json\";\n\treason: \"explicit-jsonc\" | \"json-only\";\n\tscope: \"global\" | \"project\";\n}\n\n/**\n * Emitted after the session's active model changed, with the thinking level in force AFTER\n * the switch (per-model memory, a favorite's pinned level, or the clamped previous level).\n *\n * Clients that tracked the model by inferring it from `entry_appended` can consume this\n * instead. Additive: an old client that does not know the type filters it out.\n */\nexport interface RpcModelChangedEvent {\n\ttype: \"model_changed\";\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\t/** Why the model changed: \"set\", \"cycle\", \"restore\", \"fallback\", or \"fallback-revert\". */\n\tsource: string;\n\t/** Selector provenance for `thinkingLevel` after the switch, when one was explicit. */\n\tthinkingSelection?: ThinkingSelection;\n}\n\n/** Emitted when the effective service tier or fast-mode state of the session changes. */\nexport interface RpcServiceTierChangedEvent {\n\ttype: \"service_tier_changed\";\n\ttier?: ServiceTier;\n\tfastMode: boolean;\n}\n/**\n * Emitted after the host swapped the live session behind this connection (new session,\n * fork, or switch), carrying the new authoritative identity.\n *\n * A replacement can be initiated by ANY attached client. Without this event the other\n * attached clients keep their stale identity and keep routing replacement-dependent\n * actions at the session that no longer exists. Additive: an old client that does not\n * know the type filters it out.\n */\nexport interface RpcSessionReplacedEvent {\n\ttype: \"session_replaced\";\n\t/**\n\t * Durable session id of the session now bound to this connection.\n\t *\n\t * Deliberately NOT `sessionId`: top-level `sessionId` is reserved for the\n\t * per-connection routing handle that multi-session hosts tag every record\n\t * with, and that tag is applied last - it would overwrite this value and\n\t * leave the event carrying no identity at all.\n\t */\n\tdurableSessionId: string;\n\t/** Session file backing the new session, absent for a deferred setup-only session. */\n\tsessionFile?: string;\n\tcwd: string;\n\tsessionName?: string;\n}\n\n/** Emitted after the loaded skill, extension, or MCP inventory changes. */\nexport interface RpcLoadedSurfacesChangedEvent {\n\ttype: \"loaded_surfaces_changed\";\n}\n\n/** Emitted after an account is added, removed, pinned, or blocked by refresh failure. */\nexport interface RpcAuthAccountsChangedEvent {\n\ttype: \"auth_accounts_changed\";\n\tprovider: string;\n}\n\n/** Emitted when the SDK failover engine advances to a different account slot. */\nexport interface RpcAccountFailoverEvent {\n\ttype: \"account_failover\";\n\tprovider: string;\n\tfrom: string;\n\tto: string;\n\treason: string;\n}\n"]}
@@ -41,6 +41,7 @@ export declare class SessionCommandRouter {
41
41
  private readonly connectionOptions;
42
42
  private readonly widths;
43
43
  private readonly pendingCapabilities;
44
+ private readonly finalizations;
44
45
  private readonly idleNow;
45
46
  private readonly idleEvictionMs;
46
47
  private readonly emptyExitMs;
@@ -89,7 +90,28 @@ export declare class SessionCommandRouter {
89
90
  * and their event stream.
90
91
  */
91
92
  private releaseOwnedSession;
93
+ /**
94
+ * Releases one attachment (or every attachment when draining) and reports
95
+ * whether this caller became the finalizer. The join token is installed inside
96
+ * the registry callback, before any await, so a close that lands between the
97
+ * claim and finalizeClose() always finds a token to wait on instead of
98
+ * answering ahead of the terminal records.
99
+ */
100
+ private claimClose;
101
+ /** claimClose() for lifecycle paths that treat a lost race as "nothing to do". */
102
+ private tryClaimClose;
92
103
  private close;
104
+ /** Detaches the closing connection's UI/width state; a rerender failure must not abort the close. */
105
+ private releaseOwnerAttachment;
106
+ /**
107
+ * Runs the finalizer side of a close for a handle whose beginClose() made this
108
+ * caller the owner: dispose the binding, complete the registry teardown, emit
109
+ * the terminal records, then release joiners. Every step is guarded so the join
110
+ * token always resolves and a failing binding yields one logged line, never a
111
+ * second response or an escaped rejection.
112
+ */
113
+ private finalizeClose;
114
+ private createFinalization;
93
115
  private code;
94
116
  }
95
117
  //# sourceMappingURL=session-command-router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-command-router.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-command-router.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO9D,OAAO,EAAE,uBAAuB,EAA0B,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAGX,uBAAuB,EACvB,kBAAkB,EAClB,MAAM,uBAAuB,CAAC;AAK/B,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,OAAO,uBAAuB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,wGAAwG;IACxG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;CACjC;AAMD,uFAAuF;AACvF,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,gFAAgF;IAChF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA0C;IAC/E,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyC;IAC3E,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGvB;IACF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA+B;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAgB;IAClD,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,UAAU,CAAqB;gBAGtC,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,IAAI,CAAC,uBAAuB,EAAE,KAAK,GAAG,kBAAkB,GAAG,eAAe,GAAG,sBAAsB,CAAC,EAC9G,aAAa,GAAE,OAAO,uBAAiD,EACvE,iBAAiB,GAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC,CAAM,EACrE,IAAI,CAAC,EAAE,oBAAoB;IAoBtB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAmD7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB9B;;;;;;;;;OASG;IACH,iBAAiB,IAAI,IAAI;IA4BzB;;;;;OAKG;YACW,gBAAgB;IA6B9B,4EAA4E;IAC5E,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,eAAe;YAiBT,IAAI;IA8GlB;;;;OAIG;IACG,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD5D;;;;;;;OAOG;YACW,mBAAmB;YAkBnB,KAAK;IA4CnB,OAAO,CAAC,IAAI;CAWZ"}
1
+ {"version":3,"file":"session-command-router.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-command-router.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO9D,OAAO,EAAE,uBAAuB,EAA0B,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAkB,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAKzG,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,OAAO,uBAAuB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,wGAAwG;IACxG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;CACjC;AAMD,uFAAuF;AACvF,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,gFAAgF;IAChF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA0C;IAC/E,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyC;IAC3E,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGvB;IACF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA+B;IACnE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsE;IACpG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAgB;IAClD,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,UAAU,CAAqB;gBAGtC,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,IAAI,CAAC,uBAAuB,EAAE,KAAK,GAAG,kBAAkB,GAAG,eAAe,GAAG,sBAAsB,CAAC,EAC9G,aAAa,GAAE,OAAO,uBAAiD,EACvE,iBAAiB,GAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC,CAAM,EACrE,IAAI,CAAC,EAAE,oBAAoB;IAoBtB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAoD7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAa9B;;;;;;;;;OASG;IACH,iBAAiB,IAAI,IAAI;IA4BzB;;;;;OAKG;YACW,gBAAgB;IAyB9B,4EAA4E;IAC5E,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,eAAe;YAiBT,IAAI;IA8GlB;;;;OAIG;IACG,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD5D;;;;;;;OAOG;YACW,mBAAmB;IAQjC;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAYlB,kFAAkF;IAClF,OAAO,CAAC,aAAa;YAWP,KAAK;IA6BnB,qGAAqG;IACrG,OAAO,CAAC,sBAAsB;IAkB9B;;;;;;OAMG;YACW,aAAa;IA0B3B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,IAAI;CAWZ"}
@@ -1,6 +1,6 @@
1
1
  import { VERSION } from "../../config.js";
2
2
  import { buildRpcSessionState } from "./connection-handler.js";
3
- import { AUTO_TITLE_SESSIONS_CAPABILITY } from "./custom-capability.js";
3
+ import { AUTO_TITLE_SESSIONS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY } from "./custom-capability.js";
4
4
  import { RPC_ERROR_MISSING_SESSION_ID, RPC_ERROR_OPEN_FAILED, RPC_ERROR_SESSION_CLOSING, RPC_ERROR_UNKNOWN_SESSION, } from "./rpc-types.js";
5
5
  import { createRpcSessionBinding } from "./session-binding.js";
6
6
  import { RpcSessionRegistryError } from "./session-registry.js";
@@ -20,6 +20,7 @@ export class SessionCommandRouter {
20
20
  this.releasedConnections = new Set();
21
21
  this.widths = new Map();
22
22
  this.pendingCapabilities = new Map();
23
+ this.finalizations = new Map();
23
24
  this.registry = registry;
24
25
  this.writer = writer;
25
26
  this.defaults = defaults;
@@ -42,6 +43,7 @@ export class SessionCommandRouter {
42
43
  const capabilities = new Set([
43
44
  "multi_session",
44
45
  AUTO_TITLE_SESSIONS_CAPABILITY,
46
+ MEDIA_PLACEHOLDERS_CAPABILITY,
45
47
  ...(this.connectionOptions?.capabilities ?? []),
46
48
  ]);
47
49
  return {
@@ -96,25 +98,13 @@ export class SessionCommandRouter {
96
98
  async dispose() {
97
99
  this.stopSweep();
98
100
  await Promise.all([...this.bindings.entries()].map(async ([sessionId, binding]) => {
99
- let entry;
100
- try {
101
- entry = this.registry.beginClose(sessionId);
102
- }
103
- catch {
101
+ const claim = this.tryClaimClose(sessionId, { drainAttachments: true });
102
+ if (!claim)
104
103
  return;
105
- }
106
- try {
107
- if (entry.state === "open") {
108
- while (entry.state === "open")
109
- entry = this.registry.beginClose(sessionId);
110
- }
111
- await binding.dispose();
112
- }
113
- finally {
114
- this.bindings.delete(sessionId);
115
- if (entry.state === "closing")
116
- await this.registry.closeMarked(sessionId);
117
- }
104
+ if (claim.finalizer)
105
+ await this.finalizeClose(sessionId, binding);
106
+ else
107
+ await this.finalizations.get(sessionId)?.promise;
118
108
  }));
119
109
  this.bindings.clear();
120
110
  }
@@ -167,36 +157,28 @@ export class SessionCommandRouter {
167
157
  * tolerated the same way releaseOwnedSession tolerates them.
168
158
  */
169
159
  async evictIdleSession(sessionId) {
170
- let entry;
171
- try {
172
- entry = this.registry.beginClose(sessionId);
173
- while (entry.state === "open")
174
- entry = this.registry.beginClose(sessionId);
175
- }
176
- catch {
177
- // Raced with an explicit close; that path owns the entry now.
160
+ // A failed claim means an explicit close raced us and owns the entry now.
161
+ const claim = this.tryClaimClose(sessionId, { drainAttachments: true });
162
+ if (!claim)
178
163
  return;
179
- }
180
- try {
181
- this.bindings.get(sessionId)?.cancelPendingExtensionUiRequests?.();
182
- await this.bindings.get(sessionId)?.dispose();
183
- }
184
- finally {
185
- this.bindings.delete(sessionId);
186
- this.forgetSessionOwnership(sessionId);
187
- if (entry.state === "closing")
188
- await this.registry.closeMarked(sessionId);
189
- this.writer.closeSession(sessionId, {
164
+ const binding = this.bindings.get(sessionId);
165
+ binding?.cancelPendingExtensionUiRequests?.();
166
+ this.forgetSessionOwnership(sessionId);
167
+ if (claim.finalizer) {
168
+ await this.finalizeClose(sessionId, binding, () => this.writer.closeSession(sessionId, {
190
169
  type: "response",
191
170
  command: "close_session",
192
171
  success: true,
193
172
  data: {},
194
- });
195
- // The runtime is disposed and routing handles are unique per process
196
- // epoch, so nothing can emit under this id again: drop the writer's
197
- // per-session bookkeeping instead of retaining it for the host's life.
198
- this.writer.forgetSession(sessionId);
173
+ }));
199
174
  }
175
+ else {
176
+ await this.finalizations.get(sessionId)?.promise;
177
+ }
178
+ // The runtime is disposed and routing handles are unique per process
179
+ // epoch, so nothing can emit under this id again: drop the writer's
180
+ // per-session bookkeeping instead of retaining it for the host's life.
181
+ this.writer.forgetSession(sessionId);
200
182
  }
201
183
  /** Drops per-connection records for a handle the host closed on its own. */
202
184
  forgetSessionOwnership(sessionId) {
@@ -391,76 +373,133 @@ export class SessionCommandRouter {
391
373
  * and their event stream.
392
374
  */
393
375
  async releaseOwnedSession(sessionId) {
394
- let entry;
376
+ // A failed claim means the entry is already closed or owned by another path.
377
+ const claim = this.tryClaimClose(sessionId, { drainAttachments: false });
378
+ if (!claim)
379
+ return;
380
+ if (claim.finalizer)
381
+ await this.finalizeClose(sessionId, this.bindings.get(sessionId));
382
+ else
383
+ await this.finalizations.get(sessionId)?.promise;
384
+ }
385
+ /**
386
+ * Releases one attachment (or every attachment when draining) and reports
387
+ * whether this caller became the finalizer. The join token is installed inside
388
+ * the registry callback, before any await, so a close that lands between the
389
+ * claim and finalizeClose() always finds a token to wait on instead of
390
+ * answering ahead of the terminal records.
391
+ */
392
+ claimClose(sessionId, options) {
393
+ let finalizer = true;
394
+ const onRole = (isFinalizer) => {
395
+ finalizer = isFinalizer;
396
+ if (isFinalizer && !this.finalizations.has(sessionId))
397
+ this.finalizations.set(sessionId, this.createFinalization());
398
+ };
399
+ let entry = this.registry.beginClose(sessionId, onRole);
400
+ while (options.drainAttachments && entry.state === "open")
401
+ entry = this.registry.beginClose(sessionId, onRole);
402
+ return { finalizer: finalizer && entry.state === "closing" };
403
+ }
404
+ /** claimClose() for lifecycle paths that treat a lost race as "nothing to do". */
405
+ tryClaimClose(sessionId, options) {
395
406
  try {
396
- entry = this.registry.beginClose(sessionId);
407
+ return this.claimClose(sessionId, options);
397
408
  }
398
409
  catch {
399
- // Already closed or claimed by another lifecycle path; nothing to release.
400
- return;
410
+ return undefined;
401
411
  }
412
+ }
413
+ async close(command) {
414
+ // This must be the first operation: binding.dispose() awaits teardown and
415
+ // otherwise leaves a window where commands can enter the old handler.
416
+ let claim;
402
417
  try {
403
- if (entry.state === "closing")
404
- await this.bindings.get(sessionId)?.dispose();
418
+ claim = this.claimClose(command.sessionId, { drainAttachments: false });
405
419
  }
406
- finally {
407
- if (entry.state === "closing") {
408
- this.bindings.delete(sessionId);
409
- await this.registry.closeMarked(sessionId);
420
+ catch (cause) {
421
+ return error(command.id, "close_session", this.code(cause));
422
+ }
423
+ const response = {
424
+ id: command.id,
425
+ type: "response",
426
+ command: "close_session",
427
+ success: true,
428
+ data: {},
429
+ };
430
+ const owner = this.writer.currentConnection();
431
+ if (owner !== undefined)
432
+ this.releaseOwnerAttachment(owner, command.sessionId);
433
+ if (claim.finalizer) {
434
+ await this.finalizeClose(command.sessionId, this.bindings.get(command.sessionId), () => this.writer.closeSession(command.sessionId, response));
435
+ }
436
+ else {
437
+ await this.finalizations.get(command.sessionId)?.promise;
438
+ this.writer.enqueueClosedResponse(command.sessionId, response);
439
+ }
440
+ return undefined;
441
+ }
442
+ /** Detaches the closing connection's UI/width state; a rerender failure must not abort the close. */
443
+ releaseOwnerAttachment(owner, sessionId) {
444
+ this.widths.get(sessionId)?.delete(owner);
445
+ this.writer.detachConnectionFromSession(owner, sessionId);
446
+ for (const binding of this.bindings.values()) {
447
+ try {
448
+ binding.rerenderComponents?.();
449
+ }
450
+ catch (cause) {
451
+ process.stderr.write(`senpi rpc rerender after close of session ${sessionId} failed: ${String(cause)}\n`);
410
452
  }
411
453
  }
454
+ const owned = this.sessionsByConnection.get(owner);
455
+ const count = owned?.get(sessionId);
456
+ if (!owned || count === undefined)
457
+ return;
458
+ if (count === 1)
459
+ owned.delete(sessionId);
460
+ else
461
+ owned.set(sessionId, count - 1);
462
+ if (owned.size === 0)
463
+ this.sessionsByConnection.delete(owner);
412
464
  }
413
- async close(command) {
465
+ /**
466
+ * Runs the finalizer side of a close for a handle whose beginClose() made this
467
+ * caller the owner: dispose the binding, complete the registry teardown, emit
468
+ * the terminal records, then release joiners. Every step is guarded so the join
469
+ * token always resolves and a failing binding yields one logged line, never a
470
+ * second response or an escaped rejection.
471
+ */
472
+ async finalizeClose(sessionId, binding, terminal) {
473
+ const finalization = this.finalizations.get(sessionId) ?? this.createFinalization();
474
+ this.finalizations.set(sessionId, finalization);
414
475
  try {
415
- // This must be the first operation: binding.dispose() awaits teardown and
416
- // otherwise leaves a window where commands can enter the old handler.
417
- const entry = this.registry.beginClose(command.sessionId);
418
- const owner = this.writer.currentConnection();
419
- if (owner !== undefined) {
420
- this.widths.get(command.sessionId)?.delete(owner);
421
- this.writer.detachConnectionFromSession(owner, command.sessionId);
422
- for (const binding of this.bindings.values())
423
- binding.rerenderComponents?.();
476
+ try {
477
+ await binding?.dispose();
424
478
  }
425
- if (owner !== undefined) {
426
- const owned = this.sessionsByConnection.get(owner);
427
- const count = owned?.get(command.sessionId);
428
- if (owned && count !== undefined) {
429
- if (count === 1)
430
- owned.delete(command.sessionId);
431
- else
432
- owned.set(command.sessionId, count - 1);
433
- if (owned.size === 0)
434
- this.sessionsByConnection.delete(owner);
435
- }
479
+ catch (cause) {
480
+ process.stderr.write(`senpi rpc binding dispose for session ${sessionId} failed: ${String(cause)}\n`);
436
481
  }
437
- const response = {
438
- id: command.id,
439
- type: "response",
440
- command: "close_session",
441
- success: true,
442
- data: {},
443
- };
482
+ this.bindings.delete(sessionId);
444
483
  try {
445
- if (entry.state === "closing")
446
- await this.bindings.get(command.sessionId)?.dispose();
484
+ await this.registry.closeMarked(sessionId);
447
485
  }
448
- finally {
449
- if (entry.state === "closing") {
450
- this.bindings.delete(command.sessionId);
451
- await this.registry.closeMarked(command.sessionId);
452
- this.writer.closeSession(command.sessionId, response);
453
- }
454
- else {
455
- this.writer.enqueue(command.sessionId, response);
456
- }
486
+ catch (cause) {
487
+ process.stderr.write(`senpi rpc close for session ${sessionId} failed: ${String(cause)}\n`);
457
488
  }
458
- return undefined;
489
+ terminal?.();
459
490
  }
460
- catch (cause) {
461
- return error(command.id, "close_session", this.code(cause));
491
+ finally {
492
+ finalization.resolve();
493
+ this.finalizations.delete(sessionId);
462
494
  }
463
495
  }
496
+ createFinalization() {
497
+ let resolveFinalization;
498
+ const promise = new Promise((resolve) => {
499
+ resolveFinalization = resolve;
500
+ });
501
+ return { promise, resolve: () => resolveFinalization?.() };
502
+ }
464
503
  code(cause) {
465
504
  if (cause instanceof RpcSessionRegistryError) {
466
505
  return cause.code === RPC_ERROR_OPEN_FAILED ? cause.message : cause.code;