@gajae-code/coding-agent 0.13.3 → 0.14.0

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 (599) hide show
  1. package/CHANGELOG.md +184 -2
  2. package/README.md +2 -0
  3. package/bin/gajaessi.js +4 -0
  4. package/dist/types/async/job-manager.d.ts +55 -2
  5. package/dist/types/async/support.d.ts +14 -0
  6. package/dist/types/capability/mcp.d.ts +6 -0
  7. package/dist/types/capability/types.d.ts +6 -0
  8. package/dist/types/cli/accounts-cli.d.ts +19 -0
  9. package/dist/types/cli/args.d.ts +3 -0
  10. package/dist/types/cli/config-cli.d.ts +6 -0
  11. package/dist/types/cli/crash-cli.d.ts +10 -0
  12. package/dist/types/cli/customize-doctor.d.ts +145 -0
  13. package/dist/types/cli/daemon-cli.d.ts +3 -1
  14. package/dist/types/cli/mcp-cli.d.ts +11 -0
  15. package/dist/types/cli/notify-cli.d.ts +1 -1
  16. package/dist/types/cli/root-flags.d.ts +12 -0
  17. package/dist/types/cli/setup-cli.d.ts +3 -1
  18. package/dist/types/cli/skills-cli.d.ts +2 -1
  19. package/dist/types/cli/update-cli.d.ts +19 -1
  20. package/dist/types/cli.d.ts +6 -0
  21. package/dist/types/commands/accounts.d.ts +40 -0
  22. package/dist/types/commands/crash.d.ts +24 -0
  23. package/dist/types/commands/customize.d.ts +22 -0
  24. package/dist/types/commands/daemon.d.ts +1 -1
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/commands/setup.d.ts +6 -0
  27. package/dist/types/commands/skills.d.ts +6 -1
  28. package/dist/types/commands/update.d.ts +7 -0
  29. package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
  30. package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
  31. package/dist/types/config/config-schema-version.d.ts +10 -0
  32. package/dist/types/config/file-lock.d.ts +18 -0
  33. package/dist/types/config/model-profile-activation.d.ts +3 -1
  34. package/dist/types/config/model-registry.d.ts +9 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +70 -6
  37. package/dist/types/config/settings.d.ts +63 -0
  38. package/dist/types/config/skill-settings-defaults.d.ts +26 -0
  39. package/dist/types/config/task-delegation.d.ts +39 -0
  40. package/dist/types/config/update-channel.d.ts +10 -0
  41. package/dist/types/coordinator-mcp/server.d.ts +5 -1
  42. package/dist/types/crash/index-store.d.ts +87 -0
  43. package/dist/types/crash/nudge.d.ts +50 -0
  44. package/dist/types/crash/record-loader.d.ts +17 -0
  45. package/dist/types/crash/report.d.ts +134 -0
  46. package/dist/types/crash/sanitize.d.ts +25 -0
  47. package/dist/types/cursor.d.ts +13 -2
  48. package/dist/types/customization/import.d.ts +37 -0
  49. package/dist/types/customization/index.d.ts +4 -0
  50. package/dist/types/customization/inventory.d.ts +25 -0
  51. package/dist/types/customization/mutations.d.ts +32 -0
  52. package/dist/types/customization/types.d.ts +115 -0
  53. package/dist/types/daemon/control-types.d.ts +8 -1
  54. package/dist/types/daemon/operator-contract.d.ts +4 -4
  55. package/dist/types/discovery/claude.d.ts +39 -1
  56. package/dist/types/discovery/codex.d.ts +39 -1
  57. package/dist/types/discovery/index.d.ts +2 -0
  58. package/dist/types/discovery/mcp-compat.d.ts +30 -0
  59. package/dist/types/edit/renderer.d.ts +23 -0
  60. package/dist/types/extensibility/extensions/runner.d.ts +3 -0
  61. package/dist/types/extensibility/extensions/types.d.ts +21 -4
  62. package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
  63. package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
  64. package/dist/types/extensibility/hooks/loader.d.ts +19 -5
  65. package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
  66. package/dist/types/extensibility/skill-management.d.ts +107 -0
  67. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
  68. package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
  69. package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
  70. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
  71. package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
  72. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
  73. package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
  74. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
  75. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
  76. package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
  77. package/dist/types/hooks/events.d.ts +60 -0
  78. package/dist/types/hooks/normalize.d.ts +83 -0
  79. package/dist/types/hooks/skill-state.d.ts +9 -2
  80. package/dist/types/main.d.ts +1 -1
  81. package/dist/types/modes/acp/abort-scope.d.ts +13 -0
  82. package/dist/types/modes/acp/acp-agent.d.ts +7 -4
  83. package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
  84. package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
  85. package/dist/types/modes/components/customization/index.d.ts +1 -0
  86. package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
  87. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  88. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  89. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  90. package/dist/types/modes/components/pet-capability.d.ts +11 -25
  91. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  92. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  93. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  94. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  95. package/dist/types/modes/interactive-mode.d.ts +1 -0
  96. package/dist/types/modes/types.d.ts +1 -0
  97. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  98. package/dist/types/runtime-mcp/config.d.ts +9 -0
  99. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  100. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  101. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  102. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  103. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  104. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  105. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  106. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  107. package/dist/types/runtime-mcp/types.d.ts +102 -10
  108. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  109. package/dist/types/sdk/broker/broker.d.ts +3 -55
  110. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  111. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  112. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  113. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  114. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  117. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  118. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  119. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  120. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  121. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  122. package/dist/types/sdk/bus/index.d.ts +85 -99
  123. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  124. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  125. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  126. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  127. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  128. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  129. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  130. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  131. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  132. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  133. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  135. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  136. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  137. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  138. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  139. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  140. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  141. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  142. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  143. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  144. package/dist/types/sdk/cli/rows.d.ts +2 -11
  145. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  146. package/dist/types/sdk/client/client.d.ts +97 -1
  147. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  148. package/dist/types/sdk/host/control/index.d.ts +1 -1
  149. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  150. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  151. package/dist/types/sdk/host/host.d.ts +15 -1
  152. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  153. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  154. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  155. package/dist/types/sdk/host/types.d.ts +1 -1
  156. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  157. package/dist/types/sdk/index.d.ts +2 -1
  158. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  159. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  160. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  161. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  162. package/dist/types/sdk/mcp/server.d.ts +9 -6
  163. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  164. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  165. package/dist/types/sdk/prompt-status.d.ts +10 -3
  166. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  167. package/dist/types/sdk/receipt-state.d.ts +17 -0
  168. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  169. package/dist/types/sdk/router/index.d.ts +1 -0
  170. package/dist/types/sdk/router/session-router.d.ts +152 -0
  171. package/dist/types/sdk/session-list.d.ts +22 -0
  172. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  173. package/dist/types/sdk/session.d.ts +34 -1
  174. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  175. package/dist/types/session/account-inventory.d.ts +86 -0
  176. package/dist/types/session/agent-session.d.ts +145 -6
  177. package/dist/types/session/agent-storage.d.ts +10 -0
  178. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  179. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  180. package/dist/types/session/messages.d.ts +1 -1
  181. package/dist/types/session/secure-token-file.d.ts +3 -0
  182. package/dist/types/session/session-manager.d.ts +40 -1
  183. package/dist/types/session/startup-auth-config.d.ts +44 -0
  184. package/dist/types/session/terminal-abort.d.ts +378 -0
  185. package/dist/types/session/yield-queue.d.ts +7 -0
  186. package/dist/types/session-import/claude.d.ts +26 -0
  187. package/dist/types/session-import/codex.d.ts +88 -0
  188. package/dist/types/session-import/command.d.ts +35 -0
  189. package/dist/types/session-import/detect.d.ts +22 -0
  190. package/dist/types/session-import/index.d.ts +7 -0
  191. package/dist/types/session-import/provider-codex.d.ts +22 -0
  192. package/dist/types/session-import/provider-service.d.ts +38 -0
  193. package/dist/types/session-import/redact.d.ts +23 -0
  194. package/dist/types/session-import/service.d.ts +47 -0
  195. package/dist/types/session-import/types.d.ts +120 -0
  196. package/dist/types/setup/paseo/check.d.ts +16 -0
  197. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  198. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  199. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  200. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  201. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  202. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  203. package/dist/types/setup/paseo/remove.d.ts +14 -0
  204. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  205. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  206. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  207. package/dist/types/skill-state/active-state.d.ts +5 -1
  208. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  209. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  210. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  211. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  212. package/dist/types/slash-commands/types.d.ts +7 -1
  213. package/dist/types/task/executor.d.ts +10 -0
  214. package/dist/types/task/index.d.ts +3 -1
  215. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  216. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  217. package/dist/types/tools/bash.d.ts +2 -6
  218. package/dist/types/tools/browser/attach.d.ts +11 -0
  219. package/dist/types/tools/browser/launch.d.ts +20 -0
  220. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  221. package/dist/types/tools/browser/render.d.ts +1 -0
  222. package/dist/types/tools/browser.d.ts +3 -1
  223. package/dist/types/tools/image-gen.d.ts +9 -2
  224. package/dist/types/tools/index.d.ts +8 -0
  225. package/dist/types/tools/monitor.d.ts +1 -1
  226. package/dist/types/tools/skill-discovery.d.ts +8 -1
  227. package/dist/types/tools/subagent.d.ts +2 -0
  228. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  229. package/dist/types/utils/herdr-pane.d.ts +76 -0
  230. package/package.json +19 -9
  231. package/scripts/build-binary.ts +2 -1
  232. package/scripts/build-sdk-package-smoke.ts +2 -13
  233. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  234. package/scripts/compile-args.ts +2 -0
  235. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  236. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  237. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  238. package/scripts/generate-tool-catalog.ts +6 -4
  239. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  240. package/src/async/job-manager.ts +352 -17
  241. package/src/async/support.ts +25 -0
  242. package/src/autoresearch/dashboard.ts +28 -13
  243. package/src/capability/index.ts +3 -1
  244. package/src/capability/mcp.ts +6 -0
  245. package/src/capability/types.ts +6 -0
  246. package/src/cli/accounts-cli.ts +395 -0
  247. package/src/cli/args.ts +23 -0
  248. package/src/cli/auth-broker-cli.ts +136 -66
  249. package/src/cli/auth-gateway-cli.ts +94 -70
  250. package/src/cli/config-cli.ts +27 -2
  251. package/src/cli/crash-cli.ts +78 -0
  252. package/src/cli/customize-doctor.ts +1605 -0
  253. package/src/cli/daemon-cli.ts +12 -3
  254. package/src/cli/fast-help.ts +1 -0
  255. package/src/cli/mcp-cli.ts +128 -60
  256. package/src/cli/notify-cli.ts +8 -14
  257. package/src/cli/root-flags.ts +8 -0
  258. package/src/cli/setup-cli.ts +145 -0
  259. package/src/cli/skills-cli.ts +38 -2
  260. package/src/cli/update-cli.ts +167 -12
  261. package/src/cli.ts +4 -0
  262. package/src/commands/accounts.ts +71 -0
  263. package/src/commands/crash.ts +35 -0
  264. package/src/commands/customize.ts +84 -0
  265. package/src/commands/daemon.ts +2 -2
  266. package/src/commands/deep-interview.ts +2 -0
  267. package/src/commands/launch.ts +1 -0
  268. package/src/commands/mcp.ts +12 -7
  269. package/src/commands/ralplan.ts +2 -0
  270. package/src/commands/sdk.ts +65 -32
  271. package/src/commands/setup.ts +5 -0
  272. package/src/commands/skills.ts +14 -4
  273. package/src/commands/ultragoal.ts +10 -1
  274. package/src/commands/update.ts +26 -15
  275. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  276. package/src/config/atomic-yaml-patch.ts +769 -29
  277. package/src/config/config-schema-version.ts +10 -0
  278. package/src/config/file-lock.ts +70 -1
  279. package/src/config/mcp-schema.json +52 -14
  280. package/src/config/model-profile-activation.ts +20 -1
  281. package/src/config/model-profiles.ts +29 -19
  282. package/src/config/model-registry.ts +132 -21
  283. package/src/config/models-config-schema.ts +1 -1
  284. package/src/config/settings-schema.ts +76 -6
  285. package/src/config/settings.ts +4038 -199
  286. package/src/config/skill-settings-defaults.ts +41 -3
  287. package/src/config/task-delegation.ts +87 -0
  288. package/src/config/update-channel.ts +23 -0
  289. package/src/coordinator-mcp/server.ts +377 -308
  290. package/src/crash/index-store.ts +723 -0
  291. package/src/crash/nudge.ts +89 -0
  292. package/src/crash/record-loader.ts +149 -0
  293. package/src/crash/report.ts +551 -0
  294. package/src/crash/sanitize.ts +129 -0
  295. package/src/cursor.ts +36 -10
  296. package/src/customization/import.ts +946 -0
  297. package/src/customization/index.ts +4 -0
  298. package/src/customization/inventory.ts +335 -0
  299. package/src/customization/mutations.ts +141 -0
  300. package/src/customization/types.ts +223 -0
  301. package/src/daemon/control-types.ts +8 -1
  302. package/src/daemon/operator-contract.ts +6 -6
  303. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  304. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  305. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  306. package/src/discovery/claude-hooks.ts +38 -0
  307. package/src/discovery/claude.ts +142 -209
  308. package/src/discovery/codex-hooks.ts +38 -0
  309. package/src/discovery/codex.ts +132 -198
  310. package/src/discovery/helpers.ts +8 -1
  311. package/src/discovery/index.ts +2 -0
  312. package/src/discovery/mcp-compat.ts +234 -0
  313. package/src/discovery/mcp-json.ts +6 -0
  314. package/src/edit/renderer.ts +40 -0
  315. package/src/edit/streaming.ts +4 -2
  316. package/src/exec/bash-executor.ts +24 -20
  317. package/src/export/html/index.ts +51 -2
  318. package/src/extensibility/extensions/loader.ts +9 -1
  319. package/src/extensibility/extensions/runner.ts +17 -4
  320. package/src/extensibility/extensions/types.ts +31 -6
  321. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  322. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  323. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  324. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  325. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  326. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  327. package/src/extensibility/hooks/loader.ts +154 -10
  328. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  329. package/src/extensibility/skill-management.ts +368 -0
  330. package/src/extensibility/skills.ts +52 -16
  331. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  332. package/src/gjc-runtime/launch-worktree.ts +56 -2
  333. package/src/gjc-runtime/linux-proc.ts +7 -1
  334. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  335. package/src/gjc-runtime/session-state-lock.ts +992 -0
  336. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  337. package/src/gjc-runtime/state-writer.ts +39 -14
  338. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  339. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  340. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  341. package/src/gjc-runtime/workflow-settings.ts +596 -0
  342. package/src/goals/tools/goal-tool.ts +6 -1
  343. package/src/hooks/events.ts +291 -0
  344. package/src/hooks/native-skill-hook.ts +4 -0
  345. package/src/hooks/normalize.ts +369 -0
  346. package/src/hooks/skill-state.ts +165 -46
  347. package/src/internal-urls/docs-index.generated.ts +40 -32
  348. package/src/main.ts +32 -5
  349. package/src/migrate/mcp-mapper.ts +25 -2
  350. package/src/modes/acp/abort-scope.ts +29 -0
  351. package/src/modes/acp/acp-agent.ts +423 -98
  352. package/src/modes/components/assistant-message.ts +6 -1
  353. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  354. package/src/modes/components/customization/import-wizard.ts +372 -0
  355. package/src/modes/components/customization/index.ts +1 -0
  356. package/src/modes/components/gajae-pet-widget.ts +539 -213
  357. package/src/modes/components/irc-sidebar.ts +11 -0
  358. package/src/modes/components/iterm-pet-transport.ts +585 -0
  359. package/src/modes/components/oauth-selector.ts +277 -86
  360. package/src/modes/components/pet-capability.ts +39 -40
  361. package/src/modes/components/settings-selector.ts +9 -0
  362. package/src/modes/components/status-line/gh.ts +45 -1
  363. package/src/modes/components/status-line/segments.ts +16 -1
  364. package/src/modes/components/tool-status-header.ts +13 -3
  365. package/src/modes/controllers/command-controller.ts +20 -8
  366. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  367. package/src/modes/controllers/input-controller.ts +10 -0
  368. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  369. package/src/modes/controllers/selector-controller.ts +177 -72
  370. package/src/modes/controllers/stt-controller.ts +3 -3
  371. package/src/modes/interactive-mode.ts +88 -16
  372. package/src/modes/print-mode.ts +35 -6
  373. package/src/modes/runtime-init.ts +21 -68
  374. package/src/modes/types.ts +1 -0
  375. package/src/modes/utils/injected-user-submission.ts +25 -0
  376. package/src/modes/utils/terminal-bell.ts +15 -1
  377. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  378. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  379. package/src/prompts/agents/critic.md +1 -1
  380. package/src/prompts/system/rlm-research.md +1 -1
  381. package/src/prompts/system/system-prompt.md +0 -2
  382. package/src/prompts/tools/bash.md +7 -1
  383. package/src/prompts/tools/browser.md +1 -1
  384. package/src/prompts/tools/cron.md +6 -6
  385. package/src/prompts/tools/read.md +0 -2
  386. package/src/prompts/tools/skill-discovery.md +4 -2
  387. package/src/runtime-mcp/client.ts +427 -23
  388. package/src/runtime-mcp/config.ts +37 -5
  389. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  390. package/src/runtime-mcp/manager.ts +52 -2
  391. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  392. package/src/runtime-mcp/oauth-flow.ts +46 -1
  393. package/src/runtime-mcp/pool-key.ts +5 -1
  394. package/src/runtime-mcp/pool.test.ts +9 -0
  395. package/src/runtime-mcp/protocol.test.ts +353 -0
  396. package/src/runtime-mcp/protocol.ts +624 -0
  397. package/src/runtime-mcp/scope-config.ts +78 -0
  398. package/src/runtime-mcp/tool-bridge.ts +44 -10
  399. package/src/runtime-mcp/transports/http.ts +84 -13
  400. package/src/runtime-mcp/types.ts +123 -12
  401. package/src/sdk/acp/adapter.ts +328 -97
  402. package/src/sdk/broker/broker.ts +160 -741
  403. package/src/sdk/broker/ensure.ts +9 -1
  404. package/src/sdk/broker/lifecycle.ts +510 -116
  405. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  406. package/src/sdk/broker/process-incarnation.ts +19 -0
  407. package/src/sdk/broker/session-index.ts +516 -117
  408. package/src/sdk/broker/startup-failure.ts +28 -5
  409. package/src/sdk/broker/transport.ts +1 -13
  410. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  411. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  412. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  413. package/src/sdk/bus/config.ts +13 -0
  414. package/src/sdk/bus/conversation-store.ts +59 -171
  415. package/src/sdk/bus/daemon-paths.ts +20 -0
  416. package/src/sdk/bus/discord-conversation.ts +2 -0
  417. package/src/sdk/bus/discord-daemon.ts +524 -126
  418. package/src/sdk/bus/discord-live-provider.ts +206 -79
  419. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  420. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  421. package/src/sdk/bus/index.ts +2480 -456
  422. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  423. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  424. package/src/sdk/bus/managed-daemon.ts +2 -145
  425. package/src/sdk/bus/notification-service.ts +196 -0
  426. package/src/sdk/bus/operator-runtime.ts +1 -1
  427. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  428. package/src/sdk/bus/reconciliation-store.ts +553 -24
  429. package/src/sdk/bus/session-control.ts +49 -3
  430. package/src/sdk/bus/slack-conversation.ts +4 -0
  431. package/src/sdk/bus/slack-daemon.ts +733 -134
  432. package/src/sdk/bus/slack-live-provider.ts +65 -15
  433. package/src/sdk/bus/slack-provider.ts +4 -0
  434. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  435. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  436. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  437. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  438. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  439. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  440. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  441. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  442. package/src/sdk/bus/telegram-reference.ts +1 -226
  443. package/src/sdk/bus/telegram-setup.ts +2 -2
  444. package/src/sdk/bus/threaded-render.ts +1 -0
  445. package/src/sdk/bus/topic-registry.ts +279 -146
  446. package/src/sdk/cli/rows.ts +2 -35
  447. package/src/sdk/cli/session-cli.ts +776 -700
  448. package/src/sdk/client/client.ts +892 -1
  449. package/src/sdk/host/control/dispatch.ts +93 -58
  450. package/src/sdk/host/control/index.ts +1 -1
  451. package/src/sdk/host/control/operations.ts +18 -10
  452. package/src/sdk/host/control/runtime-gate.ts +40 -0
  453. package/src/sdk/host/host.ts +63 -12
  454. package/src/sdk/host/query/handlers.ts +66 -7
  455. package/src/sdk/host/reverse-leases.ts +2 -2
  456. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  457. package/src/sdk/host/session-runtime.test.ts +2787 -34
  458. package/src/sdk/host/session-runtime.ts +1489 -101
  459. package/src/sdk/host/surface-policy.ts +12 -8
  460. package/src/sdk/host/types.ts +1 -1
  461. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  462. package/src/sdk/host/websocket-transport.ts +85 -50
  463. package/src/sdk/index.ts +2 -1
  464. package/src/sdk/lifecycle/broker-client.ts +53 -0
  465. package/src/sdk/lifecycle/client.ts +234 -0
  466. package/src/sdk/lifecycle/index.ts +3 -0
  467. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  468. package/src/sdk/lifecycle/service.ts +720 -0
  469. package/src/sdk/mcp/server.ts +226 -188
  470. package/src/sdk/prompt-deadline-lease.ts +55 -0
  471. package/src/sdk/prompt-deadline-manager.ts +148 -0
  472. package/src/sdk/prompt-status.ts +11 -3
  473. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  474. package/src/sdk/protocol/operation-registry.ts +71 -8
  475. package/src/sdk/receipt-state.ts +43 -0
  476. package/src/sdk/reconciliation-extensions.ts +14 -0
  477. package/src/sdk/router/index.ts +1 -0
  478. package/src/sdk/router/session-router.ts +1658 -0
  479. package/src/sdk/session-list.ts +93 -0
  480. package/src/sdk/session-reconnect.ts +45 -1
  481. package/src/sdk/session.ts +716 -120
  482. package/src/sdk/transport/serve-cli.ts +18 -34
  483. package/src/session/account-inventory.ts +603 -0
  484. package/src/session/agent-session.ts +2857 -582
  485. package/src/session/agent-storage.ts +35 -0
  486. package/src/session/blob-store.ts +32 -1
  487. package/src/session/coordinator-tool-label.ts +40 -0
  488. package/src/session/internal/managed-session-scope.ts +4 -0
  489. package/src/session/internal/managed-session-storage.ts +173 -12
  490. package/src/session/messages.ts +1 -1
  491. package/src/session/secure-token-file.ts +80 -0
  492. package/src/session/session-manager.ts +730 -58
  493. package/src/session/session-storage.ts +25 -16
  494. package/src/session/startup-auth-config.ts +297 -0
  495. package/src/session/terminal-abort.ts +1253 -0
  496. package/src/session/yield-queue.ts +57 -15
  497. package/src/session-import/claude.ts +334 -0
  498. package/src/session-import/codex.ts +1033 -0
  499. package/src/session-import/command.ts +77 -0
  500. package/src/session-import/detect.ts +133 -0
  501. package/src/session-import/index.ts +7 -0
  502. package/src/session-import/provider-codex.ts +327 -0
  503. package/src/session-import/provider-service.ts +457 -0
  504. package/src/session-import/redact.ts +128 -0
  505. package/src/session-import/service.ts +1264 -0
  506. package/src/session-import/types.ts +148 -0
  507. package/src/setup/paseo/check.ts +213 -0
  508. package/src/setup/paseo/install-saga.ts +293 -0
  509. package/src/setup/paseo/json-publisher.ts +263 -0
  510. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  511. package/src/setup/paseo/paseo-ownership.ts +224 -0
  512. package/src/setup/paseo/paseo-setup.ts +253 -0
  513. package/src/setup/paseo/provider-config.ts +139 -0
  514. package/src/setup/paseo/remove.ts +183 -0
  515. package/src/setup/paseo/result-types.ts +79 -0
  516. package/src/setup/paseo/setup-deps.ts +175 -0
  517. package/src/setup/paseo/skills-bridge.ts +260 -0
  518. package/src/skill-state/active-state.ts +21 -11
  519. package/src/slash-commands/acp-builtins.ts +9 -1
  520. package/src/slash-commands/builtin-registry.ts +98 -16
  521. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  522. package/src/slash-commands/helpers/mcp.ts +9 -3
  523. package/src/slash-commands/helpers/usage-report.ts +61 -56
  524. package/src/slash-commands/types.ts +7 -2
  525. package/src/task/executor.ts +30 -11
  526. package/src/task/index.ts +66 -7
  527. package/src/task/render.ts +23 -9
  528. package/src/tools/ask-answer-registry.ts +23 -7
  529. package/src/tools/ask.ts +8 -4
  530. package/src/tools/bash-sleep-advisory.ts +115 -0
  531. package/src/tools/bash.ts +98 -18
  532. package/src/tools/browser/attach.ts +71 -3
  533. package/src/tools/browser/launch.ts +86 -13
  534. package/src/tools/browser/profile-discovery.ts +57 -7
  535. package/src/tools/browser/render.ts +8 -1
  536. package/src/tools/browser.ts +130 -21
  537. package/src/tools/computer.enforcement.test.ts +1 -1
  538. package/src/tools/computer.ts +3 -2
  539. package/src/tools/cron.ts +12 -1
  540. package/src/tools/image-gen.ts +27 -16
  541. package/src/tools/index.ts +8 -0
  542. package/src/tools/job.ts +33 -6
  543. package/src/tools/monitor.ts +41 -2
  544. package/src/tools/skill-discovery.ts +21 -29
  545. package/src/tools/subagent.ts +142 -24
  546. package/src/tools/tool-catalog.generated.ts +6 -6
  547. package/src/tools/ultragoal-ask-guard.ts +10 -3
  548. package/src/utils/herdr-pane.ts +345 -0
  549. package/src/utils/title-generator.ts +2 -0
  550. package/src/web/scrapers/index.ts +6 -4
  551. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  552. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  553. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  554. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  555. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  556. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  557. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  558. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  559. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  560. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  561. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  562. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  563. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  564. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  565. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  566. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  567. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  568. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  569. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  570. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  571. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  572. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  573. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  574. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  575. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  576. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  577. package/dist/types/session/auth-broker-config.d.ts +0 -13
  578. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  579. package/dist/types/skills/skills.test.d.ts +0 -1
  580. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  581. package/dist/types/task/token-log.test.d.ts +0 -1
  582. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  583. package/dist/types/tools/descriptors.test.d.ts +0 -1
  584. package/scripts/g005-daemon-smoke.ts +0 -180
  585. package/scripts/g011-daemon-path-smoke.ts +0 -153
  586. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  587. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  588. package/src/sdk/bus/telegram-cli.ts +0 -212
  589. package/src/sdk/elevation/allowlist.ts +0 -54
  590. package/src/sdk/elevation/audit.ts +0 -208
  591. package/src/sdk/elevation/capability.ts +0 -41
  592. package/src/sdk/elevation/digest.ts +0 -129
  593. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  594. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  595. package/src/sdk/elevation/owner.ts +0 -109
  596. package/src/session/auth-broker-config.ts +0 -109
  597. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  598. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  599. /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
