n9router 0.4.53 → 0.4.55

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 (1011) hide show
  1. package/app/.next/BUILD_ID +1 -1
  2. package/app/.next/app-path-routes-manifest.json +16 -12
  3. package/app/.next/build-manifest.json +2 -2
  4. package/app/.next/prerender-manifest.json +3 -3
  5. package/app/.next/routes-manifest.json +24 -0
  6. package/app/.next/server/app/(dashboard)/dashboard/basic-chat/page.js +2 -2
  7. package/app/.next/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
  8. package/app/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  9. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js +2 -2
  10. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
  11. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  12. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page.js +2 -2
  13. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  14. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  15. package/app/.next/server/app/(dashboard)/dashboard/combos/page.js +2 -2
  16. package/app/.next/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
  17. package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  18. package/app/.next/server/app/(dashboard)/dashboard/console-log/page.js +2 -2
  19. package/app/.next/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
  20. package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  21. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page.js +2 -2
  22. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  23. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  24. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +2 -2
  25. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js.nft.json +1 -1
  26. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  27. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js +2 -2
  28. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js.nft.json +1 -1
  29. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  30. package/app/.next/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js +2 -2
  31. package/app/.next/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js.nft.json +1 -1
  32. package/app/.next/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  33. package/app/.next/server/app/(dashboard)/dashboard/media-providers/web/page.js +2 -2
  34. package/app/.next/server/app/(dashboard)/dashboard/media-providers/web/page.js.nft.json +1 -1
  35. package/app/.next/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  36. package/app/.next/server/app/(dashboard)/dashboard/mitm/page.js +2 -2
  37. package/app/.next/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
  38. package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  39. package/app/.next/server/app/(dashboard)/dashboard/page.js +2 -2
  40. package/app/.next/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  41. package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  42. package/app/.next/server/app/(dashboard)/dashboard/profile/page.js +2 -2
  43. package/app/.next/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
  44. package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  45. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js +2 -2
  46. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
  47. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  48. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page.js +2 -2
  49. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
  50. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  51. package/app/.next/server/app/(dashboard)/dashboard/providers/page.js +2 -2
  52. package/app/.next/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
  53. package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  54. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js +2 -2
  55. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
  56. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  57. package/app/.next/server/app/(dashboard)/dashboard/pxpipe/page.js +2 -2
  58. package/app/.next/server/app/(dashboard)/dashboard/pxpipe/page.js.nft.json +1 -1
  59. package/app/.next/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
  60. package/app/.next/server/app/(dashboard)/dashboard/quota/page.js +2 -2
  61. package/app/.next/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
  62. package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  63. package/app/.next/server/app/(dashboard)/dashboard/skills/page.js +2 -2
  64. package/app/.next/server/app/(dashboard)/dashboard/skills/page.js.nft.json +1 -1
  65. package/app/.next/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  66. package/app/.next/server/app/(dashboard)/dashboard/token-saver/page.js +2 -2
  67. package/app/.next/server/app/(dashboard)/dashboard/token-saver/page.js.nft.json +1 -1
  68. package/app/.next/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  69. package/app/.next/server/app/(dashboard)/dashboard/translator/page.js +2 -2
  70. package/app/.next/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
  71. package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  72. package/app/.next/server/app/(dashboard)/dashboard/usage/page.js +3 -3
  73. package/app/.next/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
  74. package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  75. package/app/.next/server/app/_global-error/page.js +2 -2
  76. package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  77. package/app/.next/server/app/_global-error.html +1 -1
  78. package/app/.next/server/app/_global-error.rsc +1 -1
  79. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  80. package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  81. package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  82. package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  83. package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  84. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  85. package/app/.next/server/app/_not-found/page.js +2 -2
  86. package/app/.next/server/app/_not-found/page.js.nft.json +1 -1
  87. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  88. package/app/.next/server/app/_not-found.html +1 -1
  89. package/app/.next/server/app/_not-found.rsc +4 -4
  90. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  91. package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  92. package/app/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  93. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  94. package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  95. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  96. package/app/.next/server/app/api/antigravity-app/route.js +1 -1
  97. package/app/.next/server/app/api/antigravity-app-v2/route.js +1 -1
  98. package/app/.next/server/app/api/antigravity-ide/route.js +1 -1
  99. package/app/.next/server/app/api/antigravity-targets/route.js +1 -1
  100. package/app/.next/server/app/api/antigravity-tools/import/route.js +1 -1
  101. package/app/.next/server/app/api/antigravity-tools/import/route.js.nft.json +1 -1
  102. package/app/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js +1 -1
  103. package/app/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js.nft.json +1 -1
  104. package/app/.next/server/app/api/auth/login/route.js +3 -1
  105. package/app/.next/server/app/api/auth/login/route.js.nft.json +1 -1
  106. package/app/.next/server/app/api/auth/logout/route.js +1 -1
  107. package/app/.next/server/app/api/auth/oidc/callback/route.js +1 -1
  108. package/app/.next/server/app/api/auth/oidc/start/route.js +1 -1
  109. package/app/.next/server/app/api/auth/oidc/test/route.js +1 -1
  110. package/app/.next/server/app/api/auth/reset-password/route.js +1 -1
  111. package/app/.next/server/app/api/auth/saml/acs/route.js +3 -0
  112. package/app/.next/server/app/api/auth/saml/acs/route.js.nft.json +1 -0
  113. package/app/.next/server/app/api/auth/saml/acs/route_client-reference-manifest.js +1 -0
  114. package/app/.next/server/app/api/auth/saml/metadata/route.js +3 -0
  115. package/app/.next/server/app/api/auth/saml/metadata/route.js.nft.json +1 -0
  116. package/app/.next/server/app/api/auth/saml/metadata/route_client-reference-manifest.js +1 -0
  117. package/app/.next/server/app/api/auth/saml/start/route.js +3 -0
  118. package/app/.next/server/app/api/auth/saml/start/route.js.nft.json +1 -0
  119. package/app/.next/server/app/api/auth/saml/start/route_client-reference-manifest.js +1 -0
  120. package/app/.next/server/app/api/auth/saml/test/route.js +3 -0
  121. package/app/.next/server/app/api/auth/saml/test/route.js.nft.json +1 -0
  122. package/app/.next/server/app/api/auth/saml/test/route_client-reference-manifest.js +1 -0
  123. package/app/.next/server/app/api/auth/status/route.js +3 -1
  124. package/app/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  125. package/app/.next/server/app/api/cli-tools/all-statuses/route.js +7 -6
  126. package/app/.next/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
  127. package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js +2 -2
  128. package/app/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
  129. package/app/.next/server/app/api/cli-tools/claude-settings/route.js +2 -2
  130. package/app/.next/server/app/api/cli-tools/cline-settings/route.js +2 -2
  131. package/app/.next/server/app/api/cli-tools/codex-settings/route.js +1 -1
  132. package/app/.next/server/app/api/cli-tools/copilot-settings/route.js +2 -2
  133. package/app/.next/server/app/api/cli-tools/cowork-mcp-registry/route.js +1 -1
  134. package/app/.next/server/app/api/cli-tools/cowork-mcp-tools/route.js +2 -2
  135. package/app/.next/server/app/api/cli-tools/cowork-settings/route.js +2 -2
  136. package/app/.next/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
  137. package/app/.next/server/app/api/cli-tools/cursor-byok/jobs/[jobId]/events/route.js +2 -2
  138. package/app/.next/server/app/api/cli-tools/cursor-byok/jobs/[jobId]/sudo/route.js +1 -1
  139. package/app/.next/server/app/api/cli-tools/cursor-byok/jobs/route.js +1 -1
  140. package/app/.next/server/app/api/cli-tools/cursor-byok/route.js +2 -2
  141. package/app/.next/server/app/api/cli-tools/deepseek-tui-settings/route.js +2 -2
  142. package/app/.next/server/app/api/cli-tools/devin-settings/route.js +2 -2
  143. package/app/.next/server/app/api/cli-tools/droid-settings/route.js +2 -2
  144. package/app/.next/server/app/api/cli-tools/grok-build-settings/route.js +2 -2
  145. package/app/.next/server/app/api/cli-tools/hermes-settings/route.js +4 -3
  146. package/app/.next/server/app/api/cli-tools/jcode-settings/route.js +2 -2
  147. package/app/.next/server/app/api/cli-tools/kilo-settings/route.js +2 -2
  148. package/app/.next/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
  149. package/app/.next/server/app/api/cli-tools/opencode-settings/route.js +1 -1
  150. package/app/.next/server/app/api/combos/[id]/route.js +1 -1
  151. package/app/.next/server/app/api/combos/route.js +1 -1
  152. package/app/.next/server/app/api/donate/route.js +1 -1
  153. package/app/.next/server/app/api/headroom/extras/route.js +1 -1
  154. package/app/.next/server/app/api/headroom/proxy/[...path]/route.js +1 -1
  155. package/app/.next/server/app/api/headroom/restart/route.js +1 -1
  156. package/app/.next/server/app/api/headroom/start/route.js +1 -1
  157. package/app/.next/server/app/api/headroom/status/route.js +1 -1
  158. package/app/.next/server/app/api/headroom/stop/route.js +1 -1
  159. package/app/.next/server/app/api/health/route.js +1 -1
  160. package/app/.next/server/app/api/init/route.js +1 -1
  161. package/app/.next/server/app/api/internal/account-health/route.js +1 -1
  162. package/app/.next/server/app/api/internal/request-detail/route.js +1 -1
  163. package/app/.next/server/app/api/internal/usage/route.js +1 -1
  164. package/app/.next/server/app/api/keys/[id]/reset-usage/route.js +1 -1
  165. package/app/.next/server/app/api/keys/[id]/route.js +1 -1
  166. package/app/.next/server/app/api/keys/[id]/usage/route.js +1 -1
  167. package/app/.next/server/app/api/keys/route.js +1 -1
  168. package/app/.next/server/app/api/locale/route.js +1 -1
  169. package/app/.next/server/app/api/mcp/[plugin]/message/route.js +1 -1
  170. package/app/.next/server/app/api/mcp/[plugin]/sse/route.js +2 -2
  171. package/app/.next/server/app/api/media-providers/tts/deepgram/voices/route.js +1 -1
  172. package/app/.next/server/app/api/media-providers/tts/elevenlabs/voices/route.js +1 -1
  173. package/app/.next/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
  174. package/app/.next/server/app/api/media-providers/tts/inworld/voices/route.js +1 -1
  175. package/app/.next/server/app/api/media-providers/tts/minimax/voices/route.js +1 -1
  176. package/app/.next/server/app/api/media-providers/tts/voices/route.js +1 -1
  177. package/app/.next/server/app/api/media-providers/tts/voices/route.js.nft.json +1 -1
  178. package/app/.next/server/app/api/models/alias/route.js +1 -1
  179. package/app/.next/server/app/api/models/availability/route.js +1 -1
  180. package/app/.next/server/app/api/models/custom/route.js +1 -1
  181. package/app/.next/server/app/api/models/disabled/route.js +1 -1
  182. package/app/.next/server/app/api/models/route.js +1 -1
  183. package/app/.next/server/app/api/models/route.js.nft.json +1 -1
  184. package/app/.next/server/app/api/models/test/route.js +1 -1
  185. package/app/.next/server/app/api/models/test/route.js.nft.json +1 -1
  186. package/app/.next/server/app/api/oauth/[provider]/[action]/route.js +1 -1
  187. package/app/.next/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  188. package/app/.next/server/app/api/oauth/codex/bulk-import/route.js +1 -1
  189. package/app/.next/server/app/api/oauth/codex/bulk-import/route.js.nft.json +1 -1
  190. package/app/.next/server/app/api/oauth/codex/import-token/route.js +1 -1
  191. package/app/.next/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
  192. package/app/.next/server/app/api/oauth/cursor/auto-import/route.js +2 -2
  193. package/app/.next/server/app/api/oauth/cursor/import/route.js +1 -1
  194. package/app/.next/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  195. package/app/.next/server/app/api/oauth/gitlab/pat/route.js +1 -1
  196. package/app/.next/server/app/api/oauth/iflow/cookie/route.js +1 -1
  197. package/app/.next/server/app/api/oauth/kiro/api-key/route.js +1 -1
  198. package/app/.next/server/app/api/oauth/kiro/api-key/route.js.nft.json +1 -1
  199. package/app/.next/server/app/api/oauth/kiro/auto-import/route.js +1 -1
  200. package/app/.next/server/app/api/oauth/kiro/import/route.js +1 -1
  201. package/app/.next/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  202. package/app/.next/server/app/api/oauth/kiro/import-cli-proxy/route.js +1 -1
  203. package/app/.next/server/app/api/oauth/kiro/social-authorize/route.js +1 -1
  204. package/app/.next/server/app/api/oauth/kiro/social-authorize/route.js.nft.json +1 -1
  205. package/app/.next/server/app/api/oauth/kiro/social-exchange/route.js +1 -1
  206. package/app/.next/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  207. package/app/.next/server/app/api/pricing/route.js +1 -1
  208. package/app/.next/server/app/api/provider-nodes/[id]/route.js +1 -1
  209. package/app/.next/server/app/api/provider-nodes/route.js +1 -1
  210. package/app/.next/server/app/api/provider-nodes/route.js.nft.json +1 -1
  211. package/app/.next/server/app/api/provider-nodes/validate/route.js +1 -1
  212. package/app/.next/server/app/api/providers/[id]/models/route.js +1 -1
  213. package/app/.next/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  214. package/app/.next/server/app/api/providers/[id]/route.js +1 -1
  215. package/app/.next/server/app/api/providers/[id]/test/route.js +1 -1
  216. package/app/.next/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  217. package/app/.next/server/app/api/providers/[id]/test-models/route.js +1 -1
  218. package/app/.next/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  219. package/app/.next/server/app/api/providers/client/route.js +1 -1
  220. package/app/.next/server/app/api/providers/client/route.js.nft.json +1 -1
  221. package/app/.next/server/app/api/providers/kilo/free-models/route.js +1 -1
  222. package/app/.next/server/app/api/providers/route.js +1 -1
  223. package/app/.next/server/app/api/providers/route.js.nft.json +1 -1
  224. package/app/.next/server/app/api/providers/suggested-models/route.js +1 -1
  225. package/app/.next/server/app/api/providers/test-batch/route.js +1 -1
  226. package/app/.next/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  227. package/app/.next/server/app/api/providers/validate/route.js +1 -1
  228. package/app/.next/server/app/api/providers/validate/route.js.nft.json +1 -1
  229. package/app/.next/server/app/api/proxy-pools/[id]/route.js +1 -1
  230. package/app/.next/server/app/api/proxy-pools/[id]/test/route.js +1 -1
  231. package/app/.next/server/app/api/proxy-pools/cloudflare-deploy/route.js +2 -2
  232. package/app/.next/server/app/api/proxy-pools/deno-deploy/route.js +2 -2
  233. package/app/.next/server/app/api/proxy-pools/route.js +1 -1
  234. package/app/.next/server/app/api/proxy-pools/vercel-deploy/route.js +2 -2
  235. package/app/.next/server/app/api/pxpipe/health/route.js +2 -2
  236. package/app/.next/server/app/api/pxpipe/install/route.js +2 -2
  237. package/app/.next/server/app/api/pxpipe/logs/route.js +2 -2
  238. package/app/.next/server/app/api/pxpipe/restart/route.js +2 -2
  239. package/app/.next/server/app/api/pxpipe/start/route.js +2 -2
  240. package/app/.next/server/app/api/pxpipe/stats/route.js +2 -2
  241. package/app/.next/server/app/api/pxpipe/status/route.js +2 -2
  242. package/app/.next/server/app/api/pxpipe/stop/route.js +2 -2
  243. package/app/.next/server/app/api/settings/database/route.js +1 -1
  244. package/app/.next/server/app/api/settings/database/selective/route.js +1 -1
  245. package/app/.next/server/app/api/settings/proxy-test/route.js +1 -1
  246. package/app/.next/server/app/api/settings/require-login/route.js +1 -1
  247. package/app/.next/server/app/api/settings/route.js +1 -1
  248. package/app/.next/server/app/api/settings/route.js.nft.json +1 -1
  249. package/app/.next/server/app/api/shutdown/route.js +1 -1
  250. package/app/.next/server/app/api/tags/route.js +1 -1
  251. package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
  252. package/app/.next/server/app/api/translator/console-logs/route.js.nft.json +1 -1
  253. package/app/.next/server/app/api/translator/console-logs/stream/route.js +2 -2
  254. package/app/.next/server/app/api/translator/console-logs/stream/route.js.nft.json +1 -1
  255. package/app/.next/server/app/api/translator/load/route.js +1 -1
  256. package/app/.next/server/app/api/translator/save/route.js +1 -1
  257. package/app/.next/server/app/api/translator/send/route.js +1 -1
  258. package/app/.next/server/app/api/translator/send/route.js.nft.json +1 -1
  259. package/app/.next/server/app/api/translator/translate/route.js +1 -1
  260. package/app/.next/server/app/api/translator/translate/route.js.nft.json +1 -1
  261. package/app/.next/server/app/api/tunnel/disable/route.js +1 -1
  262. package/app/.next/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  263. package/app/.next/server/app/api/tunnel/enable/route.js +1 -1
  264. package/app/.next/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  265. package/app/.next/server/app/api/tunnel/status/route.js +1 -1
  266. package/app/.next/server/app/api/tunnel/tailscale-check/route.js +1 -1
  267. package/app/.next/server/app/api/tunnel/tailscale-disable/route.js +1 -1
  268. package/app/.next/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
  269. package/app/.next/server/app/api/tunnel/tailscale-enable/route.js +1 -1
  270. package/app/.next/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
  271. package/app/.next/server/app/api/tunnel/tailscale-install/route.js +2 -2
  272. package/app/.next/server/app/api/usage/[connectionId]/codex-reset-credits/route.js +1 -1
  273. package/app/.next/server/app/api/usage/[connectionId]/codex-reset-credits/route.js.nft.json +1 -1
  274. package/app/.next/server/app/api/usage/[connectionId]/route.js +1 -1
  275. package/app/.next/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  276. package/app/.next/server/app/api/usage/chart/route.js +1 -1
  277. package/app/.next/server/app/api/usage/history/route.js +1 -1
  278. package/app/.next/server/app/api/usage/logs/route.js +1 -1
  279. package/app/.next/server/app/api/usage/providers/route.js +1 -1
  280. package/app/.next/server/app/api/usage/providers/route.js.nft.json +1 -1
  281. package/app/.next/server/app/api/usage/report/route.js +1 -1
  282. package/app/.next/server/app/api/usage/request-details/route.js +1 -1
  283. package/app/.next/server/app/api/usage/request-logs/route.js +1 -1
  284. package/app/.next/server/app/api/usage/stats/route.js +1 -1
  285. package/app/.next/server/app/api/usage/stream/route.js +2 -2
  286. package/app/.next/server/app/api/v1/api/chat/route.js +1 -1
  287. package/app/.next/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  288. package/app/.next/server/app/api/v1/audio/speech/route.js +1 -1
  289. package/app/.next/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  290. package/app/.next/server/app/api/v1/audio/transcriptions/route.js +1 -1
  291. package/app/.next/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  292. package/app/.next/server/app/api/v1/audio/voices/route.js +1 -1
  293. package/app/.next/server/app/api/v1/audio/voices/route.js.nft.json +1 -1
  294. package/app/.next/server/app/api/v1/chat/completions/route.js +1 -1
  295. package/app/.next/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  296. package/app/.next/server/app/api/v1/embeddings/route.js +1 -1
  297. package/app/.next/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  298. package/app/.next/server/app/api/v1/images/generations/route.js +1 -1
  299. package/app/.next/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  300. package/app/.next/server/app/api/v1/messages/count_tokens/route.js +1 -1
  301. package/app/.next/server/app/api/v1/messages/route.js +1 -1
  302. package/app/.next/server/app/api/v1/messages/route.js.nft.json +1 -1
  303. package/app/.next/server/app/api/v1/models/[kind]/route.js +1 -1
  304. package/app/.next/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
  305. package/app/.next/server/app/api/v1/models/info/route.js +1 -1
  306. package/app/.next/server/app/api/v1/models/info/route.js.nft.json +1 -1
  307. package/app/.next/server/app/api/v1/models/route.js +1 -1
  308. package/app/.next/server/app/api/v1/models/route.js.nft.json +1 -1
  309. package/app/.next/server/app/api/v1/responses/compact/route.js +1 -1
  310. package/app/.next/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
  311. package/app/.next/server/app/api/v1/responses/route.js +1 -1
  312. package/app/.next/server/app/api/v1/responses/route.js.nft.json +1 -1
  313. package/app/.next/server/app/api/v1/route.js +1 -1
  314. package/app/.next/server/app/api/v1/route.js.nft.json +1 -1
  315. package/app/.next/server/app/api/v1/search/route.js +1 -1
  316. package/app/.next/server/app/api/v1/search/route.js.nft.json +1 -1
  317. package/app/.next/server/app/api/v1/videos/[id]/route.js +1 -1
  318. package/app/.next/server/app/api/v1/videos/[id]/route.js.nft.json +1 -1
  319. package/app/.next/server/app/api/v1/videos/edits/route.js +1 -1
  320. package/app/.next/server/app/api/v1/videos/edits/route.js.nft.json +1 -1
  321. package/app/.next/server/app/api/v1/videos/extensions/route.js +1 -1
  322. package/app/.next/server/app/api/v1/videos/extensions/route.js.nft.json +1 -1
  323. package/app/.next/server/app/api/v1/videos/generations/route.js +1 -1
  324. package/app/.next/server/app/api/v1/videos/generations/route.js.nft.json +1 -1
  325. package/app/.next/server/app/api/v1/web/fetch/route.js +1 -1
  326. package/app/.next/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
  327. package/app/.next/server/app/api/v1beta/models/[...path]/route.js +1 -1
  328. package/app/.next/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  329. package/app/.next/server/app/api/v1beta/models/route.js +1 -1
  330. package/app/.next/server/app/api/v1beta/models/route.js.nft.json +1 -1
  331. package/app/.next/server/app/api/version/route.js +1 -1
  332. package/app/.next/server/app/api/version/shutdown/route.js +1 -1
  333. package/app/.next/server/app/api/version/shutdown/route.js.nft.json +1 -1
  334. package/app/.next/server/app/api/version/update/route.js +1 -1
  335. package/app/.next/server/app/api/version/update/route.js.nft.json +1 -1
  336. package/app/.next/server/app/callback/page.js +2 -2
  337. package/app/.next/server/app/callback/page.js.nft.json +1 -1
  338. package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  339. package/app/.next/server/app/callback.html +1 -1
  340. package/app/.next/server/app/callback.rsc +4 -4
  341. package/app/.next/server/app/callback.segments/_full.segment.rsc +4 -4
  342. package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
  343. package/app/.next/server/app/callback.segments/_index.segment.rsc +4 -4
  344. package/app/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
  345. package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  346. package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
  347. package/app/.next/server/app/dashboard/basic-chat.html +1 -1
  348. package/app/.next/server/app/dashboard/basic-chat.rsc +6 -6
  349. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
  350. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
  351. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  352. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  353. package/app/.next/server/app/dashboard/basic-chat.segments/_full.segment.rsc +6 -6
  354. package/app/.next/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
  355. package/app/.next/server/app/dashboard/basic-chat.segments/_index.segment.rsc +4 -4
  356. package/app/.next/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +2 -2
  357. package/app/.next/server/app/dashboard/cli-tools.html +1 -1
  358. package/app/.next/server/app/dashboard/cli-tools.rsc +6 -6
  359. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  360. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  361. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  362. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  363. package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +6 -6
  364. package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  365. package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +4 -4
  366. package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
  367. package/app/.next/server/app/dashboard/combos.html +1 -1
  368. package/app/.next/server/app/dashboard/combos.rsc +6 -6
  369. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  370. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  371. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  372. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  373. package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +6 -6
  374. package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  375. package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +4 -4
  376. package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
  377. package/app/.next/server/app/dashboard/endpoint.html +1 -1
  378. package/app/.next/server/app/dashboard/endpoint.rsc +6 -6
  379. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  380. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  381. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  382. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  383. package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +6 -6
  384. package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  385. package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +4 -4
  386. package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
  387. package/app/.next/server/app/dashboard/media-providers/web.html +1 -1
  388. package/app/.next/server/app/dashboard/media-providers/web.rsc +6 -6
  389. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
  390. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
  391. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
  392. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  393. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  394. package/app/.next/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +6 -6
  395. package/app/.next/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
  396. package/app/.next/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +4 -4
  397. package/app/.next/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +2 -2
  398. package/app/.next/server/app/dashboard/mitm.html +1 -1
  399. package/app/.next/server/app/dashboard/mitm.rsc +6 -6
  400. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  401. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  402. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  403. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  404. package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +6 -6
  405. package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  406. package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +4 -4
  407. package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
  408. package/app/.next/server/app/dashboard/profile.html +1 -1
  409. package/app/.next/server/app/dashboard/profile.rsc +6 -6
  410. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  411. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  412. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  413. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  414. package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +6 -6
  415. package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  416. package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +4 -4
  417. package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
  418. package/app/.next/server/app/dashboard/providers/new.html +1 -1
  419. package/app/.next/server/app/dashboard/providers/new.rsc +6 -6
  420. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  421. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  422. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  423. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  424. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  425. package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +6 -6
  426. package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  427. package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +4 -4
  428. package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
  429. package/app/.next/server/app/dashboard/providers.html +1 -1
  430. package/app/.next/server/app/dashboard/providers.rsc +6 -6
  431. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  432. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  433. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  434. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  435. package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +6 -6
  436. package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  437. package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +4 -4
  438. package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
  439. package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
  440. package/app/.next/server/app/dashboard/proxy-pools.rsc +6 -6
  441. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  442. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  443. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  444. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  445. package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +6 -6
  446. package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  447. package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +4 -4
  448. package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
  449. package/app/.next/server/app/dashboard/pxpipe.html +1 -1
  450. package/app/.next/server/app/dashboard/pxpipe.rsc +6 -6
  451. package/app/.next/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +2 -2
  452. package/app/.next/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe.segment.rsc +1 -1
  453. package/app/.next/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  454. package/app/.next/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  455. package/app/.next/server/app/dashboard/pxpipe.segments/_full.segment.rsc +6 -6
  456. package/app/.next/server/app/dashboard/pxpipe.segments/_head.segment.rsc +1 -1
  457. package/app/.next/server/app/dashboard/pxpipe.segments/_index.segment.rsc +4 -4
  458. package/app/.next/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +2 -2
  459. package/app/.next/server/app/dashboard/quota.html +2 -2
  460. package/app/.next/server/app/dashboard/quota.rsc +7 -7
  461. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
  462. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  463. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  464. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  465. package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +7 -7
  466. package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  467. package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +4 -4
  468. package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
  469. package/app/.next/server/app/dashboard/settings/pricing/page.js +2 -2
  470. package/app/.next/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
  471. package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  472. package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
  473. package/app/.next/server/app/dashboard/settings/pricing.rsc +4 -4
  474. package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +4 -4
  475. package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  476. package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +4 -4
  477. package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
  478. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  479. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  480. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  481. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  482. package/app/.next/server/app/dashboard/skills.html +1 -1
  483. package/app/.next/server/app/dashboard/skills.rsc +6 -6
  484. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
  485. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
  486. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  487. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  488. package/app/.next/server/app/dashboard/skills.segments/_full.segment.rsc +6 -6
  489. package/app/.next/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
  490. package/app/.next/server/app/dashboard/skills.segments/_index.segment.rsc +4 -4
  491. package/app/.next/server/app/dashboard/skills.segments/_tree.segment.rsc +2 -2
  492. package/app/.next/server/app/dashboard/token-saver.html +1 -1
  493. package/app/.next/server/app/dashboard/token-saver.rsc +6 -6
  494. package/app/.next/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +2 -2
  495. package/app/.next/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver.segment.rsc +1 -1
  496. package/app/.next/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  497. package/app/.next/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  498. package/app/.next/server/app/dashboard/token-saver.segments/_full.segment.rsc +6 -6
  499. package/app/.next/server/app/dashboard/token-saver.segments/_head.segment.rsc +1 -1
  500. package/app/.next/server/app/dashboard/token-saver.segments/_index.segment.rsc +4 -4
  501. package/app/.next/server/app/dashboard/token-saver.segments/_tree.segment.rsc +2 -2
  502. package/app/.next/server/app/dashboard/translator.html +1 -1
  503. package/app/.next/server/app/dashboard/translator.rsc +6 -6
  504. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  505. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  506. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  507. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  508. package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +6 -6
  509. package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  510. package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +4 -4
  511. package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
  512. package/app/.next/server/app/dashboard/usage.html +1 -1
  513. package/app/.next/server/app/dashboard/usage.rsc +6 -6
  514. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  515. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  516. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  517. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  518. package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +6 -6
  519. package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  520. package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +4 -4
  521. package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
  522. package/app/.next/server/app/dashboard.html +1 -1
  523. package/app/.next/server/app/dashboard.rsc +6 -6
  524. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  525. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  526. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  527. package/app/.next/server/app/dashboard.segments/_full.segment.rsc +6 -6
  528. package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
  529. package/app/.next/server/app/dashboard.segments/_index.segment.rsc +4 -4
  530. package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +2 -2
  531. package/app/.next/server/app/favicon.ico/route.js +1 -1
  532. package/app/.next/server/app/index.html +1 -1
  533. package/app/.next/server/app/index.rsc +4 -4
  534. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  535. package/app/.next/server/app/index.segments/_full.segment.rsc +4 -4
  536. package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
  537. package/app/.next/server/app/index.segments/_index.segment.rsc +4 -4
  538. package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  539. package/app/.next/server/app/landing/page.js +2 -2
  540. package/app/.next/server/app/landing/page.js.nft.json +1 -1
  541. package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  542. package/app/.next/server/app/landing.html +1 -1
  543. package/app/.next/server/app/landing.rsc +4 -4
  544. package/app/.next/server/app/landing.segments/_full.segment.rsc +4 -4
  545. package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
  546. package/app/.next/server/app/landing.segments/_index.segment.rsc +4 -4
  547. package/app/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
  548. package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  549. package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
  550. package/app/.next/server/app/login/page.js +2 -2
  551. package/app/.next/server/app/login/page.js.nft.json +1 -1
  552. package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
  553. package/app/.next/server/app/login.html +1 -1
  554. package/app/.next/server/app/login.rsc +5 -5
  555. package/app/.next/server/app/login.segments/_full.segment.rsc +5 -5
  556. package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
  557. package/app/.next/server/app/login.segments/_index.segment.rsc +4 -4
  558. package/app/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  559. package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  560. package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
  561. package/app/.next/server/app/manifest.webmanifest/route.js +2 -2
  562. package/app/.next/server/app/page.js +2 -2
  563. package/app/.next/server/app/page.js.nft.json +1 -1
  564. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  565. package/app/.next/server/app-paths-manifest.json +16 -12
  566. package/app/.next/server/chunks/112.js +1 -1
  567. package/app/.next/server/chunks/1470.js +1 -1
  568. package/app/.next/server/chunks/2251.js +1 -1
  569. package/app/.next/server/chunks/241.js +1 -1
  570. package/app/.next/server/chunks/318.js +26 -34
  571. package/app/.next/server/chunks/3481.js +1 -1
  572. package/app/.next/server/chunks/3913.js +1 -1
  573. package/app/.next/server/chunks/4037.js +1 -1
  574. package/app/.next/server/chunks/412.js +1 -1
  575. package/app/.next/server/chunks/4123.js +1 -1
  576. package/app/.next/server/chunks/4125.js +1 -1
  577. package/app/.next/server/chunks/4443.js +1 -1
  578. package/app/.next/server/chunks/4705.js +1 -1
  579. package/app/.next/server/chunks/4953.js +1 -0
  580. package/app/.next/server/chunks/4975.js +1 -1
  581. package/app/.next/server/chunks/5081.js +29 -0
  582. package/app/.next/server/chunks/5285.js +1 -0
  583. package/app/.next/server/chunks/5612.js +1 -1
  584. package/app/.next/server/chunks/5699.js +1 -1
  585. package/app/.next/server/chunks/6070.js +1 -1
  586. package/app/.next/server/chunks/615.js +1 -1
  587. package/app/.next/server/chunks/6630.js +1 -1
  588. package/app/.next/server/chunks/6671.js +1 -1
  589. package/app/.next/server/chunks/7137.js +1 -1
  590. package/app/.next/server/chunks/7211.js +1 -1
  591. package/app/.next/server/chunks/8145.js +1 -1
  592. package/app/.next/server/chunks/8301.js +3 -2
  593. package/app/.next/server/chunks/8499.js +7 -7
  594. package/app/.next/server/chunks/869.js +1 -1
  595. package/app/.next/server/chunks/8895.js +4 -4
  596. package/app/.next/server/chunks/8910.js +2 -2
  597. package/app/.next/server/chunks/9718.js +1 -1
  598. package/app/.next/server/instrumentation.js +1 -1
  599. package/app/.next/server/middleware-build-manifest.js +1 -1
  600. package/app/.next/server/middleware.js +2 -2
  601. package/app/.next/server/pages/404.html +1 -1
  602. package/app/.next/server/pages/500.html +1 -1
  603. package/app/.next/server/server-reference-manifest.js +1 -1
  604. package/app/.next/server/server-reference-manifest.json +1 -1
  605. package/app/.next/static/chunks/1321-99f0141dbac9848a.js +1 -0
  606. package/app/.next/static/chunks/{4028-f5a8d63d47b1b2cf.js → 4028-9d0d68c835868df5.js} +10 -9
  607. package/app/.next/static/chunks/{5497-91a1a5870e39d2d0.js → 5497-017258c3c16b719e.js} +2 -2
  608. package/app/.next/static/chunks/8198-bf66ab4ae1cda8e0.js +1 -0
  609. package/app/.next/static/chunks/app/(dashboard)/dashboard/profile/page-0d1269add49cb3e2.js +1 -0
  610. package/app/.next/static/chunks/app/(dashboard)/dashboard/quota/page-c8a6e0e2bef2932e.js +1 -0
  611. package/app/.next/static/chunks/app/(dashboard)/dashboard/token-saver/page-46e9c726ae1032e0.js +1 -0
  612. package/app/.next/static/chunks/app/_global-error/page-1a2fcb867d9ffccf.js +1 -0
  613. package/app/.next/static/chunks/app/api/antigravity-app/route-1a2fcb867d9ffccf.js +1 -0
  614. package/app/.next/static/chunks/app/api/antigravity-app-v2/route-1a2fcb867d9ffccf.js +1 -0
  615. package/app/.next/static/chunks/app/api/antigravity-ide/route-1a2fcb867d9ffccf.js +1 -0
  616. package/app/.next/static/chunks/app/api/antigravity-targets/route-1a2fcb867d9ffccf.js +1 -0
  617. package/app/.next/static/chunks/app/api/antigravity-tools/import/route-1a2fcb867d9ffccf.js +1 -0
  618. package/app/.next/static/chunks/app/api/antigravity-tools/import-refresh-tokens/route-1a2fcb867d9ffccf.js +1 -0
  619. package/app/.next/static/chunks/app/api/auth/login/route-1a2fcb867d9ffccf.js +1 -0
  620. package/app/.next/static/chunks/app/api/auth/logout/route-1a2fcb867d9ffccf.js +1 -0
  621. package/app/.next/static/chunks/app/api/auth/oidc/callback/route-1a2fcb867d9ffccf.js +1 -0
  622. package/app/.next/static/chunks/app/api/auth/oidc/start/route-1a2fcb867d9ffccf.js +1 -0
  623. package/app/.next/static/chunks/app/api/auth/oidc/test/route-1a2fcb867d9ffccf.js +1 -0
  624. package/app/.next/static/chunks/app/api/auth/reset-password/route-1a2fcb867d9ffccf.js +1 -0
  625. package/app/.next/static/chunks/app/api/auth/saml/acs/route-1a2fcb867d9ffccf.js +1 -0
  626. package/app/.next/static/chunks/app/api/auth/saml/metadata/route-1a2fcb867d9ffccf.js +1 -0
  627. package/app/.next/static/chunks/app/api/auth/saml/start/route-1a2fcb867d9ffccf.js +1 -0
  628. package/app/.next/static/chunks/app/api/auth/saml/test/route-1a2fcb867d9ffccf.js +1 -0
  629. package/app/.next/static/chunks/app/api/auth/status/route-1a2fcb867d9ffccf.js +1 -0
  630. package/app/.next/static/chunks/app/api/cli-tools/all-statuses/route-1a2fcb867d9ffccf.js +1 -0
  631. package/app/.next/static/chunks/app/api/cli-tools/antigravity-mitm/alias/route-1a2fcb867d9ffccf.js +1 -0
  632. package/app/.next/static/chunks/app/api/cli-tools/antigravity-mitm/route-1a2fcb867d9ffccf.js +1 -0
  633. package/app/.next/static/chunks/app/api/cli-tools/claude-settings/route-1a2fcb867d9ffccf.js +1 -0
  634. package/app/.next/static/chunks/app/api/cli-tools/cline-settings/route-1a2fcb867d9ffccf.js +1 -0
  635. package/app/.next/static/chunks/app/api/cli-tools/codex-settings/route-1a2fcb867d9ffccf.js +1 -0
  636. package/app/.next/static/chunks/app/api/cli-tools/copilot-settings/route-1a2fcb867d9ffccf.js +1 -0
  637. package/app/.next/static/chunks/app/api/cli-tools/cowork-mcp-registry/route-1a2fcb867d9ffccf.js +1 -0
  638. package/app/.next/static/chunks/app/api/cli-tools/cowork-mcp-tools/route-1a2fcb867d9ffccf.js +1 -0
  639. package/app/.next/static/chunks/app/api/cli-tools/cowork-settings/route-1a2fcb867d9ffccf.js +1 -0
  640. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/[jobId]/events/route-1a2fcb867d9ffccf.js +1 -0
  641. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/[jobId]/sudo/route-1a2fcb867d9ffccf.js +1 -0
  642. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/route-1a2fcb867d9ffccf.js +1 -0
  643. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/route-1a2fcb867d9ffccf.js +1 -0
  644. package/app/.next/static/chunks/app/api/cli-tools/deepseek-tui-settings/route-1a2fcb867d9ffccf.js +1 -0
  645. package/app/.next/static/chunks/app/api/cli-tools/devin-settings/route-1a2fcb867d9ffccf.js +1 -0
  646. package/app/.next/static/chunks/app/api/cli-tools/droid-settings/route-1a2fcb867d9ffccf.js +1 -0
  647. package/app/.next/static/chunks/app/api/cli-tools/grok-build-settings/route-1a2fcb867d9ffccf.js +1 -0
  648. package/app/.next/static/chunks/app/api/cli-tools/hermes-settings/route-1a2fcb867d9ffccf.js +1 -0
  649. package/app/.next/static/chunks/app/api/cli-tools/jcode-settings/route-1a2fcb867d9ffccf.js +1 -0
  650. package/app/.next/static/chunks/app/api/cli-tools/kilo-settings/route-1a2fcb867d9ffccf.js +1 -0
  651. package/app/.next/static/chunks/app/api/cli-tools/openclaw-settings/route-1a2fcb867d9ffccf.js +1 -0
  652. package/app/.next/static/chunks/app/api/cli-tools/opencode-settings/route-1a2fcb867d9ffccf.js +1 -0
  653. package/app/.next/static/chunks/app/api/combos/[id]/route-1a2fcb867d9ffccf.js +1 -0
  654. package/app/.next/static/chunks/app/api/combos/route-1a2fcb867d9ffccf.js +1 -0
  655. package/app/.next/static/chunks/app/api/donate/route-1a2fcb867d9ffccf.js +1 -0
  656. package/app/.next/static/chunks/app/api/headroom/extras/route-1a2fcb867d9ffccf.js +1 -0
  657. package/app/.next/static/chunks/app/api/headroom/proxy/[...path]/route-1a2fcb867d9ffccf.js +1 -0
  658. package/app/.next/static/chunks/app/api/headroom/restart/route-1a2fcb867d9ffccf.js +1 -0
  659. package/app/.next/static/chunks/app/api/headroom/start/route-1a2fcb867d9ffccf.js +1 -0
  660. package/app/.next/static/chunks/app/api/headroom/status/route-1a2fcb867d9ffccf.js +1 -0
  661. package/app/.next/static/chunks/app/api/headroom/stop/route-1a2fcb867d9ffccf.js +1 -0
  662. package/app/.next/static/chunks/app/api/health/route-1a2fcb867d9ffccf.js +1 -0
  663. package/app/.next/static/chunks/app/api/init/route-1a2fcb867d9ffccf.js +1 -0
  664. package/app/.next/static/chunks/app/api/internal/account-health/route-1a2fcb867d9ffccf.js +1 -0
  665. package/app/.next/static/chunks/app/api/internal/request-detail/route-1a2fcb867d9ffccf.js +1 -0
  666. package/app/.next/static/chunks/app/api/internal/usage/route-1a2fcb867d9ffccf.js +1 -0
  667. package/app/.next/static/chunks/app/api/keys/[id]/reset-usage/route-1a2fcb867d9ffccf.js +1 -0
  668. package/app/.next/static/chunks/app/api/keys/[id]/route-1a2fcb867d9ffccf.js +1 -0
  669. package/app/.next/static/chunks/app/api/keys/[id]/usage/route-1a2fcb867d9ffccf.js +1 -0
  670. package/app/.next/static/chunks/app/api/keys/route-1a2fcb867d9ffccf.js +1 -0
  671. package/app/.next/static/chunks/app/api/locale/route-1a2fcb867d9ffccf.js +1 -0
  672. package/app/.next/static/chunks/app/api/mcp/[plugin]/message/route-1a2fcb867d9ffccf.js +1 -0
  673. package/app/.next/static/chunks/app/api/mcp/[plugin]/sse/route-1a2fcb867d9ffccf.js +1 -0
  674. package/app/.next/static/chunks/app/api/media-providers/tts/deepgram/voices/route-1a2fcb867d9ffccf.js +1 -0
  675. package/app/.next/static/chunks/app/api/media-providers/tts/elevenlabs/voices/route-1a2fcb867d9ffccf.js +1 -0
  676. package/app/.next/static/chunks/app/api/media-providers/tts/inworld/voices/route-1a2fcb867d9ffccf.js +1 -0
  677. package/app/.next/static/chunks/app/api/media-providers/tts/minimax/voices/route-1a2fcb867d9ffccf.js +1 -0
  678. package/app/.next/static/chunks/app/api/media-providers/tts/voices/route-1a2fcb867d9ffccf.js +1 -0
  679. package/app/.next/static/chunks/app/api/models/alias/route-1a2fcb867d9ffccf.js +1 -0
  680. package/app/.next/static/chunks/app/api/models/availability/route-1a2fcb867d9ffccf.js +1 -0
  681. package/app/.next/static/chunks/app/api/models/custom/route-1a2fcb867d9ffccf.js +1 -0
  682. package/app/.next/static/chunks/app/api/models/disabled/route-1a2fcb867d9ffccf.js +1 -0
  683. package/app/.next/static/chunks/app/api/models/route-1a2fcb867d9ffccf.js +1 -0
  684. package/app/.next/static/chunks/app/api/models/test/route-1a2fcb867d9ffccf.js +1 -0
  685. package/app/.next/static/chunks/app/api/oauth/[provider]/[action]/route-1a2fcb867d9ffccf.js +1 -0
  686. package/app/.next/static/chunks/app/api/oauth/codex/bulk-import/route-1a2fcb867d9ffccf.js +1 -0
  687. package/app/.next/static/chunks/app/api/oauth/codex/import-token/route-1a2fcb867d9ffccf.js +1 -0
  688. package/app/.next/static/chunks/app/api/oauth/cursor/auto-import/route-1a2fcb867d9ffccf.js +1 -0
  689. package/app/.next/static/chunks/app/api/oauth/cursor/import/route-1a2fcb867d9ffccf.js +1 -0
  690. package/app/.next/static/chunks/app/api/oauth/gitlab/pat/route-1a2fcb867d9ffccf.js +1 -0
  691. package/app/.next/static/chunks/app/api/oauth/iflow/cookie/route-1a2fcb867d9ffccf.js +1 -0
  692. package/app/.next/static/chunks/app/api/oauth/kiro/api-key/route-1a2fcb867d9ffccf.js +1 -0
  693. package/app/.next/static/chunks/app/api/oauth/kiro/auto-import/route-1a2fcb867d9ffccf.js +1 -0
  694. package/app/.next/static/chunks/app/api/oauth/kiro/import/route-1a2fcb867d9ffccf.js +1 -0
  695. package/app/.next/static/chunks/app/api/oauth/kiro/import-cli-proxy/route-1a2fcb867d9ffccf.js +1 -0
  696. package/app/.next/static/chunks/app/api/oauth/kiro/social-authorize/route-1a2fcb867d9ffccf.js +1 -0
  697. package/app/.next/static/chunks/app/api/oauth/kiro/social-exchange/route-1a2fcb867d9ffccf.js +1 -0
  698. package/app/.next/static/chunks/app/api/pricing/route-1a2fcb867d9ffccf.js +1 -0
  699. package/app/.next/static/chunks/app/api/provider-nodes/[id]/route-1a2fcb867d9ffccf.js +1 -0
  700. package/app/.next/static/chunks/app/api/provider-nodes/route-1a2fcb867d9ffccf.js +1 -0
  701. package/app/.next/static/chunks/app/api/provider-nodes/validate/route-1a2fcb867d9ffccf.js +1 -0
  702. package/app/.next/static/chunks/app/api/providers/[id]/models/route-1a2fcb867d9ffccf.js +1 -0
  703. package/app/.next/static/chunks/app/api/providers/[id]/route-1a2fcb867d9ffccf.js +1 -0
  704. package/app/.next/static/chunks/app/api/providers/[id]/test/route-1a2fcb867d9ffccf.js +1 -0
  705. package/app/.next/static/chunks/app/api/providers/[id]/test-models/route-1a2fcb867d9ffccf.js +1 -0
  706. package/app/.next/static/chunks/app/api/providers/client/route-1a2fcb867d9ffccf.js +1 -0
  707. package/app/.next/static/chunks/app/api/providers/kilo/free-models/route-1a2fcb867d9ffccf.js +1 -0
  708. package/app/.next/static/chunks/app/api/providers/route-1a2fcb867d9ffccf.js +1 -0
  709. package/app/.next/static/chunks/app/api/providers/suggested-models/route-1a2fcb867d9ffccf.js +1 -0
  710. package/app/.next/static/chunks/app/api/providers/test-batch/route-1a2fcb867d9ffccf.js +1 -0
  711. package/app/.next/static/chunks/app/api/providers/validate/route-1a2fcb867d9ffccf.js +1 -0
  712. package/app/.next/static/chunks/app/api/proxy-pools/[id]/route-1a2fcb867d9ffccf.js +1 -0
  713. package/app/.next/static/chunks/app/api/proxy-pools/[id]/test/route-1a2fcb867d9ffccf.js +1 -0
  714. package/app/.next/static/chunks/app/api/proxy-pools/cloudflare-deploy/route-1a2fcb867d9ffccf.js +1 -0
  715. package/app/.next/static/chunks/app/api/proxy-pools/deno-deploy/route-1a2fcb867d9ffccf.js +1 -0
  716. package/app/.next/static/chunks/app/api/proxy-pools/route-1a2fcb867d9ffccf.js +1 -0
  717. package/app/.next/static/chunks/app/api/proxy-pools/vercel-deploy/route-1a2fcb867d9ffccf.js +1 -0
  718. package/app/.next/static/chunks/app/api/pxpipe/health/route-1a2fcb867d9ffccf.js +1 -0
  719. package/app/.next/static/chunks/app/api/pxpipe/install/route-1a2fcb867d9ffccf.js +1 -0
  720. package/app/.next/static/chunks/app/api/pxpipe/logs/route-1a2fcb867d9ffccf.js +1 -0
  721. package/app/.next/static/chunks/app/api/pxpipe/restart/route-1a2fcb867d9ffccf.js +1 -0
  722. package/app/.next/static/chunks/app/api/pxpipe/start/route-1a2fcb867d9ffccf.js +1 -0
  723. package/app/.next/static/chunks/app/api/pxpipe/stats/route-1a2fcb867d9ffccf.js +1 -0
  724. package/app/.next/static/chunks/app/api/pxpipe/status/route-1a2fcb867d9ffccf.js +1 -0
  725. package/app/.next/static/chunks/app/api/pxpipe/stop/route-1a2fcb867d9ffccf.js +1 -0
  726. package/app/.next/static/chunks/app/api/settings/database/route-1a2fcb867d9ffccf.js +1 -0
  727. package/app/.next/static/chunks/app/api/settings/database/selective/route-1a2fcb867d9ffccf.js +1 -0
  728. package/app/.next/static/chunks/app/api/settings/proxy-test/route-1a2fcb867d9ffccf.js +1 -0
  729. package/app/.next/static/chunks/app/api/settings/require-login/route-1a2fcb867d9ffccf.js +1 -0
  730. package/app/.next/static/chunks/app/api/settings/route-1a2fcb867d9ffccf.js +1 -0
  731. package/app/.next/static/chunks/app/api/shutdown/route-1a2fcb867d9ffccf.js +1 -0
  732. package/app/.next/static/chunks/app/api/tags/route-1a2fcb867d9ffccf.js +1 -0
  733. package/app/.next/static/chunks/app/api/translator/console-logs/route-1a2fcb867d9ffccf.js +1 -0
  734. package/app/.next/static/chunks/app/api/translator/console-logs/stream/route-1a2fcb867d9ffccf.js +1 -0
  735. package/app/.next/static/chunks/app/api/translator/load/route-1a2fcb867d9ffccf.js +1 -0
  736. package/app/.next/static/chunks/app/api/translator/save/route-1a2fcb867d9ffccf.js +1 -0
  737. package/app/.next/static/chunks/app/api/translator/send/route-1a2fcb867d9ffccf.js +1 -0
  738. package/app/.next/static/chunks/app/api/translator/translate/route-1a2fcb867d9ffccf.js +1 -0
  739. package/app/.next/static/chunks/app/api/tunnel/disable/route-1a2fcb867d9ffccf.js +1 -0
  740. package/app/.next/static/chunks/app/api/tunnel/enable/route-1a2fcb867d9ffccf.js +1 -0
  741. package/app/.next/static/chunks/app/api/tunnel/status/route-1a2fcb867d9ffccf.js +1 -0
  742. package/app/.next/static/chunks/app/api/tunnel/tailscale-check/route-1a2fcb867d9ffccf.js +1 -0
  743. package/app/.next/static/chunks/app/api/tunnel/tailscale-disable/route-1a2fcb867d9ffccf.js +1 -0
  744. package/app/.next/static/chunks/app/api/tunnel/tailscale-enable/route-1a2fcb867d9ffccf.js +1 -0
  745. package/app/.next/static/chunks/app/api/tunnel/tailscale-install/route-1a2fcb867d9ffccf.js +1 -0
  746. package/app/.next/static/chunks/app/api/usage/[connectionId]/codex-reset-credits/route-1a2fcb867d9ffccf.js +1 -0
  747. package/app/.next/static/chunks/app/api/usage/[connectionId]/route-1a2fcb867d9ffccf.js +1 -0
  748. package/app/.next/static/chunks/app/api/usage/chart/route-1a2fcb867d9ffccf.js +1 -0
  749. package/app/.next/static/chunks/app/api/usage/history/route-1a2fcb867d9ffccf.js +1 -0
  750. package/app/.next/static/chunks/app/api/usage/logs/route-1a2fcb867d9ffccf.js +1 -0
  751. package/app/.next/static/chunks/app/api/usage/providers/route-1a2fcb867d9ffccf.js +1 -0
  752. package/app/.next/static/chunks/app/api/usage/report/route-1a2fcb867d9ffccf.js +1 -0
  753. package/app/.next/static/chunks/app/api/usage/request-details/route-1a2fcb867d9ffccf.js +1 -0
  754. package/app/.next/static/chunks/app/api/usage/request-logs/route-1a2fcb867d9ffccf.js +1 -0
  755. package/app/.next/static/chunks/app/api/usage/stats/route-1a2fcb867d9ffccf.js +1 -0
  756. package/app/.next/static/chunks/app/api/usage/stream/route-1a2fcb867d9ffccf.js +1 -0
  757. package/app/.next/static/chunks/app/api/v1/api/chat/route-1a2fcb867d9ffccf.js +1 -0
  758. package/app/.next/static/chunks/app/api/v1/audio/speech/route-1a2fcb867d9ffccf.js +1 -0
  759. package/app/.next/static/chunks/app/api/v1/audio/transcriptions/route-1a2fcb867d9ffccf.js +1 -0
  760. package/app/.next/static/chunks/app/api/v1/audio/voices/route-1a2fcb867d9ffccf.js +1 -0
  761. package/app/.next/static/chunks/app/api/v1/chat/completions/route-1a2fcb867d9ffccf.js +1 -0
  762. package/app/.next/static/chunks/app/api/v1/embeddings/route-1a2fcb867d9ffccf.js +1 -0
  763. package/app/.next/static/chunks/app/api/v1/images/generations/route-1a2fcb867d9ffccf.js +1 -0
  764. package/app/.next/static/chunks/app/api/v1/messages/count_tokens/route-1a2fcb867d9ffccf.js +1 -0
  765. package/app/.next/static/chunks/app/api/v1/messages/route-1a2fcb867d9ffccf.js +1 -0
  766. package/app/.next/static/chunks/app/api/v1/models/[kind]/route-1a2fcb867d9ffccf.js +1 -0
  767. package/app/.next/static/chunks/app/api/v1/models/info/route-1a2fcb867d9ffccf.js +1 -0
  768. package/app/.next/static/chunks/app/api/v1/models/route-1a2fcb867d9ffccf.js +1 -0
  769. package/app/.next/static/chunks/app/api/v1/responses/compact/route-1a2fcb867d9ffccf.js +1 -0
  770. package/app/.next/static/chunks/app/api/v1/responses/route-1a2fcb867d9ffccf.js +1 -0
  771. package/app/.next/static/chunks/app/api/v1/route-1a2fcb867d9ffccf.js +1 -0
  772. package/app/.next/static/chunks/app/api/v1/search/route-1a2fcb867d9ffccf.js +1 -0
  773. package/app/.next/static/chunks/app/api/v1/videos/[id]/route-1a2fcb867d9ffccf.js +1 -0
  774. package/app/.next/static/chunks/app/api/v1/videos/edits/route-1a2fcb867d9ffccf.js +1 -0
  775. package/app/.next/static/chunks/app/api/v1/videos/extensions/route-1a2fcb867d9ffccf.js +1 -0
  776. package/app/.next/static/chunks/app/api/v1/videos/generations/route-1a2fcb867d9ffccf.js +1 -0
  777. package/app/.next/static/chunks/app/api/v1/web/fetch/route-1a2fcb867d9ffccf.js +1 -0
  778. package/app/.next/static/chunks/app/api/v1beta/models/[...path]/route-1a2fcb867d9ffccf.js +1 -0
  779. package/app/.next/static/chunks/app/api/v1beta/models/route-1a2fcb867d9ffccf.js +1 -0
  780. package/app/.next/static/chunks/app/api/version/route-1a2fcb867d9ffccf.js +1 -0
  781. package/app/.next/static/chunks/app/api/version/shutdown/route-1a2fcb867d9ffccf.js +1 -0
  782. package/app/.next/static/chunks/app/api/version/update/route-1a2fcb867d9ffccf.js +1 -0
  783. package/app/.next/static/chunks/app/login/page-e6ff5089ced15cea.js +1 -0
  784. package/app/.next/static/chunks/app/manifest.webmanifest/route-1a2fcb867d9ffccf.js +1 -0
  785. package/app/.next/static/chunks/app/page-1a2fcb867d9ffccf.js +1 -0
  786. package/app/.next/static/chunks/next/dist/client/components/builtin/app-error-1a2fcb867d9ffccf.js +1 -0
  787. package/app/.next/static/chunks/next/dist/client/components/builtin/forbidden-1a2fcb867d9ffccf.js +1 -0
  788. package/app/.next/static/chunks/next/dist/client/components/builtin/not-found-1a2fcb867d9ffccf.js +1 -0
  789. package/app/.next/static/chunks/next/dist/client/components/builtin/unauthorized-1a2fcb867d9ffccf.js +1 -0
  790. package/app/.next/static/css/c5181f678ef0b6e0.css +1 -0
  791. package/app/.next/static/flxITMsAmoXf-wWjPORMD/_buildManifest.js +1 -0
  792. package/app/custom-server.js +139 -0
  793. package/app/open-sse/config/providerModels.js +9 -1
  794. package/app/open-sse/executors/antigravity.js +12 -0
  795. package/app/open-sse/executors/index.js +0 -3
  796. package/app/open-sse/executors/kiro.js +1162 -530
  797. package/app/open-sse/executors/opencode.js +43 -5
  798. package/app/open-sse/executors/qoder.js +91 -5
  799. package/app/open-sse/handlers/chatCore/requestDetail.js +7 -6
  800. package/app/open-sse/handlers/chatCore.js +19 -5
  801. package/app/open-sse/handlers/search/callers.js +21 -0
  802. package/app/open-sse/handlers/ttsProviders/genericFormats.js +20 -0
  803. package/app/open-sse/providers/models/schema.js +8 -0
  804. package/app/open-sse/providers/registry/alitp-intl.js +35 -0
  805. package/app/open-sse/providers/registry/fish-audio.js +31 -0
  806. package/app/open-sse/providers/registry/glm-cn.js +1 -0
  807. package/app/open-sse/providers/registry/glm.js +1 -0
  808. package/app/open-sse/providers/registry/index.js +4 -0
  809. package/app/open-sse/providers/registry/kimchi.js +1 -1
  810. package/app/open-sse/providers/registry/opencode-go.js +22 -14
  811. package/app/open-sse/services/combo.js +39 -2
  812. package/app/open-sse/services/usage/claude.js +37 -1
  813. package/app/open-sse/services/usage.js +11 -3
  814. package/app/open-sse/translator/concerns/modality.js +13 -0
  815. package/app/open-sse/translator/formats/claude.js +93 -20
  816. package/app/open-sse/translator/request/claude-to-kiro.js +12 -0
  817. package/app/open-sse/translator/request/openai-responses.js +1 -0
  818. package/app/open-sse/translator/request/openai-to-kiro.js +12 -0
  819. package/app/open-sse/translator/response/kiro-to-claude.js +16 -0
  820. package/app/open-sse/translator/response/openai-responses.js +2 -2
  821. package/app/package.json +5 -4
  822. package/app/src/mitm/config.js +19 -1
  823. package/app/src/mitm/server.js +3 -4
  824. package/app/src/shared/constants/cliTools.js +6 -1
  825. package/bin/n9router.js +13 -1
  826. package/package.json +1 -1
  827. package/app/.next/server/chunks/4963.js +0 -1
  828. package/app/.next/server/chunks/5619.js +0 -1
  829. package/app/.next/static/__qB-b0EP9cu_2Y1YJiUT/_buildManifest.js +0 -1
  830. package/app/.next/static/chunks/1321-d151de24f85b1705.js +0 -1
  831. package/app/.next/static/chunks/8198-6ba877462e24c355.js +0 -1
  832. package/app/.next/static/chunks/app/(dashboard)/dashboard/profile/page-8aff85e95a62beda.js +0 -1
  833. package/app/.next/static/chunks/app/(dashboard)/dashboard/quota/page-6916d780a2d54b89.js +0 -1
  834. package/app/.next/static/chunks/app/(dashboard)/dashboard/token-saver/page-16a983d7f45461ec.js +0 -1
  835. package/app/.next/static/chunks/app/_global-error/page-c74ff3c527010d28.js +0 -1
  836. package/app/.next/static/chunks/app/api/antigravity-app/route-c74ff3c527010d28.js +0 -1
  837. package/app/.next/static/chunks/app/api/antigravity-app-v2/route-c74ff3c527010d28.js +0 -1
  838. package/app/.next/static/chunks/app/api/antigravity-ide/route-c74ff3c527010d28.js +0 -1
  839. package/app/.next/static/chunks/app/api/antigravity-targets/route-c74ff3c527010d28.js +0 -1
  840. package/app/.next/static/chunks/app/api/antigravity-tools/import/route-c74ff3c527010d28.js +0 -1
  841. package/app/.next/static/chunks/app/api/antigravity-tools/import-refresh-tokens/route-c74ff3c527010d28.js +0 -1
  842. package/app/.next/static/chunks/app/api/auth/login/route-c74ff3c527010d28.js +0 -1
  843. package/app/.next/static/chunks/app/api/auth/logout/route-c74ff3c527010d28.js +0 -1
  844. package/app/.next/static/chunks/app/api/auth/oidc/callback/route-c74ff3c527010d28.js +0 -1
  845. package/app/.next/static/chunks/app/api/auth/oidc/start/route-c74ff3c527010d28.js +0 -1
  846. package/app/.next/static/chunks/app/api/auth/oidc/test/route-c74ff3c527010d28.js +0 -1
  847. package/app/.next/static/chunks/app/api/auth/reset-password/route-c74ff3c527010d28.js +0 -1
  848. package/app/.next/static/chunks/app/api/auth/status/route-c74ff3c527010d28.js +0 -1
  849. package/app/.next/static/chunks/app/api/cli-tools/all-statuses/route-c74ff3c527010d28.js +0 -1
  850. package/app/.next/static/chunks/app/api/cli-tools/antigravity-mitm/alias/route-c74ff3c527010d28.js +0 -1
  851. package/app/.next/static/chunks/app/api/cli-tools/antigravity-mitm/route-c74ff3c527010d28.js +0 -1
  852. package/app/.next/static/chunks/app/api/cli-tools/claude-settings/route-c74ff3c527010d28.js +0 -1
  853. package/app/.next/static/chunks/app/api/cli-tools/cline-settings/route-c74ff3c527010d28.js +0 -1
  854. package/app/.next/static/chunks/app/api/cli-tools/codex-settings/route-c74ff3c527010d28.js +0 -1
  855. package/app/.next/static/chunks/app/api/cli-tools/copilot-settings/route-c74ff3c527010d28.js +0 -1
  856. package/app/.next/static/chunks/app/api/cli-tools/cowork-mcp-registry/route-c74ff3c527010d28.js +0 -1
  857. package/app/.next/static/chunks/app/api/cli-tools/cowork-mcp-tools/route-c74ff3c527010d28.js +0 -1
  858. package/app/.next/static/chunks/app/api/cli-tools/cowork-settings/route-c74ff3c527010d28.js +0 -1
  859. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/[jobId]/events/route-c74ff3c527010d28.js +0 -1
  860. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/[jobId]/sudo/route-c74ff3c527010d28.js +0 -1
  861. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/jobs/route-c74ff3c527010d28.js +0 -1
  862. package/app/.next/static/chunks/app/api/cli-tools/cursor-byok/route-c74ff3c527010d28.js +0 -1
  863. package/app/.next/static/chunks/app/api/cli-tools/deepseek-tui-settings/route-c74ff3c527010d28.js +0 -1
  864. package/app/.next/static/chunks/app/api/cli-tools/devin-settings/route-c74ff3c527010d28.js +0 -1
  865. package/app/.next/static/chunks/app/api/cli-tools/droid-settings/route-c74ff3c527010d28.js +0 -1
  866. package/app/.next/static/chunks/app/api/cli-tools/grok-build-settings/route-c74ff3c527010d28.js +0 -1
  867. package/app/.next/static/chunks/app/api/cli-tools/hermes-settings/route-c74ff3c527010d28.js +0 -1
  868. package/app/.next/static/chunks/app/api/cli-tools/jcode-settings/route-c74ff3c527010d28.js +0 -1
  869. package/app/.next/static/chunks/app/api/cli-tools/kilo-settings/route-c74ff3c527010d28.js +0 -1
  870. package/app/.next/static/chunks/app/api/cli-tools/openclaw-settings/route-c74ff3c527010d28.js +0 -1
  871. package/app/.next/static/chunks/app/api/cli-tools/opencode-settings/route-c74ff3c527010d28.js +0 -1
  872. package/app/.next/static/chunks/app/api/combos/[id]/route-c74ff3c527010d28.js +0 -1
  873. package/app/.next/static/chunks/app/api/combos/route-c74ff3c527010d28.js +0 -1
  874. package/app/.next/static/chunks/app/api/donate/route-c74ff3c527010d28.js +0 -1
  875. package/app/.next/static/chunks/app/api/headroom/extras/route-c74ff3c527010d28.js +0 -1
  876. package/app/.next/static/chunks/app/api/headroom/proxy/[...path]/route-c74ff3c527010d28.js +0 -1
  877. package/app/.next/static/chunks/app/api/headroom/restart/route-c74ff3c527010d28.js +0 -1
  878. package/app/.next/static/chunks/app/api/headroom/start/route-c74ff3c527010d28.js +0 -1
  879. package/app/.next/static/chunks/app/api/headroom/status/route-c74ff3c527010d28.js +0 -1
  880. package/app/.next/static/chunks/app/api/headroom/stop/route-c74ff3c527010d28.js +0 -1
  881. package/app/.next/static/chunks/app/api/health/route-c74ff3c527010d28.js +0 -1
  882. package/app/.next/static/chunks/app/api/init/route-c74ff3c527010d28.js +0 -1
  883. package/app/.next/static/chunks/app/api/internal/account-health/route-c74ff3c527010d28.js +0 -1
  884. package/app/.next/static/chunks/app/api/internal/request-detail/route-c74ff3c527010d28.js +0 -1
  885. package/app/.next/static/chunks/app/api/internal/usage/route-c74ff3c527010d28.js +0 -1
  886. package/app/.next/static/chunks/app/api/keys/[id]/reset-usage/route-c74ff3c527010d28.js +0 -1
  887. package/app/.next/static/chunks/app/api/keys/[id]/route-c74ff3c527010d28.js +0 -1
  888. package/app/.next/static/chunks/app/api/keys/[id]/usage/route-c74ff3c527010d28.js +0 -1
  889. package/app/.next/static/chunks/app/api/keys/route-c74ff3c527010d28.js +0 -1
  890. package/app/.next/static/chunks/app/api/locale/route-c74ff3c527010d28.js +0 -1
  891. package/app/.next/static/chunks/app/api/mcp/[plugin]/message/route-c74ff3c527010d28.js +0 -1
  892. package/app/.next/static/chunks/app/api/mcp/[plugin]/sse/route-c74ff3c527010d28.js +0 -1
  893. package/app/.next/static/chunks/app/api/media-providers/tts/deepgram/voices/route-c74ff3c527010d28.js +0 -1
  894. package/app/.next/static/chunks/app/api/media-providers/tts/elevenlabs/voices/route-c74ff3c527010d28.js +0 -1
  895. package/app/.next/static/chunks/app/api/media-providers/tts/inworld/voices/route-c74ff3c527010d28.js +0 -1
  896. package/app/.next/static/chunks/app/api/media-providers/tts/minimax/voices/route-c74ff3c527010d28.js +0 -1
  897. package/app/.next/static/chunks/app/api/media-providers/tts/voices/route-c74ff3c527010d28.js +0 -1
  898. package/app/.next/static/chunks/app/api/models/alias/route-c74ff3c527010d28.js +0 -1
  899. package/app/.next/static/chunks/app/api/models/availability/route-c74ff3c527010d28.js +0 -1
  900. package/app/.next/static/chunks/app/api/models/custom/route-c74ff3c527010d28.js +0 -1
  901. package/app/.next/static/chunks/app/api/models/disabled/route-c74ff3c527010d28.js +0 -1
  902. package/app/.next/static/chunks/app/api/models/route-c74ff3c527010d28.js +0 -1
  903. package/app/.next/static/chunks/app/api/models/test/route-c74ff3c527010d28.js +0 -1
  904. package/app/.next/static/chunks/app/api/oauth/[provider]/[action]/route-c74ff3c527010d28.js +0 -1
  905. package/app/.next/static/chunks/app/api/oauth/codex/bulk-import/route-c74ff3c527010d28.js +0 -1
  906. package/app/.next/static/chunks/app/api/oauth/codex/import-token/route-c74ff3c527010d28.js +0 -1
  907. package/app/.next/static/chunks/app/api/oauth/cursor/auto-import/route-c74ff3c527010d28.js +0 -1
  908. package/app/.next/static/chunks/app/api/oauth/cursor/import/route-c74ff3c527010d28.js +0 -1
  909. package/app/.next/static/chunks/app/api/oauth/gitlab/pat/route-c74ff3c527010d28.js +0 -1
  910. package/app/.next/static/chunks/app/api/oauth/iflow/cookie/route-c74ff3c527010d28.js +0 -1
  911. package/app/.next/static/chunks/app/api/oauth/kiro/api-key/route-c74ff3c527010d28.js +0 -1
  912. package/app/.next/static/chunks/app/api/oauth/kiro/auto-import/route-c74ff3c527010d28.js +0 -1
  913. package/app/.next/static/chunks/app/api/oauth/kiro/import/route-c74ff3c527010d28.js +0 -1
  914. package/app/.next/static/chunks/app/api/oauth/kiro/import-cli-proxy/route-c74ff3c527010d28.js +0 -1
  915. package/app/.next/static/chunks/app/api/oauth/kiro/social-authorize/route-c74ff3c527010d28.js +0 -1
  916. package/app/.next/static/chunks/app/api/oauth/kiro/social-exchange/route-c74ff3c527010d28.js +0 -1
  917. package/app/.next/static/chunks/app/api/pricing/route-c74ff3c527010d28.js +0 -1
  918. package/app/.next/static/chunks/app/api/provider-nodes/[id]/route-c74ff3c527010d28.js +0 -1
  919. package/app/.next/static/chunks/app/api/provider-nodes/route-c74ff3c527010d28.js +0 -1
  920. package/app/.next/static/chunks/app/api/provider-nodes/validate/route-c74ff3c527010d28.js +0 -1
  921. package/app/.next/static/chunks/app/api/providers/[id]/models/route-c74ff3c527010d28.js +0 -1
  922. package/app/.next/static/chunks/app/api/providers/[id]/route-c74ff3c527010d28.js +0 -1
  923. package/app/.next/static/chunks/app/api/providers/[id]/test/route-c74ff3c527010d28.js +0 -1
  924. package/app/.next/static/chunks/app/api/providers/[id]/test-models/route-c74ff3c527010d28.js +0 -1
  925. package/app/.next/static/chunks/app/api/providers/client/route-c74ff3c527010d28.js +0 -1
  926. package/app/.next/static/chunks/app/api/providers/kilo/free-models/route-c74ff3c527010d28.js +0 -1
  927. package/app/.next/static/chunks/app/api/providers/route-c74ff3c527010d28.js +0 -1
  928. package/app/.next/static/chunks/app/api/providers/suggested-models/route-c74ff3c527010d28.js +0 -1
  929. package/app/.next/static/chunks/app/api/providers/test-batch/route-c74ff3c527010d28.js +0 -1
  930. package/app/.next/static/chunks/app/api/providers/validate/route-c74ff3c527010d28.js +0 -1
  931. package/app/.next/static/chunks/app/api/proxy-pools/[id]/route-c74ff3c527010d28.js +0 -1
  932. package/app/.next/static/chunks/app/api/proxy-pools/[id]/test/route-c74ff3c527010d28.js +0 -1
  933. package/app/.next/static/chunks/app/api/proxy-pools/cloudflare-deploy/route-c74ff3c527010d28.js +0 -1
  934. package/app/.next/static/chunks/app/api/proxy-pools/deno-deploy/route-c74ff3c527010d28.js +0 -1
  935. package/app/.next/static/chunks/app/api/proxy-pools/route-c74ff3c527010d28.js +0 -1
  936. package/app/.next/static/chunks/app/api/proxy-pools/vercel-deploy/route-c74ff3c527010d28.js +0 -1
  937. package/app/.next/static/chunks/app/api/pxpipe/health/route-c74ff3c527010d28.js +0 -1
  938. package/app/.next/static/chunks/app/api/pxpipe/install/route-c74ff3c527010d28.js +0 -1
  939. package/app/.next/static/chunks/app/api/pxpipe/logs/route-c74ff3c527010d28.js +0 -1
  940. package/app/.next/static/chunks/app/api/pxpipe/restart/route-c74ff3c527010d28.js +0 -1
  941. package/app/.next/static/chunks/app/api/pxpipe/start/route-c74ff3c527010d28.js +0 -1
  942. package/app/.next/static/chunks/app/api/pxpipe/stats/route-c74ff3c527010d28.js +0 -1
  943. package/app/.next/static/chunks/app/api/pxpipe/status/route-c74ff3c527010d28.js +0 -1
  944. package/app/.next/static/chunks/app/api/pxpipe/stop/route-c74ff3c527010d28.js +0 -1
  945. package/app/.next/static/chunks/app/api/settings/database/route-c74ff3c527010d28.js +0 -1
  946. package/app/.next/static/chunks/app/api/settings/database/selective/route-c74ff3c527010d28.js +0 -1
  947. package/app/.next/static/chunks/app/api/settings/proxy-test/route-c74ff3c527010d28.js +0 -1
  948. package/app/.next/static/chunks/app/api/settings/require-login/route-c74ff3c527010d28.js +0 -1
  949. package/app/.next/static/chunks/app/api/settings/route-c74ff3c527010d28.js +0 -1
  950. package/app/.next/static/chunks/app/api/shutdown/route-c74ff3c527010d28.js +0 -1
  951. package/app/.next/static/chunks/app/api/tags/route-c74ff3c527010d28.js +0 -1
  952. package/app/.next/static/chunks/app/api/translator/console-logs/route-c74ff3c527010d28.js +0 -1
  953. package/app/.next/static/chunks/app/api/translator/console-logs/stream/route-c74ff3c527010d28.js +0 -1
  954. package/app/.next/static/chunks/app/api/translator/load/route-c74ff3c527010d28.js +0 -1
  955. package/app/.next/static/chunks/app/api/translator/save/route-c74ff3c527010d28.js +0 -1
  956. package/app/.next/static/chunks/app/api/translator/send/route-c74ff3c527010d28.js +0 -1
  957. package/app/.next/static/chunks/app/api/translator/translate/route-c74ff3c527010d28.js +0 -1
  958. package/app/.next/static/chunks/app/api/tunnel/disable/route-c74ff3c527010d28.js +0 -1
  959. package/app/.next/static/chunks/app/api/tunnel/enable/route-c74ff3c527010d28.js +0 -1
  960. package/app/.next/static/chunks/app/api/tunnel/status/route-c74ff3c527010d28.js +0 -1
  961. package/app/.next/static/chunks/app/api/tunnel/tailscale-check/route-c74ff3c527010d28.js +0 -1
  962. package/app/.next/static/chunks/app/api/tunnel/tailscale-disable/route-c74ff3c527010d28.js +0 -1
  963. package/app/.next/static/chunks/app/api/tunnel/tailscale-enable/route-c74ff3c527010d28.js +0 -1
  964. package/app/.next/static/chunks/app/api/tunnel/tailscale-install/route-c74ff3c527010d28.js +0 -1
  965. package/app/.next/static/chunks/app/api/usage/[connectionId]/codex-reset-credits/route-c74ff3c527010d28.js +0 -1
  966. package/app/.next/static/chunks/app/api/usage/[connectionId]/route-c74ff3c527010d28.js +0 -1
  967. package/app/.next/static/chunks/app/api/usage/chart/route-c74ff3c527010d28.js +0 -1
  968. package/app/.next/static/chunks/app/api/usage/history/route-c74ff3c527010d28.js +0 -1
  969. package/app/.next/static/chunks/app/api/usage/logs/route-c74ff3c527010d28.js +0 -1
  970. package/app/.next/static/chunks/app/api/usage/providers/route-c74ff3c527010d28.js +0 -1
  971. package/app/.next/static/chunks/app/api/usage/report/route-c74ff3c527010d28.js +0 -1
  972. package/app/.next/static/chunks/app/api/usage/request-details/route-c74ff3c527010d28.js +0 -1
  973. package/app/.next/static/chunks/app/api/usage/request-logs/route-c74ff3c527010d28.js +0 -1
  974. package/app/.next/static/chunks/app/api/usage/stats/route-c74ff3c527010d28.js +0 -1
  975. package/app/.next/static/chunks/app/api/usage/stream/route-c74ff3c527010d28.js +0 -1
  976. package/app/.next/static/chunks/app/api/v1/api/chat/route-c74ff3c527010d28.js +0 -1
  977. package/app/.next/static/chunks/app/api/v1/audio/speech/route-c74ff3c527010d28.js +0 -1
  978. package/app/.next/static/chunks/app/api/v1/audio/transcriptions/route-c74ff3c527010d28.js +0 -1
  979. package/app/.next/static/chunks/app/api/v1/audio/voices/route-c74ff3c527010d28.js +0 -1
  980. package/app/.next/static/chunks/app/api/v1/chat/completions/route-c74ff3c527010d28.js +0 -1
  981. package/app/.next/static/chunks/app/api/v1/embeddings/route-c74ff3c527010d28.js +0 -1
  982. package/app/.next/static/chunks/app/api/v1/images/generations/route-c74ff3c527010d28.js +0 -1
  983. package/app/.next/static/chunks/app/api/v1/messages/count_tokens/route-c74ff3c527010d28.js +0 -1
  984. package/app/.next/static/chunks/app/api/v1/messages/route-c74ff3c527010d28.js +0 -1
  985. package/app/.next/static/chunks/app/api/v1/models/[kind]/route-c74ff3c527010d28.js +0 -1
  986. package/app/.next/static/chunks/app/api/v1/models/info/route-c74ff3c527010d28.js +0 -1
  987. package/app/.next/static/chunks/app/api/v1/models/route-c74ff3c527010d28.js +0 -1
  988. package/app/.next/static/chunks/app/api/v1/responses/compact/route-c74ff3c527010d28.js +0 -1
  989. package/app/.next/static/chunks/app/api/v1/responses/route-c74ff3c527010d28.js +0 -1
  990. package/app/.next/static/chunks/app/api/v1/route-c74ff3c527010d28.js +0 -1
  991. package/app/.next/static/chunks/app/api/v1/search/route-c74ff3c527010d28.js +0 -1
  992. package/app/.next/static/chunks/app/api/v1/videos/[id]/route-c74ff3c527010d28.js +0 -1
  993. package/app/.next/static/chunks/app/api/v1/videos/edits/route-c74ff3c527010d28.js +0 -1
  994. package/app/.next/static/chunks/app/api/v1/videos/extensions/route-c74ff3c527010d28.js +0 -1
  995. package/app/.next/static/chunks/app/api/v1/videos/generations/route-c74ff3c527010d28.js +0 -1
  996. package/app/.next/static/chunks/app/api/v1/web/fetch/route-c74ff3c527010d28.js +0 -1
  997. package/app/.next/static/chunks/app/api/v1beta/models/[...path]/route-c74ff3c527010d28.js +0 -1
  998. package/app/.next/static/chunks/app/api/v1beta/models/route-c74ff3c527010d28.js +0 -1
  999. package/app/.next/static/chunks/app/api/version/route-c74ff3c527010d28.js +0 -1
  1000. package/app/.next/static/chunks/app/api/version/shutdown/route-c74ff3c527010d28.js +0 -1
  1001. package/app/.next/static/chunks/app/api/version/update/route-c74ff3c527010d28.js +0 -1
  1002. package/app/.next/static/chunks/app/login/page-7b85623bf9ba8d60.js +0 -1
  1003. package/app/.next/static/chunks/app/manifest.webmanifest/route-c74ff3c527010d28.js +0 -1
  1004. package/app/.next/static/chunks/app/page-c74ff3c527010d28.js +0 -1
  1005. package/app/.next/static/chunks/next/dist/client/components/builtin/app-error-c74ff3c527010d28.js +0 -1
  1006. package/app/.next/static/chunks/next/dist/client/components/builtin/forbidden-c74ff3c527010d28.js +0 -1
  1007. package/app/.next/static/chunks/next/dist/client/components/builtin/not-found-c74ff3c527010d28.js +0 -1
  1008. package/app/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c74ff3c527010d28.js +0 -1
  1009. package/app/.next/static/css/d16761d8d90e43ab.css +0 -1
  1010. package/app/open-sse/executors/opencode-go.js +0 -49
  1011. /package/app/.next/static/{__qB-b0EP9cu_2Y1YJiUT → flxITMsAmoXf-wWjPORMD}/_ssgManifest.js +0 -0
