@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,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,6 +118,10 @@ 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";
82
126
  import { isPetAvailable } from "../components/pet-capability";
83
127
  import { PetSelectorComponent } from "../components/pet-selector";
@@ -142,8 +186,512 @@ function formatProviderOnboardingCommandGuide(): string {
142
186
  ].join("\n");
143
187
  }
144
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
+
145
686
  export class SelectorController {
146
- constructor(private ctx: InteractiveModeContext) {}
687
+ #credentialAutoImportStateStore?: CredentialAutoImportStateStore;
688
+
689
+ constructor(
690
+ private ctx: InteractiveModeContext,
691
+ credentialAutoImportStateStore?: CredentialAutoImportStateStore,
692
+ ) {
693
+ this.#credentialAutoImportStateStore = credentialAutoImportStateStore;
694
+ }
147
695
 
148
696
  async #refreshOAuthProviderAuthState(): Promise<void> {
149
697
  const oauthProviders = getOAuthProviders();
@@ -486,6 +1034,8 @@ export class SelectorController {
486
1034
  showSettingsSelector(): void {
487
1035
  getAvailableThemes().then(availableThemes => {
488
1036
  this.showSelector(done => {
1037
+ const notificationsOperations = createNotificationsEditorOperations(this.ctx);
1038
+
489
1039
  const selector = new SettingsSelectorComponent(
490
1040
  {
491
1041
  availableThinkingLevels: [...this.ctx.session.getAvailableThinkingLevels()],
@@ -493,7 +1043,6 @@ export class SelectorController {
493
1043
  availableThemes,
494
1044
  availableModelProfiles: [...this.ctx.session.modelRegistry.getModelProfiles().keys()],
495
1045
  cwd: getProjectDir(),
496
- petAvailable: isPetAvailable(),
497
1046
  },
498
1047
  {
499
1048
  onChange: (id, value) => this.handleSettingChange(id, value),
@@ -516,7 +1065,6 @@ export class SelectorController {
516
1065
  onPetPreview: mode => {
517
1066
  this.ctx.previewPetMode(mode as PetMode);
518
1067
  },
519
- onPetCommit: mode => this.ctx.commitPetPreviewMode(mode as PetMode),
520
1068
  onStatusLinePreview: previewSettings => {
521
1069
  // Update status line with preview settings
522
1070
  this.ctx.statusLine.updateSettings({
@@ -543,6 +1091,7 @@ export class SelectorController {
543
1091
  this.ctx.ui.requestRender();
544
1092
  },
545
1093
  },
1094
+ notificationsOperations,
546
1095
  );
547
1096
  return { component: selector, focus: selector };
548
1097
  });
@@ -594,7 +1143,6 @@ export class SelectorController {
594
1143
  showPetSelector(): void {
595
1144
  const stored = settings.get("pet.mode");
596
1145
  const initial: PetMode = isPetMode(stored) ? stored : "off";
597
- const available = isPetAvailable();
598
1146
  this.showSelector(done => {
599
1147
  // Live-preview via previewMode (no editor re-mount, so the overlay stays);
600
1148
  // Enter commits + persists, Esc restores the initial skin.
@@ -611,7 +1159,7 @@ export class SelectorController {
611
1159
  mode => {
612
1160
  this.ctx.previewPetMode(mode);
613
1161
  },
614
- available,
1162
+ isPetAvailable(),
615
1163
  );
616
1164
  return { component: selector, focus: selector.getSelectList() };
617
1165
  });
@@ -665,7 +1213,7 @@ export class SelectorController {
665
1213
  const dashboard = await AgentDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows, {
666
1214
  modelRegistry: this.ctx.session.modelRegistry,
667
1215
  activeModelPattern,
668
- defaultModelPattern,
1216
+ defaultModelPattern: selectorHead(defaultModelPattern),
669
1217
  });
670
1218
  this.showSelector(done => {
671
1219
  dashboard.onClose = () => {
@@ -767,6 +1315,12 @@ export class SelectorController {
767
1315
  });
768
1316
  break;
769
1317
  }
1318
+ case "pet.mode":
1319
+ // The settings submenu already persisted the value; apply it to the live
1320
+ // widget via previewMode (the settings overlay is still open, so a full
1321
+ // re-mount would tear it down — restoreComposer re-mounts on close).
1322
+ this.ctx.previewPetMode(value as PetMode);
1323
+ break;
770
1324
  case "symbolPreset": {
771
1325
  setSymbolPreset(value as "unicode" | "nerd" | "ascii").then(() => {
772
1326
  this.ctx.statusLine.invalidate();
@@ -941,7 +1495,13 @@ export class SelectorController {
941
1495
  const { model, role, thinkingLevel, selector: selectedSelector } = selection;
942
1496
  if (role === null) {
943
1497
  // Temporary: update agent state but don't persist to settings
944
- 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
+ );
945
1505
  this.ctx.statusLine.invalidate();
946
1506
  this.ctx.updateEditorBorderColor();
947
1507
  this.ctx.showStatus(`Temporary model: ${selectedSelector ?? model.id}`);
@@ -973,6 +1533,7 @@ export class SelectorController {
973
1533
  await this.ctx.session.setModel(model, "default", {
974
1534
  selector: defaultSelector,
975
1535
  thinkingLevel,
1536
+ cause: "user-selection",
976
1537
  });
977
1538
  if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
978
1539
  this.ctx.session.setThinkingLevel(thinkingLevel);
@@ -1018,6 +1579,7 @@ export class SelectorController {
1018
1579
  await this.ctx.session.setModel(model, role, {
1019
1580
  selector: selectedSelector,
1020
1581
  thinkingLevel,
1582
+ cause: "user-selection",
1021
1583
  });
1022
1584
  const value = formatModelSelectorValue(
1023
1585
  selectedSelector ?? `${model.provider}/${model.id}`,
@@ -1643,34 +2205,110 @@ export class SelectorController {
1643
2205
  options?.allowExternalCredentialDiscovery === true &&
1644
2206
  options.trigger === "bare-login"
1645
2207
  ) {
1646
- const preview = await runExternalCredentialAutoImport({
1647
- authStorage: {
1648
- importCredentialIfAbsent: async () => ({
1649
- inserted: false,
1650
- reason: "skipped-existing",
1651
- provider: "",
1652
- entries: [],
1653
- }),
1654
- },
1655
- trigger: "bare-login",
1656
- discover: options.externalCredentialDiscover,
1657
- });
1658
- const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
1659
- const candidates = filterAutoImportOAuthCredentials(result.importable);
1660
- if (candidates.length > 0) {
1661
- const confirmed = await this.ctx.showHookConfirm(
1662
- `Import ${candidates.length} external credential(s)?`,
1663
- `${formatDiscoverySummary({ ...result, importable: candidates }).join("\n")}\n\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`,
1664
- );
1665
- if (confirmed) {
1666
- const summary = await runExternalCredentialAutoImport({
1667
- authStorage: this.ctx.session.modelRegistry.authStorage,
1668
- trigger: "bare-login",
1669
- discover: options.externalCredentialDiscover,
1670
- });
1671
- externalCredentialCandidates = summary.imported;
1672
- if (externalCredentialCandidates.length > 0) {
1673
- 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
+ }
1674
2312
  }
1675
2313
  }
1676
2314
  }