@pentoshi/clai 4.11.26 → 4.11.27

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 (276) hide show
  1. package/dist/agent/compaction/summary-execution.js +11 -1
  2. package/dist/agent/compaction/summary-execution.js.map +1 -1
  3. package/dist/agent/context-manager.d.ts +0 -1
  4. package/dist/agent/context-manager.js +0 -1
  5. package/dist/agent/context-manager.js.map +1 -1
  6. package/dist/agent/events.d.ts +1 -5
  7. package/dist/agent/plan/actions/plan-clear.js +1 -1
  8. package/dist/agent/plan/actions/plan-clear.js.map +1 -1
  9. package/dist/agent/plan/actions/plan-create.js +38 -17
  10. package/dist/agent/plan/actions/plan-create.js.map +1 -1
  11. package/dist/agent/plan/actions/task-add.js +15 -4
  12. package/dist/agent/plan/actions/task-add.js.map +1 -1
  13. package/dist/agent/plan/actions/task-move.js +16 -5
  14. package/dist/agent/plan/actions/task-move.js.map +1 -1
  15. package/dist/agent/plan/handle-plan-tool.js +20 -6
  16. package/dist/agent/plan/handle-plan-tool.js.map +1 -1
  17. package/dist/agent/reliability-policy.d.ts +0 -10
  18. package/dist/agent/reliability-policy.js +0 -23
  19. package/dist/agent/reliability-policy.js.map +1 -1
  20. package/dist/agent/request-accounting.js +10 -10
  21. package/dist/agent/request-accounting.js.map +1 -1
  22. package/dist/agent/request-budget.d.ts +11 -18
  23. package/dist/agent/request-budget.js +14 -53
  24. package/dist/agent/request-budget.js.map +1 -1
  25. package/dist/agent/runner.js +16 -12
  26. package/dist/agent/runner.js.map +1 -1
  27. package/dist/agent/stream-recovery.d.ts +1 -2
  28. package/dist/agent/stream-recovery.js +5 -10
  29. package/dist/agent/stream-recovery.js.map +1 -1
  30. package/dist/agent/subagents/worker.js +3 -2
  31. package/dist/agent/subagents/worker.js.map +1 -1
  32. package/dist/agent/turn/automatic-compaction-execution.js +2 -2
  33. package/dist/agent/turn/automatic-compaction-execution.js.map +1 -1
  34. package/dist/agent/turn/compaction-admission.d.ts +2 -2
  35. package/dist/agent/turn/compaction-admission.js +14 -17
  36. package/dist/agent/turn/compaction-admission.js.map +1 -1
  37. package/dist/agent/turn/compaction-coordinator.d.ts +2 -1
  38. package/dist/agent/turn/compaction-coordinator.js +12 -7
  39. package/dist/agent/turn/compaction-coordinator.js.map +1 -1
  40. package/dist/agent/turn/compaction-durable-envelope.js +1 -1
  41. package/dist/agent/turn/compaction-durable-envelope.js.map +1 -1
  42. package/dist/agent/turn/compaction-replay-selection.js +2 -3
  43. package/dist/agent/turn/compaction-replay-selection.js.map +1 -1
  44. package/dist/agent/turn/compaction-summarizer.js +1 -1
  45. package/dist/agent/turn/compaction-summarizer.js.map +1 -1
  46. package/dist/agent/turn/loop/answer-path.js +2 -2
  47. package/dist/agent/turn/loop/answer-path.js.map +1 -1
  48. package/dist/agent/turn/loop/completion-interpretation.d.ts +0 -1
  49. package/dist/agent/turn/loop/completion-interpretation.js +2 -7
  50. package/dist/agent/turn/loop/completion-interpretation.js.map +1 -1
  51. package/dist/agent/turn/loop/deps.d.ts +1 -0
  52. package/dist/agent/turn/loop/empty-response.d.ts +1 -1
  53. package/dist/agent/turn/loop/empty-response.js +2 -4
  54. package/dist/agent/turn/loop/empty-response.js.map +1 -1
  55. package/dist/agent/turn/loop/output-budget.d.ts +0 -1
  56. package/dist/agent/turn/loop/output-budget.js +4 -9
  57. package/dist/agent/turn/loop/output-budget.js.map +1 -1
  58. package/dist/agent/turn/loop/request-assembly.d.ts +1 -3
  59. package/dist/agent/turn/loop/request-assembly.js +15 -15
  60. package/dist/agent/turn/loop/request-assembly.js.map +1 -1
  61. package/dist/agent/turn/loop/round-request.js +1 -6
  62. package/dist/agent/turn/loop/round-request.js.map +1 -1
  63. package/dist/agent/turn/loop/run-rounds.js +9 -15
  64. package/dist/agent/turn/loop/run-rounds.js.map +1 -1
  65. package/dist/agent/turn/loop/state.d.ts +2 -3
  66. package/dist/agent/turn/loop/state.js +1 -2
  67. package/dist/agent/turn/loop/state.js.map +1 -1
  68. package/dist/agent/turn/loop/stream-failure.d.ts +0 -1
  69. package/dist/agent/turn/loop/stream-failure.js +5 -5
  70. package/dist/agent/turn/loop/stream-failure.js.map +1 -1
  71. package/dist/agent/turn/loop/stream-request.d.ts +0 -1
  72. package/dist/agent/turn/loop/stream-request.js +1 -3
  73. package/dist/agent/turn/loop/stream-request.js.map +1 -1
  74. package/dist/agent/turn/plan-persistence.d.ts +4 -5
  75. package/dist/agent/turn/plan-persistence.js +13 -4
  76. package/dist/agent/turn/plan-persistence.js.map +1 -1
  77. package/dist/agent/turn/provider-measurement.d.ts +6 -0
  78. package/dist/agent/turn/provider-measurement.js +19 -0
  79. package/dist/agent/turn/provider-measurement.js.map +1 -0
  80. package/dist/agent/turn/responder-job-linkage.js +2 -2
  81. package/dist/agent/turn/responder-job-linkage.js.map +1 -1
  82. package/dist/agent/turn/setup/compaction-services.d.ts +2 -1
  83. package/dist/agent/turn/setup/compaction-services.js +2 -1
  84. package/dist/agent/turn/setup/compaction-services.js.map +1 -1
  85. package/dist/agent/turn/setup/task-gate-setup.d.ts +3 -3
  86. package/dist/agent/turn/setup/task-gate-setup.js.map +1 -1
  87. package/dist/agent/turn/task-autostart.d.ts +2 -2
  88. package/dist/agent/turn/task-autostart.js +7 -9
  89. package/dist/agent/turn/task-autostart.js.map +1 -1
  90. package/dist/agent/turn/task-credit.d.ts +2 -2
  91. package/dist/agent/turn/task-credit.js +8 -5
  92. package/dist/agent/turn/task-credit.js.map +1 -1
  93. package/dist/agent/turn/tool-execution/deps.d.ts +3 -3
  94. package/dist/agent/turn/tool-execution/dispatch.js +3 -5
  95. package/dist/agent/turn/tool-execution/dispatch.js.map +1 -1
  96. package/dist/agent/turn/tool-execution/meta-tools.d.ts +1 -1
  97. package/dist/agent/turn/tool-execution/meta-tools.js +13 -11
  98. package/dist/agent/turn/tool-execution/meta-tools.js.map +1 -1
  99. package/dist/agent/turn/tool-execution/plan-tool-ledger.d.ts +2 -2
  100. package/dist/agent/turn/tool-execution/plan-tool-ledger.js +6 -6
  101. package/dist/agent/turn/tool-execution/plan-tool-ledger.js.map +1 -1
  102. package/dist/agent/turn/tool-execution/result-framing.d.ts +1 -1
  103. package/dist/agent/turn/tool-execution/result-framing.js +1 -2
  104. package/dist/agent/turn/tool-execution/result-framing.js.map +1 -1
  105. package/dist/agent/turn/tool-execution/single-tool.js +28 -16
  106. package/dist/agent/turn/tool-execution/single-tool.js.map +1 -1
  107. package/dist/app/adapters/agent-event-adapter.js +7 -7
  108. package/dist/app/adapters/agent-event-adapter.js.map +1 -1
  109. package/dist/app/controllers/plan-controller.js +4 -1
  110. package/dist/app/controllers/plan-controller.js.map +1 -1
  111. package/dist/app/controllers/session-compact-helper.js +11 -8
  112. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  113. package/dist/app/controllers/session-context-usage.d.ts +6 -4
  114. package/dist/app/controllers/session-context-usage.js +94 -33
  115. package/dist/app/controllers/session-context-usage.js.map +1 -1
  116. package/dist/app/controllers/session-controller.d.ts +5 -6
  117. package/dist/app/controllers/session-controller.js +48 -40
  118. package/dist/app/controllers/session-controller.js.map +1 -1
  119. package/dist/app/controllers/session-responder.d.ts +2 -0
  120. package/dist/app/controllers/session-responder.js +18 -0
  121. package/dist/app/controllers/session-responder.js.map +1 -1
  122. package/dist/app/events/app-event.d.ts +3 -5
  123. package/dist/app/events/app-event.js.map +1 -1
  124. package/dist/classic/panels/pager-panel.js +3 -2
  125. package/dist/classic/panels/pager-panel.js.map +1 -1
  126. package/dist/commands/providers.d.ts +2 -0
  127. package/dist/commands/providers.js +49 -7
  128. package/dist/commands/providers.js.map +1 -1
  129. package/dist/llm/anthropic.d.ts +1 -0
  130. package/dist/llm/anthropic.js +20 -21
  131. package/dist/llm/anthropic.js.map +1 -1
  132. package/dist/llm/capabilities.d.ts +1 -4
  133. package/dist/llm/capabilities.js +24 -19
  134. package/dist/llm/capabilities.js.map +1 -1
  135. package/dist/llm/capability/state.js +0 -17
  136. package/dist/llm/capability/state.js.map +1 -1
  137. package/dist/llm/catalog-facts.js +40 -11
  138. package/dist/llm/catalog-facts.js.map +1 -1
  139. package/dist/llm/catalog-prefetch.js +9 -6
  140. package/dist/llm/catalog-prefetch.js.map +1 -1
  141. package/dist/llm/context-snapshot.d.ts +7 -3
  142. package/dist/llm/context-snapshot.js +35 -14
  143. package/dist/llm/context-snapshot.js.map +1 -1
  144. package/dist/llm/context-windows.d.ts +16 -0
  145. package/dist/llm/context-windows.js +54 -19
  146. package/dist/llm/context-windows.js.map +1 -1
  147. package/dist/llm/custom-providers.js +5 -4
  148. package/dist/llm/custom-providers.js.map +1 -1
  149. package/dist/llm/explabs.js +35 -26
  150. package/dist/llm/explabs.js.map +1 -1
  151. package/dist/llm/free.d.ts +1 -1
  152. package/dist/llm/free.js +26 -18
  153. package/dist/llm/free.js.map +1 -1
  154. package/dist/llm/gemini.js +25 -12
  155. package/dist/llm/gemini.js.map +1 -1
  156. package/dist/llm/kiro-auth.d.ts +34 -3
  157. package/dist/llm/kiro-auth.js +315 -144
  158. package/dist/llm/kiro-auth.js.map +1 -1
  159. package/dist/llm/kiro-import-sources.d.ts +10 -0
  160. package/dist/llm/kiro-import-sources.js +117 -0
  161. package/dist/llm/kiro-import-sources.js.map +1 -0
  162. package/dist/llm/kiro-reasoning.d.ts +28 -0
  163. package/dist/llm/kiro-reasoning.js +150 -0
  164. package/dist/llm/kiro-reasoning.js.map +1 -0
  165. package/dist/llm/kiro-social-device.d.ts +21 -0
  166. package/dist/llm/kiro-social-device.js +101 -0
  167. package/dist/llm/kiro-social-device.js.map +1 -0
  168. package/dist/llm/kiro.d.ts +3 -1
  169. package/dist/llm/kiro.js +653 -187
  170. package/dist/llm/kiro.js.map +1 -1
  171. package/dist/llm/learned-capabilities.js +1 -3
  172. package/dist/llm/learned-capabilities.js.map +1 -1
  173. package/dist/llm/merge-gateway.js +18 -13
  174. package/dist/llm/merge-gateway.js.map +1 -1
  175. package/dist/llm/model-limit-store.d.ts +15 -0
  176. package/dist/llm/model-limit-store.js +121 -0
  177. package/dist/llm/model-limit-store.js.map +1 -0
  178. package/dist/llm/nvidia.d.ts +1 -0
  179. package/dist/llm/nvidia.js +15 -17
  180. package/dist/llm/nvidia.js.map +1 -1
  181. package/dist/llm/ollama-model-limits.d.ts +4 -0
  182. package/dist/llm/ollama-model-limits.js +91 -0
  183. package/dist/llm/ollama-model-limits.js.map +1 -0
  184. package/dist/llm/ollama.js +2 -1
  185. package/dist/llm/ollama.js.map +1 -1
  186. package/dist/llm/orcarouter.d.ts +1 -0
  187. package/dist/llm/orcarouter.js +8 -1
  188. package/dist/llm/orcarouter.js.map +1 -1
  189. package/dist/llm/provider-context-usage.d.ts +9 -0
  190. package/dist/llm/provider-context-usage.js +39 -0
  191. package/dist/llm/provider-context-usage.js.map +1 -0
  192. package/dist/llm/qwen-cloud.d.ts +1 -0
  193. package/dist/llm/qwen-cloud.js +44 -9
  194. package/dist/llm/qwen-cloud.js.map +1 -1
  195. package/dist/llm/reasoning-errors.d.ts +1 -0
  196. package/dist/llm/reasoning-errors.js +6 -0
  197. package/dist/llm/reasoning-errors.js.map +1 -1
  198. package/dist/llm/routing/attempt-complete.js +9 -2
  199. package/dist/llm/routing/attempt-complete.js.map +1 -1
  200. package/dist/llm/routing/attempt-request.d.ts +1 -0
  201. package/dist/llm/routing/attempt-request.js +23 -0
  202. package/dist/llm/routing/attempt-request.js.map +1 -1
  203. package/dist/llm/routing/attempt-stream.js +15 -2
  204. package/dist/llm/routing/attempt-stream.js.map +1 -1
  205. package/dist/llm/token-estimate-calibration.js +1 -2
  206. package/dist/llm/token-estimate-calibration.js.map +1 -1
  207. package/dist/llm/token-usage.d.ts +2 -0
  208. package/dist/llm/token-usage.js +1 -1
  209. package/dist/llm/token-usage.js.map +1 -1
  210. package/dist/llm/wire/anthropic-model-catalog.d.ts +1 -0
  211. package/dist/llm/wire/anthropic-model-catalog.js +30 -0
  212. package/dist/llm/wire/anthropic-model-catalog.js.map +1 -0
  213. package/dist/llm/wire/dashscope-model-catalog.d.ts +1 -0
  214. package/dist/llm/wire/dashscope-model-catalog.js +53 -0
  215. package/dist/llm/wire/dashscope-model-catalog.js.map +1 -0
  216. package/dist/llm/wire/orcarouter-model-catalog.d.ts +2 -0
  217. package/dist/llm/wire/orcarouter-model-catalog.js +91 -0
  218. package/dist/llm/wire/orcarouter-model-catalog.js.map +1 -0
  219. package/dist/noninteractive/stream-blocks.d.ts +0 -3
  220. package/dist/noninteractive/stream-blocks.js +0 -9
  221. package/dist/noninteractive/stream-blocks.js.map +1 -1
  222. package/dist/noninteractive/stream-renderer.js +1 -4
  223. package/dist/noninteractive/stream-renderer.js.map +1 -1
  224. package/dist/store/config/endpoints.d.ts +0 -6
  225. package/dist/store/config/endpoints.js +1 -35
  226. package/dist/store/config/endpoints.js.map +1 -1
  227. package/dist/store/context-limits.d.ts +4 -0
  228. package/dist/store/context-limits.js +29 -0
  229. package/dist/store/context-limits.js.map +1 -0
  230. package/dist/store/plan/jsonl-backend.js +1 -4
  231. package/dist/store/plan/jsonl-backend.js.map +1 -1
  232. package/dist/store/plan/mutation.js +31 -1
  233. package/dist/store/plan/mutation.js.map +1 -1
  234. package/dist/store/plan/sqlite-backend.js +27 -9
  235. package/dist/store/plan/sqlite-backend.js.map +1 -1
  236. package/dist/tui-v2/components/pager/pager-line.d.ts +2 -0
  237. package/dist/tui-v2/components/pager/pager-line.js +1 -2
  238. package/dist/tui-v2/components/pager/pager-line.js.map +1 -1
  239. package/dist/tui-v2/components/pager/pager.js +5 -2
  240. package/dist/tui-v2/components/pager/pager.js.map +1 -1
  241. package/dist/tui-v2/components/transcript/tool-card.js +1 -1
  242. package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
  243. package/dist/types.d.ts +3 -1
  244. package/dist/types.js.map +1 -1
  245. package/dist/ui-core/bootstrap/composition-root.js +8 -5
  246. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  247. package/dist/ui-core/bootstrap/session-resume.js +1 -2
  248. package/dist/ui-core/bootstrap/session-resume.js.map +1 -1
  249. package/dist/ui-core/commands/key-commands.d.ts +2 -0
  250. package/dist/ui-core/commands/key-commands.js +76 -20
  251. package/dist/ui-core/commands/key-commands.js.map +1 -1
  252. package/dist/ui-core/commands/session-commands.js +33 -9
  253. package/dist/ui-core/commands/session-commands.js.map +1 -1
  254. package/dist/ui-core/rendering/batch-sections.js +10 -1
  255. package/dist/ui-core/rendering/batch-sections.js.map +1 -1
  256. package/dist/ui-core/rendering/context-limit.d.ts +0 -1
  257. package/dist/ui-core/rendering/context-limit.js +2 -2
  258. package/dist/ui-core/rendering/context-limit.js.map +1 -1
  259. package/dist/ui-core/rendering/subagent-presentation.d.ts +2 -0
  260. package/dist/ui-core/rendering/subagent-presentation.js +20 -7
  261. package/dist/ui-core/rendering/subagent-presentation.js.map +1 -1
  262. package/dist/ui-core/rendering/subagent-source.js +15 -8
  263. package/dist/ui-core/rendering/subagent-source.js.map +1 -1
  264. package/dist/ui-core/state/transcript/apply-app-event.js +0 -1
  265. package/dist/ui-core/state/transcript/apply-app-event.js.map +1 -1
  266. package/dist/ui-core/state/transcript-types.js +1 -1
  267. package/dist/ui-core/state/transcript-types.js.map +1 -1
  268. package/dist/version.generated.d.ts +2 -2
  269. package/dist/version.generated.js +2 -2
  270. package/package.json +1 -1
  271. package/dist/app/controllers/session-context-limits.d.ts +0 -8
  272. package/dist/app/controllers/session-context-limits.js +0 -35
  273. package/dist/app/controllers/session-context-limits.js.map +0 -1
  274. package/dist/store/config/compaction.d.ts +0 -1
  275. package/dist/store/config/compaction.js +0 -2
  276. package/dist/store/config/compaction.js.map +0 -1
