@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
@@ -21,27 +21,9 @@ import type {
21
21
  ClientBridgePermissionToolCall,
22
22
  ClientBridgeTerminalHandle,
23
23
  } from "../../session/client-bridge";
24
+ import { resolveAcpPermissionMode } from "./permission-mode";
24
25
 
25
- type AcpPermissionMode = "auto" | "prompt" | "always-allow";
26
-
27
- const ACP_PERMISSION_MODE_ENV = "GJC_ACP_PERMISSION_MODE";
28
-
29
- function parseAcpPermissionMode(value: unknown): AcpPermissionMode {
30
- if (value === "auto" || value === "prompt" || value === "always-allow") return value;
31
- return "prompt";
32
- }
33
-
34
- /** Client metadata is authoritative; the process environment is only a fallback when that field is absent. */
35
- function resolveAcpPermissionMode(clientCapabilities: ClientCapabilities | undefined): AcpPermissionMode {
36
- const meta = clientCapabilities?._meta;
37
- if (typeof meta === "object" && meta !== null) {
38
- const gjc = (meta as { gjc?: unknown }).gjc;
39
- if (typeof gjc === "object" && gjc !== null && "permissionHandling" in gjc) {
40
- return parseAcpPermissionMode((gjc as { permissionHandling?: unknown }).permissionHandling);
41
- }
42
- }
43
- return parseAcpPermissionMode(process.env[ACP_PERMISSION_MODE_ENV]);
44
- }
26
+ export { type AcpPermissionMode, resolveAcpPermissionMode } from "./permission-mode";
45
27
 
