@gajae-code/coding-agent 0.13.2 → 0.14.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 (610) hide show
  1. package/CHANGELOG.md +215 -8
  2. package/README.md +2 -0
  3. package/bin/gajaessi.js +4 -0
  4. package/dist/types/async/job-manager.d.ts +55 -2
  5. package/dist/types/async/support.d.ts +14 -0
  6. package/dist/types/capability/mcp.d.ts +6 -0
  7. package/dist/types/capability/types.d.ts +6 -0
  8. package/dist/types/cli/accounts-cli.d.ts +19 -0
  9. package/dist/types/cli/args.d.ts +3 -0
  10. package/dist/types/cli/config-cli.d.ts +6 -0
  11. package/dist/types/cli/crash-cli.d.ts +10 -0
  12. package/dist/types/cli/customize-doctor.d.ts +145 -0
  13. package/dist/types/cli/daemon-cli.d.ts +3 -1
  14. package/dist/types/cli/mcp-cli.d.ts +11 -0
  15. package/dist/types/cli/notify-cli.d.ts +1 -1
  16. package/dist/types/cli/root-flags.d.ts +12 -0
  17. package/dist/types/cli/setup-cli.d.ts +3 -1
  18. package/dist/types/cli/skills-cli.d.ts +2 -1
  19. package/dist/types/cli/update-cli.d.ts +19 -1
  20. package/dist/types/cli.d.ts +6 -0
  21. package/dist/types/commands/accounts.d.ts +40 -0
  22. package/dist/types/commands/crash.d.ts +24 -0
  23. package/dist/types/commands/customize.d.ts +22 -0
  24. package/dist/types/commands/daemon.d.ts +1 -1
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/commands/setup.d.ts +6 -0
  27. package/dist/types/commands/skills.d.ts +6 -1
  28. package/dist/types/commands/update.d.ts +7 -0
  29. package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
  30. package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
  31. package/dist/types/config/config-schema-version.d.ts +10 -0
  32. package/dist/types/config/file-lock.d.ts +18 -0
  33. package/dist/types/config/model-profile-activation.d.ts +3 -1
  34. package/dist/types/config/model-registry.d.ts +10 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +73 -9
  37. package/dist/types/config/settings.d.ts +63 -0
  38. package/dist/types/config/skill-settings-defaults.d.ts +26 -0
  39. package/dist/types/config/task-delegation.d.ts +39 -0
  40. package/dist/types/config/update-channel.d.ts +10 -0
  41. package/dist/types/coordinator-mcp/server.d.ts +5 -1
  42. package/dist/types/crash/index-store.d.ts +87 -0
  43. package/dist/types/crash/nudge.d.ts +50 -0
  44. package/dist/types/crash/record-loader.d.ts +17 -0
  45. package/dist/types/crash/report.d.ts +134 -0
  46. package/dist/types/crash/sanitize.d.ts +25 -0
  47. package/dist/types/cursor.d.ts +13 -2
  48. package/dist/types/customization/import.d.ts +37 -0
  49. package/dist/types/customization/index.d.ts +4 -0
  50. package/dist/types/customization/inventory.d.ts +25 -0
  51. package/dist/types/customization/mutations.d.ts +32 -0
  52. package/dist/types/customization/types.d.ts +115 -0
  53. package/dist/types/daemon/control-types.d.ts +8 -1
  54. package/dist/types/daemon/operator-contract.d.ts +4 -4
  55. package/dist/types/discovery/claude.d.ts +39 -1
  56. package/dist/types/discovery/codex.d.ts +39 -1
  57. package/dist/types/discovery/index.d.ts +2 -0
  58. package/dist/types/discovery/mcp-compat.d.ts +30 -0
  59. package/dist/types/edit/renderer.d.ts +23 -0
  60. package/dist/types/extensibility/extensions/runner.d.ts +3 -0
  61. package/dist/types/extensibility/extensions/types.d.ts +21 -4
  62. package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
  63. package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
  64. package/dist/types/extensibility/hooks/loader.d.ts +19 -5
  65. package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
  66. package/dist/types/extensibility/skill-management.d.ts +107 -0
  67. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
  68. package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
  69. package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
  70. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
  71. package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
  72. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
  73. package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
  74. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
  75. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
  76. package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
  77. package/dist/types/hooks/events.d.ts +60 -0
  78. package/dist/types/hooks/normalize.d.ts +83 -0
  79. package/dist/types/hooks/skill-state.d.ts +9 -2
  80. package/dist/types/main.d.ts +2 -1
  81. package/dist/types/modes/acp/abort-scope.d.ts +13 -0
  82. package/dist/types/modes/acp/acp-agent.d.ts +7 -4
  83. package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
  84. package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
  85. package/dist/types/modes/components/customization/index.d.ts +1 -0
  86. package/dist/types/modes/components/dynamic-theme-text.d.ts +9 -0
  87. package/dist/types/modes/components/gajae-pet-widget.d.ts +6 -28
  88. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  89. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  90. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  91. package/dist/types/modes/components/pet-capability.d.ts +7 -21
  92. package/dist/types/modes/components/settings-selector.d.ts +5 -0
  93. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  94. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  95. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  96. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  97. package/dist/types/modes/interactive-mode.d.ts +1 -0
  98. package/dist/types/modes/theme/defaults/index.d.ts +118 -0
  99. package/dist/types/modes/types.d.ts +1 -0
  100. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  101. package/dist/types/runtime-mcp/config.d.ts +9 -0
  102. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  103. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  104. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  105. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  106. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  107. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  108. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  109. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  110. package/dist/types/runtime-mcp/types.d.ts +102 -10
  111. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  112. package/dist/types/sdk/broker/broker.d.ts +3 -55
  113. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  114. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  115. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  116. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  117. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  118. package/dist/types/sdk/bus/config.d.ts +11 -0
  119. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  120. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  121. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  122. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  123. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  124. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  125. package/dist/types/sdk/bus/index.d.ts +85 -99
  126. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  127. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  128. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  129. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  130. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  131. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  132. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  133. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  135. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  136. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  137. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  138. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  139. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  140. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  141. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  142. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  143. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  144. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  145. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  146. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  147. package/dist/types/sdk/cli/rows.d.ts +2 -11
  148. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  149. package/dist/types/sdk/client/client.d.ts +97 -1
  150. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  151. package/dist/types/sdk/host/control/index.d.ts +1 -1
  152. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  153. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  154. package/dist/types/sdk/host/host.d.ts +15 -1
  155. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  156. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  157. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  158. package/dist/types/sdk/host/types.d.ts +1 -1
  159. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  160. package/dist/types/sdk/index.d.ts +2 -1
  161. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  162. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  163. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  164. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  165. package/dist/types/sdk/mcp/server.d.ts +9 -6
  166. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  167. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  168. package/dist/types/sdk/prompt-status.d.ts +10 -3
  169. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  170. package/dist/types/sdk/receipt-state.d.ts +17 -0
  171. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  172. package/dist/types/sdk/router/index.d.ts +1 -0
  173. package/dist/types/sdk/router/session-router.d.ts +152 -0
  174. package/dist/types/sdk/session-list.d.ts +22 -0
  175. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  176. package/dist/types/sdk/session.d.ts +34 -1
  177. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  178. package/dist/types/session/account-inventory.d.ts +86 -0
  179. package/dist/types/session/agent-session.d.ts +145 -6
  180. package/dist/types/session/agent-storage.d.ts +10 -0
  181. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  182. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  183. package/dist/types/session/messages.d.ts +1 -1
  184. package/dist/types/session/secure-token-file.d.ts +3 -0
  185. package/dist/types/session/session-manager.d.ts +47 -1
  186. package/dist/types/session/startup-auth-config.d.ts +44 -0
  187. package/dist/types/session/terminal-abort.d.ts +378 -0
  188. package/dist/types/session/yield-queue.d.ts +7 -0
  189. package/dist/types/session-import/claude.d.ts +26 -0
  190. package/dist/types/session-import/codex.d.ts +88 -0
  191. package/dist/types/session-import/command.d.ts +35 -0
  192. package/dist/types/session-import/detect.d.ts +22 -0
  193. package/dist/types/session-import/index.d.ts +7 -0
  194. package/dist/types/session-import/provider-codex.d.ts +22 -0
  195. package/dist/types/session-import/provider-service.d.ts +38 -0
  196. package/dist/types/session-import/redact.d.ts +23 -0
  197. package/dist/types/session-import/service.d.ts +47 -0
  198. package/dist/types/session-import/types.d.ts +120 -0
  199. package/dist/types/setup/paseo/check.d.ts +16 -0
  200. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  201. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  202. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  203. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  204. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  205. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  206. package/dist/types/setup/paseo/remove.d.ts +14 -0
  207. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  208. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  209. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  210. package/dist/types/skill-state/active-state.d.ts +5 -1
  211. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  212. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  213. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  214. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  215. package/dist/types/slash-commands/types.d.ts +7 -1
  216. package/dist/types/task/executor.d.ts +10 -0
  217. package/dist/types/task/index.d.ts +3 -1
  218. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  219. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  220. package/dist/types/tools/bash.d.ts +2 -6
  221. package/dist/types/tools/browser/attach.d.ts +11 -0
  222. package/dist/types/tools/browser/launch.d.ts +20 -0
  223. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  224. package/dist/types/tools/browser/render.d.ts +1 -0
  225. package/dist/types/tools/browser.d.ts +3 -1
  226. package/dist/types/tools/image-gen.d.ts +10 -2
  227. package/dist/types/tools/index.d.ts +8 -0
  228. package/dist/types/tools/monitor.d.ts +1 -1
  229. package/dist/types/tools/skill-discovery.d.ts +8 -1
  230. package/dist/types/tools/subagent.d.ts +2 -0
  231. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  232. package/dist/types/utils/herdr-pane.d.ts +76 -0
  233. package/package.json +19 -9
  234. package/scripts/build-binary.ts +2 -1
  235. package/scripts/build-sdk-package-smoke.ts +2 -13
  236. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  237. package/scripts/compile-args.ts +2 -0
  238. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  239. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  240. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  241. package/scripts/generate-tool-catalog.ts +6 -4
  242. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  243. package/src/async/job-manager.ts +352 -17
  244. package/src/async/support.ts +25 -0
  245. package/src/autoresearch/dashboard.ts +28 -13
  246. package/src/capability/index.ts +3 -1
  247. package/src/capability/mcp.ts +6 -0
  248. package/src/capability/types.ts +6 -0
  249. package/src/cli/accounts-cli.ts +395 -0
  250. package/src/cli/args.ts +23 -0
  251. package/src/cli/auth-broker-cli.ts +136 -66
  252. package/src/cli/auth-gateway-cli.ts +94 -70
  253. package/src/cli/config-cli.ts +27 -2
  254. package/src/cli/crash-cli.ts +78 -0
  255. package/src/cli/customize-doctor.ts +1605 -0
  256. package/src/cli/daemon-cli.ts +12 -3
  257. package/src/cli/fast-help.ts +1 -0
  258. package/src/cli/mcp-cli.ts +128 -60
  259. package/src/cli/notify-cli.ts +8 -14
  260. package/src/cli/root-flags.ts +8 -0
  261. package/src/cli/setup-cli.ts +145 -0
  262. package/src/cli/skills-cli.ts +38 -2
  263. package/src/cli/update-cli.ts +167 -12
  264. package/src/cli.ts +4 -0
  265. package/src/commands/accounts.ts +71 -0
  266. package/src/commands/crash.ts +35 -0
  267. package/src/commands/customize.ts +84 -0
  268. package/src/commands/daemon.ts +2 -2
  269. package/src/commands/deep-interview.ts +2 -0
  270. package/src/commands/launch.ts +1 -0
  271. package/src/commands/mcp.ts +12 -7
  272. package/src/commands/ralplan.ts +2 -0
  273. package/src/commands/sdk.ts +65 -32
  274. package/src/commands/setup.ts +5 -0
  275. package/src/commands/skills.ts +14 -4
  276. package/src/commands/ultragoal.ts +10 -1
  277. package/src/commands/update.ts +26 -15
  278. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  279. package/src/config/atomic-yaml-patch.ts +769 -29
  280. package/src/config/config-schema-version.ts +10 -0
  281. package/src/config/file-lock.ts +70 -1
  282. package/src/config/mcp-schema.json +52 -14
  283. package/src/config/model-profile-activation.ts +23 -2
  284. package/src/config/model-profiles.ts +88 -21
  285. package/src/config/model-registry.ts +147 -21
  286. package/src/config/models-config-schema.ts +1 -1
  287. package/src/config/settings-schema.ts +77 -7
  288. package/src/config/settings.ts +4038 -199
  289. package/src/config/skill-settings-defaults.ts +41 -3
  290. package/src/config/task-delegation.ts +87 -0
  291. package/src/config/update-channel.ts +23 -0
  292. package/src/coordinator-mcp/server.ts +377 -308
  293. package/src/crash/index-store.ts +723 -0
  294. package/src/crash/nudge.ts +89 -0
  295. package/src/crash/record-loader.ts +149 -0
  296. package/src/crash/report.ts +551 -0
  297. package/src/crash/sanitize.ts +129 -0
  298. package/src/cursor.ts +36 -10
  299. package/src/customization/import.ts +946 -0
  300. package/src/customization/index.ts +4 -0
  301. package/src/customization/inventory.ts +335 -0
  302. package/src/customization/mutations.ts +141 -0
  303. package/src/customization/types.ts +223 -0
  304. package/src/daemon/control-types.ts +8 -1
  305. package/src/daemon/operator-contract.ts +6 -6
  306. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +31 -6
  307. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  308. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  309. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  310. package/src/discovery/claude-hooks.ts +38 -0
  311. package/src/discovery/claude.ts +142 -209
  312. package/src/discovery/codex-hooks.ts +38 -0
  313. package/src/discovery/codex.ts +132 -198
  314. package/src/discovery/helpers.ts +8 -1
  315. package/src/discovery/index.ts +2 -0
  316. package/src/discovery/mcp-compat.ts +234 -0
  317. package/src/discovery/mcp-json.ts +6 -0
  318. package/src/edit/renderer.ts +40 -0
  319. package/src/edit/streaming.ts +4 -2
  320. package/src/exec/bash-executor.ts +24 -20
  321. package/src/export/html/index.ts +51 -2
  322. package/src/extensibility/extensions/loader.ts +9 -1
  323. package/src/extensibility/extensions/runner.ts +17 -4
  324. package/src/extensibility/extensions/types.ts +31 -6
  325. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  326. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  327. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  328. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  329. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  330. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  331. package/src/extensibility/hooks/loader.ts +154 -10
  332. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  333. package/src/extensibility/skill-management.ts +368 -0
  334. package/src/extensibility/skills.ts +52 -16
  335. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  336. package/src/gjc-runtime/launch-worktree.ts +56 -2
  337. package/src/gjc-runtime/linux-proc.ts +7 -1
  338. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  339. package/src/gjc-runtime/session-state-lock.ts +992 -0
  340. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  341. package/src/gjc-runtime/state-writer.ts +39 -14
  342. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  343. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  344. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  345. package/src/gjc-runtime/workflow-settings.ts +596 -0
  346. package/src/goals/tools/goal-tool.ts +6 -1
  347. package/src/hooks/events.ts +291 -0
  348. package/src/hooks/native-skill-hook.ts +4 -0
  349. package/src/hooks/normalize.ts +369 -0
  350. package/src/hooks/skill-state.ts +165 -46
  351. package/src/internal-urls/docs-index.generated.ts +41 -32
  352. package/src/main.ts +36 -5
  353. package/src/migrate/mcp-mapper.ts +25 -2
  354. package/src/modes/acp/abort-scope.ts +29 -0
  355. package/src/modes/acp/acp-agent.ts +423 -98
  356. package/src/modes/components/assistant-message.ts +6 -1
  357. package/src/modes/components/chrome.ts +4 -3
  358. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  359. package/src/modes/components/customization/import-wizard.ts +372 -0
  360. package/src/modes/components/customization/index.ts +1 -0
  361. package/src/modes/components/dynamic-theme-text.ts +22 -0
  362. package/src/modes/components/gajae-pet-widget.ts +607 -193
  363. package/src/modes/components/irc-sidebar.ts +11 -0
  364. package/src/modes/components/iterm-pet-transport.ts +585 -0
  365. package/src/modes/components/model-selector.ts +1 -6
  366. package/src/modes/components/oauth-selector.ts +277 -86
  367. package/src/modes/components/pet-capability.ts +35 -31
  368. package/src/modes/components/settings-selector.ts +29 -5
  369. package/src/modes/components/status-line/gh.ts +45 -1
  370. package/src/modes/components/status-line/segments.ts +19 -4
  371. package/src/modes/components/tool-status-header.ts +13 -3
  372. package/src/modes/controllers/command-controller.ts +20 -8
  373. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  374. package/src/modes/controllers/input-controller.ts +10 -0
  375. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  376. package/src/modes/controllers/selector-controller.ts +238 -77
  377. package/src/modes/controllers/stt-controller.ts +3 -3
  378. package/src/modes/interactive-mode.ts +88 -16
  379. package/src/modes/print-mode.ts +35 -6
  380. package/src/modes/runtime-init.ts +21 -68
  381. package/src/modes/theme/defaults/index.ts +2 -0
  382. package/src/modes/theme/defaults/ouroboros.json +118 -0
  383. package/src/modes/types.ts +1 -0
  384. package/src/modes/utils/injected-user-submission.ts +25 -0
  385. package/src/modes/utils/terminal-bell.ts +15 -1
  386. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  387. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  388. package/src/prompts/agents/critic.md +1 -1
  389. package/src/prompts/system/rlm-research.md +1 -1
  390. package/src/prompts/system/system-prompt.md +0 -2
  391. package/src/prompts/tools/bash.md +7 -1
  392. package/src/prompts/tools/browser.md +1 -1
  393. package/src/prompts/tools/cron.md +6 -6
  394. package/src/prompts/tools/read.md +0 -2
  395. package/src/prompts/tools/skill-discovery.md +4 -2
  396. package/src/runtime-mcp/client.ts +427 -23
  397. package/src/runtime-mcp/config.ts +37 -5
  398. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  399. package/src/runtime-mcp/manager.ts +52 -2
  400. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  401. package/src/runtime-mcp/oauth-flow.ts +46 -1
  402. package/src/runtime-mcp/pool-key.ts +5 -1
  403. package/src/runtime-mcp/pool.test.ts +9 -0
  404. package/src/runtime-mcp/protocol.test.ts +353 -0
  405. package/src/runtime-mcp/protocol.ts +624 -0
  406. package/src/runtime-mcp/scope-config.ts +78 -0
  407. package/src/runtime-mcp/tool-bridge.ts +44 -10
  408. package/src/runtime-mcp/transports/http.ts +84 -13
  409. package/src/runtime-mcp/types.ts +123 -12
  410. package/src/sdk/acp/adapter.ts +328 -97
  411. package/src/sdk/broker/broker.ts +160 -741
  412. package/src/sdk/broker/ensure.ts +9 -1
  413. package/src/sdk/broker/lifecycle.ts +510 -116
  414. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  415. package/src/sdk/broker/process-incarnation.ts +19 -0
  416. package/src/sdk/broker/session-index.ts +516 -117
  417. package/src/sdk/broker/startup-failure.ts +28 -5
  418. package/src/sdk/broker/transport.ts +1 -13
  419. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  420. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  421. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  422. package/src/sdk/bus/config.ts +13 -0
  423. package/src/sdk/bus/conversation-store.ts +59 -171
  424. package/src/sdk/bus/daemon-paths.ts +20 -0
  425. package/src/sdk/bus/discord-conversation.ts +2 -0
  426. package/src/sdk/bus/discord-daemon.ts +524 -126
  427. package/src/sdk/bus/discord-live-provider.ts +206 -79
  428. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  429. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  430. package/src/sdk/bus/index.ts +2480 -456
  431. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  432. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  433. package/src/sdk/bus/managed-daemon.ts +2 -145
  434. package/src/sdk/bus/notification-service.ts +196 -0
  435. package/src/sdk/bus/operator-runtime.ts +1 -1
  436. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  437. package/src/sdk/bus/reconciliation-store.ts +553 -24
  438. package/src/sdk/bus/session-control.ts +49 -3
  439. package/src/sdk/bus/slack-conversation.ts +4 -0
  440. package/src/sdk/bus/slack-daemon.ts +733 -134
  441. package/src/sdk/bus/slack-live-provider.ts +65 -15
  442. package/src/sdk/bus/slack-provider.ts +4 -0
  443. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  444. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  445. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  446. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  447. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  448. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  449. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  450. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  451. package/src/sdk/bus/telegram-reference.ts +1 -226
  452. package/src/sdk/bus/telegram-setup.ts +2 -2
  453. package/src/sdk/bus/threaded-render.ts +1 -0
  454. package/src/sdk/bus/topic-registry.ts +279 -146
  455. package/src/sdk/cli/rows.ts +2 -35
  456. package/src/sdk/cli/session-cli.ts +776 -700
  457. package/src/sdk/client/client.ts +892 -1
  458. package/src/sdk/host/control/dispatch.ts +93 -58
  459. package/src/sdk/host/control/index.ts +1 -1
  460. package/src/sdk/host/control/operations.ts +18 -10
  461. package/src/sdk/host/control/runtime-gate.ts +40 -0
  462. package/src/sdk/host/host.ts +63 -12
  463. package/src/sdk/host/query/handlers.ts +66 -7
  464. package/src/sdk/host/reverse-leases.ts +2 -2
  465. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  466. package/src/sdk/host/session-runtime.test.ts +2787 -34
  467. package/src/sdk/host/session-runtime.ts +1489 -101
  468. package/src/sdk/host/surface-policy.ts +12 -8
  469. package/src/sdk/host/types.ts +1 -1
  470. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  471. package/src/sdk/host/websocket-transport.ts +85 -50
  472. package/src/sdk/index.ts +2 -1
  473. package/src/sdk/lifecycle/broker-client.ts +53 -0
  474. package/src/sdk/lifecycle/client.ts +234 -0
  475. package/src/sdk/lifecycle/index.ts +3 -0
  476. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  477. package/src/sdk/lifecycle/service.ts +720 -0
  478. package/src/sdk/mcp/server.ts +226 -188
  479. package/src/sdk/prompt-deadline-lease.ts +55 -0
  480. package/src/sdk/prompt-deadline-manager.ts +148 -0
  481. package/src/sdk/prompt-status.ts +11 -3
  482. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  483. package/src/sdk/protocol/operation-registry.ts +71 -8
  484. package/src/sdk/receipt-state.ts +43 -0
  485. package/src/sdk/reconciliation-extensions.ts +14 -0
  486. package/src/sdk/router/index.ts +1 -0
  487. package/src/sdk/router/session-router.ts +1658 -0
  488. package/src/sdk/session-list.ts +93 -0
  489. package/src/sdk/session-reconnect.ts +45 -1
  490. package/src/sdk/session.ts +716 -120
  491. package/src/sdk/transport/serve-cli.ts +18 -34
  492. package/src/session/account-inventory.ts +603 -0
  493. package/src/session/agent-session.ts +2873 -559
  494. package/src/session/agent-storage.ts +35 -0
  495. package/src/session/blob-store.ts +32 -1
  496. package/src/session/coordinator-tool-label.ts +40 -0
  497. package/src/session/internal/managed-session-scope.ts +4 -0
  498. package/src/session/internal/managed-session-storage.ts +199 -31
  499. package/src/session/messages.ts +1 -1
  500. package/src/session/secure-token-file.ts +80 -0
  501. package/src/session/session-manager.ts +757 -57
  502. package/src/session/session-storage.ts +25 -16
  503. package/src/session/startup-auth-config.ts +297 -0
  504. package/src/session/terminal-abort.ts +1253 -0
  505. package/src/session/yield-queue.ts +57 -15
  506. package/src/session-import/claude.ts +334 -0
  507. package/src/session-import/codex.ts +1033 -0
  508. package/src/session-import/command.ts +77 -0
  509. package/src/session-import/detect.ts +133 -0
  510. package/src/session-import/index.ts +7 -0
  511. package/src/session-import/provider-codex.ts +327 -0
  512. package/src/session-import/provider-service.ts +457 -0
  513. package/src/session-import/redact.ts +128 -0
  514. package/src/session-import/service.ts +1264 -0
  515. package/src/session-import/types.ts +148 -0
  516. package/src/setup/paseo/check.ts +213 -0
  517. package/src/setup/paseo/install-saga.ts +293 -0
  518. package/src/setup/paseo/json-publisher.ts +263 -0
  519. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  520. package/src/setup/paseo/paseo-ownership.ts +224 -0
  521. package/src/setup/paseo/paseo-setup.ts +253 -0
  522. package/src/setup/paseo/provider-config.ts +139 -0
  523. package/src/setup/paseo/remove.ts +183 -0
  524. package/src/setup/paseo/result-types.ts +79 -0
  525. package/src/setup/paseo/setup-deps.ts +175 -0
  526. package/src/setup/paseo/skills-bridge.ts +260 -0
  527. package/src/skill-state/active-state.ts +21 -11
  528. package/src/slash-commands/acp-builtins.ts +9 -1
  529. package/src/slash-commands/builtin-registry.ts +117 -19
  530. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  531. package/src/slash-commands/helpers/mcp.ts +9 -3
  532. package/src/slash-commands/helpers/usage-report.ts +61 -56
  533. package/src/slash-commands/types.ts +7 -2
  534. package/src/task/executor.ts +30 -11
  535. package/src/task/index.ts +66 -7
  536. package/src/task/render.ts +23 -9
  537. package/src/tools/ask-answer-registry.ts +23 -7
  538. package/src/tools/ask.ts +8 -4
  539. package/src/tools/bash-sleep-advisory.ts +115 -0
  540. package/src/tools/bash.ts +98 -18
  541. package/src/tools/browser/attach.ts +71 -3
  542. package/src/tools/browser/launch.ts +86 -13
  543. package/src/tools/browser/profile-discovery.ts +57 -7
  544. package/src/tools/browser/render.ts +8 -1
  545. package/src/tools/browser.ts +130 -21
  546. package/src/tools/computer.enforcement.test.ts +1 -1
  547. package/src/tools/computer.ts +3 -2
  548. package/src/tools/cron.ts +12 -1
  549. package/src/tools/image-gen.ts +349 -142
  550. package/src/tools/index.ts +8 -0
  551. package/src/tools/job.ts +33 -6
  552. package/src/tools/monitor.ts +41 -2
  553. package/src/tools/skill-discovery.ts +21 -29
  554. package/src/tools/subagent.ts +142 -24
  555. package/src/tools/todo-contract.ts +55 -3
  556. package/src/tools/todo-write.ts +4 -3
  557. package/src/tools/tool-catalog.generated.ts +6 -6
  558. package/src/tools/ultragoal-ask-guard.ts +10 -3
  559. package/src/utils/herdr-pane.ts +345 -0
  560. package/src/utils/title-generator.ts +2 -0
  561. package/src/web/scrapers/index.ts +6 -4
  562. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  563. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  564. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  565. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  566. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  567. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  568. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  569. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  570. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  571. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  572. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  573. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  574. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  575. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  576. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  577. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  578. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  579. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  580. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  581. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  582. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  583. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  584. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  585. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  586. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  587. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  588. package/dist/types/session/auth-broker-config.d.ts +0 -13
  589. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  590. package/dist/types/skills/skills.test.d.ts +0 -1
  591. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  592. package/dist/types/task/token-log.test.d.ts +0 -1
  593. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  594. package/dist/types/tools/descriptors.test.d.ts +0 -1
  595. package/scripts/g005-daemon-smoke.ts +0 -180
  596. package/scripts/g011-daemon-path-smoke.ts +0 -153
  597. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  598. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  599. package/src/sdk/bus/telegram-cli.ts +0 -212
  600. package/src/sdk/elevation/allowlist.ts +0 -54
  601. package/src/sdk/elevation/audit.ts +0 -208
  602. package/src/sdk/elevation/capability.ts +0 -41
  603. package/src/sdk/elevation/digest.ts +0 -129
  604. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  605. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  606. package/src/sdk/elevation/owner.ts +0 -109
  607. package/src/session/auth-broker-config.ts +0 -109
  608. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  609. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  610. /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