package/dist/llm/kiro.js CHANGED
@@ -1,11 +1,18 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { defaultModels, } from "./provider.js";
3
3
  import { ProviderError } from "./http.js";
4
- import { assertValidAwsRegion, decodeKiroKey, getKiroUsageLimits, isKiroOAuthToken, listKiroModelsDetailed, maybeRefreshKiroCredential, } from "./kiro-auth.js";
4
+ import { decodeKiroKey, discoverKiroModelsDetailed, getKiroUsageLimits, isKiroOAuthToken, KiroRefreshError, kiroCredentialNeedsRefresh, maybeRefreshKiroCredential, resolveKiroRuntimeRegion, } from "./kiro-auth.js";
5
5
  import { currentSessionAffinity } from "./session-affinity.js";
6
- import { generationFetch } from "./operation-usage.js";
6
+ import { nearestAcceptedEffort } from "./reasoning-controls.js";
7
+ import { completeGenerationAttempt, generationFetch, } from "./operation-usage.js";
7
8
  import { learnModelVisionCapability } from "./capability/vision-registry.js";
8
9
  import { emitStreamReasoningDelta } from "./stream-events.js";
10
+ import { createReasoningArtifactProvenance, createReasoningArtifactReplayTarget, reasoningArtifactSignature, reasoningArtifactText, reasoningArtifactsForMessage, selectReasoningArtifactsForReplay, } from "./reasoning-artifacts.js";
11
+ import { createKiroReasoningAccumulator, kiroPrivateReasoningNote, kiroCatalogEfforts, kiroReasoningResult, sentKiroReasoningEffort, } from "./kiro-reasoning.js";
12
+ import { registerModelCatalogLimits, registerModelReasoningEfforts, } from "./capabilities.js";
13
+ import { modelContextWindow } from "./context-windows.js";
14
+ import { providerRatioPromptTokens, providerRatioUsage, } from "./provider-context-usage.js";
15
+ import { inBandBadRequestStatus } from "./reasoning-errors.js";
9
16
  import { replaceProviderKey } from "../store/keys.js";
