@gajae-code/coding-agent 0.10.2 → 0.11.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 (476) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/async/job-manager.d.ts +46 -7
  4. package/dist/types/cli/args.d.ts +4 -5
  5. package/dist/types/cli/daemon-cli.d.ts +12 -1
  6. package/dist/types/cli/notify-cli.d.ts +21 -1
  7. package/dist/types/cli.d.ts +3 -0
  8. package/dist/types/commands/daemon.d.ts +39 -0
  9. package/dist/types/commands/launch.d.ts +3 -0
  10. package/dist/types/commands/notify.d.ts +28 -1
  11. package/dist/types/commands/sdk.d.ts +33 -0
  12. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  13. package/dist/types/config/model-profile-activation.d.ts +35 -15
  14. package/dist/types/config/model-profiles.d.ts +11 -5
  15. package/dist/types/config/model-registry.d.ts +3 -3
  16. package/dist/types/config/model-resolver.d.ts +39 -6
  17. package/dist/types/config/model-selector-value.d.ts +17 -0
  18. package/dist/types/config/models-config-schema.d.ts +10 -6
  19. package/dist/types/config/settings-schema.d.ts +133 -6
  20. package/dist/types/config/settings.d.ts +63 -35
  21. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  22. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  23. package/dist/types/daemon/builtin.d.ts +6 -5
  24. package/dist/types/daemon/control-types.d.ts +1 -1
  25. package/dist/types/discovery/mcp-json.d.ts +12 -1
  26. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  27. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  28. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  31. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  32. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  33. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  34. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  35. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  36. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  37. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  38. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  39. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  40. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  41. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  42. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  43. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  44. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  45. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  46. package/dist/types/harness-control-plane/types.d.ts +3 -4
  47. package/dist/types/lsp/index.d.ts +1 -1
  48. package/dist/types/main.d.ts +32 -38
  49. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  50. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  51. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  52. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  53. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  54. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  55. package/dist/types/modes/components/model-selector.d.ts +1 -0
  56. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  57. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  58. package/dist/types/modes/components/welcome.d.ts +1 -1
  59. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  60. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  62. package/dist/types/modes/index.d.ts +0 -4
  63. package/dist/types/modes/interactive-mode.d.ts +5 -2
  64. package/dist/types/modes/runtime-init.d.ts +2 -2
  65. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  66. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  67. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  68. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  69. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  72. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  73. package/dist/types/modes/types.d.ts +7 -2
  74. package/dist/types/runtime-mcp/client.d.ts +2 -0
  75. package/dist/types/runtime-mcp/config.d.ts +5 -1
  76. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  77. package/dist/types/runtime-mcp/types.d.ts +4 -0
  78. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  79. package/dist/types/sdk/acp/index.d.ts +2 -0
  80. package/dist/types/sdk/broker/broker.d.ts +53 -0
  81. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  82. package/dist/types/sdk/broker/ensure.d.ts +42 -0
  83. package/dist/types/sdk/broker/identity.d.ts +3 -0
  84. package/dist/types/sdk/broker/index.d.ts +8 -0
  85. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  86. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  87. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  88. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  89. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  90. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  91. package/dist/types/sdk/broker/transport.d.ts +9 -0
  92. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  93. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  94. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  95. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  96. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  97. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  98. package/dist/types/sdk/bus/config.d.ts +274 -0
  99. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  100. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  101. package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
  102. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  103. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  104. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  105. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  107. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  108. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  109. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  110. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  111. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  112. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  113. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  114. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  115. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  116. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  117. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  118. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  119. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  121. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
  122. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  123. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  124. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  125. package/dist/types/sdk/cli/index.d.ts +1 -0
  126. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  127. package/dist/types/sdk/client/client.d.ts +1 -0
  128. package/dist/types/sdk/client/discovery.d.ts +27 -0
  129. package/dist/types/sdk/client/index.d.ts +2 -0
  130. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  131. package/dist/types/sdk/host/control/index.d.ts +2 -0
  132. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  133. package/dist/types/sdk/host/events.d.ts +35 -0
  134. package/dist/types/sdk/host/host.d.ts +35 -0
  135. package/dist/types/sdk/host/index.d.ts +4 -0
  136. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  137. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  138. package/dist/types/sdk/host/query/index.d.ts +3 -0
  139. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  140. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  141. package/dist/types/sdk/host/types.d.ts +32 -0
  142. package/dist/types/sdk/index.d.ts +6 -0
  143. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  144. package/dist/types/sdk/mcp/index.d.ts +1 -0
  145. package/dist/types/sdk/mcp/server.d.ts +37 -0
  146. package/dist/types/sdk/models.d.ts +44 -0
  147. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  148. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  149. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  150. package/dist/types/sdk/startup-capability.d.ts +50 -0
  151. package/dist/types/session/agent-session.d.ts +114 -21
  152. package/dist/types/session/default-model-selection.d.ts +25 -0
  153. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  154. package/dist/types/session/session-manager.d.ts +58 -1
  155. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  156. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  157. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  158. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  159. package/dist/types/tools/browser/launch.d.ts +22 -0
  160. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  161. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  162. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  163. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  164. package/dist/types/tools/browser/registry.d.ts +19 -0
  165. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  166. package/dist/types/tools/index.d.ts +8 -8
  167. package/dist/types/tools/subagent-render.d.ts +1 -0
  168. package/dist/types/tools/subagent.d.ts +6 -1
  169. package/package.json +34 -13
  170. package/scripts/build-sdk-package-smoke.ts +99 -0
  171. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  172. package/scripts/compile-args.ts +4 -2
  173. package/scripts/g005-daemon-smoke.ts +4 -5
  174. package/scripts/g011-daemon-path-smoke.ts +5 -5
  175. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  176. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  177. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  178. package/scripts/manifest-schema.ts +124 -0
  179. package/scripts/run-test-manifest.ts +153 -0
  180. package/scripts/run-threat-model-check.ts +157 -0
  181. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  182. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  183. package/src/append-only-mode.ts +1 -1
  184. package/src/async/job-manager.ts +406 -63
  185. package/src/cli/args.ts +43 -12
  186. package/src/cli/auth-gateway-cli.ts +2 -2
  187. package/src/cli/config-cli.ts +2 -1
  188. package/src/cli/daemon-cli.ts +63 -14
  189. package/src/cli/list-models.ts +1 -1
  190. package/src/cli/notify-cli.ts +288 -286
  191. package/src/cli.ts +21 -2
  192. package/src/commands/daemon.ts +50 -6
  193. package/src/commands/harness.ts +93 -36
  194. package/src/commands/launch.ts +5 -2
  195. package/src/commands/mcp-serve.ts +19 -12
  196. package/src/commands/notify.ts +36 -3
  197. package/src/commands/sdk.ts +426 -0
  198. package/src/commit/agentic/agent.ts +1 -0
  199. package/src/config/atomic-yaml-patch.ts +423 -0
  200. package/src/config/model-profile-activation.ts +240 -89
  201. package/src/config/model-profiles.ts +18 -15
  202. package/src/config/model-registry.ts +51 -26
  203. package/src/config/model-resolver.ts +138 -51
  204. package/src/config/model-selector-value.ts +50 -0
  205. package/src/config/models-config-schema.ts +14 -21
  206. package/src/config/settings-schema.ts +128 -10
  207. package/src/config/settings.ts +1120 -158
  208. package/src/coordinator-mcp/model-preset.ts +74 -20
  209. package/src/coordinator-mcp/server.ts +1597 -3052
  210. package/src/daemon/builtin.ts +8 -5
  211. package/src/daemon/control-types.ts +1 -1
  212. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  213. package/src/discovery/mcp-json.ts +327 -20
  214. package/src/extensibility/custom-tools/types.ts +1 -1
  215. package/src/extensibility/extensions/compact-handler.ts +3 -3
  216. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  217. package/src/extensibility/extensions/loader.ts +69 -5
  218. package/src/extensibility/extensions/runner.ts +112 -4
  219. package/src/extensibility/extensions/types.ts +176 -17
  220. package/src/extensibility/hooks/types.ts +1 -1
  221. package/src/gjc-runtime/launch-tmux.ts +170 -86
  222. package/src/gjc-runtime/psmux-detect.ts +82 -4
  223. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  224. package/src/gjc-runtime/team-runtime.ts +54 -35
  225. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  226. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  227. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  228. package/src/gjc-runtime/ultragoal-guard.ts +108 -14
  229. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  230. package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
  231. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  232. package/src/harness-control-plane/operate.ts +9 -9
  233. package/src/harness-control-plane/owner.ts +283 -39
  234. package/src/harness-control-plane/receipts.ts +0 -1
  235. package/src/harness-control-plane/sdk-transport.ts +395 -0
  236. package/src/harness-control-plane/session-transport.ts +94 -0
  237. package/src/harness-control-plane/types.ts +1 -1
  238. package/src/internal-urls/docs-index.generated.ts +34 -35
  239. package/src/lsp/client.ts +42 -6
  240. package/src/lsp/index.ts +2 -2
  241. package/src/main.ts +299 -204
  242. package/src/modes/DESIGN.md +258 -0
  243. package/src/modes/acp/acp-agent.ts +1228 -2612
  244. package/src/modes/acp/acp-client-bridge.ts +2 -20
  245. package/src/modes/acp/acp-event-mapper.ts +18 -2
  246. package/src/modes/acp/acp-mode.ts +8 -36
  247. package/src/modes/acp/permission-mode.ts +25 -0
  248. package/src/modes/acp/startup-options.ts +6 -0
  249. package/src/modes/components/agent-dashboard.ts +37 -17
  250. package/src/modes/components/model-selector.ts +93 -35
  251. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  252. package/src/modes/components/settings-selector.ts +60 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +10 -17
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +396 -28
  257. package/src/modes/controllers/selector-controller.ts +674 -36
  258. package/src/modes/index.ts +0 -22
  259. package/src/modes/interactive-mode.ts +87 -36
  260. package/src/modes/runtime-init.ts +298 -6
  261. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  262. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  263. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  264. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  265. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  266. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
  267. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  268. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  269. package/src/modes/types.ts +7 -2
  270. package/src/runtime-mcp/client.ts +94 -19
  271. package/src/runtime-mcp/config.ts +27 -15
  272. package/src/runtime-mcp/manager.ts +343 -105
  273. package/src/runtime-mcp/oauth-flow.ts +42 -12
  274. package/src/runtime-mcp/transports/http.ts +49 -19
  275. package/src/runtime-mcp/transports/stdio.ts +47 -28
  276. package/src/runtime-mcp/types.ts +10 -0
  277. package/src/sdk/acp/adapter.ts +418 -0
  278. package/src/sdk/acp/index.ts +2 -0
  279. package/src/sdk/broker/broker.ts +642 -0
  280. package/src/sdk/broker/discovery.ts +113 -0
  281. package/src/sdk/broker/ensure.ts +307 -0
  282. package/src/sdk/broker/identity.ts +42 -0
  283. package/src/sdk/broker/index.ts +8 -0
  284. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  285. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  286. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  287. package/src/sdk/broker/lifecycle.ts +2157 -0
  288. package/src/sdk/broker/process-incarnation.ts +159 -0
  289. package/src/sdk/broker/runtime.ts +164 -0
  290. package/src/sdk/broker/session-index.ts +318 -0
  291. package/src/sdk/broker/state-version.ts +23 -0
  292. package/src/sdk/broker/transport.ts +125 -0
  293. package/src/sdk/bus/chat-command-policy.ts +107 -0
  294. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  295. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  296. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  297. package/src/sdk/bus/chat-effect-journal.ts +355 -0
  298. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  299. package/src/sdk/bus/config.ts +433 -0
  300. package/src/sdk/bus/conversation-store.ts +391 -0
  301. package/src/sdk/bus/discord-conversation.ts +85 -0
  302. package/src/sdk/bus/discord-daemon.ts +2292 -0
  303. package/src/sdk/bus/discord-live-provider.ts +521 -0
  304. package/src/sdk/bus/discord-provider.ts +56 -0
  305. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  306. package/src/sdk/bus/index.ts +3979 -0
  307. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  309. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  310. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  311. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  312. package/src/sdk/bus/natives-augment.d.ts +38 -0
  313. package/src/sdk/bus/notification-orchestration.ts +535 -0
  314. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  315. package/src/sdk/bus/session-control.ts +333 -0
  316. package/src/sdk/bus/slack-conversation.ts +74 -0
  317. package/src/sdk/bus/slack-daemon.ts +2144 -0
  318. package/src/sdk/bus/slack-live-provider.ts +380 -0
  319. package/src/sdk/bus/slack-provider.ts +76 -0
  320. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  321. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  322. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  323. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  324. package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
  325. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  326. package/src/sdk/bus/telegram-setup.ts +663 -0
  327. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  328. package/src/sdk/cli/index.ts +1 -0
  329. package/src/sdk/cli/session-cli.ts +275 -0
  330. package/src/sdk/client/client.ts +1 -0
  331. package/src/sdk/client/discovery.ts +108 -0
  332. package/src/sdk/client/index.ts +2 -0
  333. package/src/sdk/host/control/dispatch.ts +367 -0
  334. package/src/sdk/host/control/index.ts +10 -0
  335. package/src/sdk/host/control/operations.ts +63 -0
  336. package/src/sdk/host/events.ts +91 -0
  337. package/src/sdk/host/host.ts +296 -0
  338. package/src/sdk/host/index.ts +4 -0
  339. package/src/sdk/host/query/cursor.ts +189 -0
  340. package/src/sdk/host/query/handlers.ts +533 -0
  341. package/src/sdk/host/query/index.ts +3 -0
  342. package/src/sdk/host/query/revision-store.ts +1126 -0
  343. package/src/sdk/host/reverse-leases.ts +325 -0
  344. package/src/sdk/host/types.ts +29 -0
  345. package/src/sdk/index.ts +13 -0
  346. package/src/sdk/lifecycle-session.ts +39 -0
  347. package/src/sdk/mcp/index.ts +1 -0
  348. package/src/sdk/mcp/server.ts +332 -0
  349. package/src/sdk/models.ts +168 -0
  350. package/src/sdk/protocol/adapter-validation.ts +48 -0
  351. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  352. package/src/sdk/protocol/operation-registry.ts +312 -0
  353. package/src/{sdk.ts → sdk/session.ts} +339 -212
  354. package/src/sdk/startup-capability.ts +189 -0
  355. package/src/session/agent-session.ts +2650 -944
  356. package/src/session/default-model-selection.ts +93 -0
  357. package/src/session/fallback-chain-controller.ts +136 -0
  358. package/src/session/session-manager.ts +438 -11
  359. package/src/session/session-storage.ts +8 -1
  360. package/src/setup/credential-auto-import.ts +290 -35
  361. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  362. package/src/slash-commands/builtin-registry.ts +2 -1
  363. package/src/task/executor.ts +62 -13
  364. package/src/task/index.ts +26 -16
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/subagent-render.ts +19 -8
  384. package/src/tools/subagent.ts +84 -32
  385. package/src/tools/telegram-send.ts +2 -2
  386. package/vendor/insane-search/MANIFEST.json +2 -1
  387. package/vendor/insane-search/engine/bias_check.py +4 -1
  388. package/vendor/insane-search/engine/phase0.py +26 -1
  389. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  390. package/dist/types/modes/bridge/auth.d.ts +0 -12
  391. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  392. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  393. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  394. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  395. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  396. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  397. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  398. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  399. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  400. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  401. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  402. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  403. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  404. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  405. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  406. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  407. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  408. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  409. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  410. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  411. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  412. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  413. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  414. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  415. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  416. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  417. package/dist/types/notifications/config.d.ts +0 -132
  418. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  419. package/src/modes/bridge/auth.ts +0 -41
  420. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  421. package/src/modes/bridge/bridge-mode.ts +0 -675
  422. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  423. package/src/modes/bridge/event-stream.ts +0 -70
  424. package/src/modes/rpc/host-tools.ts +0 -1
  425. package/src/modes/rpc/host-uris.ts +0 -1
  426. package/src/modes/rpc/rpc-client.ts +0 -1166
  427. package/src/modes/rpc/rpc-mode.ts +0 -1029
  428. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  429. package/src/modes/rpc/rpc-types.ts +0 -637
  430. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  431. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  432. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  433. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  434. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  435. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  436. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  437. package/src/modes/shared/agent-wire/responses.ts +0 -17
  438. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  439. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  440. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  441. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  442. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  443. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  444. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  445. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  446. package/src/notifications/config.ts +0 -219
  447. package/src/notifications/index.ts +0 -1835
  448. package/src/notifications/telegram-daemon-cli.ts +0 -243
  449. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  450. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  462. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  463. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  475. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  476. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import * as fs from "node:fs/promises";
