@gajae-code/coding-agent 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/CHANGELOG.md +50 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/cli/args.d.ts +4 -5
  4. package/dist/types/cli/daemon-cli.d.ts +12 -1
  5. package/dist/types/cli/notify-cli.d.ts +21 -1
  6. package/dist/types/cli.d.ts +3 -0
  7. package/dist/types/commands/daemon.d.ts +39 -0
  8. package/dist/types/commands/launch.d.ts +3 -0
  9. package/dist/types/commands/notify.d.ts +28 -1
  10. package/dist/types/commands/sdk.d.ts +33 -0
  11. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  12. package/dist/types/config/model-profile-activation.d.ts +35 -15
  13. package/dist/types/config/model-profiles.d.ts +11 -5
  14. package/dist/types/config/model-registry.d.ts +3 -3
  15. package/dist/types/config/model-resolver.d.ts +39 -6
  16. package/dist/types/config/model-selector-value.d.ts +17 -0
  17. package/dist/types/config/models-config-schema.d.ts +10 -6
  18. package/dist/types/config/settings-schema.d.ts +133 -6
  19. package/dist/types/config/settings.d.ts +63 -35
  20. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  21. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  22. package/dist/types/daemon/builtin.d.ts +6 -5
  23. package/dist/types/daemon/control-types.d.ts +1 -1
  24. package/dist/types/discovery/mcp-json.d.ts +12 -1
  25. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  27. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  28. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  29. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  30. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  31. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  32. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  33. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  35. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  36. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  37. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  38. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  39. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  40. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  41. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  42. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  43. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  44. package/dist/types/harness-control-plane/types.d.ts +3 -4
  45. package/dist/types/lsp/index.d.ts +1 -1
  46. package/dist/types/main.d.ts +32 -38
  47. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  48. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  49. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  50. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  51. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  52. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  53. package/dist/types/modes/components/model-selector.d.ts +1 -0
  54. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  55. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  56. package/dist/types/modes/components/welcome.d.ts +1 -1
  57. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  58. package/dist/types/modes/index.d.ts +0 -4
  59. package/dist/types/modes/interactive-mode.d.ts +3 -0
  60. package/dist/types/modes/runtime-init.d.ts +2 -2
  61. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  62. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  63. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  64. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  65. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  66. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  67. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  68. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  69. package/dist/types/modes/types.d.ts +5 -0
  70. package/dist/types/runtime-mcp/client.d.ts +2 -0
  71. package/dist/types/runtime-mcp/config.d.ts +5 -1
  72. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  73. package/dist/types/runtime-mcp/types.d.ts +4 -0
  74. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  75. package/dist/types/sdk/acp/index.d.ts +2 -0
  76. package/dist/types/sdk/broker/broker.d.ts +53 -0
  77. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  78. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  79. package/dist/types/sdk/broker/identity.d.ts +3 -0
  80. package/dist/types/sdk/broker/index.d.ts +8 -0
  81. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  82. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  83. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  84. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  85. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  86. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  87. package/dist/types/sdk/broker/transport.d.ts +9 -0
  88. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  89. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  90. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  91. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  92. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  93. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  94. package/dist/types/sdk/bus/config.d.ts +274 -0
  95. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  96. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  97. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  98. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  99. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  100. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  101. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  102. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  103. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  104. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  105. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  106. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  107. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  108. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  109. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  110. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  111. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  112. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  113. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  114. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  115. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  118. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  119. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  120. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  121. package/dist/types/sdk/cli/index.d.ts +1 -0
  122. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  123. package/dist/types/sdk/client/client.d.ts +1 -0
  124. package/dist/types/sdk/client/discovery.d.ts +27 -0
  125. package/dist/types/sdk/client/index.d.ts +2 -0
  126. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  127. package/dist/types/sdk/host/control/index.d.ts +2 -0
  128. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  129. package/dist/types/sdk/host/events.d.ts +35 -0
  130. package/dist/types/sdk/host/host.d.ts +35 -0
  131. package/dist/types/sdk/host/index.d.ts +4 -0
  132. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  133. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  134. package/dist/types/sdk/host/query/index.d.ts +3 -0
  135. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  136. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  137. package/dist/types/sdk/host/types.d.ts +32 -0
  138. package/dist/types/sdk/index.d.ts +6 -0
  139. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  140. package/dist/types/sdk/mcp/index.d.ts +1 -0
  141. package/dist/types/sdk/mcp/server.d.ts +37 -0
  142. package/dist/types/sdk/models.d.ts +44 -0
  143. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  144. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  145. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  146. package/dist/types/sdk/startup-capability.d.ts +50 -0
  147. package/dist/types/session/agent-session.d.ts +114 -21
  148. package/dist/types/session/default-model-selection.d.ts +25 -0
  149. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  150. package/dist/types/session/session-manager.d.ts +58 -1
  151. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  152. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  153. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  154. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  155. package/dist/types/tools/browser/launch.d.ts +22 -0
  156. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  157. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  158. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  159. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  160. package/dist/types/tools/browser/registry.d.ts +19 -0
  161. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  162. package/dist/types/tools/index.d.ts +8 -8
  163. package/package.json +34 -13
  164. package/scripts/build-sdk-package-smoke.ts +94 -0
  165. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  166. package/scripts/compile-args.ts +4 -2
  167. package/scripts/g005-daemon-smoke.ts +4 -5
  168. package/scripts/g011-daemon-path-smoke.ts +5 -5
  169. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  170. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  171. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  172. package/scripts/manifest-schema.ts +124 -0
  173. package/scripts/run-test-manifest.ts +153 -0
  174. package/scripts/run-threat-model-check.ts +157 -0
  175. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  176. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  177. package/src/append-only-mode.ts +1 -1
  178. package/src/cli/args.ts +43 -12
  179. package/src/cli/auth-gateway-cli.ts +2 -2
  180. package/src/cli/config-cli.ts +2 -1
  181. package/src/cli/daemon-cli.ts +63 -14
  182. package/src/cli/list-models.ts +1 -1
  183. package/src/cli/notify-cli.ts +288 -286
  184. package/src/cli.ts +21 -2
  185. package/src/commands/daemon.ts +50 -6
  186. package/src/commands/harness.ts +93 -36
  187. package/src/commands/launch.ts +5 -2
  188. package/src/commands/mcp-serve.ts +19 -12
  189. package/src/commands/notify.ts +36 -3
  190. package/src/commands/sdk.ts +426 -0
  191. package/src/commit/agentic/agent.ts +1 -0
  192. package/src/config/atomic-yaml-patch.ts +423 -0
  193. package/src/config/model-profile-activation.ts +240 -89
  194. package/src/config/model-profiles.ts +18 -15
  195. package/src/config/model-registry.ts +51 -26
  196. package/src/config/model-resolver.ts +138 -51
  197. package/src/config/model-selector-value.ts +50 -0
  198. package/src/config/models-config-schema.ts +14 -21
  199. package/src/config/settings-schema.ts +128 -10
  200. package/src/config/settings.ts +1120 -158
  201. package/src/coordinator-mcp/model-preset.ts +74 -20
  202. package/src/coordinator-mcp/server.ts +1597 -3052
  203. package/src/daemon/builtin.ts +8 -5
  204. package/src/daemon/control-types.ts +1 -1
  205. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  206. package/src/discovery/mcp-json.ts +327 -20
  207. package/src/extensibility/custom-tools/types.ts +1 -1
  208. package/src/extensibility/extensions/compact-handler.ts +3 -3
  209. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  210. package/src/extensibility/extensions/loader.ts +69 -5
  211. package/src/extensibility/extensions/runner.ts +112 -4
  212. package/src/extensibility/extensions/types.ts +176 -17
  213. package/src/extensibility/hooks/types.ts +1 -1
  214. package/src/gjc-runtime/launch-tmux.ts +170 -86
  215. package/src/gjc-runtime/psmux-detect.ts +82 -4
  216. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  217. package/src/gjc-runtime/team-runtime.ts +54 -35
  218. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  219. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  220. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  221. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  222. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  223. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  224. package/src/harness-control-plane/operate.ts +9 -9
  225. package/src/harness-control-plane/owner.ts +283 -39
  226. package/src/harness-control-plane/receipts.ts +0 -1
  227. package/src/harness-control-plane/sdk-transport.ts +395 -0
  228. package/src/harness-control-plane/session-transport.ts +94 -0
  229. package/src/harness-control-plane/types.ts +1 -1
  230. package/src/internal-urls/docs-index.generated.ts +34 -35
  231. package/src/lsp/client.ts +42 -6
  232. package/src/lsp/index.ts +2 -2
  233. package/src/main.ts +299 -204
  234. package/src/modes/DESIGN.md +258 -0
  235. package/src/modes/acp/acp-agent.ts +1228 -2612
  236. package/src/modes/acp/acp-client-bridge.ts +2 -20
  237. package/src/modes/acp/acp-event-mapper.ts +18 -2
  238. package/src/modes/acp/acp-mode.ts +8 -36
  239. package/src/modes/acp/permission-mode.ts +25 -0
  240. package/src/modes/acp/startup-options.ts +6 -0
  241. package/src/modes/components/agent-dashboard.ts +37 -17
  242. package/src/modes/components/model-selector.ts +93 -35
  243. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  244. package/src/modes/components/settings-selector.ts +60 -11
  245. package/src/modes/components/welcome.ts +4 -4
  246. package/src/modes/controllers/command-controller.ts +1 -2
  247. package/src/modes/controllers/event-controller.ts +11 -16
  248. package/src/modes/controllers/extension-ui-controller.ts +348 -4
  249. package/src/modes/controllers/selector-controller.ts +674 -36
  250. package/src/modes/index.ts +0 -22
  251. package/src/modes/interactive-mode.ts +59 -20
  252. package/src/modes/runtime-init.ts +298 -6
  253. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  254. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  255. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  256. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  257. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  258. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  259. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  260. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  261. package/src/modes/types.ts +5 -0
  262. package/src/runtime-mcp/client.ts +94 -19
  263. package/src/runtime-mcp/config.ts +27 -15
  264. package/src/runtime-mcp/manager.ts +343 -105
  265. package/src/runtime-mcp/oauth-flow.ts +42 -12
  266. package/src/runtime-mcp/transports/http.ts +49 -19
  267. package/src/runtime-mcp/transports/stdio.ts +47 -28
  268. package/src/runtime-mcp/types.ts +10 -0
  269. package/src/sdk/acp/adapter.ts +418 -0
  270. package/src/sdk/acp/index.ts +2 -0
  271. package/src/sdk/broker/broker.ts +642 -0
  272. package/src/sdk/broker/discovery.ts +94 -0
  273. package/src/sdk/broker/ensure.ts +249 -0
  274. package/src/sdk/broker/identity.ts +42 -0
  275. package/src/sdk/broker/index.ts +8 -0
  276. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  277. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  278. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  279. package/src/sdk/broker/lifecycle.ts +2157 -0
  280. package/src/sdk/broker/process-incarnation.ts +159 -0
  281. package/src/sdk/broker/runtime.ts +164 -0
  282. package/src/sdk/broker/session-index.ts +318 -0
  283. package/src/sdk/broker/state-version.ts +23 -0
  284. package/src/sdk/broker/transport.ts +125 -0
  285. package/src/sdk/bus/chat-command-policy.ts +107 -0
  286. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  287. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  288. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  289. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  290. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  291. package/src/sdk/bus/config.ts +433 -0
  292. package/src/sdk/bus/conversation-store.ts +391 -0
  293. package/src/sdk/bus/discord-conversation.ts +85 -0
  294. package/src/sdk/bus/discord-daemon.ts +2275 -0
  295. package/src/sdk/bus/discord-live-provider.ts +521 -0
  296. package/src/sdk/bus/discord-provider.ts +56 -0
  297. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  298. package/src/sdk/bus/index.ts +3943 -0
  299. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  300. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  301. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  302. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  303. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  304. package/src/sdk/bus/natives-augment.d.ts +38 -0
  305. package/src/sdk/bus/notification-orchestration.ts +535 -0
  306. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  307. package/src/sdk/bus/session-control.ts +333 -0
  308. package/src/sdk/bus/slack-conversation.ts +74 -0
  309. package/src/sdk/bus/slack-daemon.ts +2144 -0
  310. package/src/sdk/bus/slack-live-provider.ts +380 -0
  311. package/src/sdk/bus/slack-provider.ts +76 -0
  312. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  313. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  314. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  315. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  316. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  317. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  318. package/src/sdk/bus/telegram-setup.ts +663 -0
  319. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  320. package/src/sdk/cli/index.ts +1 -0
  321. package/src/sdk/cli/session-cli.ts +275 -0
  322. package/src/sdk/client/client.ts +1 -0
  323. package/src/sdk/client/discovery.ts +108 -0
  324. package/src/sdk/client/index.ts +2 -0
  325. package/src/sdk/host/control/dispatch.ts +367 -0
  326. package/src/sdk/host/control/index.ts +10 -0
  327. package/src/sdk/host/control/operations.ts +63 -0
  328. package/src/sdk/host/events.ts +91 -0
  329. package/src/sdk/host/host.ts +296 -0
  330. package/src/sdk/host/index.ts +4 -0
  331. package/src/sdk/host/query/cursor.ts +189 -0
  332. package/src/sdk/host/query/handlers.ts +533 -0
  333. package/src/sdk/host/query/index.ts +3 -0
  334. package/src/sdk/host/query/revision-store.ts +1126 -0
  335. package/src/sdk/host/reverse-leases.ts +325 -0
  336. package/src/sdk/host/types.ts +29 -0
  337. package/src/sdk/index.ts +13 -0
  338. package/src/sdk/lifecycle-session.ts +39 -0
  339. package/src/sdk/mcp/index.ts +1 -0
  340. package/src/sdk/mcp/server.ts +332 -0
  341. package/src/sdk/models.ts +168 -0
  342. package/src/sdk/protocol/adapter-validation.ts +48 -0
  343. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  344. package/src/sdk/protocol/operation-registry.ts +312 -0
  345. package/src/{sdk.ts → sdk/session.ts} +339 -212
  346. package/src/sdk/startup-capability.ts +189 -0
  347. package/src/session/agent-session.ts +2453 -894
  348. package/src/session/default-model-selection.ts +93 -0
  349. package/src/session/fallback-chain-controller.ts +136 -0
  350. package/src/session/session-manager.ts +438 -11
  351. package/src/session/session-storage.ts +8 -1
  352. package/src/setup/credential-auto-import.ts +290 -35
  353. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  354. package/src/slash-commands/builtin-registry.ts +2 -1
  355. package/src/task/executor.ts +62 -13
  356. package/src/tools/ask-answer-registry.ts +1 -1
  357. package/src/tools/ask.ts +13 -8
  358. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  359. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  360. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  361. package/src/tools/browser/launch.ts +124 -19
  362. package/src/tools/browser/profile-discovery.ts +63 -0
  363. package/src/tools/browser/profile-posture.ts +59 -0
  364. package/src/tools/browser/profile-reuse.ts +102 -0
  365. package/src/tools/browser/profile-warmup.ts +109 -0
  366. package/src/tools/browser/registry.ts +87 -11
  367. package/src/tools/browser/tab-protocol.ts +1 -0
  368. package/src/tools/browser/tab-supervisor.ts +1 -0
  369. package/src/tools/browser/tab-worker.ts +1 -1
  370. package/src/tools/browser.ts +6 -0
  371. package/src/tools/index.ts +8 -8
  372. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  373. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  374. package/src/tools/telegram-send.ts +2 -2
  375. package/vendor/insane-search/MANIFEST.json +2 -1
  376. package/vendor/insane-search/engine/bias_check.py +4 -1
  377. package/vendor/insane-search/engine/phase0.py +26 -1
  378. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  379. package/dist/types/modes/bridge/auth.d.ts +0 -12
  380. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  381. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  382. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  383. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  384. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  385. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  386. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  387. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  388. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  389. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  390. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  391. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  392. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  393. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  394. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  395. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  396. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  397. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  398. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  399. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  400. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  401. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  402. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  403. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  404. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  405. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  406. package/dist/types/notifications/config.d.ts +0 -132
  407. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  408. package/src/modes/bridge/auth.ts +0 -41
  409. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  410. package/src/modes/bridge/bridge-mode.ts +0 -675
  411. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  412. package/src/modes/bridge/event-stream.ts +0 -70
  413. package/src/modes/rpc/host-tools.ts +0 -1
  414. package/src/modes/rpc/host-uris.ts +0 -1
  415. package/src/modes/rpc/rpc-client.ts +0 -1166
  416. package/src/modes/rpc/rpc-mode.ts +0 -1029
  417. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  418. package/src/modes/rpc/rpc-types.ts +0 -637
  419. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  420. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  421. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  422. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  423. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  424. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  425. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  426. package/src/modes/shared/agent-wire/responses.ts +0 -17
  427. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  428. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  429. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  430. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  431. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  432. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  433. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  434. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  435. package/src/notifications/config.ts +0 -219
  436. package/src/notifications/index.ts +0 -1835
  437. package/src/notifications/telegram-daemon-cli.ts +0 -243
  438. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  439. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  440. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  441. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  442. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  443. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  444. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  445. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  446. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  447. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  448. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  453. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  454. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  455. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  456. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  457. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  458. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  459. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  460. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  461. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { ThinkingLevel, type ThinkingLevel as ThinkingLevelValue } from "@gajae-code/agent-core";
