@code-yeongyu/senpi 2026.9.7 → 2026.9.8

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 (323) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/core/agent-session.d.ts +40 -3
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +159 -40
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/compaction/compaction.d.ts.map +1 -1
  7. package/dist/core/compaction/compaction.js +2 -1
  8. package/dist/core/compaction/compaction.js.map +1 -1
  9. package/dist/core/dynamic-prompt/working-task.js +1 -1
  10. package/dist/core/dynamic-prompt/working-task.js.map +1 -1
  11. package/dist/core/extensions/builtin/cache-keepalive/index.d.ts.map +1 -1
  12. package/dist/core/extensions/builtin/cache-keepalive/index.js +4 -21
  13. package/dist/core/extensions/builtin/cache-keepalive/index.js.map +1 -1
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts +2 -0
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts.map +1 -1
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js +10 -25
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js.map +1 -1
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +36 -19
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js +21 -10
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +4 -17
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +23 -33
  27. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
  28. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  29. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +1 -0
  30. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js +5 -3
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js.map +1 -1
  34. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +8 -3
  36. package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js.map +1 -1
  37. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts +6 -5
  38. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js +6 -5
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/circuit-breaker.d.ts +8 -0
  42. package/dist/core/extensions/builtin/compaction/circuit-breaker.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/compaction/circuit-breaker.js +8 -0
  44. package/dist/core/extensions/builtin/compaction/circuit-breaker.js.map +1 -1
  45. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -0
  46. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +125 -20
  48. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  49. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.d.ts +18 -0
  50. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.d.ts.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.js +20 -0
  52. package/dist/core/extensions/builtin/compaction/fallback-failed-turn-normalization.js.map +1 -0
  53. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/compaction/index.js +54 -11
  55. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  56. package/dist/core/extensions/builtin/compaction/lane-policy.d.ts +3 -0
  57. package/dist/core/extensions/builtin/compaction/lane-policy.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/compaction/lane-policy.js +47 -23
  59. package/dist/core/extensions/builtin/compaction/lane-policy.js.map +1 -1
  60. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +11 -0
  62. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  63. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js +6 -4
  64. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js.map +1 -1
  65. package/dist/core/extensions/builtin/goal/cache-warm.d.ts +25 -1
  66. package/dist/core/extensions/builtin/goal/cache-warm.d.ts.map +1 -1
  67. package/dist/core/extensions/builtin/goal/cache-warm.js +29 -10
  68. package/dist/core/extensions/builtin/goal/cache-warm.js.map +1 -1
  69. package/dist/core/extensions/builtin/goal/continuation.d.ts +3 -1
  70. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/goal/continuation.js +17 -2
  72. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  73. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +1 -0
  75. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  76. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +1 -1
  77. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/goal/monitor-continuation.js +8 -3
  79. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  80. package/dist/core/extensions/builtin/gpt-account.d.ts +5 -1
  81. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -1
  82. package/dist/core/extensions/builtin/gpt-account.js +9 -26
  83. package/dist/core/extensions/builtin/gpt-account.js.map +1 -1
  84. package/dist/core/extensions/builtin/hooks/plugin-manifest.js +2 -2
  85. package/dist/core/extensions/builtin/hooks/plugin-manifest.js.map +1 -1
  86. package/dist/core/extensions/builtin/hooks/safety.js +2 -2
  87. package/dist/core/extensions/builtin/hooks/safety.js.map +1 -1
  88. package/dist/core/extensions/builtin/monitor-state-event.d.ts +18 -0
  89. package/dist/core/extensions/builtin/monitor-state-event.d.ts.map +1 -1
  90. package/dist/core/extensions/builtin/monitor-state-event.js +23 -0
  91. package/dist/core/extensions/builtin/monitor-state-event.js.map +1 -1
  92. package/dist/core/extensions/builtin/oauth-login-interaction.d.ts +24 -0
  93. package/dist/core/extensions/builtin/oauth-login-interaction.d.ts.map +1 -0
  94. package/dist/core/extensions/builtin/oauth-login-interaction.js +77 -0
  95. package/dist/core/extensions/builtin/oauth-login-interaction.js.map +1 -0
  96. package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
  97. package/dist/core/extensions/builtin/permission-system/external-dir.js +5 -51
  98. package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
  99. package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
  100. package/dist/core/extensions/builtin/permission-system/parsers.js +5 -7
  101. package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
  102. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +1 -1
  103. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -1
  104. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +1 -1
  105. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  106. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +14 -7
  107. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts.map +1 -1
  108. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +34 -13
  109. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js.map +1 -1
  110. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +6 -10
  111. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  112. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +14 -9
  113. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  114. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +15 -15
  115. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
  116. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +49 -21
  117. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
  118. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +1 -1
  119. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  120. package/dist/core/extensions/builtin/service-tier.d.ts +2 -0
  121. package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
  122. package/dist/core/extensions/builtin/service-tier.js +17 -1
  123. package/dist/core/extensions/builtin/service-tier.js.map +1 -1
  124. package/dist/core/extensions/builtin/terminal/durable-command.d.ts.map +1 -1
  125. package/dist/core/extensions/builtin/terminal/durable-command.js +3 -0
  126. package/dist/core/extensions/builtin/terminal/durable-command.js.map +1 -1
  127. package/dist/core/extensions/builtin/terminal/durable-file.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/terminal/durable-file.js +2 -0
  129. package/dist/core/extensions/builtin/terminal/durable-file.js.map +1 -1
  130. package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/terminal/extension.js +14 -2
  132. package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
  133. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  134. package/dist/core/extensions/builtin/terminal/monitor-notify.js +27 -5
  135. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  136. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +17 -0
  137. package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
  138. package/dist/core/extensions/builtin/terminal/monitor-registry.js +76 -14
  139. package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
  140. package/dist/core/extensions/builtin/terminal/notify.d.ts +2 -0
  141. package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
  142. package/dist/core/extensions/builtin/terminal/notify.js +6 -1
  143. package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
  144. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +3 -1
  145. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/terminal/session-bundle.js +13 -0
  147. package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
  148. package/dist/core/extensions/builtin/terminal/shared.d.ts +13 -2
  149. package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/terminal/shared.js +15 -2
  151. package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
  152. package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
  153. package/dist/core/extensions/builtin/terminal/tools/monitor.js +8 -1
  154. package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
  155. package/dist/core/extensions/builtin/tool-search/index.d.ts.map +1 -1
  156. package/dist/core/extensions/builtin/tool-search/index.js +1 -0
  157. package/dist/core/extensions/builtin/tool-search/index.js.map +1 -1
  158. package/dist/core/extensions/builtin/tool-search/service.d.ts +4 -0
  159. package/dist/core/extensions/builtin/tool-search/service.d.ts.map +1 -1
  160. package/dist/core/extensions/builtin/tool-search/service.js +11 -0
  161. package/dist/core/extensions/builtin/tool-search/service.js.map +1 -1
  162. package/dist/core/extensions/runner.d.ts +1 -0
  163. package/dist/core/extensions/runner.d.ts.map +1 -1
  164. package/dist/core/extensions/runner.js +8 -1
  165. package/dist/core/extensions/runner.js.map +1 -1
  166. package/dist/core/extensions/types.d.ts +9 -0
  167. package/dist/core/extensions/types.d.ts.map +1 -1
  168. package/dist/core/extensions/types.js.map +1 -1
  169. package/dist/core/high-reasoning-warning.d.ts.map +1 -1
  170. package/dist/core/high-reasoning-warning.js +4 -6
  171. package/dist/core/high-reasoning-warning.js.map +1 -1
  172. package/dist/core/sdk.d.ts +1 -1
  173. package/dist/core/sdk.d.ts.map +1 -1
  174. package/dist/core/sdk.js +25 -6
  175. package/dist/core/sdk.js.map +1 -1
  176. package/dist/core/settings-manager.js +1 -1
  177. package/dist/core/settings-manager.js.map +1 -1
  178. package/dist/core/settings-shapes.js.map +1 -1
  179. package/dist/core/tools/bounded-realpath.d.ts +28 -0
  180. package/dist/core/tools/bounded-realpath.d.ts.map +1 -0
  181. package/dist/core/tools/bounded-realpath.js +53 -0
  182. package/dist/core/tools/bounded-realpath.js.map +1 -0
  183. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  184. package/dist/core/tools/file-mutation-queue.js +15 -13
  185. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  186. package/dist/core/tools/filesystem-policy.d.ts +7 -0
  187. package/dist/core/tools/filesystem-policy.d.ts.map +1 -1
  188. package/dist/core/tools/filesystem-policy.js +25 -15
  189. package/dist/core/tools/filesystem-policy.js.map +1 -1
  190. package/dist/core/trust-manager.d.ts.map +1 -1
  191. package/dist/core/trust-manager.js +13 -2
  192. package/dist/core/trust-manager.js.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  194. package/dist/modes/interactive/interactive-mode.js +1 -0
  195. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  196. package/dist/modes/interactive/tips/catalog/memory-tips.d.ts.map +1 -1
  197. package/dist/modes/interactive/tips/catalog/memory-tips.js +6 -0
  198. package/dist/modes/interactive/tips/catalog/memory-tips.js.map +1 -1
  199. package/dist/modes/interactive/tips/catalog/subagent-tips.d.ts.map +1 -1
  200. package/dist/modes/interactive/tips/catalog/subagent-tips.js +6 -0
  201. package/dist/modes/interactive/tips/catalog/subagent-tips.js.map +1 -1
  202. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  203. package/dist/modes/rpc/host-lifecycle.js +31 -5
  204. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  205. package/dist/modes/rpc/host-watchdog.d.ts +11 -0
  206. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  207. package/dist/modes/rpc/host-watchdog.js +16 -2
  208. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  209. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  210. package/dist/modes/rpc/multi-session-host.js +54 -16
  211. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  212. package/dist/modes/rpc/socket-ownership.d.ts +46 -0
  213. package/dist/modes/rpc/socket-ownership.d.ts.map +1 -0
  214. package/dist/modes/rpc/socket-ownership.js +178 -0
  215. package/dist/modes/rpc/socket-ownership.js.map +1 -0
  216. package/dist/utils/fs-watch.d.ts +17 -0
  217. package/dist/utils/fs-watch.d.ts.map +1 -1
  218. package/dist/utils/fs-watch.js +38 -10
  219. package/dist/utils/fs-watch.js.map +1 -1
  220. package/dist/utils/paths.d.ts +33 -0
  221. package/dist/utils/paths.d.ts.map +1 -1
  222. package/dist/utils/paths.js +109 -3
  223. package/dist/utils/paths.js.map +1 -1
  224. package/docs/development.md +3 -2
  225. package/docs/providers.md +5 -1
  226. package/docs/settings.md +1 -0
  227. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +31 -0
  228. package/node_modules/@code-yeongyu/senpi-codemode/README.md +14 -1
  229. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  230. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +1 -0
  231. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/runtime-factory.ts +3 -0
  232. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +7 -0
  233. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +7 -0
  234. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/kernel.ts +4 -0
  235. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +3 -0
  236. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +29 -0
  237. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +10 -6
  238. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.d.ts +16 -0
  239. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-shell-capture.js +44 -8
  240. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-startup.ts +1 -0
  241. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel-contract.ts +3 -0
  242. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +9 -1
  243. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/kernel.ts +4 -0
  244. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/session-env.ts +56 -0
  245. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-contract.ts +3 -0
  246. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +9 -1
  247. package/node_modules/@code-yeongyu/senpi-codemode/src/output/output-meta.ts +26 -2
  248. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +17 -24
  249. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image.ts +12 -3
  250. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  251. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
  252. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  253. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +7 -0
  254. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
  255. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +19 -0
  256. package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
  257. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -1
  258. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +24 -16
  259. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -1
  260. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +1 -1
  261. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  262. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +1 -1
  263. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  265. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +47 -178
  267. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.d.ts +3 -0
  269. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.d.ts.map +1 -0
  270. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js +260 -0
  271. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js.map +1 -0
  272. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +1 -0
  274. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +1 -0
  277. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.d.ts +40 -0
  279. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.d.ts.map +1 -0
  280. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.js +138 -0
  281. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic-callback-listener.js.map +1 -0
  282. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts +2 -3
  283. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts.map +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js +42 -139
  285. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.d.ts +6 -0
  287. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.d.ts.map +1 -0
  288. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.js +29 -0
  289. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/authorization-input.js.map +1 -0
  290. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.d.ts +3 -0
  291. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.d.ts.map +1 -0
  292. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.js +20 -0
  293. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/error-details.js.map +1 -0
  294. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  295. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -1
  297. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  298. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  299. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  301. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  303. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  304. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  305. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js +16 -1
  307. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +7 -0
  309. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +14 -3
  314. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  315. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts +2 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts.map +1 -1
  317. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js +16 -0
  318. package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js.map +1 -1
  319. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  320. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  321. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  322. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  323. package/package.json +7 -7