@@ -1,29 +1,226 @@
1
1
  import { BaseExecutor } from "./base.js";
2
2
  import { PROVIDERS } from "../config/providers.js";
3
- import { resolveKiroModel } from "../config/kiroConstants.js";
3
+ import {
4
+ KIRO_CODEWHISPERER_TARGET,
5
+ KIRO_ENDPOINT_FALLBACK_STATUSES,
6
+ resolveKiroModel,
7
+ } from "../config/kiroConstants.js";
4
8
  import { v4 as uuidv4 } from "uuid";
5
9
  import { refreshKiroToken } from "../services/tokenRefresh.js";
6
- import { proxyAwareFetch } from "../utils/proxyFetch.js";
7
- import { HTTP_STATUS, DEFAULT_KIRO_RETRY_COUNT, FETCH_CONNECT_TIMEOUT_MS } from "../config/runtimeConfig.js";
8
10
  import { SSE_DONE, SSE_HEADERS } from "../utils/sseConstants.js";
9
11
  import { getCapabilitiesForModel } from "../providers/capabilities.js";
12
+ import { STREAM_FIRST_CHUNK_TIMEOUT_MS, HTTP_STATUS, DEFAULT_KIRO_RETRY_COUNT } from "../config/runtimeConfig.js";
10
13
 
