@pentoshi/clai 4.11.23 → 4.11.25

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 (152) hide show
  1. package/dist/agent/events.d.ts +4 -1
  2. package/dist/agent/parser/arg-formatting.js +30 -0
  3. package/dist/agent/parser/arg-formatting.js.map +1 -1
  4. package/dist/agent/runner.d.ts +1 -0
  5. package/dist/agent/runner.js +3 -0
  6. package/dist/agent/runner.js.map +1 -1
  7. package/dist/agent/stream-recovery.d.ts +1 -0
  8. package/dist/agent/stream-recovery.js +9 -0
  9. package/dist/agent/stream-recovery.js.map +1 -1
  10. package/dist/agent/turn/compaction-admission.d.ts +2 -1
  11. package/dist/agent/turn/compaction-admission.js +19 -17
  12. package/dist/agent/turn/compaction-admission.js.map +1 -1
  13. package/dist/agent/turn/compaction-coordinator.d.ts +4 -4
  14. package/dist/agent/turn/compaction-coordinator.js +16 -10
  15. package/dist/agent/turn/compaction-coordinator.js.map +1 -1
  16. package/dist/agent/turn/event-emitter.d.ts +4 -3
  17. package/dist/agent/turn/event-emitter.js +10 -9
  18. package/dist/agent/turn/event-emitter.js.map +1 -1
  19. package/dist/agent/turn/loop/request-assembly.d.ts +1 -0
  20. package/dist/agent/turn/loop/request-assembly.js +4 -2
  21. package/dist/agent/turn/loop/request-assembly.js.map +1 -1
  22. package/dist/agent/turn/loop/round-request.js +1 -0
  23. package/dist/agent/turn/loop/round-request.js.map +1 -1
  24. package/dist/agent/turn/loop/state.d.ts +1 -0
  25. package/dist/agent/turn/loop/state.js +1 -1
  26. package/dist/agent/turn/loop/state.js.map +1 -1
  27. package/dist/agent/turn/loop/stream-failure.js +4 -1
  28. package/dist/agent/turn/loop/stream-failure.js.map +1 -1
  29. package/dist/agent/turn/setup/compaction-services.d.ts +4 -3
  30. package/dist/agent/turn/setup/compaction-services.js.map +1 -1
  31. package/dist/app/adapters/agent-event-adapter.js +6 -1
  32. package/dist/app/adapters/agent-event-adapter.js.map +1 -1
  33. package/dist/app/adapters/current-agent-adapter.js +3 -0
  34. package/dist/app/adapters/current-agent-adapter.js.map +1 -1
  35. package/dist/app/commands/catalog.js +31 -0
  36. package/dist/app/commands/catalog.js.map +1 -1
  37. package/dist/app/controllers/session-compact-helper.d.ts +3 -1
  38. package/dist/app/controllers/session-compact-helper.js +17 -2
  39. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  40. package/dist/app/controllers/session-controller.d.ts +3 -1
  41. package/dist/app/controllers/session-controller.js +32 -2
  42. package/dist/app/controllers/session-controller.js.map +1 -1
  43. package/dist/app/controllers/session-turn-request.d.ts +1 -0
  44. package/dist/app/controllers/session-turn-request.js +3 -0
  45. package/dist/app/controllers/session-turn-request.js.map +1 -1
  46. package/dist/app/events/app-event.d.ts +4 -1
  47. package/dist/app/events/app-event.js.map +1 -1
  48. package/dist/app/ports/agent-port.d.ts +1 -0
  49. package/dist/app/ports/transcript-item.d.ts +1 -0
  50. package/dist/commands/providers.d.ts +14 -0
  51. package/dist/commands/providers.js +223 -0
  52. package/dist/commands/providers.js.map +1 -1
  53. package/dist/index.js +13 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/llm/capabilities.js +10 -3
  56. package/dist/llm/capabilities.js.map +1 -1
  57. package/dist/llm/capability/state.d.ts +1 -1
  58. package/dist/llm/capability/tool-dialect.js +2 -0
  59. package/dist/llm/capability/tool-dialect.js.map +1 -1
  60. package/dist/llm/capability/vision-patterns.js +5 -0
  61. package/dist/llm/capability/vision-patterns.js.map +1 -1
  62. package/dist/llm/cline-auth.d.ts +12 -1
  63. package/dist/llm/cline-auth.js +229 -88
  64. package/dist/llm/cline-auth.js.map +1 -1
  65. package/dist/llm/cline.js +146 -48
  66. package/dist/llm/cline.js.map +1 -1
  67. package/dist/llm/codex-auth.d.ts +3 -1
  68. package/dist/llm/codex-auth.js +42 -8
  69. package/dist/llm/codex-auth.js.map +1 -1
  70. package/dist/llm/codex.js +17 -14
  71. package/dist/llm/codex.js.map +1 -1
  72. package/dist/llm/context-windows.js +6 -0
  73. package/dist/llm/context-windows.js.map +1 -1
  74. package/dist/llm/free.js +30 -9
  75. package/dist/llm/free.js.map +1 -1
  76. package/dist/llm/kiro-auth.d.ts +113 -0
  77. package/dist/llm/kiro-auth.js +1017 -0
  78. package/dist/llm/kiro-auth.js.map +1 -0
  79. package/dist/llm/kiro.d.ts +10 -0
  80. package/dist/llm/kiro.js +846 -0
  81. package/dist/llm/kiro.js.map +1 -0
  82. package/dist/llm/mimo.d.ts +2 -0
  83. package/dist/llm/mimo.js +89 -0
  84. package/dist/llm/mimo.js.map +1 -0
  85. package/dist/llm/model-families.js +9 -0
  86. package/dist/llm/model-families.js.map +1 -1
  87. package/dist/llm/model-layers/model-rules.js +33 -0
  88. package/dist/llm/model-layers/model-rules.js.map +1 -1
  89. package/dist/llm/provider-identity.d.ts +1 -0
  90. package/dist/llm/provider-identity.js +15 -0
  91. package/dist/llm/provider-identity.js.map +1 -1
  92. package/dist/llm/provider-info-text.js +87 -1
  93. package/dist/llm/provider-info-text.js.map +1 -1
  94. package/dist/llm/provider-profile-layers.d.ts +1 -0
  95. package/dist/llm/provider-profile-layers.js +67 -1
  96. package/dist/llm/provider-profile-layers.js.map +1 -1
  97. package/dist/llm/provider-profiles.js +5 -1
  98. package/dist/llm/provider-profiles.js.map +1 -1
  99. package/dist/llm/reasoning-capability.js +2 -0
  100. package/dist/llm/reasoning-capability.js.map +1 -1
  101. package/dist/llm/responses-complete.js +7 -1
  102. package/dist/llm/responses-complete.js.map +1 -1
  103. package/dist/llm/responses-config.d.ts +1 -1
  104. package/dist/llm/responses-config.js.map +1 -1
  105. package/dist/llm/responses-http.d.ts +2 -2
  106. package/dist/llm/responses-http.js +2 -2
  107. package/dist/llm/responses-http.js.map +1 -1
  108. package/dist/llm/responses-stream.js +9 -3
  109. package/dist/llm/responses-stream.js.map +1 -1
  110. package/dist/llm/router.js +14 -12
  111. package/dist/llm/router.js.map +1 -1
  112. package/dist/llm/routing/provider-selection.js +6 -0
  113. package/dist/llm/routing/provider-selection.js.map +1 -1
  114. package/dist/llm/sampling.js +6 -0
  115. package/dist/llm/sampling.js.map +1 -1
  116. package/dist/llm/wire/chat-body.js +47 -12
  117. package/dist/llm/wire/chat-body.js.map +1 -1
  118. package/dist/noninteractive/stream-blocks.js +17 -5
  119. package/dist/noninteractive/stream-blocks.js.map +1 -1
  120. package/dist/store/config.js +2 -0
  121. package/dist/store/config.js.map +1 -1
  122. package/dist/tui-v2/bootstrap/start-tui-v2.js +10 -0
  123. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  124. package/dist/tui-v2/components/transcript/transcript-row.js +4 -2
  125. package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
  126. package/dist/types.d.ts +1 -1
  127. package/dist/types.js +2 -0
  128. package/dist/types.js.map +1 -1
  129. package/dist/ui-core/bootstrap/composition-root.js +1 -1
  130. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  131. package/dist/ui-core/bootstrap/session-resume.d.ts +3 -0
  132. package/dist/ui-core/bootstrap/session-resume.js +52 -0
  133. package/dist/ui-core/bootstrap/session-resume.js.map +1 -1
  134. package/dist/ui-core/commands/key-commands.d.ts +9 -0
  135. package/dist/ui-core/commands/key-commands.js +438 -16
  136. package/dist/ui-core/commands/key-commands.js.map +1 -1
  137. package/dist/ui-core/commands/picker-commands.js +18 -0
  138. package/dist/ui-core/commands/picker-commands.js.map +1 -1
  139. package/dist/ui-core/state/hydrate/classic-transcript.js +5 -0
  140. package/dist/ui-core/state/hydrate/classic-transcript.js.map +1 -1
  141. package/dist/ui-core/state/transcript/apply-app-event.js +29 -0
  142. package/dist/ui-core/state/transcript/apply-app-event.js.map +1 -1
  143. package/dist/ui-core/state/transcript-hydrate.js +165 -79
  144. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  145. package/dist/ui-core/state/transcript-store.js +7 -1
  146. package/dist/ui-core/state/transcript-store.js.map +1 -1
  147. package/dist/ui-core/state/transcript-types.d.ts +5 -2
  148. package/dist/ui-core/state/transcript-types.js +17 -3
  149. package/dist/ui-core/state/transcript-types.js.map +1 -1
  150. package/dist/version.generated.d.ts +2 -2
  151. package/dist/version.generated.js +2 -2
  152. package/package.json +1 -1