2
3
  import * as path from "node:path";
3
4
  import type {
@@ -7,8 +8,8 @@ import type {
7
8
  AuthStorage,
8
9
  } from "@gajae-code/ai";
9
10
  import { getAgentDir, logger, VERSION } from "@gajae-code/utils";
11
+ import { withFileLock } from "../config/file-lock";
10
12
  import type { ModelRegistry } from "../config/model-registry";
11
-
12
13
  import {
13
14
  type CredentialDiscoveryResult,
14
15
  type CredentialOrigin,
@@ -23,42 +24,206 @@ import {
23
24
 
24
25
  export const CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING =
25
26
  "Refreshing in gjc may log out the Claude/Codex CLI because OAuth refresh tokens can rotate.";
27
+ export const CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING =
28
+ "Credential import preference could not be saved; external credentials may be offered again.";
29
+ export const CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING =
30
+ "Imported credentials were saved, but provider availability could not be refreshed.";
31
+ export const CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING =
32
+ "External credential discovery could not be completed. Use /provider to import credentials manually.";
33
+ export const CREDENTIAL_AUTO_IMPORT_RETRY_WARNING =
34
+ "Some external credentials could not be imported. Use /provider to retry.";
35
+
36
+ export const CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING =
37
+ "Credential import preference could not be read. External credential discovery was skipped; use /provider to import credentials manually.";
26
38
 
27
39
  export type CredentialAutoImportSourceLabel = "claude-code-file" | "claude-code-keychain" | "codex-file";
28
40
  export type CredentialAutoImportTrigger = "startup" | "bare-login" | "setup-cli";
41
+ export type InitialImportResolution = "accepted" | "declined";
42
+ export type CredentialAutoImportStateProblem =
43
+ | "invalid-initial-import-resolution"
44
+ | "invalid-last-import-version"
45
+ | "malformed-json"
46
+ | "malformed-root";
29
47
 
30
48
  const CREDENTIAL_AUTO_IMPORT_STATE_FILENAME = "credential-auto-import-state.json";
49
+ const VERSION_MARKER_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
50
+
51
+ export interface CredentialAutoImportStateFile {
52
+ lastImportVersion?: string;
53
+ initialImportResolution?: InitialImportResolution;
54
+ }
55
+
56
+ export interface CredentialAutoImportStateReadResult {
57
+ state: CredentialAutoImportStateFile;
58
+ problems: CredentialAutoImportStateProblem[];
59
+ unreadable: boolean;
60
+ }
31
61
 
32
- interface CredentialAutoImportStateFile {
33
- lastImportVersion?: unknown;
62
+ export interface CredentialAutoImportStateMutation {
63
+ lastImportVersion?: string;
64
+ initialImportResolution?: InitialImportResolution;
65
+ }
66
+
67
+ export interface CredentialAutoImportStateStore {
68
+ read: () => Promise<CredentialAutoImportStateReadResult>;
69
+ write: (mutation: CredentialAutoImportStateMutation) => Promise<boolean>;
70
+ }
71
+
72
+ export interface CredentialAutoImportStateStoreDependencies {
73
+ withFileLock?: <T>(filePath: string, transaction: () => Promise<T>) => Promise<T>;
74
+ rename?: (oldPath: string, newPath: string) => Promise<void>;
34
75
  }
35
76
 
36
77
  export function getCredentialAutoImportStatePath(agentDir: string = getAgentDir()): string {
37
78
  return path.join(agentDir, CREDENTIAL_AUTO_IMPORT_STATE_FILENAME);
38
79
  }
39
80
 
40
- export async function readCredentialImportMarker(agentDir?: string): Promise<string | undefined> {
81
+ function isEnoent(error: unknown): boolean {
82
+ return (error as NodeJS.ErrnoException | undefined)?.code === "ENOENT";
83
+ }
84
+
85
+ function isValidVersionMarker(value: unknown): value is string {
86
+ return (
87
+ typeof value === "string" &&
88
+ value.length > 0 &&
89
+ value.trim() === value &&
90
+ value.length <= 128 &&
91
+ VERSION_MARKER_PATTERN.test(value)
92
+ );
93
+ }
94
+
95
+ function isInitialImportResolution(value: unknown): value is InitialImportResolution {
96
+ return value === "accepted" || value === "declined";
97
+ }
98
+
99
+ function projectCredentialAutoImportState(value: unknown): CredentialAutoImportStateReadResult {
100
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
101
+ return { state: {}, problems: ["malformed-root"], unreadable: false };
102
+ }
103
+
104
+ const record = value as Record<string, unknown>;
105
+ const state: CredentialAutoImportStateFile = {};
106
+ const problems: CredentialAutoImportStateProblem[] = [];
107
+ if (Object.hasOwn(record, "initialImportResolution")) {
108
+ if (isInitialImportResolution(record.initialImportResolution)) {
109
+ state.initialImportResolution = record.initialImportResolution;
110
+ } else {
111
+ problems.push("invalid-initial-import-resolution");
112
+ }
113
+ }
114
+ if (Object.hasOwn(record, "lastImportVersion")) {
115
+ if (isValidVersionMarker(record.lastImportVersion)) {
116
+ state.lastImportVersion = record.lastImportVersion;
117
+ } else {
118
+ problems.push("invalid-last-import-version");
119
+ }
120
+ }
121
+ return { state, problems, unreadable: false };
122
+ }
123
+
124
+ async function readCredentialAutoImportStateAtPath(statePath: string): Promise<CredentialAutoImportStateReadResult> {
41
125
  try {
42
- const raw = await fs.readFile(getCredentialAutoImportStatePath(agentDir), "utf-8");
43
- const parsed = JSON.parse(raw) as CredentialAutoImportStateFile;
44
- return typeof parsed.lastImportVersion === "string" ? parsed.lastImportVersion : undefined;
45
- } catch {
46
- return undefined;
126
+ const raw = await fs.readFile(statePath, "utf-8");
127
+ try {
128
+ return projectCredentialAutoImportState(JSON.parse(raw) as unknown);
129
+ } catch {
130
+ return { state: {}, problems: ["malformed-json"], unreadable: false };
131
+ }
132
+ } catch (error: unknown) {
133
+ if (isEnoent(error)) return { state: {}, problems: [], unreadable: false };
134
+ return { state: {}, problems: [], unreadable: true };
47
135
  }
48
136
  }
49
137
 
50
- export async function writeCredentialImportMarker(version: string, agentDir?: string): Promise<boolean> {
138
+ function serializeCredentialAutoImportState(state: CredentialAutoImportStateFile): string {
139
+ const serialized: CredentialAutoImportStateFile = {};
140
+ if (isValidVersionMarker(state.lastImportVersion)) serialized.lastImportVersion = state.lastImportVersion;
141
+ if (isInitialImportResolution(state.initialImportResolution)) {
142
+ serialized.initialImportResolution = state.initialImportResolution;
143
+ }
144
+ return `${JSON.stringify(serialized)}\n`;
145
+ }
146
+
147
+ async function writeCredentialAutoImportStateAtomic(
148
+ statePath: string,
149
+ state: CredentialAutoImportStateFile,
150
+ rename: (oldPath: string, newPath: string) => Promise<void> = fs.rename,
151
+ ): Promise<void> {
152
+ const temporaryPath = `${statePath}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
51
153
  try {
52
- const statePath = getCredentialAutoImportStatePath(agentDir);
53
- await fs.mkdir(path.dirname(statePath), { recursive: true });
54
- await fs.writeFile(statePath, `${JSON.stringify({ lastImportVersion: version })}\n`);
55
- return true;
154
+ const handle = await fs.open(temporaryPath, "wx", 0o600);
155
+ try {
156
+ await handle.writeFile(serializeCredentialAutoImportState(state));
157
+ } finally {
158
+ await handle.close();
159
+ }
160
+ await rename(temporaryPath, statePath);
56
161
  } catch (error: unknown) {
57
- logger.warn("Failed to persist credential auto-import state", { error });
58
- return false;
162
+ await fs.rm(temporaryPath, { force: true }).catch(() => {});
163
+ throw error;
59
164
  }
60
165
  }
61
166
 
167
+ export function createCredentialAutoImportStateStore(
168
+ agentDir: string = getAgentDir(),
169
+ dependencies: CredentialAutoImportStateStoreDependencies = {},
170
+ ): CredentialAutoImportStateStore {
171
+ const statePath = getCredentialAutoImportStatePath(agentDir);
172
+ const lock = dependencies.withFileLock ?? withFileLock;
173
+ const rename = dependencies.rename ?? fs.rename;
174
+ return {
175
+ read: () => readCredentialAutoImportStateAtPath(statePath),
176
+ write: async mutation => {
177
+ if (
178
+ (mutation.lastImportVersion !== undefined && !isValidVersionMarker(mutation.lastImportVersion)) ||
179
+ (mutation.initialImportResolution !== undefined &&
180
+ !isInitialImportResolution(mutation.initialImportResolution))
181
+ ) {
182
+ return false;
183
+ }
184
+ try {
185
+ await fs.mkdir(path.dirname(statePath), { recursive: true, mode: 0o700 });
186
+ await lock(statePath, async () => {
187
+ const current = await readCredentialAutoImportStateAtPath(statePath);
188
+ if (current.unreadable) throw new Error("Credential auto-import state became unreadable");
189
+ const next: CredentialAutoImportStateFile = { ...current.state };
190
+ if (mutation.lastImportVersion !== undefined) next.lastImportVersion = mutation.lastImportVersion;
191
+ if (next.initialImportResolution === undefined && mutation.initialImportResolution !== undefined) {
192
+ next.initialImportResolution = mutation.initialImportResolution;
193
+ }
194
+ await writeCredentialAutoImportStateAtomic(statePath, next, rename);
195
+ });
196
+ return true;
197
+ } catch {
198
+ logger.warn("Credential auto-import state persistence failed", { classification: "state-write-failed" });
199
+ return false;
200
+ }
201
+ },
202
+ };
203
+ }
204
+
205
+ export async function readCredentialAutoImportState(agentDir?: string): Promise<CredentialAutoImportStateReadResult> {
206
+ return createCredentialAutoImportStateStore(agentDir).read();
207
+ }
208
+
209
+ export function isCredentialAutoImportStateResolvedForVersion(
210
+ state: CredentialAutoImportStateFile,
211
+ version: string,
212
+ ): boolean {
213
+ return (
214
+ state.initialImportResolution !== undefined ||
215
+ (state.lastImportVersion !== undefined && state.lastImportVersion === version)
216
+ );
217
+ }
218
+
219
+ export async function readCredentialImportMarker(agentDir?: string): Promise<string | undefined> {
220
+ return (await readCredentialAutoImportState(agentDir)).state.lastImportVersion;
221
+ }
222
+
223
+ export async function writeCredentialImportMarker(version: string, agentDir?: string): Promise<boolean> {
224
+ return createCredentialAutoImportStateStore(agentDir).write({ lastImportVersion: version });
225
+ }
226
+
62
227
  export enum CredentialAutoImportFailureClass {
63
228
  DiscoveryUnavailable = "discovery-unavailable",
64
229
  SourceUnreadable = "source-unreadable",
@@ -93,6 +258,63 @@ export interface CredentialAutoImportResult {
93
258
  globalDiscoveryFailure?: CredentialAutoImportFailure;
94
259
  }
95
260
 
261
+ const CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS: readonly ExternalProvider[] = ["anthropic", "openai-codex"];
262
+ const CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS: readonly CredentialOrigin[] = [
263
+ "claude-code-file",
264
+ "claude-code-keychain",
265
+ "codex-file",
266
+ ];
267
+ const CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS: Record<CredentialOrigin, string> = {
268
+ "claude-code-file": "Claude Code file",
269
+ "claude-code-keychain": "Claude Code Keychain",
270
+ "codex-file": "Codex CLI file",
271
+ };
272
+ const CREDENTIAL_AUTO_IMPORT_FAILURE_CLASSES = new Set(Object.values(CredentialAutoImportFailureClass));
273
+
274
+ export function formatCredentialAutoImportCandidateLabel(
275
+ candidate: Pick<ImportableCredential, "provider" | "origin">,
276
+ ): string {
277
+ const provider = CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS.includes(candidate.provider)
278
+ ? EXTERNAL_PROVIDER_LABELS[candidate.provider]
279
+ : undefined;
280
+ const origin = CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS.includes(candidate.origin)
281
+ ? CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS[candidate.origin]
282
+ : undefined;
283
+ return provider && origin ? `${provider} · ${origin}` : "External OAuth credential";
284
+ }
285
+
286
+ export function formatCredentialAutoImportPrompt(
287
+ candidates: readonly Pick<ImportableCredential, "provider" | "origin">[],
288
+ ): string {
289
+ const lines: string[] = [];
290
+ for (const provider of CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS) {
291
+ for (const origin of CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS) {
292
+ const count = candidates.filter(
293
+ candidate => candidate.provider === provider && candidate.origin === origin,
294
+ ).length;
295
+ if (count > 0)
296
+ lines.push(
297
+ `${EXTERNAL_PROVIDER_LABELS[provider]} · ${CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS[origin]}: ${count}`,
298
+ );
299
+ }
300
+ }
301
+ return `External OAuth credentials found: ${candidates.length}\n${lines.join("\n")}`;
302
+ }
303
+
304
+ export function logCredentialAutoImportFailures(
305
+ trigger: CredentialAutoImportTrigger,
306
+ failures: readonly Pick<CredentialAutoImportFailure, "failureClass">[],
307
+ ): void {
308
+ const failureCounts: Partial<Record<CredentialAutoImportFailureClass, number>> = {};
309
+ for (const failure of failures) {
310
+ if (!CREDENTIAL_AUTO_IMPORT_FAILURE_CLASSES.has(failure.failureClass)) continue;
311
+ failureCounts[failure.failureClass] = (failureCounts[failure.failureClass] ?? 0) + 1;
312
+ }
313
+ if (Object.keys(failureCounts).length > 0) {
314
+ logger.warn("Credential auto-import completed with failures", { trigger, failureCounts });
315
+ }
316
+ }
317
+
96
318
  export type CredentialAutoImportAuthStorage = Pick<AuthStorage, "importCredentialIfAbsent">;
97
319
 
98
320
  export interface CredentialAutoImportOptions {
@@ -204,18 +426,38 @@ export function formatCredentialAutoImportResult(result: CredentialAutoImportRes
204
426
  return lines;
205
427
  }
206
428
 
207
- export interface CredentialImportMarkerStore {
208
- read: () => Promise<string | undefined> | string | undefined;
209
- write: (version: string) => Promise<boolean> | boolean;
210
- }
211
-
212
429
  export interface StartupCredentialAutoImportOptions {
213
430
  authStorage: CredentialAutoImportOptions["authStorage"];
214
431
  modelRegistry: Pick<ModelRegistry, "refresh">;
215
432
  discover?: CredentialAutoImportOptions["discover"];
216
433
  version?: string;
217
434
  agentDir?: string;
218
- markerStore?: CredentialImportMarkerStore;
435
+ stateStore?: CredentialAutoImportStateStore;
436
+ }
437
+
438
+ function appendNoticeLine(notice: string | undefined, line: string): string {
439
+ return notice ? `${notice}\n${line}` : line;
440
+ }
441
+
442
+ async function readStateSafely(store: CredentialAutoImportStateStore): Promise<CredentialAutoImportStateReadResult> {
443
+ try {
444
+ return await store.read();
445
+ } catch {
446
+ logger.warn("Credential auto-import state read failed", { classification: "state-read-failed" });
447
+ return { state: {}, problems: [], unreadable: true };
448
+ }
449
+ }
450
+
451
+ async function writeStateSafely(
452
+ store: CredentialAutoImportStateStore,
453
+ mutation: CredentialAutoImportStateMutation,
454
+ ): Promise<boolean> {
455
+ try {
456
+ return await store.write(mutation);
457
+ } catch {
458
+ logger.warn("Credential auto-import state persistence failed", { classification: "state-write-failed" });
459
+ return false;
460
+ }
219
461
  }
220
462
 
221
463
  export async function runStartupCredentialAutoImportIfNeeded({
@@ -224,17 +466,15 @@ export async function runStartupCredentialAutoImportIfNeeded({
224
466
  discover,
225
467
  version = VERSION,
226
468
  agentDir,
227
- markerStore,
469
+ stateStore,
228
470
  }: StartupCredentialAutoImportOptions): Promise<string | undefined> {
229
- const store = markerStore ?? {
230
- read: () => readCredentialImportMarker(agentDir),
231
- write: (nextVersion: string) => writeCredentialImportMarker(nextVersion, agentDir),
232
- };
233
- const lastVersion = await store.read();
234
- if (lastVersion === version) {
235
- // Steady state: user already completed this version's auto-import gate. Skip all file/Keychain reads.
471
+ const store = stateStore ?? createCredentialAutoImportStateStore(agentDir);
472
+ const stateRead = await readStateSafely(store);
473
+ if (stateRead.unreadable) {
474
+ logger.warn("Credential auto-import state unavailable", { classification: "state-unreadable" });
236
475
  return undefined;
237
476
  }
477
+ if (isCredentialAutoImportStateResolvedForVersion(stateRead.state, version)) return undefined;
238
478
 
239
479
  const result = await runExternalCredentialAutoImport({
240
480
  authStorage: activeAuthStorage,
@@ -242,17 +482,32 @@ export async function runStartupCredentialAutoImportIfNeeded({
242
482
  trigger: "startup",
243
483
  });
244
484
  if (!result.discovered) {
485
+ logCredentialAutoImportFailures("startup", result.failures);
245
486
  return undefined;
246
487
  }
247
488
 
248
489
  const candidates = filterAutoImportOAuthCredentials(result.discovery?.importable ?? []);
249
- if (candidates.length > 0 && result.imported.length === 0 && result.skipped.length === 0) {
250
- return undefined;
490
+ const handledCandidates = result.imported.length + result.skipped.length > 0;
491
+ if (result.failures.length > 0) logCredentialAutoImportFailures("startup", result.failures);
492
+ let persisted = true;
493
+ if (handledCandidates) {
494
+ persisted = await writeStateSafely(store, {
495
+ lastImportVersion: version,
496
+ initialImportResolution: "accepted",
497
+ });
498
+ } else if (candidates.length === 0 && result.failures.length === 0) {
499
+ persisted = await writeStateSafely(store, { lastImportVersion: version });
251
500
  }
252
- await store.write(version);
253
501
 
502
+ let notice = buildCredentialAutoImportNotice(result);
503
+ if (!persisted) notice = appendNoticeLine(notice, CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
254
504
  if (result.imported.length > 0) {
255
- await activeModelRegistry.refresh("offline");
505
+ try {
506
+ await activeModelRegistry.refresh("offline");
507
+ } catch {
508
+ logger.warn("Credential auto-import refresh failed", { classification: "refresh-failed" });
509
+ notice = appendNoticeLine(notice, CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING);
510
+ }
256
511
  }
257
- return buildCredentialAutoImportNotice(result);
512
+ return notice;
258
513
  }
@@ -13,7 +13,7 @@ These instructions teach a Hermes-style coordinator how to operate GJC through t
13
13
  If a second task is needed while one turn is active, pass `queue: true`; the next queued turn is promoted after the active turn is reported terminal.
14
14
  5. If GJC asks a structured question, use `{{TOOL_PREFIX}}_list_questions` and answer with `{{TOOL_PREFIX}}_submit_question_answer`.
15
15
  6. Use `{{TOOL_PREFIX}}_report_status` for coordinator-visible status and final reports.
16
- 7. Use `{{TOOL_PREFIX}}_read_tail` only as advisory debug output when structured turn state is insufficient.
16
+ 7. Use `{{TOOL_PREFIX}}_read_tail` only to inspect the latest assistant response through the SDK when structured turn state is insufficient; it never reads terminal output.
17
17
 
18
18
  ## Prefer high-level delegation
19
19
 
@@ -39,11 +39,9 @@ The Hermes bridge does not choose a model/provider. Generated setup configures `
39
39
 
40
40
  Provider-specific commands are examples only, never product defaults.
41
41
 
42
- ## Visible routed-session fallback
42
+ ## Human-visible TUI boundary
43
43
 
44
- If a Hermes/OpenClaw/Clawhip-style operator needs a human-visible, channel-routed GJC pane instead of a pure Coordinator MCP session, use the visible session pattern in [`docs/gjc-session-clawhip-routing.md`](../../../../../../docs/gjc-session-clawhip-routing.md).
45
-
46
- Use that pattern only when the router must watch tmux output, send stale-session alerts, or inject follow-up prompts into the same visible pane. The short version is: prepare a dedicated worktree, register a stable tmux session through the host router, start interactive `gjc`, wait for TUI readiness, inject the task prompt separately, and verify actual tool/work activity before reporting acceptance.
44
+ A human may choose to run the local TUI in tmux for terminal visibility. That terminal is not a controller API: Hermes/OpenClaw/Clawhip-style operators must not inject prompts into, scrape, or route machine decisions through a tmux pane. Use the Coordinator MCP tools above for every external control and viewing operation.
47
45
 
48
46
  Do not put private channel ids, mention targets, socket names, tokens, or local routing policy into portable setup output. Keep those in the host/operator deployment.
49
47
 
@@ -33,7 +33,7 @@ import {
33
33
  formatNotificationTestResult,
34
34
  recoverNotifications,
35
35
  sendNotificationTest,
36
- } from "../notifications/notification-service";
36
+ } from "../sdk/bus/notification-service";
37
37
  import { computeCacheMissCostSummary, formatCacheMissSummaryLines } from "../session/cache-economics";
38
38
  import { formatModelOnboardingGuidance } from "../setup/model-onboarding-guidance";
39
39
  import {
@@ -697,6 +697,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
697
697
  await runtime.session.setModel(selection.model, "default", {
698
698
  selector: selection.selector,
699
699
  thinkingLevel: existingDefaultThinkingLevel,
700
+ cause: "user-selection",
700
701
  });
701
702
  if (existingDefaultThinkingLevel) {
702
703
  runtime.session.setThinkingLevel(existingDefaultThinkingLevel);
@@ -914,19 +914,24 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
914
914
  progress.recentOutput = [];
915
915
  };
916
916
 
917
+ const forwardSubagentEvent = (
918
+ event: AgentEvent | Extract<AgentSessionEvent, { type: "model_fallback_switched" }>,
919
+ ) => {
920
+ if (!options.eventBus) return;
921
+ options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
922
+ index,
923
+ agent: agent.name,
924
+ agentSource: agent.source,
925
+ task,
926
+ assignment,
927
+ event,
928
+ });
929
+ };
930
+
917
931
  const processEvent = (event: AgentEvent) => {
918
932
  if (resolved) return;
919
933
 
920
- if (options.eventBus) {
921
- options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
922
- index,
923
- agent: agent.name,
924
- agentSource: agent.source,
925
- task,
926
- assignment,
927
- event,
928
- });
929
- }
934
+ forwardSubagentEvent(event);
930
935
 
931
936
  const now = Date.now();
932
937
  let flushProgress = false;
@@ -1234,6 +1239,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1234
1239
  authFallbackUsed,
1235
1240
  requestedModel,
1236
1241
  fallbackReason,
1242
+ activeIndex,
1243
+ parentFallbackSelector,
1244
+ skips,
1237
1245
  } = await awaitAbortable(
1238
1246
  resolveModelOverrideWithAuthFallback(
1239
1247
  modelPatterns,
@@ -1241,6 +1249,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1241
1249
  modelRegistry,
1242
1250
  settings,
1243
1251
  options.parentSessionId,
1252
+ { managedFallback: true },
1244
1253
  ),
1245
1254
  );
1246
1255
  if (model) {
@@ -1431,6 +1440,21 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1431
1440
  );
1432
1441
 
1433
1442
  activeSession = session;
1443
+ // Each subagent invocation owns a fresh controller; its configured chain
1444
+ // is scoped to this child session and never shares parent sticky state.
1445
+ // Auth-aware resolution can substitute the parent model only after every
1446
+ // override entry was unavailable. Rebase the controller to that concrete
1447
+ // parent selector so its request is never charged to override index zero.
1448
+ session.setConfiguredModelChain(
1449
+ "default",
1450
+ parentFallbackSelector ? [parentFallbackSelector] : modelPatterns,
1451
+ "subagent",
1452
+ agent.name,
1453
+ true,
1454
+ );
1455
+ if (activeIndex !== undefined && !parentFallbackSelector) {
1456
+ session.seedDefaultFallbackResolution(activeIndex, skips);
1457
+ }
1434
1458
  const liveSubagentId = options.subagentId ?? id;
1435
1459
  const manager = AsyncJobManager.instance();
1436
1460
  if (manager) {
@@ -1508,12 +1532,14 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1508
1532
  pendingExtensionMessages.push(sendPromise);
1509
1533
  },
1510
1534
  sendUserMessage: (content, options) => {
1511
- const sendPromise = session.sendUserMessage(content, options).catch(e => {
1535
+ const send = session.sendUserMessage(content, options);
1536
+ const observedSend = send.catch(e => {
1512
1537
  logger.error("Extension sendUserMessage failed", {
1513
1538
  error: e instanceof Error ? e.message : String(e),
1514
1539
  });
1515
1540
  });
1516
- pendingExtensionMessages.push(sendPromise);
1541
+ pendingExtensionMessages.push(observedSend);
1542
+ return send;
1517
1543
  },
1518
1544
  appendEntry: (customType, data) => {
1519
1545
  session.sessionManager.appendCustomEntry(customType, data);
@@ -1528,7 +1554,17 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1528
1554
  getCommands: () => getSessionSlashCommands(session),
1529
1555
  setModel: model => runExtensionSetModel(session, model),
1530
1556
  getThinkingLevel: () => session.thinkingLevel,
1531
- setThinkingLevel: level => session.setThinkingLevel(level),
1557
+ setThinkingLevel: (level, persist) => session.setThinkingLevel(level, persist),
1558
+ getThinkingVisibility: () => session.getThinkingVisibility(),
1559
+ setThinkingVisibility: (visibility, persist) => session.setThinkingVisibility(visibility, persist),
1560
+ cycleThinkingLevel: () => session.cycleThinkingLevel(),
1561
+ setThinkingLevelForControl: (level, persist) => session.setThinkingLevelForControl(level, persist),
1562
+ setThinkingVisibilityForControl: (visibility, persist) =>
1563
+ session.setThinkingVisibilityForControl(visibility, persist),
1564
+ setModelTemporaryForControl: (model, expectedSessionId) =>
1565
+ session.setModelTemporaryForControl(model, expectedSessionId),
1566
+ fetchUsageReportsForControl: () => session.fetchUsageReportsForControl(),
1567
+ getThinkingScopeForControl: () => session.getThinkingScopeForControl(),
1532
1568
  getSessionName: () => session.sessionManager.getSessionName(),
1533
1569
  setSessionName: async name => {
1534
1570
  await session.sessionManager.setSessionName(name, "user");
@@ -1539,10 +1575,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1539
1575
  isIdle: () => !session.isStreaming,
1540
1576
  abort: () => session.abort(),
1541
1577
  hasPendingMessages: () => session.queuedMessageCount > 0,
1578
+ getPendingMessageCounts: () => session.pendingMessageCounts,
1579
+ getTranscript: () => session.getTranscript(),
1580
+ getTranscriptBody: entryId => session.getTranscriptBody(entryId),
1581
+ getGoalState: () => session.getGoalModeState(),
1582
+ getTodoState: () => session.getTodoPhases(),
1583
+ getQueuedMessages: () => session.getQueuedMessageEntries(),
1584
+ getActiveTools: () => session.getActiveToolNames(),
1585
+ getAllTools: () => session.getAllToolNames(),
1542
1586
  shutdown: () => {},
1543
1587
  getContextUsage: () => session.getContextUsage(),
1544
1588
  getSystemPrompt: () => session.systemPrompt,
1545
1589
  compact: instructionsOrOptions => runExtensionCompact(session, instructionsOrOptions),
1590
+ clearContext: () => session.clearContext(),
1546
1591
  },
1547
1592
  );
1548
1593
  extensionRunner.onError(err => {
@@ -1581,6 +1626,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1581
1626
  scheduleProgress(true);
1582
1627
  return;
1583
1628
  }
1629
+ if (event.type === "model_fallback_switched") {
1630
+ forwardSubagentEvent(event);
1631
+ return;
1632
+ }
1584
1633
  if (isAgentEvent(event)) {
1585
1634
  try {
1586
1635
  processEvent(event);
package/src/task/index.ts CHANGED
@@ -19,7 +19,7 @@ import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "@gajae
19
19
  import type { Model, Usage } from "@gajae-code/ai";
20
20
  import { $env, prompt, Snowflake } from "@gajae-code/utils";
21
21
  import type { ToolSession } from "..";
22
- import { AsyncJobManager } from "../async";
22
+ import { AsyncJobManager, OwnerSubagentShutdownError, type ResumeRunner } from "../async";
23
23
  import { resolveAgentModelPatterns } from "../config/model-resolver";
24
24
  import type { Theme } from "../modes/theme/theme";
25
25
  import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
@@ -547,8 +547,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
547
547
  };
548
548
 
549
549
  const maxConcurrency = this.session.settings.get("task.maxConcurrency");
550
+ let resumeRunner: ResumeRunner | undefined;
550
551
  if (typeof manager.setResumeRunner === "function") {
551
- manager.setResumeRunner((_subagentId, message, resumeDescriptor) => {
552
+ resumeRunner = (_subagentId, message, resumeDescriptor) => {
552
553
  const descriptor = isTaskResumeDescriptor(resumeDescriptor?.data) ? resumeDescriptor.data : undefined;
553
554
  if (!descriptor) return undefined;
554
555
  const forkSeeds = descriptor.forkContextSeed
@@ -590,7 +591,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
590
591
  },
591
592
  },
592
593
  );
593
- });
594
+ };
595
+ manager.setResumeRunner(resumeRunner);
594
596
  }
595
597
  const semaphore = new Semaphore(maxConcurrency);
596
598
  const buildForkContextSeedForTask = async (task: TaskItem): Promise<ForkContextSeed | undefined> => {
@@ -770,18 +772,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
770
772
  );
771
773
  startedJobs.push({ jobId, taskId: taskItem.id });
772
774
  if (typeof manager.registerResumeDescriptor === "function") {
773
- manager.registerResumeDescriptor({
774
- subagentId: uniqueId,
775
- ownerId: this.session.getAgentId?.() ?? undefined,
776
- data: {
777
- toolCallId: _toolCallId,
778
- params,
779
- task: { ...taskItem, id: uniqueId },
780
- sessionFile: subtaskSessionFile,
781
- forkContextSeed: frozenForkSeed,
782
- agentSource: fallbackAgentSource,
783
- } satisfies TaskResumeDescriptor,
784
- });
775
+ manager.registerResumeDescriptor(
776
+ {
777
+ subagentId: uniqueId,
778
+ ownerId: this.session.getAgentId?.() ?? undefined,
779
+ data: {
780
+ toolCallId: _toolCallId,
781
+ params,
782
+ task: { ...taskItem, id: uniqueId },
783
+ sessionFile: subtaskSessionFile,
784
+ forkContextSeed: frozenForkSeed,
785
+ agentSource: fallbackAgentSource,
786
+ } satisfies TaskResumeDescriptor,
787
+ },
788
+ resumeRunner,
789
+ );
785
790
  }
786
791
  if (typeof manager.registerSubagentRecord === "function") {
787
792
  manager.registerSubagentRecord({
@@ -795,7 +800,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
795
800
  });
796
801
  }
797
802
  } catch (error) {
798
- const message = error instanceof Error ? error.message : String(error);
803
+ const message =
804
+ error instanceof OwnerSubagentShutdownError
805
+ ? error.message
806
+ : error instanceof Error
807
+ ? error.message
808
+ : String(error);
799
809
  failedSchedules.push(`${taskItem.id}: ${message}`);
800
810
  const progress = progressByTaskId.get(taskItem.id);
801
811
  if (progress) {
@@ -7,7 +7,7 @@
7
7
  * source; registering returns a disposer.
8
8
  */
9
9
 
10
- import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/unattended-session";
10
+ import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/workflow-gate-broker";
11
11
  import type { AskAnswerSource } from "./index";
12
12
 
13
13
  const sources = new Map<string, AskAnswerSource>();