2
2
  import type { Effort } from "@gajae-code/ai";
3
3
  import {
4
+ type Component,
4
5
  Container,
5
6
  Input,
6
7
  matchesKey,
@@ -25,6 +26,10 @@ import { getCurrentThemeName, getSelectListTheme, getSettingsListTheme, theme }
25
26
  import { matchesAppInterrupt } from "../../modes/utils/keybinding-matchers";
26
27
  import { getTabBarTheme } from "../shared";
27
28
  import { DynamicBorder } from "./dynamic-border";
29
+ import {
30
+ type NotificationsEditorOperations,
31
+ NotificationsSettingsEditorComponent,
32
+ } from "./notifications-settings-editor";
28
33
  import { createPetSelectItems, getPetUnavailableWarning, isPetAvailable } from "./pet-capability";
29
34
  import { handleInputOrEscape, PluginSettingsComponent } from "./plugin-settings";
30
35
  import { getSettingsForTab, type SettingDef } from "./settings-defs";
@@ -712,6 +717,7 @@ export class SettingsSelectorComponent extends Container {
712
717
  #tabBar: TabBar;
713
718
  #currentList: SettingsList | null = null;
714
719
  #pluginComponent: PluginSettingsComponent | null = null;
720
+ #notificationsEditor: NotificationsSettingsEditorComponent | null = null;
715
721
  #statusPreviewContainer: Container | null = null;
716
722
  #statusPreviewText: Text | null = null;
717
723
  #currentTabId: SettingTab | "plugins" = "appearance";
@@ -720,6 +726,7 @@ export class SettingsSelectorComponent extends Container {
720
726
  constructor(
721
727
  private readonly context: SettingsRuntimeContext,
722
728
  private readonly callbacks: SettingsCallbacks,
729
+ private readonly notificationsOperations?: NotificationsEditorOperations,
723
730
  ) {
724
731
  super();
725
732
 
@@ -731,6 +738,7 @@ export class SettingsSelectorComponent extends Container {
731
738
  this.#tabBar.onTabChange = () => {
732
739
  this.#switchToTab(this.#tabBar.getActiveTab().id as SettingTab | "plugins");
733
740
  };
741
+
734
742
  this.addChild(this.#tabBar);
735
743
 
736
744
  // Spacer after tab bar
@@ -744,6 +752,9 @@ export class SettingsSelectorComponent extends Container {
744
752
  }
745
753
 
746
754
  #switchToTab(tabId: SettingTab | "plugins"): void {
755
+ if (this.#currentTabId === "notifications" && tabId !== "notifications" && !this.#disposeNotificationsEditor()) {
756
+ return;
757
+ }
747
758
  this.#currentTabId = tabId;
748
759
 
749
760
  // Remove current content
@@ -767,6 +778,8 @@ export class SettingsSelectorComponent extends Container {
767
778
 
768
779
  if (tabId === "plugins") {
769
780
  this.#showPluginsTab();
781
+ } else if (tabId === "notifications") {
782
+ this.#showNotificationsTab();
770
783
  } else {
771
784
  this.#showSettingsTab(tabId);
772
785
  }
@@ -775,6 +788,16 @@ export class SettingsSelectorComponent extends Container {
775
788
  this.addChild(bottomBorder);
776
789
  }
777
790
 
791
+ #disposeNotificationsEditor(): boolean {
792
+ const editor = this.#notificationsEditor;
793
+ if (!editor) return true;
794
+ if (editor.navigationLocked) return false;
795
+ editor.dispose();
796
+ this.removeChild(editor);
797
+ this.#notificationsEditor = null;
798
+ return true;
799
+ }
800
+
778
801
  /**
779
802
  * Convert a setting definition to a SettingItem for the UI.
780
803
  */
@@ -851,7 +874,7 @@ export class SettingsSelectorComponent extends Container {
851
874
  currentValue: string,
852
875
  done: (value?: string) => void,
853
876
  ): Container {
854
- let options: ReadonlyArray<SelectItem> = def.options;
877
+ let options = def.options;
855
878
 
856
879
  // Special case: inject runtime options for thinking level
857
880
  if (def.path === "defaultThinkingLevel") {
@@ -1033,6 +1056,14 @@ export class SettingsSelectorComponent extends Container {
1033
1056
  }
1034
1057
  }
1035
1058
 
1059
+ #showNotificationsTab(): void {
1060
+ if (!this.notificationsOperations) return;
1061
+ this.#notificationsEditor = new NotificationsSettingsEditorComponent(this.notificationsOperations, {
1062
+ onCancel: () => this.callbacks.onCancel(),
1063
+ });
1064
+ this.addChild(this.#notificationsEditor);
1065
+ }
1066
+
1036
1067
  /**
1037
1068
  * Show a settings tab using definitions.
1038
1069
  */
@@ -1197,21 +1228,39 @@ export class SettingsSelectorComponent extends Container {
1197
1228
  this.addChild(this.#pluginComponent);
1198
1229
  }
1199
1230
 
1200
- getFocusComponent(): SettingsList | PluginSettingsComponent {
1201
- // Return the current focusable component - one of these will always be set
1202
- return (this.#currentList || this.#pluginComponent)!;
1231
+ getFocusComponent(): Component {
1232
+ return (this.#currentList || this.#pluginComponent || this.#notificationsEditor)!;
1233
+ }
1234
+
1235
+ override dispose(): void {
1236
+ if (this.#notificationsEditor?.navigationLocked) return;
1237
+ this.#notificationsEditor?.dispose();
1238
+ this.#notificationsEditor = null;
1239
+ super.dispose();
1203
1240
  }
1204
1241
 
1205
1242
  handleInput(data: string): void {
1243
+ const tabNavigation =
1244
+ matchesKey(data, "tab") ||
1245
+ matchesKey(data, "shift+tab") ||
1246
+ matchesKey(data, "left") ||
1247
+ matchesKey(data, "right");
1248
+ if (this.#notificationsEditor && this.#currentTabId === "notifications") {
1249
+ if (tabNavigation) {
1250
+ if (this.#notificationsEditor.navigationLocked) {
1251
+ this.#notificationsEditor.handleInput(data);
1252
+ return;
1253
+ }
1254
+ this.#tabBar.handleInput(data);
1255
+ return;
1256
+ }
1257
+ this.#notificationsEditor.handleInput(data);
1258
+ return;
1259
+ }
1260
+
1206
1261
  // Handle tab switching — but NOT when a text input is active, since
1207
1262
  // arrow keys must reach the cursor and Tab must not switch tabs.
1208
- if (
1209
- !this.#textInputActive &&
1210
- (matchesKey(data, "tab") ||
1211
- matchesKey(data, "shift+tab") ||
1212
- matchesKey(data, "left") ||
1213
- matchesKey(data, "right"))
1214
- ) {
1263
+ if (!this.#textInputActive && tabNavigation) {
1215
1264
  this.#tabBar.handleInput(data);
1216
1265
  return;
1217
1266
  }
@@ -10,7 +10,7 @@ export interface RecentSession {
10
10
 
11
11
  export interface LspServerInfo {
12
12
  name: string;
13
- status: "ready" | "error" | "connecting";
13
+ status: "idle" | "ready" | "error" | "connecting";
14
14
  fileTypes: string[];
15
15
  }
16
16
 
@@ -172,9 +172,9 @@ export class WelcomeComponent implements Component {
172
172
  const icon =
173
173
  server.status === "ready"
174
174
  ? theme.styledSymbol("status.success", "success")
175
- : server.status === "connecting"
176
- ? theme.styledSymbol("status.pending", "muted")
177
- : theme.styledSymbol("status.error", "error");
175
+ : server.status === "error"
176
+ ? theme.styledSymbol("status.error", "error")
177
+ : theme.styledSymbol("status.pending", "muted");
178
178
  const exts = server.fileTypes.slice(0, 3).join(" ");
179
179
  lspLines.push(` ${icon} ${theme.fg("muted", server.name)} ${theme.fg("dim", exts)}`);
180
180
  }
@@ -450,8 +450,7 @@ export class CommandController {
450
450
  if (this.ctx.lspServers && this.ctx.lspServers.length > 0) {
451
451
  info += `\n${theme.bold("LSP Servers")}\n`;
452
452
  for (const server of this.ctx.lspServers) {
453
- const statusColor =
454
- server.status === "ready" ? "success" : server.status === "connecting" ? "warning" : "error";
453
+ const statusColor = server.status === "ready" ? "success" : server.status === "error" ? "error" : "warning";
455
454
  const statusText =
456
455
  server.status === "error" && server.error ? `${server.status}: ${server.error}` : server.status;
457
456
  info += `${theme.fg("dim", `${server.name}:`)} ${theme.fg(statusColor, statusText)} ${theme.fg("dim", `(${server.fileTypes.join(", ")})`)}\n`;
@@ -16,9 +16,9 @@ import { ToolExecutionComponent } from "../../modes/components/tool-execution";
16
16
  import { TtsrNotificationComponent } from "../../modes/components/ttsr-notification";
17
17
  import { getSymbolTheme, theme } from "../../modes/theme/theme";
18
18
  import type { InteractiveModeContext, TodoPhase } from "../../modes/types";
19
- import { completionNotifyDisabledByEnv } from "../../notifications/config";
20
- import { summaryFromMessage } from "../../notifications/helpers";
21
19
  import type { PlanApprovalDetails } from "../../plan-mode/approved-plan";
20
+ import { completionNotifyDisabledByEnv } from "../../sdk/bus/config";
21
+ import { summaryFromMessage } from "../../sdk/bus/helpers";
22
22
  import type { AgentSessionEvent } from "../../session/agent-session";
23
23
  import { type CustomMessage, isSilentAbort, readPendingDisplayTag } from "../../session/messages";
24
24
  import { transferSessionMessageIdentity } from "../../session/session-manager";
@@ -135,14 +135,13 @@ export class EventController {
135
135
  auto_compaction_end: e => this.#handleAutoCompactionEnd(e),
136
136
  auto_retry_start: e => this.#handleAutoRetryStart(e),
137
137
  auto_retry_end: e => this.#handleAutoRetryEnd(e),
138
- retry_fallback_applied: e => this.#handleRetryFallbackApplied(e),
139
- retry_fallback_succeeded: e => this.#handleRetryFallbackSucceeded(e),
140
138
  ttsr_triggered: e => this.#handleTtsrTriggered(e),
141
139
  todo_reminder: e => this.#handleTodoReminder(e),
142
140
  todo_auto_clear: e => this.#handleTodoAutoClear(e),
143
141
  irc_message: e => this.#handleIrcMessage(e),
144
142
  subagent_steer_message: e => this.#handleSubagentSteerMessage(e),
145
143
  notice: e => this.#handleNotice(e),
144
+ model_fallback_switched: e => this.#handleModelFallbackSwitched(e),
146
145
  thinking_level_changed: async () => {},
147
146
  goal_updated: async () => {},
148
147
  } satisfies AgentSessionEventHandlers;
@@ -497,6 +496,14 @@ export class EventController {
497
496
  this.ctx.ui.requestRender();
498
497
  }
499
498
 
499
+ async #handleModelFallbackSwitched(
500
+ event: Extract<AgentSessionEvent, { type: "model_fallback_switched" }>,
501
+ ): Promise<void> {
502
+ this.ctx.showStatus(`Fallback model: ${event.from} → ${event.to}`);
503
+ this.ctx.statusLine.invalidate();
504
+ this.ctx.ui.requestRender();
505
+ }
506
+
500
507
  async #handleNotice(event: Extract<AgentSessionEvent, { type: "notice" }>): Promise<void> {
501
508
  const message = event.source ? `${event.source}: ${event.message}` : event.message;
502
509
  if (event.level === "error") {
@@ -977,18 +984,6 @@ export class EventController {
977
984
  this.ctx.ui.requestRender();
978
985
  }
979
986
 
980
- async #handleRetryFallbackApplied(
981
- event: Extract<AgentSessionEvent, { type: "retry_fallback_applied" }>,
982
- ): Promise<void> {
983
- this.ctx.showWarning(`Fallback: ${event.from} -> ${event.to}`);
984
- }
985
-
986
- async #handleRetryFallbackSucceeded(
987
- event: Extract<AgentSessionEvent, { type: "retry_fallback_succeeded" }>,
988
- ): Promise<void> {
989
- this.ctx.showStatus(`Fallback succeeded on ${event.model}`);
990
- }
991
-
992
987
  async #handleTtsrTriggered(event: Extract<AgentSessionEvent, { type: "ttsr_triggered" }>): Promise<void> {
993
988
  const component = new TtsrNotificationComponent(event.rules);
994
989
  component.setExpanded(this.ctx.toolOutputExpanded);
@@ -1,3 +1,4 @@
1
+ import { ThinkingLevel } from "@gajae-code/agent-core";
1
2
  import type { Component, OverlayHandle, TUI } from "@gajae-code/tui";
2
3
  import { Container, Spacer, Text } from "@gajae-code/tui";
3
4
  import { logger } from "@gajae-code/utils";
@@ -22,6 +23,8 @@ import { HookInputComponent } from "../../modes/components/hook-input";
22
23
  import { HookSelectorComponent } from "../../modes/components/hook-selector";
23
24
  import { getAvailableThemesWithPaths, getThemeByName, setTheme, type Theme, theme } from "../../modes/theme/theme";
24
25
  import type { InteractiveModeContext } from "../../modes/types";
26
+ import { parseThinkingLevel } from "../../thinking";
27
+ import type { TodoPhase } from "../../tools/todo-write";
25
28
  import { setSessionTerminalTitle, setTerminalTitle } from "../../utils/title-generator";
26
29
  import { applyInjectedUserSubmission } from "../utils/injected-user-submission";
27
30
  import { classifyHookSelectorBellEvent, ringTerminalBell } from "../utils/terminal-bell";
@@ -50,6 +53,201 @@ export class ExtensionUiController {
50
53
  overlay?.hide();
51
54
  }
52
55
 
56
+ #sdkControl = async (operation: string, input: Record<string, unknown>): Promise<unknown> => {
57
+ const session = this.ctx.session;
58
+ switch (operation) {
59
+ case "model.set": {
60
+ const selector = typeof input.id === "string" ? input.id : "";
61
+ const slashIndex = selector.indexOf("/");
62
+ const model =
63
+ slashIndex > 0
64
+ ? session.modelRegistry.find(selector.slice(0, slashIndex), selector.slice(slashIndex + 1))
65
+ : undefined;
66
+ const thinkingLevel =
67
+ typeof input.thinkingLevel === "string" ? parseThinkingLevel(input.thinkingLevel) : undefined;
68
+ if (!model || !thinkingLevel || thinkingLevel === ThinkingLevel.Inherit)
69
+ throw Object.assign(new Error("model.set requires a valid model id and concrete thinkingLevel."), {
70
+ code: "invalid_input",
71
+ });
72
+ return await session.setDefaultModelSelection(model, thinkingLevel);
73
+ }
74
+ case "todo.replace": {
75
+ const phases = input.items;
76
+ if (
77
+ !Array.isArray(phases) ||
78
+ !phases.every(phase => {
79
+ if (!phase || typeof phase !== "object") return false;
80
+ const candidate = phase as { name?: unknown; tasks?: unknown };
81
+ return (
82
+ typeof candidate.name === "string" &&
83
+ Array.isArray(candidate.tasks) &&
84
+ candidate.tasks.every(task => {
85
+ if (!task || typeof task !== "object") return false;
86
+ const item = task as { content?: unknown; status?: unknown };
87
+ return (
88
+ typeof item.content === "string" &&
89
+ ["pending", "in_progress", "completed", "abandoned"].includes(String(item.status))
90
+ );
91
+ })
92
+ );
93
+ })
94
+ )
95
+ throw Object.assign(new Error("todo.replace requires TodoPhase items."), { code: "invalid_input" });
96
+ session.setTodoPhases(phases as TodoPhase[]);
97
+ return { replaced: session.getTodoPhases() };
98
+ }
99
+ case "permission_mode.set": {
100
+ const requested = input.mode;
101
+ const mode =
102
+ requested === "allow" || requested === "always-allow"
103
+ ? "allow"
104
+ : requested === "deny" || requested === "always-deny"
105
+ ? "deny"
106
+ : requested === "prompt"
107
+ ? "prompt"
108
+ : undefined;
109
+ if (!mode)
110
+ throw Object.assign(new Error("permission_mode.set requires prompt, allow, or deny."), {
111
+ code: "invalid_input",
112
+ });
113
+ session.setSdkPermissionMode(mode);
114
+ return { changed: true, mode: session.sdkPermissionMode };
115
+ }
116
+ case "bash.execute": {
117
+ if (typeof input.cmd !== "string" || input.cmd.trim() === "")
118
+ throw Object.assign(new Error("bash.execute requires a command."), { code: "invalid_input" });
119
+ const result = await session.executeBash(input.cmd, undefined, { excludeFromContext: true });
120
+ return {
121
+ exitCode: result.exitCode,
122
+ cancelled: result.cancelled,
123
+ output: result.output,
124
+ truncated: result.truncated,
125
+ };
126
+ }
127
+ case "bash.abort":
128
+ if (!session.isBashRunning) return { aborted: false };
129
+ session.abortBash();
130
+ return { aborted: true };
131
+ case "retry.last":
132
+ if (!(await session.retry()))
133
+ throw Object.assign(new Error("There is no failed or interrupted turn to retry."), {
134
+ code: "nothing_to_retry",
135
+ });
136
+ return { retried: true };
137
+ case "retry.now":
138
+ if (!session.isRetrying)
139
+ throw Object.assign(new Error("No retry backoff is pending."), { code: "retry_not_pending" });
140
+ session.retryNow();
141
+ return { retried: true, immediate: true };
142
+ case "bash.background":
143
+ if (!session.requestForegroundBashBackground())
144
+ throw Object.assign(new Error("The active bash command cannot be moved to a managed background job."), {
145
+ code: "not_foldable",
146
+ });
147
+ return { backgrounded: true };
148
+ case "compaction.auto.set":
149
+ session.setAutoCompactionEnabled(input.on === true);
150
+ return { changed: true };
151
+ case "retry.auto.set":
152
+ session.setAutoRetryEnabled(input.on === true);
153
+ return { changed: true };
154
+ case "retry.abort":
155
+ session.abortRetry();
156
+ return { aborted: true };
157
+ case "session.new":
158
+ return { created: await session.newSession() };
159
+ case "session.fork":
160
+ return { session: await session.fork() };
161
+ case "session.resume":
162
+ return { resumed: await session.switchSession(String(input.id)) };
163
+ case "session.close":
164
+ await session.sessionManager.flush();
165
+ return { closed: true };
166
+ case "session.switch":
167
+ return { switched: await session.switchSession(String(input.id)) };
168
+ case "session.branch":
169
+ try {
170
+ return await session.branch(String(input.entryId));
171
+ } catch (error) {
172
+ throw Object.assign(new Error(error instanceof Error ? error.message : "Branch entry was not found."), {
173
+ code: "resource_gone",
174
+ });
175
+ }
176
+ case "session.rename":
177
+ return { renamed: await session.setSessionName(String(input.name), "user") };
178
+ case "session.handoff":
179
+ try {
180
+ return {
181
+ handoff: await session.handoff(
182
+ typeof input.instructions === "string" ? input.instructions : undefined,
183
+ ),
184
+ };
185
+ } catch (error) {
186
+ throw Object.assign(
187
+ new Error(error instanceof Error ? error.message : "Handoff is unavailable for the current state."),
188
+ { code: "invalid_request" },
189
+ );
190
+ }
191
+ case "session.export_html":
192
+ try {
193
+ return { path: await session.exportToHtml(typeof input.path === "string" ? input.path : undefined) };
194
+ } catch (error) {
195
+ throw Object.assign(
196
+ new Error(
197
+ error instanceof Error ? error.message : "Session export is unavailable for the current state.",
198
+ ),
199
+ { code: "invalid_request" },
200
+ );
201
+ }
202
+ case "runtime.reload":
203
+ await session.reload();
204
+ return { reloaded: true };
205
+ case "service_tier.set":
206
+ session.setServiceTier(input.tier as never);
207
+ return { changed: true };
208
+ case "queue.message.remove": {
209
+ const removed = session.removeQueuedMessageForEditing(String(input.id));
210
+ if (removed === undefined)
211
+ throw Object.assign(new Error("Queued message was not found."), { code: "resource_gone" });
212
+ return { removed };
213
+ }
214
+ case "queue.message.move": {
215
+ const id = String(input.id);
216
+ const moved =
217
+ input.before !== undefined
218
+ ? session.moveQueuedMessageForEditing(id, "up")
219
+ : session.moveQueuedMessageForEditing(id, "down");
220
+ if (!moved) throw Object.assign(new Error("Queue position is invalid."), { code: "invalid_position" });
221
+ return { moved };
222
+ }
223
+ case "queue.message.update": {
224
+ const id = String(input.id);
225
+ const old = session.removeQueuedMessageForEditing(id);
226
+ const patch = input.patch as { text?: unknown };
227
+ if (old === undefined || typeof patch?.text !== "string")
228
+ throw Object.assign(new Error("Queued message update is invalid."), { code: "invalid_message" });
229
+ await session.sendUserMessage(patch.text, { deliverAs: id.startsWith("steer:") ? "steer" : "followUp" });
230
+ return { updated: true };
231
+ }
232
+ case "extension.set_enabled": {
233
+ const id = String(input.id);
234
+ const disabled = [...(session.settings.get("disabledExtensions") ?? [])];
235
+ const on = input.on === true;
236
+ const next = on ? disabled.filter(value => value !== id) : [...new Set([...disabled, id])];
237
+ session.settings.set("disabledExtensions", next);
238
+ return { changed: true, enabled: on };
239
+ }
240
+ case "session.delete":
241
+ await session.sessionManager.dropSession(String(input.id));
242
+ return { deleted: true };
243
+ case "session.cwd.move":
244
+ await session.sessionManager.moveTo(String(input.path));
245
+ return { moved: true, cwd: session.sessionManager.getCwd() };
246
+ default:
247
+ throw Object.assign(new Error(`${operation} has no AgentSession implementation.`), { code: "unavailable" });
248
+ }
249
+ };
250
+
53
251
  /** Re-mount the pet-aware composer after a transient hook UI closes. */
54
252
  #restoreComposerEditor(): void {
55
253
  this.ctx.restoreComposer();
@@ -128,11 +326,21 @@ export class ExtensionUiController {
128
326
  setModel: async model => {
129
327
  const key = await this.ctx.session.modelRegistry.getApiKey(model);
130
328
  if (!key) return false;
131
- await this.ctx.session.setModel(model);
329
+ await this.ctx.session.setModel(model, "default", { cause: "user-selection" });
132
330
  return true;
133
331
  },
134
332
  getThinkingLevel: () => this.ctx.session.thinkingLevel,
135
- setThinkingLevel: level => this.ctx.session.setThinkingLevel(level),
333
+ setThinkingLevel: (level, persist) => this.ctx.session.setThinkingLevel(level, persist),
334
+ getThinkingVisibility: () => this.ctx.session.getThinkingVisibility(),
335
+ setThinkingVisibility: (visibility, persist) => this.ctx.session.setThinkingVisibility(visibility, persist),
336
+ cycleThinkingLevel: () => this.ctx.session.cycleThinkingLevel(),
337
+ setThinkingLevelForControl: (level, persist) => this.ctx.session.setThinkingLevelForControl(level, persist),
338
+ setThinkingVisibilityForControl: (visibility, persist) =>
339
+ this.ctx.session.setThinkingVisibilityForControl(visibility, persist),
340
+ setModelTemporaryForControl: (model, expectedSessionId) =>
341
+ this.ctx.session.setModelTemporaryForControl(model, expectedSessionId),
342
+ fetchUsageReportsForControl: () => this.ctx.session.fetchUsageReportsForControl(),
343
+ getThinkingScopeForControl: () => this.ctx.session.getThinkingScopeForControl(),
136
344
  getCommands: () => getSessionSlashCommands(this.ctx.session),
137
345
  getSessionName: () => this.ctx.sessionManager.getSessionName(),
138
346
  setSessionName: name => this.#updateSessionName(name),
@@ -142,6 +350,15 @@ export class ExtensionUiController {
142
350
  isIdle: () => !this.ctx.session.isStreaming,
143
351
  abort: () => this.ctx.session.abort(),
144
352
  hasPendingMessages: () => this.ctx.session.queuedMessageCount > 0,
353
+ getPendingMessageCounts: () => this.ctx.session.pendingMessageCounts,
354
+ getTranscript: () => this.ctx.session.getTranscript(),
355
+ getTranscriptBody: entryId => this.ctx.session.getTranscriptBody(entryId),
356
+ getGoalState: () => this.ctx.session.getGoalModeState(),
357
+ getTodoState: () => this.ctx.session.getTodoPhases(),
358
+ getQueuedMessages: () => this.ctx.session.getQueuedMessageEntries(),
359
+ getActiveTools: () => this.ctx.session.getActiveToolNames(),
360
+ getAllTools: () => this.ctx.session.getAllToolNames(),
361
+
145
362
  shutdown: () => {
146
363
  // Defer the actual teardown to the main loop, which calls
147
364
  // `checkShutdownRequested()` at idle boundaries so any queued
@@ -151,6 +368,38 @@ export class ExtensionUiController {
151
368
  getContextUsage: () => this.ctx.session.getContextUsage(),
152
369
  compact: instructionsOrOptions => this.#compactSession(instructionsOrOptions),
153
370
  getSystemPrompt: () => this.ctx.session.systemPrompt,
371
+ clearContext: () => this.ctx.session.clearContext(),
372
+ cycleModel: () => this.ctx.session.cycleModel(),
373
+ cycleThinkingLevel: () => this.ctx.session.cycleThinkingLevel(),
374
+ setQueueMode: (kind, mode) => {
375
+ if (kind === "steering" && (mode === "all" || mode === "one-at-a-time")) {
376
+ this.ctx.session.setSteeringMode(mode);
377
+ return true;
378
+ }
379
+ if (kind === "follow_up" && (mode === "all" || mode === "one-at-a-time")) {
380
+ this.ctx.session.setFollowUpMode(mode);
381
+ return true;
382
+ }
383
+ if (kind === "interrupt" && (mode === "immediate" || mode === "wait")) {
384
+ this.ctx.session.setInterruptMode(mode);
385
+ return true;
386
+ }
387
+ return false;
388
+ },
389
+ invokeSkill: (name, args) => this.ctx.session.invokeSkill(name, args),
390
+ setPlanMode: on => this.ctx.session.setSdkPlanMode(on),
391
+ operateGoal: (op, objective) => this.ctx.session.operateGoal(op, objective),
392
+ getSkillState: () =>
393
+ this.ctx.session.skills.map(skill => ({ name: skill.name, description: skill.description })),
394
+ getConfigItems: () => ({
395
+ steeringMode: this.ctx.session.steeringMode,
396
+ followUpMode: this.ctx.session.followUpMode,
397
+ interruptMode: this.ctx.session.interruptMode,
398
+ }),
399
+ getBranchCandidates: () => this.ctx.sessionManager.getTree(),
400
+ getExtensions: () => this.ctx.session.extensionRunner?.getExtensionPaths() ?? [],
401
+ setSdkPermissionProvider: provider => this.ctx.session.setSdkPermissionProvider(provider),
402
+ sdkControl: this.#sdkControl,
154
403
  };
155
404
  const commandActions: ExtensionCommandContextActions = {
156
405
  getContextUsage: () => this.ctx.session.getContextUsage(),
@@ -377,11 +626,21 @@ export class ExtensionUiController {
377
626
  setModel: async model => {
378
627
  const key = await this.ctx.session.modelRegistry.getApiKey(model);
379
628
  if (!key) return false;
380
- await this.ctx.session.setModel(model);
629
+ await this.ctx.session.setModel(model, "default", { cause: "user-selection" });
381
630
  return true;
382
631
  },
383
632
  getThinkingLevel: () => this.ctx.session.thinkingLevel,
384
633
  setThinkingLevel: (level, persist) => this.ctx.session.setThinkingLevel(level, persist),
634
+ getThinkingVisibility: () => this.ctx.session.getThinkingVisibility(),
635
+ setThinkingVisibility: (visibility, persist) => this.ctx.session.setThinkingVisibility(visibility, persist),
636
+ cycleThinkingLevel: () => this.ctx.session.cycleThinkingLevel(),
637
+ setThinkingLevelForControl: (level, persist) => this.ctx.session.setThinkingLevelForControl(level, persist),
638
+ setThinkingVisibilityForControl: (visibility, persist) =>
639
+ this.ctx.session.setThinkingVisibilityForControl(visibility, persist),
640
+ setModelTemporaryForControl: (model, expectedSessionId) =>
641
+ this.ctx.session.setModelTemporaryForControl(model, expectedSessionId),
642
+ fetchUsageReportsForControl: () => this.ctx.session.fetchUsageReportsForControl(),
643
+ getThinkingScopeForControl: () => this.ctx.session.getThinkingScopeForControl(),
385
644
  getCommands: () => getSessionSlashCommands(this.ctx.session),
386
645
  getSessionName: () => this.ctx.sessionManager.getSessionName(),
387
646
  setSessionName: name => this.#updateSessionName(name),
@@ -391,6 +650,15 @@ export class ExtensionUiController {
391
650
  isIdle: () => !this.ctx.session.isStreaming,
392
651
  abort: () => this.ctx.session.abort(),
393
652
  hasPendingMessages: () => this.ctx.session.queuedMessageCount > 0,
653
+ getPendingMessageCounts: () => this.ctx.session.pendingMessageCounts,
654
+ getTranscript: () => this.ctx.session.getTranscript(),
655
+ getTranscriptBody: entryId => this.ctx.session.getTranscriptBody(entryId),
656
+ getGoalState: () => this.ctx.session.getGoalModeState(),
657
+ getTodoState: () => this.ctx.session.getTodoPhases(),
658
+ getQueuedMessages: () => this.ctx.session.getQueuedMessageEntries(),
659
+ getActiveTools: () => this.ctx.session.getActiveToolNames(),
660
+ getAllTools: () => this.ctx.session.getAllToolNames(),
661
+
394
662
  shutdown: () => {
395
663
  // Defer the actual teardown to the main loop, which calls
396
664
  // `checkShutdownRequested()` at idle boundaries so any queued
@@ -400,6 +668,35 @@ export class ExtensionUiController {
400
668
  getContextUsage: () => this.ctx.session.getContextUsage(),
401
669
  compact: instructionsOrOptions => this.#compactSession(instructionsOrOptions),
402
670
  getSystemPrompt: () => this.ctx.session.systemPrompt,
671
+ clearContext: () => this.ctx.session.clearContext(),
672
+ cycleModel: () => this.ctx.session.cycleModel(),
673
+ cycleThinkingLevel: () => this.ctx.session.cycleThinkingLevel(),
674
+ setQueueMode: (kind, mode) => {
675
+ if (kind === "steering" && (mode === "all" || mode === "one-at-a-time")) {
676
+ this.ctx.session.setSteeringMode(mode);
677
+ return true;
678
+ }
679
+ if (kind === "follow_up" && (mode === "all" || mode === "one-at-a-time")) {
680
+ this.ctx.session.setFollowUpMode(mode);
681
+ return true;
682
+ }
683
+ if (kind === "interrupt" && (mode === "immediate" || mode === "wait")) {
684
+ this.ctx.session.setInterruptMode(mode);
685
+ return true;
686
+ }
687
+ return false;
688
+ },
689
+ getSkillState: () =>
690
+ this.ctx.session.skills.map(skill => ({ name: skill.name, description: skill.description })),
691
+ getConfigItems: () => ({
692
+ steeringMode: this.ctx.session.steeringMode,
693
+ followUpMode: this.ctx.session.followUpMode,
694
+ interruptMode: this.ctx.session.interruptMode,
695
+ }),
696
+ getBranchCandidates: () => this.ctx.sessionManager.getTree(),
697
+ getExtensions: () => this.ctx.session.extensionRunner?.getExtensionPaths() ?? [],
698
+ setSdkPermissionProvider: provider => this.ctx.session.setSdkPermissionProvider(provider),
699
+ sdkControl: this.#sdkControl,
403
700
  };
404
701
  const commandActions: ExtensionCommandContextActions = {
405
702
  getContextUsage: () => this.ctx.session.getContextUsage(),
@@ -576,6 +873,14 @@ export class ExtensionUiController {
576
873
  model: this.ctx.session.model,
577
874
  isIdle: () => !this.ctx.session.isStreaming,
578
875
  hasPendingMessages: () => this.ctx.session.queuedMessageCount > 0,
876
+ getPendingMessageCounts: () => this.ctx.session.pendingMessageCounts,
877
+ getTranscript: () => this.ctx.session.getTranscript(),
878
+ getTranscriptBody: entryId => this.ctx.session.getTranscriptBody(entryId),
879
+ getGoalState: () => this.ctx.session.getGoalModeState(),
880
+ getTodoState: () => this.ctx.session.getTodoPhases(),
881
+ getQueuedMessages: () => this.ctx.session.getQueuedMessageEntries(),
882
+ getActiveTools: () => this.ctx.session.getActiveToolNames(),
883
+ getAllTools: () => this.ctx.session.getAllToolNames(),
579
884
  hasQueuedMessages: () => this.ctx.session.queuedMessageCount > 0,
580
885
  abort: () => {
581
886
  this.ctx.session.abort();
@@ -584,6 +889,44 @@ export class ExtensionUiController {
584
889
  // Signal shutdown request
585
890
  },
586
891
  getSystemPrompt: () => [...this.ctx.session.systemPrompt],
892
+ cycleModel: () => this.ctx.session.cycleModel(),
893
+ cycleThinkingLevel: () => this.ctx.session.cycleThinkingLevel(),
894
+ setQueueMode: (kind, mode) => {
895
+ if (kind === "steering" && (mode === "all" || mode === "one-at-a-time")) {
896
+ this.ctx.session.setSteeringMode(mode);
897
+ return true;
898
+ }
899
+ if (kind === "follow_up" && (mode === "all" || mode === "one-at-a-time")) {
900
+ this.ctx.session.setFollowUpMode(mode);
901
+ return true;
902
+ }
903
+ if (kind === "interrupt" && (mode === "immediate" || mode === "wait")) {
904
+ this.ctx.session.setInterruptMode(mode);
905
+ return true;
906
+ }
907
+ return false;
908
+ },
909
+ getSkillState: () =>
910
+ this.ctx.session.skills.map(skill => ({ name: skill.name, description: skill.description })),
911
+ getConfigItems: () => ({
912
+ steeringMode: this.ctx.session.steeringMode,
913
+ followUpMode: this.ctx.session.followUpMode,
914
+ interruptMode: this.ctx.session.interruptMode,
915
+ }),
916
+ getBranchCandidates: () => this.ctx.sessionManager.getTree(),
917
+ getExtensions: () => this.ctx.session.extensionRunner?.getExtensionPaths() ?? [],
918
+ getArtifact: () => undefined,
919
+ getJobs: () => undefined,
920
+ sdkBindings: () => [
921
+ "cycleModel",
922
+ "cycleThinkingLevel",
923
+ "setQueueMode",
924
+ "getSkillState",
925
+ "getConfigItems",
926
+ "getBranchCandidates",
927
+ "getExtensions",
928
+ ],
929
+ clearContext: () => this.ctx.session.clearContext(),
587
930
  });
588
931
  } catch (err) {
589
932
  this.showToolError(registeredTool.definition.name, err instanceof Error ? err.message : String(err));
@@ -981,9 +1324,10 @@ export class ExtensionUiController {
981
1324
  // (queueSteer/queueFollowUp push synchronously) before refreshing pending display.
982
1325
  const send = this.ctx.session.sendUserMessage(content, options);
983
1326
  applyInjectedUserSubmission(this.ctx, { content, queued });
984
- send.catch((err: unknown) => {
1327
+ void send.catch((err: unknown) => {
985
1328
  this.ctx.showError(`Extension sendUserMessage failed: ${err instanceof Error ? err.message : String(err)}`);
986
1329
  });
1330
+ return send;
987
1331
  };
988
1332
 
989
1333
  #applyCustomMessageDisplay(wasStreaming: boolean, shouldDisplay: boolean | undefined): void {