@@ -0,0 +1,846 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { defaultModels, } from "./provider.js";
3
+ import { ProviderError } from "./http.js";
4
+ import { assertValidAwsRegion, decodeKiroKey, isKiroOAuthToken, maybeRefreshKiroCredential, } from "./kiro-auth.js";
5
+ import { currentSessionAffinity } from "./session-affinity.js";
6
+ import { replaceProviderKey } from "../store/keys.js";
7
+ export const kiroFallbackModels = [
8
+ "claude-sonnet-4.5",
9
+ "claude-sonnet-4.5-thinking",
10
+ "claude-sonnet-4.5-agentic",
11
+ "claude-sonnet-4.5-thinking-agentic",
12
+ "claude-opus-5",
13
+ "claude-opus-5-thinking",
14
+ "claude-opus-5-agentic",
15
+ "claude-opus-5-thinking-agentic",
16
+ "claude-haiku-4.5",
17
+ "claude-haiku-4.5-thinking",
18
+ "claude-haiku-4.5-agentic",
19
+ "claude-haiku-4.5-thinking-agentic",
20
+ ];
21
+ const CRC32_TABLE = new Uint32Array(256);
22
+ for (let i = 0; i < 256; i++) {
23
+ let c = i;
24
+ for (let j = 0; j < 8; j++) {
25
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
26
+ }
27
+ CRC32_TABLE[i] = c >>> 0;
28
+ }
29
+ function crc32(buf, start = 0, end = buf.length) {
30
+ let crc = 0xffffffff;
31
+ for (let i = start; i < end; i++) {
32
+ crc = (crc >>> 8) ^ CRC32_TABLE[(crc ^ buf[i]) & 0xff];
33
+ }
34
+ return (crc ^ 0xffffffff) >>> 0;
35
+ }
36
+ function parseHeaders(buf) {
37
+ const headers = {};
38
+ let offset = 0;
39
+ while (offset < buf.length) {
40
+ const nameLen = buf.readUInt8(offset);
41
+ offset += 1;
42
+ const name = buf.toString("utf8", offset, offset + nameLen);
43
+ offset += nameLen;
44
+ const type = buf.readUInt8(offset);
45
+ offset += 1;
46
+ if (type === 0) {
47
+ headers[name] = true;
48
+ }
49
+ else if (type === 1) {
50
+ headers[name] = false;
51
+ }
52
+ else if (type === 2) {
53
+ headers[name] = buf.readInt8(offset);
54
+ offset += 1;
55
+ }
56
+ else if (type === 3) {
57
+ headers[name] = buf.readInt16BE(offset);
58
+ offset += 2;
59
+ }
60
+ else if (type === 4) {
61
+ headers[name] = buf.readInt32BE(offset);
62
+ offset += 4;
63
+ }
64
+ else if (type === 5) {
65
+ headers[name] = buf.readBigInt64BE(offset);
66
+ offset += 8;
67
+ }
68
+ else if (type === 6) {
69
+ const len = buf.readUInt16BE(offset);
70
+ offset += 2;
71
+ headers[name] = buf.subarray(offset, offset + len);
72
+ offset += len;
73
+ }
74
+ else if (type === 7) {
75
+ const len = buf.readUInt16BE(offset);
76
+ offset += 2;
77
+ headers[name] = buf.toString("utf8", offset, offset + len);
78
+ offset += len;
79
+ }
80
+ else if (type === 8) {
81
+ headers[name] = new Date(Number(buf.readBigInt64BE(offset)));
82
+ offset += 8;
83
+ }
84
+ else if (type === 9) {
85
+ headers[name] = buf.subarray(offset, offset + 16).toString("hex");
86
+ offset += 16;
87
+ }
88
+ else {
89
+ break;
90
+ }
91
+ }
92
+ return headers;
93
+ }
94
+ async function* parseEventStream(stream) {
95
+ const reader = stream.getReader();
96
+ let buffer = Buffer.alloc(0);
97
+ try {
98
+ for (;;) {
99
+ const { done, value } = await reader.read();
100
+ if (done)
101
+ break;
102
+ if (value) {
103
+ buffer = Buffer.concat([buffer, Buffer.from(value)]);
104
+ }
105
+ while (buffer.length >= 12) {
106
+ const totalLength = buffer.readUInt32BE(0);
107
+ if (totalLength < 16) {
108
+ buffer = buffer.subarray(1);
109
+ continue;
110
+ }
111
+ const headersLength = buffer.readUInt32BE(4);
112
+ const preludeCrc = buffer.readUInt32BE(8);
113
+ const expectedPreludeCrc = crc32(buffer, 0, 8);
114
+ if (preludeCrc !== expectedPreludeCrc) {
115
+ buffer = buffer.subarray(1);
116
+ continue;
117
+ }
118
+ if (buffer.length < totalLength) {
119
+ break;
120
+ }
121
+ const messageCrc = buffer.readUInt32BE(totalLength - 4);
122
+ const expectedMessageCrc = crc32(buffer, 0, totalLength - 4);
123
+ if (messageCrc !== expectedMessageCrc) {
124
+ buffer = buffer.subarray(totalLength);
125
+ continue;
126
+ }
127
+ const headersBuffer = buffer.subarray(12, 12 + headersLength);
128
+ const payloadBuffer = buffer.subarray(12 + headersLength, totalLength - 4);
129
+ buffer = buffer.subarray(totalLength);
130
+ const headers = parseHeaders(headersBuffer);
131
+ let payload = {};
132
+ if (payloadBuffer.length > 0) {
133
+ try {
134
+ const raw = payloadBuffer.toString("utf8");
135
+ payload = JSON.parse(raw);
136
+ }
137
+ catch {
138
+ payload = { raw: payloadBuffer.toString("utf8") };
139
+ }
140
+ }
141
+ yield { headers, payload };
142
+ }
143
+ }
144
+ }
145
+ finally {
146
+ reader.releaseLock();
147
+ }
148
+ }
149
+ export function isThinkingModel(model) {
150
+ return model.endsWith("-thinking") || model.includes("-thinking-");
151
+ }
152
+ export function isAgenticModel(model) {
153
+ return model.endsWith("-agentic");
154
+ }
155
+ const KIRO_UPSTREAM_MODEL_PATTERN = /^(claude|gpt|o\d|amazon|nova|titan|deepseek|meta|mistral|qwen|minimax|glm|kimi|llama)/i;
156
+ export function resolveKiroModel(model) {
157
+ let upstream = model.trim();
158
+ let agentic = false;
159
+ let thinking = false;
160
+ if (upstream.endsWith("-agentic")) {
161
+ agentic = true;
162
+ upstream = upstream.slice(0, -"-agentic".length);
163
+ }
164
+ if (upstream.endsWith("-thinking")) {
165
+ thinking = true;
166
+ upstream = upstream.slice(0, -"-thinking".length);
167
+ }
168
+ if (!KIRO_UPSTREAM_MODEL_PATTERN.test(upstream)) {
169
+ upstream = defaultModels.kiro;
170
+ }
171
+ return { upstream, agentic, thinking };
172
+ }
173
+ function isNativeReasoningModel(model) {
174
+ return /^(gpt|o\d)/i.test(model);
175
+ }
176
+ function isAdaptiveThinkingModel(model) {
177
+ return /^claude/i.test(model);
178
+ }
179
+ function kiroEffortString(effort) {
180
+ if (!effort || effort === "none")
181
+ return "";
182
+ if (effort === "minimal" || effort === "low")
183
+ return "low";
184
+ if (effort === "medium")
185
+ return "medium";
186
+ return "high";
187
+ }
188
+ const KIRO_THINKING_BUDGET = {
189
+ low: 4000,
190
+ medium: 8000,
191
+ high: 16000,
192
+ };
193
+ function resolveKiroCredential(auth) {
194
+ const raw = auth.apiKey?.trim();
195
+ if (!raw) {
196
+ throw new Error("Kiro AI authentication required. Run `clai auth kiro` to sign in or `clai set kiro <key>`.");
197
+ }
198
+ const decoded = decodeKiroKey(raw);
199
+ if (decoded)
200
+ return decoded;
201
+ if (raw.startsWith("aorAAAAAG")) {
202
+ return {
203
+ accessToken: "",
204
+ refreshToken: raw,
205
+ authMethod: "imported",
206
+ region: "us-east-1",
207
+ };
208
+ }
209
+ if (raw.startsWith("ey") && raw.includes(".")) {
210
+ return {
211
+ accessToken: raw,
212
+ authMethod: "external_idp",
213
+ region: "us-east-1",
214
+ };
215
+ }
216
+ return {
217
+ accessToken: raw,
218
+ apiKey: raw,
219
+ authMethod: "api_key",
220
+ region: "us-east-1",
221
+ };
222
+ }
223
+ async function withKiroCredential(auth, run, onStatus) {
224
+ const credential = resolveKiroCredential(auth);
225
+ try {
226
+ return await run(credential);
227
+ }
228
+ catch (error) {
229
+ const status = error instanceof ProviderError ? error.status : undefined;
230
+ if (status !== 401 && status !== 403)
231
+ throw error;
232
+ onStatus?.("ℹ Kiro authentication expired — attempting token refresh");
233
+ const oldKey = auth.apiKey ?? "";
234
+ const refreshedKey = await maybeRefreshKiroCredential(oldKey, auth.refreshToken);
235
+ if (!refreshedKey || refreshedKey === oldKey) {
236
+ throw error;
237
+ }
238
+ await replaceProviderKey("kiro", oldKey, refreshedKey).catch(() => { });
239
+ auth.apiKey = refreshedKey;
240
+ const newCredential = resolveKiroCredential({ ...auth, apiKey: refreshedKey });
241
+ onStatus?.("ℹ Kiro token refreshed — retrying request");
242
+ return run(newCredential);
243
+ }
244
+ }
245
+ function getCandidateEndpoints(credential) {
246
+ const region = assertValidAwsRegion(credential.region);
247
+ const qUrl = `https://q.${region}.amazonaws.com/generateAssistantResponse`;
248
+ const cwUrl = `https://codewhisperer.${region}.amazonaws.com/generateAssistantResponse`;
249
+ const rtUrl = `https://runtime.${region}.kiro.dev/generateAssistantResponse`;
250
+ if (credential.authMethod === "api_key") {
251
+ return [qUrl, cwUrl, rtUrl];
252
+ }
253
+ return [cwUrl, rtUrl, qUrl];
254
+ }
255
+ function uuidFromHex(hex) {
256
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
257
+ }
258
+ function kiroConversationId(seedContent) {
259
+ const affinity = currentSessionAffinity();
260
+ if (affinity) {
261
+ return uuidFromHex(createHash("md5").update(`kiro-${affinity}`).digest("hex"));
262
+ }
263
+ const seed = seedContent.trim();
264
+ if (seed) {
265
+ return uuidFromHex(createHash("md5").update(`kiro-${seed.slice(0, 4000)}`).digest("hex"));
266
+ }
267
+ return randomUUID();
268
+ }
269
+ function sanitizeToolName(name) {
270
+ return name.slice(0, 64).replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
271
+ }
272
+ function formatKiroTools(tools) {
273
+ if (!tools || tools.length === 0)
274
+ return [];
275
+ return tools.map((t) => ({
276
+ toolSpecification: {
277
+ name: sanitizeToolName(t.wireName || t.name),
278
+ description: (t.description || "").slice(0, 10237),
279
+ inputSchema: {
280
+ json: t.parameters,
281
+ },
282
+ },
283
+ }));
284
+ }
285
+ function imageFormatFromMediaType(mediaType) {
286
+ const lower = mediaType.toLowerCase();
287
+ if (lower.includes("jpeg") || lower.includes("jpg"))
288
+ return "jpeg";
289
+ if (lower.includes("png"))
290
+ return "png";
291
+ if (lower.includes("gif"))
292
+ return "gif";
293
+ if (lower.includes("webp"))
294
+ return "webp";
295
+ return "png";
296
+ }
297
+ function buildKiroRequestBody(request, credential, upstreamModel, agentic, thinking) {
298
+ const agenticInstruction = agentic
299
+ ? "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."
300
+ : "";
301
+ const systemParts = [];
302
+ if (agenticInstruction)
303
+ systemParts.push(agenticInstruction);
304
+ const nonSystemMessages = [];
305
+ for (const msg of request.messages) {
306
+ if (msg.role === "system") {
307
+ if (msg.content.trim())
308
+ systemParts.push(msg.content.trim());
309
+ }
310
+ else {
311
+ nonSystemMessages.push(msg);
312
+ }
313
+ }
314
+ const systemPrompt = systemParts.join("\n\n").trim();
315
+ const turns = [];
316
+ for (const msg of nonSystemMessages) {
317
+ if (msg.role === "user") {
318
+ const images = (msg.images ?? []).map((img) => ({
319
+ format: imageFormatFromMediaType(img.mediaType),
320
+ source: { bytes: img.dataBase64 },
321
+ }));
322
+ const last = turns[turns.length - 1];
323
+ if (last && last.role === "user") {
324
+ if (msg.content) {
325
+ last.content = last.content
326
+ ? `${last.content}\n\n${msg.content}`
327
+ : msg.content;
328
+ }
329
+ if (images.length > 0) {
330
+ last.images = [...(last.images ?? []), ...images];
331
+ }
332
+ }
333
+ else {
334
+ turns.push({
335
+ role: "user",
336
+ content: msg.content || "",
337
+ images: images.length > 0 ? images : undefined,
338
+ });
339
+ }
340
+ }
341
+ else if (msg.role === "assistant") {
342
+ const toolUses = (msg.toolCalls ?? [])
343
+ .filter((tc) => tc.id)
344
+ .map((tc) => ({
345
+ toolUseId: tc.id,
346
+ name: sanitizeToolName(tc.name),
347
+ input: tc.args ?? {},
348
+ }));
349
+ const last = turns[turns.length - 1];
350
+ if (last && last.role === "assistant") {
351
+ if (msg.content) {
352
+ last.content = last.content
353
+ ? `${last.content}\n\n${msg.content}`
354
+ : msg.content;
355
+ }
356
+ if (toolUses.length > 0) {
357
+ last.toolUses = [...(last.toolUses ?? []), ...toolUses];
358
+ }
359
+ }
360
+ else {
361
+ turns.push({
362
+ role: "assistant",
363
+ content: msg.content || "",
364
+ toolUses: toolUses.length > 0 ? toolUses : undefined,
365
+ });
366
+ }
367
+ }
368
+ else if (msg.role === "tool") {
369
+ const toolResult = {
370
+ toolUseId: msg.toolCallId || "tool_result",
371
+ content: [{ text: msg.content || "" }],
372
+ status: msg.ok === false ? "error" : "success",
373
+ };
374
+ const last = turns[turns.length - 1];
375
+ if (last && last.role === "user") {
376
+ last.toolResults = [...(last.toolResults ?? []), toolResult];
377
+ }
378
+ else {
379
+ turns.push({
380
+ role: "user",
381
+ content: "",
382
+ toolResults: [toolResult],
383
+ });
384
+ }
385
+ }
386
+ }
387
+ if (turns.length === 0) {
388
+ turns.push({ role: "user", content: "continue" });
389
+ }
390
+ if (systemPrompt && turns[0] && turns[0].role === "user") {
391
+ turns[0].content = turns[0].content
392
+ ? `${systemPrompt}\n\n${turns[0].content}`
393
+ : systemPrompt;
394
+ }
395
+ if (turns[turns.length - 1]?.role !== "user") {
396
+ turns.push({ role: "user", content: "continue" });
397
+ }
398
+ for (const turn of turns) {
399
+ if (turn.role === "user" && !turn.content.trim()) {
400
+ turn.content =
401
+ turn.toolResults && turn.toolResults.length > 0
402
+ ? "Tool results provided."
403
+ : "continue";
404
+ }
405
+ }
406
+ const kiroTools = formatKiroTools(request.tools);
407
+ const history = [];
408
+ for (let i = 0; i < turns.length - 1; i++) {
409
+ const turn = turns[i];
410
+ if (turn.role === "user") {
411
+ const userContext = {};
412
+ if (turn.toolResults && turn.toolResults.length > 0) {
413
+ userContext.toolResults = turn.toolResults;
414
+ }
415
+ history.push({
416
+ userInputMessage: {
417
+ content: turn.content,
418
+ modelId: upstreamModel,
419
+ origin: "AI_EDITOR",
420
+ userInputMessageContext: userContext,
421
+ ...(turn.images && turn.images.length > 0
422
+ ? { images: turn.images }
423
+ : {}),
424
+ },
425
+ });
426
+ }
427
+ else {
428
+ history.push({
429
+ assistantResponseMessage: {
430
+ content: turn.content,
431
+ ...(turn.toolUses && turn.toolUses.length > 0
432
+ ? { toolUses: turn.toolUses }
433
+ : {}),
434
+ },
435
+ });
436
+ }
437
+ }
438
+ const lastTurn = turns[turns.length - 1];
439
+ const currentContext = {};
440
+ if (kiroTools.length > 0) {
441
+ currentContext.tools = kiroTools;
442
+ }
443
+ if (lastTurn.toolResults && lastTurn.toolResults.length > 0) {
444
+ currentContext.toolResults = lastTurn.toolResults;
445
+ }
446
+ const currentMessage = {
447
+ userInputMessage: {
448
+ content: lastTurn.content,
449
+ modelId: upstreamModel,
450
+ origin: "AI_EDITOR",
451
+ userInputMessageContext: currentContext,
452
+ ...(lastTurn.images && lastTurn.images.length > 0
453
+ ? { images: lastTurn.images }
454
+ : {}),
455
+ },
456
+ };
457
+ const firstUserContent = turns.find((t) => t.role === "user" && t.content.trim())?.content ?? "";
458
+ const conversationId = kiroConversationId(firstUserContent);
459
+ const payload = {
460
+ conversationState: {
461
+ conversationId,
462
+ chatTriggerType: "MANUAL",
463
+ history,
464
+ currentMessage,
465
+ },
466
+ };
467
+ if (credential.profileArn) {
468
+ payload.profileArn = credential.profileArn;
469
+ }
470
+ const wantsThinking = thinking || request.thinking?.enabled === true;
471
+ const effort = kiroEffortString(request.thinking?.effort) || "high";
472
+ if (wantsThinking && isNativeReasoningModel(upstreamModel)) {
473
+ payload.additionalModelRequestFields = { reasoning: { effort } };
474
+ }
475
+ else if (wantsThinking && isAdaptiveThinkingModel(upstreamModel)) {
476
+ const budget = KIRO_THINKING_BUDGET[effort] ?? 16000;
477
+ const directive = `<thinking_mode>enabled</thinking_mode><max_thinking_length>${budget}</max_thinking_length>`;
478
+ const uim = payload.conversationState
479
+ .currentMessage;
480
+ const msg = uim.userInputMessage;
481
+ msg.content = `${directive}\n\n${String(msg.content ?? "")}`;
482
+ payload.additionalModelRequestFields = {
483
+ output_config: { effort },
484
+ thinking: { type: "adaptive", display: "summarized" },
485
+ };
486
+ }
487
+ return payload;
488
+ }
489
+ let cachedKiroModels = null;
490
+ let lastKiroModelFetch = 0;
491
+ const MODEL_CACHE_TTL_MS = 30 * 60 * 1000;
492
+ export const kiroProvider = {
493
+ id: "kiro",
494
+ displayName: "Kiro AI",
495
+ defaultModel: defaultModels.kiro,
496
+ envVar: "KIRO_API_KEY",
497
+ validateKey(key) {
498
+ const trimmed = key.trim();
499
+ if (!trimmed)
500
+ return false;
501
+ if (isKiroOAuthToken(trimmed))
502
+ return decodeKiroKey(trimmed) !== undefined;
503
+ if (trimmed.startsWith("aorAAAAAG"))
504
+ return true;
505
+ if (trimmed.startsWith("ey") && trimmed.includes("."))
506
+ return true;
507
+ return trimmed.length >= 8;
508
+ },
509
+ async listModels(auth) {
510
+ const now = Date.now();
511
+ if (cachedKiroModels && now - lastKiroModelFetch < MODEL_CACHE_TTL_MS) {
512
+ return cachedKiroModels;
513
+ }
514
+ try {
515
+ const credential = resolveKiroCredential(auth);
516
+ const region = assertValidAwsRegion(credential.region);
517
+ const params = new URLSearchParams({ origin: "AI_EDITOR" });
518
+ const endpoint = `https://q.${region}.amazonaws.com/ListAvailableModels?${params.toString()}`;
519
+ const headers = {
520
+ Accept: "application/json",
521
+ "User-Agent": "AWS-SDK-JS/3.0.0 kiro-ide/1.0.0",
522
+ "X-Amz-User-Agent": "aws-sdk-js/3.0.0 kiro-ide/1.0.0",
523
+ };
524
+ if (credential.authMethod === "api_key" && credential.apiKey) {
525
+ headers["Authorization"] = `Bearer ${credential.apiKey}`;
526
+ headers["TokenType"] = "API_KEY";
527
+ }
528
+ else if (credential.accessToken) {
529
+ headers["Authorization"] = `Bearer ${credential.accessToken}`;
530
+ if (credential.authMethod === "external_idp") {
531
+ headers["TokenType"] = "EXTERNAL_IDP";
532
+ }
533
+ }
534
+ const response = await fetch(endpoint, {
535
+ method: "GET",
536
+ headers,
537
+ signal: AbortSignal.timeout(15_000),
538
+ });
539
+ if (response.ok) {
540
+ const json = (await response.json());
541
+ const models = Array.isArray(json?.models) ? json.models : [];
542
+ const baseIds = models
543
+ .map((m) => m.modelId || m.id || "")
544
+ .filter(Boolean);
545
+ if (baseIds.length > 0) {
546
+ const variants = [];
547
+ for (const id of baseIds) {
548
+ variants.push(id);
549
+ variants.push(`${id}-thinking`);
550
+ variants.push(`${id}-agentic`);
551
+ variants.push(`${id}-thinking-agentic`);
552
+ }
553
+ cachedKiroModels = variants;
554
+ lastKiroModelFetch = now;
555
+ return variants;
556
+ }
557
+ }
558
+ }
559
+ catch { }
560
+ return cachedKiroModels ?? [...kiroFallbackModels];
561
+ },
562
+ async ping(auth) {
563
+ const credential = resolveKiroCredential(auth);
564
+ const region = assertValidAwsRegion(credential.region);
565
+ const params = new URLSearchParams({ origin: "AI_EDITOR" });
566
+ const endpoint = `https://q.${region}.amazonaws.com/ListAvailableModels?${params.toString()}`;
567
+ const headers = {
568
+ Accept: "application/json",
569
+ "User-Agent": "AWS-SDK-JS/3.0.0 kiro-ide/1.0.0",
570
+ "X-Amz-User-Agent": "aws-sdk-js/3.0.0 kiro-ide/1.0.0",
571
+ };
572
+ if (credential.authMethod === "api_key" && credential.apiKey) {
573
+ headers["Authorization"] = `Bearer ${credential.apiKey}`;
574
+ headers["TokenType"] = "API_KEY";
575
+ }
576
+ else if (credential.accessToken) {
577
+ headers["Authorization"] = `Bearer ${credential.accessToken}`;
578
+ if (credential.authMethod === "external_idp") {
579
+ headers["TokenType"] = "EXTERNAL_IDP";
580
+ }
581
+ }
582
+ const response = await fetch(endpoint, {
583
+ method: "GET",
584
+ headers,
585
+ signal: AbortSignal.timeout(15_000),
586
+ });
587
+ if (!response.ok) {
588
+ throw new ProviderError(`Kiro AI ping failed (HTTP ${response.status}). Run \`clai auth kiro\` to sign in.`, response.status);
589
+ }
590
+ },
591
+ async complete(request, auth, onStatus) {
592
+ return this.stream(request, auth, () => { }, onStatus);
593
+ },
594
+ async stream(request, auth, onToken, onStatus) {
595
+ const requestedModel = request.model ?? defaultModels.kiro;
596
+ const { upstream, agentic, thinking } = resolveKiroModel(requestedModel);
597
+ return withKiroCredential(auth, async (credential) => {
598
+ const body = buildKiroRequestBody(request, credential, upstream, agentic, thinking);
599
+ const endpoints = getCandidateEndpoints(credential);
600
+ let lastError;
601
+ for (const endpoint of endpoints) {
602
+ try {
603
+ const headers = {
604
+ "Content-Type": "application/json",
605
+ Accept: "application/vnd.amazon.eventstream",
606
+ "Amz-Sdk-Request": "attempt=1; max=3",
607
+ "Amz-Sdk-Invocation-Id": randomUUID(),
608
+ "x-amzn-kiro-agent-mode": "spec",
609
+ "x-amzn-codewhisperer-machine-id": "kiro-desktop",
610
+ };
611
+ if (endpoint.includes("codewhisperer")) {
612
+ headers["X-Amz-Target"] =
613
+ "AmazonCodeWhispererStreamingService.GenerateAssistantResponse";
614
+ }
615
+ if (credential.authMethod === "api_key" && credential.apiKey) {
616
+ headers["Authorization"] = `Bearer ${credential.apiKey}`;
617
+ headers["TokenType"] = "API_KEY";
618
+ }
619
+ else if (credential.accessToken) {
620
+ headers["Authorization"] = `Bearer ${credential.accessToken}`;
621
+ headers["x-amz-sso-bearer"] = credential.accessToken;
622
+ if (credential.authMethod === "external_idp") {
623
+ headers["TokenType"] = "EXTERNAL_IDP";
624
+ }
625
+ if (credential.profileArn) {
626
+ headers["x-amzn-codewhisperer-profile-arn"] = credential.profileArn;
627
+ }
628
+ }
629
+ const response = await fetch(endpoint, {
630
+ method: "POST",
631
+ headers,
632
+ body: JSON.stringify(body),
633
+ ...(request.signal ? { signal: request.signal } : {}),
634
+ });
635
+ if (!response.ok) {
636
+ const errorText = await response.text().catch(() => "");
637
+ if (response.status === 401 || response.status === 403) {
638
+ throw new ProviderError(`Kiro authentication failed (${response.status}): ${errorText}`, response.status);
639
+ }
640
+ if (response.status === 400) {
641
+ throw new ProviderError(`Kiro request invalid (${response.status}): ${errorText}`, response.status);
642
+ }
643
+ lastError = new ProviderError(`Kiro endpoint error (${response.status}): ${errorText}`, response.status);
644
+ continue;
645
+ }
646
+ if (!response.body) {
647
+ throw new ProviderError("Empty response body from Kiro endpoint", 500);
648
+ }
649
+ let fullText = "";
650
+ let reasoningText = "";
651
+ let insideThinkingTag = false;
652
+ let finishReason = "stop";
653
+ const accumulatedTools = [];
654
+ let currentToolIndex = -1;
655
+ let promptTokens = 0;
656
+ let completionTokens = 0;
657
+ let cachedTokens = 0;
658
+ let cacheCreationTokens = 0;
659
+ for await (const frame of parseEventStream(response.body)) {
660
+ const eventType = (typeof frame.headers[":event-type"] === "string"
661
+ ? frame.headers[":event-type"]
662
+ : undefined) ||
663
+ Object.keys(frame.payload).find((k) => k.endsWith("Event")) ||
664
+ "";
665
+ const eventPayload = frame.payload[eventType] ||
666
+ frame.payload;
667
+ if (eventType === "assistantResponseEvent" ||
668
+ eventType.includes("Response")) {
669
+ const chunk = typeof eventPayload.content === "string"
670
+ ? eventPayload.content
671
+ : "";
672
+ if (chunk) {
673
+ let visibleChunk = "";
674
+ let i = 0;
675
+ while (i < chunk.length) {
676
+ if (!insideThinkingTag) {
677
+ const tagStart = chunk.indexOf("<thinking>", i);
678
+ if (tagStart !== -1) {
679
+ visibleChunk += chunk.slice(i, tagStart);
680
+ insideThinkingTag = true;
681
+ i = tagStart + 10;
682
+ }
683
+ else {
684
+ visibleChunk += chunk.slice(i);
685
+ break;
686
+ }
687
+ }
688
+ else {
689
+ const tagEnd = chunk.indexOf("</thinking>", i);
690
+ if (tagEnd !== -1) {
691
+ reasoningText += chunk.slice(i, tagEnd);
692
+ insideThinkingTag = false;
693
+ i = tagEnd + 11;
694
+ }
695
+ else {
696
+ reasoningText += chunk.slice(i);
697
+ break;
698
+ }
699
+ }
700
+ }
701
+ if (visibleChunk) {
702
+ fullText += visibleChunk;
703
+ onToken(visibleChunk);
704
+ }
705
+ }
706
+ }
707
+ else if (eventType === "reasoningContentEvent" ||
708
+ eventType.includes("Reasoning")) {
709
+ const chunk = typeof eventPayload.content === "string"
710
+ ? eventPayload.content
711
+ : "";
712
+ if (chunk) {
713
+ reasoningText += chunk;
714
+ }
715
+ }
716
+ else if (eventType === "codeEvent") {
717
+ const chunk = typeof eventPayload.content === "string"
718
+ ? eventPayload.content
719
+ : "";
720
+ if (chunk) {
721
+ fullText += chunk;
722
+ onToken(chunk);
723
+ }
724
+ }
725
+ else if (eventType === "toolUseEvent") {
726
+ const toolId = typeof eventPayload.toolUseId === "string"
727
+ ? eventPayload.toolUseId
728
+ : `tool_${accumulatedTools.length + 1}`;
729
+ const name = typeof eventPayload.name === "string" ? eventPayload.name : "";
730
+ const input = eventPayload.input;
731
+ let existing = accumulatedTools.find((t) => t.id === toolId);
732
+ if (!existing) {
733
+ existing = { id: toolId, name, rawArgs: "" };
734
+ accumulatedTools.push(existing);
735
+ currentToolIndex = accumulatedTools.length - 1;
736
+ }
737
+ let chunkBytes = 0;
738
+ if (typeof input === "string") {
739
+ existing.rawArgs += input;
740
+ chunkBytes = Buffer.byteLength(input, "utf8");
741
+ }
742
+ else if (input && typeof input === "object") {
743
+ existing.rawArgs = JSON.stringify(input);
744
+ chunkBytes = Buffer.byteLength(existing.rawArgs, "utf8");
745
+ }
746
+ if (name && !existing.name) {
747
+ existing.name = name;
748
+ }
749
+ const delta = {
750
+ index: currentToolIndex,
751
+ id: existing.id,
752
+ name: existing.name,
753
+ argumentsBytes: chunkBytes,
754
+ };
755
+ request.onToolCallDelta?.(delta);
756
+ finishReason = "tool_calls";
757
+ }
758
+ else if (eventType === "messageStopEvent") {
759
+ const stop = typeof eventPayload.stopReason === "string"
760
+ ? eventPayload.stopReason
761
+ : "";
762
+ if (stop) {
763
+ finishReason =
764
+ stop === "tool_use" || stop === "tool_calls"
765
+ ? "tool_calls"
766
+ : stop === "max_tokens" || stop === "length"
767
+ ? "length"
768
+ : "stop";
769
+ }
770
+ }
771
+ else if (eventType === "metricsEvent" ||
772
+ eventType === "contextUsageEvent" ||
773
+ eventType === "meteringEvent") {
774
+ if (typeof eventPayload.inputTokens === "number") {
775
+ promptTokens = eventPayload.inputTokens;
776
+ }
777
+ if (typeof eventPayload.outputTokens === "number") {
778
+ completionTokens = eventPayload.outputTokens;
779
+ }
780
+ if (typeof eventPayload.cachedTokens === "number") {
781
+ cachedTokens = eventPayload.cachedTokens;
782
+ }
783
+ if (typeof eventPayload.cacheReadInputTokens === "number") {
784
+ cachedTokens = Math.max(cachedTokens, eventPayload.cacheReadInputTokens);
785
+ }
786
+ if (typeof eventPayload.cacheWriteInputTokens === "number") {
787
+ cacheCreationTokens = eventPayload.cacheWriteInputTokens;
788
+ }
789
+ }
790
+ }
791
+ const toolCalls = accumulatedTools.map((t) => {
792
+ let parsedArgs = {};
793
+ try {
794
+ parsedArgs = JSON.parse(t.rawArgs || "{}");
795
+ }
796
+ catch {
797
+ parsedArgs = { raw: t.rawArgs };
798
+ }
799
+ return {
800
+ id: t.id,
801
+ name: t.name,
802
+ args: parsedArgs,
803
+ rawArguments: t.rawArgs,
804
+ };
805
+ });
806
+ if (toolCalls.length > 0) {
807
+ finishReason = "tool_calls";
808
+ }
809
+ const usage = promptTokens > 0 || completionTokens > 0
810
+ ? {
811
+ promptTokens,
812
+ completionTokens,
813
+ totalTokens: promptTokens + completionTokens,
814
+ exact: true,
815
+ cachedPromptTokens: cachedTokens > 0 ? cachedTokens : undefined,
816
+ cacheCreationTokens: cacheCreationTokens > 0 ? cacheCreationTokens : undefined,
817
+ uncachedPromptTokens: cachedTokens > 0
818
+ ? Math.max(0, promptTokens - cachedTokens)
819
+ : promptTokens,
820
+ }
821
+ : undefined;
822
+ return {
823
+ text: fullText,
824
+ provider: "kiro",
825
+ model: requestedModel,
826
+ api: "kiro-eventstream",
827
+ finishReason,
828
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
829
+ usage,
830
+ reasoningBlock: reasoningText.trim()
831
+ ? { text: reasoningText.trim() }
832
+ : undefined,
833
+ };
834
+ }
835
+ catch (err) {
836
+ if (err instanceof ProviderError && (err.status === 401 || err.status === 403 || err.status === 400)) {
837
+ throw err;
838
+ }
839
+ lastError = err instanceof Error ? err : new Error(String(err));
840
+ }
841
+ }
842
+ throw lastError ?? new Error("All Kiro endpoints failed");
843
+ }, onStatus);
844
+ },
845
+ };
846
+ //# sourceMappingURL=kiro.js.map