@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,19 +1,20 @@
1
1
  /**
2
2
  * Static built-in daemon controller map.
3
3
  *
4
- * Intentionally a static map keyed by daemon kind rather than a mutable plugin
5
- * registry: there is exactly one kind today (`telegram`). Promote to a richer
6
- * registry only when a second daemon kind exists.
4
+ * Controllers are deliberately static rather than a mutable plugin registry.
7
5
  */
8
6
 
9
7
  import type { Settings } from "../config/settings";
10
- import { type TelegramDaemonControlDeps, TelegramDaemonController } from "../notifications/telegram-daemon-control";
8
+ import { type ChatDaemonControlDeps, ChatDaemonController } from "../sdk/bus/chat-daemon-control";
9
+ import { type TelegramDaemonControlDeps, TelegramDaemonController } from "../sdk/bus/telegram-daemon-control";
11
10
  import type { BuiltInDaemonController, DaemonKind } from "./control-types";
12
11
 
13
- export const BUILT_IN_DAEMON_KINDS = ["telegram"] as const satisfies readonly DaemonKind[];
12
+ export const BUILT_IN_DAEMON_KINDS = ["telegram", "discord", "slack"] as const satisfies readonly DaemonKind[];
14
13
 
15
14
  export interface BuiltInDaemonControllerDeps {
16
15
  telegram?: TelegramDaemonControlDeps;
16
+ discord?: ChatDaemonControlDeps;
17
+ slack?: ChatDaemonControlDeps;
17
18
  }
18
19
 
