ns-omp-provider-kiro 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1473 -1024
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -245,6 +245,12 @@ function getKiroEndpoints(region) {
|
|
|
245
245
|
runtime: `https://runtime.${region}.kiro.dev/`
|
|
246
246
|
};
|
|
247
247
|
}
|
|
248
|
+
function getKiroRegionFromProfileArn(profileArn) {
|
|
249
|
+
if (!profileArn)
|
|
250
|
+
return void 0;
|
|
251
|
+
const region = profileArn.split(":")[3];
|
|
252
|
+
return region && /^[a-z]{2}(?:-[a-z]+)+-\d$/.test(region) ? region : void 0;
|
|
253
|
+
}
|
|
248
254
|
function getKiroRegionFromEndpoint(endpoint) {
|
|
249
255
|
try {
|
|
250
256
|
const [service, region, ...suffix] = new URL(endpoint).hostname.split(".");
|
|
@@ -267,6 +273,7 @@ var init_endpoints = __esm({
|
|
|
267
273
|
"ap-southeast-1": "us-east-1",
|
|
268
274
|
"ap-southeast-2": "us-east-1",
|
|
269
275
|
"ap-northeast-1": "us-east-1",
|
|
276
|
+
"ap-northeast-2": "us-east-1",
|
|
270
277
|
"ap-south-1": "us-east-1",
|
|
271
278
|
"eu-west-1": "eu-central-1",
|
|
272
279
|
"eu-west-2": "eu-central-1",
|
|
@@ -285,6 +292,7 @@ __export(kiro_cli_exports, {
|
|
|
285
292
|
getKiroCliCredentials: () => getKiroCliCredentials,
|
|
286
293
|
getKiroCliCredentialsAllowExpired: () => getKiroCliCredentialsAllowExpired,
|
|
287
294
|
getKiroCliDbPath: () => getKiroCliDbPath,
|
|
295
|
+
getKiroCliExternalIdpCredentials: () => getKiroCliExternalIdpCredentials,
|
|
288
296
|
getKiroCliModelRates: () => getKiroCliModelRates,
|
|
289
297
|
getKiroCliSocialToken: () => getKiroCliSocialToken,
|
|
290
298
|
getKiroCliSocialTokenAllowExpired: () => getKiroCliSocialTokenAllowExpired,
|
|
@@ -308,6 +316,16 @@ function getKiroCliDbPath() {
|
|
|
308
316
|
dbPath = join2(homedir2(), ".local", "share", "kiro-cli", "data.sqlite3");
|
|
309
317
|
return existsSync(dbPath) ? dbPath : void 0;
|
|
310
318
|
}
|
|
319
|
+
function getKiroCliExternalIdpCredentials() {
|
|
320
|
+
const dbPath = getKiroCliDbPath();
|
|
321
|
+
if (!dbPath)
|
|
322
|
+
return void 0;
|
|
323
|
+
try {
|
|
324
|
+
return tryKiroCliToken(dbPath, EXTERNAL_IDP_TOKEN_KEY, "external-idp", true);
|
|
325
|
+
} catch {
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
311
329
|
function getNodeSqlite() {
|
|
312
330
|
try {
|
|
313
331
|
return require2("node:sqlite");
|
|
@@ -642,778 +660,317 @@ var init_kiro_ide = __esm({
|
|
|
642
660
|
}
|
|
643
661
|
});
|
|
644
662
|
|
|
645
|
-
// ../kiro-core/dist/
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
applyEffortLadder: () => applyEffortLadder,
|
|
653
|
-
getCachedModels: () => getCachedModels,
|
|
654
|
-
isCacheStale: () => isCacheStale,
|
|
655
|
-
kiroModels: () => kiroModels,
|
|
656
|
-
loadCachedModelIds: () => loadCachedModelIds,
|
|
657
|
-
mapKiroCatalogModels: () => mapKiroCatalogModels,
|
|
658
|
-
resolveApiRegion: () => resolveApiRegion,
|
|
659
|
-
resolveKiroModel: () => resolveKiroModel,
|
|
660
|
-
updateKiroModelsCache: () => updateKiroModelsCache
|
|
661
|
-
});
|
|
662
|
-
import { randomUUID } from "node:crypto";
|
|
663
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
664
|
-
import { homedir as homedir4 } from "node:os";
|
|
665
|
-
import { join as join4 } from "node:path";
|
|
666
|
-
function isRecord2(value) {
|
|
667
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
668
|
-
}
|
|
669
|
-
function isPositiveNumber(value) {
|
|
670
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
671
|
-
}
|
|
672
|
-
function isEffortList(value) {
|
|
673
|
-
return Array.isArray(value) && value.length > 0 && value.every((effort) => KIRO_EFFORT_ORDER.includes(effort));
|
|
663
|
+
// ../kiro-core/dist/oauth.js
|
|
664
|
+
function kiroUserAgent(service, sdkVersion) {
|
|
665
|
+
return {
|
|
666
|
+
"User-Agent": `aws-sdk-js/3.714.0 os/macos/24.3.0 lang/js md/nodejs/22.14.0 api/${service}/3.714.0 exec-env/kiro-cli/2.7.0 m/E`,
|
|
667
|
+
"amz-sdk-invocation-id": "00000000-0000-0000-0000-000000000000",
|
|
668
|
+
"amz-sdk-request": `attempt=1; max=${sdkVersion}`
|
|
669
|
+
};
|
|
674
670
|
}
|
|
675
|
-
function
|
|
676
|
-
|
|
671
|
+
function kiroAuthHeaders(token) {
|
|
672
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
673
|
+
if (isApiKey(token))
|
|
674
|
+
headers.tokentype = "API_KEY";
|
|
675
|
+
return headers;
|
|
677
676
|
}
|
|
678
|
-
function
|
|
679
|
-
|
|
680
|
-
return false;
|
|
681
|
-
const cost = value.cost;
|
|
682
|
-
const input = value.input;
|
|
683
|
-
const schema = value.additionalModelRequestFieldsSchema;
|
|
684
|
-
const tokenLimits = value.tokenLimits;
|
|
685
|
-
return typeof value.id === "string" && value.id.length > 0 && typeof value.kiroModelId === "string" && value.kiroModelId.length > 0 && typeof value.name === "string" && value.name.length > 0 && typeof value.reasoning === "boolean" && Array.isArray(input) && input.length > 0 && input.every((modality) => modality === "text" || modality === "image") && isRecord2(cost) && typeof cost.input === "number" && typeof cost.output === "number" && typeof cost.cacheRead === "number" && typeof cost.cacheWrite === "number" && isPositiveNumber(value.contextWindow) && isPositiveNumber(value.maxTokens) && (value.efforts === void 0 || isEffortList(value.efforts)) && (value.effortMap === void 0 || isEffortMap(value.effortMap)) && (schema === void 0 || isRecord2(schema)) && (tokenLimits === void 0 || isRecord2(tokenLimits)) && (value.firstTokenTimeout === void 0 || isPositiveNumber(value.firstTokenTimeout)) && (value.rateMultiplier === void 0 || isPositiveNumber(value.rateMultiplier)) && (value.rateUnit === void 0 || typeof value.rateUnit === "string");
|
|
677
|
+
function isApiKey(token) {
|
|
678
|
+
return token.startsWith("ksk_");
|
|
686
679
|
}
|
|
687
|
-
function
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
value = JSON.parse(raw);
|
|
691
|
-
} catch {
|
|
692
|
-
return void 0;
|
|
693
|
-
}
|
|
694
|
-
if (!isRecord2(value) || value.version !== KIRO_MANAGEMENT_CACHE_VERSION || value.source !== KIRO_MANAGEMENT_CACHE_SOURCE || !isRecord2(value.regions)) {
|
|
695
|
-
return void 0;
|
|
680
|
+
async function loginKiroWithApiKey(apiKey, onProgress) {
|
|
681
|
+
if (!apiKey.startsWith("ksk_")) {
|
|
682
|
+
throw new Error("Invalid API key format. Kiro API keys start with 'ksk_'.");
|
|
696
683
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
684
|
+
onProgress?.("Validating API key...");
|
|
685
|
+
const region = "us-east-1";
|
|
686
|
+
const managementUrl = `https://management.${resolveApiRegion(region)}.kiro.dev/`;
|
|
687
|
+
const response = await fetch(managementUrl, {
|
|
688
|
+
method: "POST",
|
|
689
|
+
headers: {
|
|
690
|
+
"Content-Type": "application/x-amz-json-1.0",
|
|
691
|
+
"X-Amz-Target": "AmazonCodeWhispererService.GetProfile",
|
|
692
|
+
...kiroAuthHeaders(apiKey),
|
|
693
|
+
...kiroUserAgent("codewhispererruntime", "F,C")
|
|
694
|
+
},
|
|
695
|
+
body: "{}"
|
|
696
|
+
});
|
|
697
|
+
if (!response.ok) {
|
|
698
|
+
let detail = "";
|
|
699
|
+
try {
|
|
700
|
+
detail = await response.text();
|
|
701
|
+
} catch {
|
|
702
|
+
detail = "";
|
|
701
703
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
if (modelIds.has(model.id))
|
|
705
|
-
return void 0;
|
|
706
|
-
modelIds.add(model.id);
|
|
704
|
+
if (response.status === 401 || response.status === 403 || /Invalid token/i.test(detail)) {
|
|
705
|
+
throw new Error("API key was rejected by Kiro. Check that the key is valid and not expired.");
|
|
707
706
|
}
|
|
708
|
-
|
|
707
|
+
throw new Error(`Kiro GetProfile failed: ${response.status} ${response.statusText} ${detail}`.trim());
|
|
709
708
|
}
|
|
709
|
+
const data = await response.json();
|
|
710
|
+
const profileArn = data.profile?.arn;
|
|
710
711
|
return {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
712
|
+
access: apiKey,
|
|
713
|
+
refresh: `${apiKey}|apikey`,
|
|
714
|
+
expires: Date.now() + 365 * 24 * 60 * 60 * 1e3,
|
|
715
|
+
clientId: "",
|
|
716
|
+
clientSecret: "",
|
|
717
|
+
region,
|
|
718
|
+
authMethod: "apikey",
|
|
719
|
+
...profileArn ? { profileArn } : {}
|
|
714
720
|
};
|
|
715
721
|
}
|
|
716
|
-
function
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
722
|
+
async function refreshKiroToken(credentials) {
|
|
723
|
+
const refreshed = await refreshKiroTokenInternal(credentials);
|
|
724
|
+
if (!process.env.VITEST) {
|
|
725
|
+
try {
|
|
726
|
+
const { updateKiroModelsCache: updateKiroModelsCache2 } = await Promise.resolve().then(() => (init_models(), models_exports));
|
|
727
|
+
const region = resolveApiRegion(refreshed.region);
|
|
728
|
+
updateKiroModelsCache2(refreshed.access, region, refreshed.profileArn).catch((error2) => {
|
|
729
|
+
console.warn(`[kiro-core] Failed to refresh Kiro model catalog in ${region}: ${formatSafeError(error2)}`);
|
|
730
|
+
});
|
|
731
|
+
} catch (error2) {
|
|
732
|
+
console.warn(`[kiro-core] Failed to start Kiro model catalog refresh: ${formatSafeError(error2)}`);
|
|
733
|
+
}
|
|
723
734
|
}
|
|
735
|
+
return refreshed;
|
|
724
736
|
}
|
|
725
|
-
function
|
|
726
|
-
const
|
|
737
|
+
async function refreshKiroTokenInternal(credentials) {
|
|
738
|
+
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2, saveKiroCliCredentials: saveKiroCliCredentials2, getKiroCliSocialToken: getKiroCliSocialToken2, getKiroCliSocialTokenAllowExpired: getKiroCliSocialTokenAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
739
|
+
const credentialAuthMethod = credentials.authMethod ?? (credentials.refresh.split("|").at(-1) === "desktop" ? "desktop" : "idc");
|
|
740
|
+
const getValidCliCredentials = () => {
|
|
741
|
+
if (credentialAuthMethod === "desktop")
|
|
742
|
+
return getKiroCliSocialToken2();
|
|
743
|
+
const cliCreds = getKiroCliCredentials2();
|
|
744
|
+
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
745
|
+
};
|
|
746
|
+
const getExpiredCliCredentials = () => {
|
|
747
|
+
if (credentialAuthMethod === "desktop")
|
|
748
|
+
return getKiroCliSocialTokenAllowExpired2();
|
|
749
|
+
const cliCreds = getKiroCliCredentialsAllowExpired2();
|
|
750
|
+
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
751
|
+
};
|
|
752
|
+
if (credentials.authMethod === "apikey" || isApiKey(credentials.access))
|
|
753
|
+
return credentials;
|
|
754
|
+
if (credentialAuthMethod === "idc") {
|
|
755
|
+
const ideCreds = getKiroIdeCredentials();
|
|
756
|
+
if (ideCreds)
|
|
757
|
+
return ideCreds;
|
|
758
|
+
}
|
|
759
|
+
const preCheckCreds = getValidCliCredentials();
|
|
760
|
+
if (preCheckCreds)
|
|
761
|
+
return preCheckCreds;
|
|
727
762
|
try {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
763
|
+
const refreshed = await refreshKiroTokenDirect(credentials);
|
|
764
|
+
saveKiroCliCredentials2(refreshed);
|
|
765
|
+
return refreshed;
|
|
766
|
+
} catch (refreshError) {
|
|
767
|
+
const retryCreds = getValidCliCredentials();
|
|
768
|
+
if (retryCreds)
|
|
769
|
+
return retryCreds;
|
|
770
|
+
const expiredCliCreds = getExpiredCliCredentials();
|
|
771
|
+
if (expiredCliCreds && expiredCliCreds.refresh !== credentials.refresh) {
|
|
772
|
+
try {
|
|
773
|
+
const refreshedFromCli = await refreshKiroTokenDirect(expiredCliCreds);
|
|
774
|
+
saveKiroCliCredentials2(refreshedFromCli);
|
|
775
|
+
return refreshedFromCli;
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
const actualExpiry = credentials.expires + EXPIRES_BUFFER_MS;
|
|
780
|
+
if (credentials.access && Date.now() < actualExpiry) {
|
|
781
|
+
return { ...credentials, expires: actualExpiry };
|
|
782
|
+
}
|
|
783
|
+
throw refreshError;
|
|
732
784
|
}
|
|
733
785
|
}
|
|
734
|
-
function
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
if (
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
throw new Error(`Kiro management catalog model ${model.modelId} has an invalid request-fields schema`);
|
|
786
|
+
async function refreshKiroTokenDirect(credentials) {
|
|
787
|
+
const parts = credentials.refresh.split("|");
|
|
788
|
+
const refreshToken = parts[0] ?? "";
|
|
789
|
+
const authMethod = parts[parts.length - 1] ?? "idc";
|
|
790
|
+
const region = credentials.region || "us-east-1";
|
|
791
|
+
if (authMethod === "apikey")
|
|
792
|
+
return credentials;
|
|
793
|
+
if (authMethod === "desktop") {
|
|
794
|
+
const url = KIRO_DESKTOP_REFRESH_URL.replace("{region}", region);
|
|
795
|
+
const response2 = await fetch(url, {
|
|
796
|
+
method: "POST",
|
|
797
|
+
headers: { "Content-Type": "application/json", "User-Agent": KIRO_DESKTOP_USER_AGENT },
|
|
798
|
+
body: JSON.stringify({ refreshToken })
|
|
799
|
+
});
|
|
800
|
+
if (!response2.ok)
|
|
801
|
+
throw new Error(`Desktop token refresh failed: ${response2.status}`);
|
|
802
|
+
const data2 = await response2.json();
|
|
803
|
+
if (!data2.accessToken)
|
|
804
|
+
throw new Error("Desktop token refresh: missing accessToken");
|
|
805
|
+
return {
|
|
806
|
+
refresh: `${data2.refreshToken || refreshToken}|desktop`,
|
|
807
|
+
access: data2.accessToken,
|
|
808
|
+
expires: Date.now() + data2.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
809
|
+
clientId: "",
|
|
810
|
+
clientSecret: "",
|
|
811
|
+
region,
|
|
812
|
+
authMethod: "desktop",
|
|
813
|
+
profileArn: data2.profileArn || credentials.profileArn,
|
|
814
|
+
startUrl: credentials.startUrl
|
|
815
|
+
};
|
|
765
816
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
const existing = kiroModels.find((model) => model.id === id);
|
|
791
|
-
const rate = rates?.get(kiroModelId);
|
|
792
|
-
const { schema, tokenLimits } = validateCatalogMetadata(catalogModel);
|
|
793
|
-
const effortConfig = getKiroEffortConfig(schema, kiroModelId);
|
|
794
|
-
const catalogName = typeof catalogModel.displayName === "string" && catalogModel.displayName.length > 0 ? catalogModel.displayName : void 0;
|
|
817
|
+
if (authMethod === "external-idp") {
|
|
818
|
+
const idpClientId = parts[1] ?? "";
|
|
819
|
+
const tokenEndpoint = parts[2] ?? "";
|
|
820
|
+
if (!tokenEndpoint)
|
|
821
|
+
throw new Error("External IdP token refresh: missing token endpoint");
|
|
822
|
+
const response2 = await fetch(tokenEndpoint, {
|
|
823
|
+
method: "POST",
|
|
824
|
+
headers: {
|
|
825
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
826
|
+
Accept: "application/json",
|
|
827
|
+
"User-Agent": "kiro-core"
|
|
828
|
+
},
|
|
829
|
+
body: new URLSearchParams({
|
|
830
|
+
grant_type: "refresh_token",
|
|
831
|
+
client_id: idpClientId,
|
|
832
|
+
refresh_token: refreshToken
|
|
833
|
+
}).toString()
|
|
834
|
+
});
|
|
835
|
+
if (!response2.ok)
|
|
836
|
+
throw new Error(`External IdP token refresh failed: ${response2.status}`);
|
|
837
|
+
const data2 = await response2.json();
|
|
838
|
+
if (!data2.access_token)
|
|
839
|
+
throw new Error("External IdP token refresh: missing access_token");
|
|
840
|
+
const expiresIn = typeof data2.expires_in === "number" ? data2.expires_in : 3600;
|
|
795
841
|
return {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
842
|
+
refresh: `${data2.refresh_token || refreshToken}|${idpClientId}|${tokenEndpoint}|external-idp`,
|
|
843
|
+
access: data2.access_token,
|
|
844
|
+
expires: Date.now() + expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
845
|
+
clientId: idpClientId,
|
|
846
|
+
clientSecret: "",
|
|
799
847
|
region,
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
// decides. The fallback tier feeds the ladders, not this flag.
|
|
803
|
-
reasoning: schema !== void 0 && effortConfig !== void 0 || schema === void 0 && hasReasoningFamilyFallback(id),
|
|
804
|
-
...applyEffortLadder(effortConfig),
|
|
805
|
-
input: existing ? [...existing.input] : hasVerifiedImageInput(kiroModelId) ? ["text", "image"] : ["text"],
|
|
806
|
-
...id.startsWith("claude-") ? { recoverTextToolCalls: false } : {},
|
|
807
|
-
cost: ZERO_COST,
|
|
808
|
-
...rate ? { rateMultiplier: rate.multiplier, ...rate.unit ? { rateUnit: rate.unit } : {} } : {},
|
|
809
|
-
contextWindow: tokenLimits?.maxInputTokens ?? DEFAULT_CONTEXT_WINDOW,
|
|
810
|
-
maxTokens: tokenLimits?.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
811
|
-
...existing?.firstTokenTimeout ? { firstTokenTimeout: existing.firstTokenTimeout } : {},
|
|
812
|
-
...schema ? { additionalModelRequestFieldsSchema: schema } : {},
|
|
813
|
-
...tokenLimits ? { tokenLimits } : {}
|
|
848
|
+
authMethod: "external-idp",
|
|
849
|
+
profileArn: credentials.profileArn
|
|
814
850
|
};
|
|
851
|
+
}
|
|
852
|
+
const clientId = parts[1] ?? "";
|
|
853
|
+
const clientSecret = parts[2] ?? "";
|
|
854
|
+
const ssoEndpoint = `https://oidc.${region}.amazonaws.com`;
|
|
855
|
+
const response = await fetch(`${ssoEndpoint}/token`, {
|
|
856
|
+
method: "POST",
|
|
857
|
+
headers: { "Content-Type": "application/json", ...kiroUserAgent("ssooidc", "E") },
|
|
858
|
+
body: JSON.stringify({ clientId, clientSecret, refreshToken, grantType: "refresh_token" })
|
|
815
859
|
});
|
|
860
|
+
if (!response.ok)
|
|
861
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
862
|
+
const data = await response.json();
|
|
863
|
+
return {
|
|
864
|
+
refresh: `${data.refreshToken}|${clientId}|${clientSecret}|idc`,
|
|
865
|
+
access: data.accessToken,
|
|
866
|
+
expires: Date.now() + data.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
867
|
+
clientId,
|
|
868
|
+
clientSecret,
|
|
869
|
+
region,
|
|
870
|
+
authMethod: "idc",
|
|
871
|
+
profileArn: credentials.profileArn,
|
|
872
|
+
startUrl: credentials.startUrl,
|
|
873
|
+
isEnterprise: credentials.isEnterprise
|
|
874
|
+
};
|
|
816
875
|
}
|
|
817
|
-
function
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
876
|
+
async function resolveKiroCredentials() {
|
|
877
|
+
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
878
|
+
const fresh = getKiroCliCredentials2() ?? getKiroIdeCredentials();
|
|
879
|
+
if (fresh)
|
|
880
|
+
return fresh;
|
|
881
|
+
const stale = getKiroCliCredentialsAllowExpired2();
|
|
882
|
+
if (!stale)
|
|
883
|
+
return void 0;
|
|
884
|
+
return refreshKiroToken(stale);
|
|
827
885
|
}
|
|
828
|
-
|
|
829
|
-
|
|
886
|
+
var KIRO_DESKTOP_REFRESH_URL, EXPIRES_BUFFER_MS, KIRO_DESKTOP_USER_AGENT;
|
|
887
|
+
var init_oauth = __esm({
|
|
888
|
+
"../kiro-core/dist/oauth.js"() {
|
|
889
|
+
"use strict";
|
|
890
|
+
init_debug();
|
|
891
|
+
init_endpoints();
|
|
892
|
+
init_kiro_ide();
|
|
893
|
+
KIRO_DESKTOP_REFRESH_URL = "https://prod.{region}.auth.desktop.kiro.dev/refreshToken";
|
|
894
|
+
EXPIRES_BUFFER_MS = 5 * 60 * 1e3;
|
|
895
|
+
KIRO_DESKTOP_USER_AGENT = "Kiro-Desktop/0.2.13 (darwin; arm64)";
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
// ../kiro-core/dist/token-type.js
|
|
900
|
+
function isExternalIdpAccessToken(accessToken) {
|
|
901
|
+
if (typeof accessToken !== "string" || !accessToken)
|
|
902
|
+
return false;
|
|
903
|
+
const segments = accessToken.split(".");
|
|
904
|
+
const payloadSegment = segments[1];
|
|
905
|
+
if (segments.length === 3 && payloadSegment) {
|
|
906
|
+
try {
|
|
907
|
+
const payload = JSON.parse(Buffer.from(payloadSegment.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf-8"));
|
|
908
|
+
if (payload.aud === EXTERNAL_IDP_AUDIENCE || Array.isArray(payload.aud) && payload.aud.includes(EXTERNAL_IDP_AUDIENCE)) {
|
|
909
|
+
return true;
|
|
910
|
+
}
|
|
911
|
+
} catch {
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
try {
|
|
915
|
+
return getKiroCliExternalIdpCredentials()?.access === accessToken;
|
|
916
|
+
} catch {
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
830
919
|
}
|
|
831
|
-
function
|
|
832
|
-
|
|
833
|
-
refreshKnownModelIds(cache);
|
|
834
|
-
const models = cache?.regions[region]?.models ?? kiroModels;
|
|
835
|
-
let changed = false;
|
|
836
|
-
const corrected = models.map((model) => {
|
|
837
|
-
const result = applyVerifiedCapabilities(model);
|
|
838
|
-
if (result !== model)
|
|
839
|
-
changed = true;
|
|
840
|
-
return result;
|
|
841
|
-
});
|
|
842
|
-
return changed ? corrected : models;
|
|
920
|
+
function kiroTokenTypeHeaders(accessToken) {
|
|
921
|
+
return isExternalIdpAccessToken(accessToken) ? { tokentype: "EXTERNAL_IDP" } : {};
|
|
843
922
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
923
|
+
var EXTERNAL_IDP_AUDIENCE;
|
|
924
|
+
var init_token_type = __esm({
|
|
925
|
+
"../kiro-core/dist/token-type.js"() {
|
|
926
|
+
"use strict";
|
|
927
|
+
init_kiro_cli();
|
|
928
|
+
EXTERNAL_IDP_AUDIENCE = "api://kiro";
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
// ../kiro-core/dist/management.js
|
|
933
|
+
import { createHash } from "node:crypto";
|
|
934
|
+
function candidateManagementRegions(primary) {
|
|
935
|
+
const seen = /* @__PURE__ */ new Set([primary]);
|
|
936
|
+
const candidates = [primary];
|
|
937
|
+
for (const region of CANONICAL_MANAGEMENT_REGIONS) {
|
|
938
|
+
if (!seen.has(region)) {
|
|
939
|
+
seen.add(region);
|
|
940
|
+
candidates.push(region);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return candidates;
|
|
847
944
|
}
|
|
848
|
-
async function
|
|
849
|
-
const
|
|
850
|
-
const
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
945
|
+
async function requestManagement(auth, operation, path, method, body) {
|
|
946
|
+
const url = new URL(path, getKiroEndpoints(auth.region).management);
|
|
947
|
+
const request = {
|
|
948
|
+
method,
|
|
949
|
+
headers: {
|
|
950
|
+
Accept: "application/json",
|
|
951
|
+
...kiroAuthHeaders(auth.accessToken),
|
|
952
|
+
...kiroTokenTypeHeaders(auth.accessToken)
|
|
953
|
+
}
|
|
855
954
|
};
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
if (cachedModel) {
|
|
865
|
-
KIRO_MODEL_IDS.add(cachedModel.kiroModelId);
|
|
866
|
-
return cachedModel.kiroModelId;
|
|
955
|
+
if (method === "GET") {
|
|
956
|
+
for (const [name, value] of Object.entries(body)) {
|
|
957
|
+
if (value !== void 0)
|
|
958
|
+
url.searchParams.set(name, String(value));
|
|
959
|
+
}
|
|
960
|
+
} else {
|
|
961
|
+
request.headers = { ...request.headers, "Content-Type": "application/json" };
|
|
962
|
+
request.body = JSON.stringify(body);
|
|
867
963
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
if (!KIRO_MODEL_IDS.has(normalizedId)) {
|
|
874
|
-
throw new Error(`Unknown Kiro model ID: ${modelId}`);
|
|
964
|
+
let response;
|
|
965
|
+
try {
|
|
966
|
+
response = await fetch(url.toString(), request);
|
|
967
|
+
} catch (error2) {
|
|
968
|
+
throw new Error(`Kiro management ${operation} request failed in ${auth.region}`, { cause: error2 });
|
|
875
969
|
}
|
|
876
|
-
return
|
|
877
|
-
}
|
|
878
|
-
var KIRO_MANAGEMENT_CACHE_VERSION, KIRO_MANAGEMENT_CACHE_SOURCE, KIRO_MANAGEMENT_CACHE_PATH, CACHE_MAX_AGE_MS, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS, ZERO_COST, REASONING_FAMILY_MARKERS, VERIFIED_IMAGE_MODEL_IDS, bootstrapKiroModels, kiroModels, BOOTSTRAP_KIRO_MODEL_IDS, KIRO_MODEL_IDS;
|
|
879
|
-
var init_models = __esm({
|
|
880
|
-
"../kiro-core/dist/models.js"() {
|
|
881
|
-
"use strict";
|
|
882
|
-
init_effort();
|
|
883
|
-
init_kiro_cli();
|
|
884
|
-
init_management();
|
|
885
|
-
init_types();
|
|
886
|
-
init_endpoints();
|
|
887
|
-
KIRO_MANAGEMENT_CACHE_VERSION = 1;
|
|
888
|
-
KIRO_MANAGEMENT_CACHE_SOURCE = "ns-kiro-provider-management";
|
|
889
|
-
KIRO_MANAGEMENT_CACHE_PATH = join4(homedir4(), ".ns-kiro-provider-models-cache.json");
|
|
890
|
-
CACHE_MAX_AGE_MS = 36e5;
|
|
891
|
-
DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
892
|
-
DEFAULT_MAX_TOKENS = 8192;
|
|
893
|
-
ZERO_COST = Object.freeze({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
|
|
894
|
-
REASONING_FAMILY_MARKERS = ["opus", "sonnet", "fable", "coder", "deepseek", "gpt", "glm", "qwen"];
|
|
895
|
-
VERIFIED_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.6-luna"]);
|
|
896
|
-
bootstrapKiroModels = [
|
|
897
|
-
{
|
|
898
|
-
id: "claude-opus-5",
|
|
899
|
-
kiroModelId: "claude-opus-5",
|
|
900
|
-
name: "Claude Opus 5",
|
|
901
|
-
reasoning: true,
|
|
902
|
-
input: ["text", "image"],
|
|
903
|
-
cost: ZERO_COST,
|
|
904
|
-
contextWindow: 1e6,
|
|
905
|
-
maxTokens: 128e3,
|
|
906
|
-
firstTokenTimeout: 18e4
|
|
907
|
-
},
|
|
908
|
-
{
|
|
909
|
-
id: "claude-opus-4-8",
|
|
910
|
-
kiroModelId: "claude-opus-4.8",
|
|
911
|
-
name: "Claude Opus 4.8",
|
|
912
|
-
reasoning: true,
|
|
913
|
-
input: ["text", "image"],
|
|
914
|
-
cost: ZERO_COST,
|
|
915
|
-
contextWindow: 1e6,
|
|
916
|
-
maxTokens: 128e3,
|
|
917
|
-
firstTokenTimeout: 18e4
|
|
918
|
-
},
|
|
919
|
-
{
|
|
920
|
-
id: "claude-opus-4-7",
|
|
921
|
-
kiroModelId: "claude-opus-4.7",
|
|
922
|
-
name: "Claude Opus 4.7",
|
|
923
|
-
reasoning: true,
|
|
924
|
-
input: ["text", "image"],
|
|
925
|
-
cost: ZERO_COST,
|
|
926
|
-
contextWindow: 1e6,
|
|
927
|
-
maxTokens: 128e3,
|
|
928
|
-
firstTokenTimeout: 18e4
|
|
929
|
-
},
|
|
930
|
-
{
|
|
931
|
-
id: "claude-opus-4-6",
|
|
932
|
-
kiroModelId: "claude-opus-4.6",
|
|
933
|
-
name: "Claude Opus 4.6",
|
|
934
|
-
reasoning: true,
|
|
935
|
-
input: ["text", "image"],
|
|
936
|
-
cost: ZERO_COST,
|
|
937
|
-
contextWindow: 1e6,
|
|
938
|
-
maxTokens: 32768
|
|
939
|
-
},
|
|
940
|
-
{
|
|
941
|
-
id: "claude-opus-4-5",
|
|
942
|
-
kiroModelId: "claude-opus-4.5",
|
|
943
|
-
name: "Claude Opus 4.5",
|
|
944
|
-
reasoning: true,
|
|
945
|
-
input: ["text", "image"],
|
|
946
|
-
cost: ZERO_COST,
|
|
947
|
-
contextWindow: 2e5,
|
|
948
|
-
maxTokens: 64e3
|
|
949
|
-
},
|
|
950
|
-
{
|
|
951
|
-
id: "claude-sonnet-5",
|
|
952
|
-
kiroModelId: "claude-sonnet-5",
|
|
953
|
-
name: "Claude Sonnet 5",
|
|
954
|
-
reasoning: true,
|
|
955
|
-
input: ["text", "image"],
|
|
956
|
-
cost: ZERO_COST,
|
|
957
|
-
contextWindow: 1e6,
|
|
958
|
-
maxTokens: 65536
|
|
959
|
-
},
|
|
960
|
-
{
|
|
961
|
-
id: "claude-sonnet-4-6",
|
|
962
|
-
kiroModelId: "claude-sonnet-4.6",
|
|
963
|
-
name: "Claude Sonnet 4.6",
|
|
964
|
-
reasoning: true,
|
|
965
|
-
input: ["text", "image"],
|
|
966
|
-
cost: ZERO_COST,
|
|
967
|
-
contextWindow: 1e6,
|
|
968
|
-
maxTokens: 65536
|
|
969
|
-
},
|
|
970
|
-
{
|
|
971
|
-
id: "claude-sonnet-4-5",
|
|
972
|
-
kiroModelId: "claude-sonnet-4.5",
|
|
973
|
-
name: "Claude Sonnet 4.5",
|
|
974
|
-
reasoning: true,
|
|
975
|
-
input: ["text", "image"],
|
|
976
|
-
cost: ZERO_COST,
|
|
977
|
-
contextWindow: 2e5,
|
|
978
|
-
maxTokens: 65536
|
|
979
|
-
},
|
|
980
|
-
{
|
|
981
|
-
id: "claude-sonnet-4",
|
|
982
|
-
kiroModelId: "claude-sonnet-4",
|
|
983
|
-
name: "Claude Sonnet 4",
|
|
984
|
-
reasoning: true,
|
|
985
|
-
input: ["text", "image"],
|
|
986
|
-
cost: ZERO_COST,
|
|
987
|
-
contextWindow: 2e5,
|
|
988
|
-
maxTokens: 65536
|
|
989
|
-
},
|
|
990
|
-
{
|
|
991
|
-
id: "claude-haiku-4-5",
|
|
992
|
-
kiroModelId: "claude-haiku-4.5",
|
|
993
|
-
name: "Claude Haiku 4.5",
|
|
994
|
-
reasoning: false,
|
|
995
|
-
input: ["text", "image"],
|
|
996
|
-
cost: ZERO_COST,
|
|
997
|
-
contextWindow: 2e5,
|
|
998
|
-
maxTokens: 65536
|
|
999
|
-
},
|
|
1000
|
-
{
|
|
1001
|
-
id: "claude-fable-5",
|
|
1002
|
-
kiroModelId: "claude-fable-5",
|
|
1003
|
-
name: "Claude Fable 5",
|
|
1004
|
-
reasoning: true,
|
|
1005
|
-
input: ["text", "image"],
|
|
1006
|
-
cost: ZERO_COST,
|
|
1007
|
-
contextWindow: 1e6,
|
|
1008
|
-
maxTokens: 65536
|
|
1009
|
-
},
|
|
1010
|
-
{
|
|
1011
|
-
id: "gpt-5-6-luna",
|
|
1012
|
-
kiroModelId: "gpt-5.6-luna",
|
|
1013
|
-
name: "GPT-5.6 Luna",
|
|
1014
|
-
reasoning: true,
|
|
1015
|
-
input: ["text", "image"],
|
|
1016
|
-
cost: ZERO_COST,
|
|
1017
|
-
contextWindow: 272e3,
|
|
1018
|
-
maxTokens: 128e3
|
|
1019
|
-
},
|
|
1020
|
-
{
|
|
1021
|
-
id: "gpt-5-6-sol",
|
|
1022
|
-
kiroModelId: "gpt-5.6-sol",
|
|
1023
|
-
name: "GPT-5.6 Sol",
|
|
1024
|
-
reasoning: true,
|
|
1025
|
-
input: ["text"],
|
|
1026
|
-
cost: ZERO_COST,
|
|
1027
|
-
contextWindow: 272e3,
|
|
1028
|
-
maxTokens: 128e3
|
|
1029
|
-
},
|
|
1030
|
-
{
|
|
1031
|
-
id: "gpt-5-6-terra",
|
|
1032
|
-
kiroModelId: "gpt-5.6-terra",
|
|
1033
|
-
name: "GPT-5.6 Terra",
|
|
1034
|
-
reasoning: true,
|
|
1035
|
-
input: ["text"],
|
|
1036
|
-
cost: ZERO_COST,
|
|
1037
|
-
contextWindow: 272e3,
|
|
1038
|
-
maxTokens: 128e3
|
|
1039
|
-
},
|
|
1040
|
-
{
|
|
1041
|
-
id: "deepseek-3-2",
|
|
1042
|
-
kiroModelId: "deepseek-3.2",
|
|
1043
|
-
name: "DeepSeek 3.2",
|
|
1044
|
-
reasoning: true,
|
|
1045
|
-
input: ["text"],
|
|
1046
|
-
cost: ZERO_COST,
|
|
1047
|
-
contextWindow: 164e3,
|
|
1048
|
-
maxTokens: 8192
|
|
1049
|
-
},
|
|
1050
|
-
{
|
|
1051
|
-
id: "minimax-m2-5",
|
|
1052
|
-
kiroModelId: "minimax-m2.5",
|
|
1053
|
-
name: "MiniMax M2.5",
|
|
1054
|
-
reasoning: false,
|
|
1055
|
-
input: ["text"],
|
|
1056
|
-
cost: ZERO_COST,
|
|
1057
|
-
contextWindow: 196e3,
|
|
1058
|
-
maxTokens: 8192
|
|
1059
|
-
},
|
|
1060
|
-
{
|
|
1061
|
-
id: "minimax-m2-1",
|
|
1062
|
-
kiroModelId: "minimax-m2.1",
|
|
1063
|
-
name: "MiniMax M2.1",
|
|
1064
|
-
reasoning: false,
|
|
1065
|
-
input: ["text"],
|
|
1066
|
-
cost: ZERO_COST,
|
|
1067
|
-
contextWindow: 196e3,
|
|
1068
|
-
maxTokens: 8192
|
|
1069
|
-
},
|
|
1070
|
-
{
|
|
1071
|
-
id: "glm-5",
|
|
1072
|
-
kiroModelId: "glm-5",
|
|
1073
|
-
name: "GLM 5",
|
|
1074
|
-
reasoning: true,
|
|
1075
|
-
input: ["text"],
|
|
1076
|
-
cost: ZERO_COST,
|
|
1077
|
-
contextWindow: 2e5,
|
|
1078
|
-
maxTokens: 8192
|
|
1079
|
-
},
|
|
1080
|
-
{
|
|
1081
|
-
id: "qwen3-coder-next",
|
|
1082
|
-
kiroModelId: "qwen3-coder-next",
|
|
1083
|
-
name: "Qwen3 Coder Next",
|
|
1084
|
-
reasoning: true,
|
|
1085
|
-
input: ["text"],
|
|
1086
|
-
cost: ZERO_COST,
|
|
1087
|
-
contextWindow: 256e3,
|
|
1088
|
-
maxTokens: 8192
|
|
1089
|
-
},
|
|
1090
|
-
{
|
|
1091
|
-
id: "auto",
|
|
1092
|
-
kiroModelId: "auto",
|
|
1093
|
-
name: "Auto",
|
|
1094
|
-
reasoning: true,
|
|
1095
|
-
input: ["text", "image"],
|
|
1096
|
-
cost: ZERO_COST,
|
|
1097
|
-
contextWindow: 1e6,
|
|
1098
|
-
maxTokens: 65536
|
|
1099
|
-
}
|
|
1100
|
-
];
|
|
1101
|
-
kiroModels = bootstrapKiroModels.map((model) => ({
|
|
1102
|
-
...model,
|
|
1103
|
-
...applyEffortLadder(model.reasoning ? getKiroEffortConfig(model.additionalModelRequestFieldsSchema, model.kiroModelId) : void 0),
|
|
1104
|
-
...model.id.startsWith("claude-") ? { recoverTextToolCalls: false } : {}
|
|
1105
|
-
}));
|
|
1106
|
-
BOOTSTRAP_KIRO_MODEL_IDS = kiroModels.map((model) => model.kiroModelId);
|
|
1107
|
-
KIRO_MODEL_IDS = new Set(BOOTSTRAP_KIRO_MODEL_IDS);
|
|
1108
|
-
}
|
|
1109
|
-
});
|
|
1110
|
-
|
|
1111
|
-
// ../kiro-core/dist/oauth.js
|
|
1112
|
-
function kiroUserAgent(service, sdkVersion) {
|
|
1113
|
-
return {
|
|
1114
|
-
"User-Agent": `aws-sdk-js/3.714.0 os/macos/24.3.0 lang/js md/nodejs/22.14.0 api/${service}/3.714.0 exec-env/kiro-cli/2.7.0 m/E`,
|
|
1115
|
-
"amz-sdk-invocation-id": "00000000-0000-0000-0000-000000000000",
|
|
1116
|
-
"amz-sdk-request": `attempt=1; max=${sdkVersion}`
|
|
1117
|
-
};
|
|
1118
|
-
}
|
|
1119
|
-
function kiroAuthHeaders(token) {
|
|
1120
|
-
const headers = { Authorization: `Bearer ${token}` };
|
|
1121
|
-
if (isApiKey(token))
|
|
1122
|
-
headers.tokentype = "API_KEY";
|
|
1123
|
-
return headers;
|
|
1124
|
-
}
|
|
1125
|
-
function isApiKey(token) {
|
|
1126
|
-
return token.startsWith("ksk_");
|
|
1127
|
-
}
|
|
1128
|
-
async function loginKiroWithApiKey(apiKey, onProgress) {
|
|
1129
|
-
if (!apiKey.startsWith("ksk_")) {
|
|
1130
|
-
throw new Error("Invalid API key format. Kiro API keys start with 'ksk_'.");
|
|
1131
|
-
}
|
|
1132
|
-
onProgress?.("Validating API key...");
|
|
1133
|
-
const region = "us-east-1";
|
|
1134
|
-
const managementUrl = `https://management.${resolveApiRegion(region)}.kiro.dev/`;
|
|
1135
|
-
const response = await fetch(managementUrl, {
|
|
1136
|
-
method: "POST",
|
|
1137
|
-
headers: {
|
|
1138
|
-
"Content-Type": "application/x-amz-json-1.0",
|
|
1139
|
-
"X-Amz-Target": "AmazonCodeWhispererService.GetProfile",
|
|
1140
|
-
...kiroAuthHeaders(apiKey),
|
|
1141
|
-
...kiroUserAgent("codewhispererruntime", "F,C")
|
|
1142
|
-
},
|
|
1143
|
-
body: "{}"
|
|
1144
|
-
});
|
|
1145
|
-
if (!response.ok) {
|
|
1146
|
-
let detail = "";
|
|
1147
|
-
try {
|
|
1148
|
-
detail = await response.text();
|
|
1149
|
-
} catch {
|
|
1150
|
-
detail = "";
|
|
1151
|
-
}
|
|
1152
|
-
if (response.status === 401 || response.status === 403 || /Invalid token/i.test(detail)) {
|
|
1153
|
-
throw new Error("API key was rejected by Kiro. Check that the key is valid and not expired.");
|
|
1154
|
-
}
|
|
1155
|
-
throw new Error(`Kiro GetProfile failed: ${response.status} ${response.statusText} ${detail}`.trim());
|
|
1156
|
-
}
|
|
1157
|
-
const data = await response.json();
|
|
1158
|
-
const profileArn = data.profile?.arn;
|
|
1159
|
-
return {
|
|
1160
|
-
access: apiKey,
|
|
1161
|
-
refresh: `${apiKey}|apikey`,
|
|
1162
|
-
expires: Date.now() + 365 * 24 * 60 * 60 * 1e3,
|
|
1163
|
-
clientId: "",
|
|
1164
|
-
clientSecret: "",
|
|
1165
|
-
region,
|
|
1166
|
-
authMethod: "apikey",
|
|
1167
|
-
...profileArn ? { profileArn } : {}
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
async function refreshKiroToken(credentials) {
|
|
1171
|
-
const refreshed = await refreshKiroTokenInternal(credentials);
|
|
1172
|
-
if (!process.env.VITEST) {
|
|
1173
|
-
try {
|
|
1174
|
-
const { updateKiroModelsCache: updateKiroModelsCache2 } = await Promise.resolve().then(() => (init_models(), models_exports));
|
|
1175
|
-
const region = resolveApiRegion(refreshed.region);
|
|
1176
|
-
updateKiroModelsCache2(refreshed.access, region, refreshed.profileArn).catch((error2) => {
|
|
1177
|
-
console.warn(`[kiro-core] Failed to refresh Kiro model catalog in ${region}: ${formatSafeError(error2)}`);
|
|
1178
|
-
});
|
|
1179
|
-
} catch (error2) {
|
|
1180
|
-
console.warn(`[kiro-core] Failed to start Kiro model catalog refresh: ${formatSafeError(error2)}`);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
return refreshed;
|
|
1184
|
-
}
|
|
1185
|
-
async function refreshKiroTokenInternal(credentials) {
|
|
1186
|
-
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2, saveKiroCliCredentials: saveKiroCliCredentials2, getKiroCliSocialToken: getKiroCliSocialToken2, getKiroCliSocialTokenAllowExpired: getKiroCliSocialTokenAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
1187
|
-
const credentialAuthMethod = credentials.authMethod ?? (credentials.refresh.split("|").at(-1) === "desktop" ? "desktop" : "idc");
|
|
1188
|
-
const getValidCliCredentials = () => {
|
|
1189
|
-
if (credentialAuthMethod === "desktop")
|
|
1190
|
-
return getKiroCliSocialToken2();
|
|
1191
|
-
const cliCreds = getKiroCliCredentials2();
|
|
1192
|
-
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
1193
|
-
};
|
|
1194
|
-
const getExpiredCliCredentials = () => {
|
|
1195
|
-
if (credentialAuthMethod === "desktop")
|
|
1196
|
-
return getKiroCliSocialTokenAllowExpired2();
|
|
1197
|
-
const cliCreds = getKiroCliCredentialsAllowExpired2();
|
|
1198
|
-
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
1199
|
-
};
|
|
1200
|
-
if (credentials.authMethod === "apikey" || isApiKey(credentials.access))
|
|
1201
|
-
return credentials;
|
|
1202
|
-
if (credentialAuthMethod === "idc") {
|
|
1203
|
-
const ideCreds = getKiroIdeCredentials();
|
|
1204
|
-
if (ideCreds)
|
|
1205
|
-
return ideCreds;
|
|
1206
|
-
}
|
|
1207
|
-
const preCheckCreds = getValidCliCredentials();
|
|
1208
|
-
if (preCheckCreds)
|
|
1209
|
-
return preCheckCreds;
|
|
1210
|
-
try {
|
|
1211
|
-
const refreshed = await refreshKiroTokenDirect(credentials);
|
|
1212
|
-
saveKiroCliCredentials2(refreshed);
|
|
1213
|
-
return refreshed;
|
|
1214
|
-
} catch (refreshError) {
|
|
1215
|
-
const retryCreds = getValidCliCredentials();
|
|
1216
|
-
if (retryCreds)
|
|
1217
|
-
return retryCreds;
|
|
1218
|
-
const expiredCliCreds = getExpiredCliCredentials();
|
|
1219
|
-
if (expiredCliCreds && expiredCliCreds.refresh !== credentials.refresh) {
|
|
1220
|
-
try {
|
|
1221
|
-
const refreshedFromCli = await refreshKiroTokenDirect(expiredCliCreds);
|
|
1222
|
-
saveKiroCliCredentials2(refreshedFromCli);
|
|
1223
|
-
return refreshedFromCli;
|
|
1224
|
-
} catch {
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
const actualExpiry = credentials.expires + EXPIRES_BUFFER_MS;
|
|
1228
|
-
if (credentials.access && Date.now() < actualExpiry) {
|
|
1229
|
-
return { ...credentials, expires: actualExpiry };
|
|
1230
|
-
}
|
|
1231
|
-
throw refreshError;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
async function refreshKiroTokenDirect(credentials) {
|
|
1235
|
-
const parts = credentials.refresh.split("|");
|
|
1236
|
-
const refreshToken = parts[0] ?? "";
|
|
1237
|
-
const authMethod = parts[parts.length - 1] ?? "idc";
|
|
1238
|
-
const region = credentials.region || "us-east-1";
|
|
1239
|
-
if (authMethod === "apikey")
|
|
1240
|
-
return credentials;
|
|
1241
|
-
if (authMethod === "desktop") {
|
|
1242
|
-
const url = KIRO_DESKTOP_REFRESH_URL.replace("{region}", region);
|
|
1243
|
-
const response2 = await fetch(url, {
|
|
1244
|
-
method: "POST",
|
|
1245
|
-
headers: { "Content-Type": "application/json", "User-Agent": KIRO_DESKTOP_USER_AGENT },
|
|
1246
|
-
body: JSON.stringify({ refreshToken })
|
|
1247
|
-
});
|
|
1248
|
-
if (!response2.ok)
|
|
1249
|
-
throw new Error(`Desktop token refresh failed: ${response2.status}`);
|
|
1250
|
-
const data2 = await response2.json();
|
|
1251
|
-
if (!data2.accessToken)
|
|
1252
|
-
throw new Error("Desktop token refresh: missing accessToken");
|
|
1253
|
-
return {
|
|
1254
|
-
refresh: `${data2.refreshToken || refreshToken}|desktop`,
|
|
1255
|
-
access: data2.accessToken,
|
|
1256
|
-
expires: Date.now() + data2.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
1257
|
-
clientId: "",
|
|
1258
|
-
clientSecret: "",
|
|
1259
|
-
region,
|
|
1260
|
-
authMethod: "desktop",
|
|
1261
|
-
profileArn: data2.profileArn || credentials.profileArn,
|
|
1262
|
-
startUrl: credentials.startUrl
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
if (authMethod === "external-idp") {
|
|
1266
|
-
const idpClientId = parts[1] ?? "";
|
|
1267
|
-
const tokenEndpoint = parts[2] ?? "";
|
|
1268
|
-
if (!tokenEndpoint)
|
|
1269
|
-
throw new Error("External IdP token refresh: missing token endpoint");
|
|
1270
|
-
const response2 = await fetch(tokenEndpoint, {
|
|
1271
|
-
method: "POST",
|
|
1272
|
-
headers: {
|
|
1273
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
1274
|
-
Accept: "application/json",
|
|
1275
|
-
"User-Agent": "kiro-core"
|
|
1276
|
-
},
|
|
1277
|
-
body: new URLSearchParams({
|
|
1278
|
-
grant_type: "refresh_token",
|
|
1279
|
-
client_id: idpClientId,
|
|
1280
|
-
refresh_token: refreshToken
|
|
1281
|
-
}).toString()
|
|
1282
|
-
});
|
|
1283
|
-
if (!response2.ok)
|
|
1284
|
-
throw new Error(`External IdP token refresh failed: ${response2.status}`);
|
|
1285
|
-
const data2 = await response2.json();
|
|
1286
|
-
if (!data2.access_token)
|
|
1287
|
-
throw new Error("External IdP token refresh: missing access_token");
|
|
1288
|
-
const expiresIn = typeof data2.expires_in === "number" ? data2.expires_in : 3600;
|
|
1289
|
-
return {
|
|
1290
|
-
refresh: `${data2.refresh_token || refreshToken}|${idpClientId}|${tokenEndpoint}|external-idp`,
|
|
1291
|
-
access: data2.access_token,
|
|
1292
|
-
expires: Date.now() + expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
1293
|
-
clientId: idpClientId,
|
|
1294
|
-
clientSecret: "",
|
|
1295
|
-
region,
|
|
1296
|
-
authMethod: "external-idp",
|
|
1297
|
-
profileArn: credentials.profileArn
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1300
|
-
const clientId = parts[1] ?? "";
|
|
1301
|
-
const clientSecret = parts[2] ?? "";
|
|
1302
|
-
const ssoEndpoint = `https://oidc.${region}.amazonaws.com`;
|
|
1303
|
-
const response = await fetch(`${ssoEndpoint}/token`, {
|
|
1304
|
-
method: "POST",
|
|
1305
|
-
headers: { "Content-Type": "application/json", ...kiroUserAgent("ssooidc", "E") },
|
|
1306
|
-
body: JSON.stringify({ clientId, clientSecret, refreshToken, grantType: "refresh_token" })
|
|
1307
|
-
});
|
|
1308
|
-
if (!response.ok)
|
|
1309
|
-
throw new Error(`Token refresh failed: ${response.status}`);
|
|
1310
|
-
const data = await response.json();
|
|
1311
|
-
return {
|
|
1312
|
-
refresh: `${data.refreshToken}|${clientId}|${clientSecret}|idc`,
|
|
1313
|
-
access: data.accessToken,
|
|
1314
|
-
expires: Date.now() + data.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
1315
|
-
clientId,
|
|
1316
|
-
clientSecret,
|
|
1317
|
-
region,
|
|
1318
|
-
authMethod: "idc",
|
|
1319
|
-
profileArn: credentials.profileArn,
|
|
1320
|
-
startUrl: credentials.startUrl,
|
|
1321
|
-
isEnterprise: credentials.isEnterprise
|
|
1322
|
-
};
|
|
1323
|
-
}
|
|
1324
|
-
async function resolveKiroCredentials() {
|
|
1325
|
-
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
1326
|
-
const fresh = getKiroCliCredentials2() ?? getKiroIdeCredentials();
|
|
1327
|
-
if (fresh)
|
|
1328
|
-
return fresh;
|
|
1329
|
-
const stale = getKiroCliCredentialsAllowExpired2();
|
|
1330
|
-
if (!stale)
|
|
1331
|
-
return void 0;
|
|
1332
|
-
return refreshKiroToken(stale);
|
|
1333
|
-
}
|
|
1334
|
-
var KIRO_DESKTOP_REFRESH_URL, EXPIRES_BUFFER_MS, KIRO_DESKTOP_USER_AGENT;
|
|
1335
|
-
var init_oauth = __esm({
|
|
1336
|
-
"../kiro-core/dist/oauth.js"() {
|
|
1337
|
-
"use strict";
|
|
1338
|
-
init_debug();
|
|
1339
|
-
init_endpoints();
|
|
1340
|
-
init_kiro_ide();
|
|
1341
|
-
KIRO_DESKTOP_REFRESH_URL = "https://prod.{region}.auth.desktop.kiro.dev/refreshToken";
|
|
1342
|
-
EXPIRES_BUFFER_MS = 5 * 60 * 1e3;
|
|
1343
|
-
KIRO_DESKTOP_USER_AGENT = "Kiro-Desktop/0.2.13 (darwin; arm64)";
|
|
1344
|
-
}
|
|
1345
|
-
});
|
|
1346
|
-
|
|
1347
|
-
// ../kiro-core/dist/token-type.js
|
|
1348
|
-
function isExternalIdpAccessToken(accessToken) {
|
|
1349
|
-
if (typeof accessToken !== "string")
|
|
1350
|
-
return false;
|
|
1351
|
-
const segments = accessToken.split(".");
|
|
1352
|
-
if (segments.length !== 3)
|
|
1353
|
-
return false;
|
|
1354
|
-
const payloadSegment = segments[1];
|
|
1355
|
-
if (!payloadSegment)
|
|
1356
|
-
return false;
|
|
1357
|
-
try {
|
|
1358
|
-
const payload = JSON.parse(Buffer.from(payloadSegment.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf-8"));
|
|
1359
|
-
return payload.aud === EXTERNAL_IDP_AUDIENCE;
|
|
1360
|
-
} catch {
|
|
1361
|
-
return false;
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
function kiroTokenTypeHeaders(accessToken) {
|
|
1365
|
-
return isExternalIdpAccessToken(accessToken) ? { tokentype: "EXTERNAL_IDP" } : {};
|
|
1366
|
-
}
|
|
1367
|
-
var EXTERNAL_IDP_AUDIENCE;
|
|
1368
|
-
var init_token_type = __esm({
|
|
1369
|
-
"../kiro-core/dist/token-type.js"() {
|
|
1370
|
-
"use strict";
|
|
1371
|
-
EXTERNAL_IDP_AUDIENCE = "api://kiro";
|
|
1372
|
-
}
|
|
1373
|
-
});
|
|
1374
|
-
|
|
1375
|
-
// ../kiro-core/dist/management.js
|
|
1376
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
1377
|
-
function candidateManagementRegions(primary) {
|
|
1378
|
-
const seen = /* @__PURE__ */ new Set([primary]);
|
|
1379
|
-
const candidates = [primary];
|
|
1380
|
-
for (const region of CANONICAL_MANAGEMENT_REGIONS) {
|
|
1381
|
-
if (!seen.has(region)) {
|
|
1382
|
-
seen.add(region);
|
|
1383
|
-
candidates.push(region);
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
return candidates;
|
|
1387
|
-
}
|
|
1388
|
-
async function requestManagement(auth, operation, path, method, body) {
|
|
1389
|
-
const url = new URL(path, getKiroEndpoints(auth.region).management);
|
|
1390
|
-
const request = {
|
|
1391
|
-
method,
|
|
1392
|
-
headers: {
|
|
1393
|
-
Accept: "application/json",
|
|
1394
|
-
...kiroAuthHeaders(auth.accessToken),
|
|
1395
|
-
...kiroTokenTypeHeaders(auth.accessToken)
|
|
1396
|
-
}
|
|
1397
|
-
};
|
|
1398
|
-
if (method === "GET") {
|
|
1399
|
-
for (const [name, value] of Object.entries(body)) {
|
|
1400
|
-
if (value !== void 0)
|
|
1401
|
-
url.searchParams.set(name, String(value));
|
|
1402
|
-
}
|
|
1403
|
-
} else {
|
|
1404
|
-
request.headers = { ...request.headers, "Content-Type": "application/json" };
|
|
1405
|
-
request.body = JSON.stringify(body);
|
|
1406
|
-
}
|
|
1407
|
-
let response;
|
|
1408
|
-
try {
|
|
1409
|
-
response = await fetch(url.toString(), request);
|
|
1410
|
-
} catch (error2) {
|
|
1411
|
-
throw new Error(`Kiro management ${operation} request failed in ${auth.region}`, { cause: error2 });
|
|
1412
|
-
}
|
|
1413
|
-
return parseManagementResponse(response, operation, auth.region);
|
|
970
|
+
return parseManagementResponse(response, operation, auth.region);
|
|
1414
971
|
}
|
|
1415
972
|
function profileCacheKey(auth) {
|
|
1416
|
-
const tokenHash =
|
|
973
|
+
const tokenHash = createHash("sha256").update(auth.accessToken).digest("base64url");
|
|
1417
974
|
return `${auth.region}:${tokenHash}`;
|
|
1418
975
|
}
|
|
1419
976
|
async function getApiKeyProfileArn(accessToken) {
|
|
@@ -1517,75 +1074,544 @@ async function resolveKiroProfileArn(auth, providedArn) {
|
|
|
1517
1074
|
pendingProfileRequests.delete(key);
|
|
1518
1075
|
}
|
|
1519
1076
|
}
|
|
1520
|
-
async function listAvailableModels(auth, profileArn) {
|
|
1521
|
-
const response = await requestManagement(auth, "ListAvailableModels", LIST_MODELS_PATH, "GET", {
|
|
1522
|
-
origin: "KIRO_CLI",
|
|
1523
|
-
profileArn
|
|
1524
|
-
});
|
|
1525
|
-
if (!Array.isArray(response.models) || response.models.length === 0) {
|
|
1526
|
-
throw new Error(`Kiro management ListAvailableModels returned no models in ${auth.region}`);
|
|
1077
|
+
async function listAvailableModels(auth, profileArn) {
|
|
1078
|
+
const response = await requestManagement(auth, "ListAvailableModels", LIST_MODELS_PATH, "GET", {
|
|
1079
|
+
origin: "KIRO_CLI",
|
|
1080
|
+
profileArn
|
|
1081
|
+
});
|
|
1082
|
+
if (!Array.isArray(response.models) || response.models.length === 0) {
|
|
1083
|
+
throw new Error(`Kiro management ListAvailableModels returned no models in ${auth.region}`);
|
|
1084
|
+
}
|
|
1085
|
+
if (response.models.some((model) => !model || typeof model.modelId !== "string" || !model.modelId)) {
|
|
1086
|
+
throw new Error(`Kiro management ListAvailableModels returned an invalid catalog in ${auth.region}`);
|
|
1087
|
+
}
|
|
1088
|
+
return response;
|
|
1089
|
+
}
|
|
1090
|
+
async function fetchKiroModelCatalog(auth, providedProfileArn) {
|
|
1091
|
+
const profileArn = await resolveKiroProfileArn(auth, providedProfileArn);
|
|
1092
|
+
const region = isApiKey(auth.accessToken) ? API_KEY_REGION : profileRegionCache.get(profileCacheKey(auth)) ?? auth.region;
|
|
1093
|
+
if (region !== auth.region) {
|
|
1094
|
+
return listAvailableModels({ ...auth, region }, profileArn);
|
|
1095
|
+
}
|
|
1096
|
+
return listAvailableModels(auth, profileArn);
|
|
1097
|
+
}
|
|
1098
|
+
async function getUsageLimits(auth, request) {
|
|
1099
|
+
const operation = "GetUsageLimits";
|
|
1100
|
+
const url = new URL("Get-Usage-Limits", getKiroEndpoints(auth.region).management);
|
|
1101
|
+
for (const [name, value] of Object.entries(request)) {
|
|
1102
|
+
if (value !== void 0)
|
|
1103
|
+
url.searchParams.set(name, String(value));
|
|
1104
|
+
}
|
|
1105
|
+
let response;
|
|
1106
|
+
try {
|
|
1107
|
+
response = await fetch(url.toString(), {
|
|
1108
|
+
method: "GET",
|
|
1109
|
+
headers: {
|
|
1110
|
+
Accept: "application/json",
|
|
1111
|
+
...kiroAuthHeaders(auth.accessToken),
|
|
1112
|
+
...kiroTokenTypeHeaders(auth.accessToken),
|
|
1113
|
+
"User-Agent": "ns-kiro-provider"
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
} catch (error2) {
|
|
1117
|
+
throw new Error(`Kiro management ${operation} request failed in ${auth.region}`, { cause: error2 });
|
|
1118
|
+
}
|
|
1119
|
+
return parseManagementResponse(response, operation, auth.region);
|
|
1120
|
+
}
|
|
1121
|
+
var LIST_PROFILES_PATH, LIST_MODELS_PATH, GET_PROFILE_TARGET, API_KEY_REGION, profileArnCache, pendingProfileRequests, profileRegionCache, CANONICAL_MANAGEMENT_REGIONS, ENV_PROFILE_ARN, KiroManagementHttpError;
|
|
1122
|
+
var init_management = __esm({
|
|
1123
|
+
"../kiro-core/dist/management.js"() {
|
|
1124
|
+
"use strict";
|
|
1125
|
+
init_debug();
|
|
1126
|
+
init_endpoints();
|
|
1127
|
+
init_oauth();
|
|
1128
|
+
init_token_type();
|
|
1129
|
+
LIST_PROFILES_PATH = "List-Available-Profiles";
|
|
1130
|
+
LIST_MODELS_PATH = "List-Available-Models";
|
|
1131
|
+
GET_PROFILE_TARGET = "AmazonCodeWhispererService.GetProfile";
|
|
1132
|
+
API_KEY_REGION = "us-east-1";
|
|
1133
|
+
profileArnCache = /* @__PURE__ */ new Map();
|
|
1134
|
+
pendingProfileRequests = /* @__PURE__ */ new Map();
|
|
1135
|
+
profileRegionCache = /* @__PURE__ */ new Map();
|
|
1136
|
+
CANONICAL_MANAGEMENT_REGIONS = ["us-east-1", "eu-central-1"];
|
|
1137
|
+
ENV_PROFILE_ARN = "KIRO_PROFILE_ARN";
|
|
1138
|
+
KiroManagementHttpError = class extends Error {
|
|
1139
|
+
status;
|
|
1140
|
+
constructor(message, status) {
|
|
1141
|
+
super(message);
|
|
1142
|
+
this.status = status;
|
|
1143
|
+
this.name = "KiroManagementHttpError";
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
// ../kiro-core/dist/models.js
|
|
1150
|
+
var models_exports = {};
|
|
1151
|
+
__export(models_exports, {
|
|
1152
|
+
KIRO_MANAGEMENT_CACHE_PATH: () => KIRO_MANAGEMENT_CACHE_PATH,
|
|
1153
|
+
KIRO_MANAGEMENT_CACHE_SOURCE: () => KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1154
|
+
KIRO_MANAGEMENT_CACHE_VERSION: () => KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1155
|
+
KIRO_MODEL_IDS: () => KIRO_MODEL_IDS,
|
|
1156
|
+
applyEffortLadder: () => applyEffortLadder,
|
|
1157
|
+
getCachedModels: () => getCachedModels,
|
|
1158
|
+
isCacheStale: () => isCacheStale,
|
|
1159
|
+
kiroModels: () => kiroModels,
|
|
1160
|
+
loadCachedModelIds: () => loadCachedModelIds,
|
|
1161
|
+
mapKiroCatalogModels: () => mapKiroCatalogModels,
|
|
1162
|
+
resolveApiRegion: () => resolveApiRegion,
|
|
1163
|
+
resolveKiroModel: () => resolveKiroModel,
|
|
1164
|
+
updateKiroModelsCache: () => updateKiroModelsCache
|
|
1165
|
+
});
|
|
1166
|
+
import { randomUUID } from "node:crypto";
|
|
1167
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
1168
|
+
import { homedir as homedir4 } from "node:os";
|
|
1169
|
+
import { join as join4 } from "node:path";
|
|
1170
|
+
function isRecord2(value) {
|
|
1171
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1172
|
+
}
|
|
1173
|
+
function isPositiveNumber(value) {
|
|
1174
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
1175
|
+
}
|
|
1176
|
+
function isEffortList(value) {
|
|
1177
|
+
return Array.isArray(value) && value.length > 0 && value.every((effort) => KIRO_EFFORT_ORDER.includes(effort));
|
|
1178
|
+
}
|
|
1179
|
+
function isEffortMap(value) {
|
|
1180
|
+
return isRecord2(value) && Object.values(value).every((mapped) => typeof mapped === "string");
|
|
1181
|
+
}
|
|
1182
|
+
function isCachedKiroModel(value) {
|
|
1183
|
+
if (!isRecord2(value))
|
|
1184
|
+
return false;
|
|
1185
|
+
const cost = value.cost;
|
|
1186
|
+
const input = value.input;
|
|
1187
|
+
const schema = value.additionalModelRequestFieldsSchema;
|
|
1188
|
+
const tokenLimits = value.tokenLimits;
|
|
1189
|
+
return typeof value.id === "string" && value.id.length > 0 && typeof value.kiroModelId === "string" && value.kiroModelId.length > 0 && typeof value.name === "string" && value.name.length > 0 && typeof value.reasoning === "boolean" && Array.isArray(input) && input.length > 0 && input.every((modality) => modality === "text" || modality === "image") && isRecord2(cost) && typeof cost.input === "number" && typeof cost.output === "number" && typeof cost.cacheRead === "number" && typeof cost.cacheWrite === "number" && isPositiveNumber(value.contextWindow) && isPositiveNumber(value.maxTokens) && (value.efforts === void 0 || isEffortList(value.efforts)) && (value.effortMap === void 0 || isEffortMap(value.effortMap)) && (schema === void 0 || isRecord2(schema)) && (tokenLimits === void 0 || isRecord2(tokenLimits)) && (value.firstTokenTimeout === void 0 || isPositiveNumber(value.firstTokenTimeout)) && (value.rateMultiplier === void 0 || isPositiveNumber(value.rateMultiplier)) && (value.rateUnit === void 0 || typeof value.rateUnit === "string");
|
|
1190
|
+
}
|
|
1191
|
+
function parseManagementCache(raw) {
|
|
1192
|
+
let value;
|
|
1193
|
+
try {
|
|
1194
|
+
value = JSON.parse(raw);
|
|
1195
|
+
} catch {
|
|
1196
|
+
return void 0;
|
|
1197
|
+
}
|
|
1198
|
+
if (!isRecord2(value) || value.version !== KIRO_MANAGEMENT_CACHE_VERSION || value.source !== KIRO_MANAGEMENT_CACHE_SOURCE || !isRecord2(value.regions)) {
|
|
1199
|
+
return void 0;
|
|
1200
|
+
}
|
|
1201
|
+
const regions = {};
|
|
1202
|
+
for (const [region, rawEntry] of Object.entries(value.regions)) {
|
|
1203
|
+
if (!isRecord2(rawEntry) || rawEntry.region !== region || !isPositiveNumber(rawEntry.fetchedAt) || !Array.isArray(rawEntry.models) || rawEntry.models.length === 0 || !rawEntry.models.every(isCachedKiroModel)) {
|
|
1204
|
+
return void 0;
|
|
1205
|
+
}
|
|
1206
|
+
const modelIds = /* @__PURE__ */ new Set();
|
|
1207
|
+
for (const model of rawEntry.models) {
|
|
1208
|
+
if (modelIds.has(model.id))
|
|
1209
|
+
return void 0;
|
|
1210
|
+
modelIds.add(model.id);
|
|
1211
|
+
}
|
|
1212
|
+
regions[region] = rawEntry;
|
|
1213
|
+
}
|
|
1214
|
+
return {
|
|
1215
|
+
version: KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1216
|
+
source: KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1217
|
+
regions
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function readManagementCache() {
|
|
1221
|
+
if (!existsSync3(KIRO_MANAGEMENT_CACHE_PATH))
|
|
1222
|
+
return void 0;
|
|
1223
|
+
try {
|
|
1224
|
+
return parseManagementCache(readFileSync2(KIRO_MANAGEMENT_CACHE_PATH, "utf-8"));
|
|
1225
|
+
} catch {
|
|
1226
|
+
return void 0;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function writeManagementCache(cache) {
|
|
1230
|
+
const temporaryPath = `${KIRO_MANAGEMENT_CACHE_PATH}.${process.pid}.${randomUUID()}.tmp`;
|
|
1231
|
+
try {
|
|
1232
|
+
writeFileSync(temporaryPath, JSON.stringify(cache, null, 2), "utf-8");
|
|
1233
|
+
renameSync(temporaryPath, KIRO_MANAGEMENT_CACHE_PATH);
|
|
1234
|
+
} finally {
|
|
1235
|
+
rmSync(temporaryPath, { force: true });
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
function toLocalModelId(kiroModelId) {
|
|
1239
|
+
return kiroModelId.replace(/(\d)\.(\d)/g, "$1-$2");
|
|
1240
|
+
}
|
|
1241
|
+
function humanizeModelId(modelId) {
|
|
1242
|
+
return modelId.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1243
|
+
}
|
|
1244
|
+
function applyEffortLadder(config) {
|
|
1245
|
+
if (!config || config.values.length === 0)
|
|
1246
|
+
return {};
|
|
1247
|
+
const efforts = KIRO_EFFORT_ORDER.filter((effort) => config.values.includes(effort));
|
|
1248
|
+
if (efforts.length === 0)
|
|
1249
|
+
return {};
|
|
1250
|
+
return { efforts, ...config.summarizedThinking ? { supportsSummarizedThinking: true } : {} };
|
|
1251
|
+
}
|
|
1252
|
+
function hasReasoningFamilyFallback(modelId) {
|
|
1253
|
+
const normalizedId = modelId.toLowerCase();
|
|
1254
|
+
return normalizedId === "auto" || REASONING_FAMILY_MARKERS.some((marker) => normalizedId.includes(marker));
|
|
1255
|
+
}
|
|
1256
|
+
function hasVerifiedImageInput(kiroModelId) {
|
|
1257
|
+
return kiroModelId.startsWith("claude-") || VERIFIED_IMAGE_MODEL_IDS.has(kiroModelId.toLowerCase());
|
|
1258
|
+
}
|
|
1259
|
+
function applyVerifiedCapabilities(model) {
|
|
1260
|
+
if (!hasVerifiedImageInput(model.kiroModelId) || model.input.includes("image"))
|
|
1261
|
+
return model;
|
|
1262
|
+
return { ...model, input: ["text", "image"] };
|
|
1263
|
+
}
|
|
1264
|
+
function validateCatalogMetadata(model) {
|
|
1265
|
+
const rawSchema = model.additionalModelRequestFieldsSchema;
|
|
1266
|
+
const schema = rawSchema ?? void 0;
|
|
1267
|
+
if (schema !== void 0 && !isRecord2(schema)) {
|
|
1268
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has an invalid request-fields schema`);
|
|
1527
1269
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1270
|
+
const tokenLimits = model.tokenLimits;
|
|
1271
|
+
if (tokenLimits !== void 0 && !isRecord2(tokenLimits)) {
|
|
1272
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
1530
1273
|
}
|
|
1531
|
-
|
|
1274
|
+
if (tokenLimits && (tokenLimits.maxInputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxInputTokens) || tokenLimits.maxOutputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxOutputTokens))) {
|
|
1275
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
1276
|
+
}
|
|
1277
|
+
return { schema, tokenLimits };
|
|
1532
1278
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
if (region !== auth.region) {
|
|
1537
|
-
return listAvailableModels({ ...auth, region }, profileArn);
|
|
1279
|
+
function mapKiroCatalogModels(catalogModels, region, rates) {
|
|
1280
|
+
if (catalogModels.length === 0) {
|
|
1281
|
+
throw new Error(`Kiro management catalog returned no models in ${region}`);
|
|
1538
1282
|
}
|
|
1539
|
-
|
|
1283
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
1284
|
+
return catalogModels.map((catalogModel) => {
|
|
1285
|
+
const kiroModelId = catalogModel.modelId;
|
|
1286
|
+
if (!kiroModelId || kiroModelId.trim() !== kiroModelId) {
|
|
1287
|
+
throw new Error(`Kiro management catalog returned an invalid model ID in ${region}`);
|
|
1288
|
+
}
|
|
1289
|
+
const id = toLocalModelId(kiroModelId);
|
|
1290
|
+
if (seenIds.has(id)) {
|
|
1291
|
+
throw new Error(`Kiro management catalog contains conflicting model ID ${id} in ${region}`);
|
|
1292
|
+
}
|
|
1293
|
+
seenIds.add(id);
|
|
1294
|
+
const existing = kiroModels.find((model) => model.id === id);
|
|
1295
|
+
const rate = rates?.get(kiroModelId);
|
|
1296
|
+
const { schema, tokenLimits } = validateCatalogMetadata(catalogModel);
|
|
1297
|
+
const effortConfig = getKiroEffortConfig(schema, kiroModelId);
|
|
1298
|
+
const catalogName = typeof catalogModel.displayName === "string" && catalogModel.displayName.length > 0 ? catalogModel.displayName : void 0;
|
|
1299
|
+
return {
|
|
1300
|
+
id,
|
|
1301
|
+
kiroModelId,
|
|
1302
|
+
// Humanize the wire id, not the local one: `toLocalModelId` rewrites
|
|
1303
|
+
// `5.1` as `5-1`, and a display name derived from it loses the dot —
|
|
1304
|
+
// "Claude Fable 5 1" instead of "Claude Fable 5.1".
|
|
1305
|
+
name: catalogName ?? existing?.name ?? humanizeModelId(kiroModelId),
|
|
1306
|
+
region,
|
|
1307
|
+
// Deliberately schema-only: when a schema exists the resolver returns
|
|
1308
|
+
// `deriveKiroEffort(schema)`, and when it does not the family-marker guess
|
|
1309
|
+
// decides. The fallback tier feeds the ladders, not this flag.
|
|
1310
|
+
reasoning: schema !== void 0 && effortConfig !== void 0 || schema === void 0 && hasReasoningFamilyFallback(id),
|
|
1311
|
+
...applyEffortLadder(effortConfig),
|
|
1312
|
+
input: existing ? [...existing.input] : hasVerifiedImageInput(kiroModelId) ? ["text", "image"] : ["text"],
|
|
1313
|
+
...id.startsWith("claude-") ? { recoverTextToolCalls: false } : {},
|
|
1314
|
+
cost: ZERO_COST,
|
|
1315
|
+
...rate ? { rateMultiplier: rate.multiplier, ...rate.unit ? { rateUnit: rate.unit } : {} } : {},
|
|
1316
|
+
contextWindow: tokenLimits?.maxInputTokens ?? DEFAULT_CONTEXT_WINDOW,
|
|
1317
|
+
maxTokens: tokenLimits?.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
1318
|
+
...existing?.firstTokenTimeout ? { firstTokenTimeout: existing.firstTokenTimeout } : {},
|
|
1319
|
+
...schema ? { additionalModelRequestFieldsSchema: schema } : {},
|
|
1320
|
+
...tokenLimits ? { tokenLimits } : {}
|
|
1321
|
+
};
|
|
1322
|
+
});
|
|
1540
1323
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1324
|
+
function refreshKnownModelIds(cache) {
|
|
1325
|
+
KIRO_MODEL_IDS.clear();
|
|
1326
|
+
for (const modelId of BOOTSTRAP_KIRO_MODEL_IDS)
|
|
1327
|
+
KIRO_MODEL_IDS.add(modelId);
|
|
1328
|
+
if (!cache)
|
|
1329
|
+
return;
|
|
1330
|
+
for (const entry of Object.values(cache.regions)) {
|
|
1331
|
+
for (const model of entry.models)
|
|
1332
|
+
KIRO_MODEL_IDS.add(model.kiroModelId);
|
|
1547
1333
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1334
|
+
}
|
|
1335
|
+
function loadCachedModelIds() {
|
|
1336
|
+
refreshKnownModelIds(readManagementCache());
|
|
1337
|
+
}
|
|
1338
|
+
function getCachedModels(region) {
|
|
1339
|
+
const cache = readManagementCache();
|
|
1340
|
+
refreshKnownModelIds(cache);
|
|
1341
|
+
const models = cache?.regions[region]?.models ?? kiroModels;
|
|
1342
|
+
let changed = false;
|
|
1343
|
+
const corrected = models.map((model) => {
|
|
1344
|
+
const result = applyVerifiedCapabilities(model);
|
|
1345
|
+
if (result !== model)
|
|
1346
|
+
changed = true;
|
|
1347
|
+
return result;
|
|
1348
|
+
});
|
|
1349
|
+
return changed ? corrected : models;
|
|
1350
|
+
}
|
|
1351
|
+
function isCacheStale(region) {
|
|
1352
|
+
const entry = readManagementCache()?.regions[region];
|
|
1353
|
+
return !entry || Date.now() - entry.fetchedAt > CACHE_MAX_AGE_MS;
|
|
1354
|
+
}
|
|
1355
|
+
async function updateKiroModelsCache(accessToken, region, profileArn) {
|
|
1356
|
+
const response = await fetchKiroModelCatalog({ accessToken, region }, profileArn);
|
|
1357
|
+
const models = mapKiroCatalogModels(response.models, region, getKiroCliModelRates());
|
|
1358
|
+
const cache = readManagementCache() ?? {
|
|
1359
|
+
version: KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1360
|
+
source: KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1361
|
+
regions: {}
|
|
1362
|
+
};
|
|
1363
|
+
cache.regions[region] = { region, fetchedAt: Date.now(), models };
|
|
1364
|
+
writeManagementCache(cache);
|
|
1365
|
+
refreshKnownModelIds(cache);
|
|
1366
|
+
}
|
|
1367
|
+
function resolveKiroModel(modelId, exactKiroModelId) {
|
|
1368
|
+
if (exactKiroModelId)
|
|
1369
|
+
return exactKiroModelId;
|
|
1370
|
+
const cachedModel = Object.values(readManagementCache()?.regions ?? {}).flatMap((entry) => entry.models).find((model) => model.id === modelId);
|
|
1371
|
+
if (cachedModel) {
|
|
1372
|
+
KIRO_MODEL_IDS.add(cachedModel.kiroModelId);
|
|
1373
|
+
return cachedModel.kiroModelId;
|
|
1561
1374
|
}
|
|
1562
|
-
|
|
1375
|
+
const bootstrapModel = kiroModels.find((model) => model.id === modelId);
|
|
1376
|
+
if (bootstrapModel)
|
|
1377
|
+
return bootstrapModel.kiroModelId;
|
|
1378
|
+
const normalizedId = modelId.replace(/(\d)-(\d)/g, "$1.$2");
|
|
1379
|
+
loadCachedModelIds();
|
|
1380
|
+
if (!KIRO_MODEL_IDS.has(normalizedId)) {
|
|
1381
|
+
throw new Error(`Unknown Kiro model ID: ${modelId}`);
|
|
1382
|
+
}
|
|
1383
|
+
return normalizedId;
|
|
1563
1384
|
}
|
|
1564
|
-
var
|
|
1565
|
-
var
|
|
1566
|
-
"../kiro-core/dist/
|
|
1385
|
+
var KIRO_MANAGEMENT_CACHE_VERSION, KIRO_MANAGEMENT_CACHE_SOURCE, KIRO_MANAGEMENT_CACHE_PATH, CACHE_MAX_AGE_MS, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS, ZERO_COST, REASONING_FAMILY_MARKERS, VERIFIED_IMAGE_MODEL_IDS, bootstrapKiroModels, kiroModels, BOOTSTRAP_KIRO_MODEL_IDS, KIRO_MODEL_IDS;
|
|
1386
|
+
var init_models = __esm({
|
|
1387
|
+
"../kiro-core/dist/models.js"() {
|
|
1567
1388
|
"use strict";
|
|
1568
|
-
|
|
1389
|
+
init_effort();
|
|
1390
|
+
init_kiro_cli();
|
|
1391
|
+
init_management();
|
|
1392
|
+
init_types();
|
|
1569
1393
|
init_endpoints();
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1394
|
+
KIRO_MANAGEMENT_CACHE_VERSION = 1;
|
|
1395
|
+
KIRO_MANAGEMENT_CACHE_SOURCE = "ns-kiro-provider-management";
|
|
1396
|
+
KIRO_MANAGEMENT_CACHE_PATH = join4(homedir4(), ".ns-kiro-provider-models-cache.json");
|
|
1397
|
+
CACHE_MAX_AGE_MS = 36e5;
|
|
1398
|
+
DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
1399
|
+
DEFAULT_MAX_TOKENS = 8192;
|
|
1400
|
+
ZERO_COST = Object.freeze({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
|
|
1401
|
+
REASONING_FAMILY_MARKERS = ["opus", "sonnet", "fable", "coder", "deepseek", "gpt", "glm", "qwen"];
|
|
1402
|
+
VERIFIED_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.6-luna"]);
|
|
1403
|
+
bootstrapKiroModels = [
|
|
1404
|
+
{
|
|
1405
|
+
id: "claude-opus-5",
|
|
1406
|
+
kiroModelId: "claude-opus-5",
|
|
1407
|
+
name: "Claude Opus 5",
|
|
1408
|
+
reasoning: true,
|
|
1409
|
+
input: ["text", "image"],
|
|
1410
|
+
cost: ZERO_COST,
|
|
1411
|
+
contextWindow: 1e6,
|
|
1412
|
+
maxTokens: 128e3,
|
|
1413
|
+
firstTokenTimeout: 18e4
|
|
1414
|
+
},
|
|
1415
|
+
{
|
|
1416
|
+
id: "claude-opus-4-8",
|
|
1417
|
+
kiroModelId: "claude-opus-4.8",
|
|
1418
|
+
name: "Claude Opus 4.8",
|
|
1419
|
+
reasoning: true,
|
|
1420
|
+
input: ["text", "image"],
|
|
1421
|
+
cost: ZERO_COST,
|
|
1422
|
+
contextWindow: 1e6,
|
|
1423
|
+
maxTokens: 128e3,
|
|
1424
|
+
firstTokenTimeout: 18e4
|
|
1425
|
+
},
|
|
1426
|
+
{
|
|
1427
|
+
id: "claude-opus-4-7",
|
|
1428
|
+
kiroModelId: "claude-opus-4.7",
|
|
1429
|
+
name: "Claude Opus 4.7",
|
|
1430
|
+
reasoning: true,
|
|
1431
|
+
input: ["text", "image"],
|
|
1432
|
+
cost: ZERO_COST,
|
|
1433
|
+
contextWindow: 1e6,
|
|
1434
|
+
maxTokens: 128e3,
|
|
1435
|
+
firstTokenTimeout: 18e4
|
|
1436
|
+
},
|
|
1437
|
+
{
|
|
1438
|
+
id: "claude-opus-4-6",
|
|
1439
|
+
kiroModelId: "claude-opus-4.6",
|
|
1440
|
+
name: "Claude Opus 4.6",
|
|
1441
|
+
reasoning: true,
|
|
1442
|
+
input: ["text", "image"],
|
|
1443
|
+
cost: ZERO_COST,
|
|
1444
|
+
contextWindow: 1e6,
|
|
1445
|
+
maxTokens: 32768
|
|
1446
|
+
},
|
|
1447
|
+
{
|
|
1448
|
+
id: "claude-opus-4-5",
|
|
1449
|
+
kiroModelId: "claude-opus-4.5",
|
|
1450
|
+
name: "Claude Opus 4.5",
|
|
1451
|
+
reasoning: true,
|
|
1452
|
+
input: ["text", "image"],
|
|
1453
|
+
cost: ZERO_COST,
|
|
1454
|
+
contextWindow: 2e5,
|
|
1455
|
+
maxTokens: 64e3
|
|
1456
|
+
},
|
|
1457
|
+
{
|
|
1458
|
+
id: "claude-sonnet-5",
|
|
1459
|
+
kiroModelId: "claude-sonnet-5",
|
|
1460
|
+
name: "Claude Sonnet 5",
|
|
1461
|
+
reasoning: true,
|
|
1462
|
+
input: ["text", "image"],
|
|
1463
|
+
cost: ZERO_COST,
|
|
1464
|
+
contextWindow: 1e6,
|
|
1465
|
+
maxTokens: 65536
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
id: "claude-sonnet-4-6",
|
|
1469
|
+
kiroModelId: "claude-sonnet-4.6",
|
|
1470
|
+
name: "Claude Sonnet 4.6",
|
|
1471
|
+
reasoning: true,
|
|
1472
|
+
input: ["text", "image"],
|
|
1473
|
+
cost: ZERO_COST,
|
|
1474
|
+
contextWindow: 1e6,
|
|
1475
|
+
maxTokens: 65536
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
id: "claude-sonnet-4-5",
|
|
1479
|
+
kiroModelId: "claude-sonnet-4.5",
|
|
1480
|
+
name: "Claude Sonnet 4.5",
|
|
1481
|
+
reasoning: true,
|
|
1482
|
+
input: ["text", "image"],
|
|
1483
|
+
cost: ZERO_COST,
|
|
1484
|
+
contextWindow: 2e5,
|
|
1485
|
+
maxTokens: 65536
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
id: "claude-sonnet-4",
|
|
1489
|
+
kiroModelId: "claude-sonnet-4",
|
|
1490
|
+
name: "Claude Sonnet 4",
|
|
1491
|
+
reasoning: true,
|
|
1492
|
+
input: ["text", "image"],
|
|
1493
|
+
cost: ZERO_COST,
|
|
1494
|
+
contextWindow: 2e5,
|
|
1495
|
+
maxTokens: 65536
|
|
1496
|
+
},
|
|
1497
|
+
{
|
|
1498
|
+
id: "claude-haiku-4-5",
|
|
1499
|
+
kiroModelId: "claude-haiku-4.5",
|
|
1500
|
+
name: "Claude Haiku 4.5",
|
|
1501
|
+
reasoning: false,
|
|
1502
|
+
input: ["text", "image"],
|
|
1503
|
+
cost: ZERO_COST,
|
|
1504
|
+
contextWindow: 2e5,
|
|
1505
|
+
maxTokens: 65536
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
id: "claude-fable-5",
|
|
1509
|
+
kiroModelId: "claude-fable-5",
|
|
1510
|
+
name: "Claude Fable 5",
|
|
1511
|
+
reasoning: true,
|
|
1512
|
+
input: ["text", "image"],
|
|
1513
|
+
cost: ZERO_COST,
|
|
1514
|
+
contextWindow: 1e6,
|
|
1515
|
+
maxTokens: 65536
|
|
1516
|
+
},
|
|
1517
|
+
{
|
|
1518
|
+
id: "gpt-5-6-luna",
|
|
1519
|
+
kiroModelId: "gpt-5.6-luna",
|
|
1520
|
+
name: "GPT-5.6 Luna",
|
|
1521
|
+
reasoning: true,
|
|
1522
|
+
input: ["text", "image"],
|
|
1523
|
+
cost: ZERO_COST,
|
|
1524
|
+
contextWindow: 272e3,
|
|
1525
|
+
maxTokens: 128e3
|
|
1526
|
+
},
|
|
1527
|
+
{
|
|
1528
|
+
id: "gpt-5-6-sol",
|
|
1529
|
+
kiroModelId: "gpt-5.6-sol",
|
|
1530
|
+
name: "GPT-5.6 Sol",
|
|
1531
|
+
reasoning: true,
|
|
1532
|
+
input: ["text"],
|
|
1533
|
+
cost: ZERO_COST,
|
|
1534
|
+
contextWindow: 272e3,
|
|
1535
|
+
maxTokens: 128e3
|
|
1536
|
+
},
|
|
1537
|
+
{
|
|
1538
|
+
id: "gpt-5-6-terra",
|
|
1539
|
+
kiroModelId: "gpt-5.6-terra",
|
|
1540
|
+
name: "GPT-5.6 Terra",
|
|
1541
|
+
reasoning: true,
|
|
1542
|
+
input: ["text"],
|
|
1543
|
+
cost: ZERO_COST,
|
|
1544
|
+
contextWindow: 272e3,
|
|
1545
|
+
maxTokens: 128e3
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
id: "deepseek-3-2",
|
|
1549
|
+
kiroModelId: "deepseek-3.2",
|
|
1550
|
+
name: "DeepSeek 3.2",
|
|
1551
|
+
reasoning: true,
|
|
1552
|
+
input: ["text"],
|
|
1553
|
+
cost: ZERO_COST,
|
|
1554
|
+
contextWindow: 164e3,
|
|
1555
|
+
maxTokens: 8192
|
|
1556
|
+
},
|
|
1557
|
+
{
|
|
1558
|
+
id: "minimax-m2-5",
|
|
1559
|
+
kiroModelId: "minimax-m2.5",
|
|
1560
|
+
name: "MiniMax M2.5",
|
|
1561
|
+
reasoning: false,
|
|
1562
|
+
input: ["text"],
|
|
1563
|
+
cost: ZERO_COST,
|
|
1564
|
+
contextWindow: 196e3,
|
|
1565
|
+
maxTokens: 8192
|
|
1566
|
+
},
|
|
1567
|
+
{
|
|
1568
|
+
id: "minimax-m2-1",
|
|
1569
|
+
kiroModelId: "minimax-m2.1",
|
|
1570
|
+
name: "MiniMax M2.1",
|
|
1571
|
+
reasoning: false,
|
|
1572
|
+
input: ["text"],
|
|
1573
|
+
cost: ZERO_COST,
|
|
1574
|
+
contextWindow: 196e3,
|
|
1575
|
+
maxTokens: 8192
|
|
1576
|
+
},
|
|
1577
|
+
{
|
|
1578
|
+
id: "glm-5",
|
|
1579
|
+
kiroModelId: "glm-5",
|
|
1580
|
+
name: "GLM 5",
|
|
1581
|
+
reasoning: true,
|
|
1582
|
+
input: ["text"],
|
|
1583
|
+
cost: ZERO_COST,
|
|
1584
|
+
contextWindow: 2e5,
|
|
1585
|
+
maxTokens: 8192
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
id: "qwen3-coder-next",
|
|
1589
|
+
kiroModelId: "qwen3-coder-next",
|
|
1590
|
+
name: "Qwen3 Coder Next",
|
|
1591
|
+
reasoning: true,
|
|
1592
|
+
input: ["text"],
|
|
1593
|
+
cost: ZERO_COST,
|
|
1594
|
+
contextWindow: 256e3,
|
|
1595
|
+
maxTokens: 8192
|
|
1596
|
+
},
|
|
1597
|
+
{
|
|
1598
|
+
id: "auto",
|
|
1599
|
+
kiroModelId: "auto",
|
|
1600
|
+
name: "Auto",
|
|
1601
|
+
reasoning: true,
|
|
1602
|
+
input: ["text", "image"],
|
|
1603
|
+
cost: ZERO_COST,
|
|
1604
|
+
contextWindow: 1e6,
|
|
1605
|
+
maxTokens: 65536
|
|
1587
1606
|
}
|
|
1588
|
-
|
|
1607
|
+
];
|
|
1608
|
+
kiroModels = bootstrapKiroModels.map((model) => ({
|
|
1609
|
+
...model,
|
|
1610
|
+
...applyEffortLadder(model.reasoning ? getKiroEffortConfig(model.additionalModelRequestFieldsSchema, model.kiroModelId) : void 0),
|
|
1611
|
+
...model.id.startsWith("claude-") ? { recoverTextToolCalls: false } : {}
|
|
1612
|
+
}));
|
|
1613
|
+
BOOTSTRAP_KIRO_MODEL_IDS = kiroModels.map((model) => model.kiroModelId);
|
|
1614
|
+
KIRO_MODEL_IDS = new Set(BOOTSTRAP_KIRO_MODEL_IDS);
|
|
1589
1615
|
}
|
|
1590
1616
|
});
|
|
1591
1617
|
|
|
@@ -1653,8 +1679,8 @@ var require_base64_js = __commonJS({
|
|
|
1653
1679
|
}
|
|
1654
1680
|
return arr;
|
|
1655
1681
|
}
|
|
1656
|
-
function tripletToBase64(
|
|
1657
|
-
return lookup[
|
|
1682
|
+
function tripletToBase64(num2) {
|
|
1683
|
+
return lookup[num2 >> 18 & 63] + lookup[num2 >> 12 & 63] + lookup[num2 >> 6 & 63] + lookup[num2 & 63];
|
|
1658
1684
|
}
|
|
1659
1685
|
function encodeChunk(uint8, start, end) {
|
|
1660
1686
|
var tmp;
|
|
@@ -1747,6 +1773,10 @@ var KiroBlockBuffer = class {
|
|
|
1747
1773
|
getText(index) {
|
|
1748
1774
|
return this.blocks.get(index)?.text ?? "";
|
|
1749
1775
|
}
|
|
1776
|
+
/** Kinds of the live blocks, in allocation order. */
|
|
1777
|
+
kinds() {
|
|
1778
|
+
return [...this.blocks.values()].map((block) => block.kind);
|
|
1779
|
+
}
|
|
1750
1780
|
/**
|
|
1751
1781
|
* Rewrite one accumulated block before it is closed. Used by the recovery
|
|
1752
1782
|
* passes that lift tool calls out of text and by echo-noise stripping, both
|
|
@@ -1836,23 +1866,262 @@ function parseBracketToolCalls(text) {
|
|
|
1836
1866
|
}
|
|
1837
1867
|
return { toolCalls, cleanedText };
|
|
1838
1868
|
}
|
|
1839
|
-
|
|
1840
|
-
// ../kiro-core/dist/
|
|
1841
|
-
var
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
const
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1869
|
+
|
|
1870
|
+
// ../kiro-core/dist/cache-estimator.js
|
|
1871
|
+
var stateByConversation = /* @__PURE__ */ new Map();
|
|
1872
|
+
var MAX_TRACKED_CONVERSATIONS = 128;
|
|
1873
|
+
var warnedWireCacheCounters = false;
|
|
1874
|
+
function applyCacheEstimate(conversationId, usage, wireUsage, config, now = Date.now()) {
|
|
1875
|
+
const previous = stateByConversation.get(conversationId);
|
|
1876
|
+
const promptTokens = usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0) + usage.output;
|
|
1877
|
+
const wireReportedCache = wireUsage?.cacheReadInputTokens !== void 0 || wireUsage?.cacheWriteInputTokens !== void 0;
|
|
1878
|
+
if (wireReportedCache) {
|
|
1879
|
+
if (config.estimateCacheUsage && !warnedWireCacheCounters) {
|
|
1880
|
+
warnedWireCacheCounters = true;
|
|
1881
|
+
console.warn("[kiro-core] Kiro now reports cache token counters; cache estimation was skipped and may be disabled.");
|
|
1882
|
+
}
|
|
1883
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1884
|
+
return 0;
|
|
1885
|
+
}
|
|
1886
|
+
if (!config.estimateCacheUsage || usage.input <= 0)
|
|
1887
|
+
return 0;
|
|
1888
|
+
if (!previous) {
|
|
1889
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1890
|
+
return 0;
|
|
1891
|
+
}
|
|
1892
|
+
const expired = config.estimatedCacheTimeout > 0 && now - previous.turnTimestamp > config.estimatedCacheTimeout;
|
|
1893
|
+
const contextShrank = usage.input < previous.promptTokens * 0.6;
|
|
1894
|
+
if (expired || contextShrank) {
|
|
1895
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1896
|
+
return 0;
|
|
1897
|
+
}
|
|
1898
|
+
const estimatedRead = Math.min(previous.promptTokens, usage.input);
|
|
1899
|
+
if (estimatedRead > 0) {
|
|
1900
|
+
usage.input -= estimatedRead;
|
|
1901
|
+
usage.cacheRead = (usage.cacheRead ?? 0) + estimatedRead;
|
|
1902
|
+
usage.cacheEstimated = true;
|
|
1903
|
+
}
|
|
1904
|
+
noteSuccessfulTurn(conversationId, promptTokens, promptTokens, now);
|
|
1905
|
+
return estimatedRead;
|
|
1906
|
+
}
|
|
1907
|
+
function noteSuccessfulTurn(conversationId, promptTokens, input, now) {
|
|
1908
|
+
if (input <= 0 || promptTokens <= 0)
|
|
1909
|
+
return;
|
|
1910
|
+
stateByConversation.delete(conversationId);
|
|
1911
|
+
stateByConversation.set(conversationId, { promptTokens, turnTimestamp: now });
|
|
1912
|
+
if (stateByConversation.size > MAX_TRACKED_CONVERSATIONS) {
|
|
1913
|
+
const oldest = stateByConversation.keys().next().value;
|
|
1914
|
+
if (oldest !== void 0)
|
|
1915
|
+
stateByConversation.delete(oldest);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
// ../kiro-core/dist/cost.js
|
|
1920
|
+
var PER_MILLION = 1e6;
|
|
1921
|
+
function calculateKiroCost(cost, usage) {
|
|
1922
|
+
const input = usage.input * cost.input / PER_MILLION;
|
|
1923
|
+
const output = usage.output * cost.output / PER_MILLION;
|
|
1924
|
+
const cacheRead = (usage.cacheRead ?? 0) * cost.cacheRead / PER_MILLION;
|
|
1925
|
+
const cacheWrite = (usage.cacheWrite ?? 0) * cost.cacheWrite / PER_MILLION;
|
|
1926
|
+
return { input, output, cacheRead, cacheWrite, total: input + output + cacheRead + cacheWrite };
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
// ../kiro-core/dist/index.js
|
|
1930
|
+
init_debug();
|
|
1931
|
+
init_effort();
|
|
1932
|
+
init_endpoints();
|
|
1933
|
+
|
|
1934
|
+
// ../kiro-core/dist/retry.js
|
|
1935
|
+
init_models();
|
|
1936
|
+
var FIRST_TOKEN_TIMEOUT = 9e4;
|
|
1937
|
+
var REQUEST_HEADER_TIMEOUT = 9e4;
|
|
1938
|
+
function firstTokenTimeoutForModel(modelId) {
|
|
1939
|
+
if (retryConfig.firstTokenTimeoutMs !== FIRST_TOKEN_TIMEOUT) {
|
|
1940
|
+
return retryConfig.firstTokenTimeoutMs;
|
|
1941
|
+
}
|
|
1942
|
+
const model = kiroModels.find((m) => m.id === modelId);
|
|
1943
|
+
return model?.firstTokenTimeout ?? FIRST_TOKEN_TIMEOUT;
|
|
1944
|
+
}
|
|
1945
|
+
var retryConfig = {
|
|
1946
|
+
firstTokenTimeoutMs: FIRST_TOKEN_TIMEOUT,
|
|
1947
|
+
requestHeaderTimeoutMs: REQUEST_HEADER_TIMEOUT
|
|
1948
|
+
};
|
|
1949
|
+
function exponentialBackoff(attempt, baseMs, maxMs) {
|
|
1950
|
+
return Math.min(baseMs * 2 ** attempt, maxMs);
|
|
1951
|
+
}
|
|
1952
|
+
var MAX_RETRY_DELAY = 1e4;
|
|
1953
|
+
var REQUEST_RATE_FALLBACK_DELAY_MS = 1e4;
|
|
1954
|
+
function extractKiroReason(errorText) {
|
|
1955
|
+
if (!errorText)
|
|
1956
|
+
return void 0;
|
|
1957
|
+
try {
|
|
1958
|
+
const parsed = JSON.parse(errorText);
|
|
1959
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1960
|
+
return void 0;
|
|
1961
|
+
const reason = parsed.reason;
|
|
1962
|
+
return typeof reason === "string" && reason.length > 0 ? reason : void 0;
|
|
1963
|
+
} catch {
|
|
1964
|
+
return void 0;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
function parseRetryAfterMs(headers, nowMs = Date.now()) {
|
|
1968
|
+
const get = headers?.get?.bind(headers);
|
|
1969
|
+
if (!get)
|
|
1970
|
+
return void 0;
|
|
1971
|
+
const milliseconds = nonNegativeNumber(get("retry-after-ms"));
|
|
1972
|
+
if (milliseconds !== void 0)
|
|
1973
|
+
return Math.round(milliseconds);
|
|
1974
|
+
const retryAfter = get("retry-after");
|
|
1975
|
+
if (retryAfter !== null && retryAfter.trim() !== "") {
|
|
1976
|
+
const seconds = Number(retryAfter);
|
|
1977
|
+
if (Number.isFinite(seconds)) {
|
|
1978
|
+
if (seconds >= 0) {
|
|
1979
|
+
const delayMs = seconds * 1e3;
|
|
1980
|
+
if (Number.isFinite(delayMs))
|
|
1981
|
+
return Math.round(delayMs);
|
|
1982
|
+
}
|
|
1983
|
+
} else {
|
|
1984
|
+
const dateMs = Date.parse(retryAfter);
|
|
1985
|
+
if (!Number.isNaN(dateMs))
|
|
1986
|
+
return Math.max(0, dateMs - nowMs);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
const resetAfterSeconds = nonNegativeNumber(get("x-ratelimit-reset-after"));
|
|
1990
|
+
if (resetAfterSeconds !== void 0) {
|
|
1991
|
+
const delayMs = resetAfterSeconds * 1e3;
|
|
1992
|
+
if (Number.isFinite(delayMs))
|
|
1993
|
+
return Math.round(delayMs);
|
|
1994
|
+
}
|
|
1995
|
+
return void 0;
|
|
1996
|
+
}
|
|
1997
|
+
function resolveRequestRateRetryDelay(headers, nowMs = Date.now()) {
|
|
1998
|
+
const advertisedDelayMs = parseRetryAfterMs(headers, nowMs);
|
|
1999
|
+
const requestedDelayMs = advertisedDelayMs ?? REQUEST_RATE_FALLBACK_DELAY_MS;
|
|
2000
|
+
return {
|
|
2001
|
+
delayMs: Math.min(requestedDelayMs, MAX_RETRY_DELAY),
|
|
2002
|
+
...advertisedDelayMs !== void 0 ? { advertisedDelayMs } : {},
|
|
2003
|
+
capped: requestedDelayMs > MAX_RETRY_DELAY
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
function nonNegativeNumber(value) {
|
|
2007
|
+
if (value === null || value.trim() === "")
|
|
2008
|
+
return void 0;
|
|
2009
|
+
const parsed = Number(value);
|
|
2010
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
|
|
2011
|
+
}
|
|
2012
|
+
var KIRO_REASON_CODES = Object.freeze({
|
|
2013
|
+
/** Request body exceeded the service's size threshold. */
|
|
2014
|
+
CONTENT_LENGTH_EXCEEDS_THRESHOLD: "CONTENT_LENGTH_EXCEEDS_THRESHOLD",
|
|
2015
|
+
/** Prose-only size rejection; the service sends no reason code for this one. */
|
|
2016
|
+
INPUT_TOO_LONG: "Input is too long",
|
|
2017
|
+
/** Monthly request quota exhausted — hard limit, not transient. */
|
|
2018
|
+
MONTHLY_REQUEST_COUNT: "MONTHLY_REQUEST_COUNT",
|
|
2019
|
+
/** Model capacity temporarily unavailable — transient, worth retrying. */
|
|
2020
|
+
INSUFFICIENT_MODEL_CAPACITY: "INSUFFICIENT_MODEL_CAPACITY",
|
|
2021
|
+
/** Short-window request throttle — retry only within the provider budget. */
|
|
2022
|
+
USER_REQUEST_RATE_EXCEEDED: "USER_REQUEST_RATE_EXCEEDED",
|
|
2023
|
+
/**
|
|
2024
|
+
* Generic request-validation rejection, returned for a malformed body of any
|
|
2025
|
+
* size (empty `content`, history referencing tools absent from the catalog).
|
|
2026
|
+
* Not a size signal: classifying it as "too big" makes the caller compact a
|
|
2027
|
+
* history that was never the problem, a loop it can never satisfy.
|
|
2028
|
+
*/
|
|
2029
|
+
REQUEST_BODY_INVALID: "REQUEST_BODY_INVALID"
|
|
2030
|
+
});
|
|
2031
|
+
var TOO_BIG_PATTERNS = Object.freeze([
|
|
2032
|
+
KIRO_REASON_CODES.CONTENT_LENGTH_EXCEEDS_THRESHOLD,
|
|
2033
|
+
KIRO_REASON_CODES.INPUT_TOO_LONG
|
|
2034
|
+
]);
|
|
2035
|
+
var NON_RETRYABLE_BODY_PATTERNS = Object.freeze([KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT]);
|
|
2036
|
+
var CAPACITY_PATTERN = KIRO_REASON_CODES.INSUFFICIENT_MODEL_CAPACITY;
|
|
2037
|
+
var CAPACITY_MAX_RETRIES = 3;
|
|
2038
|
+
var CAPACITY_BASE_DELAY_MS = 5e3;
|
|
2039
|
+
var capacityRetryConfig = {
|
|
2040
|
+
maxRetries: CAPACITY_MAX_RETRIES,
|
|
2041
|
+
baseDelayMs: CAPACITY_BASE_DELAY_MS
|
|
2042
|
+
};
|
|
2043
|
+
function isTooBigError(status, errorText) {
|
|
2044
|
+
return status === 413 || status === 400 && TOO_BIG_PATTERNS.some((p) => errorText.includes(p));
|
|
2045
|
+
}
|
|
2046
|
+
function isNonRetryableBodyError(errorText) {
|
|
2047
|
+
return NON_RETRYABLE_BODY_PATTERNS.some((p) => errorText.includes(p));
|
|
2048
|
+
}
|
|
2049
|
+
function isCapacityError(errorText) {
|
|
2050
|
+
return errorText.includes(CAPACITY_PATTERN);
|
|
1848
2051
|
}
|
|
1849
2052
|
|
|
1850
|
-
// ../kiro-core/dist/
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
2053
|
+
// ../kiro-core/dist/errors.js
|
|
2054
|
+
var REASON_CODE_MARKERS = [
|
|
2055
|
+
KIRO_REASON_CODES.CONTENT_LENGTH_EXCEEDS_THRESHOLD,
|
|
2056
|
+
KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT,
|
|
2057
|
+
KIRO_REASON_CODES.INSUFFICIENT_MODEL_CAPACITY,
|
|
2058
|
+
KIRO_REASON_CODES.REQUEST_BODY_INVALID
|
|
2059
|
+
];
|
|
2060
|
+
var KiroApiError = class extends Error {
|
|
2061
|
+
status;
|
|
2062
|
+
reasonCode;
|
|
2063
|
+
retryAfterMs;
|
|
2064
|
+
providerAttempts;
|
|
2065
|
+
constructor(message, status, reasonCode, retryAfterMs, providerAttempts) {
|
|
2066
|
+
super(message);
|
|
2067
|
+
this.status = status;
|
|
2068
|
+
this.reasonCode = reasonCode;
|
|
2069
|
+
this.retryAfterMs = retryAfterMs;
|
|
2070
|
+
this.providerAttempts = providerAttempts;
|
|
2071
|
+
this.name = "KiroApiError";
|
|
2072
|
+
}
|
|
2073
|
+
};
|
|
2074
|
+
function extractKiroReasonCode(errorText) {
|
|
2075
|
+
if (!errorText)
|
|
2076
|
+
return void 0;
|
|
2077
|
+
const trimmed = errorText.trim();
|
|
2078
|
+
if (trimmed.startsWith("{")) {
|
|
2079
|
+
try {
|
|
2080
|
+
const parsed = JSON.parse(trimmed);
|
|
2081
|
+
const reason = parsed.reason ?? parsed.reasonCode;
|
|
2082
|
+
if (typeof reason === "string" && reason.length > 0)
|
|
2083
|
+
return reason;
|
|
2084
|
+
} catch {
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return REASON_CODE_MARKERS.find((code) => errorText.includes(code));
|
|
2088
|
+
}
|
|
1854
2089
|
|
|
1855
2090
|
// ../kiro-core/dist/event-parser.js
|
|
2091
|
+
var KIRO_EVENT_KEYS = [
|
|
2092
|
+
"assistantResponseEvent",
|
|
2093
|
+
"codeReferenceEvent",
|
|
2094
|
+
"contextUsageEvent",
|
|
2095
|
+
"documentCitationEvent",
|
|
2096
|
+
"error",
|
|
2097
|
+
"metadataEvent",
|
|
2098
|
+
"meteringEvent",
|
|
2099
|
+
"reasoningContentEvent",
|
|
2100
|
+
"serviceUnavailableError",
|
|
2101
|
+
"throttlingError",
|
|
2102
|
+
"toolResultEvent",
|
|
2103
|
+
"toolUseEvent",
|
|
2104
|
+
"validationError"
|
|
2105
|
+
];
|
|
2106
|
+
var KIRO_EVENT_KEY_SET = new Set(KIRO_EVENT_KEYS);
|
|
2107
|
+
var KIRO_ERROR_MEMBERS = {
|
|
2108
|
+
error: { kind: "internalServer", exception: "InternalServerException" },
|
|
2109
|
+
throttlingError: { kind: "throttling", exception: "ThrottlingException" },
|
|
2110
|
+
validationError: { kind: "validation", exception: "ValidationException" },
|
|
2111
|
+
serviceUnavailableError: { kind: "serviceUnavailable", exception: "ServiceUnavailableException" }
|
|
2112
|
+
};
|
|
2113
|
+
var KIRO_ERROR_TOKENS = {
|
|
2114
|
+
...KIRO_ERROR_MEMBERS,
|
|
2115
|
+
InternalServerException: KIRO_ERROR_MEMBERS.error,
|
|
2116
|
+
ThrottlingException: KIRO_ERROR_MEMBERS.throttlingError,
|
|
2117
|
+
ValidationException: KIRO_ERROR_MEMBERS.validationError,
|
|
2118
|
+
ServiceUnavailableException: KIRO_ERROR_MEMBERS.serviceUnavailableError
|
|
2119
|
+
};
|
|
2120
|
+
function lookupKiroErrorMember(key) {
|
|
2121
|
+
return Object.hasOwn(KIRO_ERROR_TOKENS, key) ? KIRO_ERROR_TOKENS[key] : void 0;
|
|
2122
|
+
}
|
|
2123
|
+
var num = (v) => typeof v === "number" ? v : void 0;
|
|
2124
|
+
var str = (v) => typeof v === "string" ? v : void 0;
|
|
1856
2125
|
function tokenCount(value) {
|
|
1857
2126
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1858
2127
|
}
|
|
@@ -1871,30 +2140,136 @@ var CACHE_WRITE_KEYS = [
|
|
|
1871
2140
|
"cacheCreationInputTokens",
|
|
1872
2141
|
"cacheWriteTokens"
|
|
1873
2142
|
];
|
|
1874
|
-
function
|
|
1875
|
-
if (
|
|
1876
|
-
return
|
|
1877
|
-
if (typeof
|
|
1878
|
-
return
|
|
1879
|
-
|
|
1880
|
-
|
|
2143
|
+
function toolInput(raw) {
|
|
2144
|
+
if (typeof raw === "string")
|
|
2145
|
+
return raw;
|
|
2146
|
+
if (raw && typeof raw === "object" && Object.keys(raw).length > 0) {
|
|
2147
|
+
return JSON.stringify(raw);
|
|
2148
|
+
}
|
|
2149
|
+
return "";
|
|
2150
|
+
}
|
|
2151
|
+
function parseToolUse(parsed) {
|
|
1881
2152
|
if (parsed.name && parsed.toolUseId) {
|
|
1882
|
-
const input = typeof parsed.input === "string" ? parsed.input : parsed.input && typeof parsed.input === "object" && Object.keys(parsed.input).length > 0 ? JSON.stringify(parsed.input) : "";
|
|
1883
2153
|
return {
|
|
1884
2154
|
type: "toolUse",
|
|
1885
2155
|
data: {
|
|
1886
2156
|
name: parsed.name,
|
|
1887
2157
|
toolUseId: parsed.toolUseId,
|
|
1888
|
-
input,
|
|
2158
|
+
input: toolInput(parsed.input),
|
|
1889
2159
|
stop: parsed.stop
|
|
1890
2160
|
}
|
|
1891
2161
|
};
|
|
1892
2162
|
}
|
|
2163
|
+
if (parsed.input !== void 0) {
|
|
2164
|
+
return { type: "toolUseInput", data: { input: toolInput(parsed.input) } };
|
|
2165
|
+
}
|
|
2166
|
+
if (parsed.stop !== void 0)
|
|
2167
|
+
return { type: "toolUseStop", data: { stop: parsed.stop } };
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2170
|
+
function parseMetadata(parsed) {
|
|
2171
|
+
const tu = parsed.tokenUsage ?? {};
|
|
2172
|
+
const data = {
|
|
2173
|
+
inputTokens: tokenCount(tu.uncachedInputTokens) ?? tokenCount(tu.inputTokens),
|
|
2174
|
+
outputTokens: tokenCount(tu.outputTokens),
|
|
2175
|
+
totalTokens: tokenCount(tu.totalTokens),
|
|
2176
|
+
cacheReadInputTokens: firstTokenCount(tu, CACHE_READ_KEYS),
|
|
2177
|
+
cacheWriteInputTokens: firstTokenCount(tu, CACHE_WRITE_KEYS),
|
|
2178
|
+
contextUsagePercentage: num(tu.contextUsagePercentage),
|
|
2179
|
+
normalizedTokenUsage: num(tu.normalizedTokenUsage),
|
|
2180
|
+
rawStopReason: str(parsed.stopReason),
|
|
2181
|
+
stopDetails: parsed.stopDetails && typeof parsed.stopDetails === "object" ? parsed.stopDetails : void 0
|
|
2182
|
+
};
|
|
2183
|
+
for (const k of Object.keys(data)) {
|
|
2184
|
+
if (data[k] === void 0)
|
|
2185
|
+
delete data[k];
|
|
2186
|
+
}
|
|
2187
|
+
return Object.keys(data).length > 0 ? { type: "usage", data } : null;
|
|
2188
|
+
}
|
|
2189
|
+
function parseError(parsed, kind, fallbackName) {
|
|
2190
|
+
const rawError = parsed.error ?? parsed.Error;
|
|
2191
|
+
const error2 = typeof rawError === "string" ? rawError : rawError !== void 0 ? JSON.stringify(rawError) : str(parsed.name) ?? fallbackName;
|
|
2192
|
+
const message = parsed.message ?? parsed.Message ?? parsed.reason;
|
|
2193
|
+
const data = { error: error2, kind };
|
|
2194
|
+
if (typeof message === "string")
|
|
2195
|
+
data.message = message;
|
|
2196
|
+
const reason = str(parsed.reason);
|
|
2197
|
+
if (reason !== void 0)
|
|
2198
|
+
data.reason = reason;
|
|
2199
|
+
const retryAfterMilliseconds = num(parsed.retryAfterMilliseconds);
|
|
2200
|
+
if (retryAfterMilliseconds !== void 0)
|
|
2201
|
+
data.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
2202
|
+
return { type: "error", data };
|
|
2203
|
+
}
|
|
2204
|
+
function parseKiroEvent(key, parsed) {
|
|
2205
|
+
switch (key) {
|
|
2206
|
+
case "assistantResponseEvent": {
|
|
2207
|
+
const content = str(parsed.content);
|
|
2208
|
+
return content !== void 0 ? { type: "content", data: content } : null;
|
|
2209
|
+
}
|
|
2210
|
+
case "reasoningContentEvent": {
|
|
2211
|
+
const text = str(parsed.text);
|
|
2212
|
+
if (text !== void 0)
|
|
2213
|
+
return { type: "thinkingText", data: text };
|
|
2214
|
+
const signature = str(parsed.signature);
|
|
2215
|
+
if (signature !== void 0)
|
|
2216
|
+
return { type: "thinkingSignature", data: signature };
|
|
2217
|
+
return { type: "ignored", data: { key } };
|
|
2218
|
+
}
|
|
2219
|
+
case "toolUseEvent":
|
|
2220
|
+
return parseToolUse(parsed);
|
|
2221
|
+
case "contextUsageEvent": {
|
|
2222
|
+
const pct = num(parsed.contextUsagePercentage);
|
|
2223
|
+
return pct !== void 0 ? { type: "contextUsage", data: { contextUsagePercentage: pct } } : null;
|
|
2224
|
+
}
|
|
2225
|
+
case "metadataEvent":
|
|
2226
|
+
return parseMetadata(parsed);
|
|
2227
|
+
case "meteringEvent":
|
|
2228
|
+
return {
|
|
2229
|
+
type: "metering",
|
|
2230
|
+
data: { credits: tokenCount(parsed.usage), unit: str(parsed.unit), unitPlural: str(parsed.unitPlural) }
|
|
2231
|
+
};
|
|
2232
|
+
// Reachable when a member that models an exception is delivered as an
|
|
2233
|
+
// ordinary event frame. The real wire uses exception framing, handled by
|
|
2234
|
+
// parseKiroExceptionFrame, but both routes must agree.
|
|
2235
|
+
case "error":
|
|
2236
|
+
case "throttlingError":
|
|
2237
|
+
case "validationError":
|
|
2238
|
+
case "serviceUnavailableError": {
|
|
2239
|
+
const member = lookupKiroErrorMember(key);
|
|
2240
|
+
return parseError(parsed, member.kind, member.exception);
|
|
2241
|
+
}
|
|
2242
|
+
// Known members with no consumer yet: explicitly ignored, not unparseable.
|
|
2243
|
+
case "codeReferenceEvent":
|
|
2244
|
+
case "documentCitationEvent":
|
|
2245
|
+
case "toolResultEvent":
|
|
2246
|
+
return { type: "ignored", data: { key } };
|
|
2247
|
+
default: {
|
|
2248
|
+
const member = lookupKiroErrorMember(key);
|
|
2249
|
+
if (member)
|
|
2250
|
+
return parseError(parsed, member.kind, member.exception);
|
|
2251
|
+
return parseKiroEventByShape(parsed);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
function parseKiroExceptionFrame(key, parsed) {
|
|
2256
|
+
const member = lookupKiroErrorMember(key);
|
|
2257
|
+
if (!member)
|
|
2258
|
+
return null;
|
|
2259
|
+
const event = parseError(parsed, member.kind, member.exception);
|
|
2260
|
+
return event.data;
|
|
2261
|
+
}
|
|
2262
|
+
function parseKiroEventByShape(parsed) {
|
|
2263
|
+
if (parsed.content !== void 0)
|
|
2264
|
+
return { type: "content", data: parsed.content };
|
|
2265
|
+
if (typeof parsed.text === "string")
|
|
2266
|
+
return { type: "thinkingText", data: parsed.text };
|
|
2267
|
+
if (typeof parsed.signature === "string")
|
|
2268
|
+
return { type: "thinkingSignature", data: parsed.signature };
|
|
2269
|
+
if (parsed.name && parsed.toolUseId)
|
|
2270
|
+
return parseToolUse(parsed);
|
|
1893
2271
|
if (parsed.input !== void 0 && !parsed.name) {
|
|
1894
|
-
return {
|
|
1895
|
-
type: "toolUseInput",
|
|
1896
|
-
data: { input: typeof parsed.input === "string" ? parsed.input : JSON.stringify(parsed.input) }
|
|
1897
|
-
};
|
|
2272
|
+
return { type: "toolUseInput", data: { input: toolInput(parsed.input) } };
|
|
1898
2273
|
}
|
|
1899
2274
|
if (parsed.stop !== void 0 && parsed.contextUsagePercentage === void 0)
|
|
1900
2275
|
return { type: "toolUseStop", data: { stop: parsed.stop } };
|
|
@@ -1902,42 +2277,23 @@ function parseKiroEvent(parsed) {
|
|
|
1902
2277
|
return { type: "contextUsage", data: { contextUsagePercentage: parsed.contextUsagePercentage } };
|
|
1903
2278
|
if (parsed.followupPrompt !== void 0)
|
|
1904
2279
|
return { type: "followupPrompt", data: parsed.followupPrompt };
|
|
2280
|
+
if (parsed.tokenUsage !== void 0 || parsed.stopReason !== void 0 || parsed.stopDetails !== void 0) {
|
|
2281
|
+
return parseMetadata(parsed);
|
|
2282
|
+
}
|
|
1905
2283
|
if (parsed.error !== void 0 || parsed.Error !== void 0) {
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
}
|
|
1910
|
-
if (parsed.usage !== void 0) {
|
|
1911
|
-
if (typeof parsed.usage === "number") {
|
|
1912
|
-
const credits = tokenCount(parsed.usage);
|
|
1913
|
-
if (credits === void 0)
|
|
1914
|
-
return null;
|
|
1915
|
-
return {
|
|
1916
|
-
type: "usage",
|
|
1917
|
-
data: {
|
|
1918
|
-
credits,
|
|
1919
|
-
...typeof parsed.unit === "string" && parsed.unit ? { creditUnit: parsed.unit } : {}
|
|
1920
|
-
}
|
|
1921
|
-
};
|
|
1922
|
-
}
|
|
1923
|
-
const u = parsed.usage;
|
|
1924
|
-
const cacheReadTokens = firstTokenCount(u, CACHE_READ_KEYS);
|
|
1925
|
-
const cacheWriteTokens = firstTokenCount(u, CACHE_WRITE_KEYS);
|
|
2284
|
+
return parseError(parsed, "unknown", "unknown");
|
|
2285
|
+
}
|
|
2286
|
+
if (typeof parsed.usage === "number") {
|
|
1926
2287
|
return {
|
|
1927
|
-
type: "
|
|
1928
|
-
data: {
|
|
1929
|
-
inputTokens: tokenCount(u.inputTokens),
|
|
1930
|
-
outputTokens: tokenCount(u.outputTokens),
|
|
1931
|
-
...cacheReadTokens !== void 0 ? { cacheReadTokens } : {},
|
|
1932
|
-
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
|
|
1933
|
-
}
|
|
2288
|
+
type: "metering",
|
|
2289
|
+
data: { credits: tokenCount(parsed.usage), unit: str(parsed.unit), unitPlural: str(parsed.unitPlural) }
|
|
1934
2290
|
};
|
|
1935
2291
|
}
|
|
1936
2292
|
return null;
|
|
1937
2293
|
}
|
|
1938
2294
|
|
|
1939
2295
|
// ../kiro-core/dist/transform.js
|
|
1940
|
-
import { createHash } from "node:crypto";
|
|
2296
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1941
2297
|
var TOOL_RESULT_LIMIT = 25e4;
|
|
1942
2298
|
var EMPTY_CONTENT_PLACEHOLDER = "Please proceed with the task.";
|
|
1943
2299
|
function sanitizeSurrogates(text) {
|
|
@@ -1955,7 +2311,7 @@ var KIRO_TOOL_USE_ID_PATTERN = /^[a-zA-Z0-9_.:-]{1,64}$/;
|
|
|
1955
2311
|
function toKiroToolUseId(toolUseId) {
|
|
1956
2312
|
if (KIRO_TOOL_USE_ID_PATTERN.test(toolUseId))
|
|
1957
2313
|
return toolUseId;
|
|
1958
|
-
const digest =
|
|
2314
|
+
const digest = createHash2("sha256").update(toolUseId).digest("base64url").slice(0, 32);
|
|
1959
2315
|
return `pi_${digest}`;
|
|
1960
2316
|
}
|
|
1961
2317
|
function normalizeMessages(messages) {
|
|
@@ -2969,8 +3325,8 @@ function bytePairEncode(piece, ranks) {
|
|
|
2969
3325
|
return [ranks.get(piece.join(","))];
|
|
2970
3326
|
return bytePairMerge(piece, ranks).map((p) => ranks.get(piece.slice(p.start, p.end).join(","))).filter((x) => x != null);
|
|
2971
3327
|
}
|
|
2972
|
-
function escapeRegex(
|
|
2973
|
-
return
|
|
3328
|
+
function escapeRegex(str2) {
|
|
3329
|
+
return str2.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
2974
3330
|
}
|
|
2975
3331
|
var _Tiktoken = class {
|
|
2976
3332
|
/** @internal */
|
|
@@ -3117,6 +3473,7 @@ var KiroResponseAssembler = class {
|
|
|
3117
3473
|
totalContent = "";
|
|
3118
3474
|
lastContentData = "";
|
|
3119
3475
|
usageEvent = null;
|
|
3476
|
+
meteringEvent = null;
|
|
3120
3477
|
receivedContextUsage = false;
|
|
3121
3478
|
thinkingParser = null;
|
|
3122
3479
|
nativeThinkingBlockIndex = null;
|
|
@@ -3124,16 +3481,19 @@ var KiroResponseAssembler = class {
|
|
|
3124
3481
|
textBlockIndex = null;
|
|
3125
3482
|
emittedToolCalls = 0;
|
|
3126
3483
|
sawAnyToolCalls = false;
|
|
3484
|
+
droppedToolCalls = [];
|
|
3127
3485
|
currentToolCall = null;
|
|
3486
|
+
stopReason = "stop";
|
|
3128
3487
|
constructor(model, thinkingEnabled) {
|
|
3129
3488
|
this.model = model;
|
|
3130
3489
|
this.thinkingEnabled = thinkingEnabled;
|
|
3131
3490
|
}
|
|
3132
|
-
/** Clear per-attempt state.
|
|
3491
|
+
/** Clear per-attempt state. Only block indexes are kept. */
|
|
3133
3492
|
beginAttempt() {
|
|
3134
3493
|
this.totalContent = "";
|
|
3135
3494
|
this.lastContentData = "";
|
|
3136
3495
|
this.usageEvent = null;
|
|
3496
|
+
this.meteringEvent = null;
|
|
3137
3497
|
this.receivedContextUsage = false;
|
|
3138
3498
|
this.thinkingParser = this.thinkingEnabled ? new ThinkingTagParser(this.blocks) : null;
|
|
3139
3499
|
this.nativeThinkingBlockIndex = null;
|
|
@@ -3141,7 +3501,17 @@ var KiroResponseAssembler = class {
|
|
|
3141
3501
|
this.textBlockIndex = null;
|
|
3142
3502
|
this.emittedToolCalls = 0;
|
|
3143
3503
|
this.sawAnyToolCalls = false;
|
|
3504
|
+
this.droppedToolCalls = [];
|
|
3144
3505
|
this.currentToolCall = null;
|
|
3506
|
+
this.usage.input = 0;
|
|
3507
|
+
this.usage.output = 0;
|
|
3508
|
+
this.usage.totalTokens = 0;
|
|
3509
|
+
this.usage.cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
3510
|
+
delete this.usage.cacheRead;
|
|
3511
|
+
delete this.usage.cacheWrite;
|
|
3512
|
+
delete this.usage.contextPercent;
|
|
3513
|
+
delete this.usage.credits;
|
|
3514
|
+
delete this.usage.creditUnit;
|
|
3145
3515
|
}
|
|
3146
3516
|
/** Hand over the events buffered so far. */
|
|
3147
3517
|
takeEvents() {
|
|
@@ -3218,11 +3588,17 @@ var KiroResponseAssembler = class {
|
|
|
3218
3588
|
break;
|
|
3219
3589
|
}
|
|
3220
3590
|
case "usage": {
|
|
3221
|
-
this.usageEvent = event.data;
|
|
3591
|
+
this.usageEvent = { ...this.usageEvent ?? {}, ...event.data };
|
|
3222
3592
|
if (debugEnabled())
|
|
3223
3593
|
debugLog("response.usageRaw", payload);
|
|
3224
3594
|
break;
|
|
3225
3595
|
}
|
|
3596
|
+
case "metering": {
|
|
3597
|
+
this.meteringEvent = event.data;
|
|
3598
|
+
if (debugEnabled())
|
|
3599
|
+
debugLog("stream.metering", [event.data]);
|
|
3600
|
+
break;
|
|
3601
|
+
}
|
|
3226
3602
|
}
|
|
3227
3603
|
}
|
|
3228
3604
|
/**
|
|
@@ -3230,8 +3606,12 @@ var KiroResponseAssembler = class {
|
|
|
3230
3606
|
* text-dialect recovery and echo-stripping passes.
|
|
3231
3607
|
*/
|
|
3232
3608
|
endTurn() {
|
|
3233
|
-
if (this.currentToolCall
|
|
3234
|
-
this.
|
|
3609
|
+
if (this.currentToolCall) {
|
|
3610
|
+
if (this.emitToolCall(this.currentToolCall))
|
|
3611
|
+
this.emittedToolCalls++;
|
|
3612
|
+
else
|
|
3613
|
+
this.droppedToolCalls.push(this.currentToolCall.name);
|
|
3614
|
+
}
|
|
3235
3615
|
this.currentToolCall = null;
|
|
3236
3616
|
this.endNativeThinking();
|
|
3237
3617
|
if (this.thinkingParser) {
|
|
@@ -3242,13 +3622,16 @@ var KiroResponseAssembler = class {
|
|
|
3242
3622
|
this.stripEchoNoise();
|
|
3243
3623
|
const responseText = this.textBlockIndex === null ? "" : this.blocks.getText(this.textBlockIndex);
|
|
3244
3624
|
const hasText2 = responseText.length > 0;
|
|
3625
|
+
this.stopReason = !this.receivedContextUsage && this.emittedToolCalls === 0 ? "length" : this.emittedToolCalls > 0 ? "toolUse" : "stop";
|
|
3245
3626
|
return {
|
|
3246
3627
|
responseText,
|
|
3247
3628
|
hasText: hasText2,
|
|
3248
3629
|
sawAnyToolCalls: this.sawAnyToolCalls,
|
|
3249
3630
|
emittedToolCalls: this.emittedToolCalls,
|
|
3250
3631
|
isEchoLoop: hasText2 && !this.sawAnyToolCalls && ECHO_NOISE_PATTERN.test(responseText),
|
|
3251
|
-
isEmpty: !hasText2 && !this.sawAnyToolCalls
|
|
3632
|
+
isEmpty: !hasText2 && !this.sawAnyToolCalls,
|
|
3633
|
+
stopReason: this.stopReason,
|
|
3634
|
+
droppedToolCalls: this.droppedToolCalls
|
|
3252
3635
|
};
|
|
3253
3636
|
}
|
|
3254
3637
|
/** Drop an echo the caller decided not to retry, so it is not read as a continuation signal. */
|
|
@@ -3256,6 +3639,10 @@ var KiroResponseAssembler = class {
|
|
|
3256
3639
|
if (this.textBlockIndex !== null)
|
|
3257
3640
|
this.blocks.setText(this.textBlockIndex, "");
|
|
3258
3641
|
}
|
|
3642
|
+
/** Kinds of the blocks this attempt produced, for the exhaustion diagnostic. */
|
|
3643
|
+
contentKinds() {
|
|
3644
|
+
return this.blocks.kinds();
|
|
3645
|
+
}
|
|
3259
3646
|
/** Close the text block and settle usage and the stop reason. */
|
|
3260
3647
|
complete() {
|
|
3261
3648
|
if (this.textBlockIndex !== null)
|
|
@@ -3263,17 +3650,17 @@ var KiroResponseAssembler = class {
|
|
|
3263
3650
|
if (this.usageEvent?.inputTokens !== void 0)
|
|
3264
3651
|
this.usage.input = this.usageEvent.inputTokens;
|
|
3265
3652
|
this.usage.output = this.usageEvent?.outputTokens ?? countTokens(this.totalContent);
|
|
3266
|
-
this.usage.totalTokens = this.usage.input + this.usage.output;
|
|
3267
|
-
if (this.usageEvent?.
|
|
3268
|
-
this.usage.cacheRead = this.usageEvent.
|
|
3269
|
-
if (this.usageEvent?.
|
|
3270
|
-
this.usage.cacheWrite = this.usageEvent.
|
|
3271
|
-
if (this.
|
|
3272
|
-
this.usage.credits = this.
|
|
3273
|
-
if (this.
|
|
3274
|
-
this.usage.creditUnit = this.
|
|
3653
|
+
this.usage.totalTokens = this.usageEvent?.totalTokens ?? this.usage.input + (this.usageEvent?.cacheReadInputTokens ?? 0) + (this.usageEvent?.cacheWriteInputTokens ?? 0) + this.usage.output;
|
|
3654
|
+
if (this.usageEvent?.cacheReadInputTokens !== void 0)
|
|
3655
|
+
this.usage.cacheRead = this.usageEvent.cacheReadInputTokens;
|
|
3656
|
+
if (this.usageEvent?.cacheWriteInputTokens !== void 0)
|
|
3657
|
+
this.usage.cacheWrite = this.usageEvent.cacheWriteInputTokens;
|
|
3658
|
+
if (this.meteringEvent?.credits !== void 0)
|
|
3659
|
+
this.usage.credits = this.meteringEvent.credits;
|
|
3660
|
+
if (this.meteringEvent?.unit !== void 0)
|
|
3661
|
+
this.usage.creditUnit = this.meteringEvent.unit;
|
|
3275
3662
|
this.usage.cost = calculateKiroCost(this.model.cost, this.usage);
|
|
3276
|
-
const stopReason =
|
|
3663
|
+
const stopReason = this.stopReason;
|
|
3277
3664
|
debugLog("response.done", {
|
|
3278
3665
|
stopReason,
|
|
3279
3666
|
receivedContextUsage: this.receivedContextUsage,
|
|
@@ -3282,7 +3669,12 @@ var KiroResponseAssembler = class {
|
|
|
3282
3669
|
textLen: this.textBlockIndex === null ? 0 : this.blocks.getText(this.textBlockIndex).length,
|
|
3283
3670
|
usage: this.usage
|
|
3284
3671
|
});
|
|
3285
|
-
return {
|
|
3672
|
+
return {
|
|
3673
|
+
stopReason,
|
|
3674
|
+
usage: this.usage,
|
|
3675
|
+
wireUsage: this.usageEvent,
|
|
3676
|
+
metering: this.meteringEvent
|
|
3677
|
+
};
|
|
3286
3678
|
}
|
|
3287
3679
|
ensureNativeThinkingBlock() {
|
|
3288
3680
|
if (this.nativeThinkingBlockIndex === null)
|
|
@@ -3317,6 +3709,8 @@ var KiroResponseAssembler = class {
|
|
|
3317
3709
|
return;
|
|
3318
3710
|
if (this.emitToolCall(this.currentToolCall))
|
|
3319
3711
|
this.emittedToolCalls++;
|
|
3712
|
+
else
|
|
3713
|
+
this.droppedToolCalls.push(this.currentToolCall.name);
|
|
3320
3714
|
this.currentToolCall = null;
|
|
3321
3715
|
}
|
|
3322
3716
|
/**
|
|
@@ -3358,6 +3752,8 @@ var KiroResponseAssembler = class {
|
|
|
3358
3752
|
for (const call of recovered) {
|
|
3359
3753
|
if (this.emitToolCall({ toolUseId: call.toolUseId, name: call.name, input: JSON.stringify(call.arguments) })) {
|
|
3360
3754
|
this.emittedToolCalls++;
|
|
3755
|
+
} else {
|
|
3756
|
+
this.droppedToolCalls.push(call.name);
|
|
3361
3757
|
}
|
|
3362
3758
|
}
|
|
3363
3759
|
}
|
|
@@ -4117,6 +4513,7 @@ function readKiroEventStream(body, options) {
|
|
|
4117
4513
|
const outcome = { firstTokenTimedOut: false, idleTimedOut: false, error: null };
|
|
4118
4514
|
const idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT;
|
|
4119
4515
|
const bodyReader = body.getReader();
|
|
4516
|
+
const callerSignal = options.signal;
|
|
4120
4517
|
async function* frames() {
|
|
4121
4518
|
let idleTimer = null;
|
|
4122
4519
|
const resetIdle = () => {
|
|
@@ -4128,6 +4525,14 @@ function readKiroEventStream(body, options) {
|
|
|
4128
4525
|
});
|
|
4129
4526
|
}, idleTimeoutMs);
|
|
4130
4527
|
};
|
|
4528
|
+
const onCallerStreamAbort = () => {
|
|
4529
|
+
void bodyReader.cancel().catch(() => {
|
|
4530
|
+
});
|
|
4531
|
+
};
|
|
4532
|
+
if (callerSignal?.aborted)
|
|
4533
|
+
onCallerStreamAbort();
|
|
4534
|
+
else
|
|
4535
|
+
callerSignal?.addEventListener("abort", onCallerStreamAbort, { once: true });
|
|
4131
4536
|
const bodyIterable = {
|
|
4132
4537
|
async *[Symbol.asyncIterator]() {
|
|
4133
4538
|
try {
|
|
@@ -4148,6 +4553,26 @@ function readKiroEventStream(body, options) {
|
|
|
4148
4553
|
if (!entry)
|
|
4149
4554
|
throw new Error("Received an empty event stream message");
|
|
4150
4555
|
const [key, msg] = entry;
|
|
4556
|
+
if (msg.headers[":message-type"]?.value === "exception") {
|
|
4557
|
+
let parsedException = {};
|
|
4558
|
+
try {
|
|
4559
|
+
const decoded = JSON.parse(utf8Decoder.decode(msg.body));
|
|
4560
|
+
if (decoded && typeof decoded === "object")
|
|
4561
|
+
parsedException = decoded;
|
|
4562
|
+
} catch {
|
|
4563
|
+
}
|
|
4564
|
+
const data = parseKiroExceptionFrame(key, parsedException) ?? {
|
|
4565
|
+
error: key,
|
|
4566
|
+
kind: "unknown",
|
|
4567
|
+
...typeof parsedException.message === "string" ? { message: parsedException.message } : {},
|
|
4568
|
+
...typeof parsedException.reason === "string" ? { reason: parsedException.reason } : {},
|
|
4569
|
+
...typeof parsedException.retryAfterMilliseconds === "number" ? { retryAfterMilliseconds: parsedException.retryAfterMilliseconds } : {}
|
|
4570
|
+
};
|
|
4571
|
+
const error2 = new Error(data.message ? `${data.error}: ${data.message}` : data.error);
|
|
4572
|
+
error2.name = data.error;
|
|
4573
|
+
error2.kiroError = data;
|
|
4574
|
+
return { [key]: error2 };
|
|
4575
|
+
}
|
|
4151
4576
|
const parsed = JSON.parse(utf8Decoder.decode(msg.body));
|
|
4152
4577
|
return { [key]: parsed };
|
|
4153
4578
|
});
|
|
@@ -4156,29 +4581,43 @@ function readKiroEventStream(body, options) {
|
|
|
4156
4581
|
const FIRST_TOKEN_SENTINEL = /* @__PURE__ */ Symbol("firstTokenTimeout");
|
|
4157
4582
|
try {
|
|
4158
4583
|
while (true) {
|
|
4584
|
+
if (callerSignal?.aborted) {
|
|
4585
|
+
throw callerSignal.reason ?? new Error("Request aborted");
|
|
4586
|
+
}
|
|
4159
4587
|
let iterResult;
|
|
4160
4588
|
try {
|
|
4161
4589
|
if (!gotFirstToken) {
|
|
4162
4590
|
const readPromise = iterator.next();
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4591
|
+
let firstTokenTimer;
|
|
4592
|
+
try {
|
|
4593
|
+
const result = await Promise.race([
|
|
4594
|
+
readPromise,
|
|
4595
|
+
new Promise((resolve) => {
|
|
4596
|
+
firstTokenTimer = setTimeout(() => resolve(FIRST_TOKEN_SENTINEL), options.firstTokenTimeoutMs);
|
|
4597
|
+
})
|
|
4598
|
+
]);
|
|
4599
|
+
if (result === FIRST_TOKEN_SENTINEL) {
|
|
4600
|
+
readPromise.catch(() => {
|
|
4601
|
+
});
|
|
4602
|
+
void bodyReader.cancel().catch(() => {
|
|
4603
|
+
});
|
|
4604
|
+
outcome.firstTokenTimedOut = true;
|
|
4605
|
+
return;
|
|
4606
|
+
}
|
|
4607
|
+
iterResult = result;
|
|
4608
|
+
gotFirstToken = true;
|
|
4609
|
+
resetIdle();
|
|
4610
|
+
} finally {
|
|
4611
|
+
if (firstTokenTimer !== void 0)
|
|
4612
|
+
clearTimeout(firstTokenTimer);
|
|
4174
4613
|
}
|
|
4175
|
-
iterResult = result;
|
|
4176
|
-
gotFirstToken = true;
|
|
4177
|
-
resetIdle();
|
|
4178
4614
|
} else {
|
|
4179
4615
|
iterResult = await iterator.next();
|
|
4180
4616
|
}
|
|
4181
4617
|
} catch (e) {
|
|
4618
|
+
const kiroError = e?.kiroError;
|
|
4619
|
+
if (kiroError)
|
|
4620
|
+
outcome.errorData = kiroError;
|
|
4182
4621
|
outcome.error = e instanceof Error ? e.message : (typeof e === "object" && e !== null ? JSON.stringify(e) : String(e)) || "Unknown stream error";
|
|
4183
4622
|
return;
|
|
4184
4623
|
}
|
|
@@ -4186,148 +4625,40 @@ function readKiroEventStream(body, options) {
|
|
|
4186
4625
|
if (done)
|
|
4187
4626
|
return;
|
|
4188
4627
|
resetIdle();
|
|
4189
|
-
const
|
|
4190
|
-
|
|
4628
|
+
const frameEntry = Object.entries(value)[0];
|
|
4629
|
+
if (!frameEntry)
|
|
4630
|
+
continue;
|
|
4631
|
+
const [frameKey, framePayload] = frameEntry;
|
|
4632
|
+
const event = parseKiroEvent(frameKey, framePayload ?? {});
|
|
4191
4633
|
if (!event)
|
|
4192
4634
|
continue;
|
|
4635
|
+
if (event.type === "ignored") {
|
|
4636
|
+
if (debugEnabled())
|
|
4637
|
+
debugLog("stream.events.ignored", [event.data.key]);
|
|
4638
|
+
continue;
|
|
4639
|
+
}
|
|
4193
4640
|
if (debugEnabled())
|
|
4194
4641
|
debugLog("stream.events", [event]);
|
|
4195
4642
|
if (event.type === "error") {
|
|
4196
4643
|
outcome.error = event.data.message ? `${event.data.error}: ${event.data.message}` : event.data.error;
|
|
4644
|
+
outcome.errorData = event.data;
|
|
4197
4645
|
void bodyReader.cancel().catch(() => {
|
|
4198
4646
|
});
|
|
4199
4647
|
return;
|
|
4200
4648
|
}
|
|
4201
|
-
yield { event, payload };
|
|
4649
|
+
yield { event, payload: framePayload };
|
|
4202
4650
|
}
|
|
4203
4651
|
} finally {
|
|
4204
4652
|
if (idleTimer)
|
|
4205
4653
|
clearTimeout(idleTimer);
|
|
4654
|
+
callerSignal?.removeEventListener("abort", onCallerStreamAbort);
|
|
4206
4655
|
}
|
|
4207
4656
|
}
|
|
4208
4657
|
return { frames: frames(), outcome };
|
|
4209
4658
|
}
|
|
4210
4659
|
|
|
4211
|
-
// ../kiro-core/dist/retry.js
|
|
4212
|
-
init_models();
|
|
4213
|
-
var FIRST_TOKEN_TIMEOUT = 9e4;
|
|
4214
|
-
var REQUEST_HEADER_TIMEOUT = 9e4;
|
|
4215
|
-
function firstTokenTimeoutForModel(modelId) {
|
|
4216
|
-
if (retryConfig.firstTokenTimeoutMs !== FIRST_TOKEN_TIMEOUT) {
|
|
4217
|
-
return retryConfig.firstTokenTimeoutMs;
|
|
4218
|
-
}
|
|
4219
|
-
const model = kiroModels.find((m) => m.id === modelId);
|
|
4220
|
-
return model?.firstTokenTimeout ?? FIRST_TOKEN_TIMEOUT;
|
|
4221
|
-
}
|
|
4222
|
-
var retryConfig = {
|
|
4223
|
-
firstTokenTimeoutMs: FIRST_TOKEN_TIMEOUT,
|
|
4224
|
-
requestHeaderTimeoutMs: REQUEST_HEADER_TIMEOUT
|
|
4225
|
-
};
|
|
4226
|
-
function exponentialBackoff(attempt, baseMs, maxMs) {
|
|
4227
|
-
return Math.min(baseMs * 2 ** attempt, maxMs);
|
|
4228
|
-
}
|
|
4229
|
-
var MAX_RETRY_DELAY = 1e4;
|
|
4230
|
-
var REQUEST_RATE_FALLBACK_DELAY_MS = 1e4;
|
|
4231
|
-
function extractKiroReason(errorText) {
|
|
4232
|
-
if (!errorText)
|
|
4233
|
-
return void 0;
|
|
4234
|
-
try {
|
|
4235
|
-
const parsed = JSON.parse(errorText);
|
|
4236
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
4237
|
-
return void 0;
|
|
4238
|
-
const reason = parsed.reason;
|
|
4239
|
-
return typeof reason === "string" && reason.length > 0 ? reason : void 0;
|
|
4240
|
-
} catch {
|
|
4241
|
-
return void 0;
|
|
4242
|
-
}
|
|
4243
|
-
}
|
|
4244
|
-
function parseRetryAfterMs(headers, nowMs = Date.now()) {
|
|
4245
|
-
const get = headers?.get?.bind(headers);
|
|
4246
|
-
if (!get)
|
|
4247
|
-
return void 0;
|
|
4248
|
-
const milliseconds = nonNegativeNumber(get("retry-after-ms"));
|
|
4249
|
-
if (milliseconds !== void 0)
|
|
4250
|
-
return Math.round(milliseconds);
|
|
4251
|
-
const retryAfter = get("retry-after");
|
|
4252
|
-
if (retryAfter !== null && retryAfter.trim() !== "") {
|
|
4253
|
-
const seconds = Number(retryAfter);
|
|
4254
|
-
if (Number.isFinite(seconds)) {
|
|
4255
|
-
if (seconds >= 0) {
|
|
4256
|
-
const delayMs = seconds * 1e3;
|
|
4257
|
-
if (Number.isFinite(delayMs))
|
|
4258
|
-
return Math.round(delayMs);
|
|
4259
|
-
}
|
|
4260
|
-
} else {
|
|
4261
|
-
const dateMs = Date.parse(retryAfter);
|
|
4262
|
-
if (!Number.isNaN(dateMs))
|
|
4263
|
-
return Math.max(0, dateMs - nowMs);
|
|
4264
|
-
}
|
|
4265
|
-
}
|
|
4266
|
-
const resetAfterSeconds = nonNegativeNumber(get("x-ratelimit-reset-after"));
|
|
4267
|
-
if (resetAfterSeconds !== void 0) {
|
|
4268
|
-
const delayMs = resetAfterSeconds * 1e3;
|
|
4269
|
-
if (Number.isFinite(delayMs))
|
|
4270
|
-
return Math.round(delayMs);
|
|
4271
|
-
}
|
|
4272
|
-
return void 0;
|
|
4273
|
-
}
|
|
4274
|
-
function resolveRequestRateRetryDelay(headers, nowMs = Date.now()) {
|
|
4275
|
-
const advertisedDelayMs = parseRetryAfterMs(headers, nowMs);
|
|
4276
|
-
const requestedDelayMs = advertisedDelayMs ?? REQUEST_RATE_FALLBACK_DELAY_MS;
|
|
4277
|
-
return {
|
|
4278
|
-
delayMs: Math.min(requestedDelayMs, MAX_RETRY_DELAY),
|
|
4279
|
-
...advertisedDelayMs !== void 0 ? { advertisedDelayMs } : {},
|
|
4280
|
-
capped: requestedDelayMs > MAX_RETRY_DELAY
|
|
4281
|
-
};
|
|
4282
|
-
}
|
|
4283
|
-
function nonNegativeNumber(value) {
|
|
4284
|
-
if (value === null || value.trim() === "")
|
|
4285
|
-
return void 0;
|
|
4286
|
-
const parsed = Number(value);
|
|
4287
|
-
return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
|
|
4288
|
-
}
|
|
4289
|
-
var KIRO_REASON_CODES = Object.freeze({
|
|
4290
|
-
/** Request body exceeded the service's size threshold. */
|
|
4291
|
-
CONTENT_LENGTH_EXCEEDS_THRESHOLD: "CONTENT_LENGTH_EXCEEDS_THRESHOLD",
|
|
4292
|
-
/** Prose-only size rejection; the service sends no reason code for this one. */
|
|
4293
|
-
INPUT_TOO_LONG: "Input is too long",
|
|
4294
|
-
/** Monthly request quota exhausted — hard limit, not transient. */
|
|
4295
|
-
MONTHLY_REQUEST_COUNT: "MONTHLY_REQUEST_COUNT",
|
|
4296
|
-
/** Model capacity temporarily unavailable — transient, worth retrying. */
|
|
4297
|
-
INSUFFICIENT_MODEL_CAPACITY: "INSUFFICIENT_MODEL_CAPACITY",
|
|
4298
|
-
/** Short-window request throttle — retry only within the provider budget. */
|
|
4299
|
-
USER_REQUEST_RATE_EXCEEDED: "USER_REQUEST_RATE_EXCEEDED",
|
|
4300
|
-
/**
|
|
4301
|
-
* Generic request-validation rejection, returned for a malformed body of any
|
|
4302
|
-
* size (empty `content`, history referencing tools absent from the catalog).
|
|
4303
|
-
* Not a size signal: classifying it as "too big" makes the caller compact a
|
|
4304
|
-
* history that was never the problem, a loop it can never satisfy.
|
|
4305
|
-
*/
|
|
4306
|
-
REQUEST_BODY_INVALID: "REQUEST_BODY_INVALID"
|
|
4307
|
-
});
|
|
4308
|
-
var TOO_BIG_PATTERNS = Object.freeze([
|
|
4309
|
-
KIRO_REASON_CODES.CONTENT_LENGTH_EXCEEDS_THRESHOLD,
|
|
4310
|
-
KIRO_REASON_CODES.INPUT_TOO_LONG
|
|
4311
|
-
]);
|
|
4312
|
-
var NON_RETRYABLE_BODY_PATTERNS = Object.freeze([KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT]);
|
|
4313
|
-
var CAPACITY_PATTERN = KIRO_REASON_CODES.INSUFFICIENT_MODEL_CAPACITY;
|
|
4314
|
-
var CAPACITY_MAX_RETRIES = 3;
|
|
4315
|
-
var CAPACITY_BASE_DELAY_MS = 5e3;
|
|
4316
|
-
var capacityRetryConfig = {
|
|
4317
|
-
maxRetries: CAPACITY_MAX_RETRIES,
|
|
4318
|
-
baseDelayMs: CAPACITY_BASE_DELAY_MS
|
|
4319
|
-
};
|
|
4320
|
-
function isTooBigError(status, errorText) {
|
|
4321
|
-
return status === 413 || status === 400 && TOO_BIG_PATTERNS.some((p) => errorText.includes(p));
|
|
4322
|
-
}
|
|
4323
|
-
function isNonRetryableBodyError(errorText) {
|
|
4324
|
-
return NON_RETRYABLE_BODY_PATTERNS.some((p) => errorText.includes(p));
|
|
4325
|
-
}
|
|
4326
|
-
function isCapacityError(errorText) {
|
|
4327
|
-
return errorText.includes(CAPACITY_PATTERN);
|
|
4328
|
-
}
|
|
4329
|
-
|
|
4330
4660
|
// ../kiro-core/dist/stream.js
|
|
4661
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
4331
4662
|
init_debug();
|
|
4332
4663
|
init_effort();
|
|
4333
4664
|
init_endpoints();
|
|
@@ -4400,7 +4731,64 @@ function createResponseHeaderDeadline(callerSignal, timeoutMs) {
|
|
|
4400
4731
|
};
|
|
4401
4732
|
}
|
|
4402
4733
|
|
|
4734
|
+
// ../kiro-core/dist/usage-tracking.js
|
|
4735
|
+
var DEFAULT_USD_PER_CREDIT = 0.04;
|
|
4736
|
+
var DEFAULT_ESTIMATED_CACHE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
4737
|
+
var KIRO_USAGE_TRACKING_DISABLED = Object.freeze({
|
|
4738
|
+
estimateDollarValue: false,
|
|
4739
|
+
usdPerCredit: DEFAULT_USD_PER_CREDIT,
|
|
4740
|
+
estimateCacheUsage: false,
|
|
4741
|
+
estimatedCacheTimeout: DEFAULT_ESTIMATED_CACHE_TIMEOUT_MS
|
|
4742
|
+
});
|
|
4743
|
+
var CREDIT_UNITS = /* @__PURE__ */ new Set(["credit", "credits"]);
|
|
4744
|
+
function estimateKiroCreditCost(tracking, metering) {
|
|
4745
|
+
if (!tracking.estimateDollarValue || !metering)
|
|
4746
|
+
return void 0;
|
|
4747
|
+
if (typeof metering.unit !== "string" || !CREDIT_UNITS.has(metering.unit.toLowerCase()))
|
|
4748
|
+
return void 0;
|
|
4749
|
+
const { credits } = metering;
|
|
4750
|
+
if (typeof credits !== "number" || !Number.isFinite(credits) || credits < 0)
|
|
4751
|
+
return void 0;
|
|
4752
|
+
return credits * tracking.usdPerCredit;
|
|
4753
|
+
}
|
|
4754
|
+
|
|
4403
4755
|
// ../kiro-core/dist/stream.js
|
|
4756
|
+
function describeAttempts(count) {
|
|
4757
|
+
return count === 1 ? "1 attempt" : `${count} attempts`;
|
|
4758
|
+
}
|
|
4759
|
+
var DIAGNOSTIC_QUOTE_LIMIT = 200;
|
|
4760
|
+
function clampForDiagnostic(text) {
|
|
4761
|
+
return text.length <= DIAGNOSTIC_QUOTE_LIMIT ? text : `${text.slice(0, DIAGNOSTIC_QUOTE_LIMIT)}\u2026 (truncated)`;
|
|
4762
|
+
}
|
|
4763
|
+
function encodeBytesForDiagnostic(bytes) {
|
|
4764
|
+
let encoded = "";
|
|
4765
|
+
for (const byte of bytes) {
|
|
4766
|
+
encoded += String.fromCharCode(65 + (byte >> 4), 65 + (byte & 15));
|
|
4767
|
+
}
|
|
4768
|
+
return encoded;
|
|
4769
|
+
}
|
|
4770
|
+
function encodeToolNameForDiagnostic(name) {
|
|
4771
|
+
const identity = typeof name === "string" ? name : `${typeof name}:${JSON.stringify(name)}`;
|
|
4772
|
+
let encoded = "";
|
|
4773
|
+
for (let i = 0; i < identity.length; i++) {
|
|
4774
|
+
const codeUnit = identity.charCodeAt(i);
|
|
4775
|
+
encoded += String.fromCharCode(65 + (codeUnit >> 12), 65 + (codeUnit >> 8 & 15), 65 + (codeUnit >> 4 & 15), 65 + (codeUnit & 15));
|
|
4776
|
+
}
|
|
4777
|
+
return encoded;
|
|
4778
|
+
}
|
|
4779
|
+
function describeDroppedToolNames(names) {
|
|
4780
|
+
const encoded = names.map((name) => `A-P:${encodeToolNameForDiagnostic(name)}`).join(", ");
|
|
4781
|
+
if (encoded.length <= DIAGNOSTIC_QUOTE_LIMIT)
|
|
4782
|
+
return encoded;
|
|
4783
|
+
const digest = createHash3("sha256").update(JSON.stringify(names)).digest();
|
|
4784
|
+
return `A-P-DIGEST:${encodeBytesForDiagnostic(digest)} (tool identities fingerprinted)`;
|
|
4785
|
+
}
|
|
4786
|
+
function describeReturnedContent(kinds) {
|
|
4787
|
+
const unique = [...new Set(kinds)].sort();
|
|
4788
|
+
if (unique.length === 0)
|
|
4789
|
+
return "returning empty content";
|
|
4790
|
+
return `returning only ${unique.join(" and ")} content`;
|
|
4791
|
+
}
|
|
4404
4792
|
var skipProfileResolutionForTests = false;
|
|
4405
4793
|
var TEST_PROFILE_ARN = "arn:aws:codewhisperer:us-east-1:000000000000:profile/test";
|
|
4406
4794
|
async function* streamKiro(request) {
|
|
@@ -4411,7 +4799,6 @@ async function* streamKiro(request) {
|
|
|
4411
4799
|
}
|
|
4412
4800
|
let accessToken = initialAccessToken;
|
|
4413
4801
|
const region = model.region ?? "us-east-1";
|
|
4414
|
-
const endpoint = new URL("generateAssistantResponse", getKiroEndpoints(region).runtime).toString();
|
|
4415
4802
|
let managementAuth = { accessToken, region };
|
|
4416
4803
|
const cliCreds = getKiroCliCredentials() ?? getKiroCliCredentialsAllowExpired();
|
|
4417
4804
|
const cliProfileArn = cliCreds?.access === accessToken ? cliCreds.profileArn : void 0;
|
|
@@ -4430,9 +4817,11 @@ async function* streamKiro(request) {
|
|
|
4430
4817
|
managementAuth = { accessToken, region };
|
|
4431
4818
|
profileArn = freshCreds.profileArn || (skipProfileResolutionForTests ? TEST_PROFILE_ARN : await resolveKiroProfileArn(managementAuth));
|
|
4432
4819
|
}
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4820
|
+
let runtimeRegion = getKiroRegionFromProfileArn(profileArn) ?? region;
|
|
4821
|
+
let endpoint = new URL("generateAssistantResponse", getKiroEndpoints(runtimeRegion).runtime).toString();
|
|
4822
|
+
if (!process.env.VITEST && isCacheStale(runtimeRegion)) {
|
|
4823
|
+
updateKiroModelsCache(accessToken, runtimeRegion, profileArn).catch((error2) => {
|
|
4824
|
+
console.warn(`[kiro-core] Failed to refresh Kiro model catalog in ${runtimeRegion}: ${formatSafeError(error2)}`);
|
|
4436
4825
|
});
|
|
4437
4826
|
}
|
|
4438
4827
|
const kiroModelId = resolveKiroModel(model.id, model.kiroModelId);
|
|
@@ -4461,8 +4850,13 @@ async function* streamKiro(request) {
|
|
|
4461
4850
|
${systemPrompt}` : ""}`;
|
|
4462
4851
|
}
|
|
4463
4852
|
const assembler = new KiroResponseAssembler(model, thinkingEnabled);
|
|
4853
|
+
const usageTracking = request.usageTracking ?? KIRO_USAGE_TRACKING_DISABLED;
|
|
4464
4854
|
let retryCount = 0;
|
|
4465
4855
|
const maxRetries = 3;
|
|
4856
|
+
let emptyAttempts = 0;
|
|
4857
|
+
let echoAttempts = 0;
|
|
4858
|
+
let credentialRefreshTotal = 0;
|
|
4859
|
+
let capacityRetryTotal = 0;
|
|
4466
4860
|
const conversationId = request.sessionId ?? crypto.randomUUID();
|
|
4467
4861
|
requestLoop: while (retryCount <= maxRetries) {
|
|
4468
4862
|
if (signal?.aborted)
|
|
@@ -4545,6 +4939,7 @@ ${systemPrompt}` : ""}`;
|
|
|
4545
4939
|
});
|
|
4546
4940
|
if (isCapacityError(errText) && capacityRetryCount < capacityRetryConfig.maxRetries) {
|
|
4547
4941
|
capacityRetryCount++;
|
|
4942
|
+
capacityRetryTotal++;
|
|
4548
4943
|
const delayMs = exponentialBackoff(capacityRetryCount - 1, capacityRetryConfig.baseDelayMs, 3e4);
|
|
4549
4944
|
logCapacityEvent(`INSUFFICIENT_MODEL_CAPACITY \u2014 retrying in ${delayMs}ms (${capacityRetryCount}/${capacityRetryConfig.maxRetries})`);
|
|
4550
4945
|
await abortableDelay(delayMs, signal);
|
|
@@ -4572,6 +4967,7 @@ ${systemPrompt}` : ""}`;
|
|
|
4572
4967
|
}
|
|
4573
4968
|
if (response.status === 403 && !isCapacityError(errText) && retryCount < maxRetries) {
|
|
4574
4969
|
retryCount++;
|
|
4970
|
+
credentialRefreshTotal++;
|
|
4575
4971
|
invalidateKiroProfileArn(managementAuth);
|
|
4576
4972
|
const rejectedAccessToken = accessToken;
|
|
4577
4973
|
const rejectedProfileArn = profileArn;
|
|
@@ -4583,16 +4979,23 @@ ${systemPrompt}` : ""}`;
|
|
|
4583
4979
|
managementAuth = { accessToken, region };
|
|
4584
4980
|
const inheritedDesktopProfileArn = rejectedCliCreds?.authMethod === "desktop" && freshCreds?.authMethod === "desktop" ? rejectedProfileArn : void 0;
|
|
4585
4981
|
profileArn = freshCreds?.profileArn || inheritedDesktopProfileArn || (skipProfileResolutionForTests ? TEST_PROFILE_ARN : await resolveKiroProfileArn(managementAuth));
|
|
4982
|
+
runtimeRegion = getKiroRegionFromProfileArn(profileArn) ?? region;
|
|
4983
|
+
endpoint = new URL("generateAssistantResponse", getKiroEndpoints(runtimeRegion).runtime).toString();
|
|
4586
4984
|
await abortableDelay(exponentialBackoff(retryCount - 1, 500, MAX_RETRY_DELAY), signal);
|
|
4587
4985
|
break;
|
|
4588
4986
|
}
|
|
4987
|
+
const errorMeta = {
|
|
4988
|
+
reasonCode: extractKiroReasonCode(errText),
|
|
4989
|
+
retryAfterMs: parseRetryAfterMs(response.headers),
|
|
4990
|
+
providerAttempts: { credentialRefresh: credentialRefreshTotal, capacity: capacityRetryTotal }
|
|
4991
|
+
};
|
|
4589
4992
|
if (isNonRetryableBodyError(errText) || isCapacityError(errText)) {
|
|
4590
|
-
throw new
|
|
4993
|
+
throw new KiroApiError(`Kiro API error: ${errText || safeStatusText}`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4591
4994
|
}
|
|
4592
4995
|
if (isTooBigError(response.status, errText)) {
|
|
4593
|
-
throw new
|
|
4996
|
+
throw new KiroApiError(`Kiro API error: context_length_exceeded (${response.status} ${errText})`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4594
4997
|
}
|
|
4595
|
-
throw new
|
|
4998
|
+
throw new KiroApiError(`Kiro API error: ${response.status} ${safeStatusText} ${errText}`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4596
4999
|
}
|
|
4597
5000
|
break;
|
|
4598
5001
|
}
|
|
@@ -4606,7 +5009,8 @@ ${systemPrompt}` : ""}`;
|
|
|
4606
5009
|
throw new Error("No response body");
|
|
4607
5010
|
assembler.beginAttempt();
|
|
4608
5011
|
const { frames, outcome } = readKiroEventStream(response.body, {
|
|
4609
|
-
firstTokenTimeoutMs: model.firstTokenTimeout ?? firstTokenTimeoutForModel(model.id)
|
|
5012
|
+
firstTokenTimeoutMs: model.firstTokenTimeout ?? firstTokenTimeoutForModel(model.id),
|
|
5013
|
+
signal
|
|
4610
5014
|
});
|
|
4611
5015
|
for await (const frame of frames) {
|
|
4612
5016
|
assembler.handle(frame);
|
|
@@ -4616,6 +5020,11 @@ ${systemPrompt}` : ""}`;
|
|
|
4616
5020
|
if (outcome.firstTokenTimedOut || outcome.idleTimedOut || outcome.error) {
|
|
4617
5021
|
if (retryCount < maxRetries) {
|
|
4618
5022
|
retryCount++;
|
|
5023
|
+
if (outcome.errorData && debugEnabled()) {
|
|
5024
|
+
debugLog("stream.error.typed", [outcome.errorData]);
|
|
5025
|
+
}
|
|
5026
|
+
assembler.discard();
|
|
5027
|
+
yield* assembler.takeEvents();
|
|
4619
5028
|
await abortableDelay(exponentialBackoff(retryCount - 1, 1e3, MAX_RETRY_DELAY), signal);
|
|
4620
5029
|
continue;
|
|
4621
5030
|
}
|
|
@@ -4625,7 +5034,13 @@ ${systemPrompt}` : ""}`;
|
|
|
4625
5034
|
}
|
|
4626
5035
|
const summary = assembler.endTurn();
|
|
4627
5036
|
yield* assembler.takeEvents();
|
|
4628
|
-
|
|
5037
|
+
const degenerate = summary.isEmpty || summary.isEchoLoop;
|
|
5038
|
+
if (summary.isEchoLoop)
|
|
5039
|
+
echoAttempts++;
|
|
5040
|
+
else if (degenerate)
|
|
5041
|
+
emptyAttempts++;
|
|
5042
|
+
let errorMessage;
|
|
5043
|
+
if (degenerate) {
|
|
4629
5044
|
const mayRetry = retryCount < maxRetries && (!summary.isEchoLoop || request.canDiscardEmittedBlocks === true);
|
|
4630
5045
|
if (mayRetry) {
|
|
4631
5046
|
retryCount++;
|
|
@@ -4637,15 +5052,39 @@ ${systemPrompt}` : ""}`;
|
|
|
4637
5052
|
}
|
|
4638
5053
|
if (summary.isEchoLoop) {
|
|
4639
5054
|
assembler.stripEcho();
|
|
4640
|
-
|
|
5055
|
+
const alsoEmpty = emptyAttempts > 0 ? ` (plus ${describeAttempts(emptyAttempts)} with no text at all)` : "";
|
|
5056
|
+
console.warn(`[kiro-core] Echo loop persisted across ${describeAttempts(echoAttempts)}${alsoEmpty} \u2014 stripping "Continue" response (${summary.responseText.length} chars)`);
|
|
5057
|
+
errorMessage = `Kiro model echoed its own continuation prompt (${JSON.stringify(clampForDiagnostic(summary.responseText))}) on ${describeAttempts(echoAttempts)}${alsoEmpty} and emitted no tool calls; retry budget exhausted, text stripped, stopReason:"${summary.stopReason}"`;
|
|
4641
5058
|
} else {
|
|
4642
|
-
|
|
5059
|
+
const alsoEchoed = echoAttempts > 0 ? ` (plus ${describeAttempts(echoAttempts)} that echoed the continuation prompt)` : "";
|
|
5060
|
+
console.warn(`[kiro-core] Empty response on ${describeAttempts(emptyAttempts)}${alsoEchoed}, retry budget exhausted \u2014 returning stopReason:"${summary.stopReason}" to avoid agent loop stall`);
|
|
5061
|
+
errorMessage = `Kiro returned no text and no tool calls on ${describeAttempts(emptyAttempts)}${alsoEchoed}; retry budget exhausted, ${describeReturnedContent(assembler.contentKinds())} with stopReason:"${summary.stopReason}"`;
|
|
4643
5062
|
}
|
|
4644
5063
|
}
|
|
4645
|
-
|
|
5064
|
+
if (summary.droppedToolCalls.length > 0) {
|
|
5065
|
+
const names = describeDroppedToolNames(summary.droppedToolCalls);
|
|
5066
|
+
const one = summary.droppedToolCalls.length === 1;
|
|
5067
|
+
const dropDiagnostic = `Kiro sent ${one ? "a tool call" : "tool calls"} with unparseable arguments (${names}); ${one ? "it was" : "they were"} dropped and never reached the agent, stopReason:"${summary.stopReason}"`;
|
|
5068
|
+
errorMessage = errorMessage ? `${errorMessage}. ${dropDiagnostic}` : dropDiagnostic;
|
|
5069
|
+
}
|
|
5070
|
+
const { stopReason, usage, wireUsage, metering } = assembler.complete();
|
|
4646
5071
|
yield* assembler.takeEvents();
|
|
5072
|
+
if (!errorMessage) {
|
|
5073
|
+
const estimatedRead = applyCacheEstimate(conversationId, usage, wireUsage, usageTracking);
|
|
5074
|
+
if (estimatedRead > 0) {
|
|
5075
|
+
debugLog("usage.estimate", {
|
|
5076
|
+
conversationId,
|
|
5077
|
+
estimatedRead,
|
|
5078
|
+
input: usage.input,
|
|
5079
|
+
cacheRead: usage.cacheRead
|
|
5080
|
+
});
|
|
5081
|
+
}
|
|
5082
|
+
const estimatedCost = estimateKiroCreditCost(usageTracking, metering);
|
|
5083
|
+
if (estimatedCost !== void 0)
|
|
5084
|
+
usage.cost.total = estimatedCost;
|
|
5085
|
+
}
|
|
4647
5086
|
yield { type: "usage", usage };
|
|
4648
|
-
yield { type: "done", stopReason };
|
|
5087
|
+
yield { type: "done", stopReason, ...errorMessage ? { errorMessage } : {} };
|
|
4649
5088
|
return;
|
|
4650
5089
|
}
|
|
4651
5090
|
}
|
|
@@ -5023,10 +5462,20 @@ function streamKiroForOmp(model, context, options) {
|
|
|
5023
5462
|
if (event.usage.contextPercent !== void 0) {
|
|
5024
5463
|
output.usage.contextPercent = event.usage.contextPercent;
|
|
5025
5464
|
}
|
|
5465
|
+
if (event.usage.credits !== void 0) {
|
|
5466
|
+
output.usage.credits = event.usage.credits;
|
|
5467
|
+
}
|
|
5468
|
+
if (event.usage.creditUnit !== void 0) {
|
|
5469
|
+
output.usage.creditUnit = event.usage.creditUnit;
|
|
5470
|
+
}
|
|
5471
|
+
if (event.usage.cacheEstimated !== void 0) {
|
|
5472
|
+
output.usage.cacheEstimated = event.usage.cacheEstimated;
|
|
5473
|
+
}
|
|
5026
5474
|
break;
|
|
5027
5475
|
}
|
|
5028
5476
|
case "done":
|
|
5029
5477
|
output.stopReason = event.stopReason;
|
|
5478
|
+
if (event.errorMessage) output.errorMessage = event.errorMessage;
|
|
5030
5479
|
stream.push({ type: "done", reason: event.stopReason, message: output });
|
|
5031
5480
|
break;
|
|
5032
5481
|
}
|