10
17
  const KIRO_FALLBACK_BASE_MODELS = [
11
18
  "auto",
@@ -39,6 +46,8 @@ for (let i = 0; i < 256; i++) {
39
46
  }
40
47
  CRC32_TABLE[i] = c >>> 0;
41
48
  }
49
+ const KIRO_EVENTSTREAM_MAX_MESSAGE_BYTES = 24 * 1024 * 1024;
50
+ const KIRO_EVENTSTREAM_MAX_HEADERS_BYTES = 128 * 1024;
42
51
  function crc32(buf, start = 0, end = buf.length) {
43
52
  let crc = 0xffffffff;
44
53
  for (let i = start; i < end; i++) {
@@ -48,59 +57,73 @@ function crc32(buf, start = 0, end = buf.length) {
48
57
  }
49
58
  function parseHeaders(buf) {
50
59
  const headers = {};
60
+ const names = new Set();
51
61
  let offset = 0;
62
+ const requireBytes = (count) => {
63
+ if (offset + count > buf.length) {
64
+ throw new ProviderError("Kiro event-stream header exceeds its declared bounds", 502);
65
+ }
66
+ };
52
67
  while (offset < buf.length) {
68
+ requireBytes(1);
53
69
  const nameLen = buf.readUInt8(offset);
54
70
  offset += 1;
71
+ requireBytes(nameLen + 1);
55
72
  const name = buf.toString("utf8", offset, offset + nameLen);
56
73
  offset += nameLen;
74
+ if (names.has(name)) {
75
+ throw new ProviderError(`Duplicate Kiro event-stream header: ${name}`, 502);
76
+ }
77
+ names.add(name);
57
78
  const type = buf.readUInt8(offset);
58
79
  offset += 1;
59
- if (type === 0) {
60
- headers[name] = true;
61
- }
62
- else if (type === 1) {
63
- headers[name] = false;
80
+ if (type === 0 || type === 1) {
81
+ headers[name] = type === 0;
82
+ continue;
64
83
  }
65
- else if (type === 2) {
84
+ if (type === 2) {
85
+ requireBytes(1);
66
86
  headers[name] = buf.readInt8(offset);
67
87
  offset += 1;
88
+ continue;
68
89
  }
69
- else if (type === 3) {
90
+ if (type === 3) {
91
+ requireBytes(2);
70
92
  headers[name] = buf.readInt16BE(offset);
71
93
  offset += 2;
94
+ continue;
72
95
  }
73
- else if (type === 4) {
96
+ if (type === 4) {
97
+ requireBytes(4);
74
98
  headers[name] = buf.readInt32BE(offset);
75
99
  offset += 4;
100
+ continue;
76
101
  }
77
- else if (type === 5) {
78
- headers[name] = buf.readBigInt64BE(offset);
102
+ if (type === 5 || type === 8) {
103
+ requireBytes(8);
104
+ const value = buf.readBigInt64BE(offset);
105
+ headers[name] = type === 5 ? value : new Date(Number(value));
79
106
  offset += 8;
107
+ continue;
80
108
  }
81
- else if (type === 6) {
82
- const len = buf.readUInt16BE(offset);
83
- offset += 2;
84
- headers[name] = buf.subarray(offset, offset + len);
85
- offset += len;
86
- }
87
- else if (type === 7) {
109
+ if (type === 6 || type === 7) {
110
+ requireBytes(2);
88
111
  const len = buf.readUInt16BE(offset);
89
112
  offset += 2;
90
- headers[name] = buf.toString("utf8", offset, offset + len);
113
+ requireBytes(len);
114
+ headers[name] = type === 7
115
+ ? buf.toString("utf8", offset, offset + len)
116
+ : buf.subarray(offset, offset + len);
91
117
  offset += len;
118
+ continue;
92
119
  }
93
- else if (type === 8) {
94
- headers[name] = new Date(Number(buf.readBigInt64BE(offset)));
95
- offset += 8;
96
- }
97
- else if (type === 9) {
120
+ if (type === 9) {
121
+ requireBytes(16);
98
122
  headers[name] = buf.subarray(offset, offset + 16).toString("hex");
99
123
  offset += 16;
124
+ continue;
100
125
  }
101
- else {
102
- break;
103
- }
126
+ throw new ProviderError(`Unknown Kiro event-stream header type ${type}`, 502);
104
127
  }
105
128
  return headers;
106
129
  }
@@ -118,15 +141,20 @@ async function* parseEventStream(stream) {
118
141
  while (buffer.length >= 12) {
119
142
  const totalLength = buffer.readUInt32BE(0);
120
143
  if (totalLength < 16) {
121
- buffer = buffer.subarray(1);
122
- continue;
144
+ throw new ProviderError("Invalid Kiro event-stream frame length", 502);
145
+ }
146
+ if (totalLength > KIRO_EVENTSTREAM_MAX_MESSAGE_BYTES) {
147
+ throw new ProviderError(`Kiro event-stream frame length exceeds the ${KIRO_EVENTSTREAM_MAX_MESSAGE_BYTES}-byte protocol bound`, 502);
123
148
  }
124
149
  const headersLength = buffer.readUInt32BE(4);
150
+ if (headersLength > KIRO_EVENTSTREAM_MAX_HEADERS_BYTES ||
151
+ headersLength > totalLength - 16) {
152
+ throw new ProviderError("Invalid Kiro event-stream header length", 502);
153
+ }
125
154
  const preludeCrc = buffer.readUInt32BE(8);
126
155
  const expectedPreludeCrc = crc32(buffer, 0, 8);
127
156
  if (preludeCrc !== expectedPreludeCrc) {
128
- buffer = buffer.subarray(1);
129
- continue;
157
+ throw new ProviderError("Kiro event-stream prelude checksum failed", 502);
130
158
  }
131
159
  if (buffer.length < totalLength) {
132
160
  break;
@@ -134,8 +162,7 @@ async function* parseEventStream(stream) {
134
162
  const messageCrc = buffer.readUInt32BE(totalLength - 4);
135
163
  const expectedMessageCrc = crc32(buffer, 0, totalLength - 4);
136
164
  if (messageCrc !== expectedMessageCrc) {
137
- buffer = buffer.subarray(totalLength);
138
- continue;
165
+ throw new ProviderError("Kiro event-stream message checksum failed", 502);
139
166
  }
140
167
  const headersBuffer = buffer.subarray(12, 12 + headersLength);
141
168
  const payloadBuffer = buffer.subarray(12 + headersLength, totalLength - 4);
@@ -144,16 +171,27 @@ async function* parseEventStream(stream) {
144
171
  let payload = {};
145
172
  if (payloadBuffer.length > 0) {
146
173
  try {
147
- const raw = payloadBuffer.toString("utf8");
148
- payload = JSON.parse(raw);
174
+ const decoded = JSON.parse(payloadBuffer.toString("utf8"));
175
+ if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) {
176
+ throw new Error("payload is not an object");
177
+ }
178
+ payload = decoded;
149
179
  }
150
- catch {
151
- payload = { raw: payloadBuffer.toString("utf8") };
180
+ catch (error) {
181
+ const detail = error instanceof Error ? `: ${error.message}` : "";
182
+ throw new ProviderError(`Invalid Kiro event-stream JSON payload${detail}`, 502);
152
183
  }
153
184
  }
154
185
  yield { headers, payload };
155
186
  }
156
187
  }
188
+ if (buffer.length > 0) {
189
+ throw new ProviderError("Kiro event stream ended with a partial frame", 502);
190
+ }
191
+ }
192
+ catch (error) {
193
+ await reader.cancel(error).catch(() => { });
194
+ throw error;
157
195
  }
158
196
  finally {
159
197
  reader.releaseLock();
@@ -183,8 +221,8 @@ export function resolveKiroModel(model) {
183
221
  }
184
222
  return { upstream, agentic, thinking };
185
223
  }
186
- function isAdaptiveThinkingModel(model) {
187
- return /^claude/i.test(model);
224
+ function isLegacyThinkingDirectiveModel(model) {
225
+ return /^claude-(?:opus-4\.5|sonnet-4(?:\.5)?|haiku-4\.5)$/i.test(model);
188
226
  }
189
227
  function kiroEffortString(effort) {
190
228
  if (!effort || effort === "none")
@@ -201,6 +239,145 @@ function kiroEffortString(effort) {
201
239
  return "xhigh";
202
240
  return "max";
203
241
  }
242
+ function asKiroRecord(value) {
243
+ return value && typeof value === "object" && !Array.isArray(value)
244
+ ? value
245
+ : undefined;
246
+ }
247
+ function normalizeKiroStopReason(value) {
248
+ const reason = typeof value === "string" ? value.trim() : "";
249
+ const normalized = reason
250
+ .replace(/([a-z])([A-Z])/g, "$1_$2")
251
+ .toLowerCase()
252
+ .replace(/[\s-]+/g, "_");
253
+ if (["endturn", "end_turn", "stop", "stop_sequence", "completed"].includes(normalized)) {
254
+ return "end_turn";
255
+ }
256
+ if (["tooluse", "tool_use", "tool_calls"].includes(normalized))
257
+ return "tool_use";
258
+ if (["maxtokens", "max_tokens", "max_output_tokens", "length"].includes(normalized)) {
259
+ return "max_tokens";
260
+ }
261
+ return normalized;
262
+ }
263
+ function kiroStopDisposition(reason, hasToolCalls) {
264
+ if (["malformed_model_output", "invalid_model_output"].includes(reason))
265
+ return "retryable";
266
+ if (reason === "refusal" || /(?:content.*filter|guardrail|safety|policy|blocked)/u.test(reason)) {
267
+ return "blocked";
268
+ }
269
+ if (["cancelled", "pause_turn"].includes(reason))
270
+ return "incomplete";
271
+ if (["max_tokens", "model_context_window_exceeded"].includes(reason)) {
272
+ return hasToolCalls ? "incomplete" : "length";
273
+ }
274
+ if (hasToolCalls || reason === "tool_use")
275
+ return "tool_calls";
276
+ if (!reason || reason === "end_turn")
277
+ return "complete";
278
+ return "unknown";
279
+ }
280
+ function mergeKiroStopReason(current, incoming) {
281
+ if (!incoming)
282
+ return current;
283
+ if (!current)
284
+ return incoming;
285
+ const severity = (reason) => {
286
+ const disposition = kiroStopDisposition(reason, false);
287
+ if (disposition === "blocked")
288
+ return 6;
289
+ if (disposition === "incomplete" || disposition === "unknown")
290
+ return 5;
291
+ if (disposition === "retryable")
292
+ return 4;
293
+ if (disposition === "length")
294
+ return 3;
295
+ if (disposition === "tool_calls")
296
+ return 2;
297
+ return 1;
298
+ };
299
+ return severity(incoming) > severity(current) ? incoming : current;
300
+ }
301
+ function firstKiroMetric(sources, names) {
302
+ for (const source of sources) {
303
+ for (const name of names) {
304
+ const value = source[name];
305
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
306
+ return value;
307
+ }
308
+ }
309
+ }
310
+ return undefined;
311
+ }
312
+ function schemaEnum(schema) {
313
+ return Array.isArray(schema?.enum)
314
+ ? schema.enum.filter((value) => typeof value === "string")
315
+ : [];
316
+ }
317
+ function schemaProperty(schema, name) {
318
+ return asKiroRecord(asKiroRecord(schema?.properties)?.[name]);
319
+ }
320
+ function supportedEffort(requested, schema) {
321
+ const efforts = schemaEnum(schema);
322
+ if (efforts.length === 0)
323
+ return undefined;
324
+ const normalized = requested === "minimal" ? "low" : requested;
325
+ return nearestAcceptedEffort(normalized, efforts);
326
+ }
327
+ function schemaEffortFields(schema) {
328
+ const output = schemaProperty(schema, "output_config");
329
+ const outputEffort = schemaProperty(output, "effort");
330
+ if (outputEffort)
331
+ return { key: "output_config", schema: outputEffort };
332
+ const reasoning = schemaProperty(schema, "reasoning");
333
+ const reasoningEffort = schemaProperty(reasoning, "effort");
334
+ return reasoningEffort
335
+ ? { key: "reasoning", schema: reasoningEffort }
336
+ : undefined;
337
+ }
338
+ function kiroAdditionalModelFields(request, info, wantsThinking) {
339
+ const schema = info?.additionalModelRequestFieldsSchema;
340
+ const thinkingSchema = schemaProperty(schema, "thinking");
341
+ const effortFields = schemaEffortFields(schema);
342
+ if (!wantsThinking && !request.thinking)
343
+ return undefined;
344
+ const requestedEffort = wantsThinking
345
+ ? request.thinking?.effort ?? "high"
346
+ : "none";
347
+ if (!thinkingSchema && !effortFields)
348
+ return undefined;
349
+ const fields = {};
350
+ if (thinkingSchema) {
351
+ const types = schemaEnum(schemaProperty(thinkingSchema, "type"));
352
+ if (!wantsThinking && types.includes("disabled")) {
353
+ return { thinking: { type: "disabled" } };
354
+ }
355
+ if (types.includes("adaptive")) {
356
+ fields.thinking = { type: "adaptive", display: "summarized" };
357
+ }
358
+ else if (wantsThinking) {
359
+ return undefined;
360
+ }
361
+ }
362
+ if (effortFields) {
363
+ const effort = supportedEffort(requestedEffort, effortFields.schema);
364
+ if (effort)
365
+ fields[effortFields.key] = { effort };
366
+ }
367
+ const maxTokensSchema = schemaProperty(schema, "max_tokens");
368
+ if (wantsThinking && request.maxTokens && maxTokensSchema) {
369
+ const minimum = typeof maxTokensSchema.minimum === "number" ? maxTokensSchema.minimum : 1;
370
+ const maximum = typeof maxTokensSchema.maximum === "number"
371
+ ? maxTokensSchema.maximum
372
+ : info?.maxOutputTokens ?? request.maxTokens;
373
+ fields.max_tokens = Math.min(maximum, Math.max(minimum, request.maxTokens));
374
+ }
375
+ return Object.keys(fields).length > 0 ? fields : undefined;
376
+ }
377
+ function legacyThinkingDirective(effort) {
378
+ const budget = KIRO_THINKING_BUDGET[kiroEffortString(effort) || "high"] ?? 16000;
379
+ return `<thinking_mode>enabled</thinking_mode><max_thinking_length>${budget}</max_thinking_length>`;
380
+ }
204
381
  const KIRO_THINKING_BUDGET = {
205
382
  low: 4000,
206
383
  medium: 8000,
@@ -239,7 +416,12 @@ function resolveKiroCredential(auth) {
239
416
  };
240
417
  }
241
418
  async function withKiroCredential(auth, run, onStatus) {
242
- const credential = resolveKiroCredential(auth);
419
+ let credential = resolveKiroCredential(auth);
420
+ if (credential.refreshToken && kiroCredentialNeedsRefresh(credential)) {
421
+ const refreshed = await refreshStoredKiroKey(auth).catch(() => undefined);
422
+ if (refreshed)
423
+ credential = refreshed;
424
+ }
243
425
  try {
244
426
  return await run(credential);
245
427
  }
@@ -248,27 +430,51 @@ async function withKiroCredential(auth, run, onStatus) {
248
430
  if (status !== 401 && status !== 403)
249
431
  throw error;
250
432
  onStatus?.("ℹ Kiro authentication expired — attempting token refresh");
251
- const oldKey = auth.apiKey ?? "";
252
- const refreshedKey = await maybeRefreshKiroCredential(oldKey, auth.refreshToken);
253
- if (!refreshedKey || refreshedKey === oldKey) {
433
+ let newCredential;
434
+ try {
435
+ newCredential = await refreshStoredKiroKey(auth);
436
+ }
437
+ catch (refreshError) {
438
+ if (refreshError instanceof KiroRefreshError) {
439
+ throw new ProviderError(refreshError.message, status);
440
+ }
254
441
  throw error;
255
442
  }
256
- await replaceProviderKey("kiro", oldKey, refreshedKey).catch(() => { });
257
- auth.apiKey = refreshedKey;
258
- const newCredential = resolveKiroCredential({ ...auth, apiKey: refreshedKey });
443
+ if (!newCredential)
444
+ throw error;
259
445
  onStatus?.("ℹ Kiro token refreshed — retrying request");
260
446
  return run(newCredential);
261
447
  }
262
448
  }
263
- function getCandidateEndpoints(credential) {
264
- const region = assertValidAwsRegion(credential.region);
265
- const qUrl = `https://q.${region}.amazonaws.com/generateAssistantResponse`;
266
- const cwUrl = `https://codewhisperer.${region}.amazonaws.com/generateAssistantResponse`;
267
- const rtUrl = `https://runtime.${region}.kiro.dev/generateAssistantResponse`;
268
- if (credential.authMethod === "api_key") {
269
- return [qUrl, cwUrl, rtUrl];
449
+ async function refreshStoredKiroKey(auth) {
450
+ const oldKey = auth.apiKey ?? "";
451
+ const refreshedKey = await maybeRefreshKiroCredential(oldKey, auth.refreshToken);
452
+ if (!refreshedKey || refreshedKey === oldKey)
453
+ return undefined;
454
+ await replaceProviderKey("kiro", oldKey, refreshedKey).catch(() => { });
455
+ auth.apiKey = refreshedKey;
456
+ return resolveKiroCredential({ ...auth, apiKey: refreshedKey });
457
+ }
458
+ function getCandidateEndpoints(credential, generation) {
459
+ const region = resolveKiroRuntimeRegion(credential);
460
+ const apiRegion = region;
461
+ const modern = { url: `https://runtime.${apiRegion}.kiro.dev/`, awsTarget: true };
462
+ const q = {
463
+ url: `https://q.${region}.amazonaws.com/generateAssistantResponse`,
464
+ awsTarget: false,
465
+ };
466
+ const codewhisperer = {
467
+ url: `https://codewhisperer.${region}.amazonaws.com/generateAssistantResponse`,
468
+ awsTarget: true,
469
+ };
470
+ if (generation === "modern") {
471
+ return credential.authMethod === "api_key"
472
+ ? [modern, q, codewhisperer]
473
+ : [modern, codewhisperer, q];
270
474
  }
271
- return [cwUrl, rtUrl, qUrl];
475
+ return credential.authMethod === "api_key"
476
+ ? [q, modern, codewhisperer]
477
+ : [codewhisperer, modern, q];
272
478
  }
273
479
  function uuidFromHex(hex) {
274
480
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
@@ -290,12 +496,12 @@ function sanitizeToolName(name) {
290
496
  function formatKiroTools(tools) {
291
497
  if (!tools || tools.length === 0)
292
498
  return [];
293
- return tools.map((t) => ({
499
+ return tools.map((tool) => ({
294
500
  toolSpecification: {
295
- name: sanitizeToolName(t.wireName || t.name),
296
- description: (t.description || "").slice(0, 10237),
501
+ name: sanitizeToolName(tool.wireName || tool.name),
502
+ description: (tool.description || `Tool: ${tool.name}`).slice(0, 10237),
297
503
  inputSchema: {
298
- json: t.parameters,
504
+ json: tool.parameters,
299
505
  },
300
506
  },
301
507
  }));
@@ -312,21 +518,34 @@ function imageFormatFromMediaType(mediaType) {
312
518
  return "webp";
313
519
  return "png";
314
520
  }
315
- function buildKiroRequestBody(request, credential, upstreamModel, agentic, thinking) {
521
+ export function buildKiroRequestBody(request, credential, upstreamModel, agentic, thinking) {
316
522
  const agenticInstruction = agentic
317
523
  ? "When modifying or creating files, keep writes concise:\n- Maximum 350 lines per file write/tool call (recommended 300 lines or fewer).\n- Prefer targeted, incremental edits instead of rewriting entire files.\n- For large files, write or append in chunks across multiple tool calls."
318
524
  : "";
319
525
  const systemParts = [];
320
526
  if (agenticInstruction)
321
527
  systemParts.push(agenticInstruction);
528
+ let sawLeadingSystem = false;
322
529
  const nonSystemMessages = [];
323
530
  for (const msg of request.messages) {
324
- if (msg.role === "system") {
531
+ if (msg.role !== "system") {
532
+ nonSystemMessages.push(msg);
533
+ continue;
534
+ }
535
+ if (!sawLeadingSystem) {
536
+ sawLeadingSystem = true;
325
537
  if (msg.content.trim())
326
538
  systemParts.push(msg.content.trim());
539
+ continue;
327
540
  }
328
- else {
329
- nonSystemMessages.push(msg);
541
+ if (msg.content.trim()) {
542
+ nonSystemMessages.push({
543
+ ...msg,
544
+ role: "user",
545
+ content: msg.content.startsWith("[SYSTEM]")
546
+ ? msg.content
547
+ : `[SYSTEM]\n${msg.content}`,
548
+ });
330
549
  }
331
550
  }
332
551
  const systemPrompt = systemParts.join("\n\n").trim();
@@ -357,6 +576,40 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
357
576
  }
358
577
  }
359
578
  else if (msg.role === "assistant") {
579
+ const replayTarget = createReasoningArtifactReplayTarget({
580
+ provider: "kiro",
581
+ model: upstreamModel,
582
+ dialect: "kiro-eventstream",
583
+ });
584
+ const replayedReasoning = request.forceReasoningReplay === false
585
+ ? []
586
+ : selectReasoningArtifactsForReplay({
587
+ artifacts: reasoningArtifactsForMessage(msg),
588
+ target: replayTarget,
589
+ context: {
590
+ hasToolCalls: Boolean(msg.toolCalls?.length),
591
+ forceScope: request.forceReasoningReplay === true,
592
+ },
593
+ observe: request.onReasoningArtifactReplayDecision,
594
+ });
595
+ const signedReasoning = replayedReasoning.find((artifact) => reasoningArtifactText(artifact) && reasoningArtifactSignature(artifact));
596
+ const redactedReasoning = replayedReasoning.find((artifact) => {
597
+ const raw = asKiroRecord(artifact.raw);
598
+ return artifact.kind === "encrypted" && typeof raw?.redactedContent === "string";
599
+ });
600
+ const redactedRaw = redactedReasoning
601
+ ? asKiroRecord(redactedReasoning.raw)
602
+ : undefined;
603
+ const reasoningContent = signedReasoning
604
+ ? {
605
+ reasoningText: {
606
+ text: reasoningArtifactText(signedReasoning),
607
+ signature: reasoningArtifactSignature(signedReasoning),
608
+ },
609
+ }
610
+ : typeof redactedRaw?.redactedContent === "string"
611
+ ? { redactedContent: redactedRaw.redactedContent }
612
+ : undefined;
360
613
  const toolUses = (msg.toolCalls ?? [])
361
614
  .filter((tc) => tc.id)
362
615
  .map((tc) => ({
@@ -371,6 +624,9 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
371
624
  ? `${last.content}\n\n${msg.content}`
372
625
  : msg.content;
373
626
  }
627
+ if (reasoningContent && !last.reasoningContent) {
628
+ last.reasoningContent = reasoningContent;
629
+ }
374
630
  if (toolUses.length > 0) {
375
631
  last.toolUses = [...(last.toolUses ?? []), ...toolUses];
376
632
  }
@@ -379,6 +635,7 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
379
635
  turns.push({
380
636
  role: "assistant",
381
637
  content: msg.content || "",
638
+ reasoningContent,
382
639
  toolUses: toolUses.length > 0 ? toolUses : undefined,
383
640
  });
384
641
  }
@@ -421,7 +678,24 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
421
678
  : "continue";
422
679
  }
423
680
  }
681
+ const modelInfo = kiroModelCatalog().find((info) => info.modelId === upstreamModel);
424
682
  const kiroTools = formatKiroTools(request.tools);
683
+ const wantsThinking = (request.thinking?.enabled ?? thinking) &&
684
+ request.thinking?.effort !== "none";
685
+ const additionalFields = kiroAdditionalModelFields(request, modelInfo, wantsThinking);
686
+ const thinkingDirective = !additionalFields &&
687
+ wantsThinking &&
688
+ isLegacyThinkingDirectiveModel(upstreamModel) &&
689
+ !modelInfo?.additionalModelRequestFieldsSchema
690
+ ? legacyThinkingDirective(request.thinking?.effort)
691
+ : "";
692
+ if (thinkingDirective) {
693
+ for (const turn of turns) {
694
+ if (turn.role === "user") {
695
+ turn.content = `${thinkingDirective}\n\n${turn.content}`;
696
+ }
697
+ }
698
+ }
425
699
  const history = [];
426
700
  for (let i = 0; i < turns.length - 1; i++) {
427
701
  const turn = turns[i];
@@ -446,6 +720,9 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
446
720
  history.push({
447
721
  assistantResponseMessage: {
448
722
  content: turn.content,
723
+ ...(turn.reasoningContent
724
+ ? { reasoningContent: turn.reasoningContent }
725
+ : {}),
449
726
  ...(turn.toolUses && turn.toolUses.length > 0
450
727
  ? { toolUses: turn.toolUses }
451
728
  : {}),
@@ -485,28 +762,68 @@ function buildKiroRequestBody(request, credential, upstreamModel, agentic, think
485
762
  if (credential.profileArn) {
486
763
  payload.profileArn = credential.profileArn;
487
764
  }
488
- const wantsThinking = thinking || request.thinking?.enabled === true;
489
- const effort = kiroEffortString(request.thinking?.effort) || "high";
490
- if (wantsThinking && isAdaptiveThinkingModel(upstreamModel)) {
491
- const budget = KIRO_THINKING_BUDGET[effort] ?? 16000;
492
- const directive = `<thinking_mode>enabled</thinking_mode><max_thinking_length>${budget}</max_thinking_length>`;
493
- const uim = payload.conversationState
494
- .currentMessage;
495
- const msg = uim.userInputMessage;
496
- msg.content = `${directive}\n\n${String(msg.content ?? "")}`;
765
+ if (additionalFields) {
766
+ payload.additionalModelRequestFields = additionalFields;
497
767
  }
498
768
  return payload;
499
769
  }
500
770
  let cachedKiroModels = null;
501
771
  let cachedKiroModelInfo = [];
772
+ let cachedKiroApiGeneration;
773
+ let cachedKiroCredentialId = "";
502
774
  let lastKiroModelFetch = 0;
503
775
  const MODEL_CACHE_TTL_MS = 30 * 60 * 1000;
776
+ function kiroCredentialId(credential) {
777
+ return createHash("sha256")
778
+ .update(credential.apiKey || credential.accessToken || credential.refreshToken || "")
779
+ .digest("hex");
780
+ }
781
+ function hasFreshKiroCatalog(credentialId) {
782
+ return (cachedKiroCredentialId === credentialId &&
783
+ cachedKiroModels !== null &&
784
+ Date.now() - lastKiroModelFetch < MODEL_CACHE_TTL_MS);
785
+ }
786
+ function kiroCatalogLimits(modelId, info) {
787
+ if (info.maxInputTokens === undefined && info.maxOutputTokens === undefined)
788
+ return [];
789
+ return [{
790
+ id: modelId,
791
+ ...(info.maxInputTokens !== undefined ? { contextTokens: info.maxInputTokens } : {}),
792
+ ...(info.maxOutputTokens !== undefined ? { maxOutputTokens: info.maxOutputTokens } : {}),
793
+ ...(info.supportsImages !== undefined ? { vision: info.supportsImages } : {}),
794
+ }];
795
+ }
796
+ async function ensureKiroModelCatalog(credential) {
797
+ const credentialId = kiroCredentialId(credential);
798
+ if (hasFreshKiroCatalog(credentialId))
799
+ return;
800
+ const catalog = await discoverKiroModelsDetailed(credential);
801
+ cachedKiroCredentialId = credentialId;
802
+ cachedKiroModelInfo = catalog.models;
803
+ cachedKiroApiGeneration = catalog.generation;
804
+ cachedKiroModels = withKiroVariants(catalog.models.map((info) => info.modelId));
805
+ lastKiroModelFetch = Date.now();
806
+ const limits = [];
807
+ for (const info of catalog.models) {
808
+ if (info.supportsImages !== undefined) {
809
+ learnModelVisionCapability("kiro", info.modelId, info.supportsImages);
810
+ }
811
+ const efforts = kiroCatalogEfforts(info.additionalModelRequestFieldsSchema);
812
+ for (const variant of withKiroVariants([info.modelId])) {
813
+ registerModelReasoningEfforts("kiro", variant, efforts);
814
+ limits.push(...kiroCatalogLimits(variant, info));
815
+ }
816
+ }
817
+ registerModelCatalogLimits("kiro", limits);
818
+ }
504
819
  export function kiroModelCatalog() {
505
820
  return cachedKiroModelInfo;
506
821
  }
507
822
  export function resetKiroModelCacheForTesting() {
508
823
  cachedKiroModels = null;
509
824
  cachedKiroModelInfo = [];
825
+ cachedKiroApiGeneration = undefined;
826
+ cachedKiroCredentialId = "";
510
827
  lastKiroModelFetch = 0;
511
828
  }
512
829
  export async function fetchKiroUsageLimits(auth, onStatus) {
@@ -541,56 +858,35 @@ export const kiroProvider = {
541
858
  return trimmed.length >= 8;
542
859
  },
543
860
  async listModels(auth) {
544
- const now = Date.now();
545
- if (cachedKiroModels && now - lastKiroModelFetch < MODEL_CACHE_TTL_MS) {
861
+ const credential = resolveKiroCredential(auth);
862
+ const credentialId = kiroCredentialId(credential);
863
+ const cacheIsFresh = cachedKiroCredentialId === credentialId &&
864
+ cachedKiroModels !== null &&
865
+ Date.now() - lastKiroModelFetch < MODEL_CACHE_TTL_MS;
866
+ if (cacheIsFresh)
546
867
  return cachedKiroModels;
547
- }
548
868
  try {
549
- const credential = resolveKiroCredential(auth);
550
- const infos = await listKiroModelsDetailed(credential);
551
- if (infos.length > 0) {
552
- cachedKiroModelInfo = infos;
553
- for (const info of infos) {
554
- if (info.supportsImages !== undefined) {
555
- learnModelVisionCapability("kiro", info.modelId, info.supportsImages);
556
- }
557
- }
558
- const variants = withKiroVariants(infos.map((info) => info.modelId));
559
- cachedKiroModels = variants;
560
- lastKiroModelFetch = now;
561
- return variants;
869
+ const refreshedId = await withKiroCredential(auth, async (current) => {
870
+ await ensureKiroModelCatalog(current);
871
+ return kiroCredentialId(current);
872
+ });
873
+ if ((cachedKiroCredentialId === credentialId ||
874
+ cachedKiroCredentialId === refreshedId) &&
875
+ cachedKiroModels) {
876
+ return cachedKiroModels;
562
877
  }
563
878
  }
564
879
  catch { }
565
- return cachedKiroModels ?? [...kiroFallbackModels];
880
+ return [...kiroFallbackModels];
566
881
  },
567
882
  async ping(auth) {
568
883
  const credential = resolveKiroCredential(auth);
569
- const region = assertValidAwsRegion(credential.region);
570
- const params = new URLSearchParams({ origin: "AI_EDITOR" });
571
- const endpoint = `https://q.${region}.amazonaws.com/ListAvailableModels?${params.toString()}`;
572
- const headers = {
573
- Accept: "application/json",
574
- "User-Agent": "AWS-SDK-JS/3.0.0 kiro-ide/1.0.0",
575
- "X-Amz-User-Agent": "aws-sdk-js/3.0.0 kiro-ide/1.0.0",
576
- };
577
- if (credential.authMethod === "api_key" && credential.apiKey) {
578
- headers["Authorization"] = `Bearer ${credential.apiKey}`;
579
- headers["TokenType"] = "API_KEY";
580
- }
581
- else if (credential.accessToken) {
582
- headers["Authorization"] = `Bearer ${credential.accessToken}`;
583
- if (credential.authMethod === "external_idp") {
584
- headers["TokenType"] = "EXTERNAL_IDP";
585
- }
884
+ try {
885
+ await discoverKiroModelsDetailed(credential);
586
886
  }
587
- const response = await fetch(endpoint, {
588
- method: "GET",
589
- headers,
590
- signal: AbortSignal.timeout(15_000),
591
- });
592
- if (!response.ok) {
593
- throw new ProviderError(`Kiro AI ping failed (HTTP ${response.status}). Run \`clai auth kiro\` to sign in.`, response.status);
887
+ catch (error) {
888
+ const detail = error instanceof Error ? `: ${error.message}` : "";
889
+ throw new ProviderError(`Kiro AI ping failed${detail}. Run \`clai auth kiro\` to sign in.`);
594
890
  }
595
891
  },
596
892
  async complete(request, auth, onStatus) {
@@ -600,13 +896,17 @@ export const kiroProvider = {
600
896
  const requestedModel = request.model ?? defaultModels.kiro;
601
897
  const { upstream, agentic, thinking } = resolveKiroModel(requestedModel);
602
898
  return withKiroCredential(auth, async (credential) => {
899
+ await ensureKiroModelCatalog(credential).catch(() => { });
603
900
  const body = buildKiroRequestBody(request, credential, upstream, agentic, thinking);
604
- const endpoints = getCandidateEndpoints(credential);
901
+ const catalogIsFresh = hasFreshKiroCatalog(kiroCredentialId(credential));
902
+ const endpoints = getCandidateEndpoints(credential, catalogIsFresh ? cachedKiroApiGeneration : undefined);
605
903
  let lastError;
606
904
  for (const endpoint of endpoints) {
607
905
  try {
608
906
  const headers = {
609
- "Content-Type": "application/json",
907
+ "Content-Type": endpoint.awsTarget
908
+ ? "application/x-amz-json-1.0"
909
+ : "application/json",
610
910
  Accept: "application/vnd.amazon.eventstream",
611
911
  "Amz-Sdk-Request": "attempt=1; max=3",
612
912
  "Amz-Sdk-Invocation-Id": randomUUID(),
@@ -616,7 +916,7 @@ export const kiroProvider = {
616
916
  "x-amzn-codewhisperer-optout": "true",
617
917
  "x-amzn-codewhisperer-machine-id": "kiro-desktop",
618
918
  };
619
- if (endpoint.includes("codewhisperer")) {
919
+ if (endpoint.awsTarget) {
620
920
  headers["X-Amz-Target"] =
621
921
  "AmazonCodeWhispererStreamingService.GenerateAssistantResponse";
622
922
  }
@@ -634,7 +934,7 @@ export const kiroProvider = {
634
934
  headers["x-amzn-codewhisperer-profile-arn"] = credential.profileArn;
635
935
  }
636
936
  }
637
- const response = await generationFetch(endpoint, {
937
+ const response = await generationFetch(endpoint.url, {
638
938
  method: "POST",
639
939
  headers,
640
940
  body: JSON.stringify(body),
@@ -643,7 +943,12 @@ export const kiroProvider = {
643
943
  if (!response.ok) {
644
944
  const errorText = await response.text().catch(() => "");
645
945
  if (response.status === 401 || response.status === 403) {
646
- throw new ProviderError(`Kiro authentication failed (${response.status}): ${errorText}`, response.status);
946
+ const authError = new ProviderError(`Kiro authentication failed (${response.status}): ${errorText}`, response.status);
947
+ if (response.status === 401 && credential.refreshToken) {
948
+ throw authError;
949
+ }
950
+ lastError = authError;
951
+ continue;
647
952
  }
648
953
  if (response.status === 400) {
649
954
  throw new ProviderError(`Kiro request invalid (${response.status}): ${errorText}`, response.status, errorText);
@@ -655,9 +960,11 @@ export const kiroProvider = {
655
960
  throw new ProviderError("Empty response body from Kiro endpoint", 500);
656
961
  }
657
962
  let fullText = "";
658
- let reasoningText = "";
963
+ const pendingStreamEvents = [];
964
+ const reasoning = createKiroReasoningAccumulator((text) => pendingStreamEvents.push({ kind: "reasoning", text }));
659
965
  let insideThinkingTag = false;
660
966
  let finishReason = "stop";
967
+ let stopReason = "";
661
968
  const accumulatedTools = [];
662
969
  let currentToolIndex = -1;
663
970
  let promptTokens = 0;
@@ -667,13 +974,35 @@ export const kiroProvider = {
667
974
  const usageCharges = [];
668
975
  let contextUsagePercentage;
669
976
  for await (const frame of parseEventStream(response.body)) {
977
+ const messageType = typeof frame.headers[":message-type"] === "string"
978
+ ? frame.headers[":message-type"]
979
+ : "event";
980
+ const headerExceptionType = typeof frame.headers[":exception-type"] === "string"
981
+ ? frame.headers[":exception-type"]
982
+ : "";
670
983
  const eventType = (typeof frame.headers[":event-type"] === "string"
671
984
  ? frame.headers[":event-type"]
672
985
  : undefined) ||
673
- Object.keys(frame.payload).find((k) => k.endsWith("Event")) ||
986
+ headerExceptionType ||
987
+ Object.keys(frame.payload).find((key) => key.endsWith("Event") || key.endsWith("Exception")) ||
674
988
  "";
675
- const eventPayload = frame.payload[eventType] ||
676
- frame.payload;
989
+ const nestedPayload = asKiroRecord(frame.payload[eventType]);
990
+ const eventPayload = nestedPayload ?? frame.payload;
991
+ if (messageType === "exception" || headerExceptionType || eventType.endsWith("Exception")) {
992
+ const message = typeof eventPayload.message === "string"
993
+ ? eventPayload.message
994
+ : typeof eventPayload.reason === "string"
995
+ ? eventPayload.reason
996
+ : "Kiro stream exception";
997
+ throw new ProviderError(`${headerExceptionType || eventType || "Kiro stream exception"}: ${message}`, inBandBadRequestStatus({
998
+ type: headerExceptionType || eventType,
999
+ code: eventPayload.code,
1000
+ message,
1001
+ }) ??
1002
+ (/THINKING_SIGNATURE_INVALID|THINKING_SIGNATURE_MISMATCH/i.test(`${headerExceptionType} ${eventType} ${message}`)
1003
+ ? 400
1004
+ : 502), JSON.stringify(eventPayload));
1005
+ }
677
1006
  if (typeof eventPayload.usage === "number" &&
678
1007
  Number.isFinite(eventPayload.usage) &&
679
1008
  eventPayload.usage >= 0 &&
@@ -728,25 +1057,41 @@ export const kiroProvider = {
728
1057
  }
729
1058
  }
730
1059
  }
731
- if (reasoningChunk) {
732
- reasoningText += reasoningChunk;
733
- emitStreamReasoningDelta(request.onStreamEvent, reasoningChunk);
734
- }
1060
+ reasoning.push(reasoningChunk);
735
1061
  if (visibleChunk) {
736
1062
  fullText += visibleChunk;
737
- onToken(visibleChunk);
1063
+ pendingStreamEvents.push({ kind: "token", text: visibleChunk });
738
1064
  }
739
1065
  }
740
1066
  }
741
1067
  else if (eventType === "reasoningContentEvent" ||
742
- eventType.includes("Reasoning")) {
743
- const chunk = typeof eventPayload.content === "string"
744
- ? eventPayload.content
745
- : "";
746
- if (chunk) {
747
- reasoningText += chunk;
748
- emitStreamReasoningDelta(request.onStreamEvent, chunk);
749
- }
1068
+ /reasoning/i.test(eventType) ||
1069
+ eventPayload.reasoningText !== undefined) {
1070
+ const reasoningPayload = asKiroRecord(eventPayload.reasoningText);
1071
+ const chunk = typeof eventPayload.text === "string"
1072
+ ? eventPayload.text
1073
+ : typeof eventPayload.content === "string"
1074
+ ? eventPayload.content
1075
+ : typeof eventPayload.reasoningText === "string"
1076
+ ? eventPayload.reasoningText
1077
+ : typeof reasoningPayload?.text === "string"
1078
+ ? reasoningPayload.text
1079
+ : typeof reasoningPayload?.Text === "string"
1080
+ ? reasoningPayload.Text
1081
+ : "";
1082
+ reasoning.sign(typeof eventPayload.signature === "string"
1083
+ ? eventPayload.signature
1084
+ : typeof eventPayload.Signature === "string"
1085
+ ? eventPayload.Signature
1086
+ : typeof reasoningPayload?.signature === "string"
1087
+ ? reasoningPayload.signature
1088
+ : typeof reasoningPayload?.Signature === "string"
1089
+ ? reasoningPayload.Signature
1090
+ : "");
1091
+ reasoning.redact(typeof eventPayload.redactedContent === "string"
1092
+ ? eventPayload.redactedContent
1093
+ : "");
1094
+ reasoning.push(chunk);
750
1095
  }
751
1096
  else if (eventType === "codeEvent") {
752
1097
  const chunk = typeof eventPayload.content === "string"
@@ -754,54 +1099,67 @@ export const kiroProvider = {
754
1099
  : "";
755
1100
  if (chunk) {
756
1101
  fullText += chunk;
757
- onToken(chunk);
1102
+ pendingStreamEvents.push({ kind: "token", text: chunk });
758
1103
  }
759
1104
  }
760
1105
  else if (eventType === "toolUseEvent") {
761
- const toolId = typeof eventPayload.toolUseId === "string"
1106
+ const explicitToolId = typeof eventPayload.toolUseId === "string"
762
1107
  ? eventPayload.toolUseId
763
- : `tool_${accumulatedTools.length + 1}`;
1108
+ : typeof eventPayload.tool_use_id === "string"
1109
+ ? eventPayload.tool_use_id
1110
+ : undefined;
764
1111
  const name = typeof eventPayload.name === "string" ? eventPayload.name : "";
765
1112
  const input = eventPayload.input;
766
- let existing = accumulatedTools.find((t) => t.id === toolId);
767
- if (!existing) {
768
- existing = { id: toolId, name, rawArgs: "" };
1113
+ const stopped = eventPayload.stop === true;
1114
+ let existing = explicitToolId
1115
+ ? accumulatedTools.find((tool) => tool.id === explicitToolId)
1116
+ : accumulatedTools[currentToolIndex];
1117
+ if (explicitToolId &&
1118
+ !existing &&
1119
+ currentToolIndex >= 0 &&
1120
+ accumulatedTools[currentToolIndex]?.syntheticId) {
1121
+ const activeTool = accumulatedTools[currentToolIndex];
1122
+ activeTool.id = explicitToolId;
1123
+ activeTool.syntheticId = false;
1124
+ existing = activeTool;
1125
+ }
1126
+ if (!existing && (explicitToolId || name || input !== undefined)) {
1127
+ existing = {
1128
+ id: explicitToolId ?? `tool_${accumulatedTools.length + 1}`,
1129
+ name,
1130
+ rawArgs: "",
1131
+ syntheticId: explicitToolId === undefined,
1132
+ };
769
1133
  accumulatedTools.push(existing);
770
- currentToolIndex = accumulatedTools.length - 1;
771
1134
  }
772
- let chunkBytes = 0;
1135
+ if (!existing) {
1136
+ if (stopped)
1137
+ currentToolIndex = -1;
1138
+ continue;
1139
+ }
773
1140
  if (typeof input === "string") {
774
1141
  existing.rawArgs += input;
775
- chunkBytes = Buffer.byteLength(input, "utf8");
776
1142
  }
777
1143
  else if (input && typeof input === "object") {
778
1144
  existing.rawArgs = JSON.stringify(input);
779
- chunkBytes = Buffer.byteLength(existing.rawArgs, "utf8");
780
1145
  }
781
- if (name && !existing.name) {
1146
+ if (name && !existing.name)
782
1147
  existing.name = name;
783
- }
1148
+ currentToolIndex = accumulatedTools.indexOf(existing);
1149
+ const argumentsBytes = Buffer.byteLength(existing.rawArgs, "utf8");
784
1150
  const delta = {
785
1151
  index: currentToolIndex,
786
1152
  id: existing.id,
787
1153
  name: existing.name,
788
- argumentsBytes: chunkBytes,
1154
+ argumentsBytes,
789
1155
  };
790
- request.onToolCallDelta?.(delta);
1156
+ pendingStreamEvents.push({ kind: "tool", delta });
791
1157
  finishReason = "tool_calls";
1158
+ if (stopped)
1159
+ currentToolIndex = -1;
792
1160
  }
793
1161
  else if (eventType === "messageStopEvent") {
794
- const stop = typeof eventPayload.stopReason === "string"
795
- ? eventPayload.stopReason
796
- : "";
797
- if (stop) {
798
- finishReason =
799
- stop === "tool_use" || stop === "tool_calls"
800
- ? "tool_calls"
801
- : stop === "max_tokens" || stop === "length"
802
- ? "length"
803
- : "stop";
804
- }
1162
+ stopReason = mergeKiroStopReason(stopReason, normalizeKiroStopReason(eventPayload.stopReason ?? eventPayload.stop_reason));
805
1163
  }
806
1164
  else if (eventType === "contextUsageEvent") {
807
1165
  if (typeof eventPayload.contextUsagePercentage === "number") {
@@ -809,21 +1167,56 @@ export const kiroProvider = {
809
1167
  }
810
1168
  }
811
1169
  else if (eventType === "metricsEvent" ||
812
- eventType === "meteringEvent") {
813
- if (typeof eventPayload.inputTokens === "number") {
814
- promptTokens = eventPayload.inputTokens;
815
- }
816
- if (typeof eventPayload.outputTokens === "number") {
817
- completionTokens = eventPayload.outputTokens;
1170
+ eventType === "meteringEvent" ||
1171
+ eventType === "metadataEvent" ||
1172
+ eventType === "MetadataEvent") {
1173
+ const usagePayload = asKiroRecord(eventPayload.usage);
1174
+ const tokenUsagePayload = asKiroRecord(eventPayload.tokenUsage);
1175
+ const usageSources = [
1176
+ eventPayload,
1177
+ ...(usagePayload ? [usagePayload] : []),
1178
+ ...(tokenUsagePayload ? [tokenUsagePayload] : []),
1179
+ ];
1180
+ const inputTokens = firstKiroMetric(usageSources, [
1181
+ "inputTokens",
1182
+ "input_tokens",
1183
+ "promptTokens",
1184
+ "prompt_tokens",
1185
+ ]);
1186
+ const outputTokens = firstKiroMetric(usageSources, [
1187
+ "outputTokens",
1188
+ "output_tokens",
1189
+ "completionTokens",
1190
+ "completion_tokens",
1191
+ ]);
1192
+ const cacheReadTokens = firstKiroMetric(usageSources, [
1193
+ "cacheReadTokens",
1194
+ "cache_read_tokens",
1195
+ "cacheReadInputTokens",
1196
+ "cache_read_input_tokens",
1197
+ "cachedTokens",
1198
+ ]);
1199
+ const cacheWriteTokens = firstKiroMetric(usageSources, [
1200
+ "cacheCreationTokens",
1201
+ "cache_creation_tokens",
1202
+ "cacheWriteTokens",
1203
+ "cache_write_tokens",
1204
+ "cacheWriteInputTokens",
1205
+ "cacheCreationInputTokens",
1206
+ "cache_creation_input_tokens",
1207
+ ]);
1208
+ if (inputTokens !== undefined)
1209
+ promptTokens = inputTokens;
1210
+ if (outputTokens !== undefined)
1211
+ completionTokens = outputTokens;
1212
+ if (cacheReadTokens !== undefined) {
1213
+ cachedTokens = Math.max(cachedTokens, cacheReadTokens);
818
1214
  }
819
- if (typeof eventPayload.cachedTokens === "number") {
820
- cachedTokens = eventPayload.cachedTokens;
1215
+ if (cacheWriteTokens !== undefined) {
1216
+ cacheCreationTokens = Math.max(cacheCreationTokens, cacheWriteTokens);
821
1217
  }
822
- if (typeof eventPayload.cacheReadInputTokens === "number") {
823
- cachedTokens = Math.max(cachedTokens, eventPayload.cacheReadInputTokens);
824
- }
825
- if (typeof eventPayload.cacheWriteInputTokens === "number") {
826
- cacheCreationTokens = eventPayload.cacheWriteInputTokens;
1218
+ if (/^metadataevent$/i.test(eventType)) {
1219
+ stopReason = mergeKiroStopReason(stopReason, normalizeKiroStopReason(eventPayload.stopReason ?? eventPayload.stop_reason));
827
1220
  }
828
1221
  }
829
1222
  }
@@ -842,11 +1235,49 @@ export const kiroProvider = {
842
1235
  rawArguments: t.rawArgs,
843
1236
  };
844
1237
  });
845
- if (toolCalls.length > 0) {
1238
+ reasoning.finish();
1239
+ const hasReasoningEvidence = Boolean(reasoning.text.trim() || reasoning.signature || reasoning.redactedContent);
1240
+ const stopDisposition = kiroStopDisposition(stopReason, toolCalls.length > 0);
1241
+ if (stopDisposition === "blocked") {
1242
+ throw new ProviderError(`Kiro blocked the response under its content safety policy (${stopReason})`, 400);
1243
+ }
1244
+ if (stopDisposition === "retryable" ||
1245
+ stopDisposition === "incomplete" ||
1246
+ stopDisposition === "unknown") {
1247
+ throw new ProviderError(`Kiro ended with non-success stop reason: ${stopReason}`, 502);
1248
+ }
1249
+ if (!fullText.trim() &&
1250
+ !hasReasoningEvidence &&
1251
+ toolCalls.length === 0) {
1252
+ throw new ProviderError("Kiro completed without a visible answer.");
1253
+ }
1254
+ if (toolCalls.length === 0 && ["...", "…"].includes(fullText.trim())) {
1255
+ throw new ProviderError("Kiro completed without a visible answer.");
1256
+ }
1257
+ if (reasoning.opaque && (fullText.trim() || toolCalls.length > 0)) {
1258
+ pendingStreamEvents.push({
1259
+ kind: "reasoning",
1260
+ text: kiroPrivateReasoningNote({
1261
+ model: upstream,
1262
+ effort: sentKiroReasoningEffort(asKiroRecord(body.additionalModelRequestFields)),
1263
+ signatureChars: reasoning.signature.length,
1264
+ }),
1265
+ });
1266
+ }
1267
+ if (stopDisposition === "length") {
1268
+ finishReason = "length";
1269
+ }
1270
+ else if (toolCalls.length > 0) {
846
1271
  finishReason = "tool_calls";
847
1272
  }
848
- const catalogWindow = kiroModelCatalog().find((info) => info.modelId === upstream)
849
- ?.maxInputTokens ?? 200_000;
1273
+ const advertisedWindow = kiroModelCatalog().find((info) => info.modelId === upstream)
1274
+ ?.maxInputTokens;
1275
+ const catalogWindow = advertisedWindow !== undefined &&
1276
+ Number.isFinite(advertisedWindow) &&
1277
+ advertisedWindow > 0
1278
+ ? Math.floor(advertisedWindow)
1279
+ : undefined;
1280
+ const estimatedPromptTokens = providerRatioPromptTokens(contextUsagePercentage, catalogWindow ?? modelContextWindow(upstream, "kiro"));
850
1281
  const tokenUsage = promptTokens > 0 || completionTokens > 0
851
1282
  ? {
852
1283
  promptTokens,
@@ -859,14 +1290,19 @@ export const kiroProvider = {
859
1290
  ? Math.max(0, promptTokens - cachedTokens)
860
1291
  : promptTokens,
861
1292
  }
862
- : contextUsagePercentage !== undefined
863
- ? {
864
- promptTokens: Math.round((contextUsagePercentage / 100) * catalogWindow),
865
- completionTokens: 0,
866
- totalTokens: Math.round((contextUsagePercentage / 100) * catalogWindow),
867
- exact: false,
868
- }
869
- : undefined;
1293
+ : catalogWindow !== undefined
1294
+ ? providerRatioUsage({
1295
+ percentUsed: contextUsagePercentage,
1296
+ windowTokens: catalogWindow,
1297
+ })
1298
+ : estimatedPromptTokens !== undefined
1299
+ ? {
1300
+ promptTokens: estimatedPromptTokens,
1301
+ completionTokens: 0,
1302
+ totalTokens: estimatedPromptTokens,
1303
+ exact: false,
1304
+ }
1305
+ : undefined;
870
1306
  const usage = tokenUsage
871
1307
  ? {
872
1308
  ...tokenUsage,
@@ -882,6 +1318,26 @@ export const kiroProvider = {
882
1318
  charges: usageCharges,
883
1319
  }
884
1320
  : undefined;
1321
+ const reasoningResult = kiroReasoningResult({
1322
+ reasoning,
1323
+ provenance: createReasoningArtifactProvenance({
1324
+ provider: "kiro",
1325
+ model: upstream,
1326
+ dialect: "kiro-eventstream",
1327
+ }),
1328
+ hasToolCalls: toolCalls.length > 0,
1329
+ });
1330
+ for (const event of pendingStreamEvents) {
1331
+ if (event.kind === "token") {
1332
+ onToken(event.text);
1333
+ }
1334
+ else if (event.kind === "reasoning") {
1335
+ emitStreamReasoningDelta(request.onStreamEvent, event.text);
1336
+ }
1337
+ else {
1338
+ request.onToolCallDelta?.(event.delta);
1339
+ }
1340
+ }
885
1341
  return {
886
1342
  text: fullText,
887
1343
  provider: "kiro",
@@ -890,13 +1346,23 @@ export const kiroProvider = {
890
1346
  finishReason,
891
1347
  toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
892
1348
  usage,
893
- reasoningBlock: reasoningText.trim()
894
- ? { text: reasoningText.trim() }
1349
+ reasoningArtifacts: reasoningResult.artifacts.length > 0
1350
+ ? reasoningResult.artifacts
895
1351
  : undefined,
1352
+ reasoningBlock: reasoningResult.block,
896
1353
  };
897
1354
  }
898
1355
  catch (err) {
899
- if (err instanceof ProviderError && (err.status === 401 || err.status === 403 || err.status === 400)) {
1356
+ if (request.signal?.aborted) {
1357
+ completeGenerationAttempt("cancelled");
1358
+ throw err;
1359
+ }
1360
+ const status = err instanceof ProviderError ? err.status : undefined;
1361
+ completeGenerationAttempt("failure", undefined, status);
1362
+ if (err instanceof ProviderError &&
1363
+ (status === 400 ||
1364
+ status === undefined ||
1365
+ (status === 401 && Boolean(credential.refreshToken)))) {
900
1366
  throw err;
901
1367
  }
902
1368
  lastError = err instanceof Error ? err : new Error(String(err));