@gajae-code/coding-agent 0.10.1 → 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 (474) hide show
  1. package/CHANGELOG.md +70 -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/gajae-pet-widget.d.ts +1 -0
  54. package/dist/types/modes/components/model-selector.d.ts +1 -0
  55. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  56. package/dist/types/modes/components/pet-capability.d.ts +37 -0
  57. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  58. package/dist/types/modes/components/settings-selector.d.ts +15 -4
  59. package/dist/types/modes/components/welcome.d.ts +1 -1
  60. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  61. package/dist/types/modes/index.d.ts +0 -4
  62. package/dist/types/modes/interactive-mode.d.ts +5 -1
  63. package/dist/types/modes/runtime-init.d.ts +2 -2
  64. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  65. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  66. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  67. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  68. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  69. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  72. package/dist/types/modes/types.d.ts +16 -1
  73. package/dist/types/runtime-mcp/client.d.ts +2 -0
  74. package/dist/types/runtime-mcp/config.d.ts +5 -1
  75. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  76. package/dist/types/runtime-mcp/types.d.ts +4 -0
  77. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  78. package/dist/types/sdk/acp/index.d.ts +2 -0
  79. package/dist/types/sdk/broker/broker.d.ts +53 -0
  80. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  81. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  82. package/dist/types/sdk/broker/identity.d.ts +3 -0
  83. package/dist/types/sdk/broker/index.d.ts +8 -0
  84. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  85. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  86. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  87. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  88. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  89. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  90. package/dist/types/sdk/broker/transport.d.ts +9 -0
  91. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  92. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  93. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  94. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  95. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  96. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  97. package/dist/types/sdk/bus/config.d.ts +274 -0
  98. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  99. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  100. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  101. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  102. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  103. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  104. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  105. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  107. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  108. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  109. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  110. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  111. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  112. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  113. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  114. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  115. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  118. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  119. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  121. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  122. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  123. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  124. package/dist/types/sdk/cli/index.d.ts +1 -0
  125. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  126. package/dist/types/sdk/client/client.d.ts +1 -0
  127. package/dist/types/sdk/client/discovery.d.ts +27 -0
  128. package/dist/types/sdk/client/index.d.ts +2 -0
  129. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  130. package/dist/types/sdk/host/control/index.d.ts +2 -0
  131. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  132. package/dist/types/sdk/host/events.d.ts +35 -0
  133. package/dist/types/sdk/host/host.d.ts +35 -0
  134. package/dist/types/sdk/host/index.d.ts +4 -0
  135. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  136. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  137. package/dist/types/sdk/host/query/index.d.ts +3 -0
  138. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  139. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  140. package/dist/types/sdk/host/types.d.ts +32 -0
  141. package/dist/types/sdk/index.d.ts +6 -0
  142. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  143. package/dist/types/sdk/mcp/index.d.ts +1 -0
  144. package/dist/types/sdk/mcp/server.d.ts +37 -0
  145. package/dist/types/sdk/models.d.ts +44 -0
  146. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  147. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  148. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  149. package/dist/types/sdk/startup-capability.d.ts +50 -0
  150. package/dist/types/session/agent-session.d.ts +114 -21
  151. package/dist/types/session/default-model-selection.d.ts +25 -0
  152. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  153. package/dist/types/session/session-manager.d.ts +58 -1
  154. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  155. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  156. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  157. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  158. package/dist/types/tools/browser/launch.d.ts +22 -0
  159. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  160. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  161. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  162. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  163. package/dist/types/tools/browser/registry.d.ts +19 -0
  164. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  165. package/dist/types/tools/index.d.ts +8 -8
  166. package/package.json +34 -13
  167. package/scripts/build-sdk-package-smoke.ts +94 -0
  168. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  169. package/scripts/compile-args.ts +4 -2
  170. package/scripts/g005-daemon-smoke.ts +4 -5
  171. package/scripts/g011-daemon-path-smoke.ts +5 -5
  172. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  173. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  174. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  175. package/scripts/manifest-schema.ts +124 -0
  176. package/scripts/run-test-manifest.ts +153 -0
  177. package/scripts/run-threat-model-check.ts +157 -0
  178. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  179. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  180. package/src/append-only-mode.ts +1 -1
  181. package/src/cli/args.ts +43 -12
  182. package/src/cli/auth-gateway-cli.ts +2 -2
  183. package/src/cli/config-cli.ts +2 -1
  184. package/src/cli/daemon-cli.ts +63 -14
  185. package/src/cli/list-models.ts +1 -1
  186. package/src/cli/notify-cli.ts +288 -286
  187. package/src/cli.ts +21 -2
  188. package/src/commands/daemon.ts +50 -6
  189. package/src/commands/harness.ts +93 -36
  190. package/src/commands/launch.ts +5 -2
  191. package/src/commands/mcp-serve.ts +19 -12
  192. package/src/commands/notify.ts +36 -3
  193. package/src/commands/sdk.ts +426 -0
  194. package/src/commit/agentic/agent.ts +1 -0
  195. package/src/config/atomic-yaml-patch.ts +423 -0
  196. package/src/config/model-profile-activation.ts +240 -89
  197. package/src/config/model-profiles.ts +37 -34
  198. package/src/config/model-registry.ts +51 -26
  199. package/src/config/model-resolver.ts +138 -51
  200. package/src/config/model-selector-value.ts +50 -0
  201. package/src/config/models-config-schema.ts +14 -21
  202. package/src/config/settings-schema.ts +128 -10
  203. package/src/config/settings.ts +1120 -158
  204. package/src/coordinator-mcp/model-preset.ts +74 -20
  205. package/src/coordinator-mcp/server.ts +1597 -3052
  206. package/src/daemon/builtin.ts +8 -5
  207. package/src/daemon/control-types.ts +1 -1
  208. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  209. package/src/discovery/mcp-json.ts +327 -20
  210. package/src/extensibility/custom-tools/types.ts +1 -1
  211. package/src/extensibility/extensions/compact-handler.ts +3 -3
  212. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  213. package/src/extensibility/extensions/loader.ts +69 -5
  214. package/src/extensibility/extensions/runner.ts +112 -4
  215. package/src/extensibility/extensions/types.ts +176 -17
  216. package/src/extensibility/hooks/types.ts +1 -1
  217. package/src/extensibility/slash-commands.ts +3 -3
  218. package/src/gjc-runtime/launch-tmux.ts +170 -86
  219. package/src/gjc-runtime/psmux-detect.ts +82 -4
  220. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  221. package/src/gjc-runtime/team-runtime.ts +54 -35
  222. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  223. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -2
  224. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  225. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  226. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  227. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  228. package/src/harness-control-plane/operate.ts +9 -9
  229. package/src/harness-control-plane/owner.ts +283 -39
  230. package/src/harness-control-plane/receipts.ts +0 -1
  231. package/src/harness-control-plane/sdk-transport.ts +395 -0
  232. package/src/harness-control-plane/session-transport.ts +94 -0
  233. package/src/harness-control-plane/types.ts +1 -1
  234. package/src/internal-urls/docs-index.generated.ts +36 -37
  235. package/src/lsp/client.ts +42 -6
  236. package/src/lsp/index.ts +2 -2
  237. package/src/main.ts +299 -204
  238. package/src/modes/DESIGN.md +258 -0
  239. package/src/modes/acp/acp-agent.ts +1228 -2612
  240. package/src/modes/acp/acp-client-bridge.ts +2 -20
  241. package/src/modes/acp/acp-event-mapper.ts +18 -2
  242. package/src/modes/acp/acp-mode.ts +8 -36
  243. package/src/modes/acp/permission-mode.ts +25 -0
  244. package/src/modes/acp/startup-options.ts +6 -0
  245. package/src/modes/components/agent-dashboard.ts +37 -17
  246. package/src/modes/components/custom-editor.ts +1 -0
  247. package/src/modes/components/gajae-pet-widget.ts +169 -20
  248. package/src/modes/components/model-selector.ts +93 -35
  249. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  250. package/src/modes/components/pet-capability.ts +115 -0
  251. package/src/modes/components/pet-selector.ts +4 -6
  252. package/src/modes/components/settings-selector.ts +86 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +1 -2
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +357 -12
  257. package/src/modes/controllers/input-controller.ts +43 -13
  258. package/src/modes/controllers/selector-controller.ts +671 -44
  259. package/src/modes/index.ts +0 -22
  260. package/src/modes/interactive-mode.ts +108 -24
  261. package/src/modes/runtime-init.ts +298 -6
  262. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  263. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  264. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  265. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  266. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  267. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  268. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  269. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  270. package/src/modes/types.ts +16 -1
  271. package/src/runtime-mcp/client.ts +94 -19
  272. package/src/runtime-mcp/config.ts +27 -15
  273. package/src/runtime-mcp/manager.ts +343 -105
  274. package/src/runtime-mcp/oauth-flow.ts +42 -12
  275. package/src/runtime-mcp/transports/http.ts +49 -19
  276. package/src/runtime-mcp/transports/stdio.ts +47 -28
  277. package/src/runtime-mcp/types.ts +10 -0
  278. package/src/sdk/acp/adapter.ts +418 -0
  279. package/src/sdk/acp/index.ts +2 -0
  280. package/src/sdk/broker/broker.ts +642 -0
  281. package/src/sdk/broker/discovery.ts +94 -0
  282. package/src/sdk/broker/ensure.ts +249 -0
  283. package/src/sdk/broker/identity.ts +42 -0
  284. package/src/sdk/broker/index.ts +8 -0
  285. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  286. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  287. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  288. package/src/sdk/broker/lifecycle.ts +2157 -0
  289. package/src/sdk/broker/process-incarnation.ts +159 -0
  290. package/src/sdk/broker/runtime.ts +164 -0
  291. package/src/sdk/broker/session-index.ts +318 -0
  292. package/src/sdk/broker/state-version.ts +23 -0
  293. package/src/sdk/broker/transport.ts +125 -0
  294. package/src/sdk/bus/chat-command-policy.ts +107 -0
  295. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  296. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  297. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  298. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  299. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  300. package/src/sdk/bus/config.ts +433 -0
  301. package/src/sdk/bus/conversation-store.ts +391 -0
  302. package/src/sdk/bus/discord-conversation.ts +85 -0
  303. package/src/sdk/bus/discord-daemon.ts +2275 -0
  304. package/src/sdk/bus/discord-live-provider.ts +521 -0
  305. package/src/sdk/bus/discord-provider.ts +56 -0
  306. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  307. package/src/sdk/bus/index.ts +3943 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  309. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  310. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  311. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  312. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  313. package/src/sdk/bus/natives-augment.d.ts +38 -0
  314. package/src/sdk/bus/notification-orchestration.ts +535 -0
  315. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  316. package/src/sdk/bus/session-control.ts +333 -0
  317. package/src/sdk/bus/slack-conversation.ts +74 -0
  318. package/src/sdk/bus/slack-daemon.ts +2144 -0
  319. package/src/sdk/bus/slack-live-provider.ts +380 -0
  320. package/src/sdk/bus/slack-provider.ts +76 -0
  321. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  322. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  323. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  324. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  325. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  326. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  327. package/src/sdk/bus/telegram-setup.ts +663 -0
  328. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  329. package/src/sdk/cli/index.ts +1 -0
  330. package/src/sdk/cli/session-cli.ts +275 -0
  331. package/src/sdk/client/client.ts +1 -0
  332. package/src/sdk/client/discovery.ts +108 -0
  333. package/src/sdk/client/index.ts +2 -0
  334. package/src/sdk/host/control/dispatch.ts +367 -0
  335. package/src/sdk/host/control/index.ts +10 -0
  336. package/src/sdk/host/control/operations.ts +63 -0
  337. package/src/sdk/host/events.ts +91 -0
  338. package/src/sdk/host/host.ts +296 -0
  339. package/src/sdk/host/index.ts +4 -0
  340. package/src/sdk/host/query/cursor.ts +189 -0
  341. package/src/sdk/host/query/handlers.ts +533 -0
  342. package/src/sdk/host/query/index.ts +3 -0
  343. package/src/sdk/host/query/revision-store.ts +1126 -0
  344. package/src/sdk/host/reverse-leases.ts +325 -0
  345. package/src/sdk/host/types.ts +29 -0
  346. package/src/sdk/index.ts +13 -0
  347. package/src/sdk/lifecycle-session.ts +39 -0
  348. package/src/sdk/mcp/index.ts +1 -0
  349. package/src/sdk/mcp/server.ts +332 -0
  350. package/src/sdk/models.ts +168 -0
  351. package/src/sdk/protocol/adapter-validation.ts +48 -0
  352. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  353. package/src/sdk/protocol/operation-registry.ts +312 -0
  354. package/src/{sdk.ts → sdk/session.ts} +339 -212
  355. package/src/sdk/startup-capability.ts +189 -0
  356. package/src/session/agent-session.ts +2470 -866
  357. package/src/session/default-model-selection.ts +93 -0
  358. package/src/session/fallback-chain-controller.ts +136 -0
  359. package/src/session/session-manager.ts +447 -13
  360. package/src/session/session-storage.ts +8 -1
  361. package/src/setup/credential-auto-import.ts +290 -35
  362. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  363. package/src/slash-commands/builtin-registry.ts +33 -30
  364. package/src/task/executor.ts +62 -13
  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/telegram-send.ts +2 -2
  384. package/vendor/insane-search/MANIFEST.json +2 -1
  385. package/vendor/insane-search/engine/bias_check.py +4 -1
  386. package/vendor/insane-search/engine/phase0.py +26 -1
  387. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  388. package/dist/types/modes/bridge/auth.d.ts +0 -12
  389. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  390. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  391. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  392. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  393. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  394. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  395. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  396. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  397. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  398. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  399. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  400. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  401. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  402. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  403. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  404. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  405. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  406. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  407. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  408. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  409. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  410. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  411. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  412. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  413. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  414. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  415. package/dist/types/notifications/config.d.ts +0 -132
  416. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  417. package/src/modes/bridge/auth.ts +0 -41
  418. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  419. package/src/modes/bridge/bridge-mode.ts +0 -675
  420. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  421. package/src/modes/bridge/event-stream.ts +0 -70
  422. package/src/modes/rpc/host-tools.ts +0 -1
  423. package/src/modes/rpc/host-uris.ts +0 -1
  424. package/src/modes/rpc/rpc-client.ts +0 -1166
  425. package/src/modes/rpc/rpc-mode.ts +0 -1029
  426. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  427. package/src/modes/rpc/rpc-types.ts +0 -637
  428. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  429. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  430. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  431. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  432. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  433. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  434. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  435. package/src/modes/shared/agent-wire/responses.ts +0 -17
  436. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  437. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  438. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  439. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  440. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  441. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  442. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  443. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  444. package/src/notifications/config.ts +0 -219
  445. package/src/notifications/index.ts +0 -1835
  446. package/src/notifications/telegram-daemon-cli.ts +0 -243
  447. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  448. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,9 +1,10 @@