46
28
  export function createAcpClientBridge(
47
29
  connection: AgentSideConnection,
@@ -232,6 +232,24 @@ export function mapAgentSessionEventToAcpSessionUpdates(
232
232
  }
233
233
  case "todo_auto_clear":
234
234
  return [toSessionNotification(sessionId, { sessionUpdate: "plan", entries: [] })];
235
+ case "model_fallback_switched":
236
+ return [
237
+ toSessionNotification(sessionId, {
238
+ sessionUpdate: "session_info_update",
239
+ _meta: {
240
+ gjcModelFallbackSwitched: true,
241
+ gjcModelFallbackEventId: event.eventId,
242
+ gjcModelFallbackFrom: event.from,
243
+ gjcModelFallbackTo: event.to,
244
+ gjcModelFallbackReason: event.reason,
245
+ gjcModelFallbackRole: event.role,
246
+ gjcModelFallbackScope: event.scope,
247
+ gjcModelFallbackActiveIndex: event.activeIndex,
248
+ gjcModelFallbackChainLength: event.chainLength,
249
+ gjcModelFallbackAttemptsUsed: event.attemptsUsed,
250
+ },
251
+ }),
252
+ ];
235
253
  // These event types are intentionally not represented as ACP session updates.
236
254
  case "agent_start":
237
255
  case "agent_end":
@@ -278,8 +296,6 @@ export function mapAgentSessionEventToAcpSessionUpdates(
278
296
  }
279
297
  case "auto_retry_start":
280
298
  case "auto_retry_end":
281
- case "retry_fallback_applied":
282
- case "retry_fallback_succeeded":
283
299
  case "ttsr_triggered":
284
300
  case "irc_message":
285
301
  case "subagent_steer_message":
@@ -1,50 +1,22 @@
1
1
  import * as stream from "node:stream";
2
2
  import { AgentSideConnection, ndJsonStream, type Stream } from "@agentclientprotocol/sdk";
3
- import type { AgentSession } from "../../session/agent-session";
4
3
  import { AcpAgent } from "./acp-agent";
4
+ import type { AcpStartupOptions } from "./startup-options";
5
5
 
6
- export type AcpSessionFactory = (cwd: string) => Promise<AgentSession>;
7
-
8
- export interface AcpConnectionHandle {
9
- connection: AgentSideConnection;
10
- agent: AcpAgent;
11
- }
12
-
13
- export function createAcpConnection(
14
- transport: Stream,
15
- createSession: AcpSessionFactory,
16
- initialSession?: AgentSession,
17
- ): AgentSideConnection {
18
- return createAcpConnectionWithAgent(transport, createSession, initialSession).connection;
6
+ export interface AcpModeOptions {
7
+ agentDir?: string;
8
+ startupOptions?: AcpStartupOptions;
19
9
  }
20
10
 
21
- /**
22
- * Create an ACP connection and return both the {@link AgentSideConnection} and the
23
- * underlying {@link AcpAgent}. Callers that need to await agent shutdown (terminal
24
- * delete/dispose work) after transport closure should use this instead of
25
- * {@link createAcpConnection}.
26
- */
27
- export function createAcpConnectionWithAgent(
28
- transport: Stream,
29
- createSession: AcpSessionFactory,
30
- initialSession?: AgentSession,
31
- ): AcpConnectionHandle {
32
- let agent: AcpAgent | undefined;
33
- const connection = new AgentSideConnection(conn => {
34
- agent = new AcpAgent(conn, createSession, initialSession);
35
- return agent;
36
- }, transport);
37
- return { connection, agent: agent! };
11
+ export function createAcpConnection(transport: Stream, options: AcpModeOptions = {}): AgentSideConnection {
12
+ return new AgentSideConnection(conn => new AcpAgent(conn, options), transport);
38
13
  }
39
14
 
40
- export async function runAcpMode(createSession: AcpSessionFactory, initialSession?: AgentSession): Promise<never> {
15
+ export async function runAcpMode(options: AcpModeOptions = {}): Promise<never> {
41
16
  const input = stream.Writable.toWeb(process.stdout);
42
17
  const output = stream.Readable.toWeb(process.stdin);
43
18
  const transport = ndJsonStream(input, output);
44
- const { connection, agent } = createAcpConnectionWithAgent(transport, createSession, initialSession);
19
+ const connection = createAcpConnection(transport, options);
45
20
  await connection.closed;
46
- // Await connection-local terminal work (active deletes, disposal) so
47
- // `process.exit` never kills in-flight deletion/cleanup.
48
- await agent.shutdownPromise;
49
21
  process.exit(0);
50
22
  }
@@ -0,0 +1,25 @@
1
+ import type { ClientCapabilities } from "@agentclientprotocol/sdk";
2
+
3
+ export type AcpPermissionMode = "auto" | "prompt" | "always-allow";
4
+
5
+ const ACP_PERMISSION_MODE_ENV = "GJC_ACP_PERMISSION_MODE";
6
+
7
+ function parseAcpPermissionMode(value: unknown): AcpPermissionMode {
8
+ if (value === "auto" || value === "prompt" || value === "always-allow") return value;
9
+ return "prompt";
10
+ }
11
+
12
+ /** Client metadata is authoritative; the process environment is only a fallback when that field is absent. */
13
+ export function resolveAcpPermissionMode(
14
+ clientCapabilities: ClientCapabilities | undefined,
15
+ env: NodeJS.ProcessEnv = process.env,
16
+ ): AcpPermissionMode {
17
+ const meta = clientCapabilities?._meta;
18
+ if (typeof meta === "object" && meta !== null) {
19
+ const gjc = (meta as { gjc?: unknown }).gjc;
20
+ if (typeof gjc === "object" && gjc !== null && "permissionHandling" in gjc) {
21
+ return parseAcpPermissionMode((gjc as { permissionHandling?: unknown }).permissionHandling);
22
+ }
23
+ }
24
+ return parseAcpPermissionMode(env[ACP_PERMISSION_MODE_ENV]);
25
+ }
@@ -0,0 +1,6 @@
1
+ /** Startup settings that ACP can apply through the canonical SDK control surface. */
2
+ export interface AcpStartupOptions {
3
+ modelId?: string;
4
+ modelPreset?: string;
5
+ thinkingLevel?: string;
6
+ }
@@ -40,6 +40,7 @@ import {
40
40
  resolveConfiguredModelPatterns,
41
41
  resolveModelOverride,
42
42
  } from "../../config/model-resolver";
43
+ import { type ModelSelectorValue, selectorHead } from "../../config/model-selector-value";
43
44
  import { Settings } from "../../config/settings";
44
45
  import agentCreationArchitectPrompt from "../../prompts/system/agent-creation-architect.md" with { type: "text" };
45
46
  import agentCreationUserPrompt from "../../prompts/system/agent-creation-user.md" with { type: "text" };
@@ -84,6 +85,35 @@ interface AgentDashboardModelContext {
84
85
  defaultModelPattern?: string;
85
86
  }
86
87
 
88
+ export function resolveAgentCreationModel(
89
+ modelPatterns: string[],
90
+ modelRegistry: ModelRegistry,
91
+ settings: Settings | undefined,
92
+ ) {
93
+ const { model } = resolveModelOverride(modelPatterns, modelRegistry, settings);
94
+ if (model) return model;
95
+ if (modelPatterns.length > 0) {
96
+ throw new Error(`Configured model selector(s) did not resolve: ${modelPatterns.join(", ")}.`);
97
+ }
98
+
99
+ const fallbackModel = modelRegistry.getAvailable()[0];
100
+ if (!fallbackModel) {
101
+ throw new Error("No available model to generate agent specification.");
102
+ }
103
+ return fallbackModel;
104
+ }
105
+
106
+ export function updateAgentModelOverride(
107
+ overrides: Record<string, ModelSelectorValue>,
108
+ agentName: string,
109
+ rawValue: string,
110
+ ): Record<string, ModelSelectorValue> {
111
+ const value = rawValue.trim();
112
+ if (value) return { ...overrides, [agentName]: value };
113
+ const { [agentName]: _, ...remainingOverrides } = overrides;
114
+ return remainingOverrides;
115
+ }
116
+
87
117
  const SOURCE_ORDER: Record<AgentSource, number> = {
88
118
  project: 0,
89
119
  user: 1,
@@ -370,7 +400,7 @@ export class AgentDashboard extends Container {
370
400
  .map(agent => ({
371
401
  ...agent,
372
402
  disabled: disabled.has(agent.name),
373
- overrideModel: overrides[agent.name]?.trim() || undefined,
403
+ overrideModel: selectorHead(overrides[agent.name])?.trim() || undefined,
374
404
  }));
375
405
 
376
406
  this.#tabs = this.#buildTabs(this.#allAgents);
@@ -465,16 +495,10 @@ export class AgentDashboard extends Container {
465
495
  this.#settingsManager.set("task.disabledAgents", disabled);
466
496
  }
467
497
 
468
- #persistModelOverrides(): void {
498
+ #persistModelOverride(agentName: string, rawValue: string): void {
469
499
  if (!this.#settingsManager) return;
470
- const overrides: Record<string, string> = {};
471
- for (const agent of this.#allAgents) {
472
- const value = agent.overrideModel?.trim();
473
- if (value) {
474
- overrides[agent.name] = value;
475
- }
476
- }
477
- this.#settingsManager.set("task.agentModelOverrides", overrides);
500
+ const overrides = this.#settingsManager.get("task.agentModelOverrides");
501
+ this.#settingsManager.set("task.agentModelOverrides", updateAgentModelOverride(overrides, agentName, rawValue));
478
502
  }
479
503
 
480
504
  #toggleSelectedAgent(): void {
@@ -506,7 +530,7 @@ export class AgentDashboard extends Container {
506
530
  if (!selected) return;
507
531
  const value = rawValue.trim();
508
532
  selected.overrideModel = value || undefined;
509
- this.#persistModelOverrides();
533
+ this.#persistModelOverride(selected.name, value);
510
534
  this.#editingAgentName = null;
511
535
  this.#editInput = null;
512
536
  this.#applyFilters();
@@ -587,12 +611,7 @@ export class AgentDashboard extends Container {
587
611
  settings?.getModelRole("default"),
588
612
  settings,
589
613
  );
590
- const { model } = resolveModelOverride(modelPatterns, modelRegistry, settings);
591
- const fallbackModel = modelRegistry.getAvailable()[0];
592
- const selectedModel = model ?? fallbackModel;
593
- if (!selectedModel) {
594
- throw new Error("No available model to generate agent specification.");
595
- }
614
+ const selectedModel = resolveAgentCreationModel(modelPatterns, modelRegistry, settings);
596
615
 
597
616
  const systemPrompt = prompt.render(agentCreationArchitectPrompt, { TASK_TOOL_NAME: "task" });
598
617
  const userPrompt = prompt.render(agentCreationUserPrompt, { request: description });
@@ -605,6 +624,7 @@ export class AgentDashboard extends Container {
605
624
  model: selectedModel,
606
625
  systemPrompt: [systemPrompt],
607
626
  hasUI: false,
627
+ notificationHostModeSupported: false,
608
628
  enableLsp: false,
609
629
  enableMCP: false,
610
630
  disableExtensionDiscovery: true,
@@ -25,9 +25,11 @@ import {
25
25
  } from "../../config/model-registry";
26
26
  import {
27
27
  formatModelSelectorValue,
28
+ resolveConfiguredModelPatterns,
28
29
  resolveModelRoleValue,
29
30
  type ScopedModelSelection,
30
31
  } from "../../config/model-resolver";
32
+ import { type ModelSelectorValue, normalizeModelSelectorValue, selectorHead } from "../../config/model-selector-value";
31
33
  import type { ModelProfileConfig } from "../../config/models-config-schema";
32
34
  import type { Settings } from "../../config/settings";
33
35
  import { type ThemeColor, theme } from "../../modes/theme/theme";
@@ -227,9 +229,8 @@ function profileRequiredProviders(profile: ModelProfileDefinition): string[] {
227
229
  return [...new Set(profile.requiredProviders)].sort((a, b) => a.localeCompare(b));
228
230
  }
229
231
 
230
- function isInheritedRoleSelector(value: string | undefined): boolean {
231
- const normalized = value?.trim();
232
- return !normalized || normalized === "default" || normalized === "pi/default";
232
+ function isInheritedRoleSelector(value: string): boolean {
233
+ return value === "default" || value === "pi/default";
233
234
  }
234
235
 
235
236
  function getDefaultAliasThinkingLevel(value: string | undefined): ThinkingLevel | undefined {
@@ -245,28 +246,35 @@ function getSelectorProvider(selector: string): string | undefined {
245
246
 
246
247
  function deriveRequiredProviders(modelMapping: ModelProfileConfig["model_mapping"]): string[] {
247
248
  const providers = new Set<string>();
248
- for (const selector of Object.values(modelMapping)) {
249
- const provider = getSelectorProvider(selector);
250
- if (provider) providers.add(provider);
249
+ for (const selectorValue of Object.values(modelMapping)) {
250
+ for (const selector of normalizeModelSelectorValue(selectorValue)) {
251
+ const provider = getSelectorProvider(selector);
252
+ if (provider) providers.add(provider);
253
+ }
251
254
  }
252
255
  return [...providers].sort((a, b) => a.localeCompare(b));
253
256
  }
254
257
 
255
- function sameStringRecord(
256
- left: Readonly<Record<string, string | undefined>>,
257
- right: Readonly<Record<string, string | undefined>>,
258
+ function sameModelSelectorRecord(
259
+ left: Readonly<Record<string, ModelSelectorValue | undefined>>,
260
+ right: Readonly<Record<string, ModelSelectorValue | undefined>>,
258
261
  ): boolean {
259
262
  const leftEntries = Object.entries(left)
260
- .filter((entry): entry is [string, string] => entry[1] !== undefined)
263
+ .filter((entry): entry is [string, ModelSelectorValue] => entry[1] !== undefined)
261
264
  .sort(([a], [b]) => a.localeCompare(b));
262
265
  const rightEntries = Object.entries(right)
263
- .filter((entry): entry is [string, string] => entry[1] !== undefined)
266
+ .filter((entry): entry is [string, ModelSelectorValue] => entry[1] !== undefined)
264
267
  .sort(([a], [b]) => a.localeCompare(b));
265
268
  if (leftEntries.length !== rightEntries.length) return false;
266
269
  for (let i = 0; i < leftEntries.length; i++) {
267
270
  const leftEntry = leftEntries[i];
268
271
  const rightEntry = rightEntries[i];
269
- if (!leftEntry || !rightEntry || leftEntry[0] !== rightEntry[0] || leftEntry[1] !== rightEntry[1]) {
272
+ if (
273
+ !leftEntry ||
274
+ !rightEntry ||
275
+ leftEntry[0] !== rightEntry[0] ||
276
+ !sameStringArray(normalizeModelSelectorValue(leftEntry[1]), normalizeModelSelectorValue(rightEntry[1]))
277
+ ) {
270
278
  return false;
271
279
  }
272
280
  }
@@ -318,6 +326,7 @@ export class ModelSelectorComponent extends Container {
318
326
  #currentModel?: Model;
319
327
  #currentThinkingLevel?: ThinkingLevel;
320
328
  #activeModelProfile?: string;
329
+ #configuredDefaultChain?: readonly string[];
321
330
  #isFastForProvider: (provider?: string) => boolean = () => false;
322
331
  #isFastForSubagentProvider: (provider?: string) => boolean = () => false;
323
332
  #isCurrentModelFastModeActive: () => boolean = () => false;
@@ -359,6 +368,7 @@ export class ModelSelectorComponent extends Container {
359
368
  isCurrentModelFastModeActive?: () => boolean;
360
369
  currentThinkingLevel?: ThinkingLevel;
361
370
  activeModelProfile?: string;
371
+ configuredDefaultChain?: readonly string[];
362
372
  },
363
373
  ) {
364
374
  super();
@@ -374,6 +384,7 @@ export class ModelSelectorComponent extends Container {
374
384
  this.#currentModel = _currentModel;
375
385
  this.#currentThinkingLevel = options?.currentThinkingLevel;
376
386
  this.#activeModelProfile = options?.activeModelProfile;
387
+ this.#configuredDefaultChain = options?.configuredDefaultChain;
377
388
  this.#isFastForProvider = options?.isFastForProvider ?? (() => false);
378
389
  this.#isFastForSubagentProvider = options?.isFastForSubagentProvider ?? (() => false);
379
390
  // Current-model EFFECTIVE fast state. Defaults to intent for the current
@@ -451,6 +462,24 @@ export class ModelSelectorComponent extends Container {
451
462
  });
452
463
  }
453
464
 
465
+ #isActiveDefaultFallback(): boolean {
466
+ if (!this.#currentModel) return false;
467
+ const configuredChain =
468
+ this.#configuredDefaultChain ?? normalizeModelSelectorValue(this.#settings.getModelRole("default"));
469
+ if (configuredChain.length < 2) return false;
470
+
471
+ const allModels = this.#modelRegistry.getAll();
472
+ const matchPreferences = { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() };
473
+ return configuredChain.slice(1).some(selector => {
474
+ const resolved = resolveModelRoleValue(selector, allModels, {
475
+ settings: this.#settings,
476
+ matchPreferences,
477
+ modelRegistry: this.#modelRegistry,
478
+ });
479
+ return resolved.model !== undefined && modelsAreEqual(resolved.model, this.#currentModel);
480
+ });
481
+ }
482
+
454
483
  #loadRoleModels(): void {
455
484
  const allModels = this.#modelRegistry.getAll();
456
485
  const matchPreferences = { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() };
@@ -476,7 +505,12 @@ export class ModelSelectorComponent extends Container {
476
505
  };
477
506
  }
478
507
  }
479
- if (this.#activeModelProfile && this.#currentModel) {
508
+ if (
509
+ ((this.#configuredDefaultChain?.length ?? 0) > 0 ||
510
+ this.#activeModelProfile ||
511
+ this.#isActiveDefaultFallback()) &&
512
+ this.#currentModel
513
+ ) {
480
514
  this.#roles.default = {
481
515
  model: this.#currentModel,
482
516
  thinkingLevel: this.#currentThinkingLevel ?? ThinkingLevel.Inherit,
@@ -835,33 +869,57 @@ export class ModelSelectorComponent extends Container {
835
869
  return formatModelSelectorValue(`${this.#currentModel.provider}/${this.#currentModel.id}`, thinkingLevel);
836
870
  }
837
871
 
838
- #resolveProfileModelSelector(value: string | undefined): string | undefined {
839
- const normalized = value?.trim();
840
- if (isInheritedRoleSelector(normalized)) return undefined;
872
+ #resolveProfileModelSelector(value: ModelSelectorValue | undefined): string | string[] | undefined {
873
+ const resolvedSelectors: string[] = [];
874
+ for (const configuredSelector of normalizeModelSelectorValue(value)) {
875
+ if (isInheritedRoleSelector(configuredSelector)) continue;
876
+ const selectors = resolveConfiguredModelPatterns(configuredSelector, this.#settings);
877
+ for (const selector of selectors.length > 0 ? selectors : [configuredSelector]) {
878
+ const resolved = resolveModelRoleValue(selector, this.#modelRegistry.getAll(), {
879
+ settings: this.#settings,
880
+ matchPreferences: { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() },
881
+ modelRegistry: this.#modelRegistry,
882
+ });
883
+ if (resolved.model) {
884
+ resolvedSelectors.push(
885
+ formatModelSelectorValue(`${resolved.model.provider}/${resolved.model.id}`, resolved.thinkingLevel),
886
+ );
887
+ continue;
888
+ }
841
889
 
842
- const resolved = resolveModelRoleValue(normalized, this.#modelRegistry.getAll(), {
843
- settings: this.#settings,
844
- matchPreferences: { usageOrder: this.#settings.getStorage()?.getModelUsageOrder() },
845
- modelRegistry: this.#modelRegistry,
846
- });
847
- if (resolved.model) {
848
- return formatModelSelectorValue(`${resolved.model.provider}/${resolved.model.id}`, resolved.thinkingLevel);
849
- }
890
+ const inheritedDefaultThinkingLevel = getDefaultAliasThinkingLevel(selector);
891
+ if (inheritedDefaultThinkingLevel) {
892
+ const currentSelector = this.#formatCurrentModelSelector(inheritedDefaultThinkingLevel);
893
+ if (currentSelector) resolvedSelectors.push(currentSelector);
894
+ continue;
895
+ }
850
896
 
851
- const inheritedDefaultThinkingLevel = getDefaultAliasThinkingLevel(normalized);
852
- if (inheritedDefaultThinkingLevel) return this.#formatCurrentModelSelector(inheritedDefaultThinkingLevel);
853
- return undefined;
897
+ // Preserve unresolved chain members verbatim instead of silently
898
+ // truncating configured fallback tails.
899
+ resolvedSelectors.push(selector);
900
+ }
901
+ }
902
+ if (resolvedSelectors.length === 0) return undefined;
903
+ return resolvedSelectors.length === 1 ? resolvedSelectors[0] : resolvedSelectors;
854
904
  }
855
905
 
856
906
  #buildCustomModelProfileSnapshot(): ModelProfileConfig {
857
907
  const modelMapping: ModelProfileConfig["model_mapping"] = {};
858
- const currentModelSelector = this.#formatCurrentModelSelector();
859
- if (currentModelSelector) {
860
- modelMapping.default = currentModelSelector;
908
+ // Prefer the session's configured default chain so fallback tails are
909
+ // never dropped from the snapshot; the live model only replaces the head.
910
+ if (this.#configuredDefaultChain && this.#configuredDefaultChain.length > 0) {
911
+ const head = this.#formatCurrentModelSelector() ?? this.#configuredDefaultChain[0]!;
912
+ const tail = this.#configuredDefaultChain.slice(1);
913
+ modelMapping.default = tail.length > 0 ? [head, ...tail] : head;
861
914
  } else {
862
- const defaultRole = this.#settings.getModelRole("default");
863
- const defaultSelector = this.#resolveProfileModelSelector(defaultRole);
864
- if (defaultSelector) modelMapping.default = defaultSelector;
915
+ const currentModelSelector = this.#formatCurrentModelSelector();
916
+ if (currentModelSelector) {
917
+ modelMapping.default = currentModelSelector;
918
+ } else {
919
+ const defaultRole = this.#settings.getModelRole("default");
920
+ const defaultSelector = this.#resolveProfileModelSelector(defaultRole);
921
+ if (defaultSelector) modelMapping.default = defaultSelector;
922
+ }
865
923
  }
866
924
 
867
925
  const agentOverrides = this.#settings.get("task.agentModelOverrides");
@@ -880,7 +938,7 @@ export class ModelSelectorComponent extends Container {
880
938
  #findDuplicateGeneratedProfile(snapshot: ModelProfileConfig): ModelProfileDefinition | undefined {
881
939
  for (const profile of this.#modelRegistry.getModelProfiles?.().values() ?? []) {
882
940
  if (
883
- sameStringRecord(profile.modelMapping, snapshot.model_mapping) &&
941
+ sameModelSelectorRecord(profile.modelMapping, snapshot.model_mapping) &&
884
942
  sameStringArray(profile.requiredProviders, snapshot.required_providers)
885
943
  ) {
886
944
  return profile;
@@ -1148,7 +1206,7 @@ export class ModelSelectorComponent extends Container {
1148
1206
  });
1149
1207
  const label = GJC_MODEL_ASSIGNMENT_TARGETS[role].tag ?? role.toUpperCase();
1150
1208
  this.#listContainer.addChild(
1151
- new Text(` ${label}: ${formatClampedModelSelector(selector, resolved.model)}`, 0, 0),
1209
+ new Text(` ${label}: ${formatClampedModelSelector(selectorHead(selector) ?? "", resolved.model)}`, 0, 0),
1152
1210
  );
1153
1211
  }
1154
1212
  this.#listContainer.addChild(new Spacer(1));