@@ -1,9 +1,11 @@
1
+ import { createExtensionLoginInteraction, LOGIN_CANCELLED_MESSAGE } from "../oauth-login-interaction.js";
1
2
  import { emitProviderAccountsChanged } from "./account-events.js";
2
3
  import { CLAUDE_SDK_OAUTH_PROVIDER_ID, pinProviderAccount, removeProviderAccount } from "./account-management.js";
3
4
  import { emptyCredential, listAccounts } from "./accounts.js";
4
5
  import { selectAccount } from "./affinity.js";
5
6
  import { loadClaudeSdkOauthProviderSettingsFromDisk } from "./settings.js";
6
7
  const cliPinsBySession = new Map();
8
+ const CLAUDE_SDK_OAUTH_PROVIDER_LABEL = "Claude SDK OAuth";
7
9
  function asCredential(value) {
8
10
  return value?.type === "oauth" ? value : undefined;
9
11
  }
@@ -28,18 +30,6 @@ function accountError(ctx, name) {
28
30
  function parseArgs(rawArgs) {
29
31
  return rawArgs.trim().split(/\s+/).filter(Boolean);
30
32
  }
31
- function authEventMessage(event) {
32
- if (event === null || typeof event !== "object")
33
- return "Claude SDK OAuth authentication update.";
34
- const value = event;
35
- if (value.type === "auth_url" && typeof value.url === "string") {
36
- return `Open this URL to authorize Claude SDK OAuth:\n${value.url}`;
37
- }
38
- if (value.type === "device_code" && typeof value.verificationUri === "string") {
39
- return `Open this URL to authorize Claude SDK OAuth:\n${value.verificationUri}`;
40
- }
41
- return typeof value.message === "string" ? value.message : "Claude SDK OAuth authentication update.";
42
- }
43
33
  export function getSessionClaudeAccountPin(sessionId) {
44
34
  return sessionId === undefined ? undefined : cliPinsBySession.get(sessionId);
45
35
  }
@@ -76,7 +66,7 @@ export function registerClaudeAccountCommand(pi, deps = {}) {
76
66
  return;
77
67
  }
78
68
  if (action === "add") {
79
- await addAccount(ctx);
69
+ await addAccount(ctx, deps);
80
70
  return;
81
71
  }
82
72
  if (action === "remove") {
@@ -128,29 +118,24 @@ function showAccounts(ctx, settings, environment) {
128
118
  lines.push(`Affinity pick: ${affinityPick ?? (affinityError ? `unavailable - ${affinityError}` : "none")}`);
129
119
  ctx.ui.notify(lines.join("\n"), "info");
130
120
  }
131
- async function addAccount(ctx) {
121
+ async function addAccount(ctx, deps) {
132
122
  if (!ctx.hasUI) {
133
123
  ctx.ui.notify("/claude-account add requires an interactive UI.", "error");
134
124
  return;
135
125
  }
136
126
  try {
137
- await ctx.modelRegistry.modelRuntime.login(CLAUDE_SDK_OAUTH_PROVIDER_ID, "oauth", {
138
- signal: ctx.signal,
139
- prompt: async (prompt) => {
140
- const answer = await ctx.ui.input(prompt.message);
141
- if (answer === undefined)
142
- throw new Error("Login cancelled");
143
- return answer;
144
- },
145
- notify: (event) => ctx.ui.notify(authEventMessage(event), "info"),
146
- });
127
+ await ctx.modelRegistry.modelRuntime.login(CLAUDE_SDK_OAUTH_PROVIDER_ID, "oauth", createExtensionLoginInteraction(ctx, {
128
+ providerLabel: CLAUDE_SDK_OAUTH_PROVIDER_LABEL,
129
+ openBrowser: deps.openBrowser,
130
+ }));
147
131
  emitProviderAccountsChanged(CLAUDE_SDK_OAUTH_PROVIDER_ID);
148
132
  ctx.ui.notify("Claude SDK OAuth account added.", "info");
149
133
  }
150
134
  catch (error) {
151
135
  const message = error instanceof Error ? error.message : String(error);
152
- if (message !== "Login cancelled")
136
+ if (message !== LOGIN_CANCELLED_MESSAGE) {
153
137
  ctx.ui.notify(`Failed to add Claude SDK OAuth account: ${message}`, "error");
138
+ }
154
139
  }
155
140
  }
156
141
  async function removeNamedAccount(ctx, name, environment) {
@@ -1 +1 @@
1
- {"version":3,"file":"account-command.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/account-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Credential } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../types.ts\";\nimport { emitProviderAccountsChanged } from \"./account-events.ts\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID, pinProviderAccount, removeProviderAccount } from \"./account-management.ts\";\nimport { type AccountSlot, type ClaudeSdkOauthCredential, emptyCredential, listAccounts } from \"./accounts.ts\";\nimport { selectAccount } from \"./affinity.ts\";\nimport { type ClaudeSdkOauthProviderSettings, loadClaudeSdkOauthProviderSettingsFromDisk } from \"./settings.ts\";\n\nconst cliPinsBySession = new Map<string, string>();\n\ntype CommandEnvironment = (name: string) => string | undefined;\n\nexport interface ClaudeAccountCommandDeps {\n\tloadSettings?: (cwd: string) => ClaudeSdkOauthProviderSettings;\n\tenvironment?: CommandEnvironment;\n}\n\nfunction asCredential(value: Credential | undefined): ClaudeSdkOauthCredential | undefined {\n\treturn value?.type === \"oauth\" ? (value as ClaudeSdkOauthCredential) : undefined;\n}\n\nfunction slotStatus(slot: AccountSlot): string {\n\tif (slot.blockReason === \"auth_error\") return \"blocked until re-login\";\n\tif (slot.blockedUntil !== undefined && slot.blockedUntil > Date.now()) {\n\t\treturn `blocked until ${new Date(slot.blockedUntil).toISOString()}`;\n\t}\n\treturn \"available\";\n}\n\nfunction readAccounts(\n\tctx: ExtensionCommandContext,\n\tenvironment: CommandEnvironment,\n): {\n\tcredential: ClaudeSdkOauthCredential | undefined;\n\taccounts: AccountSlot[];\n} {\n\tconst credential = asCredential(ctx.modelRegistry.authStorage.get(CLAUDE_SDK_OAUTH_PROVIDER_ID));\n\treturn {\n\t\tcredential,\n\t\taccounts: listAccounts(credential ?? emptyCredential(), environment),\n\t};\n}\n\nfunction accountError(ctx: ExtensionCommandContext, name: string): void {\n\tctx.ui.notify(`Claude SDK OAuth account '${name}' does not exist.`, \"error\");\n}\n\nfunction parseArgs(rawArgs: string): string[] {\n\treturn rawArgs.trim().split(/\\s+/).filter(Boolean);\n}\n\nfunction authEventMessage(event: unknown): string {\n\tif (event === null || typeof event !== \"object\") return \"Claude SDK OAuth authentication update.\";\n\tconst value = event as Record<string, unknown>;\n\tif (value.type === \"auth_url\" && typeof value.url === \"string\") {\n\t\treturn `Open this URL to authorize Claude SDK OAuth:\\n${value.url}`;\n\t}\n\tif (value.type === \"device_code\" && typeof value.verificationUri === \"string\") {\n\t\treturn `Open this URL to authorize Claude SDK OAuth:\\n${value.verificationUri}`;\n\t}\n\treturn typeof value.message === \"string\" ? value.message : \"Claude SDK OAuth authentication update.\";\n}\n\nexport function getSessionClaudeAccountPin(sessionId: string | undefined): string | undefined {\n\treturn sessionId === undefined ? undefined : cliPinsBySession.get(sessionId);\n}\n\n/** CLI pins are request-local overrides; settings and stored pins remain fallback choices. */\nexport function resolveClaudeAccountPin(\n\tcliPinnedAccount: string | undefined,\n\tsettingsPinnedAccount: string | undefined,\n\tstoredPinnedAccount: string | undefined,\n): string | undefined {\n\treturn cliPinnedAccount ?? settingsPinnedAccount ?? storedPinnedAccount;\n}\n\nexport function registerClaudeAccountCommand(pi: ExtensionAPI, deps: ClaudeAccountCommandDeps = {}): void {\n\tconst loadSettings = deps.loadSettings ?? loadClaudeSdkOauthProviderSettingsFromDisk;\n\tconst environment = deps.environment ?? ((name: string) => process.env[name]);\n\n\tpi.registerFlag(\"claude-account\", {\n\t\ttype: \"string\",\n\t\tdescription: \"Pin Claude SDK OAuth account for this session.\",\n\t});\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tconst flag = pi.getFlag(\"claude-account\");\n\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\tif (typeof flag === \"string\" && flag.length > 0) cliPinsBySession.set(sessionId, flag);\n\t\telse cliPinsBySession.delete(sessionId);\n\t});\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\tcliPinsBySession.delete(ctx.sessionManager.getSessionId());\n\t});\n\tpi.registerCommand(\"claude-account\", {\n\t\tdescription: \"List and manage Claude SDK OAuth accounts.\",\n\t\targumentHint: \"[add | remove <name> | pin <name> | unpin]\",\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\tconst args = parseArgs(rawArgs);\n\t\t\tconst action = args[0] ?? \"list\";\n\t\t\tif (action === \"list\") {\n\t\t\t\tshowAccounts(ctx, loadSettings(ctx.cwd), environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"add\") {\n\t\t\t\tawait addAccount(ctx);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"remove\") {\n\t\t\t\tawait removeNamedAccount(ctx, args[1], environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"pin\" && args[1] !== \"unpin\") {\n\t\t\t\tawait pinNamedAccount(ctx, args[1], environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"unpin\" || (action === \"pin\" && args[1] === \"unpin\")) {\n\t\t\t\tawait unpinAccount(ctx);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx.ui.notify(\"Usage: /claude-account [add | remove <name> | pin <name> | unpin]\", \"error\");\n\t\t},\n\t});\n}\n\nfunction showAccounts(\n\tctx: ExtensionCommandContext,\n\tsettings: ClaudeSdkOauthProviderSettings,\n\tenvironment: CommandEnvironment,\n): void {\n\tconst { credential, accounts } = readAccounts(ctx, environment);\n\tconst cliPin = getSessionClaudeAccountPin(ctx.sessionManager.getSessionId());\n\tconst pinned = resolveClaudeAccountPin(cliPin, settings.pinnedAccount, credential?.pinned);\n\tconst pinSource = cliPin !== undefined ? \"CLI\" : settings.pinnedAccount !== undefined ? \"settings\" : \"stored\";\n\tlet affinityPick: string | undefined;\n\tlet affinityError: string | undefined;\n\tif (accounts.length > 0) {\n\t\ttry {\n\t\t\taffinityPick = selectAccount(accounts, {\n\t\t\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\t\t\tpinnedAccount: pinned,\n\t\t\t}).name;\n\t\t} catch (error) {\n\t\t\taffinityError = error instanceof Error ? error.message : String(error);\n\t\t}\n\t}\n\tconst lines = [\"Claude SDK OAuth accounts:\"];\n\tif (accounts.length === 0) lines.push(\" (none)\");\n\tfor (const account of accounts) {\n\t\tconst states = [account.name, account.source, slotStatus(account)];\n\t\tif (account.name === pinned) states.push(\"pinned\");\n\t\tif (account.name === affinityPick) states.push(\"affinity pick\");\n\t\tlines.push(` ${states.join(\" | \")}`);\n\t}\n\tlines.push(`Pinned account: ${pinned === undefined ? \"none\" : `${pinned} (${pinSource.toLowerCase()})`}`);\n\tlines.push(`Affinity pick: ${affinityPick ?? (affinityError ? `unavailable - ${affinityError}` : \"none\")}`);\n\tctx.ui.notify(lines.join(\"\\n\"), \"info\");\n}\n\nasync function addAccount(ctx: ExtensionCommandContext): Promise<void> {\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"/claude-account add requires an interactive UI.\", \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tawait ctx.modelRegistry.modelRuntime.login(CLAUDE_SDK_OAUTH_PROVIDER_ID, \"oauth\", {\n\t\t\tsignal: ctx.signal,\n\t\t\tprompt: async (prompt) => {\n\t\t\t\tconst answer = await ctx.ui.input(prompt.message);\n\t\t\t\tif (answer === undefined) throw new Error(\"Login cancelled\");\n\t\t\t\treturn answer;\n\t\t\t},\n\t\t\tnotify: (event) => ctx.ui.notify(authEventMessage(event), \"info\"),\n\t\t});\n\t\temitProviderAccountsChanged(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\t\tctx.ui.notify(\"Claude SDK OAuth account added.\", \"info\");\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tif (message !== \"Login cancelled\") ctx.ui.notify(`Failed to add Claude SDK OAuth account: ${message}`, \"error\");\n\t}\n}\n\nasync function removeNamedAccount(\n\tctx: ExtensionCommandContext,\n\tname: string | undefined,\n\tenvironment: CommandEnvironment,\n): Promise<void> {\n\tif (!name) {\n\t\tctx.ui.notify(\"Usage: /claude-account remove <name>\", \"error\");\n\t\treturn;\n\t}\n\tconst { accounts } = readAccounts(ctx, environment);\n\tconst target = accounts.find((account) => account.name === name);\n\tif (!target) return accountError(ctx, name);\n\tif (target.source === \"env\") {\n\t\tctx.ui.notify(`Claude SDK OAuth account '${name}' comes from the environment and cannot be removed.`, \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tawait removeProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, name);\n\t\tctx.ui.notify(`Removed Claude SDK OAuth account: ${name}.`, \"info\");\n\t} catch (error) {\n\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t}\n}\n\nasync function pinNamedAccount(\n\tctx: ExtensionCommandContext,\n\tname: string | undefined,\n\tenvironment: CommandEnvironment,\n): Promise<void> {\n\tif (!name) {\n\t\tctx.ui.notify(\"Usage: /claude-account pin <name>\", \"error\");\n\t\treturn;\n\t}\n\tif (!readAccounts(ctx, environment).accounts.some((account) => account.name === name)) {\n\t\treturn accountError(ctx, name);\n\t}\n\ttry {\n\t\tawait pinProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, name);\n\t\tctx.ui.notify(`Pinned Claude SDK OAuth account: ${name}.`, \"info\");\n\t} catch (error) {\n\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t}\n}\n\nasync function unpinAccount(ctx: ExtensionCommandContext): Promise<void> {\n\tconst credential = asCredential(ctx.modelRegistry.authStorage.get(CLAUDE_SDK_OAUTH_PROVIDER_ID));\n\tif (!credential?.pinned) {\n\t\tctx.ui.notify(\"No stored Claude SDK OAuth account pin is set.\", \"info\");\n\t\treturn;\n\t}\n\tawait pinProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, null);\n\tctx.ui.notify(\"Unpinned Claude SDK OAuth account.\", \"info\");\n}\n"]}
1
+ {"version":3,"file":"account-command.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/account-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Credential } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../types.ts\";\nimport { createExtensionLoginInteraction, LOGIN_CANCELLED_MESSAGE } from \"../oauth-login-interaction.ts\";\nimport { emitProviderAccountsChanged } from \"./account-events.ts\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID, pinProviderAccount, removeProviderAccount } from \"./account-management.ts\";\nimport { type AccountSlot, type ClaudeSdkOauthCredential, emptyCredential, listAccounts } from \"./accounts.ts\";\nimport { selectAccount } from \"./affinity.ts\";\nimport { type ClaudeSdkOauthProviderSettings, loadClaudeSdkOauthProviderSettingsFromDisk } from \"./settings.ts\";\n\nconst cliPinsBySession = new Map<string, string>();\n\ntype CommandEnvironment = (name: string) => string | undefined;\n\nexport interface ClaudeAccountCommandDeps {\n\tloadSettings?: (cwd: string) => ClaudeSdkOauthProviderSettings;\n\tenvironment?: CommandEnvironment;\n\t/** Browser launcher for the OAuth authorize URL; tests inject a recorder. */\n\topenBrowser?: ((url: string) => void) | undefined;\n}\n\nconst CLAUDE_SDK_OAUTH_PROVIDER_LABEL = \"Claude SDK OAuth\";\n\nfunction asCredential(value: Credential | undefined): ClaudeSdkOauthCredential | undefined {\n\treturn value?.type === \"oauth\" ? (value as ClaudeSdkOauthCredential) : undefined;\n}\n\nfunction slotStatus(slot: AccountSlot): string {\n\tif (slot.blockReason === \"auth_error\") return \"blocked until re-login\";\n\tif (slot.blockedUntil !== undefined && slot.blockedUntil > Date.now()) {\n\t\treturn `blocked until ${new Date(slot.blockedUntil).toISOString()}`;\n\t}\n\treturn \"available\";\n}\n\nfunction readAccounts(\n\tctx: ExtensionCommandContext,\n\tenvironment: CommandEnvironment,\n): {\n\tcredential: ClaudeSdkOauthCredential | undefined;\n\taccounts: AccountSlot[];\n} {\n\tconst credential = asCredential(ctx.modelRegistry.authStorage.get(CLAUDE_SDK_OAUTH_PROVIDER_ID));\n\treturn {\n\t\tcredential,\n\t\taccounts: listAccounts(credential ?? emptyCredential(), environment),\n\t};\n}\n\nfunction accountError(ctx: ExtensionCommandContext, name: string): void {\n\tctx.ui.notify(`Claude SDK OAuth account '${name}' does not exist.`, \"error\");\n}\n\nfunction parseArgs(rawArgs: string): string[] {\n\treturn rawArgs.trim().split(/\\s+/).filter(Boolean);\n}\n\nexport function getSessionClaudeAccountPin(sessionId: string | undefined): string | undefined {\n\treturn sessionId === undefined ? undefined : cliPinsBySession.get(sessionId);\n}\n\n/** CLI pins are request-local overrides; settings and stored pins remain fallback choices. */\nexport function resolveClaudeAccountPin(\n\tcliPinnedAccount: string | undefined,\n\tsettingsPinnedAccount: string | undefined,\n\tstoredPinnedAccount: string | undefined,\n): string | undefined {\n\treturn cliPinnedAccount ?? settingsPinnedAccount ?? storedPinnedAccount;\n}\n\nexport function registerClaudeAccountCommand(pi: ExtensionAPI, deps: ClaudeAccountCommandDeps = {}): void {\n\tconst loadSettings = deps.loadSettings ?? loadClaudeSdkOauthProviderSettingsFromDisk;\n\tconst environment = deps.environment ?? ((name: string) => process.env[name]);\n\n\tpi.registerFlag(\"claude-account\", {\n\t\ttype: \"string\",\n\t\tdescription: \"Pin Claude SDK OAuth account for this session.\",\n\t});\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tconst flag = pi.getFlag(\"claude-account\");\n\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\tif (typeof flag === \"string\" && flag.length > 0) cliPinsBySession.set(sessionId, flag);\n\t\telse cliPinsBySession.delete(sessionId);\n\t});\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\tcliPinsBySession.delete(ctx.sessionManager.getSessionId());\n\t});\n\tpi.registerCommand(\"claude-account\", {\n\t\tdescription: \"List and manage Claude SDK OAuth accounts.\",\n\t\targumentHint: \"[add | remove <name> | pin <name> | unpin]\",\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\tconst args = parseArgs(rawArgs);\n\t\t\tconst action = args[0] ?? \"list\";\n\t\t\tif (action === \"list\") {\n\t\t\t\tshowAccounts(ctx, loadSettings(ctx.cwd), environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"add\") {\n\t\t\t\tawait addAccount(ctx, deps);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"remove\") {\n\t\t\t\tawait removeNamedAccount(ctx, args[1], environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"pin\" && args[1] !== \"unpin\") {\n\t\t\t\tawait pinNamedAccount(ctx, args[1], environment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"unpin\" || (action === \"pin\" && args[1] === \"unpin\")) {\n\t\t\t\tawait unpinAccount(ctx);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx.ui.notify(\"Usage: /claude-account [add | remove <name> | pin <name> | unpin]\", \"error\");\n\t\t},\n\t});\n}\n\nfunction showAccounts(\n\tctx: ExtensionCommandContext,\n\tsettings: ClaudeSdkOauthProviderSettings,\n\tenvironment: CommandEnvironment,\n): void {\n\tconst { credential, accounts } = readAccounts(ctx, environment);\n\tconst cliPin = getSessionClaudeAccountPin(ctx.sessionManager.getSessionId());\n\tconst pinned = resolveClaudeAccountPin(cliPin, settings.pinnedAccount, credential?.pinned);\n\tconst pinSource = cliPin !== undefined ? \"CLI\" : settings.pinnedAccount !== undefined ? \"settings\" : \"stored\";\n\tlet affinityPick: string | undefined;\n\tlet affinityError: string | undefined;\n\tif (accounts.length > 0) {\n\t\ttry {\n\t\t\taffinityPick = selectAccount(accounts, {\n\t\t\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\t\t\tpinnedAccount: pinned,\n\t\t\t}).name;\n\t\t} catch (error) {\n\t\t\taffinityError = error instanceof Error ? error.message : String(error);\n\t\t}\n\t}\n\tconst lines = [\"Claude SDK OAuth accounts:\"];\n\tif (accounts.length === 0) lines.push(\" (none)\");\n\tfor (const account of accounts) {\n\t\tconst states = [account.name, account.source, slotStatus(account)];\n\t\tif (account.name === pinned) states.push(\"pinned\");\n\t\tif (account.name === affinityPick) states.push(\"affinity pick\");\n\t\tlines.push(` ${states.join(\" | \")}`);\n\t}\n\tlines.push(`Pinned account: ${pinned === undefined ? \"none\" : `${pinned} (${pinSource.toLowerCase()})`}`);\n\tlines.push(`Affinity pick: ${affinityPick ?? (affinityError ? `unavailable - ${affinityError}` : \"none\")}`);\n\tctx.ui.notify(lines.join(\"\\n\"), \"info\");\n}\n\nasync function addAccount(ctx: ExtensionCommandContext, deps: ClaudeAccountCommandDeps): Promise<void> {\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"/claude-account add requires an interactive UI.\", \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tawait ctx.modelRegistry.modelRuntime.login(\n\t\t\tCLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\t\t\"oauth\",\n\t\t\tcreateExtensionLoginInteraction(ctx, {\n\t\t\t\tproviderLabel: CLAUDE_SDK_OAUTH_PROVIDER_LABEL,\n\t\t\t\topenBrowser: deps.openBrowser,\n\t\t\t}),\n\t\t);\n\t\temitProviderAccountsChanged(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\t\tctx.ui.notify(\"Claude SDK OAuth account added.\", \"info\");\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tif (message !== LOGIN_CANCELLED_MESSAGE) {\n\t\t\tctx.ui.notify(`Failed to add Claude SDK OAuth account: ${message}`, \"error\");\n\t\t}\n\t}\n}\n\nasync function removeNamedAccount(\n\tctx: ExtensionCommandContext,\n\tname: string | undefined,\n\tenvironment: CommandEnvironment,\n): Promise<void> {\n\tif (!name) {\n\t\tctx.ui.notify(\"Usage: /claude-account remove <name>\", \"error\");\n\t\treturn;\n\t}\n\tconst { accounts } = readAccounts(ctx, environment);\n\tconst target = accounts.find((account) => account.name === name);\n\tif (!target) return accountError(ctx, name);\n\tif (target.source === \"env\") {\n\t\tctx.ui.notify(`Claude SDK OAuth account '${name}' comes from the environment and cannot be removed.`, \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tawait removeProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, name);\n\t\tctx.ui.notify(`Removed Claude SDK OAuth account: ${name}.`, \"info\");\n\t} catch (error) {\n\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t}\n}\n\nasync function pinNamedAccount(\n\tctx: ExtensionCommandContext,\n\tname: string | undefined,\n\tenvironment: CommandEnvironment,\n): Promise<void> {\n\tif (!name) {\n\t\tctx.ui.notify(\"Usage: /claude-account pin <name>\", \"error\");\n\t\treturn;\n\t}\n\tif (!readAccounts(ctx, environment).accounts.some((account) => account.name === name)) {\n\t\treturn accountError(ctx, name);\n\t}\n\ttry {\n\t\tawait pinProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, name);\n\t\tctx.ui.notify(`Pinned Claude SDK OAuth account: ${name}.`, \"info\");\n\t} catch (error) {\n\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t}\n}\n\nasync function unpinAccount(ctx: ExtensionCommandContext): Promise<void> {\n\tconst credential = asCredential(ctx.modelRegistry.authStorage.get(CLAUDE_SDK_OAUTH_PROVIDER_ID));\n\tif (!credential?.pinned) {\n\t\tctx.ui.notify(\"No stored Claude SDK OAuth account pin is set.\", \"info\");\n\t\treturn;\n\t}\n\tawait pinProviderAccount(ctx.modelRegistry.authStorage, CLAUDE_SDK_OAUTH_PROVIDER_ID, null);\n\tctx.ui.notify(\"Unpinned Claude SDK OAuth account.\", \"info\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-binding.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAC7D,eAAO,MAAM,cAAc;;;CAA8C,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,CAgBf;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,GAAG,SAAS,CAsB3B;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,aAAa,GACnB,iBAAiB,GAAG,SAAS,CAe/B"}
1
+ {"version":3,"file":"session-binding.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAC7D,eAAO,MAAM,cAAc;;;CAA8C,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,CAgBf;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,GAAG,SAAS,CAsB3B;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,aAAa,GACnB,iBAAiB,GAAG,SAAS,CAW/B"}
@@ -58,12 +58,12 @@ export function bindingFromStoredBranch(branch, stored) {
58
58
  if (markerIndex < 0)
59
59
  return undefined;
60
60
  const marker = branch[markerIndex];
61
- if (marker?.id !== stored.markerEntryId ||
62
- !isBindingMarker(marker.data) ||
63
- !branch.slice(markerIndex + 2).every(isSafeBindingSuffix)) {
61
+ if (marker?.id !== stored.markerEntryId || !isBindingMarker(marker.data))
64
62
  return undefined;
65
- }
66
- const committedAssistant = branch[markerIndex + 1]?.message;
63
+ const assistantIndex = committedAssistantIndex(branch, markerIndex + 1);
64
+ if (assistantIndex < 0 || !branch.slice(assistantIndex + 1).every(isLedgerOnlyEntry))
65
+ return undefined;
66
+ const committedAssistant = branch[assistantIndex]?.message;
67
67
  if (!isAssistantMessage(committedAssistant))
68
68
  return undefined;
69
69
  if (assistantContentHash(committedAssistant) !== stored.assistantContentHash)
@@ -71,24 +71,41 @@ export function bindingFromStoredBranch(branch, stored) {
71
71
  return bindingFromStored(stored);
72
72
  }
73
73
  /**
74
- * Display-only metadata the co-resident builtins append after the committed
75
- * assistant (stop-hook state/diagnostics/output, rule activations, rule scans).
76
- * None participates in the sent stream, so none can shift the prefix digest.
74
+ * The marker is appended inside `message_end`, so handlers that run after this
75
+ * builtin (and extensions loaded later) can append ledger entries before the
76
+ * assistant itself persists. The committed assistant is the first message after
77
+ * the marker; anything that reaches the model in between fails closed.
78
+ */
79
+ function committedAssistantIndex(branch, from) {
80
+ for (let index = from; index < branch.length; index += 1) {
81
+ const entry = branch[index];
82
+ if (entry?.type === "message")
83
+ return index;
84
+ if (!entry || !isLedgerOnlyEntry(entry))
85
+ return -1;
86
+ }
87
+ return -1;
88
+ }
89
+ /**
90
+ * Entry types the session-manager never projects into the LLM context. They
91
+ * cannot shift the sent-stream digest the binding is verified against, so any
92
+ * `custom` ledger record (hook state, rule scans, memory bookkeeping, ...) is
93
+ * admitted regardless of who wrote it. Everything the model can see - messages,
94
+ * custom messages other than the goal continuation, compaction and branch
95
+ * summaries - keeps failing closed (oh-my-openagent#7925).
77
96
  */
78
- const SAFE_BINDING_SUFFIX_TYPES = new Set([
79
- "senpi.hooks.stop-state",
80
- "senpi.hooks.stop-diagnostics",
81
- "senpi.hooks.stop-output",
82
- "pi-rules.scan",
83
- "rule-activation",
84
- "goal-cache-warmup",
97
+ const LEDGER_ONLY_ENTRY_TYPES = new Set([
98
+ "custom",
99
+ "label",
100
+ "session_info",
101
+ "thinking_level_change",
102
+ "model_change",
103
+ "configuration_update",
85
104
  ]);
86
- function isSafeBindingSuffix(entry) {
87
- if (entry.type === "label")
88
- return true;
105
+ function isLedgerOnlyEntry(entry) {
89
106
  if (entry.type === "custom_message")
90
107
  return entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE;
91
- return entry.type === "custom" && entry.customType !== undefined && SAFE_BINDING_SUFFIX_TYPES.has(entry.customType);
108
+ return LEDGER_ONLY_ENTRY_TYPES.has(entry.type);
92
109
  }
93
110
  function newestBindingEntryIndex(branch) {
94
111
  for (let index = branch.length - 1; index >= 0; index -= 1) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-binding.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { StoredBinding } from \"./session-binding-store.ts\";\nimport { assistantContentHash } from \"./session-commit-boundary.ts\";\nimport type { ContinuityBinding } from \"./session-reattach.ts\";\nimport { sentHashPrefixDigest } from \"./session-sync.ts\";\n\nexport const BINDING_ENTRY_TYPE = \"claude-sdk-oauth-binding\";\nexport const BINDING_MARKER = { schemaVersion: 2, marker: true } as const;\n\nexport type BindingInvalidation = {\n\treadonly schemaVersion: 1;\n\treadonly invalidated: true;\n\treadonly reason: string;\n};\n\ntype BranchEntry = {\n\treadonly id?: string;\n\treadonly type: string;\n\treadonly customType?: string;\n\treadonly data?: unknown;\n\treadonly message?: unknown;\n};\n\nexport type StoredBindingAnchor = {\n\treadonly sessionPath: string;\n\treadonly sessionId: string;\n\treadonly markerEntryId: string;\n\treadonly assistantContentHash: string;\n};\n\nexport type BindingEntryState = {\n\treadonly sdkSessionId: string;\n\treadonly accountName: string;\n\treadonly modelId: string;\n\treadonly systemPromptHash: string;\n\treadonly toolsetHash: string;\n\treadonly assistantUuidByIndex: ReadonlyMap<number, string>;\n};\n\n/**\n * The record is derived from the registry entry plus the hashes the branch\n * actually carries, never from the process binding map: that map holds the\n * previous turn's state while `message_end` runs (and only a prefix digest right\n * after a restart), so reading it would anchor this turn's marker to a stale or\n * absent sent-stream.\n */\nexport function storedBindingFromEntry(\n\tentry: BindingEntryState,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: entry.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: entry.assistantUuidByIndex.get(hashes.length) ?? null,\n\t\taccountName: entry.accountName,\n\t\tmodelId: entry.modelId,\n\t\tsystemPromptHash: entry.systemPromptHash,\n\t\ttoolsetHash: entry.toolsetHash,\n\t};\n}\n\n/** Persist a completed turn whose resident registry entry closed before `message_end`. */\nexport function storedBindingFromBinding(\n\tbinding: ContinuityBinding,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding | undefined {\n\tif (binding.sdkSessionIdConfirmed === false) return undefined;\n\tif (binding.sentCount !== hashes.length) return undefined;\n\tconst expectedDigest = sentHashPrefixDigest(hashes);\n\tconst bindingDigest =\n\t\tbinding.sentPrefixHash ?? (binding.sentHashes.length > 0 ? sentHashPrefixDigest(binding.sentHashes) : undefined);\n\tif (bindingDigest === undefined || bindingDigest !== expectedDigest) return undefined;\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: binding.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: binding.lastAssistantUuid,\n\t\taccountName: binding.accountName,\n\t\tmodelId: binding.modelId,\n\t\tsystemPromptHash: binding.systemPromptHash,\n\t\ttoolsetHash: binding.toolsetHash,\n\t};\n}\n\nexport function bindingFromStoredBranch(\n\tbranch: readonly BranchEntry[],\n\tstored: StoredBinding,\n): ContinuityBinding | undefined {\n\tconst markerIndex = newestBindingEntryIndex(branch);\n\tif (markerIndex < 0) return undefined;\n\tconst marker = branch[markerIndex];\n\tif (\n\t\tmarker?.id !== stored.markerEntryId ||\n\t\t!isBindingMarker(marker.data) ||\n\t\t!branch.slice(markerIndex + 2).every(isSafeBindingSuffix)\n\t) {\n\t\treturn undefined;\n\t}\n\tconst committedAssistant = branch[markerIndex + 1]?.message;\n\tif (!isAssistantMessage(committedAssistant)) return undefined;\n\tif (assistantContentHash(committedAssistant) !== stored.assistantContentHash) return undefined;\n\treturn bindingFromStored(stored);\n}\n\n/**\n * Display-only metadata the co-resident builtins append after the committed\n * assistant (stop-hook state/diagnostics/output, rule activations, rule scans).\n * None participates in the sent stream, so none can shift the prefix digest.\n */\nconst SAFE_BINDING_SUFFIX_TYPES: ReadonlySet<string> = new Set([\n\t\"senpi.hooks.stop-state\",\n\t\"senpi.hooks.stop-diagnostics\",\n\t\"senpi.hooks.stop-output\",\n\t\"pi-rules.scan\",\n\t\"rule-activation\",\n\t\"goal-cache-warmup\",\n]);\n\nfunction isSafeBindingSuffix(entry: BranchEntry): boolean {\n\tif (entry.type === \"label\") return true;\n\tif (entry.type === \"custom_message\") return entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE;\n\treturn entry.type === \"custom\" && entry.customType !== undefined && SAFE_BINDING_SUFFIX_TYPES.has(entry.customType);\n}\n\nfunction newestBindingEntryIndex(branch: readonly BranchEntry[]): number {\n\tfor (let index = branch.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = branch[index];\n\t\tif (entry?.type === \"custom\" && entry.customType === BINDING_ENTRY_TYPE) return index;\n\t}\n\treturn -1;\n}\n\nfunction isBindingMarker(value: unknown): boolean {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"schemaVersion\" in value && value.schemaVersion === 2 && \"marker\" in value && value.marker === true;\n}\n\nfunction isAssistantMessage(value: unknown): value is AssistantMessage {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn (\n\t\t\"role\" in value &&\n\t\tvalue.role === \"assistant\" &&\n\t\t\"api\" in value &&\n\t\ttypeof value.api === \"string\" &&\n\t\t\"provider\" in value &&\n\t\ttypeof value.provider === \"string\" &&\n\t\t\"model\" in value &&\n\t\ttypeof value.model === \"string\" &&\n\t\t\"content\" in value &&\n\t\tArray.isArray(value.content)\n\t);\n}\n\nfunction bindingFromStored(stored: StoredBinding): ContinuityBinding {\n\treturn {\n\t\tsenpiSessionId: stored.sessionId,\n\t\tsdkSessionId: stored.sdkSessionId,\n\t\tsentCount: stored.sentCount,\n\t\tsentHashes: [],\n\t\tsentPrefixHash: stored.sentPrefixHash,\n\t\tlastAssistantUuid: stored.lastAssistantUuid,\n\t\tassistantUuidByIndex: stored.lastAssistantUuid === null ? [] : [[stored.sentCount, stored.lastAssistantUuid]],\n\t\taccountName: stored.accountName,\n\t\tmodelId: stored.modelId,\n\t\tsystemPromptHash: stored.systemPromptHash,\n\t\ttoolsetHash: stored.toolsetHash,\n\t};\n}\n"]}
1
+ {"version":3,"file":"session-binding.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { StoredBinding } from \"./session-binding-store.ts\";\nimport { assistantContentHash } from \"./session-commit-boundary.ts\";\nimport type { ContinuityBinding } from \"./session-reattach.ts\";\nimport { sentHashPrefixDigest } from \"./session-sync.ts\";\n\nexport const BINDING_ENTRY_TYPE = \"claude-sdk-oauth-binding\";\nexport const BINDING_MARKER = { schemaVersion: 2, marker: true } as const;\n\nexport type BindingInvalidation = {\n\treadonly schemaVersion: 1;\n\treadonly invalidated: true;\n\treadonly reason: string;\n};\n\ntype BranchEntry = {\n\treadonly id?: string;\n\treadonly type: string;\n\treadonly customType?: string;\n\treadonly data?: unknown;\n\treadonly message?: unknown;\n};\n\nexport type StoredBindingAnchor = {\n\treadonly sessionPath: string;\n\treadonly sessionId: string;\n\treadonly markerEntryId: string;\n\treadonly assistantContentHash: string;\n};\n\nexport type BindingEntryState = {\n\treadonly sdkSessionId: string;\n\treadonly accountName: string;\n\treadonly modelId: string;\n\treadonly systemPromptHash: string;\n\treadonly toolsetHash: string;\n\treadonly assistantUuidByIndex: ReadonlyMap<number, string>;\n};\n\n/**\n * The record is derived from the registry entry plus the hashes the branch\n * actually carries, never from the process binding map: that map holds the\n * previous turn's state while `message_end` runs (and only a prefix digest right\n * after a restart), so reading it would anchor this turn's marker to a stale or\n * absent sent-stream.\n */\nexport function storedBindingFromEntry(\n\tentry: BindingEntryState,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: entry.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: entry.assistantUuidByIndex.get(hashes.length) ?? null,\n\t\taccountName: entry.accountName,\n\t\tmodelId: entry.modelId,\n\t\tsystemPromptHash: entry.systemPromptHash,\n\t\ttoolsetHash: entry.toolsetHash,\n\t};\n}\n\n/** Persist a completed turn whose resident registry entry closed before `message_end`. */\nexport function storedBindingFromBinding(\n\tbinding: ContinuityBinding,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding | undefined {\n\tif (binding.sdkSessionIdConfirmed === false) return undefined;\n\tif (binding.sentCount !== hashes.length) return undefined;\n\tconst expectedDigest = sentHashPrefixDigest(hashes);\n\tconst bindingDigest =\n\t\tbinding.sentPrefixHash ?? (binding.sentHashes.length > 0 ? sentHashPrefixDigest(binding.sentHashes) : undefined);\n\tif (bindingDigest === undefined || bindingDigest !== expectedDigest) return undefined;\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: binding.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: binding.lastAssistantUuid,\n\t\taccountName: binding.accountName,\n\t\tmodelId: binding.modelId,\n\t\tsystemPromptHash: binding.systemPromptHash,\n\t\ttoolsetHash: binding.toolsetHash,\n\t};\n}\n\nexport function bindingFromStoredBranch(\n\tbranch: readonly BranchEntry[],\n\tstored: StoredBinding,\n): ContinuityBinding | undefined {\n\tconst markerIndex = newestBindingEntryIndex(branch);\n\tif (markerIndex < 0) return undefined;\n\tconst marker = branch[markerIndex];\n\tif (marker?.id !== stored.markerEntryId || !isBindingMarker(marker.data)) return undefined;\n\tconst assistantIndex = committedAssistantIndex(branch, markerIndex + 1);\n\tif (assistantIndex < 0 || !branch.slice(assistantIndex + 1).every(isLedgerOnlyEntry)) return undefined;\n\tconst committedAssistant = branch[assistantIndex]?.message;\n\tif (!isAssistantMessage(committedAssistant)) return undefined;\n\tif (assistantContentHash(committedAssistant) !== stored.assistantContentHash) return undefined;\n\treturn bindingFromStored(stored);\n}\n\n/**\n * The marker is appended inside `message_end`, so handlers that run after this\n * builtin (and extensions loaded later) can append ledger entries before the\n * assistant itself persists. The committed assistant is the first message after\n * the marker; anything that reaches the model in between fails closed.\n */\nfunction committedAssistantIndex(branch: readonly BranchEntry[], from: number): number {\n\tfor (let index = from; index < branch.length; index += 1) {\n\t\tconst entry = branch[index];\n\t\tif (entry?.type === \"message\") return index;\n\t\tif (!entry || !isLedgerOnlyEntry(entry)) return -1;\n\t}\n\treturn -1;\n}\n\n/**\n * Entry types the session-manager never projects into the LLM context. They\n * cannot shift the sent-stream digest the binding is verified against, so any\n * `custom` ledger record (hook state, rule scans, memory bookkeeping, ...) is\n * admitted regardless of who wrote it. Everything the model can see - messages,\n * custom messages other than the goal continuation, compaction and branch\n * summaries - keeps failing closed (oh-my-openagent#7925).\n */\nconst LEDGER_ONLY_ENTRY_TYPES: ReadonlySet<string> = new Set([\n\t\"custom\",\n\t\"label\",\n\t\"session_info\",\n\t\"thinking_level_change\",\n\t\"model_change\",\n\t\"configuration_update\",\n]);\n\nfunction isLedgerOnlyEntry(entry: BranchEntry): boolean {\n\tif (entry.type === \"custom_message\") return entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE;\n\treturn LEDGER_ONLY_ENTRY_TYPES.has(entry.type);\n}\n\nfunction newestBindingEntryIndex(branch: readonly BranchEntry[]): number {\n\tfor (let index = branch.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = branch[index];\n\t\tif (entry?.type === \"custom\" && entry.customType === BINDING_ENTRY_TYPE) return index;\n\t}\n\treturn -1;\n}\n\nfunction isBindingMarker(value: unknown): boolean {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"schemaVersion\" in value && value.schemaVersion === 2 && \"marker\" in value && value.marker === true;\n}\n\nfunction isAssistantMessage(value: unknown): value is AssistantMessage {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn (\n\t\t\"role\" in value &&\n\t\tvalue.role === \"assistant\" &&\n\t\t\"api\" in value &&\n\t\ttypeof value.api === \"string\" &&\n\t\t\"provider\" in value &&\n\t\ttypeof value.provider === \"string\" &&\n\t\t\"model\" in value &&\n\t\ttypeof value.model === \"string\" &&\n\t\t\"content\" in value &&\n\t\tArray.isArray(value.content)\n\t);\n}\n\nfunction bindingFromStored(stored: StoredBinding): ContinuityBinding {\n\treturn {\n\t\tsenpiSessionId: stored.sessionId,\n\t\tsdkSessionId: stored.sdkSessionId,\n\t\tsentCount: stored.sentCount,\n\t\tsentHashes: [],\n\t\tsentPrefixHash: stored.sentPrefixHash,\n\t\tlastAssistantUuid: stored.lastAssistantUuid,\n\t\tassistantUuidByIndex: stored.lastAssistantUuid === null ? [] : [[stored.sentCount, stored.lastAssistantUuid]],\n\t\taccountName: stored.accountName,\n\t\tmodelId: stored.modelId,\n\t\tsystemPromptHash: stored.systemPromptHash,\n\t\ttoolsetHash: stored.toolsetHash,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-commit-boundary.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,CAAC;AAE5E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAgBtE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMvF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAEhE,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIlE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB;IAQvF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGzB"}
1
+ {"version":3,"file":"session-commit-boundary.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,CAAC;AAyB5E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAQtE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMvF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAEhE,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIlE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB;IAQvF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGzB"}
@@ -1,21 +1,32 @@
1
1
  import { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "./account-management.js";
2
2
  import { sessionSyncDigest } from "./session-sync.js";
3
+ /**
4
+ * Only the payload the model produced is fingerprinted. Everything the stream
5
+ * pipeline stamps around it (thinking timing, content-block indices, partial
6
+ * JSON) can legitimately differ between the last `message_update` and `message_end`
7
+ * without any extension rewriting the answer; hashing such fields marked plain
8
+ * turns `assistant_rewritten` and forced a full re-send on the next turn
9
+ * (senpi#691, oh-my-openagent#7925). An unknown block shape stays fail-closed.
10
+ */
11
+ function semanticContentBlock(block) {
12
+ switch (block.type) {
13
+ case "text":
14
+ return { type: block.type, text: block.text };
15
+ case "thinking":
16
+ return { type: block.type, thinking: block.thinking, thinkingSignature: block.thinkingSignature };
17
+ case "toolCall":
18
+ return { type: block.type, id: block.id, name: block.name, arguments: block.arguments };
19
+ default:
20
+ return block;
21
+ }
22
+ }
3
23
  export function assistantContentHash(message) {
4
24
  return sessionSyncDigest({
5
25
  role: message.role,
6
26
  api: message.api,
7
27
  provider: message.provider,
8
28
  model: message.model,
9
- content: message.content.map((block) => {
10
- if (block.type !== "thinking")
11
- return block;
12
- // Agent-core stamps these display-only fields after the final
13
- // message_update; every semantic thinking field stays fail-closed.
14
- const stableBlock = { ...block };
15
- delete stableBlock.startedAt;
16
- delete stableBlock.endedAt;
17
- return stableBlock;
18
- }),
29
+ content: message.content.map(semanticContentBlock),
19
30
  });
20
31
  }
21
32
  export function isResidentAssistant(message, modelId) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-commit-boundary.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAItD,MAAM,UAAU,oBAAoB,CAAC,OAAyB;IAC7D,OAAO,iBAAiB,CAAC;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACtC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;gBAAE,OAAO,KAAK,CAAC;YAC5C,8DAA8D;YAC9D,mEAAmE;YACnE,MAAM,WAAW,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;YACjC,OAAO,WAAW,CAAC,SAAS,CAAC;YAC7B,OAAO,WAAW,CAAC,OAAO,CAAC;YAC3B,OAAO,WAAW,CAAC;QACpB,CAAC,CAAC;KACF,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAyB,EAAE,OAAe;IAC7E,OAAO,CACN,OAAO,CAAC,GAAG,KAAK,4BAA4B;QAC5C,OAAO,CAAC,QAAQ,KAAK,4BAA4B;QACjD,OAAO,CAAC,KAAK,KAAK,OAAO,CACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IAC1D,OAAO,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IAApC;QACkB,uBAAkB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAiBjE,CAAC;IAfA,oBAAoB,CAAC,GAAW,EAAE,OAAyB;QAC1D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,GAAW,EAAE,OAAyB,EAAE,OAAe;QAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC;YAAE,OAAO,cAAc,CAAC;QAClE,IAAI,aAAa,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAChD,OAAO,aAAa,KAAK,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAChF,CAAC;IAED,MAAM,CAAC,GAAW;QACjB,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\nimport { sessionSyncDigest } from \"./session-sync.ts\";\n\nexport type AssistantCommitOutcome = \"clean\" | \"rewritten\" | \"not-resident\";\n\nexport function assistantContentHash(message: AssistantMessage): string {\n\treturn sessionSyncDigest({\n\t\trole: message.role,\n\t\tapi: message.api,\n\t\tprovider: message.provider,\n\t\tmodel: message.model,\n\t\tcontent: message.content.map((block) => {\n\t\t\tif (block.type !== \"thinking\") return block;\n\t\t\t// Agent-core stamps these display-only fields after the final\n\t\t\t// message_update; every semantic thinking field stays fail-closed.\n\t\t\tconst stableBlock = { ...block };\n\t\t\tdelete stableBlock.startedAt;\n\t\t\tdelete stableBlock.endedAt;\n\t\t\treturn stableBlock;\n\t\t}),\n\t});\n}\n\nexport function isResidentAssistant(message: AssistantMessage, modelId: string): boolean {\n\treturn (\n\t\tmessage.api === CLAUDE_SDK_OAUTH_PROVIDER_ID &&\n\t\tmessage.provider === CLAUDE_SDK_OAUTH_PROVIDER_ID &&\n\t\tmessage.model === modelId\n\t);\n}\n\nexport function isTerminalFailure(message: AssistantMessage): boolean {\n\treturn message.stopReason === \"error\" || message.stopReason === \"aborted\";\n}\n\n/**\n * Divergence is decided by comparing what the provider streamed against what the\n * session ledger committed, never by in-flight staging: a result-only turn fills\n * its content at the terminal message with no preceding delta, so a staged-hash\n * comparison reports false divergence on a perfectly valid SDK response shape.\n */\nexport class AssistantCommitBoundary {\n\tprivate readonly providerFinalByKey = new Map<string, string>();\n\n\tcaptureProviderFinal(key: string, message: AssistantMessage): void {\n\t\tthis.providerFinalByKey.set(key, assistantContentHash(message));\n\t}\n\n\tcommit(key: string, message: AssistantMessage, modelId: string): AssistantCommitOutcome {\n\t\tconst providerFinal = this.providerFinalByKey.get(key);\n\t\tthis.providerFinalByKey.delete(key);\n\t\tif (!isResidentAssistant(message, modelId)) return \"not-resident\";\n\t\tif (providerFinal === undefined) return \"clean\";\n\t\treturn providerFinal === assistantContentHash(message) ? \"clean\" : \"rewritten\";\n\t}\n\n\tforget(key: string): void {\n\t\tthis.providerFinalByKey.delete(key);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-commit-boundary.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAMtD;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAAC,KAAmB;IAChD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,MAAM;YACV,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QAC/C,KAAK,UAAU;YACd,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC;QACnG,KAAK,UAAU;YACd,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;QACzF;YACC,OAAO,KAAK,CAAC;IACf,CAAC;AACF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAyB;IAC7D,OAAO,iBAAiB,CAAC;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;KAClD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAyB,EAAE,OAAe;IAC7E,OAAO,CACN,OAAO,CAAC,GAAG,KAAK,4BAA4B;QAC5C,OAAO,CAAC,QAAQ,KAAK,4BAA4B;QACjD,OAAO,CAAC,KAAK,KAAK,OAAO,CACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IAC1D,OAAO,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IAApC;QACkB,uBAAkB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAiBjE,CAAC;IAfA,oBAAoB,CAAC,GAAW,EAAE,OAAyB;QAC1D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,GAAW,EAAE,OAAyB,EAAE,OAAe;QAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC;YAAE,OAAO,cAAc,CAAC;QAClE,IAAI,aAAa,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAChD,OAAO,aAAa,KAAK,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAChF,CAAC;IAED,MAAM,CAAC,GAAW;QACjB,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\nimport { sessionSyncDigest } from \"./session-sync.ts\";\n\nexport type AssistantCommitOutcome = \"clean\" | \"rewritten\" | \"not-resident\";\n\ntype ContentBlock = AssistantMessage[\"content\"][number];\n\n/**\n * Only the payload the model produced is fingerprinted. Everything the stream\n * pipeline stamps around it (thinking timing, content-block indices, partial\n * JSON) can legitimately differ between the last `message_update` and `message_end`\n * without any extension rewriting the answer; hashing such fields marked plain\n * turns `assistant_rewritten` and forced a full re-send on the next turn\n * (senpi#691, oh-my-openagent#7925). An unknown block shape stays fail-closed.\n */\nfunction semanticContentBlock(block: ContentBlock): unknown {\n\tswitch (block.type) {\n\t\tcase \"text\":\n\t\t\treturn { type: block.type, text: block.text };\n\t\tcase \"thinking\":\n\t\t\treturn { type: block.type, thinking: block.thinking, thinkingSignature: block.thinkingSignature };\n\t\tcase \"toolCall\":\n\t\t\treturn { type: block.type, id: block.id, name: block.name, arguments: block.arguments };\n\t\tdefault:\n\t\t\treturn block;\n\t}\n}\n\nexport function assistantContentHash(message: AssistantMessage): string {\n\treturn sessionSyncDigest({\n\t\trole: message.role,\n\t\tapi: message.api,\n\t\tprovider: message.provider,\n\t\tmodel: message.model,\n\t\tcontent: message.content.map(semanticContentBlock),\n\t});\n}\n\nexport function isResidentAssistant(message: AssistantMessage, modelId: string): boolean {\n\treturn (\n\t\tmessage.api === CLAUDE_SDK_OAUTH_PROVIDER_ID &&\n\t\tmessage.provider === CLAUDE_SDK_OAUTH_PROVIDER_ID &&\n\t\tmessage.model === modelId\n\t);\n}\n\nexport function isTerminalFailure(message: AssistantMessage): boolean {\n\treturn message.stopReason === \"error\" || message.stopReason === \"aborted\";\n}\n\n/**\n * Divergence is decided by comparing what the provider streamed against what the\n * session ledger committed, never by in-flight staging: a result-only turn fills\n * its content at the terminal message with no preceding delta, so a staged-hash\n * comparison reports false divergence on a perfectly valid SDK response shape.\n */\nexport class AssistantCommitBoundary {\n\tprivate readonly providerFinalByKey = new Map<string, string>();\n\n\tcaptureProviderFinal(key: string, message: AssistantMessage): void {\n\t\tthis.providerFinalByKey.set(key, assistantContentHash(message));\n\t}\n\n\tcommit(key: string, message: AssistantMessage, modelId: string): AssistantCommitOutcome {\n\t\tconst providerFinal = this.providerFinalByKey.get(key);\n\t\tthis.providerFinalByKey.delete(key);\n\t\tif (!isResidentAssistant(message, modelId)) return \"not-resident\";\n\t\tif (providerFinal === undefined) return \"clean\";\n\t\treturn providerFinal === assistantContentHash(message) ? \"clean\" : \"rewritten\";\n\t}\n\n\tforget(key: string): void {\n\t\tthis.providerFinalByKey.delete(key);\n\t}\n}\n"]}
@@ -38,6 +38,8 @@ export type ContinuityDecisionInput = {
38
38
  toolsetHash: string;
39
39
  };
40
40
  transcriptAvailable: boolean;
41
+ /** false only on the config-dir lane, whose per-account credential roots cannot share a transcript root, so cross-account resume is impossible there. */
42
+ crossAccountResumeSupported: boolean;
41
43
  idleExpired?: boolean;
42
44
  };
43
45
  export type ContinuityDecision = {
@@ -60,25 +62,10 @@ export type ContinuityDecision = {
60
62
  kind: "flatten";
61
63
  reason: ContinuityReason;
62
64
  };
63
- export type FailoverLane = "oauth-slots" | "ambient" | "config-dir";
64
- export type FailoverContinuityInput = {
65
- authLane: FailoverLane;
66
- crossAccountResumeSupported: boolean;
67
- entry: {
68
- sdkSessionId: string;
69
- sentCount: number;
70
- lastAssistantUuid: string | null;
71
- };
72
- };
73
- /**
74
- * The config-dir lane keeps each account's credentials inside its own
75
- * CLAUDE_CONFIG_DIR, and no official SDK API moves a transcript across roots, so
76
- * its failover is the one declared residual that must still flatten.
77
- */
78
- export declare function decideFailoverContinuity(input: FailoverContinuityInput): ContinuityDecision;
79
65
  /**
80
66
  * Resume-first: a live session is never abandoned for a flattened re-send. Only a
81
- * missing transcript or an unrecoverable boundary reaches `flatten`; every other
67
+ * missing transcript, an unrecoverable boundary, a model identity drift, or account
68
+ * drift on the config-dir lane on a persisted binding reaches `flatten`; every other
82
69
  * divergence resolves to `fork` (same lineage, new branch) or `reattach` (same
83
70
  * session, new query).
84
71
  */
@@ -1 +1 @@
1
- {"version":3,"file":"session-continuity.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-continuity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-continuity.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-continuity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,MAAM,MAAM,uBAAuB,GAAG;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sGAAsG;IACtG,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAC/C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yJAAyJ;IACzJ,2BAA2B,EAAE,OAAO,CAAC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC3B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC9F;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AA6JjD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,uBAAuB,GAAG,kBAAkB,CA8BzF"}
@@ -41,9 +41,9 @@ function identityDrift(input, entry) {
41
41
  if (entry.modelId !== input.modelId)
42
42
  return "model_changed";
43
43
  if (entry.systemPromptHash !== input.fingerprint.systemPromptHash)
44
- return "options_changed";
44
+ return "system_prompt_changed";
45
45
  if (entry.toolsetHash !== input.fingerprint.toolsetHash)
46
- return "options_changed";
46
+ return "toolset_changed";
47
47
  return null;
48
48
  }
49
49
  /**
@@ -96,8 +96,19 @@ function decideFromBinding(input, binding) {
96
96
  if (!input.transcriptAvailable)
97
97
  return { kind: "flatten", reason: "transcript_missing" };
98
98
  const drift = identityDrift(input, binding);
99
- if (drift)
99
+ // Model identity drift fails closed: the persisted identity no longer matches the turn.
100
+ // Account drift flattens only on the config-dir lane, whose per-account roots cannot
101
+ // share a transcript; on shared-root lanes it falls through like prompt/toolset drift
102
+ // (senpi#1432), so the retry checkpoint forks a same-turn failover at the pre-turn
103
+ // boundary and a matching prefix reattaches with reason account_changed.
104
+ if (drift === "model_changed")
100
105
  return { kind: "flatten", reason: drift };
106
+ if (drift === "account_changed" && !input.crossAccountResumeSupported)
107
+ return { kind: "flatten", reason: "cross_root_unsupported" };
108
+ // Prompt/toolset drift instead reattaches like the live path
109
+ // (oh-my-openagent#7884) - a restart has no live query, so the resume builds a
110
+ // fresh query carrying the CURRENT options and hooks, and flattening would
111
+ // re-send the whole conversation for drift the SDK applies per-query anyway.
101
112
  const retry = retryCheckpointDecision(input, binding);
102
113
  if (retry)
103
114
  return retry;
@@ -109,7 +120,7 @@ function decideFromBinding(input, binding) {
109
120
  kind: "reattach",
110
121
  sdkSessionId: binding.sdkSessionId,
111
122
  from: binding.sentCount,
112
- reason: "registry_miss",
123
+ reason: drift ?? "registry_miss",
113
124
  };
114
125
  }
115
126
  return {
@@ -119,7 +130,12 @@ function decideFromBinding(input, binding) {
119
130
  }
120
131
  const shared = commonPrefixLength(binding.sentHashes, input.currentHashes);
121
132
  if (shared === binding.sentCount) {
122
- return { kind: "reattach", sdkSessionId: binding.sdkSessionId, from: binding.sentCount, reason: "registry_miss" };
133
+ return {
134
+ kind: "reattach",
135
+ sdkSessionId: binding.sdkSessionId,
136
+ from: binding.sentCount,
137
+ reason: drift ?? "registry_miss",
138
+ };
123
139
  }
124
140
  if (!binding.lastAssistantUuid)
125
141
  return { kind: "flatten", reason: "registry_miss" };
@@ -131,36 +147,10 @@ function decideFromBinding(input, binding) {
131
147
  reason: shared < binding.sentCount ? "history_rolled_back" : "sent_stream_diverged",
132
148
  };
133
149
  }
134
- /**
135
- * The config-dir lane keeps each account's credentials inside its own
136
- * CLAUDE_CONFIG_DIR, and no official SDK API moves a transcript across roots, so
137
- * its failover is the one declared residual that must still flatten.
138
- */
139
- export function decideFailoverContinuity(input) {
140
- const { entry } = input;
141
- if (input.authLane === "config-dir")
142
- return { kind: "flatten", reason: "cross_root_unsupported" };
143
- if (input.crossAccountResumeSupported) {
144
- return {
145
- kind: "reattach",
146
- sdkSessionId: entry.sdkSessionId,
147
- from: entry.sentCount,
148
- reason: "account_changed",
149
- };
150
- }
151
- if (!entry.lastAssistantUuid)
152
- return { kind: "flatten", reason: "branch_boundary_unavailable" };
153
- return {
154
- kind: "fork",
155
- sdkSessionId: entry.sdkSessionId,
156
- atUuid: entry.lastAssistantUuid,
157
- from: entry.sentCount,
158
- reason: "account_changed",
159
- };
160
- }
161
150
  /**
162
151
  * Resume-first: a live session is never abandoned for a flattened re-send. Only a
163
- * missing transcript or an unrecoverable boundary reaches `flatten`; every other
152
+ * missing transcript, an unrecoverable boundary, a model identity drift, or account
153
+ * drift on the config-dir lane on a persisted binding reaches `flatten`; every other
164
154
  * divergence resolves to `fork` (same lineage, new branch) or `reattach` (same
165
155
  * session, new query).
166
156
  */