@@ -0,0 +1,457 @@
1
+ import { createHash } from "node:crypto";
2
+ import * as nodeFs from "node:fs";
3
+ import * as fsp from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ import { canContinuePersistedHistory } from "@gajae-code/agent-core";
6
+ import { type SessionDestinationInput, SessionManager } from "../session/session-manager";
7
+ import { parseClaudeCodeTranscript, parseClaudeExport } from "./claude";
8
+ import { detectSessionImportFormat } from "./detect";
9
+ import { parseCodexRollout } from "./provider-codex";
10
+ import { IMPORT_SANITIZER_VERSION, redactImportedText } from "./redact";
11
+ import {
12
+ type ImportedConversation,
13
+ type ImportQuarantineRecord,
14
+ type PreparedSessionImport,
15
+ type SessionImportCompleted,
16
+ type SessionImportCounts,
17
+ SessionImportError,
18
+ type SessionImportProvenance,
19
+ type SessionImportProviderId,
20
+ } from "./types";
21
+
22
+ /** Bumped when normalization/rendering changes; persisted in provenance. */
23
+ export const EXTERNAL_IMPORT_CONVERTER_VERSION = 1;
24
+ /** Persisted custom-entry type carrying import provenance (never enters LLM context). */
25
+ export const EXTERNAL_IMPORT_PROVENANCE_CUSTOM_TYPE = "session-import";
26
+ /** Persisted custom-message type carrying the reconstructed continuation context. */
27
+ export const EXTERNAL_IMPORT_CONTEXT_CUSTOM_TYPE = "session-import";
28
+
29
+ /** Hard source size limit; larger exports fail with `content_too_large`. */
30
+ export const EXTERNAL_IMPORT_SOURCE_MAX_BYTES = 64 * 1024 * 1024;
31
+ const MAX_SOURCE_MESSAGES = 5000;
32
+ const MAX_CONTEXT_CHARS = 120_000;
33
+ const HEAD_CONTEXT_CHARS = 20_000;
34
+ const MAX_MESSAGE_CHARS = 16_000;
35
+ const MAX_TITLE_CHARS = 200;
36
+ const MAX_QUARANTINE_RECORDS = 512;
37
+
38
+ export interface ExternalSessionImportRequest {
39
+ /** Explicit user-selected transcript/export file. */
40
+ sourcePath: string;
41
+ /** Explicit provider; omitted = deterministic auto-detection. */
42
+ provider?: SessionImportProviderId;
43
+ /** Import-owner workspace (recorded as the new session's cwd). */
44
+ cwd: string;
45
+ /** Session destination; defaults to the workspace's managed session store. */
46
+ destination?: SessionDestinationInput;
47
+ /** Test seam for deterministic provenance timestamps. */
48
+ now?: () => Date;
49
+ }
50
+
51
+ interface ParsedSource {
52
+ conversation: ImportedConversation;
53
+ quarantine: { present: boolean; truncated: boolean; records: ImportQuarantineRecord[] };
54
+ counts: SessionImportCounts;
55
+ redactionKinds: string[];
56
+ }
57
+
58
+ /** Read the explicit source file with fixed bounds. The source is never written. */
59
+ async function readImportSource(sourcePath: string): Promise<{ text: string; bytes: number; sha256: string }> {
60
+ const resolved = path.resolve(sourcePath);
61
+ const displayPath = redactImportedText(sourcePath).value;
62
+ let handle: fsp.FileHandle;
63
+ try {
64
+ handle = await fsp.open(resolved, nodeFs.constants.O_RDONLY | nodeFs.constants.O_NOFOLLOW);
65
+ } catch (error) {
66
+ const code = (error as NodeJS.ErrnoException).code;
67
+ if (code === "ENOENT") {
68
+ throw new SessionImportError("source_not_found", "read", `Transcript file does not exist: ${displayPath}`);
69
+ }
70
+ throw new SessionImportError(
71
+ "source_unreadable",
72
+ "read",
73
+ `Transcript file cannot be read (${code ?? "unknown error"}): ${displayPath}`,
74
+ { retryable: true },
75
+ );
76
+ }
77
+ try {
78
+ const initial = await handle.stat({ bigint: true });
79
+ if (!initial.isFile()) {
80
+ throw new SessionImportError(
81
+ "invalid_request",
82
+ "read",
83
+ `Import source must be a regular file, not a directory or special file: ${displayPath}`,
84
+ );
85
+ }
86
+ if (initial.size === 0n) {
87
+ throw new SessionImportError("malformed_input", "parse", `Transcript file is empty: ${displayPath}`);
88
+ }
89
+ if (initial.size > BigInt(EXTERNAL_IMPORT_SOURCE_MAX_BYTES)) {
90
+ throw new SessionImportError(
91
+ "content_too_large",
92
+ "read",
93
+ `Transcript is ${initial.size} bytes, exceeding the ${EXTERNAL_IMPORT_SOURCE_MAX_BYTES}-byte import limit. Export a shorter session or trim the file.`,
94
+ { limitBytes: EXTERNAL_IMPORT_SOURCE_MAX_BYTES, observedBytes: Number(initial.size) },
95
+ );
96
+ }
97
+ const bytes = Buffer.alloc(Number(initial.size));
98
+ let offset = 0;
99
+ while (offset < bytes.length) {
100
+ const read = await handle.read(bytes, offset, bytes.length - offset, offset);
101
+ if (read.bytesRead === 0) break;
102
+ offset += read.bytesRead;
103
+ }
104
+ if (offset !== bytes.length) {
105
+ throw new SessionImportError(
106
+ "source_changed",
107
+ "read",
108
+ "The transcript file changed while it was being read.",
109
+ {
110
+ retryable: true,
111
+ },
112
+ );
113
+ }
114
+ const terminal = await handle.stat({ bigint: true });
115
+ if (
116
+ terminal.dev !== initial.dev ||
117
+ terminal.ino !== initial.ino ||
118
+ terminal.nlink !== initial.nlink ||
119
+ terminal.size !== initial.size ||
120
+ terminal.mtimeNs !== initial.mtimeNs ||
121
+ terminal.ctimeNs !== initial.ctimeNs
122
+ ) {
123
+ throw new SessionImportError(
124
+ "source_changed",
125
+ "read",
126
+ "The transcript file changed while it was being read. Re-export or retry with a stable file.",
127
+ { retryable: true },
128
+ );
129
+ }
130
+ return {
131
+ text: bytes.toString("utf8"),
132
+ bytes: bytes.length,
133
+ sha256: createHash("sha256").update(bytes).digest("hex"),
134
+ };
135
+ } catch (error) {
136
+ if (error instanceof SessionImportError) throw error;
137
+ const code = (error as NodeJS.ErrnoException).code;
138
+ throw new SessionImportError(
139
+ "source_unreadable",
140
+ "read",
141
+ `Transcript file cannot be read (${code ?? "unknown error"}): ${displayPath}`,
142
+ { retryable: true },
143
+ );
144
+ } finally {
145
+ await handle.close().catch(() => {});
146
+ }
147
+ }
148
+
149
+ function parseDetectedFormat(detection: ReturnType<typeof detectSessionImportFormat>, text: string): ParsedSource {
150
+ switch (detection.format) {
151
+ case "codex-rollout-jsonl":
152
+ return normalizeAdapterResult(parseCodexRollout(text));
153
+ case "claude-code-jsonl":
154
+ return normalizeAdapterResult(parseClaudeCodeTranscript(text));
155
+ case "claude-export-json":
156
+ return normalizeAdapterResult(parseClaudeExport(text));
157
+ }
158
+ }
159
+
160
+ function normalizeAdapterResult(result: {
161
+ conversation: ImportedConversation;
162
+ quarantine: ImportQuarantineRecord[];
163
+ counts: SessionImportCounts;
164
+ redactionKinds: string[];
165
+ }): ParsedSource {
166
+ return {
167
+ conversation: result.conversation,
168
+ quarantine: {
169
+ present: result.quarantine.length > 0,
170
+ truncated: result.counts.quarantined > result.quarantine.length,
171
+ records: result.quarantine.slice(0, MAX_QUARANTINE_RECORDS),
172
+ },
173
+ counts: result.counts,
174
+ redactionKinds: result.redactionKinds,
175
+ };
176
+ }
177
+
178
+ function assertValidTimestamps(conversation: ImportedConversation): void {
179
+ for (const message of conversation.messages) {
180
+ if (message.timestamp === undefined) continue;
181
+ if (!Number.isFinite(Date.parse(message.timestamp))) {
182
+ throw new SessionImportError(
183
+ "malformed_input",
184
+ "normalize",
185
+ "A message carries an unparseable timestamp; the transcript is not a clean export.",
186
+ );
187
+ }
188
+ }
189
+ }
190
+
191
+ function truncateText(text: string, maxChars: number): string {
192
+ if (text.length <= maxChars) return text;
193
+ return `${text.slice(0, maxChars - 1)}…`;
194
+ }
195
+
196
+ /** Render the bounded continuation context document (head + tail with an elision marker). */
197
+ function renderImportContext(conversation: ImportedConversation): {
198
+ text: string;
199
+ omitted: number;
200
+ truncated: boolean;
201
+ } {
202
+ const titleLine = conversation.title ? ` titled "${truncateText(conversation.title, MAX_TITLE_CHARS)}"` : "";
203
+ const lines: string[] = [
204
+ `<imported-session provider="${conversation.provider}" format="${conversation.format}">`,
205
+ "",
206
+ `The conversation below was imported from an external ${conversation.provider === "codex" ? "Codex" : "Claude"} session transcript${titleLine}.`,
207
+ "It is reconstructed context only: roles and text are preserved, but tool/internal provider state was not cloned, and secrets were redacted.",
208
+ "Continue this conversation naturally as its current participant.",
209
+ "",
210
+ ];
211
+ if (conversation.cwd) lines.push(`Original workspace: ${conversation.cwd}`, "");
212
+
213
+ const rendered: string[] = [];
214
+ for (const message of conversation.messages) {
215
+ const speaker = message.role === "user" ? "User" : "Assistant";
216
+ const blocks: string[] = [];
217
+ if (message.text) blocks.push(truncateText(message.text, MAX_MESSAGE_CHARS));
218
+ if (message.toolEvidence && message.toolEvidence.length > 0) {
219
+ blocks.push(["Tool/file evidence:", ...message.toolEvidence.map(line => ` ${line}`)].join("\n"));
220
+ }
221
+ if (blocks.length === 0) continue;
222
+ rendered.push(`### ${speaker}\n\n${blocks.join("\n\n")}`);
223
+ }
224
+
225
+ let omitted = 0;
226
+ let truncated = false;
227
+ let body: string[];
228
+ if (rendered.length === 0) {
229
+ body = [];
230
+ } else {
231
+ const chars = rendered.reduce((total, part) => total + part.length + 2, 0);
232
+ if (chars <= MAX_CONTEXT_CHARS) {
233
+ body = rendered;
234
+ } else {
235
+ truncated = true;
236
+ const head: string[] = [];
237
+ let headChars = 0;
238
+ while (head.length < rendered.length && headChars + rendered[head.length]!.length + 2 <= HEAD_CONTEXT_CHARS) {
239
+ headChars += rendered[head.length]!.length + 2;
240
+ head.push(rendered[head.length]!);
241
+ }
242
+ const tail: string[] = [];
243
+ let tailChars = 0;
244
+ for (let index = rendered.length - 1; index >= head.length; index--) {
245
+ const part = rendered[index]!;
246
+ if (tailChars + part.length + 2 > MAX_CONTEXT_CHARS - headChars) break;
247
+ tailChars += part.length + 2;
248
+ tail.unshift(part);
249
+ }
250
+ omitted = rendered.length - head.length - tail.length;
251
+ body = [
252
+ ...head,
253
+ `[… ${omitted} earlier message${omitted === 1 ? "" : "s"} from the imported ${conversation.provider} session were elided to bound context; the continuation tail is preserved below. …]`,
254
+ ...tail,
255
+ ];
256
+ }
257
+ }
258
+
259
+ lines.push(...body);
260
+ lines.push("", "</imported-session>");
261
+ return { text: lines.join("\n"), omitted, truncated };
262
+ }
263
+
264
+ /**
265
+ * Phase 1: read, detect, parse, normalize, redact, and bound. Performs no
266
+ * session mutation; safe to run before any session transition.
267
+ */
268
+ export async function prepareExternalSessionImport(
269
+ request: Pick<ExternalSessionImportRequest, "sourcePath" | "provider">,
270
+ ): Promise<PreparedSessionImport> {
271
+ if (typeof request.sourcePath !== "string" || request.sourcePath.trim().length === 0) {
272
+ throw new SessionImportError(
273
+ "invalid_request",
274
+ "request",
275
+ "A transcript file path is required: /import-session <file> [--provider codex|claude]",
276
+ );
277
+ }
278
+ if (request.provider !== undefined && request.provider !== "codex" && request.provider !== "claude") {
279
+ throw new SessionImportError(
280
+ "invalid_request",
281
+ "request",
282
+ `Unsupported provider "${String(request.provider)}"; expected codex or claude.`,
283
+ );
284
+ }
285
+ const source = await readImportSource(request.sourcePath);
286
+ const detection = detectSessionImportFormat(source.text, request.provider);
287
+ const parsed = parseDetectedFormat(detection, source.text);
288
+ assertValidTimestamps(parsed.conversation);
289
+
290
+ if (parsed.conversation.messages.length === 0) {
291
+ throw new SessionImportError(
292
+ "malformed_input",
293
+ "parse",
294
+ `No importable user/assistant messages were found in the ${detection.format} transcript.`,
295
+ );
296
+ }
297
+ if (parsed.conversation.messages.length > MAX_SOURCE_MESSAGES) {
298
+ throw new SessionImportError(
299
+ "content_too_large",
300
+ "normalize",
301
+ `The transcript has ${parsed.conversation.messages.length} messages, exceeding the ${MAX_SOURCE_MESSAGES}-message import limit. Export a shorter session.`,
302
+ { limitBytes: MAX_SOURCE_MESSAGES, observedBytes: parsed.conversation.messages.length },
303
+ );
304
+ }
305
+
306
+ const rendered = renderImportContext(parsed.conversation);
307
+ const counts: SessionImportCounts = { ...parsed.counts, omitted: rendered.omitted };
308
+ const provenance: PreparedSessionImport["provenance"] = {
309
+ schemaVersion: 1,
310
+ customType: EXTERNAL_IMPORT_PROVENANCE_CUSTOM_TYPE,
311
+ provider: parsed.conversation.provider,
312
+ format: parsed.conversation.format,
313
+ sourceFileName: redactImportedText(path.basename(path.resolve(request.sourcePath))).value.slice(0, 255),
314
+ ...(parsed.conversation.sourceSessionId ? { sourceSessionId: parsed.conversation.sourceSessionId } : {}),
315
+ ...(parsed.conversation.title ? { sourceTitle: truncateText(parsed.conversation.title, MAX_TITLE_CHARS) } : {}),
316
+ sourceSha256: source.sha256,
317
+ sourceBytes: source.bytes,
318
+ converterVersion: EXTERNAL_IMPORT_CONVERTER_VERSION,
319
+ sanitizerVersion: IMPORT_SANITIZER_VERSION,
320
+ counts,
321
+ truncated: rendered.truncated,
322
+ quarantine: parsed.quarantine,
323
+ };
324
+ return {
325
+ conversation: parsed.conversation,
326
+ contextText: rendered.text,
327
+ provenance,
328
+ counts,
329
+ redactionKinds: parsed.redactionKinds,
330
+ sourcePath: path.resolve(request.sourcePath),
331
+ sourceSha256: source.sha256,
332
+ sourceBytes: source.bytes,
333
+ };
334
+ }
335
+
336
+ /**
337
+ * Phase 2: materialize a prepared import as a NEW GJC session file and verify
338
+ * it reopens as a resumable session. The caller's live session is untouched.
339
+ */
340
+ export async function materializeExternalSessionImport(
341
+ prepared: PreparedSessionImport,
342
+ options: Pick<ExternalSessionImportRequest, "cwd" | "destination" | "now">,
343
+ ): Promise<SessionImportCompleted> {
344
+ if (typeof options.cwd !== "string" || options.cwd.length === 0) {
345
+ throw new SessionImportError("invalid_request", "request", "A workspace cwd is required to host the import.");
346
+ }
347
+ const importedAt = (options.now?.() ?? new Date()).toISOString();
348
+ const manager = SessionManager.create(options.cwd, options.destination);
349
+ const destination = manager.getDestinationForFork();
350
+ const sessionFile = manager.getSessionFile();
351
+ if (!sessionFile) {
352
+ await manager.close().catch(() => {});
353
+ throw new SessionImportError(
354
+ "io_failed",
355
+ "persist",
356
+ "Session persistence is unavailable for this workspace; the import has nowhere to live.",
357
+ );
358
+ }
359
+ const targetSessionId = manager.getSessionId();
360
+ try {
361
+ const provenance: SessionImportProvenance = {
362
+ ...prepared.provenance,
363
+ targetSessionId,
364
+ importedAt,
365
+ };
366
+ manager.appendCustomEntry(EXTERNAL_IMPORT_PROVENANCE_CUSTOM_TYPE, provenance);
367
+ manager.appendCustomMessageEntry(
368
+ EXTERNAL_IMPORT_CONTEXT_CUSTOM_TYPE,
369
+ prepared.contextText,
370
+ true,
371
+ {
372
+ provider: prepared.conversation.provider,
373
+ format: prepared.conversation.format,
374
+ sourceSha256: prepared.sourceSha256,
375
+ sourceBytes: prepared.sourceBytes,
376
+ counts: prepared.counts,
377
+ truncated: prepared.provenance.truncated,
378
+ importedAt,
379
+ },
380
+ "agent",
381
+ );
382
+ const title =
383
+ prepared.conversation.title ??
384
+ `Imported ${prepared.conversation.provider === "codex" ? "Codex" : "Claude"} session ${(
385
+ prepared.conversation.sourceSessionId ?? prepared.sourceSha256
386
+ ).slice(0, 8)}`;
387
+ await manager.setSessionName(truncateText(title, MAX_TITLE_CHARS), "user");
388
+ await manager.ensureOnDisk();
389
+ await manager.flush();
390
+
391
+ // Verify the written file reopens cleanly and is continuable before the
392
+ // caller switches to it. Keep the creating manager open so its captured
393
+ // managed destination authority remains valid throughout verification;
394
+ // closing it afterward releases that authority exactly once.
395
+ const reopened = await SessionManager.open(sessionFile, destination);
396
+ try {
397
+ if (!canContinuePersistedHistory(reopened.buildSessionContext().messages)) {
398
+ throw new SessionImportError(
399
+ "malformed_input",
400
+ "persist",
401
+ "The imported session did not reconstruct a continuable conversation.",
402
+ );
403
+ }
404
+ } finally {
405
+ await reopened.close().catch(() => {});
406
+ }
407
+ await manager.close();
408
+ return { targetSessionId, targetPath: sessionFile, title: truncateText(title, MAX_TITLE_CHARS), prepared };
409
+ } catch (error) {
410
+ await manager.close().catch(() => {});
411
+ if (error instanceof SessionImportError) throw error;
412
+ const message = error instanceof Error ? error.message : String(error);
413
+ throw new SessionImportError("io_failed", "persist", `Failed to persist the imported session: ${message}`, {
414
+ retryable: true,
415
+ });
416
+ }
417
+ }
418
+
419
+ /** Full import: prepare + materialize. Never switches the caller's session. */
420
+ export async function importProviderSessionFile(
421
+ request: ExternalSessionImportRequest,
422
+ ): Promise<SessionImportCompleted> {
423
+ const prepared = await prepareExternalSessionImport(request);
424
+ return materializeExternalSessionImport(prepared, request);
425
+ }
426
+
427
+ /** Human-facing summary lines for a completed import. */
428
+ export function formatProviderSessionImportSummary(result: SessionImportCompleted): string {
429
+ const { prepared } = result;
430
+ const providerLabel = prepared.conversation.provider === "codex" ? "Codex" : "Claude";
431
+ const lines = [
432
+ `Imported ${providerLabel} session (${prepared.conversation.format}) into a new GJC session.`,
433
+ `Session: ${result.targetSessionId}`,
434
+ `Title: ${result.title}`,
435
+ `Messages: ${prepared.conversation.messages.length} reconstructed (${prepared.counts.mapped} records mapped, ${prepared.counts.quarantined} quarantined)`,
436
+ `Source: ${prepared.provenance.sourceFileName} (${prepared.sourceBytes} bytes, sha256 ${prepared.sourceSha256.slice(0, 12)}…)`,
437
+ ];
438
+ if (prepared.counts.omitted > 0) {
439
+ lines.push(`Bounded: ${prepared.counts.omitted} earlier messages elided between the preserved head and tail.`);
440
+ }
441
+ if (prepared.counts.redacted > 0) {
442
+ lines.push(
443
+ `Redacted: ${prepared.counts.redacted} secret/credential value${prepared.counts.redacted === 1 ? "" : "s"} (${prepared.redactionKinds.join(", ")}).`,
444
+ );
445
+ }
446
+ lines.push("The original transcript file was not modified.");
447
+ return lines.join("\n");
448
+ }
449
+
450
+ /** Human-facing diagnostic for a failed import. */
451
+ export function formatProviderSessionImportError(error: unknown): string {
452
+ if (error instanceof SessionImportError) {
453
+ const retry = error.retryable ? " (retryable)" : "";
454
+ return `Import failed: ${error.code} [${error.phase}]${retry} — ${error.message}`;
455
+ }
456
+ return `Import failed: ${error instanceof Error ? error.message : String(error)}`;
457
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Fail-closed secret redaction for imported session content (issue #3709).
3
+ *
4
+ * Every string that crosses the import boundary passes through
5
+ * {@link redactImportedText}. Patterns are conservative: a false positive costs
6
+ * one `[REDACTED]` span in reconstructed context, a false negative leaks a
7
+ * credential into a new session transcript, so the balance favors redaction.
8
+ */
9
+
10
+ export const IMPORT_REDACTED_PLACEHOLDER = "[REDACTED]";
11
+ /** Bumped when patterns change; persisted in import provenance. */
12
+ export const IMPORT_SANITIZER_VERSION = 2;
13
+
14
+ const ANSI_ESCAPE = /\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1b\\))/gu;
15
+ const UNSAFE_CONTROL =
16
+ /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2060\u2066-\u2069\ufeff]/gu;
17
+ const HEADER_CREDENTIAL = /(\b(?:authorization|cookie|set-cookie)\b[ \t]*:[ \t]*)([^\r\n]*)/giu;
18
+ const JSON_AUTHORIZATION = /((?:\\?")authorization(?:\\?")\s*:\s*(?:\\?")?)([^",}\r\n]+)/giu;
19
+
20
+ interface RedactionRule {
21
+ readonly id: string;
22
+ readonly pattern: RegExp;
23
+ }
24
+
25
+ const HEX = "[0-9a-fA-F]";
26
+
27
+ /**
28
+ * Ordered first-match-wins rules. Each rule replaces its full match with the
29
+ * placeholder, so a matched credential never survives partially.
30
+ */
31
+ const REDACTION_RULES: readonly RedactionRule[] = [
32
+ // PEM private-key blocks, header through footer.
33
+ {
34
+ id: "pem-private-key",
35
+ pattern: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
36
+ },
37
+ // AWS access key ids.
38
+ { id: "aws-access-key", pattern: /(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}/g },
39
+ // GitHub tokens (PAT, OAuth, server-to-server, refresh, fine-grained).
40
+ { id: "github-token", pattern: /(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}/g },
41
+ // Anthropic API keys.
42
+ { id: "anthropic-key", pattern: /sk-ant-[A-Za-z0-9_-]{20,}/g },
43
+ // OpenAI-style keys (project keys, service accounts, legacy sk-).
44
+ { id: "openai-key", pattern: /sk-(?:proj|svcacct|admin)-[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9]{20,}/g },
45
+ // Slack tokens.
46
+ { id: "slack-token", pattern: /xox[baprs]-[A-Za-z0-9-]{10,}/g },
47
+ // Google API keys.
48
+ { id: "google-api-key", pattern: /AIza[0-9A-Za-z_-]{35}/g },
49
+ // Bearer tokens carried in Authorization text.
50
+ {
51
+ id: "bearer-token",
52
+ pattern: /(authorization["'\s]*[:=]["'\s]*bearer\s+|bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi,
53
+ },
54
+ // JWTs (three base64url segments; middle segment non-trivial).
55
+ {
56
+ id: "jwt",
57
+ pattern: /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
58
+ },
59
+ // Long hex secrets (64+ hex chars: webhook secrets, signing keys).
60
+ { id: "hex-secret", pattern: new RegExp(`\\b${HEX}{64,}\\b`, "g") },
61
+ // Basic-auth credentials embedded in URLs (https://user:pass@host).
62
+ { id: "url-credential", pattern: /([a-z][a-z0-9+.-]*:\/\/)[^/\s:@]{1,256}:[^/\s@]{1,256}@/gi },
63
+ // Sensitive env/KEY assignments: OPENAI_API_KEY=..., token: ..., password = ...
64
+ // The name prefix is optional so a bare sensitive name (`password: …`) also matches.
65
+ {
66
+ id: "secret-assignment",
67
+ pattern:
68
+ /\b(?:[A-Za-z_][A-Za-z0-9_]*)?(?:api[_-]?key|secret|token|password|passwd|credential|client[_-]?secret|private[_-]?key|access[_-]?key|refresh[_-]?token|session[_-]?key)[A-Za-z0-9_]*\b(["']?\s*[:=]\s*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s,;}&)]{4,})/gi,
69
+ },
70
+ ];
71
+
72
+ export interface ImportRedactionResult {
73
+ value: string;
74
+ redacted: number;
75
+ kinds: string[];
76
+ }
77
+
78
+ /**
79
+ * Redact every known credential shape from imported text. The same placeholder
80
+ * is used for all kinds so a partial pattern overlap cannot leak fragments.
81
+ */
82
+ export function redactImportedText(input: string): ImportRedactionResult {
83
+ let value = input.replace(ANSI_ESCAPE, "").replace(UNSAFE_CONTROL, "");
84
+ let redacted = 0;
85
+ const kinds = new Set<string>();
86
+ value = value.replace(HEADER_CREDENTIAL, (_match, prefix: string, raw: string) => {
87
+ if (!raw.trim()) return `${prefix}${raw}`;
88
+ redacted++;
89
+ kinds.add("credential-header");
90
+ return `${prefix}${IMPORT_REDACTED_PLACEHOLDER}`;
91
+ });
92
+ value = value.replace(JSON_AUTHORIZATION, (_match, prefix: string, raw: string) => {
93
+ if (!raw.trim()) return `${prefix}${raw}`;
94
+ redacted++;
95
+ kinds.add("authorization-json");
96
+ return `${prefix}${IMPORT_REDACTED_PLACEHOLDER}`;
97
+ });
98
+ for (const rule of REDACTION_RULES) {
99
+ rule.pattern.lastIndex = 0;
100
+ value = value.replace(rule.pattern, match => {
101
+ redacted++;
102
+ kinds.add(rule.id);
103
+ if (rule.id === "url-credential") {
104
+ // Keep the scheme visible; the match ends at "@" so the host survives.
105
+ const schemeEnd = match.indexOf("://") + 3;
106
+ return `${match.slice(0, schemeEnd)}${IMPORT_REDACTED_PLACEHOLDER}@`;
107
+ }
108
+ if (rule.id === "secret-assignment") {
109
+ const sep = /(["']?\s*[:=]\s*)/.exec(match);
110
+ if (sep) {
111
+ const head = match.slice(0, (sep.index ?? 0) + sep[0].length);
112
+ return `${head}${IMPORT_REDACTED_PLACEHOLDER}`;
113
+ }
114
+ }
115
+ if (rule.id === "bearer-token") {
116
+ const bearerAt = /bearer\s+/i.exec(match);
117
+ if (bearerAt) return `${match.slice(0, bearerAt.index + bearerAt[0].length)}${IMPORT_REDACTED_PLACEHOLDER}`;
118
+ }
119
+ return IMPORT_REDACTED_PLACEHOLDER;
120
+ });
121
+ }
122
+ return { value, redacted, kinds: [...kinds].sort() };
123
+ }
124
+
125
+ /** Redact a string, returning only the sanitized value. */
126
+ export function sanitizeImportedString(input: string): string {
127
+ return redactImportedText(input).value;
128
+ }