11
- // SSE keepalive comment. Emitted when raw EventStream bytes arrive but don't yet
12
- // complete a parseable frame (partial-frame buffering during reasoning prefill).
13
- // Keeps the downstream stall watchdog (pipeWithDisconnect) aware of upstream
14
- // activity so it doesn't false-abort. Comment lines are dropped by the translate
15
- // parser and ignored by SSE clients in passthrough.
16
- const KIRO_KEEPALIVE = new TextEncoder().encode(": ka\n\n");
17
-
18
- // Exponential backoff config for Kiro retries (mirrors MITM approach)
14
+ // Transient 400 patterns that should be retried (Kiro-specific false positives)
15
+ const KIRO_RETRYABLE_400_PATTERNS = ["improperly formed request"];
19
16
  const KIRO_BACKOFF_BASE_MS = 2000;
20
17
  const KIRO_BACKOFF_CAP_MS = 15000;
21
18
 
22
- // Transient 400 patterns that should be retried (Kiro-specific false positives)
23
- const KIRO_RETRYABLE_400_PATTERNS = ["improperly formed request"];
19
+ const KIRO_REPAIR_BUFFER_MAX_BYTES = 8 * 1024 * 1024;
20
+ const KIRO_REPAIR_HEARTBEAT_MS = 10_000;
21
+ const KIRO_SHORT_FINAL_MAX_CHARS = 800;
22
+ const EVENTSTREAM_MAX_MESSAGE_BYTES = 24 * 1024 * 1024;
23
+ const EVENTSTREAM_MAX_HEADERS_BYTES = 128 * 1024;
24
+ const KIRO_EVENT_TYPES = new Set([
25
+ "assistantResponseEvent",
26
+ "reasoningContentEvent",
27
+ "codeEvent",
28
+ "toolUseEvent",
29
+ "messageStopEvent",
30
+ "metadataEvent",
31
+ "MetadataEvent",
32
+ "contextUsageEvent",
33
+ "meteringEvent",
34
+ "metricsEvent"
35
+ ]);
36
+ const encoder = new TextEncoder();
37
+ const decoder = new TextDecoder();
38
+ const CRC32_TABLE = Uint32Array.from({ length: 256 }, (_, index) => {
39
+ let value = index;
40
+ for (let bit = 0; bit < 8; bit++) {
41
+ value = (value >>> 1) ^ ((value & 1) ? 0xedb88320 : 0);
42
+ }
43
+ return value >>> 0;
44
+ });
45
+
46
+ const REPAIR_INSTRUCTIONS = Object.freeze({
47
+ tool: "Retry the previous response because its Kiro tool_call wrapper was malformed. If you use the wrapper tool named tool_call, its input must contain a non-empty name and an arguments field.",
48
+ ellipsis: "Retry the previous response because it ended with only an ellipsis. Return the complete final answer, not only ... or ….",
49
+ short_final: "Retry the previous response because its final only announced a future action. Complete the check now and return the result or a concrete blocker."
50
+ });
51
+ const SHORT_FUTURE_ACTION = /^(?:(?:(?:現在|接著|接下來|下一步)[,,::\s]*(?:我(?:只)?(?:會|要|將|再)?\s*)?|我只再)(?:補|查|確認|驗證|追(?:查|蹤)?|繼續|檢查|測試)|我(?:會|要|將)(?:再|重新)?(?:補(?:齊|查)?|抓取|查(?:詢)?|確認|驗證|追(?:查|蹤)?|繼續|檢查|測試)|(?:(?:next|now|then)\b[\s,:-]*)?(?:i(?:'ll| will| am going to| need to)|let me)\s+(?:verify|check|confirm|validate|investigate|trace|continue|follow up|test)\b)/iu;
52
+ // Keep this tied to the observed whole-response signature. Broader Chinese
53
+ // result/progress heuristics create false positives for completed findings.
54
+ const OBSERVED_TRAILING_FUTURE_ACTION = /^目前證據顯示[\s\S]{1,700}[。.!?;;]\s*最後補查\s+504\s+access\s+log[,,]\s*確認\s+host[//]路徑與是否為集中流量[。.!]?$/iu;
55
+ const ENGLISH_FUTURE_ACTION = /^(?:(?:next|now|then)\b[\s,:-]*)?(?:i(?:'ll| will| am going to| need to)|let me)\s+(?:verify|check|confirm|validate|investigate|trace|continue|follow up|test)\b/iu;
56
+ const ENGLISH_RESULT_CLAUSE = /(?:[:;\n]|[.!?]\s+\S|\b(?:status|checksum|response|deployment)\s+(?:is|are|was|were|matches?|equals?|returned)\b)/iu;
57
+ const CHINESE_FUTURE_ACTION = /^(?:(?:現在|接著|接下來|下一步)[,,::\s]*(?:我(?:只)?(?:會|要|將|再)?\s*)?|我只再|我(?:會|要|將)(?:再|重新)?)(?:補|抓取|查|確認|驗證|追|繼續|檢查|測試)/u;
58
+ const CHINESE_RESULT_CLAUSE = /(?:[。!?]\s*\S|(?:版本|狀態|回應|結果|部署|校驗碼)(?:是|為|等於|顯示))/u;
59
+ const USER_WAIT = /(?:請(?:你|先)|你(?:先|需要|可以|提供|確認|批准|允許)|等待(?:你|使用者)|等你|核准|同意|授權|\b(?:after|when|once)\s+you\b|\byour\s+(?:approval|confirmation|permission|input)\b|\bwait(?:ing)?\s+for\s+you\b|\bplease\s+(?:approve|confirm|provide|send)\b)/iu;
60
+ const COMPLETED_FINAL = /(?:已(?:經)?完成|完成(?:了|驗證|確認)|修復完成|確認無誤|驗證(?:完成|通過)|測試(?:均)?通過|結論|總結|\b(?:done|completed|fixed|verified|confirmed|passed|in conclusion|summary)\b|\b(?:is|are) complete\b)/iu;
61
+ const RESULT_EVIDENCE = /(?:顯示|發現|因此|成功|失敗|正常|無錯誤|沒有錯誤|\b(?:found|shows?|showed|because|therefore|succeeded|failed|healthy|green|no errors?)\b)/iu;
62
+
63
+ function crc32(bytes) {
64
+ let crc = 0xffffffff;
65
+ for (const byte of bytes) crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
66
+ return (crc ^ 0xffffffff) >>> 0;
67
+ }
68
+
69
+ function envPositiveInt(name, fallback) {
70
+ const parsed = Number.parseInt(process.env?.[name] || "", 10);
71
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
72
+ }
73
+
74
+ function concatChunks(chunks, totalBytes) {
75
+ const output = new Uint8Array(totalBytes);
76
+ let offset = 0;
77
+ for (const chunk of chunks) {
78
+ output.set(chunk, offset);
79
+ offset += chunk.byteLength;
80
+ }
81
+ return output;
82
+ }
83
+
84
+ function makeAbortError(reason) {
85
+ const error = new Error(reason?.message || reason || "Request aborted");
86
+ error.name = "AbortError";
87
+ return error;
88
+ }
89
+
90
+ async function readWithTimeout(reader, signal, timeoutMs, message) {
91
+ if (signal?.aborted) throw makeAbortError(signal.reason);
92
+ let timeout;
93
+ let abortHandler;
94
+ const timeoutPromise = new Promise((_, reject) => {
95
+ timeout = setTimeout(() => reject(new Error(message)), timeoutMs);
96
+ });
97
+ const abortPromise = new Promise((_, reject) => {
98
+ abortHandler = () => reject(makeAbortError(signal.reason));
99
+ signal?.addEventListener("abort", abortHandler, { once: true });
100
+ });
101
+ try {
102
+ return await Promise.race([reader.read(), timeoutPromise, abortPromise]);
103
+ } finally {
104
+ clearTimeout(timeout);
105
+ signal?.removeEventListener?.("abort", abortHandler);
106
+ }
107
+ }
108
+
109
+ async function readResponsePrefix(response, signal, maxBytes, timeoutMs) {
110
+ const reader = response?.body?.getReader?.();
111
+ if (!reader) return "";
112
+ const chunks = [];
113
+ let totalBytes = 0;
114
+ try {
115
+ while (totalBytes < maxBytes) {
116
+ const { done, value } = await readWithTimeout(
117
+ reader,
118
+ signal,
119
+ timeoutMs,
120
+ "Kiro retry error body stalled"
121
+ );
122
+ if (done) break;
123
+ const remaining = maxBytes - totalBytes;
124
+ const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;
125
+ chunks.push(chunk);
126
+ totalBytes += chunk.byteLength;
127
+ if (value.byteLength > remaining) break;
128
+ }
129
+ } finally {
130
+ await reader.cancel("bounded Kiro retry error body").catch(() => {});
131
+ }
132
+ return decoder.decode(concatChunks(chunks, totalBytes));
133
+ }
134
+
135
+ function appendRepairInstruction(body, kind) {
136
+ const repaired = structuredClone(body || {});
137
+ const instruction = REPAIR_INSTRUCTIONS[kind] || "Retry the previous incomplete Kiro response.";
138
+ repaired.systemPrompt = repaired.systemPrompt
139
+ ? `${repaired.systemPrompt}\n\n${instruction}`
140
+ : instruction;
141
+ return repaired;
142
+ }
143
+
144
+ function normalizeStopReason(value) {
145
+ const reason = String(value || "").trim().replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().replace(/[\s-]+/g, "_");
146
+ if (["endturn", "end_turn", "stop", "stop_sequence"].includes(reason)) return "end_turn";
147
+ if (["tooluse", "tool_use", "tool_calls"].includes(reason)) return "tool_use";
148
+ if (["maxtokens", "max_tokens", "max_output_tokens", "length"].includes(reason)) return "max_tokens";
149
+ return reason || null;
150
+ }
24
151
 
25
- // Status codes eligible for in-executor retry with exponential backoff
26
- const KIRO_RETRYABLE_STATUSES = new Set([400, 429, 500, 502, 503, 504]);
152
+ // Of the reasons stopDisposition() folds into "terminal_incomplete", only these
153
+ // mean "usable as far as it got, then the budget ran out" -- the case
154
+ // finish_reason "length" exists for. cancelled / pause_turn are abandoned turns
155
+ // whose partial content must stay private, so they are deliberately absent.
156
+ const KIRO_TRUNCATION_STOP_REASONS = new Set(["model_context_window_exceeded", "max_tokens"]);
157
+
158
+ function stopDisposition(stopReason, hasToolCalls) {
159
+ if (["malformed_model_output", "invalid_model_output"].includes(stopReason)) return "retryable_protocol_failure";
160
+ if (["cancelled", "pause_turn", "model_context_window_exceeded"].includes(stopReason)) return "terminal_incomplete";
161
+ if (stopReason === "refusal" || /(?:content.*filter|guardrail|safety|policy|blocked)/u.test(stopReason)) return "terminal_refusal";
162
+ if (stopReason === "max_tokens") return hasToolCalls ? "terminal_incomplete" : "length";
163
+ if (stopReason && !["end_turn", "tool_use"].includes(stopReason)) return "unknown_failure";
164
+ if (hasToolCalls || stopReason === "tool_use") return "tool_use";
165
+ if (!stopReason || stopReason === "end_turn") return "complete";
166
+ return "unknown_failure";
167
+ }
168
+
169
+ function mergeStopReason(current, incoming) {
170
+ if (!incoming) return current;
171
+ if (!current) return incoming;
172
+ const severity = (reason) => {
173
+ const disposition = stopDisposition(reason, false);
174
+ if (disposition === "terminal_refusal") return 6;
175
+ if (disposition === "terminal_incomplete") return 5;
176
+ if (disposition === "unknown_failure") return 4;
177
+ if (disposition === "retryable_protocol_failure") return 3;
178
+ if (disposition === "length") return 2;
179
+ return 1;
180
+ };
181
+ return severity(incoming) > severity(current) ? incoming : current;
182
+ }
183
+
184
+ function isEllipsisOnly(value) {
185
+ return ["...", "…"].includes(String(value || "").trim());
186
+ }
187
+
188
+ function isShortFutureAction(value) {
189
+ const text = String(value || "").trim().replaceAll("’", "'");
190
+ if (OBSERVED_TRAILING_FUTURE_ACTION.test(text)) return true;
191
+ if (ENGLISH_FUTURE_ACTION.test(text) && ENGLISH_RESULT_CLAUSE.test(text)) return false;
192
+ if (CHINESE_FUTURE_ACTION.test(text) && CHINESE_RESULT_CLAUSE.test(text)) return false;
193
+ return text.length > 0 && text.length <= KIRO_SHORT_FINAL_MAX_CHARS &&
194
+ SHORT_FUTURE_ACTION.test(text) && !USER_WAIT.test(text) &&
195
+ !COMPLETED_FINAL.test(text) && !RESULT_EVIDENCE.test(text);
196
+ }
197
+
198
+ function encodeSSEError(code, message, details) {
199
+ return encoder.encode(`data: ${JSON.stringify({ error: {
200
+ message,
201
+ type: "upstream_error",
202
+ code,
203
+ ...(details ? { details } : {})
204
+ } })}\n\ndata: [DONE]\n\n`);
205
+ }
206
+
207
+ function inspectSSEChunk(chunk, state) {
208
+ for (const line of decoder.decode(chunk).split("\n")) {
209
+ if (!line.startsWith("data: ")) continue;
210
+ const data = line.slice(6).trim();
211
+ if (!data || data === "[DONE]") continue;
212
+ try {
213
+ const event = JSON.parse(data);
214
+ if (event.error) state.error = event.error;
215
+ for (const choice of event.choices || []) {
216
+ const delta = choice.delta || {};
217
+ if (typeof delta.content === "string") state.content += delta.content;
218
+ if (typeof delta.reasoning_content === "string") state.reasoning += delta.reasoning_content;
219
+ if (delta.tool_calls?.length) state.hasToolCalls = true;
220
+ }
221
+ } catch { /* a malformed SSE line is diagnosed by the transformer */ }
222
+ }
223
+ }
27
224
 
28
225
  /**
29
226
  * KiroExecutor - Executor for Kiro AI (AWS CodeWhisperer)
@@ -34,12 +231,17 @@ export class KiroExecutor extends BaseExecutor {
34
231
  super("kiro", PROVIDERS.kiro);
35
232
  }
36
233
 
37
- buildHeaders(credentials, stream = true) {
234
+ buildHeaders(credentials, stream = true, url = "") {
38
235
  const headers = {
39
236
  ...this.config.headers,
40
237
  "Amz-Sdk-Request": "attempt=1; max=3",
41
238
  "Amz-Sdk-Invocation-Id": uuidv4()
42
239
  };
240
+ if (url.includes("://codewhisperer.")) {
241
+ headers["X-Amz-Target"] = KIRO_CODEWHISPERER_TARGET;
242
+ } else {
243
+ delete headers["X-Amz-Target"];
244
+ }
43
245
 
44
246
  // API-key auth: the key is stored as accessToken and sent as a bearer token
45
247
  // exactly like an OAuth access token, but with an extra `tokentype: API_KEY`
@@ -54,8 +256,8 @@ export class KiroExecutor extends BaseExecutor {
54
256
  const apiKey = credentials?.apiKey || (isApiKey ? credentials?.accessToken : null);
55
257
  if (isApiKey && apiKey) {
56
258
  headers["Authorization"] = `Bearer ${apiKey}`;
57
- headers["tokentype"] = "API_KEY";
58
- } else if (credentials.accessToken) {
259
+ headers["TokenType"] = "API_KEY";
260
+ } else if (credentials?.accessToken) {
59
261
  headers["Authorization"] = `Bearer ${credentials.accessToken}`;
60
262
  if (isExternalIdp) {
61
263
  headers["TokenType"] = "EXTERNAL_IDP";
@@ -68,14 +270,14 @@ export class KiroExecutor extends BaseExecutor {
68
270
  /**
69
271
  * Auth-aware endpoint ordering.
70
272
  *
71
- * API-key Kiro connections store a raw CodeWhisperer credential (validated
72
- * against codewhisperer.us-east-1.amazonaws.com via ListAvailableProfiles).
273
+ * API-key Kiro connections use the Amazon Q surface. The legacy
274
+ * codewhisperer.* GenerateAssistantResponse endpoint can authenticate the key
275
+ * but rejects the same valid payload with REQUEST_BODY_INVALID. Since a 400
276
+ * is terminal in BaseExecutor, putting CodeWhisperer first prevents the working
277
+ * q.* endpoint from ever being tried. Keep q.* first only for api_key accounts.
278
+ *
73
279
  * The Kiro IDE gateway (runtime.*.kiro.dev) expects Kiro OIDC/social tokens
74
- * and rejects an `tokentype: API_KEY` token with 401/403 — which
75
- * BaseExecutor.execute() returns immediately (only 429 / network errors fall
76
- * through to the next host). So for api-key auth we must try the *.amazonaws.com
77
- * CodeWhisperer hosts FIRST, mirroring the Kiro-Go reference fork which never
78
- * routes api-key traffic through kiro.dev. External IdP enterprise tokens also
280
+ * and rejects TokenType=API_KEY. External IdP enterprise tokens instead
79
281
  * use the CodeWhisperer surface, with the `TokenType: EXTERNAL_IDP` header.
80
282
  * Other OAuth methods keep the default order (kiro.dev first) since their
81
283
  * tokens are what that gateway accepts.
@@ -100,6 +302,14 @@ export class KiroExecutor extends BaseExecutor {
100
302
 
101
303
  const amazon = baseUrls.filter((u) => u.includes("amazonaws.com")).map(regionalize);
102
304
  const others = baseUrls.filter((u) => !u.includes("amazonaws.com"));
305
+ if (authMethod === "api_key") {
306
+ const q = amazon.filter((u) => u.includes("://q."));
307
+ const remaining = amazon.filter((u) => !u.includes("://q."));
308
+ return q.length > 0
309
+ ? [...q, ...remaining, ...others]
310
+ : [...amazon, ...others];
311
+ }
312
+
103
313
  return amazon.length > 0 ? [...amazon, ...others] : baseUrls;
104
314
  }
105
315
 
@@ -108,516 +318,913 @@ export class KiroExecutor extends BaseExecutor {
108
318
  return baseUrls[urlIndex] || baseUrls[0] || this.config.baseUrl;
109
319
  }
110
320
 
321
+ // Retry only endpoint/auth-surface failures. Payload-invalid HTTP 400 must be
322
+ // terminal: sending the same malformed body to every surface cannot repair it.
323
+ shouldRetry(status, urlIndex) {
324
+ const hasFallback = urlIndex + 1 < this.getFallbackCount();
325
+ return super.shouldRetry(status, urlIndex)
326
+ || (hasFallback && KIRO_ENDPOINT_FALLBACK_STATUSES.has(status));
327
+ }
328
+
111
329
  transformRequest(model, body, stream, credentials) {
112
330
  return body;
113
331
  }
114
332
 
115
- /**
116
- * Check if a 400 error is a known transient Kiro issue that should be retried.
117
- * Only retries specific patterns — genuine validation errors are not retried.
118
- */
333
+ // Resolve max retry count: per-account → global setting → default. Applied to
334
+ // every in-place-retryable status (429/500/502/503/504) plus 400, whose actual
335
+ // retry eligibility is decided per-body in computeRetryDelay (see below).
336
+ getRetryConfig(credentials) {
337
+ const attempts = credentials?.kiroRetryCount ?? DEFAULT_KIRO_RETRY_COUNT;
338
+ const delayMs = 2000;
339
+ return {
340
+ ...this.config.retry,
341
+ [HTTP_STATUS.RATE_LIMITED]: { attempts, delayMs },
342
+ 500: { attempts, delayMs },
343
+ 502: { attempts, delayMs },
344
+ 503: { attempts, delayMs },
345
+ 504: { attempts, delayMs },
346
+ 400: { attempts, delayMs },
347
+ };
348
+ }
349
+
350
+ // 400 is normally a terminal validation error, but Kiro occasionally returns
351
+ // "improperly formed request" for what is actually a transient upstream hiccup.
352
+ // getRetryConfig() enables in-place retry for status 400 unconditionally; this
353
+ // hook vetoes it (no attempt consumed) unless the body matches a known transient
354
+ // pattern, so genuine validation errors still fail fast. Non-400 statuses get
355
+ // the same exponential-backoff-with-jitter curve as the pre-merge implementation.
356
+ async computeRetryDelay(response, attempt) {
357
+ if (response.status === HTTP_STATUS.BAD_REQUEST) {
358
+ let bodyText = "";
359
+ try { bodyText = await response.clone().text(); } catch { /* ignore */ }
360
+ if (!this._isRetryable400(bodyText)) return false;
361
+ }
362
+ return this._computeBackoff(attempt);
363
+ }
364
+
119
365
  _isRetryable400(responseBody) {
120
366
  if (!responseBody) return false;
121
367
  const lower = responseBody.toLowerCase();
122
368
  return KIRO_RETRYABLE_400_PATTERNS.some(pattern => lower.includes(pattern));
123
369
  }
124
370
 
371
+ _computeBackoff(attempt) {
372
+ return Math.floor(Math.random() * Math.min(KIRO_BACKOFF_CAP_MS, KIRO_BACKOFF_BASE_MS * 2 ** (attempt - 1))) + KIRO_BACKOFF_BASE_MS / 2;
373
+ }
374
+
125
375
  /**
126
- * Custom execute for Kiro - handles AWS EventStream binary response with
127
- * exponential backoff retry (MITM-style) for transient errors.
376
+ * Kiro execute — delegate to BaseExecutor for endpoint fallback + retry, then
377
+ * transform the binary AWS EventStream into OpenAI-shaped SSE on success.
378
+ *
379
+ * BaseExecutor.execute() walks config.baseUrls (runtime.us-east-1.kiro.dev →
380
+ * codewhisperer → q) advancing to the next host on 429 (shouldRetry) and on
381
+ * network/5xx errors, while tryRetry handles in-place retries per `retry: {429: 2}`.
382
+ * Note: api-key connections reorder these so the *.amazonaws.com hosts come
383
+ * first — see getOrderedBaseUrls/buildUrl above.
384
+ * Note: the baseUrls are alternate surfaces of one regional service, so rotation
385
+ * is edge-level failover — it does not grant fresh 429 quota. Per-account 429
386
+ * spreading is handled upstream by account rotation in sse/handlers/chat.js.
387
+ *
388
+ * Errors are returned untransformed so the upstream handler can read the body,
389
+ * classify the status, and trigger account fallback/cooldown.
128
390
  */
129
- async execute({ model, body, stream, credentials, signal, log, proxyOptions = null, streamWatchdogEnabled = true }) {
130
- const url = this.buildUrl(model, stream, 0, credentials);
131
- const transformedBody = this.transformRequest(model, body, stream, credentials);
391
+ async execute(args) {
392
+ const result = await super.execute(args);
393
+ // Retries in getRetryConfig()/computeRetryDelay() are exhausted by the time
394
+ // execute() returns. A still-400 transient response at this point means every
395
+ // attempt failed the same way — remap to 429 so callers (e.g. Claude Code CLI)
396
+ // that only auto-retry 429/503 treat it as retryable instead of terminal.
397
+ if (result?.response && !result.response.ok && result.response.status === HTTP_STATUS.BAD_REQUEST) {
398
+ const bodyText = await result.response.clone().text().catch(() => "");
399
+ if (this._isRetryable400(bodyText)) {
400
+ args.log?.debug?.("RETRY", "400 → 429 remap (transient Kiro error)");
401
+ result.response = new Response(bodyText, {
402
+ status: HTTP_STATUS.RATE_LIMITED,
403
+ statusText: "Too Many Requests",
404
+ headers: result.response.headers
405
+ });
406
+ }
407
+ }
408
+ if (result?.response?.ok) this.attachIntegrityGate(result, args);
409
+ return result;
410
+ }
132
411
 
133
- // Resolve max retry count: per-account → global setting → default
134
- const maxRetries = credentials?.kiroRetryCount ?? DEFAULT_KIRO_RETRY_COUNT;
135
- let retryAttempts = 0;
412
+ attachIntegrityGate(result, args) {
413
+ const abortController = new AbortController();
414
+ const maxBytes = envPositiveInt("KIRO_TOOL_CALL_REPAIR_BUFFER_MAX_BYTES", KIRO_REPAIR_BUFFER_MAX_BYTES);
415
+ const legacyTimeout = envPositiveInt("KIRO_TOOL_CALL_REPAIR_TIMEOUT_MS", STREAM_FIRST_CHUNK_TIMEOUT_MS);
416
+ const ttftTimeoutMs = envPositiveInt("KIRO_TOOL_CALL_REPAIR_TTFT_TIMEOUT_MS", legacyTimeout);
417
+ const stallTimeoutMs = envPositiveInt("KIRO_TOOL_CALL_REPAIR_STALL_TIMEOUT_MS", legacyTimeout);
418
+ const repairEnabled = args.credentials?.providerSpecificData?.kiroToolCallRepair !== false &&
419
+ process.env.KIRO_TOOL_CALL_REPAIR !== "false";
420
+ const forwardAbort = () => abortController.abort(args.signal?.reason);
421
+ args.signal?.addEventListener("abort", forwardAbort, { once: true });
422
+ let open = true;
423
+ let heartbeatTimer;
424
+
425
+ const stream = new ReadableStream({
426
+ start: async (controller) => {
427
+ const heartbeat = () => {
428
+ if (!open) return;
429
+ try {
430
+ controller.enqueue(encoder.encode(": kiro-validation\n\n"));
431
+ } catch {
432
+ open = false;
433
+ }
434
+ };
435
+ heartbeat();
436
+ heartbeatTimer = setInterval(heartbeat, KIRO_REPAIR_HEARTBEAT_MS);
437
+
438
+ try {
439
+ const bytes = await this.runIntegrityRecovery(result.response, args, {
440
+ signal: abortController.signal,
441
+ maxBytes,
442
+ ttftTimeoutMs,
443
+ stallTimeoutMs,
444
+ repairEnabled
445
+ });
446
+ if (abortController.signal.aborted) throw makeAbortError(abortController.signal.reason);
447
+ controller.enqueue(bytes);
448
+ controller.close();
449
+ } catch (error) {
450
+ if (open && error.name === "AbortError") {
451
+ controller.error(error);
452
+ } else if (open && error.name !== "AbortError") {
453
+ controller.enqueue(encodeSSEError(
454
+ "kiro_integrity_gate_failed",
455
+ error.message || "Kiro integrity validation failed"
456
+ ));
457
+ controller.close();
458
+ }
459
+ } finally {
460
+ open = false;
461
+ clearInterval(heartbeatTimer);
462
+ args.signal?.removeEventListener?.("abort", forwardAbort);
463
+ }
464
+ },
465
+ cancel(reason) {
466
+ open = false;
467
+ clearInterval(heartbeatTimer);
468
+ abortController.abort(reason || "client cancelled");
469
+ }
470
+ });
136
471
 
137
- while (true) {
138
- const headers = this.buildHeaders(credentials, stream);
472
+ result.response = new Response(stream, {
473
+ status: result.response.status,
474
+ statusText: result.response.statusText,
475
+ headers: { ...SSE_HEADERS }
476
+ });
477
+ }
139
478
 
140
- // Abort if upstream doesn't return response headers within FETCH_CONNECT_TIMEOUT_MS.
141
- const connectCtrl = new AbortController();
142
- const connectTimer = setTimeout(() => connectCtrl.abort(new Error("fetch connect timeout")), FETCH_CONNECT_TIMEOUT_MS);
143
- const mergedSignal = signal ? AbortSignal.any([signal, connectCtrl.signal]) : connectCtrl.signal;
479
+ async runIntegrityRecovery(rawResponse, args, options) {
480
+ const first = await this.readRecoverableIntegrityAttempt(
481
+ rawResponse,
482
+ args.model,
483
+ options,
484
+ "initial"
485
+ );
486
+ if (first.kind === "complete") return first.bytes;
487
+ if (first.kind === "terminal_stop" || first.kind === "upstream_error") {
488
+ return this.integrityFailureSSE(first);
489
+ }
490
+ if (first.kind === "invalid_tool" && !options.repairEnabled) {
491
+ return encodeSSEError("invalid_kiro_tool_call", first.message, first.diagnostics);
492
+ }
144
493
 
145
- let response;
494
+ const repairKind = ["ellipsis", "short_final", "invalid_tool"].includes(first.kind)
495
+ ? first.kind
496
+ : null;
497
+ const repairBody = repairKind
498
+ ? appendRepairInstruction(args.body, repairKind === "invalid_tool" ? "tool" : repairKind)
499
+ : structuredClone(args.body || {});
500
+
501
+ const retry = await BaseExecutor.prototype.execute.call(this, {
502
+ ...args,
503
+ body: repairBody,
504
+ signal: options.signal
505
+ });
506
+ if (!retry?.response?.ok) {
507
+ let body = "";
146
508
  try {
147
- response = await proxyAwareFetch(url, {
148
- method: "POST",
149
- headers,
150
- body: JSON.stringify(transformedBody),
151
- signal: mergedSignal
152
- }, proxyOptions);
153
- // Headers received — body streaming is now governed by the stall watchdog.
154
- clearTimeout(connectTimer);
509
+ body = await readResponsePrefix(
510
+ retry?.response,
511
+ options.signal,
512
+ Math.min(options.maxBytes, 4096),
513
+ options.stallTimeoutMs
514
+ );
155
515
  } catch (error) {
156
- clearTimeout(connectTimer);
157
- // Connect timeout is internal: convert to a retryable network error
158
- const isConnectTimeout = connectCtrl.signal.aborted && error.name === "AbortError";
159
- if (isConnectTimeout) {
160
- if (maxRetries > 0 && retryAttempts < maxRetries) {
161
- retryAttempts++;
162
- const backoffMs = this._computeBackoff(retryAttempts);
163
- log?.debug?.("RETRY", `connect timeout retry ${retryAttempts}/${maxRetries} after ${(backoffMs / 1000).toFixed(1)}s`);
164
- await new Promise(resolve => setTimeout(resolve, backoffMs));
165
- continue;
166
- }
167
- throw new Error(`Kiro upstream connect timeout after ${FETCH_CONNECT_TIMEOUT_MS}ms`);
168
- }
169
- throw error;
516
+ if (error.name === "AbortError") throw error;
170
517
  }
518
+ return encodeSSEError(
519
+ "kiro_integrity_retry_upstream_error",
520
+ body || `Kiro integrity retry failed with HTTP ${retry?.response?.status || 502}`,
521
+ { status: retry?.response?.status || 502 }
522
+ );
523
+ }
171
524
 
172
- // Check if this status code is retryable
173
- if (!response.ok && KIRO_RETRYABLE_STATUSES.has(response.status)) {
174
- // For 400, only retry known transient patterns
175
- let isTransient400 = false;
176
- if (response.status === 400) {
177
- let bodyText = "";
178
- try { bodyText = await response.clone().text(); } catch { /* ignore */ }
179
-
180
- if (!this._isRetryable400(bodyText)) {
181
- // Genuine validation error — don't retry
182
- return { response, url, headers, transformedBody };
183
- }
184
- isTransient400 = true;
185
- }
525
+ const second = await this.readRecoverableIntegrityAttempt(
526
+ retry.response,
527
+ args.model,
528
+ options,
529
+ "retry"
530
+ );
531
+ if (second.kind === "complete") return second.bytes;
532
+ if (second.kind === "terminal_stop" || second.kind === "upstream_error") {
533
+ return this.integrityFailureSSE(second);
534
+ }
535
+ const code = second.kind === "ellipsis"
536
+ ? "kiro_ellipsis_retry_failed"
537
+ : second.kind === "short_final"
538
+ ? "kiro_short_final_retry_failed"
539
+ : second.kind === "invalid_tool"
540
+ ? "kiro_tool_call_repair_retry_failed"
541
+ : "kiro_missing_terminal_retry_failed";
542
+ return encodeSSEError(
543
+ code,
544
+ `Kiro integrity validation failed after one bounded retry: ${second.message || second.kind}`,
545
+ { attempts: [first.diagnostics, second.diagnostics].filter(Boolean) }
546
+ );
547
+ }
186
548
 
187
- if (maxRetries > 0 && retryAttempts < maxRetries) {
188
- retryAttempts++;
189
- const backoffMs = this._computeBackoff(retryAttempts);
190
- log?.debug?.("RETRY", `${response.status} retry ${retryAttempts}/${maxRetries} after ${(backoffMs / 1000).toFixed(1)}s`);
191
- await new Promise(resolve => setTimeout(resolve, backoffMs));
192
- continue;
193
- }
549
+ integrityFailureSSE(attempt) {
550
+ const disposition = attempt.diagnostics?.stop_disposition;
551
+ const code = attempt.diagnostics?.terminal_provenance === "integrity_buffer_exceeded"
552
+ ? "kiro_integrity_buffer_exceeded"
553
+ : attempt.kind === "upstream_error"
554
+ ? "kiro_upstream_eventstream_error"
555
+ : disposition === "terminal_refusal"
556
+ ? "kiro_terminal_refusal"
557
+ : disposition === "terminal_incomplete"
558
+ ? "kiro_terminal_incomplete"
559
+ : "kiro_unknown_stop_reason";
560
+ return encodeSSEError(code, attempt.message || "Kiro stream ended with a terminal failure", attempt.diagnostics);
561
+ }
194
562
 
195
- // Retries exhausted — remap transient 400 to 429 so Claude Code CLI
196
- // recognizes it as retryable (CLI only retries on 429/503, not 400)
197
- if (isTransient400) {
198
- const bodyText = await response.clone().text().catch(() => "");
199
- const remappedResponse = new Response(bodyText, {
200
- status: HTTP_STATUS.RATE_LIMITED,
201
- statusText: "Too Many Requests",
202
- headers: response.headers
203
- });
204
- log?.debug?.("RETRY", `400 → 429 remap after ${retryAttempts} retries (transient Kiro error)`);
205
- return { response: remappedResponse, url, headers, transformedBody };
563
+ async readRecoverableIntegrityAttempt(rawResponse, model, options, attempt) {
564
+ try {
565
+ return await this.readIntegrityAttempt(rawResponse, model, options, attempt);
566
+ } catch (error) {
567
+ if (error.name === "AbortError") throw error;
568
+ return {
569
+ kind: "missing_terminal",
570
+ message: error.message || "Kiro transport read failed",
571
+ diagnostics: {
572
+ attempt,
573
+ terminal_provenance: "transport_read_error",
574
+ transport_state: "upstream_error",
575
+ stop_reason: null,
576
+ stop_disposition: "terminal_incomplete",
577
+ response_state: "no_semantic_output",
578
+ event_counts: {},
579
+ incomplete_frame_bytes: 0
206
580
  }
207
- }
581
+ };
582
+ }
583
+ }
208
584
 
209
- if (!response.ok) {
210
- return { response, url, headers, transformedBody };
585
+ async readIntegrityAttempt(rawResponse, model, options, attempt) {
586
+ let diagnostics;
587
+ const transformed = this.transformEventStreamToSSE(rawResponse, model, {
588
+ maxToolBytes: Math.max(1, Math.floor(options.maxBytes / 2)),
589
+ onTerminalState: (value) => {
590
+ diagnostics = value;
211
591
  }
592
+ });
593
+ const reader = transformed.body.getReader();
594
+ const chunks = [];
595
+ let totalBytes = 0;
596
+ let sawChunk = false;
597
+ const output = { content: "", reasoning: "", hasToolCalls: false, error: null };
212
598
 
213
- // Success - transform and return
214
- const transformedResponse = this.transformEventStreamToSSE(response, model, streamWatchdogEnabled);
215
- return { response: transformedResponse, url, headers, transformedBody };
599
+ try {
600
+ while (true) {
601
+ const timeoutMs = sawChunk ? options.stallTimeoutMs : options.ttftTimeoutMs;
602
+ const phase = sawChunk ? "stalled" : "timed out before first chunk";
603
+ const { done, value } = await readWithTimeout(
604
+ reader,
605
+ options.signal,
606
+ timeoutMs,
607
+ `Kiro integrity validation ${phase}`
608
+ );
609
+ if (done) break;
610
+ sawChunk = true;
611
+ totalBytes += value.byteLength;
612
+ if (totalBytes > options.maxBytes) {
613
+ await reader.cancel("kiro_integrity_buffer_exceeded").catch(() => {});
614
+ return {
615
+ kind: "terminal_stop",
616
+ message: `Kiro integrity buffer exceeded ${options.maxBytes} bytes`,
617
+ diagnostics: { terminal_provenance: "integrity_buffer_exceeded" }
618
+ };
619
+ }
620
+ chunks.push(value);
621
+ inspectSSEChunk(value, output);
622
+ }
623
+ } catch (error) {
624
+ await reader.cancel(error.message).catch(() => {});
625
+ throw error;
216
626
  }
217
- }
218
627
 
219
- /**
220
- * Compute exponential backoff with full jitter (MITM-style).
221
- * Formula: random in [0, min(cap, base * 2^(attempt-1))]
222
- * Prevents thundering herd when multiple requests hit errors simultaneously.
223
- */
224
- _computeBackoff(attempt) {
225
- const expCeiling = Math.min(KIRO_BACKOFF_CAP_MS, KIRO_BACKOFF_BASE_MS * Math.pow(2, attempt - 1));
226
- return Math.floor(Math.random() * expCeiling) + KIRO_BACKOFF_BASE_MS / 2;
628
+ const safeDiagnostics = {
629
+ attempt,
630
+ terminal_provenance: diagnostics?.terminal_provenance || "missing_terminal_diagnostics",
631
+ transport_state: diagnostics?.transport_state || "unknown",
632
+ stop_reason: diagnostics?.stop_reason || null,
633
+ stop_disposition: diagnostics?.stop_disposition || "terminal_incomplete",
634
+ response_state: diagnostics?.response_state || "no_semantic_output",
635
+ event_counts: diagnostics?.event_counts || {},
636
+ incomplete_frame_bytes: diagnostics?.incomplete_frame_bytes || 0
637
+ };
638
+ if (safeDiagnostics.stop_disposition === "retryable_protocol_failure") {
639
+ const kind = safeDiagnostics.terminal_provenance === "invalid_tool_call"
640
+ ? "invalid_tool"
641
+ : "retryable_stop";
642
+ return { kind, message: output.error?.message, diagnostics: safeDiagnostics };
643
+ }
644
+ if (safeDiagnostics.stop_disposition === "terminal_incomplete" ||
645
+ safeDiagnostics.stop_disposition === "terminal_refusal" ||
646
+ safeDiagnostics.stop_disposition === "unknown_failure") {
647
+ const kind = safeDiagnostics.terminal_provenance === "upstream_eventstream_error"
648
+ ? "upstream_error"
649
+ : safeDiagnostics.terminal_provenance === "integrity_buffer_exceeded"
650
+ ? "terminal_stop"
651
+ : ["metadata_stop_reason", "message_stop_event"].includes(safeDiagnostics.terminal_provenance)
652
+ ? "terminal_stop"
653
+ : "missing_terminal";
654
+ return { kind, message: output.error?.message, diagnostics: safeDiagnostics };
655
+ }
656
+ if (output.error) {
657
+ return { kind: "missing_terminal", message: output.error.message, diagnostics: safeDiagnostics };
658
+ }
659
+ if (!output.hasToolCalls) {
660
+ if (isEllipsisOnly(output.content) ||
661
+ (!output.content.trim() && isEllipsisOnly(output.reasoning))) {
662
+ return { kind: "ellipsis", diagnostics: safeDiagnostics };
663
+ }
664
+ if (isShortFutureAction(output.content)) {
665
+ return { kind: "short_final", diagnostics: safeDiagnostics };
666
+ }
667
+ }
668
+ return { kind: "complete", bytes: concatChunks(chunks, totalBytes), diagnostics: safeDiagnostics };
227
669
  }
228
670
 
229
- /**
230
- * Transform AWS EventStream binary response to SSE text stream
231
- * Using TransformStream instead of ReadableStream.pull() to avoid Workers timeout
232
- */
233
- transformEventStreamToSSE(response, model, streamWatchdogEnabled = true) {
234
- let buffer = new Uint8Array(0);
235
- let chunkIndex = 0;
671
+ transformEventStreamToSSE(response, model, options = {}) {
236
672
  const responseId = `chatcmpl-${Date.now()}`;
237
673
  const created = Math.floor(Date.now() / 1000);
238
674
  const capabilityModel = resolveKiroModel(model).upstream;
239
675
  const contextWindow = getCapabilitiesForModel("kiro", capabilityModel).contextWindow || 200000;
676
+ const eventCounts = {};
240
677
  const state = {
241
- endDetected: false,
242
- finishEmitted: false,
678
+ buffer: new Uint8Array(0),
679
+ chunkIndex: 0,
680
+ toolCounter: 0,
681
+ tools: new Map(),
682
+ bufferedToolBytes: 0,
683
+ hasText: false,
684
+ hasReasoning: false,
685
+ hasCode: false,
243
686
  hasToolCalls: false,
244
- hasReasoningContent: false,
245
- reasoningChunkCount: 0,
246
- toolCallIndex: 0,
247
- seenToolIds: new Map(),
248
- inThinking: false
687
+ sawToolUse: false,
688
+ explicitStop: false,
689
+ stopReason: null,
690
+ terminalProvenance: null,
691
+ transportState: "consuming_response",
692
+ totalContentLength: 0,
693
+ contextUsagePercentage: 0,
694
+ hasContextUsage: false,
695
+ hasMetering: false,
696
+ usage: null,
697
+ inThinking: false,
698
+ toolValidationError: null,
699
+ validatedFrames: 0,
700
+ finished: false
249
701
  };
250
702
 
251
- const transformStream = new TransformStream({
252
- async transform(chunk, rawController) {
253
- // Shadow the controller so we can tell whether this call emitted anything.
254
- // Raw AWS EventStream frames can buffer for a long time (reasoning prefill)
255
- // producing no SSE output; the downstream stall watchdog measures THIS
256
- // stream's output, so a silent transform call looks like a stall and gets
257
- // aborted. When a chunk arrived but yielded no frame, emit a keepalive.
258
- let emitted = false;
259
- const controller = {
260
- enqueue: (d) => { emitted = true; rawController.enqueue(d); },
261
- error: (e) => rawController.error(e),
262
- terminate: () => rawController.terminate()
263
- };
264
- // Append to buffer
265
- const newBuffer = new Uint8Array(buffer.length + chunk.length);
266
- newBuffer.set(buffer);
267
- newBuffer.set(chunk, buffer.length);
268
- buffer = newBuffer;
269
-
270
- // Parse events from buffer
271
- let iterations = 0;
272
- const maxIterations = 1000;
273
- while (buffer.length >= 16 && iterations < maxIterations) {
274
- iterations++;
275
- const view = new DataView(buffer.buffer, buffer.byteOffset);
276
- const totalLength = view.getUint32(0, false);
277
-
278
- if (totalLength < 16 || totalLength > buffer.length || buffer.length < totalLength) break;
279
-
280
- const eventData = buffer.slice(0, totalLength);
281
- buffer = buffer.slice(totalLength);
282
-
283
- const event = parseEventFrame(eventData);
284
- if (!event) continue;
285
-
286
- const eventType = event.headers[":event-type"] || "";
287
-
288
- // Track total content length for token estimation
289
- if (!state.totalContentLength) state.totalContentLength = 0;
290
- if (!state.contextUsagePercentage) state.contextUsagePercentage = 0;
291
-
292
- // Handle assistantResponseEvent
293
- if (eventType === "assistantResponseEvent" && event.payload?.content) {
294
- let content = event.payload.content;
295
-
296
- // Kiro Claude models can leak <thinking> blocks into the content stream.
297
- // We strip these literal tags to prevent duplication, as the reasoning
298
- // is already routed correctly via reasoningContentEvent.
299
- if (state.inThinking) {
300
- if (content.includes("</thinking>")) {
301
- state.inThinking = false;
302
- const after = content.split("</thinking>").slice(1).join("</thinking>");
303
- content = after.startsWith("\n") ? after.substring(1) : after;
304
- } else {
305
- content = ""; // Drop entirely while inside thinking block
306
- }
307
- } else if (content.includes("<thinking>")) {
308
- state.inThinking = true;
309
- if (content.includes("</thinking>")) {
310
- state.inThinking = false;
311
- const before = content.split("<thinking>")[0];
312
- const after = content.split("</thinking>").slice(1).join("</thinking>");
313
- content = before + (after.startsWith("\n") ? after.substring(1) : after);
314
- } else {
315
- content = content.split("<thinking>")[0];
316
- }
317
- }
318
-
319
- if (!content && state.hasReasoningContent) {
320
- // If we stripped everything, skip emitting an empty content chunk
321
- continue;
703
+ const diagnostics = (overrides = {}) => ({
704
+ terminal_provenance: state.terminalProvenance || "clean_eventstream_eof",
705
+ transport_state: state.transportState,
706
+ stop_reason: state.stopReason,
707
+ stop_disposition: stopDisposition(state.stopReason, state.hasToolCalls),
708
+ response_state: state.hasToolCalls
709
+ ? "valid_tool"
710
+ : state.hasText || state.hasReasoning || state.hasCode
711
+ ? "text_reasoning"
712
+ : state.explicitStop
713
+ ? "explicit_stop"
714
+ : "no_semantic_output",
715
+ event_counts: { ...eventCounts },
716
+ incomplete_frame_bytes: state.buffer.byteLength,
717
+ ...overrides
718
+ });
719
+ const sseChunk = (delta, finishReason = null, usage) => encoder.encode(`data: ${JSON.stringify({
720
+ id: responseId,
721
+ object: "chat.completion.chunk",
722
+ created,
723
+ model,
724
+ choices: [{ index: 0, delta, finish_reason: finishReason }],
725
+ ...(usage ? { usage } : {})
726
+ })}\n\n`);
727
+ const emitDelta = (controller, delta) => {
728
+ if (state.chunkIndex === 0) delta = { role: "assistant", ...delta };
729
+ state.chunkIndex++;
730
+ controller.enqueue(sseChunk(delta));
731
+ };
732
+ const fail = (controller, provenance, code, message, extra = {}) => {
733
+ state.finished = true;
734
+ state.terminalProvenance = provenance;
735
+ state.transportState = extra.transport_state || "corrupt_frame";
736
+ const detail = diagnostics({
737
+ stop_disposition: extra.stop_disposition || "terminal_incomplete",
738
+ ...extra
739
+ });
740
+ options.onTerminalState?.(detail);
741
+ controller.enqueue(encodeSSEError(code, message, detail));
742
+ };
743
+ const assertToolBufferBound = () => {
744
+ if (state.bufferedToolBytes <= (options.maxToolBytes || KIRO_REPAIR_BUFFER_MAX_BYTES / 2)) return;
745
+ const error = new Error("Kiro buffered tool input exceeded the integrity memory bound");
746
+ error.code = "KIRO_BUFFER_EXCEEDED";
747
+ throw error;
748
+ };
749
+ const appendToolInput = (tool, input) => {
750
+ if (input === undefined) return;
751
+ if (typeof input === "string") {
752
+ if (tool.inputKind && tool.inputKind !== "string") throw new Error("Kiro tool input changed fragment type");
753
+ tool.inputKind = "string";
754
+ tool.inputChunks ||= [];
755
+ tool.inputChunks.push(input);
756
+ state.bufferedToolBytes += encoder.encode(input).byteLength;
757
+ } else if (input && typeof input === "object" && !Array.isArray(input)) {
758
+ if (tool.inputKind && tool.inputKind !== "object") throw new Error("Kiro tool input changed fragment type");
759
+ tool.inputKind = "object";
760
+ state.bufferedToolBytes -= tool.inputBytes || 0;
761
+ tool.inputObject = input;
762
+ tool.inputBytes = encoder.encode(JSON.stringify(input)).byteLength;
763
+ state.bufferedToolBytes += tool.inputBytes;
764
+ } else {
765
+ throw new Error("Kiro tool input must be a JSON object");
766
+ }
767
+ assertToolBufferBound();
768
+ };
769
+ const parsedToolInput = (tool) => {
770
+ if (!tool.inputKind) throw new Error("Kiro tool call is missing input");
771
+ if (tool.inputKind === "object") return tool.inputObject;
772
+ try {
773
+ const input = JSON.parse(tool.inputChunks.join(""));
774
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error("not an object");
775
+ return input;
776
+ } catch (error) {
777
+ throw new Error(`Kiro tool input must be valid object JSON (${error.message})`);
778
+ }
779
+ };
780
+ const emitTools = (controller) => {
781
+ for (const tool of state.tools.values()) {
782
+ // Validate per tool, not per turn: one unusable fragment used to throw out
783
+ // of emitTools and take every other complete tool call in the same turn
784
+ // with it, which the client saw as a turn that answered nothing.
785
+ let input;
786
+ try {
787
+ input = parsedToolInput(tool);
788
+ if (tool.name === "tool_call") {
789
+ if (typeof input.name !== "string" || !input.name.trim()) {
790
+ throw new Error("Invalid Kiro tool_call payload: missing nested MCP tool name");
322
791
  }
323
-
324
- state.totalContentLength += content.length;
325
-
326
- const chunk = {
327
- id: responseId,
328
- object: "chat.completion.chunk",
329
- created,
330
- model,
331
- choices: [{
332
- index: 0,
333
- delta: chunkIndex === 0
334
- ? { role: "assistant", content }
335
- : { content },
336
- finish_reason: null
337
- }]
338
- };
339
- chunkIndex++;
340
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(chunk)}\n\n`));
341
- }
342
-
343
- // Handle reasoningContentEvent (Kiro thinking / reasoning)
344
- // Kiro returns reasoning as a separate event when the request system
345
- // prompt contains <thinking_mode>enabled</thinking_mode>. Surface it
346
- // as OpenAI delta.reasoning_content so downstream translators can map
347
- // it back to Claude thinking blocks / Anthropic reasoning, etc.
348
- if (eventType === "reasoningContentEvent") {
349
- const reasoning = event.payload?.reasoningContentEvent || event.payload || {};
350
- const reasoningText = (typeof reasoning === "string")
351
- ? reasoning
352
- : (reasoning.text || reasoning.content || "");
353
- if (reasoningText) {
354
- state.hasReasoningContent = true;
355
- state.totalContentLength += reasoningText.length;
356
-
357
- const reasoningDelta = state.reasoningChunkCount === 0 && chunkIndex === 0
358
- ? { role: "assistant", reasoning_content: reasoningText }
359
- : { reasoning_content: reasoningText };
360
-
361
- const chunk = {
362
- id: responseId,
363
- object: "chat.completion.chunk",
364
- created,
365
- model,
366
- choices: [{
367
- index: 0,
368
- delta: reasoningDelta,
369
- finish_reason: null
370
- }]
371
- };
372
- chunkIndex++;
373
- state.reasoningChunkCount++;
374
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(chunk)}\n\n`));
792
+ if (!Object.prototype.hasOwnProperty.call(input, "arguments")) {
793
+ throw new Error("Invalid Kiro tool_call payload: missing nested MCP tool arguments");
375
794
  }
376
795
  }
796
+ } catch (error) {
797
+ state.droppedTools = (state.droppedTools || 0) + 1;
798
+ state.toolValidationError ||= error.message;
799
+ console.error(`[Kiro] dropping unusable tool call ${tool.id} (${tool.name}): ${error.message}`);
800
+ continue;
801
+ }
802
+ const index = state.toolCounter++;
803
+ emitDelta(controller, {
804
+ tool_calls: [{
805
+ index,
806
+ id: tool.id,
807
+ type: "function",
808
+ function: { name: tool.name, arguments: "" }
809
+ }]
810
+ });
811
+ const serializedInput = JSON.stringify(input);
812
+ emitDelta(controller, {
813
+ tool_calls: [{ index, function: { arguments: serializedInput } }]
814
+ });
815
+ // Tool arguments are billed output like any other completion bytes. They
816
+ // were never added to totalContentLength, so the /4 estimator in finish()
817
+ // reported OUT 0 -- or the Math.max floor of 1 -- for every turn whose
818
+ // entire answer was a tool call.
819
+ state.totalContentLength += tool.name.length + serializedInput.length;
820
+ state.hasToolCalls = true;
821
+ }
822
+ state.tools.clear();
823
+ state.bufferedToolBytes = 0;
824
+ // A declared tool turn that emitted no usable call is only fatal when the
825
+ // turn produced nothing else. Throwing unconditionally here escaped
826
+ // emitTools() with provenance "invalid_tool_call", which the integrity gate
827
+ // re-derived into a repair retry -- discarding text the client had already
828
+ // been promised.
829
+ if (state.stopReason === "tool_use" && !state.hasToolCalls &&
830
+ !state.hasText && !state.hasReasoning && !state.hasCode) {
831
+ throw new Error("Kiro tool_use stop reason did not include a complete tool call");
832
+ }
833
+ };
834
+ const processEvent = (event, controller) => {
835
+ const messageType = event.headers[":message-type"];
836
+ if (messageType === "error" || messageType === "exception") {
837
+ fail(
838
+ controller,
839
+ "upstream_eventstream_error",
840
+ "kiro_upstream_eventstream_error",
841
+ event.payload?.message || `Kiro upstream sent an EventStream ${messageType}`,
842
+ { transport_state: "upstream_error" }
843
+ );
844
+ return false;
845
+ }
377
846
 
378
- // Handle codeEvent
379
- if (eventType === "codeEvent" && event.payload?.content) {
380
- const chunk = {
381
- id: responseId,
382
- object: "chat.completion.chunk",
383
- created,
384
- model,
385
- choices: [{
386
- index: 0,
387
- delta: { content: event.payload.content },
388
- finish_reason: null
389
- }]
390
- };
391
- chunkIndex++;
392
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(chunk)}\n\n`));
847
+ const eventType = event.headers[":event-type"] || "";
848
+ const eventCountKey = KIRO_EVENT_TYPES.has(eventType) ? eventType : "other";
849
+ eventCounts[eventCountKey] = (eventCounts[eventCountKey] || 0) + 1;
850
+ if (eventType === "assistantResponseEvent" && typeof event.payload?.content === "string") {
851
+ let content = event.payload.content;
852
+ if (state.inThinking) {
853
+ const end = content.indexOf("</thinking>");
854
+ if (end < 0) content = "";
855
+ else {
856
+ state.inThinking = false;
857
+ content = content.slice(end + 11).replace(/^\n/u, "");
393
858
  }
394
-
395
- // Handle toolUseEvent
396
- if (eventType === "toolUseEvent" && event.payload) {
397
- state.hasToolCalls = true;
398
- const toolUse = event.payload;
399
- const toolUses = Array.isArray(toolUse) ? toolUse : [toolUse];
400
-
401
- for (const singleToolUse of toolUses) {
402
- const toolCallId = singleToolUse.toolUseId || `call_${Date.now()}`;
403
- const toolName = singleToolUse.name || "";
404
- const toolInput = singleToolUse.input;
405
-
406
- let toolIndex;
407
- const isNewTool = !state.seenToolIds.has(toolCallId);
408
-
409
- if (isNewTool) {
410
- toolIndex = state.toolCallIndex++;
411
- state.seenToolIds.set(toolCallId, toolIndex);
412
-
413
- const startChunk = {
414
- id: responseId,
415
- object: "chat.completion.chunk",
416
- created,
417
- model,
418
- choices: [{
419
- index: 0,
420
- delta: {
421
- ...(chunkIndex === 0 ? { role: "assistant" } : {}),
422
- tool_calls: [{
423
- index: toolIndex,
424
- id: toolCallId,
425
- type: "function",
426
- function: {
427
- name: toolName,
428
- arguments: ""
429
- }
430
- }]
431
- },
432
- finish_reason: null
433
- }]
434
- };
435
- chunkIndex++;
436
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(startChunk)}\n\n`));
437
- } else {
438
- toolIndex = state.seenToolIds.get(toolCallId);
439
- }
440
-
441
- if (toolInput !== undefined) {
442
- let argumentsStr;
443
-
444
- if (typeof toolInput === 'string') {
445
- argumentsStr = toolInput;
446
- } else if (typeof toolInput === 'object') {
447
- argumentsStr = JSON.stringify(toolInput);
448
- } else {
449
- continue;
450
- }
451
-
452
- const argsChunk = {
453
- id: responseId,
454
- object: "chat.completion.chunk",
455
- created,
456
- model,
457
- choices: [{
458
- index: 0,
459
- delta: {
460
- tool_calls: [{
461
- index: toolIndex,
462
- function: {
463
- arguments: argumentsStr
464
- }
465
- }]
466
- },
467
- finish_reason: null
468
- }]
469
- };
470
- chunkIndex++;
471
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(argsChunk)}\n\n`));
472
- }
859
+ } else {
860
+ const start = content.indexOf("<thinking>");
861
+ if (start >= 0) {
862
+ const end = content.indexOf("</thinking>", start + 10);
863
+ if (end < 0) {
864
+ state.inThinking = true;
865
+ content = content.slice(0, start);
866
+ } else {
867
+ content = content.slice(0, start) + content.slice(end + 11).replace(/^\n/u, "");
473
868
  }
474
869
  }
475
-
476
- // Handle messageStopEvent
477
- if (eventType === "messageStopEvent") {
478
- const chunk = {
479
- id: responseId,
480
- object: "chat.completion.chunk",
481
- created,
482
- model,
483
- choices: [{
484
- index: 0,
485
- delta: {},
486
- finish_reason: state.hasToolCalls ? "tool_calls" : "stop"
487
- }]
488
- };
489
- state.finishEmitted = true;
490
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(chunk)}\n\n`));
491
- }
492
-
493
- // Handle contextUsageEvent to extract contextUsagePercentage
494
- if (eventType === "contextUsageEvent" && event.payload?.contextUsagePercentage) {
495
- state.contextUsagePercentage = event.payload.contextUsagePercentage;
496
- // Mark that we received context usage event
497
- state.hasContextUsage = true;
870
+ }
871
+ if (content || !state.hasReasoning) {
872
+ state.hasText ||= content.length > 0;
873
+ state.totalContentLength += content.length;
874
+ emitDelta(controller, { content });
875
+ }
876
+ } else if (eventType === "reasoningContentEvent") {
877
+ const value = event.payload?.reasoningContentEvent || event.payload || {};
878
+ const content = typeof value === "string" ? value : value.text || value.content || "";
879
+ if (content) {
880
+ state.hasReasoning = true;
881
+ state.totalContentLength += content.length;
882
+ emitDelta(controller, { reasoning_content: content });
883
+ }
884
+ } else if (eventType === "codeEvent" && typeof event.payload?.content === "string") {
885
+ state.hasCode = true;
886
+ state.totalContentLength += event.payload.content.length;
887
+ emitDelta(controller, { content: event.payload.content });
888
+ } else if (eventType === "toolUseEvent") {
889
+ state.sawToolUse = true;
890
+ const values = Array.isArray(event.payload) ? event.payload : [event.payload];
891
+ if (!values[0]) throw new Error("Kiro toolUseEvent is empty");
892
+ for (const value of values) {
893
+ const name = typeof value?.name === "string" ? value.name.trim() : "";
894
+ if (!name) throw new Error("Kiro toolUseEvent is missing a tool name");
895
+ let id;
896
+ if (value.toolUseId == null) {
897
+ id = `call_${created}_${state.tools.size + 1}`;
898
+ } else if (typeof value.toolUseId !== "string" || !value.toolUseId.trim()) {
899
+ throw new Error("Kiro toolUseEvent has an invalid toolUseId");
900
+ } else {
901
+ id = value.toolUseId;
498
902
  }
499
-
500
- // Handle meteringEvent - mark that we received it
501
- if (eventType === "meteringEvent") {
502
- state.hasMeteringEvent = true;
903
+ let tool = state.tools.get(id);
904
+ if (!tool) {
905
+ tool = { id, name };
906
+ state.tools.set(id, tool);
907
+ state.bufferedToolBytes += encoder.encode(id).byteLength + encoder.encode(name).byteLength + 32;
908
+ assertToolBufferBound();
909
+ } else if (tool.name !== name) {
910
+ throw new Error("Kiro tool name changed between fragments");
503
911
  }
912
+ appendToolInput(tool, value.input);
913
+ }
914
+ } else if (eventType === "messageStopEvent") {
915
+ state.explicitStop = true;
916
+ const reason = normalizeStopReason(
917
+ event.payload?.stopReason ?? event.payload?.stop_reason
918
+ ) || (state.sawToolUse ? "tool_use" : "end_turn");
919
+ const merged = mergeStopReason(state.stopReason, reason);
920
+ if (merged !== state.stopReason) state.terminalProvenance = "message_stop_event";
921
+ state.stopReason = merged;
922
+ } else if (eventType === "metadataEvent" || eventType === "MetadataEvent") {
923
+ const metadata = event.payload?.metadataEvent || event.payload?.metadata || event.payload;
924
+ const reason = normalizeStopReason(metadata?.stopReason ?? metadata?.stop_reason);
925
+ if (reason) {
926
+ state.explicitStop = true;
927
+ const merged = mergeStopReason(state.stopReason, reason);
928
+ if (merged !== state.stopReason) state.terminalProvenance = "metadata_stop_reason";
929
+ state.stopReason = merged;
930
+ }
931
+ } else if (eventType === "contextUsageEvent") {
932
+ const percentage = Number(event.payload?.contextUsagePercentage);
933
+ if (Number.isFinite(percentage)) {
934
+ state.contextUsagePercentage = percentage;
935
+ state.hasContextUsage = true;
936
+ }
937
+ } else if (eventType === "meteringEvent") {
938
+ state.hasMetering = true;
939
+ const metering = event.payload?.meteringEvent || event.payload || {};
940
+ const credits = Number(metering.usage);
941
+ if (Number.isFinite(credits)) {
942
+ state.usage = {
943
+ ...(state.usage || {}),
944
+ kiro_credits: credits,
945
+ kiro_credit_unit: typeof metering.unit === "string" ? metering.unit : "credit"
946
+ };
947
+ }
948
+ } else if (eventType === "metricsEvent") {
949
+ const metrics = event.payload?.metricsEvent || event.payload || {};
950
+ const prompt = Number(metrics.inputTokens) || 0;
951
+ const completion = Number(metrics.outputTokens) || 0;
952
+ if (prompt || completion) {
953
+ state.usage = {
954
+ ...(state.usage || {}),
955
+ prompt_tokens: prompt,
956
+ completion_tokens: completion,
957
+ total_tokens: prompt + completion
958
+ };
959
+ const cacheRead = Number(metrics.cacheReadInputTokens || metrics.cache_read_input_tokens) || 0;
960
+ const cacheCreate = Number(metrics.cacheCreationInputTokens || metrics.cache_creation_input_tokens) || 0;
961
+ if (cacheRead) state.usage.cache_read_input_tokens = cacheRead;
962
+ if (cacheCreate) state.usage.cache_creation_input_tokens = cacheCreate;
963
+ }
964
+ }
965
+ return true;
966
+ };
967
+ const processBytes = (chunk, controller) => {
968
+ const combinedLength = state.buffer.byteLength + chunk.byteLength;
969
+ if (combinedLength > (options.maxRawBytes || EVENTSTREAM_MAX_MESSAGE_BYTES)) {
970
+ fail(
971
+ controller,
972
+ "corrupt_eventstream_frame",
973
+ "kiro_missing_terminal",
974
+ "Kiro EventStream buffered bytes exceed the protocol bound"
975
+ );
976
+ return false;
977
+ }
978
+ if (state.buffer.byteLength === 0) {
979
+ state.buffer = chunk;
980
+ } else {
981
+ const joined = new Uint8Array(combinedLength);
982
+ joined.set(state.buffer);
983
+ joined.set(chunk, state.buffer.byteLength);
984
+ state.buffer = joined;
985
+ }
504
986
 
505
- // Handle metricsEvent for token usage
506
- if (eventType === "metricsEvent") {
507
- // Extract usage data from metricsEvent payload
508
- const metrics = event.payload?.metricsEvent || event.payload;
509
- if (metrics && typeof metrics === 'object') {
510
- const inputTokens = metrics.inputTokens || 0;
511
- const outputTokens = metrics.outputTokens || 0;
512
- // ponytail: Amazon Q upstream does not expose cache fields today,
513
- // but pick up cache_read_input_tokens / cache_creation_input_tokens
514
- // if the event shape grows them so cost tracking stays accurate.
515
- const cachedTokens = metrics.cacheReadInputTokens || metrics.cache_read_input_tokens || 0;
516
- const cacheCreationInputTokens = metrics.cacheCreationInputTokens || metrics.cache_creation_input_tokens || 0;
517
-
518
- if (inputTokens > 0 || outputTokens > 0) {
519
- state.usage = {
520
- prompt_tokens: inputTokens,
521
- completion_tokens: outputTokens,
522
- total_tokens: inputTokens + outputTokens
523
- };
524
- // Kiro is Claude-backed: inputTokens EXCLUDES cache (Claude convention),
525
- // not inclusive like OpenAI's cached_tokens. Emit cache_read_input_tokens
526
- // (not cached_tokens) so canonicalizeUsage takes the Claude fold path and
527
- // correctly adds cache back into prompt_tokens instead of undercharging.
528
- if (cachedTokens > 0) state.usage.cache_read_input_tokens = cachedTokens;
529
- if (cacheCreationInputTokens > 0) state.usage.cache_creation_input_tokens = cacheCreationInputTokens;
530
- }
531
- }
987
+ while (state.buffer.byteLength >= 12) {
988
+ const view = new DataView(state.buffer.buffer, state.buffer.byteOffset);
989
+ if (view.getUint32(8, false) !== crc32(state.buffer.subarray(0, 8))) {
990
+ fail(controller, "corrupt_eventstream_frame", "kiro_missing_terminal", "Kiro EventStream prelude CRC mismatch");
991
+ return false;
992
+ }
993
+ const totalLength = view.getUint32(0, false);
994
+ const headersLength = view.getUint32(4, false);
995
+ if (totalLength < 16 || totalLength > EVENTSTREAM_MAX_MESSAGE_BYTES ||
996
+ headersLength > EVENTSTREAM_MAX_HEADERS_BYTES || headersLength > totalLength - 16) {
997
+ fail(controller, "corrupt_eventstream_frame", "kiro_missing_terminal", "Kiro EventStream frame bounds are invalid");
998
+ return false;
999
+ }
1000
+ if (state.buffer.byteLength < totalLength) break;
1001
+ const frame = state.buffer.slice(0, totalLength);
1002
+ state.buffer = state.buffer.slice(totalLength);
1003
+ let event;
1004
+ try {
1005
+ event = parseEventFrame(frame);
1006
+ } catch (error) {
1007
+ fail(controller, "corrupt_eventstream_frame", "kiro_missing_terminal", error.message);
1008
+ return false;
1009
+ }
1010
+ state.transportState = "valid_complete_frame";
1011
+ state.validatedFrames++;
1012
+ try {
1013
+ if (!processEvent(event, controller)) return false;
1014
+ } catch (error) {
1015
+ const bufferExceeded = error.code === "KIRO_BUFFER_EXCEEDED";
1016
+ if (!bufferExceeded) {
1017
+ // Keep whatever is already buffered: the rejected fragment belongs to
1018
+ // one tool, and clearing the map dropped the complete calls too.
1019
+ state.toolValidationError ||= error.message;
1020
+ console.error(`[Kiro] tool fragment rejected, keeping ${state.tools.size} buffered tool(s): ${error.message}`);
1021
+ continue;
532
1022
  }
533
-
534
- // Emit final chunk only after receiving BOTH meteringEvent AND contextUsageEvent
535
- if (state.hasMeteringEvent && state.hasContextUsage && !state.finishEmitted) {
536
- state.finishEmitted = true;
537
-
538
- // Estimate tokens if not available from events
539
- if (!state.usage) {
540
- // Estimate output tokens from content length
541
- const estimatedOutputTokens = state.totalContentLength > 0
542
- ? Math.max(1, Math.floor(state.totalContentLength / 4))
543
- : 0;
544
-
545
- // Estimate input tokens from contextUsagePercentage
546
- const estimatedInputTokens = state.contextUsagePercentage > 0
547
- ? Math.floor(state.contextUsagePercentage * contextWindow / 100)
548
- : 0;
549
-
550
- state.usage = {
551
- prompt_tokens: estimatedInputTokens,
552
- completion_tokens: estimatedOutputTokens,
553
- total_tokens: estimatedInputTokens + estimatedOutputTokens
554
- };
1023
+ fail(
1024
+ controller,
1025
+ "integrity_buffer_exceeded",
1026
+ "kiro_integrity_buffer_exceeded",
1027
+ error.message,
1028
+ {
1029
+ transport_state: state.transportState,
1030
+ stop_disposition: "terminal_incomplete"
555
1031
  }
556
-
557
- const finishChunk = {
558
- id: responseId,
559
- object: "chat.completion.chunk",
560
- created,
561
- model,
562
- choices: [{
563
- index: 0,
564
- delta: {},
565
- finish_reason: state.hasToolCalls ? "tool_calls" : "stop"
566
- }]
567
- };
568
-
569
- // Include usage in final chunk if available
570
- if (state.usage) {
571
- finishChunk.usage = state.usage;
572
- }
573
-
574
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(finishChunk)}\n\n`));
575
- }
576
- }
577
-
578
- if (iterations >= maxIterations) {
579
- console.warn("[Kiro] Max iterations reached in event parsing");
1032
+ );
1033
+ return false;
580
1034
  }
1035
+ }
1036
+ return true;
1037
+ };
1038
+ const finish = (controller) => {
1039
+ if (state.finished) return;
1040
+ if (state.buffer.byteLength) {
1041
+ fail(
1042
+ controller,
1043
+ "incomplete_eventstream_frame",
1044
+ "kiro_missing_terminal",
1045
+ "Kiro EventStream ended with a truncated frame",
1046
+ { transport_state: "incomplete_frame" }
1047
+ );
1048
+ return;
1049
+ }
1050
+ state.transportState = "clean_eof";
1051
+ const declaredDisposition = stopDisposition(state.stopReason, state.sawToolUse);
1052
+ // model_context_window_exceeded / max_tokens map to terminal_incomplete. When
1053
+ // they arrive after the model already streamed content, fail() threw away a
1054
+ // complete-enough answer; a truncated turn is what finish_reason "length" is
1055
+ // for. chunkIndex > 0 means at least one delta already reached the client.
1056
+ const declaredTruncatedAfterOutput = declaredDisposition === "terminal_incomplete" &&
1057
+ KIRO_TRUNCATION_STOP_REASONS.has(state.stopReason) && state.chunkIndex > 0;
1058
+ if (declaredTruncatedAfterOutput) {
1059
+ console.error(`[Kiro] truncated after ${state.chunkIndex} chunk(s) (stop_reason=${state.stopReason}); keeping output`);
1060
+ }
1061
+ if (!declaredTruncatedAfterOutput && ["retryable_protocol_failure", "terminal_incomplete", "terminal_refusal", "unknown_failure"].includes(declaredDisposition)) {
1062
+ const code = declaredDisposition === "retryable_protocol_failure"
1063
+ ? "kiro_retryable_protocol_failure"
1064
+ : declaredDisposition === "terminal_refusal"
1065
+ ? "kiro_terminal_refusal"
1066
+ : declaredDisposition === "terminal_incomplete"
1067
+ ? "kiro_terminal_incomplete"
1068
+ : "kiro_unknown_stop_reason";
1069
+ fail(
1070
+ controller,
1071
+ state.terminalProvenance || "metadata_stop_reason",
1072
+ code,
1073
+ `Kiro ended with non-success stop reason: ${state.stopReason}`,
1074
+ { transport_state: state.transportState, stop_disposition: declaredDisposition }
1075
+ );
1076
+ return;
1077
+ }
1078
+ try {
1079
+ emitTools(controller);
1080
+ } catch (error) {
1081
+ fail(
1082
+ controller,
1083
+ "invalid_tool_call",
1084
+ "invalid_kiro_tool_call",
1085
+ error.message,
1086
+ { transport_state: state.transportState, stop_disposition: "retryable_protocol_failure" }
1087
+ );
1088
+ return;
1089
+ }
1090
+ // Fail only when the turn has nothing usable left. emitTools() validates
1091
+ // per tool and drops just the unusable ones, so this has to run AFTER it:
1092
+ // before, the rejected tool was still buffered and tools.size was never 0.
1093
+ // A turn that also produced text keeps that text -- the dropped call is
1094
+ // logged, not fatal.
1095
+ if (state.toolValidationError && !state.hasToolCalls &&
1096
+ !state.hasText && !state.hasReasoning && !state.hasCode) {
1097
+ fail(
1098
+ controller,
1099
+ "invalid_tool_call",
1100
+ "invalid_kiro_tool_call",
1101
+ state.toolValidationError,
1102
+ { transport_state: state.transportState, stop_disposition: "retryable_protocol_failure" }
1103
+ );
1104
+ return;
1105
+ }
581
1106
 
582
- // Bytes arrived but yielded no SSE frame yet (partial-frame buffering
583
- // during reasoning prefill). Emit a keepalive so the downstream stall
584
- // watchdog registers upstream activity and doesn't false-abort.
585
- // Skipped when the watchdog is disabled (legacy v0.4.35 behavior).
586
- if (!emitted && streamWatchdogEnabled) {
587
- rawController.enqueue(KIRO_KEEPALIVE);
588
- }
589
- },
1107
+ const hasOutput = state.hasText || state.hasReasoning || state.hasCode || state.hasToolCalls;
1108
+ if (!hasOutput && !state.explicitStop) {
1109
+ fail(
1110
+ controller,
1111
+ "empty_response_eof",
1112
+ "kiro_missing_terminal",
1113
+ "Kiro EventStream ended without model output",
1114
+ { transport_state: state.transportState }
1115
+ );
1116
+ return;
1117
+ }
590
1118
 
591
- flush(controller) {
592
- // Emit finish chunk if not already sent
593
- if (!state.finishEmitted) {
594
- state.finishEmitted = true;
595
- const finishChunk = {
596
- id: responseId,
597
- object: "chat.completion.chunk",
598
- created,
599
- model,
600
- choices: [{
601
- index: 0,
602
- delta: {},
603
- finish_reason: state.hasToolCalls ? "tool_calls" : "stop"
604
- }]
605
- };
606
- controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(finishChunk)}\n\n`));
607
- }
1119
+ const disposition = stopDisposition(state.stopReason, state.hasToolCalls);
1120
+ // Same reasoning as declaredTruncatedAfterOutput above.
1121
+ const truncatedAfterOutput = disposition === "terminal_incomplete" &&
1122
+ KIRO_TRUNCATION_STOP_REASONS.has(state.stopReason) && state.chunkIndex > 0;
1123
+ if (truncatedAfterOutput) {
1124
+ console.error(`[Kiro] truncated after ${state.chunkIndex} chunk(s) (stop_reason=${state.stopReason}); closing as length`);
1125
+ }
1126
+ if (!truncatedAfterOutput && ["retryable_protocol_failure", "terminal_incomplete", "terminal_refusal", "unknown_failure"].includes(disposition)) {
1127
+ const code = disposition === "retryable_protocol_failure"
1128
+ ? "kiro_retryable_protocol_failure"
1129
+ : disposition === "terminal_refusal"
1130
+ ? "kiro_terminal_refusal"
1131
+ : disposition === "terminal_incomplete"
1132
+ ? "kiro_terminal_incomplete"
1133
+ : "kiro_unknown_stop_reason";
1134
+ fail(
1135
+ controller,
1136
+ state.terminalProvenance || "metadata_stop_reason",
1137
+ code,
1138
+ `Kiro ended with non-success stop reason: ${state.stopReason}`,
1139
+ { transport_state: state.transportState, stop_disposition: disposition }
1140
+ );
1141
+ return;
1142
+ }
608
1143
 
609
- // Send final done message
610
- controller.enqueue(new TextEncoder().encode(SSE_DONE));
1144
+ if (state.hasMetering && state.hasContextUsage && !state.usage?.total_tokens) {
1145
+ const completion = state.totalContentLength
1146
+ ? Math.max(1, Math.floor(state.totalContentLength / 4))
1147
+ : 0;
1148
+ const prompt = Math.floor(state.contextUsagePercentage * contextWindow / 100);
1149
+ state.usage = {
1150
+ ...(state.usage || {}),
1151
+ prompt_tokens: prompt,
1152
+ completion_tokens: completion,
1153
+ total_tokens: prompt + completion
1154
+ };
611
1155
  }
612
- });
1156
+ const finishReason = truncatedAfterOutput
1157
+ ? "length"
1158
+ : state.hasToolCalls
1159
+ ? "tool_calls"
1160
+ : disposition === "length"
1161
+ ? "length"
1162
+ : "stop";
1163
+ controller.enqueue(sseChunk({}, finishReason, state.usage));
1164
+ controller.enqueue(encoder.encode(SSE_DONE));
1165
+ state.finished = true;
1166
+ options.onTerminalState?.(diagnostics({
1167
+ terminal_provenance: state.terminalProvenance || "clean_eventstream_eof",
1168
+ transport_state: state.transportState,
1169
+ // Report what this exit actually did, not the raw disposition. The
1170
+ // integrity gate re-derives its verdict from stop_disposition, so
1171
+ // reporting "terminal_incomplete" for a turn we deliberately kept made
1172
+ // it discard the very bytes we just released to the client.
1173
+ stop_disposition: truncatedAfterOutput ? "length" : disposition
1174
+ }));
1175
+ };
613
1176
 
614
- // Pipe response body through transform stream
615
1177
  if (!response.body) {
616
- return new Response(SSE_DONE, { status: response.status, headers: { "Content-Type": "text/event-stream" } });
1178
+ const detail = diagnostics({
1179
+ terminal_provenance: "missing_response_body",
1180
+ transport_state: "missing_body",
1181
+ stop_disposition: "terminal_incomplete"
1182
+ });
1183
+ options.onTerminalState?.(detail);
1184
+ return new Response(encodeSSEError(
1185
+ "kiro_missing_terminal",
1186
+ "Kiro response did not include an EventStream body",
1187
+ detail
1188
+ ), { status: response.status, headers: { ...SSE_HEADERS } });
617
1189
  }
618
- const transformedStream = response.body.pipeThrough(transformStream);
619
1190
 
620
- return new Response(transformedStream, {
1191
+ const reader = response.body.getReader();
1192
+ const stream = new ReadableStream({
1193
+ start: async (controller) => {
1194
+ try {
1195
+ while (!state.finished) {
1196
+ const { done, value } = await reader.read();
1197
+ if (done) break;
1198
+ const chunksBefore = state.chunkIndex;
1199
+ const framesBefore = state.validatedFrames;
1200
+ if (!processBytes(value, controller)) {
1201
+ await reader.cancel("invalid Kiro EventStream").catch(() => {});
1202
+ break;
1203
+ }
1204
+ if (state.validatedFrames > framesBefore && state.chunkIndex === chunksBefore) {
1205
+ controller.enqueue(encoder.encode(": kiro-upstream\n\n"));
1206
+ }
1207
+ }
1208
+ finish(controller);
1209
+ controller.close();
1210
+ } catch (error) {
1211
+ if (!state.finished) {
1212
+ fail(
1213
+ controller,
1214
+ "upstream_read_error",
1215
+ "kiro_missing_terminal",
1216
+ error.message || "Kiro EventStream read failed",
1217
+ { transport_state: "upstream_error" }
1218
+ );
1219
+ }
1220
+ controller.close();
1221
+ }
1222
+ },
1223
+ cancel(reason) {
1224
+ return reader.cancel(reason);
1225
+ }
1226
+ });
1227
+ return new Response(stream, {
621
1228
  status: response.status,
622
1229
  statusText: response.statusText,
623
1230
  headers: { ...SSE_HEADERS }
@@ -647,65 +1254,90 @@ export class KiroExecutor extends BaseExecutor {
647
1254
  /**
648
1255
  * Parse AWS EventStream frame
649
1256
  */
650
- function parseEventFrame(data) {
651
- try {
652
- const view = new DataView(data.buffer, data.byteOffset);
653
- const headersLength = view.getUint32(4, false);
654
-
655
- // Parse headers
656
- const headers = {};
657
- let offset = 12; // After prelude
658
- const headerEnd = 12 + headersLength;
659
1257
 
660
- while (offset < headerEnd && offset < data.length) {
661
- const nameLen = data[offset];
662
- offset++;
663
- if (offset + nameLen > data.length) break;
664
-
665
- const name = new TextDecoder().decode(data.slice(offset, offset + nameLen));
666
- offset += nameLen;
667
-
668
- const headerType = data[offset];
669
- offset++;
670
-
671
- if (headerType === 7) { // String type
672
- const valueLen = (data[offset] << 8) | data[offset + 1];
673
- offset += 2;
674
- if (offset + valueLen > data.length) break;
1258
+ function parseEventFrame(data) {
1259
+ if (!(data instanceof Uint8Array) || data.byteLength < 16) {
1260
+ throw new Error("AWS EventStream frame is shorter than 16 bytes");
1261
+ }
1262
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
1263
+ const totalLength = view.getUint32(0, false);
1264
+ const headersLength = view.getUint32(4, false);
1265
+ if (totalLength !== data.byteLength) {
1266
+ throw new Error("AWS EventStream frame length does not match its prelude");
1267
+ }
1268
+ if (totalLength > EVENTSTREAM_MAX_MESSAGE_BYTES ||
1269
+ headersLength > EVENTSTREAM_MAX_HEADERS_BYTES ||
1270
+ headersLength > totalLength - 16) {
1271
+ throw new Error("AWS EventStream frame bounds are invalid");
1272
+ }
1273
+ if (view.getUint32(8, false) !== crc32(data.subarray(0, 8))) {
1274
+ throw new Error("AWS EventStream prelude CRC mismatch");
1275
+ }
1276
+ if (view.getUint32(totalLength - 4, false) !== crc32(data.subarray(0, totalLength - 4))) {
1277
+ throw new Error("AWS EventStream message CRC mismatch");
1278
+ }
675
1279
 
676
- const value = new TextDecoder().decode(data.slice(offset, offset + valueLen));
677
- offset += valueLen;
678
- headers[name] = value;
679
- } else {
680
- break;
681
- }
1280
+ const headers = Object.create(null);
1281
+ const names = new Set();
1282
+ let offset = 12;
1283
+ const headerEnd = offset + headersLength;
1284
+ const requireBytes = (count) => {
1285
+ if (offset + count > headerEnd) {
1286
+ throw new Error("AWS EventStream header exceeds its declared bounds");
682
1287
  }
683
-
684
- // Parse payload
685
- const payloadStart = 12 + headersLength;
686
- const payloadEnd = data.length - 4; // Exclude message CRC
687
-
688
- let payload = null;
689
- if (payloadEnd > payloadStart) {
690
- const payloadStr = new TextDecoder().decode(data.slice(payloadStart, payloadEnd));
691
-
692
- // Skip empty or whitespace-only payloads
693
- if (!payloadStr || !payloadStr.trim()) {
694
- return { headers, payload: null };
695
- }
696
-
697
- try {
698
- payload = JSON.parse(payloadStr);
699
- } catch (parseError) {
700
- // Log parse error for debugging
701
- console.warn(`[Kiro] Failed to parse payload: ${parseError.message} | payload: ${payloadStr.substring(0, 100)}`);
702
- payload = { raw: payloadStr };
703
- }
1288
+ };
1289
+
1290
+ while (offset < headerEnd) {
1291
+ requireBytes(1);
1292
+ const nameLength = data[offset++];
1293
+ requireBytes(nameLength + 1);
1294
+ const name = decoder.decode(data.subarray(offset, offset + nameLength));
1295
+ offset += nameLength;
1296
+ if (names.has(name)) throw new Error(`AWS EventStream contains duplicate header: ${name}`);
1297
+ names.add(name);
1298
+ const type = data[offset++];
1299
+
1300
+ if (type === 0 || type === 1) {
1301
+ headers[name] = type === 0;
1302
+ } else if (type === 2) {
1303
+ requireBytes(1);
1304
+ headers[name] = view.getInt8(offset);
1305
+ offset += 1;
1306
+ } else if (type === 3) {
1307
+ requireBytes(2);
1308
+ headers[name] = view.getInt16(offset, false);
1309
+ offset += 2;
1310
+ } else if (type === 4) {
1311
+ requireBytes(4);
1312
+ headers[name] = view.getInt32(offset, false);
1313
+ offset += 4;
1314
+ } else if (type === 5 || type === 8) {
1315
+ requireBytes(8);
1316
+ offset += 8;
1317
+ } else if (type === 6 || type === 7) {
1318
+ requireBytes(2);
1319
+ const valueLength = view.getUint16(offset, false);
1320
+ offset += 2;
1321
+ requireBytes(valueLength);
1322
+ const bytes = data.subarray(offset, offset + valueLength);
1323
+ headers[name] = type === 7 ? decoder.decode(bytes) : bytes;
1324
+ offset += valueLength;
1325
+ } else if (type === 9) {
1326
+ requireBytes(16);
1327
+ offset += 16;
1328
+ } else {
1329
+ throw new Error(`AWS EventStream header ${name} has unknown type ${type}`);
704
1330
  }
1331
+ }
705
1332
 
706
- return { headers, payload };
707
- } catch {
708
- return null;
1333
+ const payloadBytes = data.subarray(headerEnd, totalLength - 4);
1334
+ if (payloadBytes.byteLength === 0) return { headers, payload: null };
1335
+ const payloadText = decoder.decode(payloadBytes);
1336
+ if (!payloadText.trim()) return { headers, payload: null };
1337
+ try {
1338
+ return { headers, payload: JSON.parse(payloadText) };
1339
+ } catch (error) {
1340
+ throw new Error(`AWS EventStream payload is not valid JSON (${error.message})`);
709
1341
  }
710
1342
  }
711
1343