19
20
  export function createBuiltInDaemonControllers(
@@ -22,6 +23,8 @@ export function createBuiltInDaemonControllers(
22
23
  ): Record<DaemonKind, BuiltInDaemonController> {
23
24
  return {
24
25
  telegram: new TelegramDaemonController(settings, deps.telegram),
26
+ discord: new ChatDaemonController(settings, "discord", deps.discord),
27
+ slack: new ChatDaemonController(settings, "slack", deps.slack),
25
28
  };
26
29
  }
27
30
 
@@ -6,7 +6,7 @@
6
6
  * a richer registry is intentionally deferred until a second kind exists.
7
7
  */
8
8
 
9
- export type DaemonKind = "telegram";
9
+ export type DaemonKind = "telegram" | "discord" | "slack";
10
10
 
11
11
  export type DaemonAction = "list" | "status" | "stop" | "reload";
12
12
 
@@ -311,10 +311,10 @@ Worker protocol:
311
311
  Useful runtime env vars:
312
312
 
313
313
  - `GJC_TMUX_COMMAND` / `GJC_TEAM_TMUX_COMMAND`
314
- - tmux binary/name override (default `tmux` on POSIX, `psmux` / `pmux` / `tmux` on native Windows when one of those resolves on PATH). `GJC_TMUX_COMMAND` applies to every GJC tmux flow; `GJC_TEAM_TMUX_COMMAND` is honored as an alias by the team path. Both resolve through the same resolver, so the team leader and `gjc session ...` always target the same multiplexer. These values are executable path/name overrides, not shell command lines; do not include flags such as `psmux -L <namespace>` in the env var.
315
- - Native Windows psmux support: psmux is the supported tmux-compatible multiplexer for native Windows `gjc --tmux`, `gjc session`, and `gjc team`. Psmux can be exposed as `psmux.exe` or as its `tmux.exe`/`pmux.exe` aliases. GJC probes `psmux` / `pmux` / `tmux` on Windows PATH, picks the first that resolves, and treats that binary as the multiplexer. Worker commands on Windows are emitted with PowerShell-safe `$env:VAR = 'value';` assignments so psmux's ConPTY panes inherit `GJC_TEAM_*` correctly.
316
- - Multiplexer detection knobs (Windows): `GJC_PSMUX_COMMAND` forces a wrapper to be treated as psmux, `GJC_PSMUX_DETECTION=off` skips detection, `GJC_PSMUX_FORCE_DETECT=1` re-probes every call. The mouse / set-clipboard / mode-style UX profile is filtered out for psmux; the `@gjc-profile` ownership tag and branch / project / session identity markers still round-trip and are required for `gjc session` and `gjc team`.
317
- - Windows psmux namespace boundary: psmux `-c <path>` cwd/start-directory flags do not isolate the server namespace; psmux uses the tmux-compatible global `-L <namespace>` flag for isolated server instances. GJC does not currently expose structured runtime `-L` support, because launch, `gjc session`, and `gjc team` must all carry the same namespace prefix together. If you need isolated psmux servers, start `psmux -L <namespace>` yourself before `gjc --tmux` and let GJC attach to it; do not pass `-L` through `GJC_TMUX_COMMAND`.
314
+ - tmux executable override (default `tmux` on POSIX; `psmux` / `pmux` / `tmux` resolution on native Windows). `GJC_TMUX_COMMAND` applies to every GJC tmux flow; `GJC_TEAM_TMUX_COMMAND` is honored as a team-path alias. Values are executable paths/names, not shell command lines.
315
+ - Native Windows psmux boundary: a generic-banner `tmux.exe` alias is classified by matching its executable identity with resolved `psmux.exe` / `pmux.exe` companions. Unresolved or conflicting identity evidence fails closed with `gjc_tmux_provider_ambiguous`; `GJC_PSMUX_COMMAND` must resolve to the same executable identity as the selected alias.
316
+ - Managed psmux session creation, attachment, lifecycle mutation, and team startup remain unsupported because psmux cannot provide the immutable native session identity required by the owner-isolation contract. Use WSL or verified native tmux for live team workers.
317
+ - Windows psmux namespace boundary: psmux uses the tmux-compatible global `-L <namespace>` flag for server isolation, but GJC does not accept flags in `GJC_TMUX_COMMAND` or expose structured runtime `-L` support.
318
318
  - `GJC_TEAM_WORKER_COMMAND`
319
319
  - worker command override (default resolves to active GJC entrypoint or `gjc`)
320
320
  - `GJC_TEAM_STATE_ROOT`
@@ -6,6 +6,8 @@
6
6
  *
7
7
  * Priority: 5 (low, as this is a fallback after tool-specific providers)
8
8
  */
9
+ import * as fs from "node:fs";
10
+ import * as fsPromises from "node:fs/promises";
9
11
  import * as path from "node:path";
10
12
  import { logger, tryParseJson } from "@gajae-code/utils";
11
13
  import { registerProvider } from "../capability";
@@ -16,6 +18,7 @@ import { createSourceMeta, expandEnvVarsDeep } from "./helpers";
16
18
 
17
19
  const PROVIDER_ID = "mcp-json";
18
20
  const DISPLAY_NAME = "MCP Config";
21
+ const PROTOTYPE_SENSITIVE_SERVER_NAMES = new Set(["__proto__", "prototype", "constructor"]);
19
22
 
20
23
  /**
21
24
  * Raw MCP JSON format (matches Anthropic model Desktop's format).
@@ -51,12 +54,100 @@ interface MCPConfigFile {
51
54
  };
52
55
  }
53
56
  >;
57
+ disabledServers?: string[];
58
+ }
59
+ export interface MCPJsonLoadResult extends LoadResult<MCPServer> {
60
+ disabledServers: string[];
61
+ }
62
+ function isRecord(value: unknown): value is Record<string, unknown> {
63
+ return typeof value === "object" && value !== null && !Array.isArray(value);
64
+ }
65
+ function isStringArray(value: unknown): value is string[] {
66
+ return Array.isArray(value) && value.every(item => typeof item === "string");
67
+ }
68
+ function isStringRecord(value: unknown): value is Record<string, string> {
69
+ return isRecord(value) && Object.values(value).every(item => typeof item === "string");
70
+ }
71
+ function isOptionalBoolean(value: unknown): boolean {
72
+ return value === undefined || typeof value === "boolean";
73
+ }
74
+ function isOptionalString(value: unknown): boolean {
75
+ return value === undefined || typeof value === "string";
76
+ }
77
+ function isValidAuthConfig(value: unknown): boolean {
78
+ return (
79
+ isRecord(value) &&
80
+ (value.type === "oauth" || value.type === "apikey") &&
81
+ isOptionalString(value.credentialId) &&
82
+ isOptionalString(value.tokenUrl) &&
83
+ isOptionalString(value.clientId) &&
84
+ isOptionalString(value.clientSecret)
85
+ );
86
+ }
87
+ function isValidOAuthConfig(value: unknown): boolean {
88
+ return (
89
+ isRecord(value) &&
90
+ isOptionalString(value.clientId) &&
91
+ isOptionalString(value.clientSecret) &&
92
+ isOptionalString(value.redirectUri) &&
93
+ (value.callbackPort === undefined ||
94
+ (typeof value.callbackPort === "number" &&
95
+ Number.isInteger(value.callbackPort) &&
96
+ value.callbackPort >= 1 &&
97
+ value.callbackPort <= 65_535)) &&
98
+ isOptionalString(value.callbackPath)
99
+ );
100
+ }
101
+ function isValidExactServerConfig(value: unknown): boolean {
102
+ if (!isRecord(value)) return false;
103
+ return (
104
+ isOptionalBoolean(value.enabled) &&
105
+ isOptionalBoolean(value.autoload) &&
106
+ isOptionalBoolean(value.noInheritEnv) &&
107
+ (value.timeout === undefined ||
108
+ (typeof value.timeout === "number" && Number.isFinite(value.timeout) && value.timeout > 0)) &&
109
+ isOptionalString(value.command) &&
110
+ (value.args === undefined || isStringArray(value.args)) &&
111
+ (value.env === undefined || isStringRecord(value.env)) &&
112
+ isOptionalString(value.cwd) &&
113
+ isOptionalString(value.url) &&
114
+ (value.headers === undefined || isStringRecord(value.headers)) &&
115
+ (value.type === undefined || value.type === "stdio" || value.type === "sse" || value.type === "http") &&
116
+ (value.auth === undefined || isValidAuthConfig(value.auth)) &&
117
+ (value.oauth === undefined || isValidOAuthConfig(value.oauth))
118
+ );
119
+ }
120
+ function validateExactMCPConfig(config: unknown): {
121
+ config: MCPConfigFile | null;
122
+ hasInvalidServer: boolean;
123
+ } {
124
+ if (!isRecord(config)) return { config: null, hasInvalidServer: false };
125
+ if (config.disabledServers !== undefined && !isStringArray(config.disabledServers)) {
126
+ return { config: null, hasInvalidServer: false };
127
+ }
128
+ if (config.mcpServers === undefined) {
129
+ return { config: config as MCPConfigFile, hasInvalidServer: false };
130
+ }
131
+ if (!isRecord(config.mcpServers)) return { config: null, hasInvalidServer: false };
132
+ const validServers: Record<string, unknown> = Object.create(null);
133
+ let hasInvalidServer = false;
134
+ for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
135
+ if (PROTOTYPE_SENSITIVE_SERVER_NAMES.has(name) || !isValidExactServerConfig(serverConfig)) {
136
+ hasInvalidServer = true;
137
+ continue;
138
+ }
139
+ validServers[name] = serverConfig;
140
+ }
141
+ return {
142
+ config: { ...config, mcpServers: validServers } as MCPConfigFile,
143
+ hasInvalidServer,
144
+ };
54
145
  }
55
146
 
56
147
  /**
57
148
  * Transform raw MCP config to canonical MCPServer format.
58
149
  */
59
- function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServer[] {
150
+ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta, quiet = false): MCPServer[] {
60
151
  const servers: MCPServer[] = [];
61
152
 
62
153
  if (config.mcpServers) {
@@ -66,7 +157,7 @@ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServe
66
157
  if (serverConfig.enabled !== undefined) {
67
158
  if (typeof serverConfig.enabled === "boolean") {
68
159
  enabled = serverConfig.enabled;
69
- } else {
160
+ } else if (!quiet) {
70
161
  logger.warn("MCP server has invalid 'enabled' value, ignoring", { name, value: serverConfig.enabled });
71
162
  }
72
163
  }
@@ -79,7 +170,7 @@ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServe
79
170
  serverConfig.timeout > 0
80
171
  ) {
81
172
  timeout = serverConfig.timeout;
82
- } else {
173
+ } else if (!quiet) {
83
174
  logger.warn("MCP server has invalid 'timeout' value, ignoring", { name, value: serverConfig.timeout });
84
175
  }
85
176
  }
@@ -88,7 +179,7 @@ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServe
88
179
  if (serverConfig.autoload !== undefined) {
89
180
  if (typeof serverConfig.autoload === "boolean") {
90
181
  autoload = serverConfig.autoload;
91
- } else {
182
+ } else if (!quiet) {
92
183
  logger.warn("MCP server has invalid 'autoload' value, ignoring", { name, value: serverConfig.autoload });
93
184
  }
94
185
  }
@@ -97,7 +188,7 @@ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServe
97
188
  if (serverConfig.noInheritEnv !== undefined) {
98
189
  if (typeof serverConfig.noInheritEnv === "boolean") {
99
190
  noInheritEnv = serverConfig.noInheritEnv;
100
- } else {
191
+ } else if (!quiet) {
101
192
  logger.warn("MCP server has invalid 'noInheritEnv' value, ignoring", {
102
193
  name,
103
194
  value: serverConfig.noInheritEnv,
@@ -139,33 +230,249 @@ function transformMCPConfig(config: MCPConfigFile, source: SourceMeta): MCPServe
139
230
  return servers;
140
231
  }
141
232
 
233
+ interface ExactMCPConfigIdentity {
234
+ dev: bigint;
235
+ ino: bigint;
236
+ mode: bigint;
237
+ }
238
+
239
+ interface ExactMCPConfigFileState extends ExactMCPConfigIdentity {
240
+ size: bigint;
241
+ mtimeNs: bigint;
242
+ ctimeNs: bigint;
243
+ nlink: bigint;
244
+ }
245
+
246
+ interface ExactMCPConfigPathState {
247
+ ancestors: ExactMCPConfigIdentity[];
248
+ file: ExactMCPConfigFileState;
249
+ }
250
+
251
+ function exactMCPConfigIdentity(stat: fs.BigIntStats): ExactMCPConfigIdentity {
252
+ return {
253
+ dev: stat.dev,
254
+ ino: stat.ino,
255
+ mode: stat.mode,
256
+ };
257
+ }
258
+
259
+ function exactMCPConfigFileState(stat: fs.BigIntStats): ExactMCPConfigFileState | null {
260
+ if (stat.isSymbolicLink() || !stat.isFile() || stat.nlink !== 1n) return null;
261
+ return {
262
+ ...exactMCPConfigIdentity(stat),
263
+ size: stat.size,
264
+ mtimeNs: stat.mtimeNs,
265
+ ctimeNs: stat.ctimeNs,
266
+ nlink: stat.nlink,
267
+ };
268
+ }
269
+
270
+ function exactMCPConfigDirectoryIdentity(stat: fs.BigIntStats): ExactMCPConfigIdentity | null {
271
+ if (stat.isSymbolicLink() || !stat.isDirectory()) return null;
272
+ return exactMCPConfigIdentity(stat);
273
+ }
274
+
275
+ async function exactMCPConfigPathState(filePath: string): Promise<ExactMCPConfigPathState | null> {
276
+ if (!path.isAbsolute(filePath)) return null;
277
+
278
+ const root = path.parse(filePath).root;
279
+ const components = filePath
280
+ .slice(root.length)
281
+ .split(process.platform === "win32" ? /[\\/]+/ : path.sep)
282
+ .filter(component => component.length > 0);
283
+ if (
284
+ root.length === 0 ||
285
+ components.length === 0 ||
286
+ components.some(component => component === "." || component === "..")
287
+ ) {
288
+ return null;
289
+ }
290
+
291
+ let componentPath = root;
292
+ const rootIdentity = exactMCPConfigDirectoryIdentity(await fsPromises.lstat(componentPath, { bigint: true }));
293
+ if (!rootIdentity) return null;
294
+ const ancestors = [rootIdentity];
295
+
296
+ for (const [index, component] of components.entries()) {
297
+ componentPath = path.join(componentPath, component);
298
+ const componentState = await fsPromises.lstat(componentPath, { bigint: true });
299
+ if (index === components.length - 1) {
300
+ const file = exactMCPConfigFileState(componentState);
301
+ return file ? { ancestors, file } : null;
302
+ }
303
+ const directoryIdentity = exactMCPConfigDirectoryIdentity(componentState);
304
+ if (!directoryIdentity) return null;
305
+ ancestors.push(directoryIdentity);
306
+ }
307
+
308
+ return null;
309
+ }
310
+
311
+ function isSameExactMCPConfigIdentity(expected: ExactMCPConfigIdentity, actual: ExactMCPConfigIdentity): boolean {
312
+ return expected.dev === actual.dev && expected.ino === actual.ino && expected.mode === actual.mode;
313
+ }
314
+
315
+ function isSameExactMCPConfigFileState(expected: ExactMCPConfigFileState, actual: ExactMCPConfigFileState): boolean {
316
+ return (
317
+ isSameExactMCPConfigIdentity(expected, actual) &&
318
+ expected.size === actual.size &&
319
+ expected.mtimeNs === actual.mtimeNs &&
320
+ expected.ctimeNs === actual.ctimeNs &&
321
+ expected.nlink === actual.nlink
322
+ );
323
+ }
324
+
325
+ function isSameExactMCPConfigPathState(expected: ExactMCPConfigPathState, actual: ExactMCPConfigPathState): boolean {
326
+ return (
327
+ expected.ancestors.length === actual.ancestors.length &&
328
+ expected.ancestors.every((identity, index) => {
329
+ const actualIdentity = actual.ancestors[index];
330
+ return actualIdentity !== undefined && isSameExactMCPConfigIdentity(identity, actualIdentity);
331
+ }) &&
332
+ isSameExactMCPConfigFileState(expected.file, actual.file)
333
+ );
334
+ }
335
+
336
+ function isExpectedExactMCPConfigReadError(error: unknown): boolean {
337
+ if (!isRecord(error) || typeof error.code !== "string") return false;
338
+ return ["EACCES", "EISDIR", "ELOOP", "ENOENT", "ENAMETOOLONG", "ENOTDIR", "EPERM", "ESTALE"].includes(error.code);
339
+ }
340
+
341
+ async function readExactMCPConfigDescriptorBytes(handle: fsPromises.FileHandle, size: bigint): Promise<Buffer | null> {
342
+ if (size > BigInt(Number.MAX_SAFE_INTEGER)) return null;
343
+
344
+ const bytes = Buffer.allocUnsafe(Number(size));
345
+ let offset = 0;
346
+ while (offset < bytes.length) {
347
+ const { bytesRead } = await handle.read(bytes, offset, bytes.length - offset, offset);
348
+ if (bytesRead === 0) return null;
349
+ offset += bytesRead;
350
+ }
351
+ return bytes;
352
+ }
353
+
354
+ // Windows does not support O_NOFOLLOW. The lstat/fstat checks below remain required there.
355
+ const EXACT_MCP_CONFIG_OPEN_FLAGS =
356
+ fs.constants.O_RDONLY | (process.platform === "win32" ? 0 : (fs.constants.O_NOFOLLOW ?? 0));
357
+
358
+ /**
359
+ * Exact-file trust policy for quiet explicit MCP configs:
360
+ * the supplied absolute path must contain only non-link components before and after reading;
361
+ * the root and every ancestor directory must retain their identities; the leaf must be a regular,
362
+ * non-link file with one link; and one descriptor supplies all content and exact byte revalidation.
363
+ */
364
+ async function readExactMCPConfigFile(filePath: string): Promise<string | null> {
365
+ let handle: fsPromises.FileHandle | undefined;
366
+ let content: string | null = null;
367
+ let primaryFailure: unknown;
368
+ let hasPrimaryFailure = false;
369
+ try {
370
+ const initialPathState = await exactMCPConfigPathState(filePath);
371
+ if (initialPathState) {
372
+ handle = await fsPromises.open(filePath, EXACT_MCP_CONFIG_OPEN_FLAGS);
373
+ const openedFileState = exactMCPConfigFileState(await handle.stat({ bigint: true }));
374
+ const beforeReadPathState = await exactMCPConfigPathState(filePath);
375
+ if (
376
+ openedFileState &&
377
+ beforeReadPathState &&
378
+ isSameExactMCPConfigFileState(initialPathState.file, openedFileState) &&
379
+ isSameExactMCPConfigPathState(initialPathState, beforeReadPathState)
380
+ ) {
381
+ const candidate = await handle.readFile();
382
+ const afterReadFileState = exactMCPConfigFileState(await handle.stat({ bigint: true }));
383
+ const afterReadPathState = await exactMCPConfigPathState(filePath);
384
+ if (
385
+ afterReadFileState &&
386
+ afterReadPathState &&
387
+ isSameExactMCPConfigFileState(initialPathState.file, afterReadFileState) &&
388
+ isSameExactMCPConfigPathState(initialPathState, afterReadPathState)
389
+ ) {
390
+ const revalidated = await readExactMCPConfigDescriptorBytes(handle, initialPathState.file.size);
391
+ const afterRevalidationFileState = exactMCPConfigFileState(await handle.stat({ bigint: true }));
392
+ const afterRevalidationPathState = await exactMCPConfigPathState(filePath);
393
+ if (
394
+ revalidated &&
395
+ candidate.equals(revalidated) &&
396
+ afterRevalidationFileState &&
397
+ afterRevalidationPathState &&
398
+ isSameExactMCPConfigFileState(initialPathState.file, afterRevalidationFileState) &&
399
+ isSameExactMCPConfigPathState(initialPathState, afterRevalidationPathState)
400
+ ) {
401
+ content = candidate.toString("utf8");
402
+ }
403
+ }
404
+ }
405
+ }
406
+ } catch (error) {
407
+ if (!isExpectedExactMCPConfigReadError(error)) {
408
+ hasPrimaryFailure = true;
409
+ primaryFailure = error;
410
+ }
411
+ }
412
+
413
+ let closeFailure: unknown;
414
+ let hasCloseFailure = false;
415
+ if (handle) {
416
+ try {
417
+ await handle.close();
418
+ } catch (error) {
419
+ hasCloseFailure = true;
420
+ closeFailure = error;
421
+ }
422
+ }
423
+ if (hasPrimaryFailure) throw primaryFailure;
424
+ if (hasCloseFailure) throw closeFailure;
425
+ return content;
426
+ }
427
+
142
428
  /**
143
429
  * Load MCP servers from a JSON file.
144
430
  */
145
- async function loadMCPJsonFile(
146
- _ctx: LoadContext,
147
- path: string,
431
+ export async function loadMCPJsonFile(
432
+ filePath: string,
148
433
  level: "user" | "project",
149
- ): Promise<LoadResult<MCPServer>> {
434
+ options?: { quiet?: boolean; useCache?: boolean },
435
+ ): Promise<MCPJsonLoadResult> {
150
436
  const warnings: string[] = [];
151
437
  const items: MCPServer[] = [];
152
438
 
153
- const content = await readFile(path);
439
+ const content = options?.quiet
440
+ ? await readExactMCPConfigFile(filePath)
441
+ : options?.useCache === false
442
+ ? await Bun.file(filePath)
443
+ .text()
444
+ .catch(() => null)
445
+ : await readFile(filePath);
154
446
  if (content === null) {
155
- return { items, warnings };
447
+ if (options?.quiet) warnings.push("MCP configuration unavailable");
448
+ return { items, warnings, disabledServers: [] };
156
449
  }
157
450
 
158
- const config = tryParseJson<MCPConfigFile>(content);
451
+ const config = tryParseJson<unknown>(content);
159
452
  if (!config) {
160
- warnings.push(`Failed to parse JSON in ${path}`);
161
- return { items, warnings };
453
+ warnings.push(options?.quiet ? "MCP configuration unavailable" : `Failed to parse JSON in ${filePath}`);
454
+ return { items, warnings, disabledServers: [] };
162
455
  }
456
+ let validConfig: MCPConfigFile;
457
+ if (options?.quiet) {
458
+ const validation = validateExactMCPConfig(config);
459
+ if (!validation.config) {
460
+ warnings.push("MCP configuration unavailable");
461
+ return { items, warnings, disabledServers: [] };
462
+ }
463
+ if (validation.hasInvalidServer) warnings.push("MCP configuration unavailable");
464
+ validConfig = validation.config;
465
+ } else {
466
+ validConfig = config as MCPConfigFile;
467
+ }
468
+ const source = createSourceMeta(PROVIDER_ID, filePath, level);
469
+ items.push(...transformMCPConfig(validConfig, source, options?.quiet));
163
470
 
164
- const source = createSourceMeta(PROVIDER_ID, path, level);
165
- const servers = transformMCPConfig(config, source);
166
- items.push(...servers);
167
-
168
- return { items, warnings };
471
+ return {
472
+ items,
473
+ warnings,
474
+ disabledServers: isStringArray(validConfig.disabledServers) ? validConfig.disabledServers : [],
475
+ };
169
476
  }
170
477
 
171
478
  /**
@@ -174,7 +481,7 @@ async function loadMCPJsonFile(
174
481
  async function load(ctx: LoadContext): Promise<LoadResult<MCPServer>> {
175
482
  const filenames = ["mcp.json", ".mcp.json"];
176
483
  const results = await Promise.all(
177
- filenames.map(filename => loadMCPJsonFile(ctx, path.join(ctx.cwd, filename), "project")),
484
+ filenames.map(filename => loadMCPJsonFile(path.join(ctx.cwd, filename), "project")),
178
485
  );
179
486
 
180
487
  const allItems = results.flatMap(r => r.items);
@@ -47,7 +47,7 @@ export interface CustomToolAPI {
47
47
  exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
48
48
  /** UI methods for user interaction (select, confirm, input, notify, custom) */
49
49
  ui: CustomToolUIContext;
50
- /** Whether UI is available (false in print/RPC mode) */
50
+ /** Whether an interactive UI is available */
51
51
  hasUI: boolean;
52
52
  /** File logger for error/warning/debug messages */
53
53
  logger: typeof import("@gajae-code/utils").logger;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Extension-facing APIs accept `string | CompactOptions`, but `AgentSession.compact`
5
5
  * takes two positional arguments `(instructions, options)`. This helper splits the
6
- * union so the same adapter can be reused by print-mode, rpc-mode, and the executor.
6
+ * union so the same adapter can be reused by print, SDK, ACP, and executor callers.
7
7
  */
8
8
  import type { Model } from "@gajae-code/ai";
9
9
  import type { CompactOptions } from "./types";
@@ -24,7 +24,7 @@ export async function runExtensionCompact(
24
24
 
25
25
  interface SetModelCapableSession {
26
26
  modelRegistry: { getApiKey(model: Model): Promise<string | undefined> };
27
- setModel(model: Model): Promise<unknown>;
27
+ setModel(model: Model, role?: string, options?: { cause?: string }): Promise<unknown>;
28
28
  }
29
29
 
30
30
  /**
@@ -35,6 +35,6 @@ interface SetModelCapableSession {
35
35
  export async function runExtensionSetModel(session: SetModelCapableSession, model: Model): Promise<boolean> {
36
36
  const key = await session.modelRegistry.getApiKey(model);
37
37
  if (!key) return false;
38
- await session.setModel(model);
38
+ await session.setModel(model, "default", { cause: "user-selection" });
39
39
  return true;
40
40
  }
@@ -2,8 +2,8 @@
2
2
  * Helper for wiring the `getCommands` action of {@link ExtensionAPI}.
3
3
  *
4
4
  * Centralizes the union over the three slash-command sources the runtime
5
- * exposes so the five wiring sites (interactive UI, ACP, RPC, print, child
6
- * task executor) cannot drift:
5
+ * exposes so the interactive UI, ACP, SDK, print, and child task executor wiring
6
+ * sites cannot drift:
7
7
  * - extension-registered hook commands (`source: "extension"`)
8
8
  * - prompt commands loaded as `LoadedCustomCommand` — user/project/bundled
9
9
  * custom commands and MCP prompts (`source: "prompt"`)
@@ -5,7 +5,7 @@ import type * as fs1 from "node:fs";
5
5
  import * as fs from "node:fs/promises";
6
6
  import * as path from "node:path";
7
7
  import type { ThinkingLevel } from "@gajae-code/agent-core";
8
- import type { ImageContent, Model, TextContent } from "@gajae-code/ai";
8
+ import type { ImageContent, Model, TextContent, UsageReport } from "@gajae-code/ai";
9
9
  import type { KeyId } from "@gajae-code/tui";
10
10
  import { hasFsCode, isEacces, isEnoent, logger } from "@gajae-code/utils";
11
11
  import * as Zod from "zod/v4";
@@ -62,7 +62,7 @@ export class ExtensionRuntime implements IExtensionRuntime {
62
62
  throw new ExtensionRuntimeNotInitializedError();
63
63
  }
64
64
 
65
- sendUserMessage(): void {
65
+ sendUserMessage(): Promise<void> {
66
66
  throw new ExtensionRuntimeNotInitializedError();
67
67
  }
68
68
 
@@ -102,6 +102,38 @@ export class ExtensionRuntime implements IExtensionRuntime {
102
102
  throw new ExtensionRuntimeNotInitializedError();
103
103
  }
104
104
 
105
+ getThinkingVisibility(): "visible" | "hidden" {
106
+ throw new ExtensionRuntimeNotInitializedError();
107
+ }
108
+
109
+ setThinkingVisibility(): void {
110
+ throw new ExtensionRuntimeNotInitializedError();
111
+ }
112
+
113
+ cycleThinkingLevel(): ThinkingLevel | undefined {
114
+ throw new ExtensionRuntimeNotInitializedError();
115
+ }
116
+
117
+ setThinkingLevelForControl(): Promise<void> {
118
+ throw new ExtensionRuntimeNotInitializedError();
119
+ }
120
+
121
+ setThinkingVisibilityForControl(): Promise<void> {
122
+ throw new ExtensionRuntimeNotInitializedError();
123
+ }
124
+
125
+ setModelTemporaryForControl(): Promise<boolean> {
126
+ throw new ExtensionRuntimeNotInitializedError();
127
+ }
128
+
129
+ fetchUsageReportsForControl(): Promise<UsageReport[] | null> {
130
+ throw new ExtensionRuntimeNotInitializedError();
131
+ }
132
+
133
+ getThinkingScopeForControl(): "session" | "global config" {
134
+ throw new ExtensionRuntimeNotInitializedError();
135
+ }
136
+
105
137
  getSessionName(): string | undefined {
106
138
  throw new ExtensionRuntimeNotInitializedError();
107
139
  }
@@ -204,9 +236,9 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
204
236
 
205
237
  sendUserMessage(
206
238
  content: string | (TextContent | ImageContent)[],
207
- options?: { deliverAs?: "steer" | "followUp" },
208
- ): void {
209
- this.runtime.sendUserMessage(content, options);
239
+ options?: { deliverAs?: "steer" | "followUp"; onPreflightAccepted?: () => void },
240
+ ): Promise<void> {
241
+ return Promise.resolve(this.runtime.sendUserMessage(content, options));
210
242
  }
211
243
 
212
244
  appendEntry(customType: string, data?: unknown): void {
@@ -245,6 +277,38 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
245
277
  this.runtime.setThinkingLevel(level, persist);
246
278
  }
247
279
 
280
+ getThinkingVisibility(): "visible" | "hidden" {
281
+ return this.runtime.getThinkingVisibility();
282
+ }
283
+
284
+ setThinkingVisibility(visibility: "visible" | "hidden", persist?: boolean): void {
285
+ this.runtime.setThinkingVisibility(visibility, persist);
286
+ }
287
+
288
+ cycleThinkingLevel(): ThinkingLevel | undefined {
289
+ return this.runtime.cycleThinkingLevel();
290
+ }
291
+
292
+ setThinkingLevelForControl(level: ThinkingLevel, persist: boolean): Promise<void> {
293
+ return this.runtime.setThinkingLevelForControl(level, persist);
294
+ }
295
+
296
+ setThinkingVisibilityForControl(visibility: "visible" | "hidden", persist: boolean): Promise<void> {
297
+ return this.runtime.setThinkingVisibilityForControl(visibility, persist);
298
+ }
299
+
300
+ setModelTemporaryForControl(model: Model, expectedSessionId?: string): Promise<boolean> {
301
+ return this.runtime.setModelTemporaryForControl(model, expectedSessionId);
302
+ }
303
+
304
+ fetchUsageReportsForControl(): Promise<UsageReport[] | null> {
305
+ return this.runtime.fetchUsageReportsForControl();
306
+ }
307
+
308
+ getThinkingScopeForControl(): "session" | "global config" {
309
+ return this.runtime.getThinkingScopeForControl();
310
+ }
311
+
248
312
  getSessionName(): string | undefined {
249
313
  return this.runtime.getSessionName();
250
314
  }