1
+ import * as path from "node:path";
1
2
  import { ThinkingLevel } from "@gajae-code/agent-core";
2
3
  import { getOAuthProviders } from "@gajae-code/ai/utils/oauth";
3
4
  import type { OAuthProvider } from "@gajae-code/ai/utils/oauth/types";
4
5
  import type { Component, OverlayHandle } from "@gajae-code/tui";
5
6
  import { Input, isPetMode, Loader, Spacer, Text } from "@gajae-code/tui";
6
- import { getAgentDbPath, getProjectDir } from "@gajae-code/utils";
7
+ import { getAgentDbPath, getProjectDir, logger, VERSION } from "@gajae-code/utils";
7
8
  import {
8
9
  activateModelProfile,
9
10
  type MaterializeModelProfileForDeletionResult,
@@ -15,6 +16,7 @@ import {
15
16
  import { formatModelProfileDisplayLabel, recommendModelProfileForProvider } from "../../config/model-profiles";
16
17
  import { GJC_MODEL_ASSIGNMENT_TARGETS, type GjcModelAssignmentTargetId } from "../../config/model-registry";
17
18
  import { formatModelSelectorValue } from "../../config/model-resolver";
19
+ import { selectorHead } from "../../config/model-selector-value";
18
20
  import type { ModelProfileConfig } from "../../config/models-config-schema";
19
21
  import { type Settings, settings } from "../../config/settings";
20
22
  import { DebugSelectorComponent } from "../../debug";
@@ -40,10 +42,48 @@ import {
40
42
  theme,
41
43
  } from "../../modes/theme/theme";
42
44
  import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/types";
45
+ import { getNotificationConfig, maskToken } from "../../sdk/bus/config";
46
+ import {
47
+ clearTelegramActivationMarker,
48
+ createTelegramActivationMarker,
49
+ observedTelegramActivationMarker,
50
+ persistTelegramActivationMarker,
51
+ proposedTelegramIdentity,
52
+ reconcileCommittedTelegramConfiguration,
53
+ removeTelegramConfiguration,
54
+ saveTelegramInactive,
55
+ } from "../../sdk/bus/notification-orchestration";
56
+ import {
57
+ buildNotificationStatusReport,
58
+ checkNotificationHealth,
59
+ recoverNotifications,
60
+ sanitizeDiagnostic,
61
+ sendNotificationTest,
62
+ } from "../../sdk/bus/notification-service";
63
+ import type { NotificationSessionStatus } from "../../sdk/bus/session-control";
64
+ import {
65
+ ensureTelegramDaemonRunningDetailed,
66
+ readDaemonState,
67
+ unregisterNotificationRoot,
68
+ } from "../../sdk/bus/telegram-daemon";
69
+ import { TelegramDaemonController } from "../../sdk/bus/telegram-daemon-control";
70
+ import { runTelegramSetup, type TelegramSetupPreflight } from "../../sdk/bus/telegram-setup";
43
71
  import { type SessionInfo, SessionManager } from "../../session/session-manager";
44
72
  import { FileSessionStorage } from "../../session/session-storage";
45
73
  import {
74
+ CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING,
75
+ CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING,
76
+ CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING,
77
+ CREDENTIAL_AUTO_IMPORT_RETRY_WARNING,
46
78
  CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING,
79
+ CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING,
80
+ type CredentialAutoImportStateReadResult,
81
+ type CredentialAutoImportStateStore,
82
+ createCredentialAutoImportStateStore,
83
+ formatCredentialAutoImportCandidateLabel,
84
+ formatCredentialAutoImportPrompt,
85
+ isCredentialAutoImportStateResolvedForVersion,
86
+ logCredentialAutoImportFailures,
47
87
  runExternalCredentialAutoImport,
48
88
  } from "../../setup/credential-auto-import";
49
89
  import {
@@ -78,7 +118,12 @@ import type { PetMode } from "../components/gajae-pet-widget";
78
118
  import { HistorySearchComponent } from "../components/history-search";
79
119
  import { JobsOverlayComponent } from "../components/jobs-overlay";
80
120
  import { ModelSelectorComponent } from "../components/model-selector";
121
+ import type {
122
+ NotificationsEditorOperations,
123
+ PreparedTelegramConfiguration,
124
+ } from "../components/notifications-settings-editor";
81
125
  import { OAuthSelectorComponent } from "../components/oauth-selector";
126
+ import { isPetAvailable } from "../components/pet-capability";
82
127
  import { PetSelectorComponent } from "../components/pet-selector";
83
128
  import { PluginSelectorComponent } from "../components/plugin-selector";
84
129
  import {
@@ -141,8 +186,512 @@ function formatProviderOnboardingCommandGuide(): string {
141
186
  ].join("\n");
142
187
  }
143
188
 
189
+ export interface NotificationsEditorAdapterContext {
190
+ settings: Settings;
191
+ session: Pick<InteractiveModeContext["session"], "notificationSessionController">;
192
+ sessionManager: Pick<InteractiveModeContext["sessionManager"], "getCwd" | "getSessionId">;
193
+ notifyConfigChanged?: () => Promise<void> | void;
194
+ }
195
+
196
+ export interface NotificationsEditorOperationDependencies {
197
+ getNotificationConfig: typeof getNotificationConfig;
198
+ maskToken: typeof maskToken;
199
+ buildNotificationStatusReport: typeof buildNotificationStatusReport;
200
+ checkNotificationHealth: typeof checkNotificationHealth;
201
+ sendNotificationTest: typeof sendNotificationTest;
202
+ recoverNotifications: typeof recoverNotifications;
203
+ sanitizeDiagnostic: typeof sanitizeDiagnostic;
204
+ ensureTelegramDaemonRunningDetailed: typeof ensureTelegramDaemonRunningDetailed;
205
+ runTelegramSetup: typeof runTelegramSetup;
206
+ proposedTelegramIdentity: typeof proposedTelegramIdentity;
207
+ reconcileCommittedTelegramConfiguration: typeof reconcileCommittedTelegramConfiguration;
208
+ saveTelegramInactive: typeof saveTelegramInactive;
209
+ removeTelegramConfiguration: typeof removeTelegramConfiguration;
210
+ unregisterNotificationRoot: typeof unregisterNotificationRoot;
211
+ }
212
+
213
+ const notificationEditorOperationDependencies: NotificationsEditorOperationDependencies = {
214
+ getNotificationConfig,
215
+ maskToken,
216
+ buildNotificationStatusReport,
217
+ checkNotificationHealth,
218
+ sendNotificationTest,
219
+ recoverNotifications,
220
+ sanitizeDiagnostic,
221
+ ensureTelegramDaemonRunningDetailed,
222
+ runTelegramSetup,
223
+ proposedTelegramIdentity,
224
+ reconcileCommittedTelegramConfiguration,
225
+ saveTelegramInactive,
226
+ removeTelegramConfiguration,
227
+ unregisterNotificationRoot,
228
+ };
229
+
230
+ function unavailableNotificationSessionStatus(): NotificationSessionStatus {
231
+ return {
232
+ eligible: false,
233
+ locallyEnabled: true,
234
+ effectiveEnabled: false,
235
+ running: false,
236
+ environment: "off",
237
+ };
238
+ }
239
+
240
+ function unavailableNotificationSessionResult() {
241
+ return { outcome: "disabled" as const, status: unavailableNotificationSessionStatus() };
242
+ }
243
+
244
+ function notificationOperationError(
245
+ services: NotificationsEditorOperationDependencies,
246
+ error: unknown,
247
+ token?: string,
248
+ ): Error {
249
+ return new Error(
250
+ services.sanitizeDiagnostic(error instanceof Error ? error.message : "Notification operation failed.", token),
251
+ );
252
+ }
253
+
254
+ /**
255
+ * Concrete service adapter for the direct Notifications settings tab. Secrets remain in this closure's
256
+ * WeakMap and are never exposed through the editor's safe draft contract.
257
+ */
258
+ export function createNotificationsEditorOperations(
259
+ ctx: NotificationsEditorAdapterContext,
260
+ overrides: Partial<NotificationsEditorOperationDependencies> = {},
261
+ ): NotificationsEditorOperations {
262
+ const services = { ...notificationEditorOperationDependencies, ...overrides };
263
+ const drafts = new WeakMap<PreparedTelegramConfiguration, string>();
264
+ const sessionContext = () => ({ sessionManager: ctx.sessionManager });
265
+ const notifyAfterDurableCommit = async (): Promise<void> => {
266
+ await ctx.notifyConfigChanged?.();
267
+ };
268
+ const reconnect = async () =>
269
+ await services.ensureTelegramDaemonRunningDetailed({
270
+ settings: ctx.settings,
271
+ cwd: ctx.sessionManager.getCwd(),
272
+ sessionId: ctx.sessionManager.getSessionId(),
273
+ });
274
+ const telegramSetupPreflight = async (): Promise<TelegramSetupPreflight> => {
275
+ const storedChatId = services.getNotificationConfig(ctx.settings).chatId;
276
+ try {
277
+ const state = await readDaemonState(ctx.settings);
278
+ const validPid = Number.isSafeInteger(state?.pid) && (state?.pid ?? 0) > 0;
279
+ if (!state || !validPid) return { storedChatId };
280
+ let live = false;
281
+ try {
282
+ process.kill(state.pid, 0);
283
+ live = true;
284
+ } catch (error) {
285
+ live = (error as NodeJS.ErrnoException).code === "EPERM";
286
+ }
287
+ return live
288
+ ? {
289
+ storedChatId,
290
+ daemon: {
291
+ live,
292
+ tokenFingerprint: typeof state.tokenFingerprint === "string" ? state.tokenFingerprint : undefined,
293
+ chatId: typeof state.chatId === "string" && state.chatId.trim() ? state.chatId.trim() : undefined,
294
+ },
295
+ }
296
+ : { storedChatId };
297
+ } catch {
298
+ return { storedChatId };
299
+ }
300
+ };
301
+
302
+ return {
303
+ loadState: async () => {
304
+ const config = services.getNotificationConfig(ctx.settings);
305
+ return {
306
+ status: services.buildNotificationStatusReport(ctx.settings),
307
+ session:
308
+ ctx.session.notificationSessionController?.query(sessionContext()) ??
309
+ unavailableNotificationSessionStatus(),
310
+ preferences: {
311
+ redact: config.redact,
312
+ verbosity: config.verbosity,
313
+ sessionScope: config.sessionScope,
314
+ richEnabled: config.rich.enabled,
315
+ richDraftEnabled: config.richDraft.enabled,
316
+ },
317
+ };
318
+ },
319
+
320
+ refreshHealth: async ({ probe, signal }) => {
321
+ if (signal?.aborted) throw new Error("Notification health refresh cancelled.");
322
+ try {
323
+ const input: Parameters<typeof checkNotificationHealth>[0] & { signal?: AbortSignal } = {
324
+ settings: ctx.settings,
325
+ stateRoot: path.join(ctx.sessionManager.getCwd(), ".gjc", "state"),
326
+ probe,
327
+ signal,
328
+ };
329
+ const report = await services.checkNotificationHealth(input);
330
+ if (signal?.aborted) throw new Error("Notification health refresh cancelled.");
331
+ const token = services.getNotificationConfig(ctx.settings).botToken;
332
+ return {
333
+ ...report,
334
+ checks: report.checks.map(check => ({
335
+ ...check,
336
+ detail: services.sanitizeDiagnostic(check.detail, token),
337
+ })),
338
+ reachability: {
339
+ ...report.reachability,
340
+ detail: services.sanitizeDiagnostic(report.reachability.detail, token),
341
+ },
342
+ };
343
+ } catch (error) {
344
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
345
+ }
346
+ },
347
+
348
+ sendTest: async () => {
349
+ try {
350
+ const result = await services.sendNotificationTest({ settings: ctx.settings });
351
+ return {
352
+ ...result,
353
+ detail: services.sanitizeDiagnostic(
354
+ result.detail,
355
+ services.getNotificationConfig(ctx.settings).botToken,
356
+ ),
357
+ };
358
+ } catch (error) {
359
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
360
+ }
361
+ },
362
+
363
+ recover: async () => {
364
+ try {
365
+ const result = await services.recoverNotifications({
366
+ settings: ctx.settings,
367
+ stateRoot: path.join(ctx.sessionManager.getCwd(), ".gjc", "state"),
368
+ });
369
+ return {
370
+ ...result,
371
+ daemon: {
372
+ ...result.daemon,
373
+ detail: services.sanitizeDiagnostic(
374
+ result.daemon.detail,
375
+ services.getNotificationConfig(ctx.settings).botToken,
376
+ ),
377
+ },
378
+ };
379
+ } catch (error) {
380
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
381
+ }
382
+ },
383
+
384
+ reconnect: async () => {
385
+ try {
386
+ const result = await reconnect();
387
+ const controller = ctx.session.notificationSessionController;
388
+ if (result === "blocked_identity") {
389
+ await controller?.enterBlockedRuntime(sessionContext());
390
+ } else if (result === "spawned" || result === "reloaded" || result === "attached") {
391
+ await controller?.clearBlockedRuntime(sessionContext());
392
+ await controller?.reconcileCurrentSession(sessionContext());
393
+ }
394
+ return result;
395
+ } catch (error) {
396
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
397
+ }
398
+ },
399
+
400
+ preflightProposedIdentity: async (input, signal) => {
401
+ const token = input.token.consume();
402
+ const unknownIdentity = { status: "unknown" as const };
403
+ if (!token.trim()) {
404
+ return {
405
+ status: "error",
406
+ identity: unknownIdentity,
407
+ message: "Telegram bot token is required.",
408
+ };
409
+ }
410
+ try {
411
+ const setup = await services.runTelegramSetup({
412
+ token,
413
+ chatId: input.chatId,
414
+ preflight: await telegramSetupPreflight(),
415
+ revalidatePreflight: async () => await telegramSetupPreflight(),
416
+ interactive: false,
417
+ signal,
418
+ deps: { fetchImpl: globalThis.fetch },
419
+ });
420
+ if (!setup.ok) {
421
+ return {
422
+ status: setup.status === "aborted" ? "aborted" : setup.status === "cancelled" ? "cancelled" : "error",
423
+ identity: unknownIdentity,
424
+ message: services.sanitizeDiagnostic(setup.detail, token),
425
+ };
426
+ }
427
+ if (signal.aborted) {
428
+ return {
429
+ status: "aborted",
430
+ identity: unknownIdentity,
431
+ message: "Telegram setup cancelled.",
432
+ };
433
+ }
434
+ const identity = await services.proposedTelegramIdentity({
435
+ settings: ctx.settings,
436
+ botToken: token,
437
+ chatId: setup.chatId,
438
+ chatDisplay: setup.chatId,
439
+ });
440
+ if (signal.aborted) {
441
+ return {
442
+ status: "aborted",
443
+ identity,
444
+ message: "Telegram setup cancelled.",
445
+ };
446
+ }
447
+ const draft: PreparedTelegramConfiguration = {
448
+ chatId: setup.chatId,
449
+ tokenMask: services.maskToken(token),
450
+ tokenFingerprint: setup.tokenFingerprint,
451
+ richEnabled: input.richEnabled,
452
+ richDraftEnabled: input.richDraftEnabled,
453
+ };
454
+ drafts.set(draft, token);
455
+ const pairingMessage =
456
+ setup.pairingSource === "discovered"
457
+ ? "Telegram private chat discovered and validated."
458
+ : setup.pairingSource === "reused"
459
+ ? "Stored Telegram private chat validated without polling."
460
+ : "Supplied Telegram private chat validated.";
461
+ return {
462
+ status: "ready",
463
+ identity,
464
+ draft,
465
+ pairingSource: setup.pairingSource,
466
+ message:
467
+ identity.status === "foreign" || identity.status === "unknown"
468
+ ? `${pairingMessage} Activation is blocked by the current daemon identity.`
469
+ : pairingMessage,
470
+ };
471
+ } catch (error) {
472
+ return {
473
+ status: signal.aborted ? "aborted" : "error",
474
+ identity: unknownIdentity,
475
+ message: signal.aborted
476
+ ? "Telegram setup cancelled."
477
+ : services.sanitizeDiagnostic(
478
+ error instanceof Error ? error.message : "Telegram setup failed.",
479
+ token,
480
+ ),
481
+ };
482
+ }
483
+ },
484
+
485
+ commitConfigure: async draft => {
486
+ const token = drafts.get(draft);
487
+ if (!token) throw new Error("The Telegram setup draft expired. Re-enter the masked bot token.");
488
+ try {
489
+ const inactiveMarkerToClear = observedTelegramActivationMarker(ctx.settings, token, draft.chatId);
490
+ const receipt = await ctx.settings.commitAtomicBatch([
491
+ { path: "notifications.enabled", op: "set", value: true },
492
+ { path: "notifications.telegram.botToken", op: "set", value: token },
493
+ { path: "notifications.telegram.chatId", op: "set", value: draft.chatId },
494
+ { path: "notifications.telegram.rich.enabled", op: "set", value: draft.richEnabled },
495
+ { path: "notifications.telegram.richDraft.enabled", op: "set", value: draft.richDraftEnabled },
496
+ ]);
497
+ drafts.delete(draft);
498
+ const activationMarker = createTelegramActivationMarker({
499
+ botToken: token,
500
+ chatId: draft.chatId,
501
+ state: "blocked",
502
+ reason: "identity_mismatch",
503
+ });
504
+ const controller = ctx.session.notificationSessionController;
505
+ const activation = await services.reconcileCommittedTelegramConfiguration({
506
+ receipt,
507
+ inactiveMarkerToClear,
508
+ activation: {
509
+ controller: controller
510
+ ? {
511
+ enterBlockedRuntime: async () => await controller.enterBlockedRuntime(sessionContext()),
512
+ clearBlockedRuntime: async () => await controller.clearBlockedRuntime(sessionContext()),
513
+ reconcileCurrentSession: async () =>
514
+ await controller.reconcileCurrentSession(sessionContext()),
515
+ }
516
+ : {
517
+ enterBlockedRuntime: async () => undefined,
518
+ clearBlockedRuntime: async () => undefined,
519
+ reconcileCurrentSession: async () => undefined,
520
+ },
521
+ reconnect,
522
+ persistInactive: async marker => await persistTelegramActivationMarker(ctx.settings, marker),
523
+ clearInactive: async marker => await clearTelegramActivationMarker(ctx.settings, marker),
524
+ marker: activationMarker,
525
+ },
526
+ });
527
+ await notifyAfterDurableCommit();
528
+ if (activation.status === "blocked_identity") {
529
+ return {
530
+ status: "blocked_identity" as const,
531
+ receipt,
532
+ message: services.sanitizeDiagnostic(activation.message, token),
533
+ restore: async () => {
534
+ const restored = await activation.restore();
535
+ if (restored.status === "restored" || restored.status === "still_blocked") {
536
+ await notifyAfterDurableCommit();
537
+ }
538
+ return restored;
539
+ },
540
+ retainCommitted: () => activation.retainCommitted(),
541
+ };
542
+ }
543
+ return {
544
+ status: "saved" as const,
545
+ receipt,
546
+ message: services.sanitizeDiagnostic("Telegram configuration saved and reconciled.", token),
547
+ };
548
+ } catch (error) {
549
+ throw notificationOperationError(services, error, token);
550
+ }
551
+ },
552
+
553
+ saveInactive: async draft => {
554
+ const token = drafts.get(draft);
555
+ if (!token) throw new Error("The Telegram setup draft expired. Re-enter the masked bot token.");
556
+ try {
557
+ const result = await services.saveTelegramInactive({
558
+ settings: ctx.settings,
559
+ botToken: token,
560
+ chatId: draft.chatId,
561
+ });
562
+ drafts.delete(draft);
563
+ await notifyAfterDurableCommit();
564
+ return {
565
+ status: "saved_inactive" as const,
566
+ receipt: result.receipt,
567
+ message: "Telegram configuration saved inactive; no runtime activation was requested.",
568
+ };
569
+ } catch (error) {
570
+ throw notificationOperationError(services, error, token);
571
+ }
572
+ },
573
+
574
+ discardConfigureDraft: draft => {
575
+ drafts.delete(draft);
576
+ },
577
+
578
+ enableGlobally: async () => {
579
+ try {
580
+ const receipt = await ctx.settings.commitAtomicBatch([
581
+ { path: "notifications.enabled", op: "set", value: true },
582
+ ]);
583
+ await notifyAfterDurableCommit();
584
+ return { receipt, message: "Global notifications enabled using stored configuration." };
585
+ } catch (error) {
586
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
587
+ }
588
+ },
589
+
590
+ disableGlobally: async () => {
591
+ try {
592
+ const receipt = await ctx.settings.commitAtomicBatch([
593
+ { path: "notifications.enabled", op: "set", value: false },
594
+ ]);
595
+ await notifyAfterDurableCommit();
596
+ return { receipt, message: "Global notifications disabled." };
597
+ } catch (error) {
598
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
599
+ }
600
+ },
601
+
602
+ removeTelegram: async () => {
603
+ const controller = ctx.session.notificationSessionController;
604
+ let runtimePrepared = false;
605
+ try {
606
+ const result = await services.removeTelegramConfiguration({
607
+ settings: ctx.settings,
608
+ removal: {
609
+ stopAndUnregister: async () => {
610
+ if (controller) await controller.enterBlockedRuntime(sessionContext());
611
+ runtimePrepared = true;
612
+ const unregistered = await services.unregisterNotificationRoot({
613
+ settings: ctx.settings,
614
+ cwd: ctx.sessionManager.getCwd(),
615
+ sessionId: ctx.sessionManager.getSessionId(),
616
+ });
617
+ if (unregistered.remainingRoots === 0) {
618
+ const stopped = await new TelegramDaemonController(ctx.settings).stop();
619
+ if (!stopped.ok) throw new Error(stopped.message);
620
+ }
621
+ },
622
+ },
623
+ });
624
+ if (runtimePrepared && controller) {
625
+ await controller.clearBlockedRuntime(sessionContext());
626
+ await controller.reconcileCurrentSession(sessionContext());
627
+ }
628
+ await notifyAfterDurableCommit();
629
+ return {
630
+ receipt: result.receipt,
631
+ globallyDisabled: result.globallyDisabled,
632
+ message: result.globallyDisabled
633
+ ? "Telegram configuration removed and global notifications disabled."
634
+ : "Telegram configuration removed; Discord or Slack configuration was preserved.",
635
+ };
636
+ } catch (error) {
637
+ if (runtimePrepared) {
638
+ const restored = await reconnect();
639
+ if (restored !== "blocked_identity" && controller) {
640
+ await controller.clearBlockedRuntime(sessionContext());
641
+ await controller.reconcileCurrentSession(sessionContext());
642
+ }
643
+ }
644
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
645
+ }
646
+ },
647
+
648
+ setSessionLocal: async enabled => {
649
+ const controller = ctx.session.notificationSessionController;
650
+ if (!controller) return unavailableNotificationSessionResult();
651
+ try {
652
+ return await controller.setLocalEnabled(sessionContext(), enabled);
653
+ } catch (error) {
654
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
655
+ }
656
+ },
657
+
658
+ commitPreferences: async preferences => {
659
+ try {
660
+ const receipt = await ctx.settings.commitAtomicBatch([
661
+ { path: "notifications.redact", op: "set", value: preferences.redact },
662
+ { path: "notifications.verbosity", op: "set", value: preferences.verbosity },
663
+ { path: "notifications.sessionScope", op: "set", value: preferences.sessionScope },
664
+ { path: "notifications.telegram.rich.enabled", op: "set", value: preferences.richEnabled },
665
+ { path: "notifications.telegram.richDraft.enabled", op: "set", value: preferences.richDraftEnabled },
666
+ ]);
667
+ await notifyAfterDurableCommit();
668
+ return { receipt, message: "Notification preferences saved atomically." };
669
+ } catch (error) {
670
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
671
+ }
672
+ },
673
+
674
+ reconcileCurrentSession: async () => {
675
+ const controller = ctx.session.notificationSessionController;
676
+ if (!controller) return unavailableNotificationSessionResult();
677
+ try {
678
+ return await controller.reconcileCurrentSession(sessionContext());
679
+ } catch (error) {
680
+ throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
681
+ }
682
+ },
683
+ };
684
+ }
685
+
144
686
  export class SelectorController {
145
- constructor(private ctx: InteractiveModeContext) {}
687
+ #credentialAutoImportStateStore?: CredentialAutoImportStateStore;
688
+
689
+ constructor(
690
+ private ctx: InteractiveModeContext,
691
+ credentialAutoImportStateStore?: CredentialAutoImportStateStore,
692
+ ) {
693
+ this.#credentialAutoImportStateStore = credentialAutoImportStateStore;
694
+ }
146
695
 
147
696
  async #refreshOAuthProviderAuthState(): Promise<void> {
148
697
  const oauthProviders = getOAuthProviders();
@@ -485,6 +1034,8 @@ export class SelectorController {
485
1034
  showSettingsSelector(): void {
486
1035
  getAvailableThemes().then(availableThemes => {
487
1036
  this.showSelector(done => {
1037
+ const notificationsOperations = createNotificationsEditorOperations(this.ctx);
1038
+
488
1039
  const selector = new SettingsSelectorComponent(
489
1040
  {
490
1041
  availableThinkingLevels: [...this.ctx.session.getAvailableThinkingLevels()],
@@ -540,6 +1091,7 @@ export class SelectorController {
540
1091
  this.ctx.ui.requestRender();
541
1092
  },
542
1093
  },
1094
+ notificationsOperations,
543
1095
  );
544
1096
  return { component: selector, focus: selector };
545
1097
  });
@@ -607,6 +1159,7 @@ export class SelectorController {
607
1159
  mode => {
608
1160
  this.ctx.previewPetMode(mode);
609
1161
  },
1162
+ isPetAvailable(),
610
1163
  );
611
1164
  return { component: selector, focus: selector.getSelectList() };
612
1165
  });
@@ -660,7 +1213,7 @@ export class SelectorController {
660
1213
  const dashboard = await AgentDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows, {
661
1214
  modelRegistry: this.ctx.session.modelRegistry,
662
1215
  activeModelPattern,
663
- defaultModelPattern,
1216
+ defaultModelPattern: selectorHead(defaultModelPattern),
664
1217
  });
665
1218
  this.showSelector(done => {
666
1219
  dashboard.onClose = () => {
@@ -942,7 +1495,13 @@ export class SelectorController {
942
1495
  const { model, role, thinkingLevel, selector: selectedSelector } = selection;
943
1496
  if (role === null) {
944
1497
  // Temporary: update agent state but don't persist to settings
945
- await this.ctx.session.setModelTemporary(model, thinkingLevel);
1498
+ await this.ctx.session.setModelTemporary(model, thinkingLevel, {
1499
+ cause: "temporary-operation",
1500
+ reason: "other",
1501
+ });
1502
+ this.ctx.session.setDefaultFallbackRuntimeModel(
1503
+ selectedSelector ?? formatModelSelectorValue(`${model.provider}/${model.id}`, thinkingLevel),
1504
+ );
946
1505
  this.ctx.statusLine.invalidate();
947
1506
  this.ctx.updateEditorBorderColor();
948
1507
  this.ctx.showStatus(`Temporary model: ${selectedSelector ?? model.id}`);
@@ -974,6 +1533,7 @@ export class SelectorController {
974
1533
  await this.ctx.session.setModel(model, "default", {
975
1534
  selector: defaultSelector,
976
1535
  thinkingLevel,
1536
+ cause: "user-selection",
977
1537
  });
978
1538
  if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
979
1539
  this.ctx.session.setThinkingLevel(thinkingLevel);
@@ -985,21 +1545,14 @@ export class SelectorController {
985
1545
  assignments,
986
1546
  });
987
1547
  if (!materializedProfile) {
988
- const overrides = this.ctx.settings.get("task.agentModelOverrides");
989
- const nextOverrides = { ...overrides };
990
- let writesOverrides = false;
991
1548
  for (const targetRole of targetRoles) {
992
1549
  const target = GJC_MODEL_ASSIGNMENT_TARGETS[targetRole];
993
1550
  if (target.settingsPath === "modelRoles") {
994
1551
  this.ctx.settings.setModelRole(targetRole, value);
995
1552
  } else {
996
- nextOverrides[targetRole] = value;
997
- writesOverrides = true;
1553
+ this.ctx.settings.setAgentModelOverride(targetRole, value);
998
1554
  }
999
1555
  }
1000
- if (writesOverrides) {
1001
- this.ctx.settings.set("task.agentModelOverrides", nextOverrides);
1002
- }
1003
1556
  }
1004
1557
  modelSelector.refreshRoleAssignments({
1005
1558
  currentModel: this.ctx.session.model,
@@ -1026,6 +1579,7 @@ export class SelectorController {
1026
1579
  await this.ctx.session.setModel(model, role, {
1027
1580
  selector: selectedSelector,
1028
1581
  thinkingLevel,
1582
+ cause: "user-selection",
1029
1583
  });
1030
1584
  const value = formatModelSelectorValue(
1031
1585
  selectedSelector ?? `${model.provider}/${model.id}`,
@@ -1069,10 +1623,7 @@ export class SelectorController {
1069
1623
  if (target.settingsPath === "modelRoles") {
1070
1624
  this.ctx.settings.setModelRole(role, value);
1071
1625
  } else {
1072
- this.ctx.settings.set("task.agentModelOverrides", {
1073
- ...this.ctx.settings.get("task.agentModelOverrides"),
1074
- [role]: value,
1075
- });
1626
+ this.ctx.settings.setAgentModelOverride(role, value);
1076
1627
  }
1077
1628
  }
1078
1629
  modelSelector.refreshRoleAssignments({
@@ -1654,34 +2205,110 @@ export class SelectorController {
1654
2205
  options?.allowExternalCredentialDiscovery === true &&
1655
2206
  options.trigger === "bare-login"
1656
2207
  ) {
1657
- const preview = await runExternalCredentialAutoImport({
1658
- authStorage: {
1659
- importCredentialIfAbsent: async () => ({
1660
- inserted: false,
1661
- reason: "skipped-existing",
1662
- provider: "",
1663
- entries: [],
1664
- }),
1665
- },
1666
- trigger: "bare-login",
1667
- discover: options.externalCredentialDiscover,
1668
- });
1669
- const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
1670
- const candidates = filterAutoImportOAuthCredentials(result.importable);
1671
- if (candidates.length > 0) {
1672
- const confirmed = await this.ctx.showHookConfirm(
1673
- `Import ${candidates.length} external credential(s)?`,
1674
- `${formatDiscoverySummary({ ...result, importable: candidates }).join("\n")}\n\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`,
1675
- );
1676
- if (confirmed) {
1677
- const summary = await runExternalCredentialAutoImport({
1678
- authStorage: this.ctx.session.modelRegistry.authStorage,
1679
- trigger: "bare-login",
1680
- discover: options.externalCredentialDiscover,
1681
- });
1682
- externalCredentialCandidates = summary.imported;
1683
- if (externalCredentialCandidates.length > 0) {
1684
- await this.ctx.session.modelRegistry.refresh("offline");
2208
+ const stateStore =
2209
+ this.#credentialAutoImportStateStore ??
2210
+ createCredentialAutoImportStateStore(this.ctx.settings.getAgentDir());
2211
+ let stateRead: CredentialAutoImportStateReadResult | undefined;
2212
+ try {
2213
+ stateRead = await stateStore.read();
2214
+ } catch {
2215
+ logger.warn("Credential auto-import state read failed", { classification: "state-read-failed" });
2216
+ stateRead = { state: {}, problems: [], unreadable: true };
2217
+ }
2218
+ if (stateRead?.unreadable === true) {
2219
+ logger.warn("Credential auto-import state unavailable", { classification: "state-unreadable" });
2220
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING);
2221
+ } else if (stateRead && !isCredentialAutoImportStateResolvedForVersion(stateRead.state, VERSION)) {
2222
+ const preview = await runExternalCredentialAutoImport({
2223
+ authStorage: {
2224
+ importCredentialIfAbsent: async () => ({
2225
+ inserted: false,
2226
+ reason: "skipped-existing",
2227
+ provider: "",
2228
+ entries: [],
2229
+ }),
2230
+ },
2231
+ trigger: "bare-login",
2232
+ discover: options.externalCredentialDiscover,
2233
+ });
2234
+ if (!preview.discovered) {
2235
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
2236
+ } else {
2237
+ const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
2238
+ const candidates = filterAutoImportOAuthCredentials(result.importable);
2239
+ const previewSourceFailures = preview.failures.filter(failure => failure.credential === undefined);
2240
+ if (candidates.length === 0 && previewSourceFailures.length > 0) {
2241
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
2242
+ } else if (candidates.length > 0) {
2243
+ const confirmed = await this.ctx.showHookConfirm(
2244
+ `Import ${candidates.length} external credential(s)?`,
2245
+ `${formatCredentialAutoImportPrompt(candidates)}\n\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`,
2246
+ );
2247
+ if (!confirmed) {
2248
+ let persisted = false;
2249
+ try {
2250
+ persisted = await stateStore.write({ initialImportResolution: "declined" });
2251
+ } catch {
2252
+ logger.warn("Credential auto-import state persistence failed", {
2253
+ classification: "state-write-failed",
2254
+ });
2255
+ }
2256
+ if (!persisted) this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
2257
+ } else {
2258
+ const summary = await runExternalCredentialAutoImport({
2259
+ authStorage: this.ctx.session.modelRegistry.authStorage,
2260
+ trigger: "bare-login",
2261
+ discover: options.externalCredentialDiscover,
2262
+ });
2263
+ if (!summary.discovered) {
2264
+ logCredentialAutoImportFailures("bare-login", summary.failures);
2265
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
2266
+ } else {
2267
+ const secondResult = summary.discovery ?? { importable: [], skipped: [], environment: [] };
2268
+ const secondCandidates = filterAutoImportOAuthCredentials(secondResult.importable);
2269
+ const secondSourceFailures = summary.failures.filter(
2270
+ failure => failure.credential === undefined,
2271
+ );
2272
+ const handledCandidates = summary.imported.length + summary.skipped.length > 0;
2273
+ if (handledCandidates || (secondCandidates.length === 0 && secondSourceFailures.length === 0)) {
2274
+ let persisted = false;
2275
+ try {
2276
+ persisted = await stateStore.write({ initialImportResolution: "accepted" });
2277
+ } catch {
2278
+ logger.warn("Credential auto-import state persistence failed", {
2279
+ classification: "state-write-failed",
2280
+ });
2281
+ }
2282
+ if (!persisted) this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
2283
+ externalCredentialCandidates = summary.imported.map(credential => ({
2284
+ ...credential,
2285
+ source: formatCredentialAutoImportCandidateLabel(credential),
2286
+ }));
2287
+ if (!handledCandidates) {
2288
+ this.ctx.showStatus("External credentials were no longer available to import.");
2289
+ }
2290
+ if (summary.imported.length > 0) {
2291
+ try {
2292
+ await this.ctx.session.modelRegistry.refresh("offline");
2293
+ } catch {
2294
+ logger.warn("Credential auto-import refresh failed", {
2295
+ classification: "refresh-failed",
2296
+ });
2297
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING);
2298
+ }
2299
+ }
2300
+ if (handledCandidates && summary.failures.length > 0) {
2301
+ logCredentialAutoImportFailures("bare-login", summary.failures);
2302
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
2303
+ }
2304
+ } else if (secondCandidates.length > 0 && summary.failures.length > 0) {
2305
+ logCredentialAutoImportFailures("bare-login", summary.failures);
2306
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
2307
+ } else {
2308
+ this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
2309
+ }
2310
+ }
2311
+ }
1685
2312
  }
1686
2313
  }
1687
2314
  }