mixdog 1.3.5 → 1.4.1

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 (515) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/gate-local.mjs +16 -5
  7. package/scripts/latest-guard.mjs +21 -9
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +37 -37
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +123 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/native-release-status.mjs +2 -2
  14. package/scripts/post-release-check.mjs +1 -6
  15. package/scripts/pptx-kit-index.mjs +17 -4
  16. package/scripts/recall-history-cases.json +1 -1
  17. package/scripts/suite-health.mjs +20 -2
  18. package/scripts/test-data-dir.mjs +10 -7
  19. package/scripts/test.mjs +7 -11
  20. package/src/agents/reviewer/AGENT.md +7 -11
  21. package/src/agents/reviewer/agent.json +1 -1
  22. package/src/app.mjs +4 -0
  23. package/src/defaults/shipped-history.json +22 -1
  24. package/src/defaults/skills/browser-use/SKILL.md +62 -12
  25. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  26. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  27. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  28. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  29. package/src/defaults/skills/computer-use/SKILL.md +35 -9
  30. package/src/defaults/skills/setup/SKILL.md +22 -0
  31. package/src/defaults/skills/setup/references/actions.md +39 -5
  32. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  33. package/src/defaults/skills/visualize/SKILL.md +2 -1
  34. package/src/lib/rules-builder.cjs +39 -20
  35. package/src/output-styles/common.md +2 -2
  36. package/src/output-styles/simple.md +1 -1
  37. package/src/rules/agent/AGENT.md +11 -10
  38. package/src/rules/lead/LEAD.md +23 -20
  39. package/src/rules/shared/05-tool-calls.md +5 -6
  40. package/src/rules/shared/10-tool-workflow.md +4 -0
  41. package/src/rules/shared/45-destructive.md +0 -2
  42. package/src/rules/shared/50-execution.md +2 -0
  43. package/src/rules/shared/60-verification.md +7 -5
  44. package/src/rules/shared/70-delivery.md +7 -9
  45. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
  46. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  47. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  51. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  52. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
  53. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
  54. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  55. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  56. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  57. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
  58. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
  59. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  60. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  63. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
  71. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  72. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
  73. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  75. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  76. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  77. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  78. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  79. package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
  83. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  84. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  85. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  87. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  88. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  89. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  90. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  91. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  92. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  93. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  106. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  113. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
  117. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  118. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  119. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
  120. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  121. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  122. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
  131. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  132. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  133. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
  134. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  136. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  137. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  138. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
  139. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  140. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  141. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  142. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
  143. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
  144. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  145. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  146. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
  147. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  148. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  149. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  150. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  151. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
  153. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
  154. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  155. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  158. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
  159. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
  162. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  163. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  164. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
  165. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  166. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  167. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  168. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  172. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  173. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  174. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
  175. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  176. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  177. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
  178. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
  179. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
  182. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
  183. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
  185. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  187. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
  188. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
  189. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  191. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
  192. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  193. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  203. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
  209. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
  214. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  217. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  218. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  225. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
  226. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
  227. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  228. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
  229. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  231. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  232. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  233. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  234. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  235. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  236. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  237. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  238. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  239. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  240. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  241. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
  243. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  244. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  245. package/src/runtime/browser-bridge/client.mjs +73 -8
  246. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  247. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  248. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  249. package/src/runtime/channels/lib/config.mjs +6 -61
  250. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  251. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  252. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  253. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  254. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  255. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  256. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  257. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  258. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  259. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  260. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  261. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  262. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  263. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  264. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  265. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  266. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  267. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  268. package/src/runtime/channels/lib/whisper-port.mjs +10 -1
  269. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  270. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  271. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  272. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  273. package/src/runtime/computer-bridge/actions.mjs +9 -1
  274. package/src/runtime/computer-bridge/client.mjs +180 -8
  275. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  276. package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
  277. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  278. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  279. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  280. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  281. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  282. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  283. package/src/runtime/connectors/google-mcp.mjs +10 -12
  284. package/src/runtime/local-provider/server-process.mjs +2 -1
  285. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  286. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  287. package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
  288. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  289. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  290. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  291. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  292. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  293. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  294. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  295. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  296. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  297. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  298. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  299. package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
  300. package/src/runtime/office/quality/design-review.mjs +1 -5
  301. package/src/runtime/office/quality/document-brief.mjs +1 -5
  302. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  303. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  304. package/src/runtime/session-search/session-search-db.mjs +73 -9
  305. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  306. package/src/runtime/shared/abort-race.mjs +89 -0
  307. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  308. package/src/runtime/shared/agent-kind.mjs +4 -3
  309. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  310. package/src/runtime/shared/bounded-download.mjs +8 -3
  311. package/src/runtime/shared/config.mjs +2 -13
  312. package/src/runtime/shared/connector-accounts.mjs +20 -10
  313. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  314. package/src/runtime/shared/connector-catalog.mjs +150 -0
  315. package/src/runtime/shared/connector-triggers.mjs +22 -19
  316. package/src/runtime/shared/defaults-separation.mjs +2 -17
  317. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  318. package/src/runtime/shared/err-text.mjs +24 -15
  319. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  320. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  321. package/src/runtime/shared/file-permissions.d.mts +0 -8
  322. package/src/runtime/shared/file-permissions.mjs +0 -11
  323. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  324. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  325. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  326. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  327. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  328. package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
  329. package/src/runtime/shared/llm/cost.mjs +5 -1
  330. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  331. package/src/runtime/shared/loopback-listener.mjs +25 -2
  332. package/src/runtime/shared/mixy-presence.mjs +22 -0
  333. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  334. package/src/runtime/shared/model-route-chain.mjs +22 -4
  335. package/src/runtime/shared/open-url.mjs +10 -0
  336. package/src/runtime/shared/orchestration.d.mts +2 -0
  337. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  338. package/src/runtime/shared/profile-config.cjs +1 -1
  339. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  340. package/src/runtime/shared/prompt-origin.mjs +21 -0
  341. package/src/runtime/shared/provider-accounts.mjs +7 -1
  342. package/src/runtime/shared/provider-display-name.mjs +29 -0
  343. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  344. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  345. package/src/runtime/shared/routine-trigger.mjs +10 -0
  346. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  347. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  348. package/src/runtime/shared/session-activity-signal.mjs +48 -1
  349. package/src/runtime/shared/session-scratch.mjs +37 -0
  350. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  351. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  352. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  353. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  354. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  355. package/src/runtime/shared/tool-result-summary.mjs +2 -15
  356. package/src/runtime/shared/tool-surface.mjs +3 -0
  357. package/src/runtime/shared/tool-work-units.mjs +2 -0
  358. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  359. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  360. package/src/runtime/shared/worktrees/git.mjs +15 -0
  361. package/src/runtime/shared/worktrees/manager.mjs +87 -38
  362. package/src/runtime/shared/worktrees/test-support.mjs +14 -13
  363. package/src/runtime/terminal-bridge/client.mjs +10 -1
  364. package/src/runtime/visualize-bridge/client.mjs +29 -8
  365. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  366. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  367. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  368. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  369. package/src/session-runtime/agent-home-delivery.mjs +489 -185
  370. package/src/session-runtime/agent-task-sessions.mjs +467 -229
  371. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  372. package/src/session-runtime/boot/apis.mjs +9 -0
  373. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  374. package/src/session-runtime/boot/providers.mjs +3 -0
  375. package/src/session-runtime/boot/tools.mjs +11 -2
  376. package/src/session-runtime/bot-status.mjs +12 -6
  377. package/src/session-runtime/bot-target.mjs +38 -0
  378. package/src/session-runtime/channel-config-api.mjs +6 -1
  379. package/src/session-runtime/config-lifecycle.mjs +6 -0
  380. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  381. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  382. package/src/session-runtime/conversation-import/discovery.mjs +271 -25
  383. package/src/session-runtime/conversation-import/service.mjs +26 -5
  384. package/src/session-runtime/handoff-attachments.mjs +82 -31
  385. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
  386. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
  387. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  388. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
  389. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  390. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  391. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  392. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  393. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  394. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  395. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  396. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  397. package/src/session-runtime/model-route/set-route.mjs +11 -2
  398. package/src/session-runtime/notification-bus.mjs +31 -117
  399. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  400. package/src/session-runtime/notification-listeners.mjs +76 -0
  401. package/src/session-runtime/owned-automation-run.mjs +2 -1
  402. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  403. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  404. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  405. package/src/session-runtime/provider-models.mjs +4 -2
  406. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  407. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  408. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  409. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  410. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  411. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  412. package/src/session-runtime/resource-recall-api.mjs +6 -1
  413. package/src/session-runtime/routine-owner.mjs +40 -9
  414. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  415. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  416. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  417. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  418. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  419. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  420. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  422. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  423. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  424. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  425. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  426. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  427. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  428. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  429. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  430. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  431. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  432. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  433. package/src/session-runtime/services/channel-admin.mjs +7 -13
  434. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  435. package/src/session-runtime/services/provider-admin.mjs +2 -1
  436. package/src/session-runtime/services/seeds.mjs +0 -28
  437. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  438. package/src/session-runtime/session-create/session-options.mjs +1 -0
  439. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  440. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  441. package/src/session-runtime/settings-system-api.mjs +13 -1
  442. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  443. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  444. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  445. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  446. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  447. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  448. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  449. package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
  450. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  451. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  452. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
  453. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  454. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  455. package/src/session-runtime/workspace/transitions.mjs +25 -0
  456. package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
  457. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  458. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  459. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  460. package/src/standalone/channel-transport.mjs +1 -1
  461. package/src/standalone/daemon-channels-loader.mjs +10 -8
  462. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  463. package/src/standalone/daemon-session-control/request.mjs +51 -0
  464. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  465. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  466. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  467. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  468. package/src/standalone/daemon-session-control.mjs +142 -190
  469. package/src/standalone/daemon.mjs +26 -3
  470. package/src/standalone/session-client.mjs +7 -3
  471. package/src/standalone/session-protocol.mjs +5 -0
  472. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  473. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  474. package/src/standalone/session-service/quota-resume.mjs +3 -0
  475. package/src/standalone/session-service/retention/busy.mjs +65 -1
  476. package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
  477. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  478. package/src/standalone/session-tool-output.mjs +15 -7
  479. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  480. package/src/tui/app/app-view/floating-panel.jsx +7 -4
  481. package/src/tui/app/model-options.mjs +3 -28
  482. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  483. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  484. package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
  485. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  486. package/src/tui/app/provider-setup-picker.mjs +9 -5
  487. package/src/tui/components/QuestionPanel.jsx +13 -4
  488. package/src/tui/dist/index.mjs +133 -92
  489. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  490. package/src/tui/session/initial-state.mjs +3 -0
  491. package/src/tui/session/notice-surface.mjs +7 -1
  492. package/src/tui/session/queue-helpers.mjs +3 -42
  493. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  494. package/src/tui/session/session-api/routes-write.mjs +5 -1
  495. package/src/tui/session/session-api/routes.mjs +1 -0
  496. package/src/tui/session/session-api/settings.mjs +17 -1
  497. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  498. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  499. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  500. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  501. package/src/tui/session/session-flow/drain.mjs +118 -149
  502. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  503. package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
  504. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  505. package/src/tui/session/tool-approval-request.mjs +39 -0
  506. package/src/tui/session/tool-approval-settle.mjs +62 -0
  507. package/src/tui/session/tool-approval.mjs +69 -115
  508. package/src/tui/session/tui-steering-persist.mjs +8 -1
  509. package/src/tui/session/turn-stream.mjs +19 -2
  510. package/src/tui/session/turn.mjs +1 -0
  511. package/src/ui/statusline-agents.mjs +1 -3
  512. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  513. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  514. package/scripts/code-graph-description-contract.mjs +0 -188
  515. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -194,38 +194,63 @@ async function archiveIndexFor(path, handle) {
194
194
  return entries;
195
195
  }