@@ -41,6 +41,124 @@ const IMAGE_REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
41
41
  const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
42
42
  const OPENAI_IMAGE_OUTPUT_FORMAT = "webp";
43
43
  const OPENAI_IMAGE_MIME_TYPE = "image/webp";
44
+ const MAX_PROVIDER_TEXT_LENGTH = 4096;
45
+ const REDACTED_PROVIDER_SECRET = "[redacted]";
46
+ const MAX_PROVIDER_BODY_BYTES = 64 * 1024 * 1024;
47
+ const MAX_PROVIDER_SSE_EVENT_BYTES = MAX_PROVIDER_BODY_BYTES;
48
+ const PROVIDER_MALFORMED_RESPONSE = "Provider returned a malformed image response.";
49
+ const PROVIDER_OVERSIZED_RESPONSE = "Provider image response exceeded the supported size.";
50
+
51
+ function escapeRegExp(value: string): string {
52
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53
+ }
54
+
55
+ export function redactImageProviderText(value: unknown, activeApiKey?: string): string {
56
+ let text = typeof value === "string" ? value : value === undefined || value === null ? "" : String(value);
57
+ const key = activeApiKey?.trim();
58
+ if (key) {
59
+ text = text.replace(new RegExp(escapeRegExp(key), "g"), REDACTED_PROVIDER_SECRET);
60
+ const keyChars = [...key].filter(character => !/[\s\p{Cc}\p{Cf}]/u.test(character));
61
+ if (keyChars.length > 0) {
62
+ const separatorTolerantKey = keyChars.map(escapeRegExp).join("[\\s\\p{Cc}\\p{Cf}]*");
63
+ text = text.replace(new RegExp(separatorTolerantKey, "gu"), REDACTED_PROVIDER_SECRET);
64
+ }
65
+ }
66
+ text = text.replace(/[\p{Cc}\p{Cf}]/gu, " ");
67
+ text = text
68
+ .replace(/\b(?:bearer|basic)\s+[^\s,;]+/gi, match => `${match.split(/\s+/, 1)[0]} ${REDACTED_PROVIDER_SECRET}`)
69
+ .replace(
70
+ /(?:\b|["'])(?:authorization|api[-_ ]?key|access[-_ ]?token|refresh[-_ ]?token|token)["']?\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;}]+)/gi,
71
+ match => match.replace(/([:=]\s*).*/, `$1${REDACTED_PROVIDER_SECRET}`),
72
+ )
73
+ .replace(/\b(?:sk|rk|pk|sess|ghp|gho|github_pat|xox[baprs])-[-A-Za-z0-9._]{8,}\b/gi, REDACTED_PROVIDER_SECRET)
74
+ .replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, REDACTED_PROVIDER_SECRET)
75
+ .replace(/\b[A-Za-z0-9+/_-]{40,}={0,2}\b/g, REDACTED_PROVIDER_SECRET);
76
+ return text.length > MAX_PROVIDER_TEXT_LENGTH ? `${text.slice(0, MAX_PROVIDER_TEXT_LENGTH - 1)}…` : text;
77
+ }
78
+
79
+ function tryParseProviderJson<T>(rawText: string): T | undefined {
80
+ if (Buffer.byteLength(rawText, "utf8") > MAX_PROVIDER_BODY_BYTES) return undefined;
81
+ try {
82
+ const parsed: unknown = JSON.parse(rawText);
83
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? (parsed as T) : undefined;
84
+ } catch {
85
+ return undefined;
86
+ }
87
+ }
88
+
89
+ function parseProviderJson<T>(rawText: string, activeApiKey?: string): T {
90
+ const parsed = tryParseProviderJson<T>(rawText);
91
+ if (parsed !== undefined) return parsed;
92
+ const message =
93
+ Buffer.byteLength(rawText, "utf8") > MAX_PROVIDER_BODY_BYTES
94
+ ? PROVIDER_OVERSIZED_RESPONSE
95
+ : PROVIDER_MALFORMED_RESPONSE;
96
+ throw new Error(redactImageProviderText(message, activeApiKey));
97
+ }
98
+
99
+ async function readProviderResponseText(
100
+ response: Response,
101
+ activeApiKey?: string,
102
+ signal?: AbortSignal,
103
+ ): Promise<string> {
104
+ const contentLength = response.headers.get("content-length");
105
+ if (contentLength !== null) {
106
+ const declaredLength = Number(contentLength);
107
+ if (Number.isFinite(declaredLength) && declaredLength > MAX_PROVIDER_BODY_BYTES) {
108
+ await response.body?.cancel().catch(() => undefined);
109
+ throw new Error(PROVIDER_OVERSIZED_RESPONSE);
110
+ }
111
+ }
112
+
113
+ if (!response.body) return "";
114
+
115
+ const reader = response.body.getReader();
116
+ const decoder = new TextDecoder("utf-8");
117
+ const chunks: string[] = [];
118
+ let totalBytes = 0;
119
+ try {
120
+ while (true) {
121
+ const { done, value } = await reader.read();
122
+ if (done) break;
123
+ if (!value || value.byteLength === 0) continue;
124
+
125
+ if (totalBytes > MAX_PROVIDER_BODY_BYTES - value.byteLength) {
126
+ await reader.cancel().catch(() => undefined);
127
+ throw new Error(PROVIDER_OVERSIZED_RESPONSE);
128
+ }
129
+ totalBytes += value.byteLength;
130
+ const decoded = decoder.decode(value, { stream: true });
131
+ if (decoded.length > 0) chunks.push(decoded);
132
+ }
133
+
134
+ const trailingText = decoder.decode();
135
+ if (trailingText.length > 0) chunks.push(trailingText);
136
+ return chunks.join("");
137
+ } catch (error) {
138
+ if (signal?.aborted) throw signal.reason ?? error;
139
+ throw new Error(redactImageProviderText(error instanceof Error ? error.message : error, activeApiKey));
140
+ } finally {
141
+ reader.releaseLock();
142
+ }
143
+ }
144
+
145
+ const PROVIDER_SSE_READ_OPTIONS = {
146
+ maxEventBytes: MAX_PROVIDER_SSE_EVENT_BYTES,
147
+ maxTotalBytes: MAX_PROVIDER_BODY_BYTES,
148
+ } as const;
149
+
150
+ async function fetchImageProvider(
151
+ input: string | URL | Request,
152
+ init: RequestInit,
153
+ activeApiKey: string,
154
+ ): Promise<Response> {
155
+ try {
156
+ return await fetch(input, init);
157
+ } catch (error) {
158
+ if (init.signal?.aborted) throw init.signal.reason ?? error;
159
+ throw new Error(redactImageProviderText(error instanceof Error ? error.message : error, activeApiKey));
160
+ }
161
+ }
44
162
 
45
163
  const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
46
164
  const ALIBABA_TOKEN_PLAN_HOST = "https://token-plan.ap-southeast-1.maas.aliyuncs.com";
@@ -48,7 +166,7 @@ const ALIBABA_IMAGE_GENERATION_URL = `${ALIBABA_TOKEN_PLAN_HOST}/api/v1/services
48
166
  const IMAGE_SYSTEM_INSTRUCTION =
49
167
  "You are an AI image generator. Generate images based on user descriptions. Focus on creating high-quality, visually appealing images that match the user's request.";
50
168
 
51
- type ImageProvider = "alibaba" | "antigravity" | "gemini" | "openai" | "openai-codex" | "openrouter" | (string & {});
169
+ type ImageProvider = "alibaba" | "antigravity" | "gemini" | "openai" | "openai-codex" | "openrouter";
52
170
  interface ImageApiKey {
53
171
  provider: ImageProvider;
54
172
  apiKey: string;
@@ -57,6 +175,19 @@ interface ImageApiKey {
57
175
  authCredentialType?: "api_key" | "oauth";
58
176
  }
59
177
 
178
+ export class UnsupportedImageProviderError extends Error {
179
+ readonly code = "unsupported_image_provider" as const;
180
+
181
+ constructor(
182
+ readonly provider: string,
183
+ readonly modelId: string,
184
+ readonly api: Model["api"],
185
+ ) {
186
+ super(`Image generation is not supported for provider "${provider}" with transport "${api}".`);
187
+ this.name = "UnsupportedImageProviderError";
188
+ }
189
+ }
190
+
60
191
  const responseModalitySchema = z.enum(["IMAGE", "TEXT"] as const);
61
192
  const aspectRatioSchema = z.enum(["1:1", "3:4", "4:3", "9:16", "16:9"] as const).describe("aspect ratio");
62
193
  const imageSizeSchema = z.enum(["1024x1024", "1536x1024", "1024x1536"] as const).describe("image size");
@@ -244,6 +375,30 @@ interface OpenAIHostedImageResult {
244
375
  usage?: OpenAIResponsesUsage;
245
376
  }
246
377
 
378
+ function redactOpenAIHostedImageResult(result: OpenAIHostedImageResult, activeApiKey: string): OpenAIHostedImageResult {
379
+ return {
380
+ ...result,
381
+ responseText: result.responseText ? redactImageProviderText(result.responseText, activeApiKey) : undefined,
382
+ revisedPrompt: result.revisedPrompt ? redactImageProviderText(result.revisedPrompt, activeApiKey) : undefined,
383
+ };
384
+ }
385
+
386
+ function redactGeminiPromptFeedback(
387
+ promptFeedback: GeminiPromptFeedback | undefined,
388
+ activeApiKey: string,
389
+ ): GeminiPromptFeedback | undefined {
390
+ if (!promptFeedback) return undefined;
391
+ return {
392
+ blockReason: promptFeedback.blockReason
393
+ ? redactImageProviderText(promptFeedback.blockReason, activeApiKey)
394
+ : undefined,
395
+ safetyRatings: promptFeedback.safetyRatings?.map(rating => ({
396
+ category: rating.category ? redactImageProviderText(rating.category, activeApiKey) : undefined,
397
+ probability: rating.probability ? redactImageProviderText(rating.probability, activeApiKey) : undefined,
398
+ })),
399
+ };
400
+ }
401
+
247
402
  interface OpenRouterImageUrl {
248
403
  url: string;
249
404
  }
@@ -566,7 +721,11 @@ async function readImageResponse(
566
721
  }
567
722
  }
568
723
 
569
- async function loadImageFromUrl(imageUrl: string, signal?: AbortSignal): Promise<InlineImageData> {
724
+ async function loadImageFromUrl(
725
+ imageUrl: string,
726
+ signal?: AbortSignal,
727
+ activeApiKey?: string,
728
+ ): Promise<InlineImageData> {
570
729
  if (imageUrl.startsWith("data:")) {
571
730
  const normalized = normalizeDataUrl(imageUrl.trim());
572
731
  if (!normalized.mimeType) {
@@ -599,8 +758,11 @@ async function loadImageFromUrl(imageUrl: string, signal?: AbortSignal): Promise
599
758
  }
600
759
  validateImageResponseFraming(response);
601
760
  if (status < 200 || status >= 300) {
602
- const preview = (await readImageResponse(response, MAX_IMAGE_ERROR_PREVIEW_SIZE, signal)).toString("utf8");
603
- throw new Error(`Image download failed (${status}): ${preview}`);
761
+ const preview = redactImageProviderText(
762
+ (await readImageResponse(response, MAX_IMAGE_ERROR_PREVIEW_SIZE, signal)).toString("utf8"),
763
+ activeApiKey,
764
+ );
765
+ throw new Error(`Image download failed (${status}): ${preview || "provider returned an error"}`);
604
766
  }
605
767
  const rawContentType = response.headers["content-type"];
606
768
  const contentType =
@@ -786,8 +948,9 @@ async function findImageApiKey(
786
948
  }
787
949
 
788
950
  /**
789
- * Map a resolved image model to its provider credentials. Each provider
790
- * branch mirrors the original credential-resolution path.
951
+ * Map a resolved image model to its provider credentials. Transport and image
952
+ * capability are validated before any credential lookup; unsupported models
953
+ * fail without forwarding their provider credential to another endpoint.
791
954
  */
792
955
  async function resolveCredentialsForImageModel(
793
956
  model: Model,
@@ -809,19 +972,23 @@ async function resolveCredentialsForImageModel(
809
972
  };
810
973
  }
811
974
 
812
- if (provider === "antigravity" || provider === "google-antigravity") {
975
+ if (
976
+ (provider === "antigravity" || provider === "google-antigravity") &&
977
+ model.api === "google-gemini-cli" &&
978
+ model.output?.includes("image")
979
+ ) {
813
980
  return await findAntigravityCredentials(modelRegistry, sessionId);
814
981
  }
815
- if (provider === "alibaba" || provider === "alibaba-token-plan") {
982
+ if ((provider === "alibaba" || provider === "alibaba-token-plan") && model.output?.includes("image")) {
816
983
  return await findAlibabaImageCredentials(modelRegistry, sessionId);
817
984
  }
818
- if (provider === "openrouter") {
985
+ if (provider === "openrouter" && model.output?.includes("image")) {
819
986
  const openRouterKey = await modelRegistry.getApiKey(model, sessionId);
820
987
  if (isAuthenticated(openRouterKey)) return { provider: "openrouter", apiKey: openRouterKey };
821
988
  const envKey = getEnvApiKey("openrouter");
822
989
  return envKey ? { provider: "openrouter", apiKey: envKey } : null;
823
990
  }
824
- if (provider === "gemini" || provider === "google") {
991
+ if (provider === "google" && model.api === "google-generative-ai" && model.output?.includes("image")) {
825
992
  const googleKey = await modelRegistry.getApiKey(model, sessionId);
826
993
  if (isAuthenticated(googleKey)) return { provider: "gemini", apiKey: googleKey };
827
994
  const envKey = getEnvApiKey("google");
@@ -830,14 +997,7 @@ async function resolveCredentialsForImageModel(
830
997
  return fallbackKey ? { provider: "gemini", apiKey: fallbackKey } : null;
831
998
  }
832
999
 
833
- // Fallback: try the model's own API key via the registry.
834
- const apiKey = await modelRegistry.getApiKey(model, sessionId);
835
- if (!isAuthenticated(apiKey)) return null;
836
- return {
837
- provider: provider as ImageProvider,
838
- apiKey,
839
- model,
840
- };
1000
+ throw new UnsupportedImageProviderError(model.provider, model.id, model.api);
841
1001
  }
842
1002
 
843
1003
  async function loadImageFromPath(imagePath: string, cwd: string): Promise<InlineImageData> {
@@ -936,7 +1096,7 @@ function collectInlineImages(parts: GeminiPart[]): InlineImageData[] {
936
1096
  return images;
937
1097
  }
938
1098
 
939
- export function isOpenAIHostedImageModel(model: Model | undefined): model is Model {
1099
+ export function isOpenAIHostedImageModel(model: Model | undefined): boolean {
940
1100
  if (!model) return false;
941
1101
  // The hosted image_generation tool is only available over the Responses API.
942
1102
  if (model.api !== "openai-responses" && model.api !== "openai-codex-responses") return false;
@@ -1049,13 +1209,9 @@ function collectOpenAIHostedImageResult(response: OpenAIHostedImageResponse): Op
1049
1209
  };
1050
1210
  }
1051
1211
 
1052
- function getOpenAIResponseErrorMessage(rawText: string): string {
1053
- try {
1054
- const parsed = JSON.parse(rawText) as { error?: { message?: string } };
1055
- return parsed.error?.message ?? rawText;
1056
- } catch {
1057
- return rawText;
1058
- }
1212
+ function getOpenAIResponseErrorMessage(rawText: string, activeApiKey?: string): string {
1213
+ const parsed = tryParseProviderJson<{ error?: { message?: string } }>(rawText);
1214
+ return redactImageProviderText(parsed?.error?.message ?? "provider returned an error", activeApiKey);
1059
1215
  }
1060
1216
 
1061
1217
  function getOpenAIBaseUrl(model: Model, authCredentialType?: "api_key" | "oauth"): string {
@@ -1113,7 +1269,11 @@ function buildOpenAIImageHeaders(model: Model, apiKey: string, sessionId: string
1113
1269
  return headers;
1114
1270
  }
1115
1271
 
1116
- async function parseOpenAIHostedImageSse(response: Response, signal?: AbortSignal): Promise<OpenAIHostedImageResult> {
1272
+ async function parseOpenAIHostedImageSse(
1273
+ response: Response,
1274
+ signal: AbortSignal | undefined,
1275
+ activeApiKey: string,
1276
+ ): Promise<OpenAIHostedImageResult> {
1117
1277
  if (!response.body) {
1118
1278
  throw new Error("No response body");
1119
1279
  }
@@ -1121,21 +1281,33 @@ async function parseOpenAIHostedImageSse(response: Response, signal?: AbortSigna
1121
1281
  const fallbackOutput: OpenAIResponseOutput[] = [];
1122
1282
  let completedResponse: OpenAIHostedImageResponse | undefined;
1123
1283
 
1124
- for await (const event of readSseJson<OpenAISseEvent>(response.body, signal)) {
1125
- if (event.type === "error") {
1126
- const message = event.error?.message ?? event.message ?? "OpenAI image request failed";
1127
- throw new Error(message);
1128
- }
1129
- if (event.type === "response.failed") {
1130
- const message = event.response?.error?.message ?? "OpenAI image request failed";
1131
- throw new Error(message);
1132
- }
1133
- if (event.type === "response.output_item.done" && event.item) {
1134
- fallbackOutput.push(event.item);
1135
- }
1136
- if ((event.type === "response.completed" || event.type === "response.done") && event.response) {
1137
- completedResponse = event.response;
1284
+ try {
1285
+ for await (const event of readSseJson<OpenAISseEvent>(
1286
+ response.body,
1287
+ signal,
1288
+ undefined,
1289
+ PROVIDER_SSE_READ_OPTIONS,
1290
+ )) {
1291
+ if (!event || typeof event !== "object" || Array.isArray(event)) throw new Error(PROVIDER_MALFORMED_RESPONSE);
1292
+ if (event.type === "error") {
1293
+ const message = event.error?.message ?? event.message ?? "OpenAI image request failed";
1294
+ throw new Error(redactImageProviderText(message, activeApiKey));
1295
+ }
1296
+ if (event.type === "response.failed") {
1297
+ const message = event.response?.error?.message ?? "OpenAI image request failed";
1298
+ throw new Error(redactImageProviderText(message, activeApiKey));
1299
+ }
1300
+ if (event.type === "response.output_item.done" && event.item) {
1301
+ fallbackOutput.push(event.item);
1302
+ }
1303
+ if ((event.type === "response.completed" || event.type === "response.done") && event.response) {
1304
+ completedResponse = event.response;
1305
+ }
1138
1306
  }
1307
+ } catch (error) {
1308
+ if (signal?.aborted) throw signal.reason ?? error;
1309
+ if (error instanceof Error && error.message !== PROVIDER_MALFORMED_RESPONSE) throw error;
1310
+ throw new Error(redactImageProviderText(PROVIDER_MALFORMED_RESPONSE, activeApiKey));
1139
1311
  }
1140
1312
 
1141
1313
  return collectOpenAIHostedImageResult(
@@ -1157,25 +1329,32 @@ async function generateOpenAIHostedImage(
1157
1329
  const promptText = assemblePrompt(params);
1158
1330
  const stream = model.api === "openai-codex-responses" || model.provider === "openai-codex";
1159
1331
  const requestBody = buildOpenAIHostedImageRequest(model, promptText, params, inputImages, stream);
1160
- const response = await fetch(getOpenAIResponsesUrl(model, options?.authCredentialType), {
1161
- method: "POST",
1162
- headers: buildOpenAIImageHeaders(model, apiKey, sessionId),
1163
- body: JSON.stringify(requestBody),
1164
- signal,
1165
- });
1332
+ const response = await fetchImageProvider(
1333
+ getOpenAIResponsesUrl(model, options?.authCredentialType),
1334
+ {
1335
+ method: "POST",
1336
+ headers: buildOpenAIImageHeaders(model, apiKey, sessionId),
1337
+ body: JSON.stringify(requestBody),
1338
+ signal,
1339
+ },
1340
+ apiKey,
1341
+ );
1166
1342
 
1167
1343
  if (!response.ok) {
1168
- const errorText = await response.text();
1169
- throw new Error(`OpenAI image request failed (${response.status}): ${getOpenAIResponseErrorMessage(errorText)}`);
1344
+ const errorText = await readProviderResponseText(response, apiKey, signal);
1345
+ throw new Error(
1346
+ `OpenAI image request failed (${response.status}): ${getOpenAIResponseErrorMessage(errorText, apiKey)}`,
1347
+ );
1170
1348
  }
1171
1349
 
1172
1350
  const contentType = response.headers.get("content-type") ?? "";
1173
1351
  if (stream || contentType.includes("text/event-stream")) {
1174
- return parseOpenAIHostedImageSse(response, signal);
1352
+ return redactOpenAIHostedImageResult(await parseOpenAIHostedImageSse(response, signal, apiKey), apiKey);
1175
1353
  }
1176
1354
 
1177
- const data = (await response.json()) as OpenAIHostedImageResponse;
1178
- return collectOpenAIHostedImageResult(data);
1355
+ const rawText = await readProviderResponseText(response, apiKey, signal);
1356
+ const data = parseProviderJson<OpenAIHostedImageResponse>(rawText, apiKey);
1357
+ return redactOpenAIHostedImageResult(collectOpenAIHostedImageResult(data), apiKey);
1179
1358
  }
1180
1359
 
1181
1360
  function combineParts(response: GeminiGenerateContentResponse): GeminiPart[] {
@@ -1234,7 +1413,11 @@ interface AntigravitySseResult {
1234
1413
  usage?: GeminiUsageMetadata;
1235
1414
  }
1236
1415
 
1237
- async function parseAntigravitySseForImage(response: Response, signal?: AbortSignal): Promise<AntigravitySseResult> {
1416
+ async function parseAntigravitySseForImage(
1417
+ response: Response,
1418
+ signal: AbortSignal | undefined,
1419
+ activeApiKey?: string,
1420
+ ): Promise<AntigravitySseResult> {
1238
1421
  if (!response.body) {
1239
1422
  throw new Error("No response body");
1240
1423
  }
@@ -1242,25 +1425,42 @@ async function parseAntigravitySseForImage(response: Response, signal?: AbortSig
1242
1425
  const textParts: string[] = [];
1243
1426
  const images: InlineImageData[] = [];
1244
1427
  let usage: GeminiUsageMetadata | undefined;
1428
+ let chunks: AntigravityResponseChunk[];
1429
+ try {
1430
+ chunks = [];
1431
+ for await (const chunk of readSseJson<AntigravityResponseChunk>(
1432
+ response.body,
1433
+ signal,
1434
+ undefined,
1435
+ PROVIDER_SSE_READ_OPTIONS,
1436
+ )) {
1437
+ if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) throw new Error(PROVIDER_MALFORMED_RESPONSE);
1438
+ chunks.push(chunk);
1439
+ }
1440
+ } catch (error) {
1441
+ if (signal?.aborted) throw signal.reason ?? error;
1442
+ throw new Error(redactImageProviderText(PROVIDER_MALFORMED_RESPONSE, activeApiKey));
1443
+ }
1245
1444
 
1246
- for await (const chunk of readSseJson<AntigravityResponseChunk>(response.body, signal)) {
1445
+ for (const chunk of chunks) {
1247
1446
  const responseData = chunk.response;
1248
- if (!responseData) continue;
1249
- if (!responseData.candidates) continue;
1250
- for (const candidate of responseData.candidates) {
1251
- const parts = candidate.content?.parts;
1252
- if (!parts) continue;
1447
+ if (!responseData || typeof responseData !== "object") continue;
1448
+ const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
1449
+ for (const candidate of candidates) {
1450
+ if (!candidate || typeof candidate !== "object") continue;
1451
+ const parts = Array.isArray(candidate.content?.parts) ? candidate.content.parts : [];
1253
1452
  for (const part of parts) {
1254
- if (part.text) {
1453
+ if (!part || typeof part !== "object") continue;
1454
+ if (typeof part.text === "string" && part.text.length > 0) {
1255
1455
  textParts.push(part.text);
1256
1456
  }
1257
1457
  const inlineData = part.inlineData;
1258
- if (inlineData?.data && inlineData.mimeType) {
1458
+ if (inlineData && typeof inlineData === "object" && inlineData.data && inlineData.mimeType) {
1259
1459
  images.push({ data: inlineData.data, mimeType: inlineData.mimeType });
1260
1460
  }
1261
1461
  }
1262
1462
  }
1263
- if (responseData.usageMetadata) {
1463
+ if (responseData.usageMetadata && typeof responseData.usageMetadata === "object") {
1264
1464
  usage = responseData.usageMetadata;
1265
1465
  }
1266
1466
  }
@@ -1381,32 +1581,34 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1381
1581
 
1382
1582
  const { getAntigravityUserAgent } =
1383
1583
  require("@gajae-code/ai/providers/google-gemini-headers") as typeof import("@gajae-code/ai/providers/google-gemini-headers");
1384
- const response = await fetch(`${ANTIGRAVITY_ENDPOINT}/v1internal:streamGenerateContent?alt=sse`, {
1385
- method: "POST",
1386
- headers: {
1387
- Authorization: `Bearer ${apiKey.apiKey}`,
1388
- "Content-Type": "application/json",
1389
- Accept: "text/event-stream",
1390
- "User-Agent": getAntigravityUserAgent(),
1584
+ const response = await fetchImageProvider(
1585
+ `${ANTIGRAVITY_ENDPOINT}/v1internal:streamGenerateContent?alt=sse`,
1586
+ {
1587
+ method: "POST",
1588
+ headers: {
1589
+ Authorization: `Bearer ${apiKey.apiKey}`,
1590
+ "Content-Type": "application/json",
1591
+ Accept: "text/event-stream",
1592
+ "User-Agent": getAntigravityUserAgent(),
1593
+ },
1594
+ body: JSON.stringify(requestBody),
1595
+ signal: requestSignal,
1391
1596
  },
1392
- body: JSON.stringify(requestBody),
1393
- signal: requestSignal,
1394
- });
1597
+ apiKey.apiKey,
1598
+ );
1395
1599
 
1396
1600
  if (!response.ok) {
1397
- const errorText = await response.text();
1398
- let message = errorText;
1399
- try {
1400
- const parsed = JSON.parse(errorText) as { error?: { message?: string } };
1401
- message = parsed.error?.message ?? message;
1402
- } catch {
1403
- // Keep raw text.
1404
- }
1405
- throw new Error(`Antigravity image request failed (${response.status}): ${message}`);
1601
+ const errorText = await readProviderResponseText(response, apiKey.apiKey, requestSignal);
1602
+ const parsed = tryParseProviderJson<{ error?: { message?: string } }>(errorText);
1603
+ const message = parsed?.error?.message;
1604
+ throw new Error(
1605
+ `Antigravity image request failed (${response.status}): ${redactImageProviderText(message ?? "provider returned an error", apiKey.apiKey)}`,
1606
+ );
1406
1607
  }
1407
1608
 
1408
- const parsed = await parseAntigravitySseForImage(response, requestSignal);
1409
- const responseText = parsed.text.length > 0 ? parsed.text.join(" ") : undefined;
1609
+ const parsed = await parseAntigravitySseForImage(response, requestSignal, apiKey.apiKey);
1610
+ const responseText =
1611
+ parsed.text.length > 0 ? redactImageProviderText(parsed.text.join(" "), apiKey.apiKey) : undefined;
1410
1612
 
1411
1613
  if (parsed.images.length === 0) {
1412
1614
  const messageText = responseText ? `\n\n${responseText}` : "";
@@ -1452,38 +1654,40 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1452
1654
  messages: [{ role: "user" as const, content: contentParts }],
1453
1655
  };
1454
1656
 
1455
- const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
1456
- method: "POST",
1457
- headers: {
1458
- "Content-Type": "application/json",
1459
- Authorization: `Bearer ${apiKey.apiKey}`,
1460
- "HTTP-Referer": "https://gaebal-gajae.dev/",
1461
- "X-OpenRouter-Title": "Gajae Code",
1462
- "X-OpenRouter-Categories": "cli-agent",
1657
+ const response = await fetchImageProvider(
1658
+ "https://openrouter.ai/api/v1/chat/completions",
1659
+ {
1660
+ method: "POST",
1661
+ headers: {
1662
+ "Content-Type": "application/json",
1663
+ Authorization: `Bearer ${apiKey.apiKey}`,
1664
+ "HTTP-Referer": "https://gaebal-gajae.dev/",
1665
+ "X-OpenRouter-Title": "Gajae Code",
1666
+ "X-OpenRouter-Categories": "cli-agent",
1667
+ },
1668
+ body: JSON.stringify(requestBody),
1669
+ signal: requestSignal,
1463
1670
  },
1464
- body: JSON.stringify(requestBody),
1465
- signal: requestSignal,
1466
- });
1671
+ apiKey.apiKey,
1672
+ );
1467
1673
 
1468
- const rawText = await response.text();
1674
+ const rawText = await readProviderResponseText(response, apiKey.apiKey, requestSignal);
1469
1675
  if (!response.ok) {
1470
- let message = rawText;
1471
- try {
1472
- const parsed = JSON.parse(rawText) as { error?: { message?: string } };
1473
- message = parsed.error?.message ?? message;
1474
- } catch {
1475
- // Keep raw text.
1476
- }
1477
- throw new Error(`OpenRouter image request failed (${response.status}): ${message}`);
1676
+ const parsed = tryParseProviderJson<{ error?: { message?: string } }>(rawText);
1677
+ const message = parsed?.error?.message;
1678
+ throw new Error(
1679
+ `OpenRouter image request failed (${response.status}): ${redactImageProviderText(message ?? "provider returned an error", apiKey.apiKey)}`,
1680
+ );
1478
1681
  }
1479
1682
 
1480
- const data = JSON.parse(rawText) as OpenRouterResponse;
1683
+ const data = parseProviderJson<OpenRouterResponse>(rawText, apiKey.apiKey);
1481
1684
  const message = data.choices?.[0]?.message;
1482
- const responseText = collectOpenRouterResponseText(message);
1685
+ const rawResponseText = collectOpenRouterResponseText(message);
1686
+ const responseText = rawResponseText ? redactImageProviderText(rawResponseText, apiKey.apiKey) : undefined;
1483
1687
  const imageUrls = extractOpenRouterImageUrls(message);
1484
1688
  const inlineImages: InlineImageData[] = [];
1485
1689
  for (const imageUrl of imageUrls) {
1486
- inlineImages.push(await loadImageFromUrl(imageUrl, requestSignal));
1690
+ inlineImages.push(await loadImageFromUrl(imageUrl, requestSignal, apiKey.apiKey));
1487
1691
  }
1488
1692
 
1489
1693
  if (inlineImages.length === 0) {
@@ -1526,38 +1730,42 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1526
1730
  params.image_size,
1527
1731
  );
1528
1732
 
1529
- const response = await fetch(ALIBABA_IMAGE_GENERATION_URL, {
1530
- method: "POST",
1531
- headers: {
1532
- "Content-Type": "application/json",
1533
- Authorization: `Bearer ${apiKey.apiKey}`,
1733
+ const response = await fetchImageProvider(
1734
+ ALIBABA_IMAGE_GENERATION_URL,
1735
+ {
1736
+ method: "POST",
1737
+ headers: {
1738
+ "Content-Type": "application/json",
1739
+ Authorization: `Bearer ${apiKey.apiKey}`,
1740
+ },
1741
+ body: JSON.stringify(requestBody),
1742
+ signal: requestSignal,
1534
1743
  },
1535
- body: JSON.stringify(requestBody),
1536
- signal: requestSignal,
1537
- });
1744
+ apiKey.apiKey,
1745
+ );
1538
1746
 
1539
- const rawText = await response.text();
1747
+ const rawText = await readProviderResponseText(response, apiKey.apiKey, requestSignal);
1540
1748
  if (!response.ok) {
1541
- let message = rawText;
1542
- try {
1543
- const parsed = JSON.parse(rawText) as { message?: string; error?: { message?: string } };
1544
- message = parsed.error?.message ?? parsed.message ?? message;
1545
- } catch {
1546
- // Keep raw text.
1547
- }
1548
- throw new Error(`Alibaba image request failed (${response.status}): ${message}`);
1749
+ const parsed = tryParseProviderJson<{ message?: string; error?: { message?: string } }>(rawText);
1750
+ const message = parsed?.error?.message ?? parsed?.message;
1751
+ throw new Error(
1752
+ `Alibaba image request failed (${response.status}): ${redactImageProviderText(message ?? "provider returned an error", apiKey.apiKey)}`,
1753
+ );
1549
1754
  }
1550
1755
 
1551
- const data = JSON.parse(rawText) as AlibabaImageResponse;
1756
+ const data = parseProviderJson<AlibabaImageResponse>(rawText, apiKey.apiKey);
1552
1757
  if (data.code) {
1553
- throw new Error(`Alibaba image request failed: ${data.code}: ${data.message ?? ""}`.trim());
1758
+ throw new Error(
1759
+ `Alibaba image request failed: ${redactImageProviderText(`${data.code}: ${data.message ?? ""}`, apiKey.apiKey)}`,
1760
+ );
1554
1761
  }
1555
1762
 
1556
- const { imageUrls, responseText } = collectAlibabaImageResult(data);
1763
+ const { imageUrls, responseText: rawResponseText } = collectAlibabaImageResult(data);
1764
+ const responseText = rawResponseText ? redactImageProviderText(rawResponseText, apiKey.apiKey) : undefined;
1557
1765
  // Result URLs are short-lived OSS-signed URLs (24h); download immediately.
1558
1766
  const inlineImages: InlineImageData[] = [];
1559
1767
  for (const imageUrl of imageUrls) {
1560
- inlineImages.push(await loadImageFromUrl(imageUrl, requestSignal));
1768
+ inlineImages.push(await loadImageFromUrl(imageUrl, requestSignal, apiKey.apiKey));
1561
1769
  }
1562
1770
 
1563
1771
  if (inlineImages.length === 0) {
@@ -1615,7 +1823,7 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1615
1823
  generationConfig,
1616
1824
  };
1617
1825
 
1618
- const response = await fetch(
1826
+ const response = await fetchImageProvider(
1619
1827
  `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:generateContent`,
1620
1828
  {
1621
1829
  method: "POST",
@@ -1626,28 +1834,27 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1626
1834
  body: JSON.stringify(requestBody),
1627
1835
  signal: requestSignal,
1628
1836
  },
1837
+ apiKey.apiKey,
1629
1838
  );
1630
1839
 
1631
- const rawText = await response.text();
1840
+ const rawText = await readProviderResponseText(response, apiKey.apiKey, requestSignal);
1632
1841
  if (!response.ok) {
1633
- let message = rawText;
1634
- try {
1635
- const parsed = JSON.parse(rawText) as { error?: { message?: string } };
1636
- message = parsed.error?.message ?? message;
1637
- } catch {
1638
- // Keep raw text.
1639
- }
1640
- throw new Error(`Gemini image request failed (${response.status}): ${message}`);
1842
+ const parsed = tryParseProviderJson<{ error?: { message?: string } }>(rawText);
1843
+ const message = parsed?.error?.message;
1844
+ throw new Error(
1845
+ `Gemini image request failed (${response.status}): ${redactImageProviderText(message ?? "provider returned an error", apiKey.apiKey)}`,
1846
+ );
1641
1847
  }
1642
1848
 
1643
- const data = JSON.parse(rawText) as GeminiGenerateContentResponse;
1849
+ const data = parseProviderJson<GeminiGenerateContentResponse>(rawText, apiKey.apiKey);
1644
1850
  const responseParts = combineParts(data);
1645
- const responseText = collectResponseText(responseParts);
1851
+ const rawResponseText = collectResponseText(responseParts);
1852
+ const responseText = rawResponseText ? redactImageProviderText(rawResponseText, apiKey.apiKey) : undefined;
1646
1853
  const inlineImages = collectInlineImages(responseParts);
1647
1854
 
1648
1855
  if (inlineImages.length === 0) {
1649
1856
  const blocked = data.promptFeedback?.blockReason
1650
- ? `Blocked: ${data.promptFeedback.blockReason}`
1857
+ ? `Blocked: ${redactImageProviderText(data.promptFeedback.blockReason, apiKey.apiKey)}`
1651
1858
  : "No image data returned.";
1652
1859
  return {
1653
1860
  content: [{ type: "text", text: `${blocked}${responseText ? `\n\n${responseText}` : ""}` }],
@@ -1658,7 +1865,7 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1658
1865
  imagePaths: [],
1659
1866
  images: [],
1660
1867
  responseText,
1661
- promptFeedback: data.promptFeedback,
1868
+ promptFeedback: redactGeminiPromptFeedback(data.promptFeedback, apiKey.apiKey),
1662
1869
  usage: data.usageMetadata,
1663
1870
  },
1664
1871
  };
@@ -1675,7 +1882,7 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
1675
1882
  imagePaths,
1676
1883
  images: inlineImages,
1677
1884
  responseText,
1678
- promptFeedback: data.promptFeedback,
1885
+ promptFeedback: redactGeminiPromptFeedback(data.promptFeedback, apiKey.apiKey),
1679
1886
  usage: data.usageMetadata,
1680
1887
  },
1681
1888
  };