@gajae-code/coding-agent 0.10.2 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (476) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/async/job-manager.d.ts +46 -7
  4. package/dist/types/cli/args.d.ts +4 -5
  5. package/dist/types/cli/daemon-cli.d.ts +12 -1
  6. package/dist/types/cli/notify-cli.d.ts +21 -1
  7. package/dist/types/cli.d.ts +3 -0
  8. package/dist/types/commands/daemon.d.ts +39 -0
  9. package/dist/types/commands/launch.d.ts +3 -0
  10. package/dist/types/commands/notify.d.ts +28 -1
  11. package/dist/types/commands/sdk.d.ts +33 -0
  12. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  13. package/dist/types/config/model-profile-activation.d.ts +35 -15
  14. package/dist/types/config/model-profiles.d.ts +11 -5
  15. package/dist/types/config/model-registry.d.ts +3 -3
  16. package/dist/types/config/model-resolver.d.ts +39 -6
  17. package/dist/types/config/model-selector-value.d.ts +17 -0
  18. package/dist/types/config/models-config-schema.d.ts +10 -6
  19. package/dist/types/config/settings-schema.d.ts +133 -6
  20. package/dist/types/config/settings.d.ts +63 -35
  21. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  22. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  23. package/dist/types/daemon/builtin.d.ts +6 -5
  24. package/dist/types/daemon/control-types.d.ts +1 -1
  25. package/dist/types/discovery/mcp-json.d.ts +12 -1
  26. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  27. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  28. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  31. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  32. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  33. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  34. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  35. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  36. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  37. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  38. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  39. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  40. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  41. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  42. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  43. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  44. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  45. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  46. package/dist/types/harness-control-plane/types.d.ts +3 -4
  47. package/dist/types/lsp/index.d.ts +1 -1
  48. package/dist/types/main.d.ts +32 -38
  49. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  50. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  51. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  52. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  53. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  54. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  55. package/dist/types/modes/components/model-selector.d.ts +1 -0
  56. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  57. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  58. package/dist/types/modes/components/welcome.d.ts +1 -1
  59. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  60. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  62. package/dist/types/modes/index.d.ts +0 -4
  63. package/dist/types/modes/interactive-mode.d.ts +5 -2
  64. package/dist/types/modes/runtime-init.d.ts +2 -2
  65. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  66. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  67. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  68. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  69. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  72. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  73. package/dist/types/modes/types.d.ts +7 -2
  74. package/dist/types/runtime-mcp/client.d.ts +2 -0
  75. package/dist/types/runtime-mcp/config.d.ts +5 -1
  76. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  77. package/dist/types/runtime-mcp/types.d.ts +4 -0
  78. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  79. package/dist/types/sdk/acp/index.d.ts +2 -0
  80. package/dist/types/sdk/broker/broker.d.ts +53 -0
  81. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  82. package/dist/types/sdk/broker/ensure.d.ts +42 -0
  83. package/dist/types/sdk/broker/identity.d.ts +3 -0
  84. package/dist/types/sdk/broker/index.d.ts +8 -0
  85. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  86. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  87. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  88. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  89. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  90. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  91. package/dist/types/sdk/broker/transport.d.ts +9 -0
  92. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  93. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  94. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  95. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  96. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  97. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  98. package/dist/types/sdk/bus/config.d.ts +274 -0
  99. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  100. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  101. package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
  102. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  103. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  104. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  105. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  107. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  108. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  109. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  110. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  111. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  112. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  113. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  114. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  115. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  116. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  117. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  118. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  119. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  121. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
  122. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  123. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  124. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  125. package/dist/types/sdk/cli/index.d.ts +1 -0
  126. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  127. package/dist/types/sdk/client/client.d.ts +1 -0
  128. package/dist/types/sdk/client/discovery.d.ts +27 -0
  129. package/dist/types/sdk/client/index.d.ts +2 -0
  130. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  131. package/dist/types/sdk/host/control/index.d.ts +2 -0
  132. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  133. package/dist/types/sdk/host/events.d.ts +35 -0
  134. package/dist/types/sdk/host/host.d.ts +35 -0
  135. package/dist/types/sdk/host/index.d.ts +4 -0
  136. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  137. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  138. package/dist/types/sdk/host/query/index.d.ts +3 -0
  139. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  140. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  141. package/dist/types/sdk/host/types.d.ts +32 -0
  142. package/dist/types/sdk/index.d.ts +6 -0
  143. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  144. package/dist/types/sdk/mcp/index.d.ts +1 -0
  145. package/dist/types/sdk/mcp/server.d.ts +37 -0
  146. package/dist/types/sdk/models.d.ts +44 -0
  147. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  148. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  149. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  150. package/dist/types/sdk/startup-capability.d.ts +50 -0
  151. package/dist/types/session/agent-session.d.ts +114 -21
  152. package/dist/types/session/default-model-selection.d.ts +25 -0
  153. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  154. package/dist/types/session/session-manager.d.ts +58 -1
  155. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  156. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  157. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  158. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  159. package/dist/types/tools/browser/launch.d.ts +22 -0
  160. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  161. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  162. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  163. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  164. package/dist/types/tools/browser/registry.d.ts +19 -0
  165. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  166. package/dist/types/tools/index.d.ts +8 -8
  167. package/dist/types/tools/subagent-render.d.ts +1 -0
  168. package/dist/types/tools/subagent.d.ts +6 -1
  169. package/package.json +34 -13
  170. package/scripts/build-sdk-package-smoke.ts +99 -0
  171. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  172. package/scripts/compile-args.ts +4 -2
  173. package/scripts/g005-daemon-smoke.ts +4 -5
  174. package/scripts/g011-daemon-path-smoke.ts +5 -5
  175. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  176. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  177. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  178. package/scripts/manifest-schema.ts +124 -0
  179. package/scripts/run-test-manifest.ts +153 -0
  180. package/scripts/run-threat-model-check.ts +157 -0
  181. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  182. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  183. package/src/append-only-mode.ts +1 -1
  184. package/src/async/job-manager.ts +406 -63
  185. package/src/cli/args.ts +43 -12
  186. package/src/cli/auth-gateway-cli.ts +2 -2
  187. package/src/cli/config-cli.ts +2 -1
  188. package/src/cli/daemon-cli.ts +63 -14
  189. package/src/cli/list-models.ts +1 -1
  190. package/src/cli/notify-cli.ts +288 -286
  191. package/src/cli.ts +21 -2
  192. package/src/commands/daemon.ts +50 -6
  193. package/src/commands/harness.ts +93 -36
  194. package/src/commands/launch.ts +5 -2
  195. package/src/commands/mcp-serve.ts +19 -12
  196. package/src/commands/notify.ts +36 -3
  197. package/src/commands/sdk.ts +426 -0
  198. package/src/commit/agentic/agent.ts +1 -0
  199. package/src/config/atomic-yaml-patch.ts +423 -0
  200. package/src/config/model-profile-activation.ts +240 -89
  201. package/src/config/model-profiles.ts +18 -15
  202. package/src/config/model-registry.ts +51 -26
  203. package/src/config/model-resolver.ts +138 -51
  204. package/src/config/model-selector-value.ts +50 -0
  205. package/src/config/models-config-schema.ts +14 -21
  206. package/src/config/settings-schema.ts +128 -10
  207. package/src/config/settings.ts +1120 -158
  208. package/src/coordinator-mcp/model-preset.ts +74 -20
  209. package/src/coordinator-mcp/server.ts +1597 -3052
  210. package/src/daemon/builtin.ts +8 -5
  211. package/src/daemon/control-types.ts +1 -1
  212. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  213. package/src/discovery/mcp-json.ts +327 -20
  214. package/src/extensibility/custom-tools/types.ts +1 -1
  215. package/src/extensibility/extensions/compact-handler.ts +3 -3
  216. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  217. package/src/extensibility/extensions/loader.ts +69 -5
  218. package/src/extensibility/extensions/runner.ts +112 -4
  219. package/src/extensibility/extensions/types.ts +176 -17
  220. package/src/extensibility/hooks/types.ts +1 -1
  221. package/src/gjc-runtime/launch-tmux.ts +170 -86
  222. package/src/gjc-runtime/psmux-detect.ts +82 -4
  223. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  224. package/src/gjc-runtime/team-runtime.ts +54 -35
  225. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  226. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  227. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  228. package/src/gjc-runtime/ultragoal-guard.ts +108 -14
  229. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  230. package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
  231. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  232. package/src/harness-control-plane/operate.ts +9 -9
  233. package/src/harness-control-plane/owner.ts +283 -39
  234. package/src/harness-control-plane/receipts.ts +0 -1
  235. package/src/harness-control-plane/sdk-transport.ts +395 -0
  236. package/src/harness-control-plane/session-transport.ts +94 -0
  237. package/src/harness-control-plane/types.ts +1 -1
  238. package/src/internal-urls/docs-index.generated.ts +34 -35
  239. package/src/lsp/client.ts +42 -6
  240. package/src/lsp/index.ts +2 -2
  241. package/src/main.ts +299 -204
  242. package/src/modes/DESIGN.md +258 -0
  243. package/src/modes/acp/acp-agent.ts +1228 -2612
  244. package/src/modes/acp/acp-client-bridge.ts +2 -20
  245. package/src/modes/acp/acp-event-mapper.ts +18 -2
  246. package/src/modes/acp/acp-mode.ts +8 -36
  247. package/src/modes/acp/permission-mode.ts +25 -0
  248. package/src/modes/acp/startup-options.ts +6 -0
  249. package/src/modes/components/agent-dashboard.ts +37 -17
  250. package/src/modes/components/model-selector.ts +93 -35
  251. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  252. package/src/modes/components/settings-selector.ts +60 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +10 -17
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +396 -28
  257. package/src/modes/controllers/selector-controller.ts +674 -36
  258. package/src/modes/index.ts +0 -22
  259. package/src/modes/interactive-mode.ts +87 -36
  260. package/src/modes/runtime-init.ts +298 -6
  261. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  262. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  263. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  264. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  265. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  266. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
  267. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  268. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  269. package/src/modes/types.ts +7 -2
  270. package/src/runtime-mcp/client.ts +94 -19
  271. package/src/runtime-mcp/config.ts +27 -15
  272. package/src/runtime-mcp/manager.ts +343 -105
  273. package/src/runtime-mcp/oauth-flow.ts +42 -12
  274. package/src/runtime-mcp/transports/http.ts +49 -19
  275. package/src/runtime-mcp/transports/stdio.ts +47 -28
  276. package/src/runtime-mcp/types.ts +10 -0
  277. package/src/sdk/acp/adapter.ts +418 -0
  278. package/src/sdk/acp/index.ts +2 -0
  279. package/src/sdk/broker/broker.ts +642 -0
  280. package/src/sdk/broker/discovery.ts +113 -0
  281. package/src/sdk/broker/ensure.ts +307 -0
  282. package/src/sdk/broker/identity.ts +42 -0
  283. package/src/sdk/broker/index.ts +8 -0
  284. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  285. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  286. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  287. package/src/sdk/broker/lifecycle.ts +2157 -0
  288. package/src/sdk/broker/process-incarnation.ts +159 -0
  289. package/src/sdk/broker/runtime.ts +164 -0
  290. package/src/sdk/broker/session-index.ts +318 -0
  291. package/src/sdk/broker/state-version.ts +23 -0
  292. package/src/sdk/broker/transport.ts +125 -0
  293. package/src/sdk/bus/chat-command-policy.ts +107 -0
  294. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  295. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  296. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  297. package/src/sdk/bus/chat-effect-journal.ts +355 -0
  298. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  299. package/src/sdk/bus/config.ts +433 -0
  300. package/src/sdk/bus/conversation-store.ts +391 -0
  301. package/src/sdk/bus/discord-conversation.ts +85 -0
  302. package/src/sdk/bus/discord-daemon.ts +2292 -0
  303. package/src/sdk/bus/discord-live-provider.ts +521 -0
  304. package/src/sdk/bus/discord-provider.ts +56 -0
  305. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  306. package/src/sdk/bus/index.ts +3979 -0
  307. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  309. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  310. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  311. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  312. package/src/sdk/bus/natives-augment.d.ts +38 -0
  313. package/src/sdk/bus/notification-orchestration.ts +535 -0
  314. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  315. package/src/sdk/bus/session-control.ts +333 -0
  316. package/src/sdk/bus/slack-conversation.ts +74 -0
  317. package/src/sdk/bus/slack-daemon.ts +2144 -0
  318. package/src/sdk/bus/slack-live-provider.ts +380 -0
  319. package/src/sdk/bus/slack-provider.ts +76 -0
  320. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  321. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  322. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  323. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  324. package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
  325. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  326. package/src/sdk/bus/telegram-setup.ts +663 -0
  327. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  328. package/src/sdk/cli/index.ts +1 -0
  329. package/src/sdk/cli/session-cli.ts +275 -0
  330. package/src/sdk/client/client.ts +1 -0
  331. package/src/sdk/client/discovery.ts +108 -0
  332. package/src/sdk/client/index.ts +2 -0
  333. package/src/sdk/host/control/dispatch.ts +367 -0
  334. package/src/sdk/host/control/index.ts +10 -0
  335. package/src/sdk/host/control/operations.ts +63 -0
  336. package/src/sdk/host/events.ts +91 -0
  337. package/src/sdk/host/host.ts +296 -0
  338. package/src/sdk/host/index.ts +4 -0
  339. package/src/sdk/host/query/cursor.ts +189 -0
  340. package/src/sdk/host/query/handlers.ts +533 -0
  341. package/src/sdk/host/query/index.ts +3 -0
  342. package/src/sdk/host/query/revision-store.ts +1126 -0
  343. package/src/sdk/host/reverse-leases.ts +325 -0
  344. package/src/sdk/host/types.ts +29 -0
  345. package/src/sdk/index.ts +13 -0
  346. package/src/sdk/lifecycle-session.ts +39 -0
  347. package/src/sdk/mcp/index.ts +1 -0
  348. package/src/sdk/mcp/server.ts +332 -0
  349. package/src/sdk/models.ts +168 -0
  350. package/src/sdk/protocol/adapter-validation.ts +48 -0
  351. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  352. package/src/sdk/protocol/operation-registry.ts +312 -0
  353. package/src/{sdk.ts → sdk/session.ts} +339 -212
  354. package/src/sdk/startup-capability.ts +189 -0
  355. package/src/session/agent-session.ts +2650 -944
  356. package/src/session/default-model-selection.ts +93 -0
  357. package/src/session/fallback-chain-controller.ts +136 -0
  358. package/src/session/session-manager.ts +438 -11
  359. package/src/session/session-storage.ts +8 -1
  360. package/src/setup/credential-auto-import.ts +290 -35
  361. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  362. package/src/slash-commands/builtin-registry.ts +2 -1
  363. package/src/task/executor.ts +62 -13
  364. package/src/task/index.ts +26 -16
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/subagent-render.ts +19 -8
  384. package/src/tools/subagent.ts +84 -32
  385. package/src/tools/telegram-send.ts +2 -2
  386. package/vendor/insane-search/MANIFEST.json +2 -1
  387. package/vendor/insane-search/engine/bias_check.py +4 -1
  388. package/vendor/insane-search/engine/phase0.py +26 -1
  389. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  390. package/dist/types/modes/bridge/auth.d.ts +0 -12
  391. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  392. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  393. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  394. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  395. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  396. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  397. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  398. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  399. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  400. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  401. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  402. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  403. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  404. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  405. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  406. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  407. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  408. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  409. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  410. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  411. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  412. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  413. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  414. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  415. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  416. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  417. package/dist/types/notifications/config.d.ts +0 -132
  418. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  419. package/src/modes/bridge/auth.ts +0 -41
  420. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  421. package/src/modes/bridge/bridge-mode.ts +0 -675
  422. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  423. package/src/modes/bridge/event-stream.ts +0 -70
  424. package/src/modes/rpc/host-tools.ts +0 -1
  425. package/src/modes/rpc/host-uris.ts +0 -1
  426. package/src/modes/rpc/rpc-client.ts +0 -1166
  427. package/src/modes/rpc/rpc-mode.ts +0 -1029
  428. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  429. package/src/modes/rpc/rpc-types.ts +0 -637
  430. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  431. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  432. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  433. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  434. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  435. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  436. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  437. package/src/modes/shared/agent-wire/responses.ts +0 -17
  438. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  439. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  440. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  441. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  442. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  443. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  444. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  445. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  446. package/src/notifications/config.ts +0 -219
  447. package/src/notifications/index.ts +0 -1835
  448. package/src/notifications/telegram-daemon-cli.ts +0 -243
  449. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  450. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  462. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  463. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  475. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  476. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,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
  }