@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
@@ -0,0 +1,535 @@
1
+ import type { CasRestoreResult } from "../../config/atomic-yaml-patch";
2
+ import type { RawSettings, SettingsAtomicPatch, SettingsAtomicReceipt } from "../../config/settings";
3
+ import {
4
+ getNotificationConfig,
5
+ hasNonBlankValue,
6
+ type NotificationSettingsReader,
7
+ type NotificationSettingsSnapshot,
8
+ readTelegramActivationMarkers,
9
+ type TelegramActivationMarker,
10
+ type TelegramActivationMarkers,
11
+ type TelegramActivationReason,
12
+ type TelegramActivationState,
13
+ telegramActivationIdentity,
14
+ tokenFingerprint,
15
+ } from "./config";
16
+ import {
17
+ DAEMON_VERSION,
18
+ type EnsureTelegramDaemonDetailedResult,
19
+ readDaemonState,
20
+ type TelegramDaemonFs,
21
+ } from "./telegram-daemon";
22
+
23
+ export type { TelegramActivationMarker, TelegramActivationMarkers, TelegramActivationReason, TelegramActivationState };
24
+ export { telegramActivationIdentity };
25
+
26
+ /** The identity relationship between a proposed Telegram configuration and a live daemon owner. */
27
+ export type ProposedTelegramIdentityStatus = "absent" | "same" | "foreign" | "unknown";
28
+
29
+ /**
30
+ * Non-secret metadata about a daemon owner. Token fingerprints and the owner's
31
+ * chat ID intentionally never cross this boundary. `chatDisplay`, when present,
32
+ * is supplied by the caller from an already-approved proposed-chat display.
33
+ */
34
+ export interface TelegramDaemonOwnerMetadata {
35
+ ownerId: string;
36
+ pid: number;
37
+ generation?: number;
38
+ chatDisplay?: string;
39
+ }
40
+
41
+ /** Secret-safe proposed-identity preflight outcome. */
42
+ export interface ProposedTelegramIdentity {
43
+ status: ProposedTelegramIdentityStatus;
44
+ owner?: TelegramDaemonOwnerMetadata;
45
+ }
46
+
47
+ export interface ProposedTelegramIdentityPreflightInput {
48
+ settings: NotificationSettingsReader;
49
+ botToken: string;
50
+ chatId: string;
51
+ /** A UI-approved display value for the proposed chat; never inferred from a foreign daemon state. */
52
+ chatDisplay?: string;
53
+ deps?: {
54
+ fs?: TelegramDaemonFs;
55
+ pidAlive?: (pid: number) => boolean;
56
+ };
57
+ }
58
+
59
+ function defaultPidAlive(pid: number): boolean {
60
+ try {
61
+ process.kill(pid, 0);
62
+ return true;
63
+ } catch (error) {
64
+ return (error as NodeJS.ErrnoException).code === "EPERM";
65
+ }
66
+ }
67
+
68
+ function validPositiveInteger(value: unknown): value is number {
69
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
70
+ }
71
+
72
+ function validGeneration(value: unknown): value is number | undefined {
73
+ return value === undefined || (typeof value === "number" && Number.isSafeInteger(value) && value >= 0);
74
+ }
75
+
76
+ /**
77
+ * Compare a proposed identity with the current daemon owner without exposing a
78
+ * token or token fingerprint. Invalid/unreadable state is deliberately
79
+ * `unknown`, which callers must treat as cancel-by-default.
80
+ */
81
+ export async function proposedTelegramIdentity(
82
+ input: ProposedTelegramIdentityPreflightInput,
83
+ ): Promise<ProposedTelegramIdentity> {
84
+ if (!hasNonBlankValue(input.botToken) || !hasNonBlankValue(input.chatId)) return { status: "unknown" };
85
+
86
+ try {
87
+ const state = await readDaemonState(input.settings, input.deps?.fs);
88
+ if (!state) return { status: "absent" };
89
+
90
+ const metadata =
91
+ typeof state.ownerId === "string" &&
92
+ state.ownerId.trim().length > 0 &&
93
+ validPositiveInteger(state.pid) &&
94
+ validGeneration(state.generation)
95
+ ? {
96
+ ownerId: state.ownerId,
97
+ pid: state.pid,
98
+ ...(state.generation === undefined ? {} : { generation: state.generation }),
99
+ }
100
+ : undefined;
101
+ if (
102
+ !metadata ||
103
+ state.version !== DAEMON_VERSION ||
104
+ typeof state.tokenFingerprint !== "string" ||
105
+ typeof state.chatId !== "string"
106
+ ) {
107
+ return metadata ? { status: "unknown", owner: metadata } : { status: "unknown" };
108
+ }
109
+
110
+ const pidAlive = input.deps?.pidAlive ?? defaultPidAlive;
111
+ if (!pidAlive(metadata.pid)) return { status: "absent" };
112
+
113
+ if (state.tokenFingerprint === tokenFingerprint(input.botToken) && state.chatId === input.chatId) {
114
+ return {
115
+ status: "same",
116
+ owner: input.chatDisplay === undefined ? metadata : { ...metadata, chatDisplay: input.chatDisplay },
117
+ };
118
+ }
119
+ return { status: "foreign", owner: metadata };
120
+ } catch {
121
+ return { status: "unknown" };
122
+ }
123
+ }
124
+
125
+ export interface NotificationConfigurationWriter extends NotificationSettingsReader {
126
+ commitAtomicBatch(patches: readonly SettingsAtomicPatch[]): Promise<SettingsAtomicReceipt>;
127
+ commitAtomicBatchWithCurrent?(
128
+ buildPatches: (
129
+ current: Readonly<RawSettings>,
130
+ ) => Promise<readonly SettingsAtomicPatch[]> | readonly SettingsAtomicPatch[],
131
+ ): Promise<SettingsAtomicReceipt>;
132
+ }
133
+
134
+ export function createTelegramActivationMarker(input: {
135
+ botToken: string;
136
+ chatId: string;
137
+ state: TelegramActivationState;
138
+ reason?: TelegramActivationReason;
139
+ now?: Date;
140
+ }): TelegramActivationMarker {
141
+ return {
142
+ identity: telegramActivationIdentity(input.botToken, input.chatId),
143
+ state: input.state,
144
+ updatedAt: (input.now ?? new Date()).toISOString(),
145
+ ...(input.reason === undefined ? {} : { reason: input.reason }),
146
+ };
147
+ }
148
+
149
+ export function observedTelegramActivationMarker(
150
+ settings: NotificationSettingsReader,
151
+ botToken: string,
152
+ chatId: string,
153
+ ): TelegramActivationMarker | undefined {
154
+ const identity = telegramActivationIdentity(botToken, chatId);
155
+ return readTelegramActivationMarkers(settings.getNotificationSettingsSnapshot().telegram.activation)[identity];
156
+ }
157
+
158
+ function activationMarkersFromCurrent(current: Readonly<RawSettings>): TelegramActivationMarkers {
159
+ const notifications = current.notifications;
160
+ if (!notifications || typeof notifications !== "object" || Array.isArray(notifications)) return {};
161
+ const telegram = (notifications as Record<string, unknown>).telegram;
162
+ if (!telegram || typeof telegram !== "object" || Array.isArray(telegram)) return {};
163
+ return readTelegramActivationMarkers((telegram as Record<string, unknown>).activation);
164
+ }
165
+
166
+ async function commitNotificationBatchWithCurrent(
167
+ settings: NotificationConfigurationWriter,
168
+ buildPatches: (
169
+ current: Readonly<RawSettings>,
170
+ ) => Promise<readonly SettingsAtomicPatch[]> | readonly SettingsAtomicPatch[],
171
+ ): Promise<SettingsAtomicReceipt> {
172
+ if (settings.commitAtomicBatchWithCurrent) return settings.commitAtomicBatchWithCurrent(buildPatches);
173
+ const snapshot = settings.getNotificationSettingsSnapshot();
174
+ const current: RawSettings = {
175
+ notifications: {
176
+ telegram: {
177
+ activation: snapshot.telegram.activation,
178
+ },
179
+ },
180
+ };
181
+ return settings.commitAtomicBatch(await buildPatches(current));
182
+ }
183
+
184
+ function sameActivationMarker(left: TelegramActivationMarker, right: TelegramActivationMarker): boolean {
185
+ return (
186
+ left.identity === right.identity &&
187
+ left.state === right.state &&
188
+ left.updatedAt === right.updatedAt &&
189
+ left.reason === right.reason
190
+ );
191
+ }
192
+
193
+ /** Persist one durable marker without discarding markers for other identities. */
194
+ export async function persistTelegramActivationMarker(
195
+ settings: NotificationConfigurationWriter,
196
+ marker: TelegramActivationMarker,
197
+ ): Promise<SettingsAtomicReceipt> {
198
+ return await commitNotificationBatchWithCurrent(settings, current => {
199
+ const markers = activationMarkersFromCurrent(current);
200
+ markers[marker.identity] = { ...marker };
201
+ return [{ path: "notifications.telegram.activation", op: "set", value: markers }];
202
+ });
203
+ }
204
+
205
+ /** Clear only the exact marker that was safely reconciled. */
206
+ export async function clearTelegramActivationMarker(
207
+ settings: NotificationConfigurationWriter,
208
+ marker: TelegramActivationMarker,
209
+ ): Promise<void> {
210
+ const receipt = await commitNotificationBatchWithCurrent(settings, current => {
211
+ const markers = activationMarkersFromCurrent(current);
212
+ const stored = markers[marker.identity];
213
+ if (!stored || !sameActivationMarker(stored, marker)) return [];
214
+ delete markers[marker.identity];
215
+ return Object.keys(markers).length === 0
216
+ ? [{ path: "notifications.telegram.activation", op: "unset" }]
217
+ : [{ path: "notifications.telegram.activation", op: "set", value: markers }];
218
+ });
219
+ receipt.discard();
220
+ }
221
+
222
+ export type CompleteNonTelegramAdapter = "discord" | "slack";
223
+
224
+ function completeNonTelegramAdapters(snapshot: NotificationSettingsSnapshot): CompleteNonTelegramAdapter[] {
225
+ if (!snapshot.enabled) return [];
226
+ const adapters: CompleteNonTelegramAdapter[] = [];
227
+ if (
228
+ hasNonBlankValue(snapshot.discord.botToken) &&
229
+ hasNonBlankValue(snapshot.discord.applicationId) &&
230
+ hasNonBlankValue(snapshot.discord.guildId) &&
231
+ hasNonBlankValue(snapshot.discord.parentChannelId)
232
+ ) {
233
+ adapters.push("discord");
234
+ }
235
+ if (
236
+ hasNonBlankValue(snapshot.slack.botToken) &&
237
+ hasNonBlankValue(snapshot.slack.appToken) &&
238
+ hasNonBlankValue(snapshot.slack.workspaceId) &&
239
+ hasNonBlankValue(snapshot.slack.channelId)
240
+ ) {
241
+ adapters.push("slack");
242
+ }
243
+ return adapters;
244
+ }
245
+
246
+ export type SaveTelegramInactiveAvailability = { available: true };
247
+
248
+ /**
249
+ * Telegram-specific activation markers let Save inactive preserve globally
250
+ * enabled Discord and Slack adapters, so the action is always available.
251
+ */
252
+ export function getSaveTelegramInactiveAvailability(
253
+ _settings: NotificationSettingsReader,
254
+ ): SaveTelegramInactiveAvailability {
255
+ return { available: true };
256
+ }
257
+
258
+ export type SaveTelegramInactiveResult = { status: "saved_inactive"; receipt: SettingsAtomicReceipt };
259
+
260
+ /**
261
+ * Atomically persist Telegram credentials with a non-secret inactive marker.
262
+ * Global notifications are disabled only when Telegram is the sole complete adapter.
263
+ */
264
+ export async function saveTelegramInactive(input: {
265
+ settings: NotificationConfigurationWriter;
266
+ botToken: string;
267
+ chatId: string;
268
+ }): Promise<SaveTelegramInactiveResult> {
269
+ if (!hasNonBlankValue(input.botToken) || !hasNonBlankValue(input.chatId)) {
270
+ throw new TypeError("Saving inactive Telegram configuration requires a non-blank token and chat ID.");
271
+ }
272
+ const snapshot = input.settings.getNotificationSettingsSnapshot();
273
+ const marker = createTelegramActivationMarker({
274
+ botToken: input.botToken,
275
+ chatId: input.chatId,
276
+ state: "inactive",
277
+ reason: "saved_inactive",
278
+ });
279
+ const receipt = await commitNotificationBatchWithCurrent(input.settings, current => {
280
+ const markers = activationMarkersFromCurrent(current);
281
+ markers[marker.identity] = marker;
282
+ const patches: SettingsAtomicPatch[] = [
283
+ { path: "notifications.telegram.botToken", op: "set", value: input.botToken },
284
+ { path: "notifications.telegram.chatId", op: "set", value: input.chatId },
285
+ { path: "notifications.telegram.activation", op: "set", value: markers },
286
+ ];
287
+ if (completeNonTelegramAdapters(snapshot).length === 0) {
288
+ patches.push({ path: "notifications.enabled", op: "set", value: false });
289
+ }
290
+ return patches;
291
+ });
292
+ return { status: "saved_inactive", receipt };
293
+ }
294
+
295
+ export interface TelegramRemovalRuntime {
296
+ /** Stops the local endpoint, unregisters its root, and stops an unreferenced old daemon. */
297
+ stopAndUnregister(): Promise<void>;
298
+ }
299
+
300
+ /**
301
+ * Remove Telegram credentials without disturbing other adapters. Runtime
302
+ * teardown is intentionally first: a failed teardown leaves durable credentials
303
+ * untouched rather than orphaning an old daemon/root behind a successful delete.
304
+ */
305
+ export async function removeTelegramConfiguration(input: {
306
+ settings: NotificationConfigurationWriter;
307
+ removal: TelegramRemovalRuntime;
308
+ }): Promise<{ receipt: SettingsAtomicReceipt; globallyDisabled: boolean }> {
309
+ const cfg = getNotificationConfig(input.settings);
310
+ const otherAdapterRemains =
311
+ (hasNonBlankValue(cfg.discord.botToken) &&
312
+ hasNonBlankValue(cfg.discord.applicationId) &&
313
+ hasNonBlankValue(cfg.discord.guildId) &&
314
+ hasNonBlankValue(cfg.discord.parentChannelId)) ||
315
+ (hasNonBlankValue(cfg.slack.botToken) &&
316
+ hasNonBlankValue(cfg.slack.appToken) &&
317
+ hasNonBlankValue(cfg.slack.workspaceId) &&
318
+ hasNonBlankValue(cfg.slack.channelId));
319
+ await input.removal.stopAndUnregister();
320
+ const patches: SettingsAtomicPatch[] = [
321
+ { path: "notifications.telegram.botToken", op: "unset" },
322
+ { path: "notifications.telegram.chatId", op: "unset" },
323
+ { path: "notifications.telegram.activation", op: "unset" },
324
+ ];
325
+ if (!otherAdapterRemains) patches.push({ path: "notifications.enabled", op: "set", value: false });
326
+ const receipt = await input.settings.commitAtomicBatch(patches);
327
+ return { receipt, globallyDisabled: !otherAdapterRemains };
328
+ }
329
+
330
+ /** Detailed outcome of checking or reconnecting the Telegram daemon after a durable commit. */
331
+ export type TelegramDaemonReconnectOutcome = EnsureTelegramDaemonDetailedResult;
332
+
333
+ /**
334
+ * The session controller must not resolve `enterBlockedRuntime` until its
335
+ * current endpoint has stopped and been removed. This lets callers report a
336
+ * blocked save only after no further frames can reach the foreign owner.
337
+ */
338
+ export interface NotificationRuntimeController {
339
+ /** Resolves only after the current endpoint is stopped and removed. */
340
+ enterBlockedRuntime(): Promise<unknown>;
341
+ clearBlockedRuntime(): Promise<unknown>;
342
+ reconcileCurrentSession(): Promise<unknown>;
343
+ }
344
+
345
+ export interface TelegramPostCommitActivation {
346
+ controller: NotificationRuntimeController;
347
+ reconnect: () => Promise<TelegramDaemonReconnectOutcome>;
348
+ /** Durable Telegram-only marker write after the endpoint has stopped. */
349
+ persistInactive(marker: TelegramActivationMarker): Promise<SettingsAtomicReceipt>;
350
+ /** Remove the exact activation marker only after a safe reconnect. */
351
+ clearInactive(marker: TelegramActivationMarker): Promise<void>;
352
+ marker: TelegramActivationMarker;
353
+ }
354
+
355
+ export type PostCommitTelegramActivationResult =
356
+ | { status: "activated"; reconnect: Exclude<TelegramDaemonReconnectOutcome, "blocked_identity"> }
357
+ | {
358
+ status: "blocked_identity";
359
+ message: string;
360
+ restore(): Promise<BlockedTelegramRestoreResult>;
361
+ retainCommitted(): void;
362
+ };
363
+
364
+ export type BlockedTelegramRestoreResult =
365
+ | { status: "restored"; reconnect: TelegramDaemonReconnectOutcome }
366
+ | { status: "conflict"; paths: readonly string[] }
367
+ | { status: "discarded" }
368
+ | { status: "still_blocked" };
369
+
370
+ async function restoreBlockedConfiguration(input: {
371
+ receipt: SettingsAtomicReceipt;
372
+ inactiveReceipt: SettingsAtomicReceipt;
373
+ activation: TelegramPostCommitActivation;
374
+ }): Promise<BlockedTelegramRestoreResult> {
375
+ const retainBlockedMarker = async (): Promise<void> => {
376
+ const receipt = await input.activation.persistInactive(input.activation.marker);
377
+ receipt.discard();
378
+ };
379
+
380
+ let restored: CasRestoreResult;
381
+ try {
382
+ restored = await input.receipt.restore();
383
+ } catch (error) {
384
+ await retainBlockedMarker();
385
+ throw error;
386
+ }
387
+ if (restored.status === "conflict" || restored.status === "discarded") {
388
+ await retainBlockedMarker();
389
+ return restored;
390
+ }
391
+
392
+ // Keep the fail-closed marker durable until the configuration rollback has
393
+ // completed. Removing it first exposes the blocked identity between two CAS
394
+ // operations to other processes.
395
+ let inactiveRestored: CasRestoreResult;
396
+ try {
397
+ inactiveRestored = await input.inactiveReceipt.restore();
398
+ } catch (error) {
399
+ await retainBlockedMarker();
400
+ throw error;
401
+ }
402
+ if (inactiveRestored.status === "conflict" || inactiveRestored.status === "discarded") {
403
+ await retainBlockedMarker();
404
+ await input.activation.controller.enterBlockedRuntime();
405
+ return { status: "still_blocked" };
406
+ }
407
+
408
+ const reconnect = await input.activation.reconnect();
409
+ if (reconnect === "blocked_identity") {
410
+ await input.activation.controller.enterBlockedRuntime();
411
+ return { status: "still_blocked" };
412
+ }
413
+ await input.activation.controller.clearBlockedRuntime();
414
+ await input.activation.controller.reconcileCurrentSession();
415
+ return { status: "restored", reconnect };
416
+ }
417
+
418
+ /**
419
+ * Complete a committed Telegram update in the required order: identity
420
+ * reconnect first, normal session reconciliation second. A post-commit foreign
421
+ * owner race stops the endpoint, durably marks only that Telegram identity
422
+ * inactive, then exposes an ordered CAS restore/retain choice.
423
+ */
424
+ export async function reconcileCommittedTelegramConfiguration(input: {
425
+ receipt: SettingsAtomicReceipt;
426
+ activation: TelegramPostCommitActivation;
427
+ inactiveMarkerToClear?: TelegramActivationMarker;
428
+ }): Promise<PostCommitTelegramActivationResult> {
429
+ const reconnect = await input.activation.reconnect();
430
+ if (reconnect === "blocked_identity") {
431
+ await input.activation.controller.enterBlockedRuntime();
432
+ const inactiveReceipt = await input.activation.persistInactive(input.activation.marker);
433
+ return {
434
+ status: "blocked_identity",
435
+ message:
436
+ "Configuration saved inactive; activation blocked; foreign daemon untouched. Current session stopped because Telegram activation was blocked by a foreign daemon.",
437
+ restore: () => restoreBlockedConfiguration({ ...input, inactiveReceipt }),
438
+ retainCommitted: () => {
439
+ inactiveReceipt.discard();
440
+ input.receipt.discard();
441
+ },
442
+ };
443
+ }
444
+
445
+ if (input.inactiveMarkerToClear) {
446
+ try {
447
+ await input.activation.clearInactive(input.inactiveMarkerToClear);
448
+ } catch (error) {
449
+ await input.activation.controller.enterBlockedRuntime();
450
+ throw error;
451
+ }
452
+ }
453
+ await input.activation.controller.clearBlockedRuntime();
454
+ await input.activation.controller.reconcileCurrentSession();
455
+ return { status: "activated", reconnect };
456
+ }
457
+
458
+ export type SaveTelegramConfigurationResult =
459
+ | { status: "cancelled"; preflight: ProposedTelegramIdentity; guidance: string }
460
+ | SaveTelegramInactiveResult
461
+ | { status: "saved"; receipt: SettingsAtomicReceipt; preflight: ProposedTelegramIdentity }
462
+ | PostCommitTelegramActivationResult;
463
+
464
+ /**
465
+ * Guard a Telegram setup commit with proposed-identity preflight. Foreign and
466
+ * unreadable ownership are cancel-by-default and make no configuration changes.
467
+ */
468
+ export async function saveTelegramConfiguration(input: {
469
+ settings: NotificationConfigurationWriter;
470
+ botToken: string;
471
+ chatId: string;
472
+ chatDisplay?: string;
473
+ /** Explicitly persist credentials disabled after a foreign/unknown preflight; otherwise cancel remains the default. */
474
+ saveInactive: boolean;
475
+ preflight?: (input: Omit<ProposedTelegramIdentityPreflightInput, "settings">) => Promise<ProposedTelegramIdentity>;
476
+ activation?: TelegramPostCommitActivation;
477
+ }): Promise<SaveTelegramConfigurationResult> {
478
+ if (!hasNonBlankValue(input.botToken) || !hasNonBlankValue(input.chatId)) {
479
+ throw new TypeError("Saving Telegram configuration requires a non-blank token and chat ID.");
480
+ }
481
+ const runPreflight =
482
+ input.preflight ??
483
+ ((next: Omit<ProposedTelegramIdentityPreflightInput, "settings">) =>
484
+ proposedTelegramIdentity({ settings: input.settings, ...next }));
485
+ const preflight = await runPreflight({
486
+ botToken: input.botToken,
487
+ chatId: input.chatId,
488
+ chatDisplay: input.chatDisplay,
489
+ });
490
+ if (preflight.status === "foreign" || preflight.status === "unknown") {
491
+ // Cancel is the default for an untrusted owner. `saveInactive` is an
492
+ // explicit user selection that cannot activate the proposed identity.
493
+ if (input.saveInactive) return await saveTelegramInactive(input);
494
+ return {
495
+ status: "cancelled",
496
+ preflight,
497
+ guidance:
498
+ "Telegram activation was not saved. Cancel or retry after the daemon owner exits or is reconfigured.",
499
+ };
500
+ }
501
+
502
+ if (input.saveInactive) return await saveTelegramInactive(input);
503
+
504
+ const activeIdentity = telegramActivationIdentity(input.botToken, input.chatId);
505
+ const inactiveMarkerToClear = observedTelegramActivationMarker(input.settings, input.botToken, input.chatId);
506
+ const receipt = await commitNotificationBatchWithCurrent(input.settings, current => {
507
+ const patches: SettingsAtomicPatch[] = [
508
+ { path: "notifications.telegram.botToken", op: "set", value: input.botToken },
509
+ { path: "notifications.telegram.chatId", op: "set", value: input.chatId },
510
+ { path: "notifications.enabled", op: "set", value: true },
511
+ ];
512
+ // With post-commit activation, the marker has its own receipt so a blocked
513
+ // rollback can restore configuration without self-conflicting on the marker
514
+ // written after this commit. Successful activation clears that marker only
515
+ // after owner readiness is proved.
516
+ if (!input.activation) {
517
+ const markers = activationMarkersFromCurrent(current);
518
+ delete markers[activeIdentity];
519
+ patches.splice(
520
+ 2,
521
+ 0,
522
+ Object.keys(markers).length === 0
523
+ ? { path: "notifications.telegram.activation", op: "unset" }
524
+ : { path: "notifications.telegram.activation", op: "set", value: markers },
525
+ );
526
+ }
527
+ return patches;
528
+ });
529
+ if (!input.activation) return { status: "saved", receipt, preflight };
530
+ return await reconcileCommittedTelegramConfiguration({
531
+ receipt,
532
+ activation: input.activation,
533
+ inactiveMarkerToClear,
534
+ });
535
+ }