196
196
 
197
- /** One page of a session's archive sidecar (see pageFromSegments). The
198
- * open handle pins the file a concurrent atomic replace may swap out, so
199
- * the index and the segment reads describe the same bytes. */
200
- export async function readCompactionArchivePage(storeDir, sessionId, range = {}) {
197
+ /** Runs `use(entries, load)` over a session's archive sidecar: its segment
198
+ * index and a loader of one segment's items. The open handle pins the file
199
+ * a concurrent atomic replace may swap out, so the index and the segment
200
+ * reads describe the same bytes. `fallback` when the archive is absent or
201
+ * unreadable (display-only history: it shows nothing then). */
202
+ async function withArchive(storeDir, sessionId, fallback, use) {
201
203
  const path = compactionArchivePath(storeDir, sessionId);
202
- if (!path) return { items: [], hasOlder: false };
204
+ if (!path) return fallback;
203
205
  let handle;
204
206
  try {
205
207
  handle = await open(path, 'r');
206
208
  } catch {
207
- // Display-only history: an absent or unreadable archive shows nothing.
208
209
  archiveIndexes.delete(path);
209
- return { items: [], hasOlder: false };
210
+ return fallback;
210
211
  }
211
212
  try {
212
213
  const entries = await archiveIndexFor(path, handle);
213
- return await pageFromSegments(
214
- entries,
215
- async (entry) => {
216
- const buffer = Buffer.alloc(entry.length);
217
- await handle.read(buffer, 0, entry.length, entry.start);
218
- return segmentItems(buffer.toString('utf8'));
219
- },
220
- range
221
- );
214
+ return await use(entries, async (entry) => {
215
+ const buffer = Buffer.alloc(entry.length);
216
+ await handle.read(buffer, 0, entry.length, entry.start);
217
+ return segmentItems(buffer.toString('utf8'));
218
+ });
222
219
  } catch {
223
- return { items: [], hasOlder: false };
220
+ return fallback;
224
221
  } finally {
225
222
  await handle.close().catch(() => {});
226
223
  }
227
224
  }
228
225
 
226
+ /** One page of a session's archive sidecar (see pageFromSegments). */
227
+ export function readCompactionArchivePage(storeDir, sessionId, range = {}) {
228
+ return withArchive(storeDir, sessionId, { items: [], hasOlder: false }, (entries, load) =>
229
+ pageFromSegments(entries, load, range)
230
+ );
231
+ }
232
+
233
+ /** Hands every visible segment of the archive (numbered in (after, before),
234
+ * oldest first) to `visit` as its items, one segment at a time, so a whole
235
+ * walk never holds more than one segment. True when the walk completed;
236
+ * false when the archive was absent or unreadable (the visits made so far
237
+ * are then incomplete). */
238
+ export function visitCompactionArchive(
239
+ storeDir,
240
+ sessionId,
241
+ { after = 0, before = Number.POSITIVE_INFINITY } = {},
242
+ visit
243
+ ) {
244
+ return withArchive(storeDir, sessionId, false, async (entries, load) => {
245
+ for (const entry of entries) {
246
+ const { seq, count } = entry.head;
247
+ if (seq <= after || seq >= before || count < 1) continue;
248
+ visit(await load(entry));
249
+ }
250
+ return true;
251
+ });
252
+ }
253
+
229
254
  // Delete fence: every deletion bumps the session's epoch. A writer captures
230
255
  // the epoch before it starts and publishes only if it is unchanged at the
231
256
  // (synchronous) rename, so a delete that lands while a segment is being
@@ -581,8 +581,20 @@ function reasoningBreakdown(message, fullTextTokens) {
581
581
  };
582
582
  }
583
583
  }
584
+ // Price each reasoning item that is actually sent (a non-empty replay
585
+ // replaces content) at its own cost; the whole-minus-visible difference only
586
+ // caps the sum so the rows never exceed the total.
587
+ const sent = message.providerReplay?.items?.length ? message.providerReplay.items.filter(isReasoningBlock) : blocks;
584
588
  return {
585
- tokens: blocks.length ? Math.max(0, fullTextTokens() - messageTextTokens(visible)) : 0,
589
+ tokens: blocks.length
590
+ ? Math.max(
591
+ 0,
592
+ Math.min(
593
+ sent.reduce((sum, block) => sum + estimateTokens(nativeBlocksEstimateText(block)), 0),
594
+ fullTextTokens() - messageTextTokens(visible)
595
+ )
596
+ )
597
+ : 0,
586
598
  blocks,
587
599
  message: visible,
588
600
  };
@@ -3,12 +3,21 @@
3
3
  * import turns. The active branch is followed from the last main-chain entry
4
4
  * back through `parentUuid` (and `logicalParentUuid` across a compaction), so
5
5
  * replayed or abandoned branches never duplicate. Kept: text blocks and
6
- * `tool_use` as `[ran tool: <name>]` notes; images become an omission marker;
7
- * a compaction summary only when the history it replaced is no longer linked.
8
- * Dropped: sidechains, meta entries, tool results, thinking, signatures and
9
- * Claude Code's own command/notification envelopes.
6
+ * `tool_use` as tool notes; images become an omission marker; a compaction
7
+ * summary (as an assistant recap) only when the history it replaced is gone;
8
+ * a slash command as `/name args` unless the app answered it locally; pasted
9
+ * text without the app's paste envelope. Dropped: sidechains, meta entries,
10
+ * tool results, thinking, signatures and Claude Code's own
11
+ * command-output/notification envelopes.
10
12
  */
11
- import { IMAGE_OMITTED_TEXT, IMPORT_WARNING_IMAGE_OMITTED, isWholeElement, textPart, toolNote } from './turns.mjs';
13
+ import {
14
+ IMAGE_OMITTED_TEXT,
15
+ IMPORT_WARNING_IMAGE_OMITTED,
16
+ isWholeElement,
17
+ textPart,
18
+ titleFromText,
19
+ toolNote,
20
+ } from './turns.mjs';
12
21
 
13
22
  const CLAUDE_ENVELOPE_TAGS = [
14
23
  'local-command-stdout',
@@ -20,11 +29,54 @@ const CLAUDE_ENVELOPE_TAGS = [
20
29
  'bash-input',
21
30
  'bash-stdout',
22
31
  'bash-stderr',
32
+ // The app's own instructions behind its "create PR" action.
33
+ 'create-pr-command',
23
34
  ];
24
- const SLASH_COMMAND_RE = /^(?:\s*<(command-name|command-message|command-args)>[\s\S]*?<\/\1>)+\s*$/;
35
+ const LOCAL_OUTPUT_TAGS = ['local-command-stdout', 'local-command-stderr'];
36
+ const SLASH_COMMAND_RE = /^(?:\s*<(command-name|command-message|command-args|skill-format)>[\s\S]*?<\/\1>)+\s*$/;
25
37
  const INTERRUPTED_RE = /^\[Request interrupted by user[^\]\n]*\]$/;
26
38
  // Claude Code's text annotation that accompanies a pasted image block.
27
39
  const IMAGE_ANNOTATION_RE = /^\[Image\b[^\n]*\]$/;
40
+ // The desktop app's paste envelope: `<pasted_content id="hhhh">\n` body
41
+ // `\n</pasted_content id="hhhh">`, one four-hex id on both tags.
42
+ const PASTE_OPEN = '<pasted_content id="';
43
+ const PASTE_ID_RE = /^[0-9a-f]{4}$/;
44
+
45
+ /**
46
+ * Text with the app's paste envelopes unwrapped the way the app displays it:
47
+ * each paste body in place, the text around it trimmed toward it, pieces on
48
+ * their own lines. Only a complete envelope with a matching id is unwrapped; any
49
+ * other `<pasted_content…>` is the user's own text and stays as typed.
50
+ */
51
+ export function unwrapClaudePastes(text) {
52
+ const pieces = [];
53
+ let cursor = 0;
54
+ let search = 0;
55
+ for (;;) {
56
+ const open = text.indexOf(PASTE_OPEN, search);
57
+ if (open < 0) break;
58
+ const idStart = open + PASTE_OPEN.length;
59
+ const id = text.slice(idStart, idStart + 4);
60
+ const bodyStart = idStart + 7; // past `hhhh">\n`
61
+ if (!PASTE_ID_RE.test(id) || text.slice(idStart + 4, bodyStart) !== '">\n') {
62
+ search = idStart;
63
+ continue;
64
+ }
65
+ const closeTag = `\n</pasted_content id="${id}">`;
66
+ // The line feed ending the open tag may also start the close tag (an empty paste).
67
+ const close = text.indexOf(closeTag, bodyStart - 1);
68
+ if (close < 0) break;
69
+ // Trimmed only toward a paste: the first fragment keeps its leading text.
70
+ const before = text.slice(cursor, open);
71
+ pieces.push(cursor ? before.trim() : before.trimEnd(), text.slice(bodyStart, Math.max(close, bodyStart)));
72
+ cursor = close + closeTag.length;
73
+ search = cursor;
74
+ }
75
+ if (!pieces.length) return text;
76
+ pieces.push(text.slice(cursor).trimStart());
77
+ const unwrapped = pieces.filter((piece, index) => index % 2 === 1 || piece).join('\n');
78
+ return unwrapped.trim() ? unwrapped : text;
79
+ }
28
80
 
29
81
  export function isClaudeEnvelopeText(text) {
30
82
  const trimmed = String(text || '').trim();
@@ -37,6 +89,17 @@ export function isClaudeEnvelopeText(text) {
37
89
  );
38
90
  }
39
91
 
92
+ const tagValue = (text, tag) => new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`).exec(text)?.[1].trim() || '';
93
+
94
+ /** A slash-command envelope as Claude Code shows it (`/name args`), else null. */
95
+ export function claudeCommandText(text) {
96
+ const trimmed = String(text || '').trim();
97
+ if (!SLASH_COMMAND_RE.test(trimmed)) return null;
98
+ const name = (tagValue(trimmed, 'command-name') || tagValue(trimmed, 'command-message')).replace(/^\//, '');
99
+ if (!name) return null;
100
+ return [`/${name}`, tagValue(trimmed, 'command-args')].filter(Boolean).join(' ');
101
+ }
102
+
40
103
  const isMessageEntry = (record) => record?.type === 'user' || record?.type === 'assistant';
41
104
  const stringOrNull = (value) => (typeof value === 'string' && value.trim() ? value.trim() : null);
42
105
  const uuidOrNull = (value) => (typeof value === 'string' ? value : null);
@@ -49,42 +112,69 @@ const metadataLength = (entry) =>
49
112
  (entry.logicalParentUuid?.length || 0) +
50
113
  (typeof entry.at === 'string' ? entry.at.length : 0);
51
114
 
115
+ // The main-chain message written last before file position `seq`: the leaf of
116
+ // the history a compaction boundary replaced.
117
+ function precedingMain(entries, seq) {
118
+ for (let index = seq - 1; index >= 0; index--) {
119
+ if (entries[index].main && entries[index].uuid !== null) return entries[index];
120
+ }
121
+ return null;
122
+ }
123
+
52
124
  /**
53
125
  * The active branch, root first: walked back from the last main-chain entry.
54
- * `crossedCompaction` tells whether a compaction boundary led back into the
55
- * history it replaced (Claude Code often no longer keeps that history).
126
+ * A compaction boundary links back to the history it replaced through its
127
+ * logical parent, or, when Claude Code never wrote that message, to the last
128
+ * message before the boundary. `replaced` holds the compaction summaries whose
129
+ * history the walk crossed into (that history is imported instead).
56
130
  */
57
131
  function activeChain(entries) {
58
132
  const main = entries.filter((entry) => entry.main);
59
133
  const leaf = main[main.length - 1];
60
- if (!leaf || leaf.uuid === null) return { chain: main, crossedCompaction: false };
134
+ if (!leaf || leaf.uuid === null) return { chain: main, replaced: new Set() };
61
135
  const byUuid = new Map();
62
136
  for (const entry of entries) {
63
137
  if (entry.uuid !== null) byUuid.set(entry.uuid, entry);
64
138
  }
65
139
  const chain = [];
66
140
  const seen = new Set();
67
- let crossedCompaction = false;
141
+ const replaced = new Set();
142
+ let summary = null;
68
143
  let current = leaf;
69
144
  while (current && !seen.has(current.uuid)) {
70
145
  seen.add(current.uuid);
71
146
  chain.push(current);
147
+ if (current.summary) summary = current;
72
148
  const parent = current.parentUuid !== null ? byUuid.get(current.parentUuid) : null;
73
- const logical = !parent && current.logicalParentUuid !== null ? byUuid.get(current.logicalParentUuid) : null;
74
- if (logical) crossedCompaction = true;
149
+ const logical =
150
+ !parent && current.logicalParentUuid !== null
151
+ ? byUuid.get(current.logicalParentUuid) || precedingMain(entries, current.seq)
152
+ : null;
153
+ if (logical && summary) {
154
+ replaced.add(summary);
155
+ summary = null;
156
+ }
75
157
  current = parent || logical;
76
158
  }
77
- return { chain: chain.reverse().filter((entry) => entry.main), crossedCompaction };
159
+ return { chain: chain.reverse().filter((entry) => entry.main), replaced };
78
160
  }
79
161
 
80
- function entryParts(role, content, warnings) {
162
+ /** Kept parts of a message; a slash command is a `command` part, a local command's output marks `localOutput`. */
163
+ function entryParts(role, content, warnings, marks) {
81
164
  const blocks = typeof content === 'string' ? [{ type: 'text', text: content }] : content;
82
165
  if (!Array.isArray(blocks)) return [];
83
166
  const parts = [];
84
167
  for (const block of blocks) {
85
168
  if (!block || typeof block !== 'object') continue;
86
169
  if (block.type === 'text' && typeof block.text === 'string') {
87
- if (role === 'user' && isClaudeEnvelopeText(block.text)) continue;
170
+ if (role === 'user') {
171
+ const command = claudeCommandText(block.text);
172
+ if (command) parts.push({ ...textPart(command), command: true });
173
+ if (isWholeElement(block.text, LOCAL_OUTPUT_TAGS)) marks.localOutput = true;
174
+ if (isClaudeEnvelopeText(block.text)) continue;
175
+ parts.push(textPart(unwrapClaudePastes(block.text)));
176
+ continue;
177
+ }
88
178
  parts.push(textPart(block.text));
89
179
  } else if (block.type === 'image') {
90
180
  warnings.add(IMPORT_WARNING_IMAGE_OMITTED);
@@ -96,6 +186,31 @@ function entryParts(role, content, warnings) {
96
186
  return parts;
97
187
  }
98
188
 
189
+ /**
190
+ * The title Claude Code's resume list shows from the records it appends to a
191
+ * transcript: the last `custom-title` (a `/rename`), else the last `ai-title`,
192
+ * then the last `summary`, then the last `last-prompt`. A blank custom title
193
+ * (a cleared rename) ends the name tier without falling back to the AI title.
194
+ * Other record types, such as `task-summary` or `agent-name`, never name it.
195
+ */
196
+ export function createClaudeTitleScan() {
197
+ let custom;
198
+ let ai;
199
+ let summary;
200
+ let lastPrompt;
201
+ return {
202
+ push(record) {
203
+ if (record.type === 'custom-title' && typeof record.customTitle === 'string') custom = record.customTitle;
204
+ else if (record.type === 'ai-title' && typeof record.aiTitle === 'string') ai = record.aiTitle;
205
+ else if (record.type === 'summary' && typeof record.summary === 'string') summary = record.summary;
206
+ else if (record.type === 'last-prompt' && typeof record.lastPrompt === 'string') lastPrompt = record.lastPrompt;
207
+ },
208
+ title() {
209
+ return titleFromText(custom ?? ai) || titleFromText(summary) || titleFromText(lastPrompt);
210
+ },
211
+ };
212
+ }
213
+
99
214
  function skippedEntry(record) {
100
215
  // Claude Code flags its compaction summary transcript-only as well.
101
216
  if (record.isCompactSummary === true) return false;
@@ -111,9 +226,12 @@ function skippedEntry(record) {
111
226
  */
112
227
  export function createClaudeReducer() {
113
228
  const entries = [];
229
+ const titleScan = createClaudeTitleScan();
114
230
  let recognized = false;
115
231
  let foreignSessionId = null;
116
232
  let cwd = null;
233
+ let sidechainSeen = false;
234
+ let mainSeen = false;
117
235
  let chars = 0;
118
236
  let metadataBytes = 0;
119
237
  return {
@@ -126,10 +244,23 @@ export function createClaudeReducer() {
126
244
  get metadataBytes() {
127
245
  return metadataBytes;
128
246
  },
247
+ /** Cheap running check: messages seen so far are all sidechain (a verdict only at the end of the file). */
248
+ get sidechainOnly() {
249
+ return sidechainSeen && !mainSeen;
250
+ },
251
+ /** Feed a record for its stored title only (a transcript's tail window). */
252
+ pushTitle(record) {
253
+ titleScan.push(record);
254
+ },
129
255
  push(record) {
256
+ titleScan.push(record);
130
257
  const message = isMessageEntry(record);
131
258
  if (message) recognized = true;
132
259
  const main = message && record.isSidechain !== true;
260
+ if (message) {
261
+ if (main) mainSeen = true;
262
+ else sidechainSeen = true;
263
+ }
133
264
  if (main) {
134
265
  foreignSessionId ||= stringOrNull(record.sessionId);
135
266
  cwd ||= stringOrNull(record.cwd);
@@ -145,13 +276,14 @@ export function createClaudeReducer() {
145
276
  parts: null,
146
277
  warnings: null,
147
278
  at: timestampOrNull(record.timestamp),
279
+ seq: entries.length,
148
280
  };
149
281
  metadataBytes += ENTRY_OVERHEAD_BYTES + metadataLength(entry);
150
282
  if (main && !skippedEntry(record)) {
151
283
  const body = record.message && typeof record.message === 'object' ? record.message : null;
152
284
  entry.role = body?.role === 'user' || body?.role === 'assistant' ? body.role : record.type;
153
285
  const warnings = new Set();
154
- entry.parts = entryParts(entry.role, body ? body.content : null, warnings);
286
+ entry.parts = entryParts(entry.role, body ? body.content : null, warnings, entry);
155
287
  if (record.isCompactSummary === true) {
156
288
  entry.summary = true;
157
289
  entry.parts = entry.parts.map((part) => ({ ...part, summary: true }));
@@ -164,15 +296,24 @@ export function createClaudeReducer() {
164
296
  result() {
165
297
  const warnings = new Set();
166
298
  const rawTurns = [];
167
- const { chain, crossedCompaction } = activeChain(entries);
168
- for (const entry of chain) {
299
+ const { chain, replaced } = activeChain(entries);
300
+ for (const [index, entry] of chain.entries()) {
169
301
  if (!entry.parts?.length) continue;
170
- // The summary stands in for history only when that history is gone.
171
- if (entry.summary && crossedCompaction) continue;
172
- rawTurns.push({ role: entry.role, parts: entry.parts, at: entry.at });
302
+ // The summary stands in for history only when that history is gone,
303
+ // and then as the model's recap, never as something the user wrote.
304
+ if (entry.summary && replaced.has(entry)) continue;
305
+ const role = entry.summary ? 'assistant' : entry.role;
306
+ // A local command (`/model`, `/rename`…) answered by the app itself is not part of the conversation.
307
+ const local =
308
+ entry.parts.some((part) => part.command) &&
309
+ chain.slice(index + 1).find((next) => next.parts?.length || next.localOutput)?.localOutput;
310
+ const parts = local ? entry.parts.filter((part) => !part.command) : entry.parts;
311
+ rawTurns.push({ role, parts, at: entry.at });
173
312
  for (const code of entry.warnings || []) warnings.add(code);
174
313
  }
175
- return { recognized, foreignSessionId, cwd, rawTurns, warnings };
314
+ // A transcript whose every message is a sidechain is a subagent's own, not a conversation.
315
+ const internalKind = this.sidechainOnly ? 'subagent' : null;
316
+ return { recognized, foreignSessionId, cwd, internalKind, rawTurns, warnings, storedTitle: titleScan.title() };
176
317
  },
177
318
  };
178
319
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Codex CLI rollout (`rollout-*.jsonl`) → raw import turns. Kept: the first
3
3
  * `session_meta` (foreign id, cwd), user/assistant `message` items as text and
4
- * tool calls as `[ran tool: <name>]` notes. Dropped: developer/system
4
+ * tool calls as tool notes. Dropped: developer/system
5
5
  * messages, Codex's own wrapper user messages, tool outputs, reasoning,
6
6
  * event_msg, token counts and turn_context.
7
7
  */
@@ -17,6 +17,7 @@ const CODEX_ENVELOPE_TAGS = [
17
17
  'user_shell_command',
18
18
  'subagent_notification',
19
19
  'skills_instructions',
20
+ 'external_codex_apps_open_page',
20
21
  ];
21
22
  const TOOL_CALL_TYPES = new Set(['function_call', 'custom_tool_call', 'local_shell_call']);
22
23
 
@@ -29,6 +30,17 @@ export function isCodexEnvelopeText(text) {
29
30
  return /^<image\b[^>]*>$/.test(trimmed) || trimmed === '</image>';
30
31
  }
31
32
 
33
+ // Codex shows a user message after the last of these headings: what precedes it
34
+ // is context the app adds for the model (IDE state, mentioned files, response
35
+ // annotations, an earlier request it already carries).
36
+ const USER_REQUEST_HEADING = '## My request for Codex:';
37
+
38
+ /** A user text part as Codex displays it. */
39
+ export function codexUserDisplayText(text) {
40
+ const at = text.lastIndexOf(USER_REQUEST_HEADING);
41
+ return at < 0 ? text : text.slice(at + USER_REQUEST_HEADING.length).trim();
42
+ }
43
+
32
44
  function messageParts(payload, warnings) {
33
45
  const content = typeof payload.content === 'string' ? [{ type: 'text', text: payload.content }] : payload.content;
34
46
  if (!Array.isArray(content)) return [];
@@ -41,8 +53,8 @@ function messageParts(payload, warnings) {
41
53
  continue;
42
54
  }
43
55
  if (typeof item.text !== 'string') continue;
44
- if (payload.role === 'user' && isCodexEnvelopeText(item.text)) continue;
45
- parts.push(textPart(item.text));
56
+ if (payload.role !== 'user') parts.push(textPart(item.text));
57
+ else if (!isCodexEnvelopeText(item.text)) parts.push(textPart(codexUserDisplayText(item.text)));
46
58
  }
47
59
  return parts;
48
60
  }
@@ -53,6 +65,31 @@ function toolName(payload) {
53
65
  }
54
66
 
55
67
  const stringOrNull = (value) => (typeof value === 'string' && value.trim() ? value.trim() : null);
68
+
69
+ // `session_meta.thread_source` values Codex gives threads it runs for itself.
70
+ const INTERNAL_THREAD_SOURCES = {
71
+ subagent: 'subagent',
72
+ guardian_review: 'guardianReview',
73
+ memory_consolidation: 'internal',
74
+ };
75
+
76
+ /**
77
+ * What kind of Codex-internal record a `session_meta` payload marks, else null
78
+ * for a conversation the user had. Markers are Codex's own: `thread_source`
79
+ * (`subagent`, `guardian_review`, `memory_consolidation`) and a `source` of the
80
+ * form `{ subagent: … }` (spawned agent, review, compact; `{ other: "guardian" }`
81
+ * is the approval reviewer) or `{ internal: … }`. Other sources (cli, vscode,
82
+ * exec, mcp, custom) and features (automation, voice chat) are the user's.
83
+ */
84
+ export function codexInternalKind(payload) {
85
+ const byThread = INTERNAL_THREAD_SOURCES[payload?.thread_source];
86
+ if (byThread) return byThread;
87
+ const source = payload?.source;
88
+ if (!source || typeof source !== 'object') return null;
89
+ if ('subagent' in source) return source.subagent?.other === 'guardian' ? 'guardianReview' : 'subagent';
90
+ if ('internal' in source) return source.internal === 'guardian' ? 'guardianReview' : 'internal';
91
+ return null;
92
+ }
56
93
  // Rough fixed cost of one retained turn object, so tiny turns still count.
57
94
  const ENTRY_OVERHEAD_BYTES = 64;
58
95
 
@@ -67,6 +104,8 @@ export function createCodexReducer() {
67
104
  let recognized = false;
68
105
  let foreignSessionId = null;
69
106
  let cwd = null;
107
+ let internalKind = null;
108
+ let historyBase = null;
70
109
  let metaSeen = false;
71
110
  let chars = 0;
72
111
  let metadataBytes = 0;
@@ -86,15 +125,19 @@ export function createCodexReducer() {
86
125
  get metadataBytes() {
87
126
  return metadataBytes;
88
127
  },
89
- push(record) {
128
+ /** `inherited` records come from a history base: its session metadata is not this thread's. */
129
+ push(record, inherited = false) {
90
130
  const payload = record?.payload && typeof record.payload === 'object' ? record.payload : null;
91
131
  if (!payload) return;
92
132
  if (record.type === 'session_meta') {
133
+ if (inherited) return;
93
134
  recognized = true;
94
135
  if (!metaSeen) {
95
136
  metaSeen = true;
96
137
  foreignSessionId = stringOrNull(payload.id) || stringOrNull(payload.session_id);
97
138
  cwd = stringOrNull(payload.cwd);
139
+ internalKind = codexInternalKind(payload);
140
+ if (payload.history_base && typeof payload.history_base === 'object') historyBase = payload.history_base;
98
141
  }
99
142
  return;
100
143
  }
@@ -108,23 +151,95 @@ export function createCodexReducer() {
108
151
  }
109
152
  },
110
153
  result() {
111
- return { recognized, foreignSessionId, cwd, rawTurns, warnings };
154
+ return { recognized, foreignSessionId, cwd, internalKind, historyBase, rawTurns, warnings };
112
155
  },
113
156
  };
114
157
  }
115
158
 
116
- /** id/cwd of a `session_meta` first line cut off by a bounded prefix read. */
117
- export function codexMetaFromTruncatedLine(line) {
118
- const text = String(line || '');
119
- if (!/"type"\s*:\s*"session_meta"/.test(text)) return null;
120
- const field = (name) => {
121
- const match = new RegExp(`"${name}"\\s*:\\s*("(?:[^"\\\\]|\\\\.)*")`).exec(text);
122
- if (!match) return null;
123
- try {
124
- return stringOrNull(JSON.parse(match[1]));
125
- } catch {
126
- return null;
159
+ // ── bounded-prefix `session_meta` scan ───────────────────────────────────────
160
+ // Index after the string starting at `i`, or -1 when the text ends inside it.
161
+ function scanString(text, i) {
162
+ for (let j = i + 1; j < text.length; j++) {
163
+ if (text[j] === '\\') j++;
164
+ else if (text[j] === '"') return j + 1;
165
+ }
166
+ return -1;
167
+ }
168
+
169
+ // Index after the JSON value starting at `i`, or -1 when the text ends inside it.
170
+ function scanValue(text, i) {
171
+ if (text[i] === '"') return scanString(text, i);
172
+ if (text[i] === '{' || text[i] === '[') {
173
+ let depth = 0;
174
+ for (let j = i; j < text.length; j++) {
175
+ if (text[j] === '"') {
176
+ j = scanString(text, j) - 1;
177
+ if (j < 0) return -1;
178
+ } else if (text[j] === '{' || text[j] === '[') depth++;
179
+ else if ((text[j] === '}' || text[j] === ']') && --depth === 0) return j + 1;
127
180
  }
181
+ return -1;
182
+ }
183
+ const literal = /[^,}\]\s]+/y;
184
+ literal.lastIndex = i;
185
+ literal.exec(text);
186
+ return literal.lastIndex < text.length ? literal.lastIndex : -1;
187
+ }
188
+
189
+ /**
190
+ * Complete top-level values (raw JSON text) of the record object and of its
191
+ * `payload` object in a possibly cut-off line. Nested values are never
192
+ * inspected, so a key inside custom metadata is not mistaken for a payload field.
193
+ */
194
+ function recordFields(text) {
195
+ const top = {};
196
+ const payload = {};
197
+ const walk = (start, target, descend) => {
198
+ let j = start + 1;
199
+ for (;;) {
200
+ while (/[\s,]/.test(text[j] ?? '')) j++;
201
+ if (text[j] !== '"') return;
202
+ const keyEnd = scanString(text, j);
203
+ if (keyEnd < 0) return;
204
+ const key = JSON.parse(text.slice(j, keyEnd));
205
+ j = keyEnd;
206
+ while (/\s/.test(text[j] ?? '')) j++;
207
+ if (text[j] !== ':') return;
208
+ j++;
209
+ while (/\s/.test(text[j] ?? '')) j++;
210
+ if (descend && key === 'payload' && text[j] === '{') return walk(j, payload, false);
211
+ const end = scanValue(text, j);
212
+ if (end < 0) return;
213
+ target[key] = text.slice(j, end);
214
+ j = end;
215
+ }
216
+ };
217
+ const open = text.indexOf('{');
218
+ if (open >= 0) walk(open, top, true);
219
+ return { top, payload };
220
+ }
221
+
222
+ const jsonOrNull = (raw) => {
223
+ try {
224
+ return raw === undefined ? null : JSON.parse(raw);
225
+ } catch {
226
+ return null;
227
+ }
228
+ };
229
+
230
+ /**
231
+ * id/cwd/internal kind of a `session_meta` first line cut off by a bounded
232
+ * prefix read, from the payload fields that arrived whole. A marker that did
233
+ * not arrive whole leaves the record unclassified (`internalKind: null`).
234
+ */
235
+ export function codexMetaFromTruncatedLine(line) {
236
+ const { top, payload } = recordFields(String(line || ''));
237
+ if (jsonOrNull(top.type) !== 'session_meta') return null;
238
+ const field = (name) => stringOrNull(jsonOrNull(payload[name]));
239
+ const meta = { thread_source: field('thread_source'), source: jsonOrNull(payload.source) };
240
+ return {
241
+ foreignSessionId: field('id') || field('session_id'),
242
+ cwd: field('cwd'),
243
+ internalKind: codexInternalKind(meta),
128
244
  };
129
- return { foreignSessionId: field('id') || field('session_id'), cwd: field('cwd') };
130
245
  }