ns-omp-provider-kiro 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1483 -1050
- 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",
|
|
@@ -642,803 +649,337 @@ var init_kiro_ide = __esm({
|
|
|
642
649
|
}
|
|
643
650
|
});
|
|
644
651
|
|
|
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));
|
|
652
|
+
// ../kiro-core/dist/oauth.js
|
|
653
|
+
function kiroUserAgent(service, sdkVersion) {
|
|
654
|
+
return {
|
|
655
|
+
"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`,
|
|
656
|
+
"amz-sdk-invocation-id": "00000000-0000-0000-0000-000000000000",
|
|
657
|
+
"amz-sdk-request": `attempt=1; max=${sdkVersion}`
|
|
658
|
+
};
|
|
674
659
|
}
|
|
675
|
-
function
|
|
676
|
-
|
|
660
|
+
function kiroAuthHeaders(token) {
|
|
661
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
662
|
+
if (isApiKey(token))
|
|
663
|
+
headers.tokentype = "API_KEY";
|
|
664
|
+
return headers;
|
|
677
665
|
}
|
|
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");
|
|
666
|
+
function isApiKey(token) {
|
|
667
|
+
return token.startsWith("ksk_");
|
|
686
668
|
}
|
|
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;
|
|
669
|
+
async function loginKiroWithApiKey(apiKey, onProgress) {
|
|
670
|
+
if (!apiKey.startsWith("ksk_")) {
|
|
671
|
+
throw new Error("Invalid API key format. Kiro API keys start with 'ksk_'.");
|
|
696
672
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
673
|
+
onProgress?.("Validating API key...");
|
|
674
|
+
const region = "us-east-1";
|
|
675
|
+
const managementUrl = `https://management.${resolveApiRegion(region)}.kiro.dev/`;
|
|
676
|
+
const response = await fetch(managementUrl, {
|
|
677
|
+
method: "POST",
|
|
678
|
+
headers: {
|
|
679
|
+
"Content-Type": "application/x-amz-json-1.0",
|
|
680
|
+
"X-Amz-Target": "AmazonCodeWhispererService.GetProfile",
|
|
681
|
+
...kiroAuthHeaders(apiKey),
|
|
682
|
+
...kiroUserAgent("codewhispererruntime", "F,C")
|
|
683
|
+
},
|
|
684
|
+
body: "{}"
|
|
685
|
+
});
|
|
686
|
+
if (!response.ok) {
|
|
687
|
+
let detail = "";
|
|
688
|
+
try {
|
|
689
|
+
detail = await response.text();
|
|
690
|
+
} catch {
|
|
691
|
+
detail = "";
|
|
701
692
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
if (modelIds.has(model.id))
|
|
705
|
-
return void 0;
|
|
706
|
-
modelIds.add(model.id);
|
|
693
|
+
if (response.status === 401 || response.status === 403 || /Invalid token/i.test(detail)) {
|
|
694
|
+
throw new Error("API key was rejected by Kiro. Check that the key is valid and not expired.");
|
|
707
695
|
}
|
|
708
|
-
|
|
696
|
+
throw new Error(`Kiro GetProfile failed: ${response.status} ${response.statusText} ${detail}`.trim());
|
|
709
697
|
}
|
|
698
|
+
const data = await response.json();
|
|
699
|
+
const profileArn = data.profile?.arn;
|
|
710
700
|
return {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
701
|
+
access: apiKey,
|
|
702
|
+
refresh: `${apiKey}|apikey`,
|
|
703
|
+
expires: Date.now() + 365 * 24 * 60 * 60 * 1e3,
|
|
704
|
+
clientId: "",
|
|
705
|
+
clientSecret: "",
|
|
706
|
+
region,
|
|
707
|
+
authMethod: "apikey",
|
|
708
|
+
...profileArn ? { profileArn } : {}
|
|
714
709
|
};
|
|
715
710
|
}
|
|
716
|
-
function
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
711
|
+
async function refreshKiroToken(credentials) {
|
|
712
|
+
const refreshed = await refreshKiroTokenInternal(credentials);
|
|
713
|
+
if (!process.env.VITEST) {
|
|
714
|
+
try {
|
|
715
|
+
const { updateKiroModelsCache: updateKiroModelsCache2 } = await Promise.resolve().then(() => (init_models(), models_exports));
|
|
716
|
+
const region = resolveApiRegion(refreshed.region);
|
|
717
|
+
updateKiroModelsCache2(refreshed.access, region, refreshed.profileArn).catch((error2) => {
|
|
718
|
+
console.warn(`[kiro-core] Failed to refresh Kiro model catalog in ${region}: ${formatSafeError(error2)}`);
|
|
719
|
+
});
|
|
720
|
+
} catch (error2) {
|
|
721
|
+
console.warn(`[kiro-core] Failed to start Kiro model catalog refresh: ${formatSafeError(error2)}`);
|
|
722
|
+
}
|
|
723
723
|
}
|
|
724
|
+
return refreshed;
|
|
724
725
|
}
|
|
725
|
-
function
|
|
726
|
-
const
|
|
726
|
+
async function refreshKiroTokenInternal(credentials) {
|
|
727
|
+
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2, saveKiroCliCredentials: saveKiroCliCredentials2, getKiroCliSocialToken: getKiroCliSocialToken2, getKiroCliSocialTokenAllowExpired: getKiroCliSocialTokenAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
728
|
+
const credentialAuthMethod = credentials.authMethod ?? (credentials.refresh.split("|").at(-1) === "desktop" ? "desktop" : "idc");
|
|
729
|
+
const getValidCliCredentials = () => {
|
|
730
|
+
if (credentialAuthMethod === "desktop")
|
|
731
|
+
return getKiroCliSocialToken2();
|
|
732
|
+
const cliCreds = getKiroCliCredentials2();
|
|
733
|
+
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
734
|
+
};
|
|
735
|
+
const getExpiredCliCredentials = () => {
|
|
736
|
+
if (credentialAuthMethod === "desktop")
|
|
737
|
+
return getKiroCliSocialTokenAllowExpired2();
|
|
738
|
+
const cliCreds = getKiroCliCredentialsAllowExpired2();
|
|
739
|
+
return cliCreds?.authMethod === "idc" ? cliCreds : void 0;
|
|
740
|
+
};
|
|
741
|
+
if (credentials.authMethod === "apikey" || isApiKey(credentials.access))
|
|
742
|
+
return credentials;
|
|
743
|
+
if (credentialAuthMethod === "idc") {
|
|
744
|
+
const ideCreds = getKiroIdeCredentials();
|
|
745
|
+
if (ideCreds)
|
|
746
|
+
return ideCreds;
|
|
747
|
+
}
|
|
748
|
+
const preCheckCreds = getValidCliCredentials();
|
|
749
|
+
if (preCheckCreds)
|
|
750
|
+
return preCheckCreds;
|
|
727
751
|
try {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
752
|
+
const refreshed = await refreshKiroTokenDirect(credentials);
|
|
753
|
+
saveKiroCliCredentials2(refreshed);
|
|
754
|
+
return refreshed;
|
|
755
|
+
} catch (refreshError) {
|
|
756
|
+
const retryCreds = getValidCliCredentials();
|
|
757
|
+
if (retryCreds)
|
|
758
|
+
return retryCreds;
|
|
759
|
+
const expiredCliCreds = getExpiredCliCredentials();
|
|
760
|
+
if (expiredCliCreds && expiredCliCreds.refresh !== credentials.refresh) {
|
|
761
|
+
try {
|
|
762
|
+
const refreshedFromCli = await refreshKiroTokenDirect(expiredCliCreds);
|
|
763
|
+
saveKiroCliCredentials2(refreshedFromCli);
|
|
764
|
+
return refreshedFromCli;
|
|
765
|
+
} catch {
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
const actualExpiry = credentials.expires + EXPIRES_BUFFER_MS;
|
|
769
|
+
if (credentials.access && Date.now() < actualExpiry) {
|
|
770
|
+
return { ...credentials, expires: actualExpiry };
|
|
771
|
+
}
|
|
772
|
+
throw refreshError;
|
|
732
773
|
}
|
|
733
774
|
}
|
|
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`);
|
|
765
|
-
}
|
|
766
|
-
const tokenLimits = model.tokenLimits;
|
|
767
|
-
if (tokenLimits !== void 0 && !isRecord2(tokenLimits)) {
|
|
768
|
-
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
769
|
-
}
|
|
770
|
-
if (tokenLimits && (tokenLimits.maxInputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxInputTokens) || tokenLimits.maxOutputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxOutputTokens))) {
|
|
771
|
-
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
775
|
+
async function refreshKiroTokenDirect(credentials) {
|
|
776
|
+
const parts = credentials.refresh.split("|");
|
|
777
|
+
const refreshToken = parts[0] ?? "";
|
|
778
|
+
const authMethod = parts[parts.length - 1] ?? "idc";
|
|
779
|
+
const region = credentials.region || "us-east-1";
|
|
780
|
+
if (authMethod === "apikey")
|
|
781
|
+
return credentials;
|
|
782
|
+
if (authMethod === "desktop") {
|
|
783
|
+
const url = KIRO_DESKTOP_REFRESH_URL.replace("{region}", region);
|
|
784
|
+
const response2 = await fetch(url, {
|
|
785
|
+
method: "POST",
|
|
786
|
+
headers: { "Content-Type": "application/json", "User-Agent": KIRO_DESKTOP_USER_AGENT },
|
|
787
|
+
body: JSON.stringify({ refreshToken })
|
|
788
|
+
});
|
|
789
|
+
if (!response2.ok)
|
|
790
|
+
throw new Error(`Desktop token refresh failed: ${response2.status}`);
|
|
791
|
+
const data2 = await response2.json();
|
|
792
|
+
if (!data2.accessToken)
|
|
793
|
+
throw new Error("Desktop token refresh: missing accessToken");
|
|
794
|
+
return {
|
|
795
|
+
refresh: `${data2.refreshToken || refreshToken}|desktop`,
|
|
796
|
+
access: data2.accessToken,
|
|
797
|
+
expires: Date.now() + data2.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
798
|
+
clientId: "",
|
|
799
|
+
clientSecret: "",
|
|
800
|
+
region,
|
|
801
|
+
authMethod: "desktop",
|
|
802
|
+
profileArn: data2.profileArn || credentials.profileArn,
|
|
803
|
+
startUrl: credentials.startUrl
|
|
804
|
+
};
|
|
772
805
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
const
|
|
794
|
-
|
|
806
|
+
if (authMethod === "external-idp") {
|
|
807
|
+
const idpClientId = parts[1] ?? "";
|
|
808
|
+
const tokenEndpoint = parts[2] ?? "";
|
|
809
|
+
if (!tokenEndpoint)
|
|
810
|
+
throw new Error("External IdP token refresh: missing token endpoint");
|
|
811
|
+
const response2 = await fetch(tokenEndpoint, {
|
|
812
|
+
method: "POST",
|
|
813
|
+
headers: {
|
|
814
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
815
|
+
Accept: "application/json",
|
|
816
|
+
"User-Agent": "kiro-core"
|
|
817
|
+
},
|
|
818
|
+
body: new URLSearchParams({
|
|
819
|
+
grant_type: "refresh_token",
|
|
820
|
+
client_id: idpClientId,
|
|
821
|
+
refresh_token: refreshToken
|
|
822
|
+
}).toString()
|
|
823
|
+
});
|
|
824
|
+
if (!response2.ok)
|
|
825
|
+
throw new Error(`External IdP token refresh failed: ${response2.status}`);
|
|
826
|
+
const data2 = await response2.json();
|
|
827
|
+
if (!data2.access_token)
|
|
828
|
+
throw new Error("External IdP token refresh: missing access_token");
|
|
829
|
+
const expiresIn = typeof data2.expires_in === "number" ? data2.expires_in : 3600;
|
|
795
830
|
return {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
831
|
+
refresh: `${data2.refresh_token || refreshToken}|${idpClientId}|${tokenEndpoint}|external-idp`,
|
|
832
|
+
access: data2.access_token,
|
|
833
|
+
expires: Date.now() + expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
834
|
+
clientId: idpClientId,
|
|
835
|
+
clientSecret: "",
|
|
799
836
|
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 } : {}
|
|
837
|
+
authMethod: "external-idp",
|
|
838
|
+
profileArn: credentials.profileArn
|
|
814
839
|
};
|
|
840
|
+
}
|
|
841
|
+
const clientId = parts[1] ?? "";
|
|
842
|
+
const clientSecret = parts[2] ?? "";
|
|
843
|
+
const ssoEndpoint = `https://oidc.${region}.amazonaws.com`;
|
|
844
|
+
const response = await fetch(`${ssoEndpoint}/token`, {
|
|
845
|
+
method: "POST",
|
|
846
|
+
headers: { "Content-Type": "application/json", ...kiroUserAgent("ssooidc", "E") },
|
|
847
|
+
body: JSON.stringify({ clientId, clientSecret, refreshToken, grantType: "refresh_token" })
|
|
815
848
|
});
|
|
849
|
+
if (!response.ok)
|
|
850
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
851
|
+
const data = await response.json();
|
|
852
|
+
return {
|
|
853
|
+
refresh: `${data.refreshToken}|${clientId}|${clientSecret}|idc`,
|
|
854
|
+
access: data.accessToken,
|
|
855
|
+
expires: Date.now() + data.expiresIn * 1e3 - EXPIRES_BUFFER_MS,
|
|
856
|
+
clientId,
|
|
857
|
+
clientSecret,
|
|
858
|
+
region,
|
|
859
|
+
authMethod: "idc",
|
|
860
|
+
profileArn: credentials.profileArn,
|
|
861
|
+
startUrl: credentials.startUrl,
|
|
862
|
+
isEnterprise: credentials.isEnterprise
|
|
863
|
+
};
|
|
816
864
|
}
|
|
817
|
-
function
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
865
|
+
async function resolveKiroCredentials() {
|
|
866
|
+
const { getKiroCliCredentials: getKiroCliCredentials2, getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli(), kiro_cli_exports));
|
|
867
|
+
const fresh = getKiroCliCredentials2() ?? getKiroIdeCredentials();
|
|
868
|
+
if (fresh)
|
|
869
|
+
return fresh;
|
|
870
|
+
const stale = getKiroCliCredentialsAllowExpired2();
|
|
871
|
+
if (!stale)
|
|
872
|
+
return void 0;
|
|
873
|
+
return refreshKiroToken(stale);
|
|
827
874
|
}
|
|
828
|
-
|
|
829
|
-
|
|
875
|
+
var KIRO_DESKTOP_REFRESH_URL, EXPIRES_BUFFER_MS, KIRO_DESKTOP_USER_AGENT;
|
|
876
|
+
var init_oauth = __esm({
|
|
877
|
+
"../kiro-core/dist/oauth.js"() {
|
|
878
|
+
"use strict";
|
|
879
|
+
init_debug();
|
|
880
|
+
init_endpoints();
|
|
881
|
+
init_kiro_ide();
|
|
882
|
+
KIRO_DESKTOP_REFRESH_URL = "https://prod.{region}.auth.desktop.kiro.dev/refreshToken";
|
|
883
|
+
EXPIRES_BUFFER_MS = 5 * 60 * 1e3;
|
|
884
|
+
KIRO_DESKTOP_USER_AGENT = "Kiro-Desktop/0.2.13 (darwin; arm64)";
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
// ../kiro-core/dist/token-type.js
|
|
889
|
+
function isExternalIdpAccessToken(accessToken) {
|
|
890
|
+
if (typeof accessToken !== "string")
|
|
891
|
+
return false;
|
|
892
|
+
const segments = accessToken.split(".");
|
|
893
|
+
if (segments.length !== 3)
|
|
894
|
+
return false;
|
|
895
|
+
const payloadSegment = segments[1];
|
|
896
|
+
if (!payloadSegment)
|
|
897
|
+
return false;
|
|
898
|
+
try {
|
|
899
|
+
const payload = JSON.parse(Buffer.from(payloadSegment.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf-8"));
|
|
900
|
+
return payload.aud === EXTERNAL_IDP_AUDIENCE;
|
|
901
|
+
} catch {
|
|
902
|
+
return false;
|
|
903
|
+
}
|
|
830
904
|
}
|
|
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;
|
|
905
|
+
function kiroTokenTypeHeaders(accessToken) {
|
|
906
|
+
return isExternalIdpAccessToken(accessToken) ? { tokentype: "EXTERNAL_IDP" } : {};
|
|
843
907
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
908
|
+
var EXTERNAL_IDP_AUDIENCE;
|
|
909
|
+
var init_token_type = __esm({
|
|
910
|
+
"../kiro-core/dist/token-type.js"() {
|
|
911
|
+
"use strict";
|
|
912
|
+
EXTERNAL_IDP_AUDIENCE = "api://kiro";
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
// ../kiro-core/dist/management.js
|
|
917
|
+
import { createHash } from "node:crypto";
|
|
918
|
+
function candidateManagementRegions(primary) {
|
|
919
|
+
const seen = /* @__PURE__ */ new Set([primary]);
|
|
920
|
+
const candidates = [primary];
|
|
921
|
+
for (const region of CANONICAL_MANAGEMENT_REGIONS) {
|
|
922
|
+
if (!seen.has(region)) {
|
|
923
|
+
seen.add(region);
|
|
924
|
+
candidates.push(region);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return candidates;
|
|
847
928
|
}
|
|
848
|
-
async function
|
|
849
|
-
const
|
|
850
|
-
const
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
929
|
+
async function requestManagement(auth, operation, path, method, body) {
|
|
930
|
+
const url = new URL(path, getKiroEndpoints(auth.region).management);
|
|
931
|
+
const request = {
|
|
932
|
+
method,
|
|
933
|
+
headers: {
|
|
934
|
+
Accept: "application/json",
|
|
935
|
+
...kiroAuthHeaders(auth.accessToken),
|
|
936
|
+
...kiroTokenTypeHeaders(auth.accessToken)
|
|
937
|
+
}
|
|
855
938
|
};
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
939
|
+
if (method === "GET") {
|
|
940
|
+
for (const [name, value] of Object.entries(body)) {
|
|
941
|
+
if (value !== void 0)
|
|
942
|
+
url.searchParams.set(name, String(value));
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
request.headers = { ...request.headers, "Content-Type": "application/json" };
|
|
946
|
+
request.body = JSON.stringify(body);
|
|
947
|
+
}
|
|
948
|
+
let response;
|
|
949
|
+
try {
|
|
950
|
+
response = await fetch(url.toString(), request);
|
|
951
|
+
} catch (error2) {
|
|
952
|
+
throw new Error(`Kiro management ${operation} request failed in ${auth.region}`, { cause: error2 });
|
|
953
|
+
}
|
|
954
|
+
return parseManagementResponse(response, operation, auth.region);
|
|
859
955
|
}
|
|
860
|
-
function
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
956
|
+
function profileCacheKey(auth) {
|
|
957
|
+
const tokenHash = createHash("sha256").update(auth.accessToken).digest("base64url");
|
|
958
|
+
return `${auth.region}:${tokenHash}`;
|
|
959
|
+
}
|
|
960
|
+
async function getApiKeyProfileArn(accessToken) {
|
|
961
|
+
const operation = "GetProfile";
|
|
962
|
+
let response;
|
|
963
|
+
try {
|
|
964
|
+
response = await fetch(getKiroEndpoints(API_KEY_REGION).management, {
|
|
965
|
+
method: "POST",
|
|
966
|
+
headers: {
|
|
967
|
+
"Content-Type": "application/x-amz-json-1.0",
|
|
968
|
+
"X-Amz-Target": GET_PROFILE_TARGET,
|
|
969
|
+
...kiroAuthHeaders(accessToken),
|
|
970
|
+
...kiroUserAgent("codewhispererruntime", "F,C")
|
|
971
|
+
},
|
|
972
|
+
body: "{}"
|
|
973
|
+
});
|
|
974
|
+
} catch (error2) {
|
|
975
|
+
throw new Error(`Kiro management ${operation} request failed in ${API_KEY_REGION}`, { cause: error2 });
|
|
867
976
|
}
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
loadCachedModelIds();
|
|
873
|
-
if (!KIRO_MODEL_IDS.has(normalizedId)) {
|
|
874
|
-
throw new Error(`Unknown Kiro model ID: ${modelId}`);
|
|
977
|
+
const parsed = await parseManagementResponse(response, operation, API_KEY_REGION);
|
|
978
|
+
const arn = parsed.profile?.arn;
|
|
979
|
+
if (!arn) {
|
|
980
|
+
throw new Error(`Kiro management ${operation} returned no profile in ${API_KEY_REGION}`);
|
|
875
981
|
}
|
|
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);
|
|
1414
|
-
}
|
|
1415
|
-
function profileCacheKey(auth) {
|
|
1416
|
-
const tokenHash = createHash2("sha256").update(auth.accessToken).digest("base64url");
|
|
1417
|
-
return `${auth.region}:${tokenHash}`;
|
|
1418
|
-
}
|
|
1419
|
-
async function getApiKeyProfileArn(accessToken) {
|
|
1420
|
-
const operation = "GetProfile";
|
|
1421
|
-
let response;
|
|
1422
|
-
try {
|
|
1423
|
-
response = await fetch(getKiroEndpoints(API_KEY_REGION).management, {
|
|
1424
|
-
method: "POST",
|
|
1425
|
-
headers: {
|
|
1426
|
-
"Content-Type": "application/x-amz-json-1.0",
|
|
1427
|
-
"X-Amz-Target": GET_PROFILE_TARGET,
|
|
1428
|
-
...kiroAuthHeaders(accessToken),
|
|
1429
|
-
...kiroUserAgent("codewhispererruntime", "F,C")
|
|
1430
|
-
},
|
|
1431
|
-
body: "{}"
|
|
1432
|
-
});
|
|
1433
|
-
} catch (error2) {
|
|
1434
|
-
throw new Error(`Kiro management ${operation} request failed in ${API_KEY_REGION}`, { cause: error2 });
|
|
1435
|
-
}
|
|
1436
|
-
const parsed = await parseManagementResponse(response, operation, API_KEY_REGION);
|
|
1437
|
-
const arn = parsed.profile?.arn;
|
|
1438
|
-
if (!arn) {
|
|
1439
|
-
throw new Error(`Kiro management ${operation} returned no profile in ${API_KEY_REGION}`);
|
|
1440
|
-
}
|
|
1441
|
-
return arn;
|
|
982
|
+
return arn;
|
|
1442
983
|
}
|
|
1443
984
|
async function parseManagementResponse(response, operation, region) {
|
|
1444
985
|
if (!response.ok) {
|
|
@@ -1517,75 +1058,544 @@ async function resolveKiroProfileArn(auth, providedArn) {
|
|
|
1517
1058
|
pendingProfileRequests.delete(key);
|
|
1518
1059
|
}
|
|
1519
1060
|
}
|
|
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}`);
|
|
1061
|
+
async function listAvailableModels(auth, profileArn) {
|
|
1062
|
+
const response = await requestManagement(auth, "ListAvailableModels", LIST_MODELS_PATH, "GET", {
|
|
1063
|
+
origin: "KIRO_CLI",
|
|
1064
|
+
profileArn
|
|
1065
|
+
});
|
|
1066
|
+
if (!Array.isArray(response.models) || response.models.length === 0) {
|
|
1067
|
+
throw new Error(`Kiro management ListAvailableModels returned no models in ${auth.region}`);
|
|
1068
|
+
}
|
|
1069
|
+
if (response.models.some((model) => !model || typeof model.modelId !== "string" || !model.modelId)) {
|
|
1070
|
+
throw new Error(`Kiro management ListAvailableModels returned an invalid catalog in ${auth.region}`);
|
|
1071
|
+
}
|
|
1072
|
+
return response;
|
|
1073
|
+
}
|
|
1074
|
+
async function fetchKiroModelCatalog(auth, providedProfileArn) {
|
|
1075
|
+
const profileArn = await resolveKiroProfileArn(auth, providedProfileArn);
|
|
1076
|
+
const region = isApiKey(auth.accessToken) ? API_KEY_REGION : profileRegionCache.get(profileCacheKey(auth)) ?? auth.region;
|
|
1077
|
+
if (region !== auth.region) {
|
|
1078
|
+
return listAvailableModels({ ...auth, region }, profileArn);
|
|
1079
|
+
}
|
|
1080
|
+
return listAvailableModels(auth, profileArn);
|
|
1081
|
+
}
|
|
1082
|
+
async function getUsageLimits(auth, request) {
|
|
1083
|
+
const operation = "GetUsageLimits";
|
|
1084
|
+
const url = new URL("Get-Usage-Limits", getKiroEndpoints(auth.region).management);
|
|
1085
|
+
for (const [name, value] of Object.entries(request)) {
|
|
1086
|
+
if (value !== void 0)
|
|
1087
|
+
url.searchParams.set(name, String(value));
|
|
1088
|
+
}
|
|
1089
|
+
let response;
|
|
1090
|
+
try {
|
|
1091
|
+
response = await fetch(url.toString(), {
|
|
1092
|
+
method: "GET",
|
|
1093
|
+
headers: {
|
|
1094
|
+
Accept: "application/json",
|
|
1095
|
+
...kiroAuthHeaders(auth.accessToken),
|
|
1096
|
+
...kiroTokenTypeHeaders(auth.accessToken),
|
|
1097
|
+
"User-Agent": "ns-kiro-provider"
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
} catch (error2) {
|
|
1101
|
+
throw new Error(`Kiro management ${operation} request failed in ${auth.region}`, { cause: error2 });
|
|
1102
|
+
}
|
|
1103
|
+
return parseManagementResponse(response, operation, auth.region);
|
|
1104
|
+
}
|
|
1105
|
+
var LIST_PROFILES_PATH, LIST_MODELS_PATH, GET_PROFILE_TARGET, API_KEY_REGION, profileArnCache, pendingProfileRequests, profileRegionCache, CANONICAL_MANAGEMENT_REGIONS, ENV_PROFILE_ARN, KiroManagementHttpError;
|
|
1106
|
+
var init_management = __esm({
|
|
1107
|
+
"../kiro-core/dist/management.js"() {
|
|
1108
|
+
"use strict";
|
|
1109
|
+
init_debug();
|
|
1110
|
+
init_endpoints();
|
|
1111
|
+
init_oauth();
|
|
1112
|
+
init_token_type();
|
|
1113
|
+
LIST_PROFILES_PATH = "List-Available-Profiles";
|
|
1114
|
+
LIST_MODELS_PATH = "List-Available-Models";
|
|
1115
|
+
GET_PROFILE_TARGET = "AmazonCodeWhispererService.GetProfile";
|
|
1116
|
+
API_KEY_REGION = "us-east-1";
|
|
1117
|
+
profileArnCache = /* @__PURE__ */ new Map();
|
|
1118
|
+
pendingProfileRequests = /* @__PURE__ */ new Map();
|
|
1119
|
+
profileRegionCache = /* @__PURE__ */ new Map();
|
|
1120
|
+
CANONICAL_MANAGEMENT_REGIONS = ["us-east-1", "eu-central-1"];
|
|
1121
|
+
ENV_PROFILE_ARN = "KIRO_PROFILE_ARN";
|
|
1122
|
+
KiroManagementHttpError = class extends Error {
|
|
1123
|
+
status;
|
|
1124
|
+
constructor(message, status) {
|
|
1125
|
+
super(message);
|
|
1126
|
+
this.status = status;
|
|
1127
|
+
this.name = "KiroManagementHttpError";
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
// ../kiro-core/dist/models.js
|
|
1134
|
+
var models_exports = {};
|
|
1135
|
+
__export(models_exports, {
|
|
1136
|
+
KIRO_MANAGEMENT_CACHE_PATH: () => KIRO_MANAGEMENT_CACHE_PATH,
|
|
1137
|
+
KIRO_MANAGEMENT_CACHE_SOURCE: () => KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1138
|
+
KIRO_MANAGEMENT_CACHE_VERSION: () => KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1139
|
+
KIRO_MODEL_IDS: () => KIRO_MODEL_IDS,
|
|
1140
|
+
applyEffortLadder: () => applyEffortLadder,
|
|
1141
|
+
getCachedModels: () => getCachedModels,
|
|
1142
|
+
isCacheStale: () => isCacheStale,
|
|
1143
|
+
kiroModels: () => kiroModels,
|
|
1144
|
+
loadCachedModelIds: () => loadCachedModelIds,
|
|
1145
|
+
mapKiroCatalogModels: () => mapKiroCatalogModels,
|
|
1146
|
+
resolveApiRegion: () => resolveApiRegion,
|
|
1147
|
+
resolveKiroModel: () => resolveKiroModel,
|
|
1148
|
+
updateKiroModelsCache: () => updateKiroModelsCache
|
|
1149
|
+
});
|
|
1150
|
+
import { randomUUID } from "node:crypto";
|
|
1151
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
1152
|
+
import { homedir as homedir4 } from "node:os";
|
|
1153
|
+
import { join as join4 } from "node:path";
|
|
1154
|
+
function isRecord2(value) {
|
|
1155
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1156
|
+
}
|
|
1157
|
+
function isPositiveNumber(value) {
|
|
1158
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
1159
|
+
}
|
|
1160
|
+
function isEffortList(value) {
|
|
1161
|
+
return Array.isArray(value) && value.length > 0 && value.every((effort) => KIRO_EFFORT_ORDER.includes(effort));
|
|
1162
|
+
}
|
|
1163
|
+
function isEffortMap(value) {
|
|
1164
|
+
return isRecord2(value) && Object.values(value).every((mapped) => typeof mapped === "string");
|
|
1165
|
+
}
|
|
1166
|
+
function isCachedKiroModel(value) {
|
|
1167
|
+
if (!isRecord2(value))
|
|
1168
|
+
return false;
|
|
1169
|
+
const cost = value.cost;
|
|
1170
|
+
const input = value.input;
|
|
1171
|
+
const schema = value.additionalModelRequestFieldsSchema;
|
|
1172
|
+
const tokenLimits = value.tokenLimits;
|
|
1173
|
+
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");
|
|
1174
|
+
}
|
|
1175
|
+
function parseManagementCache(raw) {
|
|
1176
|
+
let value;
|
|
1177
|
+
try {
|
|
1178
|
+
value = JSON.parse(raw);
|
|
1179
|
+
} catch {
|
|
1180
|
+
return void 0;
|
|
1181
|
+
}
|
|
1182
|
+
if (!isRecord2(value) || value.version !== KIRO_MANAGEMENT_CACHE_VERSION || value.source !== KIRO_MANAGEMENT_CACHE_SOURCE || !isRecord2(value.regions)) {
|
|
1183
|
+
return void 0;
|
|
1184
|
+
}
|
|
1185
|
+
const regions = {};
|
|
1186
|
+
for (const [region, rawEntry] of Object.entries(value.regions)) {
|
|
1187
|
+
if (!isRecord2(rawEntry) || rawEntry.region !== region || !isPositiveNumber(rawEntry.fetchedAt) || !Array.isArray(rawEntry.models) || rawEntry.models.length === 0 || !rawEntry.models.every(isCachedKiroModel)) {
|
|
1188
|
+
return void 0;
|
|
1189
|
+
}
|
|
1190
|
+
const modelIds = /* @__PURE__ */ new Set();
|
|
1191
|
+
for (const model of rawEntry.models) {
|
|
1192
|
+
if (modelIds.has(model.id))
|
|
1193
|
+
return void 0;
|
|
1194
|
+
modelIds.add(model.id);
|
|
1195
|
+
}
|
|
1196
|
+
regions[region] = rawEntry;
|
|
1197
|
+
}
|
|
1198
|
+
return {
|
|
1199
|
+
version: KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1200
|
+
source: KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1201
|
+
regions
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function readManagementCache() {
|
|
1205
|
+
if (!existsSync3(KIRO_MANAGEMENT_CACHE_PATH))
|
|
1206
|
+
return void 0;
|
|
1207
|
+
try {
|
|
1208
|
+
return parseManagementCache(readFileSync2(KIRO_MANAGEMENT_CACHE_PATH, "utf-8"));
|
|
1209
|
+
} catch {
|
|
1210
|
+
return void 0;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
function writeManagementCache(cache) {
|
|
1214
|
+
const temporaryPath = `${KIRO_MANAGEMENT_CACHE_PATH}.${process.pid}.${randomUUID()}.tmp`;
|
|
1215
|
+
try {
|
|
1216
|
+
writeFileSync(temporaryPath, JSON.stringify(cache, null, 2), "utf-8");
|
|
1217
|
+
renameSync(temporaryPath, KIRO_MANAGEMENT_CACHE_PATH);
|
|
1218
|
+
} finally {
|
|
1219
|
+
rmSync(temporaryPath, { force: true });
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
function toLocalModelId(kiroModelId) {
|
|
1223
|
+
return kiroModelId.replace(/(\d)\.(\d)/g, "$1-$2");
|
|
1224
|
+
}
|
|
1225
|
+
function humanizeModelId(modelId) {
|
|
1226
|
+
return modelId.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1227
|
+
}
|
|
1228
|
+
function applyEffortLadder(config) {
|
|
1229
|
+
if (!config || config.values.length === 0)
|
|
1230
|
+
return {};
|
|
1231
|
+
const efforts = KIRO_EFFORT_ORDER.filter((effort) => config.values.includes(effort));
|
|
1232
|
+
if (efforts.length === 0)
|
|
1233
|
+
return {};
|
|
1234
|
+
return { efforts, ...config.summarizedThinking ? { supportsSummarizedThinking: true } : {} };
|
|
1235
|
+
}
|
|
1236
|
+
function hasReasoningFamilyFallback(modelId) {
|
|
1237
|
+
const normalizedId = modelId.toLowerCase();
|
|
1238
|
+
return normalizedId === "auto" || REASONING_FAMILY_MARKERS.some((marker) => normalizedId.includes(marker));
|
|
1239
|
+
}
|
|
1240
|
+
function hasVerifiedImageInput(kiroModelId) {
|
|
1241
|
+
return kiroModelId.startsWith("claude-") || VERIFIED_IMAGE_MODEL_IDS.has(kiroModelId.toLowerCase());
|
|
1242
|
+
}
|
|
1243
|
+
function applyVerifiedCapabilities(model) {
|
|
1244
|
+
if (!hasVerifiedImageInput(model.kiroModelId) || model.input.includes("image"))
|
|
1245
|
+
return model;
|
|
1246
|
+
return { ...model, input: ["text", "image"] };
|
|
1247
|
+
}
|
|
1248
|
+
function validateCatalogMetadata(model) {
|
|
1249
|
+
const rawSchema = model.additionalModelRequestFieldsSchema;
|
|
1250
|
+
const schema = rawSchema ?? void 0;
|
|
1251
|
+
if (schema !== void 0 && !isRecord2(schema)) {
|
|
1252
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has an invalid request-fields schema`);
|
|
1527
1253
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1254
|
+
const tokenLimits = model.tokenLimits;
|
|
1255
|
+
if (tokenLimits !== void 0 && !isRecord2(tokenLimits)) {
|
|
1256
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
1530
1257
|
}
|
|
1531
|
-
|
|
1258
|
+
if (tokenLimits && (tokenLimits.maxInputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxInputTokens) || tokenLimits.maxOutputTokens !== void 0 && !isPositiveNumber(tokenLimits.maxOutputTokens))) {
|
|
1259
|
+
throw new Error(`Kiro management catalog model ${model.modelId} has invalid token limits`);
|
|
1260
|
+
}
|
|
1261
|
+
return { schema, tokenLimits };
|
|
1532
1262
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
if (region !== auth.region) {
|
|
1537
|
-
return listAvailableModels({ ...auth, region }, profileArn);
|
|
1263
|
+
function mapKiroCatalogModels(catalogModels, region, rates) {
|
|
1264
|
+
if (catalogModels.length === 0) {
|
|
1265
|
+
throw new Error(`Kiro management catalog returned no models in ${region}`);
|
|
1538
1266
|
}
|
|
1539
|
-
|
|
1267
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
1268
|
+
return catalogModels.map((catalogModel) => {
|
|
1269
|
+
const kiroModelId = catalogModel.modelId;
|
|
1270
|
+
if (!kiroModelId || kiroModelId.trim() !== kiroModelId) {
|
|
1271
|
+
throw new Error(`Kiro management catalog returned an invalid model ID in ${region}`);
|
|
1272
|
+
}
|
|
1273
|
+
const id = toLocalModelId(kiroModelId);
|
|
1274
|
+
if (seenIds.has(id)) {
|
|
1275
|
+
throw new Error(`Kiro management catalog contains conflicting model ID ${id} in ${region}`);
|
|
1276
|
+
}
|
|
1277
|
+
seenIds.add(id);
|
|
1278
|
+
const existing = kiroModels.find((model) => model.id === id);
|
|
1279
|
+
const rate = rates?.get(kiroModelId);
|
|
1280
|
+
const { schema, tokenLimits } = validateCatalogMetadata(catalogModel);
|
|
1281
|
+
const effortConfig = getKiroEffortConfig(schema, kiroModelId);
|
|
1282
|
+
const catalogName = typeof catalogModel.displayName === "string" && catalogModel.displayName.length > 0 ? catalogModel.displayName : void 0;
|
|
1283
|
+
return {
|
|
1284
|
+
id,
|
|
1285
|
+
kiroModelId,
|
|
1286
|
+
// Humanize the wire id, not the local one: `toLocalModelId` rewrites
|
|
1287
|
+
// `5.1` as `5-1`, and a display name derived from it loses the dot —
|
|
1288
|
+
// "Claude Fable 5 1" instead of "Claude Fable 5.1".
|
|
1289
|
+
name: catalogName ?? existing?.name ?? humanizeModelId(kiroModelId),
|
|
1290
|
+
region,
|
|
1291
|
+
// Deliberately schema-only: when a schema exists the resolver returns
|
|
1292
|
+
// `deriveKiroEffort(schema)`, and when it does not the family-marker guess
|
|
1293
|
+
// decides. The fallback tier feeds the ladders, not this flag.
|
|
1294
|
+
reasoning: schema !== void 0 && effortConfig !== void 0 || schema === void 0 && hasReasoningFamilyFallback(id),
|
|
1295
|
+
...applyEffortLadder(effortConfig),
|
|
1296
|
+
input: existing ? [...existing.input] : hasVerifiedImageInput(kiroModelId) ? ["text", "image"] : ["text"],
|
|
1297
|
+
...id.startsWith("claude-") ? { recoverTextToolCalls: false } : {},
|
|
1298
|
+
cost: ZERO_COST,
|
|
1299
|
+
...rate ? { rateMultiplier: rate.multiplier, ...rate.unit ? { rateUnit: rate.unit } : {} } : {},
|
|
1300
|
+
contextWindow: tokenLimits?.maxInputTokens ?? DEFAULT_CONTEXT_WINDOW,
|
|
1301
|
+
maxTokens: tokenLimits?.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
1302
|
+
...existing?.firstTokenTimeout ? { firstTokenTimeout: existing.firstTokenTimeout } : {},
|
|
1303
|
+
...schema ? { additionalModelRequestFieldsSchema: schema } : {},
|
|
1304
|
+
...tokenLimits ? { tokenLimits } : {}
|
|
1305
|
+
};
|
|
1306
|
+
});
|
|
1540
1307
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1308
|
+
function refreshKnownModelIds(cache) {
|
|
1309
|
+
KIRO_MODEL_IDS.clear();
|
|
1310
|
+
for (const modelId of BOOTSTRAP_KIRO_MODEL_IDS)
|
|
1311
|
+
KIRO_MODEL_IDS.add(modelId);
|
|
1312
|
+
if (!cache)
|
|
1313
|
+
return;
|
|
1314
|
+
for (const entry of Object.values(cache.regions)) {
|
|
1315
|
+
for (const model of entry.models)
|
|
1316
|
+
KIRO_MODEL_IDS.add(model.kiroModelId);
|
|
1547
1317
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1318
|
+
}
|
|
1319
|
+
function loadCachedModelIds() {
|
|
1320
|
+
refreshKnownModelIds(readManagementCache());
|
|
1321
|
+
}
|
|
1322
|
+
function getCachedModels(region) {
|
|
1323
|
+
const cache = readManagementCache();
|
|
1324
|
+
refreshKnownModelIds(cache);
|
|
1325
|
+
const models = cache?.regions[region]?.models ?? kiroModels;
|
|
1326
|
+
let changed = false;
|
|
1327
|
+
const corrected = models.map((model) => {
|
|
1328
|
+
const result = applyVerifiedCapabilities(model);
|
|
1329
|
+
if (result !== model)
|
|
1330
|
+
changed = true;
|
|
1331
|
+
return result;
|
|
1332
|
+
});
|
|
1333
|
+
return changed ? corrected : models;
|
|
1334
|
+
}
|
|
1335
|
+
function isCacheStale(region) {
|
|
1336
|
+
const entry = readManagementCache()?.regions[region];
|
|
1337
|
+
return !entry || Date.now() - entry.fetchedAt > CACHE_MAX_AGE_MS;
|
|
1338
|
+
}
|
|
1339
|
+
async function updateKiroModelsCache(accessToken, region, profileArn) {
|
|
1340
|
+
const response = await fetchKiroModelCatalog({ accessToken, region }, profileArn);
|
|
1341
|
+
const models = mapKiroCatalogModels(response.models, region, getKiroCliModelRates());
|
|
1342
|
+
const cache = readManagementCache() ?? {
|
|
1343
|
+
version: KIRO_MANAGEMENT_CACHE_VERSION,
|
|
1344
|
+
source: KIRO_MANAGEMENT_CACHE_SOURCE,
|
|
1345
|
+
regions: {}
|
|
1346
|
+
};
|
|
1347
|
+
cache.regions[region] = { region, fetchedAt: Date.now(), models };
|
|
1348
|
+
writeManagementCache(cache);
|
|
1349
|
+
refreshKnownModelIds(cache);
|
|
1350
|
+
}
|
|
1351
|
+
function resolveKiroModel(modelId, exactKiroModelId) {
|
|
1352
|
+
if (exactKiroModelId)
|
|
1353
|
+
return exactKiroModelId;
|
|
1354
|
+
const cachedModel = Object.values(readManagementCache()?.regions ?? {}).flatMap((entry) => entry.models).find((model) => model.id === modelId);
|
|
1355
|
+
if (cachedModel) {
|
|
1356
|
+
KIRO_MODEL_IDS.add(cachedModel.kiroModelId);
|
|
1357
|
+
return cachedModel.kiroModelId;
|
|
1561
1358
|
}
|
|
1562
|
-
|
|
1359
|
+
const bootstrapModel = kiroModels.find((model) => model.id === modelId);
|
|
1360
|
+
if (bootstrapModel)
|
|
1361
|
+
return bootstrapModel.kiroModelId;
|
|
1362
|
+
const normalizedId = modelId.replace(/(\d)-(\d)/g, "$1.$2");
|
|
1363
|
+
loadCachedModelIds();
|
|
1364
|
+
if (!KIRO_MODEL_IDS.has(normalizedId)) {
|
|
1365
|
+
throw new Error(`Unknown Kiro model ID: ${modelId}`);
|
|
1366
|
+
}
|
|
1367
|
+
return normalizedId;
|
|
1563
1368
|
}
|
|
1564
|
-
var
|
|
1565
|
-
var
|
|
1566
|
-
"../kiro-core/dist/
|
|
1369
|
+
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;
|
|
1370
|
+
var init_models = __esm({
|
|
1371
|
+
"../kiro-core/dist/models.js"() {
|
|
1567
1372
|
"use strict";
|
|
1568
|
-
|
|
1373
|
+
init_effort();
|
|
1374
|
+
init_kiro_cli();
|
|
1375
|
+
init_management();
|
|
1376
|
+
init_types();
|
|
1569
1377
|
init_endpoints();
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1378
|
+
KIRO_MANAGEMENT_CACHE_VERSION = 1;
|
|
1379
|
+
KIRO_MANAGEMENT_CACHE_SOURCE = "ns-kiro-provider-management";
|
|
1380
|
+
KIRO_MANAGEMENT_CACHE_PATH = join4(homedir4(), ".ns-kiro-provider-models-cache.json");
|
|
1381
|
+
CACHE_MAX_AGE_MS = 36e5;
|
|
1382
|
+
DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
1383
|
+
DEFAULT_MAX_TOKENS = 8192;
|
|
1384
|
+
ZERO_COST = Object.freeze({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
|
|
1385
|
+
REASONING_FAMILY_MARKERS = ["opus", "sonnet", "fable", "coder", "deepseek", "gpt", "glm", "qwen"];
|
|
1386
|
+
VERIFIED_IMAGE_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.6-luna"]);
|
|
1387
|
+
bootstrapKiroModels = [
|
|
1388
|
+
{
|
|
1389
|
+
id: "claude-opus-5",
|
|
1390
|
+
kiroModelId: "claude-opus-5",
|
|
1391
|
+
name: "Claude Opus 5",
|
|
1392
|
+
reasoning: true,
|
|
1393
|
+
input: ["text", "image"],
|
|
1394
|
+
cost: ZERO_COST,
|
|
1395
|
+
contextWindow: 1e6,
|
|
1396
|
+
maxTokens: 128e3,
|
|
1397
|
+
firstTokenTimeout: 18e4
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
id: "claude-opus-4-8",
|
|
1401
|
+
kiroModelId: "claude-opus-4.8",
|
|
1402
|
+
name: "Claude Opus 4.8",
|
|
1403
|
+
reasoning: true,
|
|
1404
|
+
input: ["text", "image"],
|
|
1405
|
+
cost: ZERO_COST,
|
|
1406
|
+
contextWindow: 1e6,
|
|
1407
|
+
maxTokens: 128e3,
|
|
1408
|
+
firstTokenTimeout: 18e4
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
id: "claude-opus-4-7",
|
|
1412
|
+
kiroModelId: "claude-opus-4.7",
|
|
1413
|
+
name: "Claude Opus 4.7",
|
|
1414
|
+
reasoning: true,
|
|
1415
|
+
input: ["text", "image"],
|
|
1416
|
+
cost: ZERO_COST,
|
|
1417
|
+
contextWindow: 1e6,
|
|
1418
|
+
maxTokens: 128e3,
|
|
1419
|
+
firstTokenTimeout: 18e4
|
|
1420
|
+
},
|
|
1421
|
+
{
|
|
1422
|
+
id: "claude-opus-4-6",
|
|
1423
|
+
kiroModelId: "claude-opus-4.6",
|
|
1424
|
+
name: "Claude Opus 4.6",
|
|
1425
|
+
reasoning: true,
|
|
1426
|
+
input: ["text", "image"],
|
|
1427
|
+
cost: ZERO_COST,
|
|
1428
|
+
contextWindow: 1e6,
|
|
1429
|
+
maxTokens: 32768
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
id: "claude-opus-4-5",
|
|
1433
|
+
kiroModelId: "claude-opus-4.5",
|
|
1434
|
+
name: "Claude Opus 4.5",
|
|
1435
|
+
reasoning: true,
|
|
1436
|
+
input: ["text", "image"],
|
|
1437
|
+
cost: ZERO_COST,
|
|
1438
|
+
contextWindow: 2e5,
|
|
1439
|
+
maxTokens: 64e3
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
id: "claude-sonnet-5",
|
|
1443
|
+
kiroModelId: "claude-sonnet-5",
|
|
1444
|
+
name: "Claude Sonnet 5",
|
|
1445
|
+
reasoning: true,
|
|
1446
|
+
input: ["text", "image"],
|
|
1447
|
+
cost: ZERO_COST,
|
|
1448
|
+
contextWindow: 1e6,
|
|
1449
|
+
maxTokens: 65536
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
id: "claude-sonnet-4-6",
|
|
1453
|
+
kiroModelId: "claude-sonnet-4.6",
|
|
1454
|
+
name: "Claude Sonnet 4.6",
|
|
1455
|
+
reasoning: true,
|
|
1456
|
+
input: ["text", "image"],
|
|
1457
|
+
cost: ZERO_COST,
|
|
1458
|
+
contextWindow: 1e6,
|
|
1459
|
+
maxTokens: 65536
|
|
1460
|
+
},
|
|
1461
|
+
{
|
|
1462
|
+
id: "claude-sonnet-4-5",
|
|
1463
|
+
kiroModelId: "claude-sonnet-4.5",
|
|
1464
|
+
name: "Claude Sonnet 4.5",
|
|
1465
|
+
reasoning: true,
|
|
1466
|
+
input: ["text", "image"],
|
|
1467
|
+
cost: ZERO_COST,
|
|
1468
|
+
contextWindow: 2e5,
|
|
1469
|
+
maxTokens: 65536
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
id: "claude-sonnet-4",
|
|
1473
|
+
kiroModelId: "claude-sonnet-4",
|
|
1474
|
+
name: "Claude Sonnet 4",
|
|
1475
|
+
reasoning: true,
|
|
1476
|
+
input: ["text", "image"],
|
|
1477
|
+
cost: ZERO_COST,
|
|
1478
|
+
contextWindow: 2e5,
|
|
1479
|
+
maxTokens: 65536
|
|
1480
|
+
},
|
|
1481
|
+
{
|
|
1482
|
+
id: "claude-haiku-4-5",
|
|
1483
|
+
kiroModelId: "claude-haiku-4.5",
|
|
1484
|
+
name: "Claude Haiku 4.5",
|
|
1485
|
+
reasoning: false,
|
|
1486
|
+
input: ["text", "image"],
|
|
1487
|
+
cost: ZERO_COST,
|
|
1488
|
+
contextWindow: 2e5,
|
|
1489
|
+
maxTokens: 65536
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
id: "claude-fable-5",
|
|
1493
|
+
kiroModelId: "claude-fable-5",
|
|
1494
|
+
name: "Claude Fable 5",
|
|
1495
|
+
reasoning: true,
|
|
1496
|
+
input: ["text", "image"],
|
|
1497
|
+
cost: ZERO_COST,
|
|
1498
|
+
contextWindow: 1e6,
|
|
1499
|
+
maxTokens: 65536
|
|
1500
|
+
},
|
|
1501
|
+
{
|
|
1502
|
+
id: "gpt-5-6-luna",
|
|
1503
|
+
kiroModelId: "gpt-5.6-luna",
|
|
1504
|
+
name: "GPT-5.6 Luna",
|
|
1505
|
+
reasoning: true,
|
|
1506
|
+
input: ["text", "image"],
|
|
1507
|
+
cost: ZERO_COST,
|
|
1508
|
+
contextWindow: 272e3,
|
|
1509
|
+
maxTokens: 128e3
|
|
1510
|
+
},
|
|
1511
|
+
{
|
|
1512
|
+
id: "gpt-5-6-sol",
|
|
1513
|
+
kiroModelId: "gpt-5.6-sol",
|
|
1514
|
+
name: "GPT-5.6 Sol",
|
|
1515
|
+
reasoning: true,
|
|
1516
|
+
input: ["text"],
|
|
1517
|
+
cost: ZERO_COST,
|
|
1518
|
+
contextWindow: 272e3,
|
|
1519
|
+
maxTokens: 128e3
|
|
1520
|
+
},
|
|
1521
|
+
{
|
|
1522
|
+
id: "gpt-5-6-terra",
|
|
1523
|
+
kiroModelId: "gpt-5.6-terra",
|
|
1524
|
+
name: "GPT-5.6 Terra",
|
|
1525
|
+
reasoning: true,
|
|
1526
|
+
input: ["text"],
|
|
1527
|
+
cost: ZERO_COST,
|
|
1528
|
+
contextWindow: 272e3,
|
|
1529
|
+
maxTokens: 128e3
|
|
1530
|
+
},
|
|
1531
|
+
{
|
|
1532
|
+
id: "deepseek-3-2",
|
|
1533
|
+
kiroModelId: "deepseek-3.2",
|
|
1534
|
+
name: "DeepSeek 3.2",
|
|
1535
|
+
reasoning: true,
|
|
1536
|
+
input: ["text"],
|
|
1537
|
+
cost: ZERO_COST,
|
|
1538
|
+
contextWindow: 164e3,
|
|
1539
|
+
maxTokens: 8192
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
id: "minimax-m2-5",
|
|
1543
|
+
kiroModelId: "minimax-m2.5",
|
|
1544
|
+
name: "MiniMax M2.5",
|
|
1545
|
+
reasoning: false,
|
|
1546
|
+
input: ["text"],
|
|
1547
|
+
cost: ZERO_COST,
|
|
1548
|
+
contextWindow: 196e3,
|
|
1549
|
+
maxTokens: 8192
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
id: "minimax-m2-1",
|
|
1553
|
+
kiroModelId: "minimax-m2.1",
|
|
1554
|
+
name: "MiniMax M2.1",
|
|
1555
|
+
reasoning: false,
|
|
1556
|
+
input: ["text"],
|
|
1557
|
+
cost: ZERO_COST,
|
|
1558
|
+
contextWindow: 196e3,
|
|
1559
|
+
maxTokens: 8192
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
id: "glm-5",
|
|
1563
|
+
kiroModelId: "glm-5",
|
|
1564
|
+
name: "GLM 5",
|
|
1565
|
+
reasoning: true,
|
|
1566
|
+
input: ["text"],
|
|
1567
|
+
cost: ZERO_COST,
|
|
1568
|
+
contextWindow: 2e5,
|
|
1569
|
+
maxTokens: 8192
|
|
1570
|
+
},
|
|
1571
|
+
{
|
|
1572
|
+
id: "qwen3-coder-next",
|
|
1573
|
+
kiroModelId: "qwen3-coder-next",
|
|
1574
|
+
name: "Qwen3 Coder Next",
|
|
1575
|
+
reasoning: true,
|
|
1576
|
+
input: ["text"],
|
|
1577
|
+
cost: ZERO_COST,
|
|
1578
|
+
contextWindow: 256e3,
|
|
1579
|
+
maxTokens: 8192
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
id: "auto",
|
|
1583
|
+
kiroModelId: "auto",
|
|
1584
|
+
name: "Auto",
|
|
1585
|
+
reasoning: true,
|
|
1586
|
+
input: ["text", "image"],
|
|
1587
|
+
cost: ZERO_COST,
|
|
1588
|
+
contextWindow: 1e6,
|
|
1589
|
+
maxTokens: 65536
|
|
1587
1590
|
}
|
|
1588
|
-
|
|
1591
|
+
];
|
|
1592
|
+
kiroModels = bootstrapKiroModels.map((model) => ({
|
|
1593
|
+
...model,
|
|
1594
|
+
...applyEffortLadder(model.reasoning ? getKiroEffortConfig(model.additionalModelRequestFieldsSchema, model.kiroModelId) : void 0),
|
|
1595
|
+
...model.id.startsWith("claude-") ? { recoverTextToolCalls: false } : {}
|
|
1596
|
+
}));
|
|
1597
|
+
BOOTSTRAP_KIRO_MODEL_IDS = kiroModels.map((model) => model.kiroModelId);
|
|
1598
|
+
KIRO_MODEL_IDS = new Set(BOOTSTRAP_KIRO_MODEL_IDS);
|
|
1589
1599
|
}
|
|
1590
1600
|
});
|
|
1591
1601
|
|
|
@@ -1653,8 +1663,8 @@ var require_base64_js = __commonJS({
|
|
|
1653
1663
|
}
|
|
1654
1664
|
return arr;
|
|
1655
1665
|
}
|
|
1656
|
-
function tripletToBase64(
|
|
1657
|
-
return lookup[
|
|
1666
|
+
function tripletToBase64(num2) {
|
|
1667
|
+
return lookup[num2 >> 18 & 63] + lookup[num2 >> 12 & 63] + lookup[num2 >> 6 & 63] + lookup[num2 & 63];
|
|
1658
1668
|
}
|
|
1659
1669
|
function encodeChunk(uint8, start, end) {
|
|
1660
1670
|
var tmp;
|
|
@@ -1747,6 +1757,10 @@ var KiroBlockBuffer = class {
|
|
|
1747
1757
|
getText(index) {
|
|
1748
1758
|
return this.blocks.get(index)?.text ?? "";
|
|
1749
1759
|
}
|
|
1760
|
+
/** Kinds of the live blocks, in allocation order. */
|
|
1761
|
+
kinds() {
|
|
1762
|
+
return [...this.blocks.values()].map((block) => block.kind);
|
|
1763
|
+
}
|
|
1750
1764
|
/**
|
|
1751
1765
|
* Rewrite one accumulated block before it is closed. Used by the recovery
|
|
1752
1766
|
* passes that lift tool calls out of text and by echo-noise stripping, both
|
|
@@ -1836,23 +1850,262 @@ function parseBracketToolCalls(text) {
|
|
|
1836
1850
|
}
|
|
1837
1851
|
return { toolCalls, cleanedText };
|
|
1838
1852
|
}
|
|
1839
|
-
|
|
1840
|
-
// ../kiro-core/dist/
|
|
1841
|
-
var
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
const
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1853
|
+
|
|
1854
|
+
// ../kiro-core/dist/cache-estimator.js
|
|
1855
|
+
var stateByConversation = /* @__PURE__ */ new Map();
|
|
1856
|
+
var MAX_TRACKED_CONVERSATIONS = 128;
|
|
1857
|
+
var warnedWireCacheCounters = false;
|
|
1858
|
+
function applyCacheEstimate(conversationId, usage, wireUsage, config, now = Date.now()) {
|
|
1859
|
+
const previous = stateByConversation.get(conversationId);
|
|
1860
|
+
const promptTokens = usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0) + usage.output;
|
|
1861
|
+
const wireReportedCache = wireUsage?.cacheReadInputTokens !== void 0 || wireUsage?.cacheWriteInputTokens !== void 0;
|
|
1862
|
+
if (wireReportedCache) {
|
|
1863
|
+
if (config.estimateCacheUsage && !warnedWireCacheCounters) {
|
|
1864
|
+
warnedWireCacheCounters = true;
|
|
1865
|
+
console.warn("[kiro-core] Kiro now reports cache token counters; cache estimation was skipped and may be disabled.");
|
|
1866
|
+
}
|
|
1867
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1868
|
+
return 0;
|
|
1869
|
+
}
|
|
1870
|
+
if (!config.estimateCacheUsage || usage.input <= 0)
|
|
1871
|
+
return 0;
|
|
1872
|
+
if (!previous) {
|
|
1873
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1874
|
+
return 0;
|
|
1875
|
+
}
|
|
1876
|
+
const expired = config.estimatedCacheTimeout > 0 && now - previous.turnTimestamp > config.estimatedCacheTimeout;
|
|
1877
|
+
const contextShrank = usage.input < previous.promptTokens * 0.6;
|
|
1878
|
+
if (expired || contextShrank) {
|
|
1879
|
+
noteSuccessfulTurn(conversationId, promptTokens, usage.input, now);
|
|
1880
|
+
return 0;
|
|
1881
|
+
}
|
|
1882
|
+
const estimatedRead = Math.min(previous.promptTokens, usage.input);
|
|
1883
|
+
if (estimatedRead > 0) {
|
|
1884
|
+
usage.input -= estimatedRead;
|
|
1885
|
+
usage.cacheRead = (usage.cacheRead ?? 0) + estimatedRead;
|
|
1886
|
+
usage.cacheEstimated = true;
|
|
1887
|
+
}
|
|
1888
|
+
noteSuccessfulTurn(conversationId, promptTokens, promptTokens, now);
|
|
1889
|
+
return estimatedRead;
|
|
1890
|
+
}
|
|
1891
|
+
function noteSuccessfulTurn(conversationId, promptTokens, input, now) {
|
|
1892
|
+
if (input <= 0 || promptTokens <= 0)
|
|
1893
|
+
return;
|
|
1894
|
+
stateByConversation.delete(conversationId);
|
|
1895
|
+
stateByConversation.set(conversationId, { promptTokens, turnTimestamp: now });
|
|
1896
|
+
if (stateByConversation.size > MAX_TRACKED_CONVERSATIONS) {
|
|
1897
|
+
const oldest = stateByConversation.keys().next().value;
|
|
1898
|
+
if (oldest !== void 0)
|
|
1899
|
+
stateByConversation.delete(oldest);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
// ../kiro-core/dist/cost.js
|
|
1904
|
+
var PER_MILLION = 1e6;
|
|
1905
|
+
function calculateKiroCost(cost, usage) {
|
|
1906
|
+
const input = usage.input * cost.input / PER_MILLION;
|
|
1907
|
+
const output = usage.output * cost.output / PER_MILLION;
|
|
1908
|
+
const cacheRead = (usage.cacheRead ?? 0) * cost.cacheRead / PER_MILLION;
|
|
1909
|
+
const cacheWrite = (usage.cacheWrite ?? 0) * cost.cacheWrite / PER_MILLION;
|
|
1910
|
+
return { input, output, cacheRead, cacheWrite, total: input + output + cacheRead + cacheWrite };
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// ../kiro-core/dist/index.js
|
|
1914
|
+
init_debug();
|
|
1915
|
+
init_effort();
|
|
1916
|
+
init_endpoints();
|
|
1917
|
+
|
|
1918
|
+
// ../kiro-core/dist/retry.js
|
|
1919
|
+
init_models();
|
|
1920
|
+
var FIRST_TOKEN_TIMEOUT = 9e4;
|
|
1921
|
+
var REQUEST_HEADER_TIMEOUT = 9e4;
|
|
1922
|
+
function firstTokenTimeoutForModel(modelId) {
|
|
1923
|
+
if (retryConfig.firstTokenTimeoutMs !== FIRST_TOKEN_TIMEOUT) {
|
|
1924
|
+
return retryConfig.firstTokenTimeoutMs;
|
|
1925
|
+
}
|
|
1926
|
+
const model = kiroModels.find((m) => m.id === modelId);
|
|
1927
|
+
return model?.firstTokenTimeout ?? FIRST_TOKEN_TIMEOUT;
|
|
1928
|
+
}
|
|
1929
|
+
var retryConfig = {
|
|
1930
|
+
firstTokenTimeoutMs: FIRST_TOKEN_TIMEOUT,
|
|
1931
|
+
requestHeaderTimeoutMs: REQUEST_HEADER_TIMEOUT
|
|
1932
|
+
};
|
|
1933
|
+
function exponentialBackoff(attempt, baseMs, maxMs) {
|
|
1934
|
+
return Math.min(baseMs * 2 ** attempt, maxMs);
|
|
1935
|
+
}
|
|
1936
|
+
var MAX_RETRY_DELAY = 1e4;
|
|
1937
|
+
var REQUEST_RATE_FALLBACK_DELAY_MS = 1e4;
|
|
1938
|
+
function extractKiroReason(errorText) {
|
|
1939
|
+
if (!errorText)
|
|
1940
|
+
return void 0;
|
|
1941
|
+
try {
|
|
1942
|
+
const parsed = JSON.parse(errorText);
|
|
1943
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1944
|
+
return void 0;
|
|
1945
|
+
const reason = parsed.reason;
|
|
1946
|
+
return typeof reason === "string" && reason.length > 0 ? reason : void 0;
|
|
1947
|
+
} catch {
|
|
1948
|
+
return void 0;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
function parseRetryAfterMs(headers, nowMs = Date.now()) {
|
|
1952
|
+
const get = headers?.get?.bind(headers);
|
|
1953
|
+
if (!get)
|
|
1954
|
+
return void 0;
|
|
1955
|
+
const milliseconds = nonNegativeNumber(get("retry-after-ms"));
|
|
1956
|
+
if (milliseconds !== void 0)
|
|
1957
|
+
return Math.round(milliseconds);
|
|
1958
|
+
const retryAfter = get("retry-after");
|
|
1959
|
+
if (retryAfter !== null && retryAfter.trim() !== "") {
|
|
1960
|
+
const seconds = Number(retryAfter);
|
|
1961
|
+
if (Number.isFinite(seconds)) {
|
|
1962
|
+
if (seconds >= 0) {
|
|
1963
|
+
const delayMs = seconds * 1e3;
|
|
1964
|
+
if (Number.isFinite(delayMs))
|
|
1965
|
+
return Math.round(delayMs);
|
|
1966
|
+
}
|
|
1967
|
+
} else {
|
|
1968
|
+
const dateMs = Date.parse(retryAfter);
|
|
1969
|
+
if (!Number.isNaN(dateMs))
|
|
1970
|
+
return Math.max(0, dateMs - nowMs);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
const resetAfterSeconds = nonNegativeNumber(get("x-ratelimit-reset-after"));
|
|
1974
|
+
if (resetAfterSeconds !== void 0) {
|
|
1975
|
+
const delayMs = resetAfterSeconds * 1e3;
|
|
1976
|
+
if (Number.isFinite(delayMs))
|
|
1977
|
+
return Math.round(delayMs);
|
|
1978
|
+
}
|
|
1979
|
+
return void 0;
|
|
1980
|
+
}
|
|
1981
|
+
function resolveRequestRateRetryDelay(headers, nowMs = Date.now()) {
|
|
1982
|
+
const advertisedDelayMs = parseRetryAfterMs(headers, nowMs);
|
|
1983
|
+
const requestedDelayMs = advertisedDelayMs ?? REQUEST_RATE_FALLBACK_DELAY_MS;
|
|
1984
|
+
return {
|
|
1985
|
+
delayMs: Math.min(requestedDelayMs, MAX_RETRY_DELAY),
|
|
1986
|
+
...advertisedDelayMs !== void 0 ? { advertisedDelayMs } : {},
|
|
1987
|
+
capped: requestedDelayMs > MAX_RETRY_DELAY
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
function nonNegativeNumber(value) {
|
|
1991
|
+
if (value === null || value.trim() === "")
|
|
1992
|
+
return void 0;
|
|
1993
|
+
const parsed = Number(value);
|
|
1994
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
|
|
1995
|
+
}
|
|
1996
|
+
var KIRO_REASON_CODES = Object.freeze({
|
|
1997
|
+
/** Request body exceeded the service's size threshold. */
|
|
1998
|
+
CONTENT_LENGTH_EXCEEDS_THRESHOLD: "CONTENT_LENGTH_EXCEEDS_THRESHOLD",
|
|
1999
|
+
/** Prose-only size rejection; the service sends no reason code for this one. */
|
|
2000
|
+
INPUT_TOO_LONG: "Input is too long",
|
|
2001
|
+
/** Monthly request quota exhausted — hard limit, not transient. */
|
|
2002
|
+
MONTHLY_REQUEST_COUNT: "MONTHLY_REQUEST_COUNT",
|
|
2003
|
+
/** Model capacity temporarily unavailable — transient, worth retrying. */
|
|
2004
|
+
INSUFFICIENT_MODEL_CAPACITY: "INSUFFICIENT_MODEL_CAPACITY",
|
|
2005
|
+
/** Short-window request throttle — retry only within the provider budget. */
|
|
2006
|
+
USER_REQUEST_RATE_EXCEEDED: "USER_REQUEST_RATE_EXCEEDED",
|
|
2007
|
+
/**
|
|
2008
|
+
* Generic request-validation rejection, returned for a malformed body of any
|
|
2009
|
+
* size (empty `content`, history referencing tools absent from the catalog).
|
|
2010
|
+
* Not a size signal: classifying it as "too big" makes the caller compact a
|
|
2011
|
+
* history that was never the problem, a loop it can never satisfy.
|
|
2012
|
+
*/
|
|
2013
|
+
REQUEST_BODY_INVALID: "REQUEST_BODY_INVALID"
|
|
2014
|
+
});
|
|
2015
|
+
var TOO_BIG_PATTERNS = Object.freeze([
|
|
2016
|
+
KIRO_REASON_CODES.CONTENT_LENGTH_EXCEEDS_THRESHOLD,
|
|
2017
|
+
KIRO_REASON_CODES.INPUT_TOO_LONG
|
|
2018
|
+
]);
|
|
2019
|
+
var NON_RETRYABLE_BODY_PATTERNS = Object.freeze([KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT]);
|
|
2020
|
+
var CAPACITY_PATTERN = KIRO_REASON_CODES.INSUFFICIENT_MODEL_CAPACITY;
|
|
2021
|
+
var CAPACITY_MAX_RETRIES = 3;
|
|
2022
|
+
var CAPACITY_BASE_DELAY_MS = 5e3;
|
|
2023
|
+
var capacityRetryConfig = {
|
|
2024
|
+
maxRetries: CAPACITY_MAX_RETRIES,
|
|
2025
|
+
baseDelayMs: CAPACITY_BASE_DELAY_MS
|
|
2026
|
+
};
|
|
2027
|
+
function isTooBigError(status, errorText) {
|
|
2028
|
+
return status === 413 || status === 400 && TOO_BIG_PATTERNS.some((p) => errorText.includes(p));
|
|
2029
|
+
}
|
|
2030
|
+
function isNonRetryableBodyError(errorText) {
|
|
2031
|
+
return NON_RETRYABLE_BODY_PATTERNS.some((p) => errorText.includes(p));
|
|
2032
|
+
}
|
|
2033
|
+
function isCapacityError(errorText) {
|
|
2034
|
+
return errorText.includes(CAPACITY_PATTERN);
|
|
1848
2035
|
}
|
|
1849
2036
|
|
|
1850
|
-
// ../kiro-core/dist/
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
2037
|
+
// ../kiro-core/dist/errors.js
|
|
2038
|
+
var REASON_CODE_MARKERS = [
|
|
2039
|
+
KIRO_REASON_CODES.CONTENT_LENGTH_EXCEEDS_THRESHOLD,
|
|
2040
|
+
KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT,
|
|
2041
|
+
KIRO_REASON_CODES.INSUFFICIENT_MODEL_CAPACITY,
|
|
2042
|
+
KIRO_REASON_CODES.REQUEST_BODY_INVALID
|
|
2043
|
+
];
|
|
2044
|
+
var KiroApiError = class extends Error {
|
|
2045
|
+
status;
|
|
2046
|
+
reasonCode;
|
|
2047
|
+
retryAfterMs;
|
|
2048
|
+
providerAttempts;
|
|
2049
|
+
constructor(message, status, reasonCode, retryAfterMs, providerAttempts) {
|
|
2050
|
+
super(message);
|
|
2051
|
+
this.status = status;
|
|
2052
|
+
this.reasonCode = reasonCode;
|
|
2053
|
+
this.retryAfterMs = retryAfterMs;
|
|
2054
|
+
this.providerAttempts = providerAttempts;
|
|
2055
|
+
this.name = "KiroApiError";
|
|
2056
|
+
}
|
|
2057
|
+
};
|
|
2058
|
+
function extractKiroReasonCode(errorText) {
|
|
2059
|
+
if (!errorText)
|
|
2060
|
+
return void 0;
|
|
2061
|
+
const trimmed = errorText.trim();
|
|
2062
|
+
if (trimmed.startsWith("{")) {
|
|
2063
|
+
try {
|
|
2064
|
+
const parsed = JSON.parse(trimmed);
|
|
2065
|
+
const reason = parsed.reason ?? parsed.reasonCode;
|
|
2066
|
+
if (typeof reason === "string" && reason.length > 0)
|
|
2067
|
+
return reason;
|
|
2068
|
+
} catch {
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
return REASON_CODE_MARKERS.find((code) => errorText.includes(code));
|
|
2072
|
+
}
|
|
1854
2073
|
|
|
1855
2074
|
// ../kiro-core/dist/event-parser.js
|
|
2075
|
+
var KIRO_EVENT_KEYS = [
|
|
2076
|
+
"assistantResponseEvent",
|
|
2077
|
+
"codeReferenceEvent",
|
|
2078
|
+
"contextUsageEvent",
|
|
2079
|
+
"documentCitationEvent",
|
|
2080
|
+
"error",
|
|
2081
|
+
"metadataEvent",
|
|
2082
|
+
"meteringEvent",
|
|
2083
|
+
"reasoningContentEvent",
|
|
2084
|
+
"serviceUnavailableError",
|
|
2085
|
+
"throttlingError",
|
|
2086
|
+
"toolResultEvent",
|
|
2087
|
+
"toolUseEvent",
|
|
2088
|
+
"validationError"
|
|
2089
|
+
];
|
|
2090
|
+
var KIRO_EVENT_KEY_SET = new Set(KIRO_EVENT_KEYS);
|
|
2091
|
+
var KIRO_ERROR_MEMBERS = {
|
|
2092
|
+
error: { kind: "internalServer", exception: "InternalServerException" },
|
|
2093
|
+
throttlingError: { kind: "throttling", exception: "ThrottlingException" },
|
|
2094
|
+
validationError: { kind: "validation", exception: "ValidationException" },
|
|
2095
|
+
serviceUnavailableError: { kind: "serviceUnavailable", exception: "ServiceUnavailableException" }
|
|
2096
|
+
};
|
|
2097
|
+
var KIRO_ERROR_TOKENS = {
|
|
2098
|
+
...KIRO_ERROR_MEMBERS,
|
|
2099
|
+
InternalServerException: KIRO_ERROR_MEMBERS.error,
|
|
2100
|
+
ThrottlingException: KIRO_ERROR_MEMBERS.throttlingError,
|
|
2101
|
+
ValidationException: KIRO_ERROR_MEMBERS.validationError,
|
|
2102
|
+
ServiceUnavailableException: KIRO_ERROR_MEMBERS.serviceUnavailableError
|
|
2103
|
+
};
|
|
2104
|
+
function lookupKiroErrorMember(key) {
|
|
2105
|
+
return Object.hasOwn(KIRO_ERROR_TOKENS, key) ? KIRO_ERROR_TOKENS[key] : void 0;
|
|
2106
|
+
}
|
|
2107
|
+
var num = (v) => typeof v === "number" ? v : void 0;
|
|
2108
|
+
var str = (v) => typeof v === "string" ? v : void 0;
|
|
1856
2109
|
function tokenCount(value) {
|
|
1857
2110
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1858
2111
|
}
|
|
@@ -1871,30 +2124,136 @@ var CACHE_WRITE_KEYS = [
|
|
|
1871
2124
|
"cacheCreationInputTokens",
|
|
1872
2125
|
"cacheWriteTokens"
|
|
1873
2126
|
];
|
|
1874
|
-
function
|
|
1875
|
-
if (
|
|
1876
|
-
return
|
|
1877
|
-
if (typeof
|
|
1878
|
-
return
|
|
1879
|
-
|
|
1880
|
-
|
|
2127
|
+
function toolInput(raw) {
|
|
2128
|
+
if (typeof raw === "string")
|
|
2129
|
+
return raw;
|
|
2130
|
+
if (raw && typeof raw === "object" && Object.keys(raw).length > 0) {
|
|
2131
|
+
return JSON.stringify(raw);
|
|
2132
|
+
}
|
|
2133
|
+
return "";
|
|
2134
|
+
}
|
|
2135
|
+
function parseToolUse(parsed) {
|
|
1881
2136
|
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
2137
|
return {
|
|
1884
2138
|
type: "toolUse",
|
|
1885
2139
|
data: {
|
|
1886
2140
|
name: parsed.name,
|
|
1887
2141
|
toolUseId: parsed.toolUseId,
|
|
1888
|
-
input,
|
|
2142
|
+
input: toolInput(parsed.input),
|
|
1889
2143
|
stop: parsed.stop
|
|
1890
2144
|
}
|
|
1891
2145
|
};
|
|
1892
2146
|
}
|
|
2147
|
+
if (parsed.input !== void 0) {
|
|
2148
|
+
return { type: "toolUseInput", data: { input: toolInput(parsed.input) } };
|
|
2149
|
+
}
|
|
2150
|
+
if (parsed.stop !== void 0)
|
|
2151
|
+
return { type: "toolUseStop", data: { stop: parsed.stop } };
|
|
2152
|
+
return null;
|
|
2153
|
+
}
|
|
2154
|
+
function parseMetadata(parsed) {
|
|
2155
|
+
const tu = parsed.tokenUsage ?? {};
|
|
2156
|
+
const data = {
|
|
2157
|
+
inputTokens: tokenCount(tu.uncachedInputTokens) ?? tokenCount(tu.inputTokens),
|
|
2158
|
+
outputTokens: tokenCount(tu.outputTokens),
|
|
2159
|
+
totalTokens: tokenCount(tu.totalTokens),
|
|
2160
|
+
cacheReadInputTokens: firstTokenCount(tu, CACHE_READ_KEYS),
|
|
2161
|
+
cacheWriteInputTokens: firstTokenCount(tu, CACHE_WRITE_KEYS),
|
|
2162
|
+
contextUsagePercentage: num(tu.contextUsagePercentage),
|
|
2163
|
+
normalizedTokenUsage: num(tu.normalizedTokenUsage),
|
|
2164
|
+
rawStopReason: str(parsed.stopReason),
|
|
2165
|
+
stopDetails: parsed.stopDetails && typeof parsed.stopDetails === "object" ? parsed.stopDetails : void 0
|
|
2166
|
+
};
|
|
2167
|
+
for (const k of Object.keys(data)) {
|
|
2168
|
+
if (data[k] === void 0)
|
|
2169
|
+
delete data[k];
|
|
2170
|
+
}
|
|
2171
|
+
return Object.keys(data).length > 0 ? { type: "usage", data } : null;
|
|
2172
|
+
}
|
|
2173
|
+
function parseError(parsed, kind, fallbackName) {
|
|
2174
|
+
const rawError = parsed.error ?? parsed.Error;
|
|
2175
|
+
const error2 = typeof rawError === "string" ? rawError : rawError !== void 0 ? JSON.stringify(rawError) : str(parsed.name) ?? fallbackName;
|
|
2176
|
+
const message = parsed.message ?? parsed.Message ?? parsed.reason;
|
|
2177
|
+
const data = { error: error2, kind };
|
|
2178
|
+
if (typeof message === "string")
|
|
2179
|
+
data.message = message;
|
|
2180
|
+
const reason = str(parsed.reason);
|
|
2181
|
+
if (reason !== void 0)
|
|
2182
|
+
data.reason = reason;
|
|
2183
|
+
const retryAfterMilliseconds = num(parsed.retryAfterMilliseconds);
|
|
2184
|
+
if (retryAfterMilliseconds !== void 0)
|
|
2185
|
+
data.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
2186
|
+
return { type: "error", data };
|
|
2187
|
+
}
|
|
2188
|
+
function parseKiroEvent(key, parsed) {
|
|
2189
|
+
switch (key) {
|
|
2190
|
+
case "assistantResponseEvent": {
|
|
2191
|
+
const content = str(parsed.content);
|
|
2192
|
+
return content !== void 0 ? { type: "content", data: content } : null;
|
|
2193
|
+
}
|
|
2194
|
+
case "reasoningContentEvent": {
|
|
2195
|
+
const text = str(parsed.text);
|
|
2196
|
+
if (text !== void 0)
|
|
2197
|
+
return { type: "thinkingText", data: text };
|
|
2198
|
+
const signature = str(parsed.signature);
|
|
2199
|
+
if (signature !== void 0)
|
|
2200
|
+
return { type: "thinkingSignature", data: signature };
|
|
2201
|
+
return { type: "ignored", data: { key } };
|
|
2202
|
+
}
|
|
2203
|
+
case "toolUseEvent":
|
|
2204
|
+
return parseToolUse(parsed);
|
|
2205
|
+
case "contextUsageEvent": {
|
|
2206
|
+
const pct = num(parsed.contextUsagePercentage);
|
|
2207
|
+
return pct !== void 0 ? { type: "contextUsage", data: { contextUsagePercentage: pct } } : null;
|
|
2208
|
+
}
|
|
2209
|
+
case "metadataEvent":
|
|
2210
|
+
return parseMetadata(parsed);
|
|
2211
|
+
case "meteringEvent":
|
|
2212
|
+
return {
|
|
2213
|
+
type: "metering",
|
|
2214
|
+
data: { credits: tokenCount(parsed.usage), unit: str(parsed.unit), unitPlural: str(parsed.unitPlural) }
|
|
2215
|
+
};
|
|
2216
|
+
// Reachable when a member that models an exception is delivered as an
|
|
2217
|
+
// ordinary event frame. The real wire uses exception framing, handled by
|
|
2218
|
+
// parseKiroExceptionFrame, but both routes must agree.
|
|
2219
|
+
case "error":
|
|
2220
|
+
case "throttlingError":
|
|
2221
|
+
case "validationError":
|
|
2222
|
+
case "serviceUnavailableError": {
|
|
2223
|
+
const member = lookupKiroErrorMember(key);
|
|
2224
|
+
return parseError(parsed, member.kind, member.exception);
|
|
2225
|
+
}
|
|
2226
|
+
// Known members with no consumer yet: explicitly ignored, not unparseable.
|
|
2227
|
+
case "codeReferenceEvent":
|
|
2228
|
+
case "documentCitationEvent":
|
|
2229
|
+
case "toolResultEvent":
|
|
2230
|
+
return { type: "ignored", data: { key } };
|
|
2231
|
+
default: {
|
|
2232
|
+
const member = lookupKiroErrorMember(key);
|
|
2233
|
+
if (member)
|
|
2234
|
+
return parseError(parsed, member.kind, member.exception);
|
|
2235
|
+
return parseKiroEventByShape(parsed);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
function parseKiroExceptionFrame(key, parsed) {
|
|
2240
|
+
const member = lookupKiroErrorMember(key);
|
|
2241
|
+
if (!member)
|
|
2242
|
+
return null;
|
|
2243
|
+
const event = parseError(parsed, member.kind, member.exception);
|
|
2244
|
+
return event.data;
|
|
2245
|
+
}
|
|
2246
|
+
function parseKiroEventByShape(parsed) {
|
|
2247
|
+
if (parsed.content !== void 0)
|
|
2248
|
+
return { type: "content", data: parsed.content };
|
|
2249
|
+
if (typeof parsed.text === "string")
|
|
2250
|
+
return { type: "thinkingText", data: parsed.text };
|
|
2251
|
+
if (typeof parsed.signature === "string")
|
|
2252
|
+
return { type: "thinkingSignature", data: parsed.signature };
|
|
2253
|
+
if (parsed.name && parsed.toolUseId)
|
|
2254
|
+
return parseToolUse(parsed);
|
|
1893
2255
|
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
|
-
};
|
|
2256
|
+
return { type: "toolUseInput", data: { input: toolInput(parsed.input) } };
|
|
1898
2257
|
}
|
|
1899
2258
|
if (parsed.stop !== void 0 && parsed.contextUsagePercentage === void 0)
|
|
1900
2259
|
return { type: "toolUseStop", data: { stop: parsed.stop } };
|
|
@@ -1902,42 +2261,23 @@ function parseKiroEvent(parsed) {
|
|
|
1902
2261
|
return { type: "contextUsage", data: { contextUsagePercentage: parsed.contextUsagePercentage } };
|
|
1903
2262
|
if (parsed.followupPrompt !== void 0)
|
|
1904
2263
|
return { type: "followupPrompt", data: parsed.followupPrompt };
|
|
2264
|
+
if (parsed.tokenUsage !== void 0 || parsed.stopReason !== void 0 || parsed.stopDetails !== void 0) {
|
|
2265
|
+
return parseMetadata(parsed);
|
|
2266
|
+
}
|
|
1905
2267
|
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);
|
|
2268
|
+
return parseError(parsed, "unknown", "unknown");
|
|
2269
|
+
}
|
|
2270
|
+
if (typeof parsed.usage === "number") {
|
|
1926
2271
|
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
|
-
}
|
|
2272
|
+
type: "metering",
|
|
2273
|
+
data: { credits: tokenCount(parsed.usage), unit: str(parsed.unit), unitPlural: str(parsed.unitPlural) }
|
|
1934
2274
|
};
|
|
1935
2275
|
}
|
|
1936
2276
|
return null;
|
|
1937
2277
|
}
|
|
1938
2278
|
|
|
1939
2279
|
// ../kiro-core/dist/transform.js
|
|
1940
|
-
import { createHash } from "node:crypto";
|
|
2280
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1941
2281
|
var TOOL_RESULT_LIMIT = 25e4;
|
|
1942
2282
|
var EMPTY_CONTENT_PLACEHOLDER = "Please proceed with the task.";
|
|
1943
2283
|
function sanitizeSurrogates(text) {
|
|
@@ -1955,7 +2295,7 @@ var KIRO_TOOL_USE_ID_PATTERN = /^[a-zA-Z0-9_.:-]{1,64}$/;
|
|
|
1955
2295
|
function toKiroToolUseId(toolUseId) {
|
|
1956
2296
|
if (KIRO_TOOL_USE_ID_PATTERN.test(toolUseId))
|
|
1957
2297
|
return toolUseId;
|
|
1958
|
-
const digest =
|
|
2298
|
+
const digest = createHash2("sha256").update(toolUseId).digest("base64url").slice(0, 32);
|
|
1959
2299
|
return `pi_${digest}`;
|
|
1960
2300
|
}
|
|
1961
2301
|
function normalizeMessages(messages) {
|
|
@@ -2969,8 +3309,8 @@ function bytePairEncode(piece, ranks) {
|
|
|
2969
3309
|
return [ranks.get(piece.join(","))];
|
|
2970
3310
|
return bytePairMerge(piece, ranks).map((p) => ranks.get(piece.slice(p.start, p.end).join(","))).filter((x) => x != null);
|
|
2971
3311
|
}
|
|
2972
|
-
function escapeRegex(
|
|
2973
|
-
return
|
|
3312
|
+
function escapeRegex(str2) {
|
|
3313
|
+
return str2.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
2974
3314
|
}
|
|
2975
3315
|
var _Tiktoken = class {
|
|
2976
3316
|
/** @internal */
|
|
@@ -3117,6 +3457,7 @@ var KiroResponseAssembler = class {
|
|
|
3117
3457
|
totalContent = "";
|
|
3118
3458
|
lastContentData = "";
|
|
3119
3459
|
usageEvent = null;
|
|
3460
|
+
meteringEvent = null;
|
|
3120
3461
|
receivedContextUsage = false;
|
|
3121
3462
|
thinkingParser = null;
|
|
3122
3463
|
nativeThinkingBlockIndex = null;
|
|
@@ -3124,16 +3465,19 @@ var KiroResponseAssembler = class {
|
|
|
3124
3465
|
textBlockIndex = null;
|
|
3125
3466
|
emittedToolCalls = 0;
|
|
3126
3467
|
sawAnyToolCalls = false;
|
|
3468
|
+
droppedToolCalls = [];
|
|
3127
3469
|
currentToolCall = null;
|
|
3470
|
+
stopReason = "stop";
|
|
3128
3471
|
constructor(model, thinkingEnabled) {
|
|
3129
3472
|
this.model = model;
|
|
3130
3473
|
this.thinkingEnabled = thinkingEnabled;
|
|
3131
3474
|
}
|
|
3132
|
-
/** Clear per-attempt state.
|
|
3475
|
+
/** Clear per-attempt state. Only block indexes are kept. */
|
|
3133
3476
|
beginAttempt() {
|
|
3134
3477
|
this.totalContent = "";
|
|
3135
3478
|
this.lastContentData = "";
|
|
3136
3479
|
this.usageEvent = null;
|
|
3480
|
+
this.meteringEvent = null;
|
|
3137
3481
|
this.receivedContextUsage = false;
|
|
3138
3482
|
this.thinkingParser = this.thinkingEnabled ? new ThinkingTagParser(this.blocks) : null;
|
|
3139
3483
|
this.nativeThinkingBlockIndex = null;
|
|
@@ -3141,7 +3485,17 @@ var KiroResponseAssembler = class {
|
|
|
3141
3485
|
this.textBlockIndex = null;
|
|
3142
3486
|
this.emittedToolCalls = 0;
|
|
3143
3487
|
this.sawAnyToolCalls = false;
|
|
3488
|
+
this.droppedToolCalls = [];
|
|
3144
3489
|
this.currentToolCall = null;
|
|
3490
|
+
this.usage.input = 0;
|
|
3491
|
+
this.usage.output = 0;
|
|
3492
|
+
this.usage.totalTokens = 0;
|
|
3493
|
+
this.usage.cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
3494
|
+
delete this.usage.cacheRead;
|
|
3495
|
+
delete this.usage.cacheWrite;
|
|
3496
|
+
delete this.usage.contextPercent;
|
|
3497
|
+
delete this.usage.credits;
|
|
3498
|
+
delete this.usage.creditUnit;
|
|
3145
3499
|
}
|
|
3146
3500
|
/** Hand over the events buffered so far. */
|
|
3147
3501
|
takeEvents() {
|
|
@@ -3218,11 +3572,17 @@ var KiroResponseAssembler = class {
|
|
|
3218
3572
|
break;
|
|
3219
3573
|
}
|
|
3220
3574
|
case "usage": {
|
|
3221
|
-
this.usageEvent = event.data;
|
|
3575
|
+
this.usageEvent = { ...this.usageEvent ?? {}, ...event.data };
|
|
3222
3576
|
if (debugEnabled())
|
|
3223
3577
|
debugLog("response.usageRaw", payload);
|
|
3224
3578
|
break;
|
|
3225
3579
|
}
|
|
3580
|
+
case "metering": {
|
|
3581
|
+
this.meteringEvent = event.data;
|
|
3582
|
+
if (debugEnabled())
|
|
3583
|
+
debugLog("stream.metering", [event.data]);
|
|
3584
|
+
break;
|
|
3585
|
+
}
|
|
3226
3586
|
}
|
|
3227
3587
|
}
|
|
3228
3588
|
/**
|
|
@@ -3230,8 +3590,12 @@ var KiroResponseAssembler = class {
|
|
|
3230
3590
|
* text-dialect recovery and echo-stripping passes.
|
|
3231
3591
|
*/
|
|
3232
3592
|
endTurn() {
|
|
3233
|
-
if (this.currentToolCall
|
|
3234
|
-
this.
|
|
3593
|
+
if (this.currentToolCall) {
|
|
3594
|
+
if (this.emitToolCall(this.currentToolCall))
|
|
3595
|
+
this.emittedToolCalls++;
|
|
3596
|
+
else
|
|
3597
|
+
this.droppedToolCalls.push(this.currentToolCall.name);
|
|
3598
|
+
}
|
|
3235
3599
|
this.currentToolCall = null;
|
|
3236
3600
|
this.endNativeThinking();
|
|
3237
3601
|
if (this.thinkingParser) {
|
|
@@ -3242,13 +3606,16 @@ var KiroResponseAssembler = class {
|
|
|
3242
3606
|
this.stripEchoNoise();
|
|
3243
3607
|
const responseText = this.textBlockIndex === null ? "" : this.blocks.getText(this.textBlockIndex);
|
|
3244
3608
|
const hasText2 = responseText.length > 0;
|
|
3609
|
+
this.stopReason = !this.receivedContextUsage && this.emittedToolCalls === 0 ? "length" : this.emittedToolCalls > 0 ? "toolUse" : "stop";
|
|
3245
3610
|
return {
|
|
3246
3611
|
responseText,
|
|
3247
3612
|
hasText: hasText2,
|
|
3248
3613
|
sawAnyToolCalls: this.sawAnyToolCalls,
|
|
3249
3614
|
emittedToolCalls: this.emittedToolCalls,
|
|
3250
3615
|
isEchoLoop: hasText2 && !this.sawAnyToolCalls && ECHO_NOISE_PATTERN.test(responseText),
|
|
3251
|
-
isEmpty: !hasText2 && !this.sawAnyToolCalls
|
|
3616
|
+
isEmpty: !hasText2 && !this.sawAnyToolCalls,
|
|
3617
|
+
stopReason: this.stopReason,
|
|
3618
|
+
droppedToolCalls: this.droppedToolCalls
|
|
3252
3619
|
};
|
|
3253
3620
|
}
|
|
3254
3621
|
/** Drop an echo the caller decided not to retry, so it is not read as a continuation signal. */
|
|
@@ -3256,6 +3623,10 @@ var KiroResponseAssembler = class {
|
|
|
3256
3623
|
if (this.textBlockIndex !== null)
|
|
3257
3624
|
this.blocks.setText(this.textBlockIndex, "");
|
|
3258
3625
|
}
|
|
3626
|
+
/** Kinds of the blocks this attempt produced, for the exhaustion diagnostic. */
|
|
3627
|
+
contentKinds() {
|
|
3628
|
+
return this.blocks.kinds();
|
|
3629
|
+
}
|
|
3259
3630
|
/** Close the text block and settle usage and the stop reason. */
|
|
3260
3631
|
complete() {
|
|
3261
3632
|
if (this.textBlockIndex !== null)
|
|
@@ -3263,17 +3634,17 @@ var KiroResponseAssembler = class {
|
|
|
3263
3634
|
if (this.usageEvent?.inputTokens !== void 0)
|
|
3264
3635
|
this.usage.input = this.usageEvent.inputTokens;
|
|
3265
3636
|
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.
|
|
3637
|
+
this.usage.totalTokens = this.usageEvent?.totalTokens ?? this.usage.input + (this.usageEvent?.cacheReadInputTokens ?? 0) + (this.usageEvent?.cacheWriteInputTokens ?? 0) + this.usage.output;
|
|
3638
|
+
if (this.usageEvent?.cacheReadInputTokens !== void 0)
|
|
3639
|
+
this.usage.cacheRead = this.usageEvent.cacheReadInputTokens;
|
|
3640
|
+
if (this.usageEvent?.cacheWriteInputTokens !== void 0)
|
|
3641
|
+
this.usage.cacheWrite = this.usageEvent.cacheWriteInputTokens;
|
|
3642
|
+
if (this.meteringEvent?.credits !== void 0)
|
|
3643
|
+
this.usage.credits = this.meteringEvent.credits;
|
|
3644
|
+
if (this.meteringEvent?.unit !== void 0)
|
|
3645
|
+
this.usage.creditUnit = this.meteringEvent.unit;
|
|
3275
3646
|
this.usage.cost = calculateKiroCost(this.model.cost, this.usage);
|
|
3276
|
-
const stopReason =
|
|
3647
|
+
const stopReason = this.stopReason;
|
|
3277
3648
|
debugLog("response.done", {
|
|
3278
3649
|
stopReason,
|
|
3279
3650
|
receivedContextUsage: this.receivedContextUsage,
|
|
@@ -3282,7 +3653,12 @@ var KiroResponseAssembler = class {
|
|
|
3282
3653
|
textLen: this.textBlockIndex === null ? 0 : this.blocks.getText(this.textBlockIndex).length,
|
|
3283
3654
|
usage: this.usage
|
|
3284
3655
|
});
|
|
3285
|
-
return {
|
|
3656
|
+
return {
|
|
3657
|
+
stopReason,
|
|
3658
|
+
usage: this.usage,
|
|
3659
|
+
wireUsage: this.usageEvent,
|
|
3660
|
+
metering: this.meteringEvent
|
|
3661
|
+
};
|
|
3286
3662
|
}
|
|
3287
3663
|
ensureNativeThinkingBlock() {
|
|
3288
3664
|
if (this.nativeThinkingBlockIndex === null)
|
|
@@ -3317,6 +3693,8 @@ var KiroResponseAssembler = class {
|
|
|
3317
3693
|
return;
|
|
3318
3694
|
if (this.emitToolCall(this.currentToolCall))
|
|
3319
3695
|
this.emittedToolCalls++;
|
|
3696
|
+
else
|
|
3697
|
+
this.droppedToolCalls.push(this.currentToolCall.name);
|
|
3320
3698
|
this.currentToolCall = null;
|
|
3321
3699
|
}
|
|
3322
3700
|
/**
|
|
@@ -3358,6 +3736,8 @@ var KiroResponseAssembler = class {
|
|
|
3358
3736
|
for (const call of recovered) {
|
|
3359
3737
|
if (this.emitToolCall({ toolUseId: call.toolUseId, name: call.name, input: JSON.stringify(call.arguments) })) {
|
|
3360
3738
|
this.emittedToolCalls++;
|
|
3739
|
+
} else {
|
|
3740
|
+
this.droppedToolCalls.push(call.name);
|
|
3361
3741
|
}
|
|
3362
3742
|
}
|
|
3363
3743
|
}
|
|
@@ -4117,6 +4497,7 @@ function readKiroEventStream(body, options) {
|
|
|
4117
4497
|
const outcome = { firstTokenTimedOut: false, idleTimedOut: false, error: null };
|
|
4118
4498
|
const idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT;
|
|
4119
4499
|
const bodyReader = body.getReader();
|
|
4500
|
+
const callerSignal = options.signal;
|
|
4120
4501
|
async function* frames() {
|
|
4121
4502
|
let idleTimer = null;
|
|
4122
4503
|
const resetIdle = () => {
|
|
@@ -4128,6 +4509,14 @@ function readKiroEventStream(body, options) {
|
|
|
4128
4509
|
});
|
|
4129
4510
|
}, idleTimeoutMs);
|
|
4130
4511
|
};
|
|
4512
|
+
const onCallerStreamAbort = () => {
|
|
4513
|
+
void bodyReader.cancel().catch(() => {
|
|
4514
|
+
});
|
|
4515
|
+
};
|
|
4516
|
+
if (callerSignal?.aborted)
|
|
4517
|
+
onCallerStreamAbort();
|
|
4518
|
+
else
|
|
4519
|
+
callerSignal?.addEventListener("abort", onCallerStreamAbort, { once: true });
|
|
4131
4520
|
const bodyIterable = {
|
|
4132
4521
|
async *[Symbol.asyncIterator]() {
|
|
4133
4522
|
try {
|
|
@@ -4148,6 +4537,26 @@ function readKiroEventStream(body, options) {
|
|
|
4148
4537
|
if (!entry)
|
|
4149
4538
|
throw new Error("Received an empty event stream message");
|
|
4150
4539
|
const [key, msg] = entry;
|
|
4540
|
+
if (msg.headers[":message-type"]?.value === "exception") {
|
|
4541
|
+
let parsedException = {};
|
|
4542
|
+
try {
|
|
4543
|
+
const decoded = JSON.parse(utf8Decoder.decode(msg.body));
|
|
4544
|
+
if (decoded && typeof decoded === "object")
|
|
4545
|
+
parsedException = decoded;
|
|
4546
|
+
} catch {
|
|
4547
|
+
}
|
|
4548
|
+
const data = parseKiroExceptionFrame(key, parsedException) ?? {
|
|
4549
|
+
error: key,
|
|
4550
|
+
kind: "unknown",
|
|
4551
|
+
...typeof parsedException.message === "string" ? { message: parsedException.message } : {},
|
|
4552
|
+
...typeof parsedException.reason === "string" ? { reason: parsedException.reason } : {},
|
|
4553
|
+
...typeof parsedException.retryAfterMilliseconds === "number" ? { retryAfterMilliseconds: parsedException.retryAfterMilliseconds } : {}
|
|
4554
|
+
};
|
|
4555
|
+
const error2 = new Error(data.message ? `${data.error}: ${data.message}` : data.error);
|
|
4556
|
+
error2.name = data.error;
|
|
4557
|
+
error2.kiroError = data;
|
|
4558
|
+
return { [key]: error2 };
|
|
4559
|
+
}
|
|
4151
4560
|
const parsed = JSON.parse(utf8Decoder.decode(msg.body));
|
|
4152
4561
|
return { [key]: parsed };
|
|
4153
4562
|
});
|
|
@@ -4156,29 +4565,43 @@ function readKiroEventStream(body, options) {
|
|
|
4156
4565
|
const FIRST_TOKEN_SENTINEL = /* @__PURE__ */ Symbol("firstTokenTimeout");
|
|
4157
4566
|
try {
|
|
4158
4567
|
while (true) {
|
|
4568
|
+
if (callerSignal?.aborted) {
|
|
4569
|
+
throw callerSignal.reason ?? new Error("Request aborted");
|
|
4570
|
+
}
|
|
4159
4571
|
let iterResult;
|
|
4160
4572
|
try {
|
|
4161
4573
|
if (!gotFirstToken) {
|
|
4162
4574
|
const readPromise = iterator.next();
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4575
|
+
let firstTokenTimer;
|
|
4576
|
+
try {
|
|
4577
|
+
const result = await Promise.race([
|
|
4578
|
+
readPromise,
|
|
4579
|
+
new Promise((resolve) => {
|
|
4580
|
+
firstTokenTimer = setTimeout(() => resolve(FIRST_TOKEN_SENTINEL), options.firstTokenTimeoutMs);
|
|
4581
|
+
})
|
|
4582
|
+
]);
|
|
4583
|
+
if (result === FIRST_TOKEN_SENTINEL) {
|
|
4584
|
+
readPromise.catch(() => {
|
|
4585
|
+
});
|
|
4586
|
+
void bodyReader.cancel().catch(() => {
|
|
4587
|
+
});
|
|
4588
|
+
outcome.firstTokenTimedOut = true;
|
|
4589
|
+
return;
|
|
4590
|
+
}
|
|
4591
|
+
iterResult = result;
|
|
4592
|
+
gotFirstToken = true;
|
|
4593
|
+
resetIdle();
|
|
4594
|
+
} finally {
|
|
4595
|
+
if (firstTokenTimer !== void 0)
|
|
4596
|
+
clearTimeout(firstTokenTimer);
|
|
4174
4597
|
}
|
|
4175
|
-
iterResult = result;
|
|
4176
|
-
gotFirstToken = true;
|
|
4177
|
-
resetIdle();
|
|
4178
4598
|
} else {
|
|
4179
4599
|
iterResult = await iterator.next();
|
|
4180
4600
|
}
|
|
4181
4601
|
} catch (e) {
|
|
4602
|
+
const kiroError = e?.kiroError;
|
|
4603
|
+
if (kiroError)
|
|
4604
|
+
outcome.errorData = kiroError;
|
|
4182
4605
|
outcome.error = e instanceof Error ? e.message : (typeof e === "object" && e !== null ? JSON.stringify(e) : String(e)) || "Unknown stream error";
|
|
4183
4606
|
return;
|
|
4184
4607
|
}
|
|
@@ -4186,148 +4609,40 @@ function readKiroEventStream(body, options) {
|
|
|
4186
4609
|
if (done)
|
|
4187
4610
|
return;
|
|
4188
4611
|
resetIdle();
|
|
4189
|
-
const
|
|
4190
|
-
|
|
4612
|
+
const frameEntry = Object.entries(value)[0];
|
|
4613
|
+
if (!frameEntry)
|
|
4614
|
+
continue;
|
|
4615
|
+
const [frameKey, framePayload] = frameEntry;
|
|
4616
|
+
const event = parseKiroEvent(frameKey, framePayload ?? {});
|
|
4191
4617
|
if (!event)
|
|
4192
4618
|
continue;
|
|
4619
|
+
if (event.type === "ignored") {
|
|
4620
|
+
if (debugEnabled())
|
|
4621
|
+
debugLog("stream.events.ignored", [event.data.key]);
|
|
4622
|
+
continue;
|
|
4623
|
+
}
|
|
4193
4624
|
if (debugEnabled())
|
|
4194
4625
|
debugLog("stream.events", [event]);
|
|
4195
4626
|
if (event.type === "error") {
|
|
4196
4627
|
outcome.error = event.data.message ? `${event.data.error}: ${event.data.message}` : event.data.error;
|
|
4628
|
+
outcome.errorData = event.data;
|
|
4197
4629
|
void bodyReader.cancel().catch(() => {
|
|
4198
4630
|
});
|
|
4199
4631
|
return;
|
|
4200
4632
|
}
|
|
4201
|
-
yield { event, payload };
|
|
4633
|
+
yield { event, payload: framePayload };
|
|
4202
4634
|
}
|
|
4203
4635
|
} finally {
|
|
4204
4636
|
if (idleTimer)
|
|
4205
4637
|
clearTimeout(idleTimer);
|
|
4638
|
+
callerSignal?.removeEventListener("abort", onCallerStreamAbort);
|
|
4206
4639
|
}
|
|
4207
4640
|
}
|
|
4208
4641
|
return { frames: frames(), outcome };
|
|
4209
4642
|
}
|
|
4210
4643
|
|
|
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
4644
|
// ../kiro-core/dist/stream.js
|
|
4645
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
4331
4646
|
init_debug();
|
|
4332
4647
|
init_effort();
|
|
4333
4648
|
init_endpoints();
|
|
@@ -4400,7 +4715,64 @@ function createResponseHeaderDeadline(callerSignal, timeoutMs) {
|
|
|
4400
4715
|
};
|
|
4401
4716
|
}
|
|
4402
4717
|
|
|
4718
|
+
// ../kiro-core/dist/usage-tracking.js
|
|
4719
|
+
var DEFAULT_USD_PER_CREDIT = 0.04;
|
|
4720
|
+
var DEFAULT_ESTIMATED_CACHE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
4721
|
+
var KIRO_USAGE_TRACKING_DISABLED = Object.freeze({
|
|
4722
|
+
estimateDollarValue: false,
|
|
4723
|
+
usdPerCredit: DEFAULT_USD_PER_CREDIT,
|
|
4724
|
+
estimateCacheUsage: false,
|
|
4725
|
+
estimatedCacheTimeout: DEFAULT_ESTIMATED_CACHE_TIMEOUT_MS
|
|
4726
|
+
});
|
|
4727
|
+
var CREDIT_UNITS = /* @__PURE__ */ new Set(["credit", "credits"]);
|
|
4728
|
+
function estimateKiroCreditCost(tracking, metering) {
|
|
4729
|
+
if (!tracking.estimateDollarValue || !metering)
|
|
4730
|
+
return void 0;
|
|
4731
|
+
if (typeof metering.unit !== "string" || !CREDIT_UNITS.has(metering.unit.toLowerCase()))
|
|
4732
|
+
return void 0;
|
|
4733
|
+
const { credits } = metering;
|
|
4734
|
+
if (typeof credits !== "number" || !Number.isFinite(credits) || credits < 0)
|
|
4735
|
+
return void 0;
|
|
4736
|
+
return credits * tracking.usdPerCredit;
|
|
4737
|
+
}
|
|
4738
|
+
|
|
4403
4739
|
// ../kiro-core/dist/stream.js
|
|
4740
|
+
function describeAttempts(count) {
|
|
4741
|
+
return count === 1 ? "1 attempt" : `${count} attempts`;
|
|
4742
|
+
}
|
|
4743
|
+
var DIAGNOSTIC_QUOTE_LIMIT = 200;
|
|
4744
|
+
function clampForDiagnostic(text) {
|
|
4745
|
+
return text.length <= DIAGNOSTIC_QUOTE_LIMIT ? text : `${text.slice(0, DIAGNOSTIC_QUOTE_LIMIT)}\u2026 (truncated)`;
|
|
4746
|
+
}
|
|
4747
|
+
function encodeBytesForDiagnostic(bytes) {
|
|
4748
|
+
let encoded = "";
|
|
4749
|
+
for (const byte of bytes) {
|
|
4750
|
+
encoded += String.fromCharCode(65 + (byte >> 4), 65 + (byte & 15));
|
|
4751
|
+
}
|
|
4752
|
+
return encoded;
|
|
4753
|
+
}
|
|
4754
|
+
function encodeToolNameForDiagnostic(name) {
|
|
4755
|
+
const identity = typeof name === "string" ? name : `${typeof name}:${JSON.stringify(name)}`;
|
|
4756
|
+
let encoded = "";
|
|
4757
|
+
for (let i = 0; i < identity.length; i++) {
|
|
4758
|
+
const codeUnit = identity.charCodeAt(i);
|
|
4759
|
+
encoded += String.fromCharCode(65 + (codeUnit >> 12), 65 + (codeUnit >> 8 & 15), 65 + (codeUnit >> 4 & 15), 65 + (codeUnit & 15));
|
|
4760
|
+
}
|
|
4761
|
+
return encoded;
|
|
4762
|
+
}
|
|
4763
|
+
function describeDroppedToolNames(names) {
|
|
4764
|
+
const encoded = names.map((name) => `A-P:${encodeToolNameForDiagnostic(name)}`).join(", ");
|
|
4765
|
+
if (encoded.length <= DIAGNOSTIC_QUOTE_LIMIT)
|
|
4766
|
+
return encoded;
|
|
4767
|
+
const digest = createHash3("sha256").update(JSON.stringify(names)).digest();
|
|
4768
|
+
return `A-P-DIGEST:${encodeBytesForDiagnostic(digest)} (tool identities fingerprinted)`;
|
|
4769
|
+
}
|
|
4770
|
+
function describeReturnedContent(kinds) {
|
|
4771
|
+
const unique = [...new Set(kinds)].sort();
|
|
4772
|
+
if (unique.length === 0)
|
|
4773
|
+
return "returning empty content";
|
|
4774
|
+
return `returning only ${unique.join(" and ")} content`;
|
|
4775
|
+
}
|
|
4404
4776
|
var skipProfileResolutionForTests = false;
|
|
4405
4777
|
var TEST_PROFILE_ARN = "arn:aws:codewhisperer:us-east-1:000000000000:profile/test";
|
|
4406
4778
|
async function* streamKiro(request) {
|
|
@@ -4411,7 +4783,6 @@ async function* streamKiro(request) {
|
|
|
4411
4783
|
}
|
|
4412
4784
|
let accessToken = initialAccessToken;
|
|
4413
4785
|
const region = model.region ?? "us-east-1";
|
|
4414
|
-
const endpoint = new URL("generateAssistantResponse", getKiroEndpoints(region).runtime).toString();
|
|
4415
4786
|
let managementAuth = { accessToken, region };
|
|
4416
4787
|
const cliCreds = getKiroCliCredentials() ?? getKiroCliCredentialsAllowExpired();
|
|
4417
4788
|
const cliProfileArn = cliCreds?.access === accessToken ? cliCreds.profileArn : void 0;
|
|
@@ -4430,9 +4801,11 @@ async function* streamKiro(request) {
|
|
|
4430
4801
|
managementAuth = { accessToken, region };
|
|
4431
4802
|
profileArn = freshCreds.profileArn || (skipProfileResolutionForTests ? TEST_PROFILE_ARN : await resolveKiroProfileArn(managementAuth));
|
|
4432
4803
|
}
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4804
|
+
let runtimeRegion = getKiroRegionFromProfileArn(profileArn) ?? region;
|
|
4805
|
+
let endpoint = new URL("generateAssistantResponse", getKiroEndpoints(runtimeRegion).runtime).toString();
|
|
4806
|
+
if (!process.env.VITEST && isCacheStale(runtimeRegion)) {
|
|
4807
|
+
updateKiroModelsCache(accessToken, runtimeRegion, profileArn).catch((error2) => {
|
|
4808
|
+
console.warn(`[kiro-core] Failed to refresh Kiro model catalog in ${runtimeRegion}: ${formatSafeError(error2)}`);
|
|
4436
4809
|
});
|
|
4437
4810
|
}
|
|
4438
4811
|
const kiroModelId = resolveKiroModel(model.id, model.kiroModelId);
|
|
@@ -4461,8 +4834,13 @@ async function* streamKiro(request) {
|
|
|
4461
4834
|
${systemPrompt}` : ""}`;
|
|
4462
4835
|
}
|
|
4463
4836
|
const assembler = new KiroResponseAssembler(model, thinkingEnabled);
|
|
4837
|
+
const usageTracking = request.usageTracking ?? KIRO_USAGE_TRACKING_DISABLED;
|
|
4464
4838
|
let retryCount = 0;
|
|
4465
4839
|
const maxRetries = 3;
|
|
4840
|
+
let emptyAttempts = 0;
|
|
4841
|
+
let echoAttempts = 0;
|
|
4842
|
+
let credentialRefreshTotal = 0;
|
|
4843
|
+
let capacityRetryTotal = 0;
|
|
4466
4844
|
const conversationId = request.sessionId ?? crypto.randomUUID();
|
|
4467
4845
|
requestLoop: while (retryCount <= maxRetries) {
|
|
4468
4846
|
if (signal?.aborted)
|
|
@@ -4545,6 +4923,7 @@ ${systemPrompt}` : ""}`;
|
|
|
4545
4923
|
});
|
|
4546
4924
|
if (isCapacityError(errText) && capacityRetryCount < capacityRetryConfig.maxRetries) {
|
|
4547
4925
|
capacityRetryCount++;
|
|
4926
|
+
capacityRetryTotal++;
|
|
4548
4927
|
const delayMs = exponentialBackoff(capacityRetryCount - 1, capacityRetryConfig.baseDelayMs, 3e4);
|
|
4549
4928
|
logCapacityEvent(`INSUFFICIENT_MODEL_CAPACITY \u2014 retrying in ${delayMs}ms (${capacityRetryCount}/${capacityRetryConfig.maxRetries})`);
|
|
4550
4929
|
await abortableDelay(delayMs, signal);
|
|
@@ -4572,6 +4951,7 @@ ${systemPrompt}` : ""}`;
|
|
|
4572
4951
|
}
|
|
4573
4952
|
if (response.status === 403 && !isCapacityError(errText) && retryCount < maxRetries) {
|
|
4574
4953
|
retryCount++;
|
|
4954
|
+
credentialRefreshTotal++;
|
|
4575
4955
|
invalidateKiroProfileArn(managementAuth);
|
|
4576
4956
|
const rejectedAccessToken = accessToken;
|
|
4577
4957
|
const rejectedProfileArn = profileArn;
|
|
@@ -4583,16 +4963,23 @@ ${systemPrompt}` : ""}`;
|
|
|
4583
4963
|
managementAuth = { accessToken, region };
|
|
4584
4964
|
const inheritedDesktopProfileArn = rejectedCliCreds?.authMethod === "desktop" && freshCreds?.authMethod === "desktop" ? rejectedProfileArn : void 0;
|
|
4585
4965
|
profileArn = freshCreds?.profileArn || inheritedDesktopProfileArn || (skipProfileResolutionForTests ? TEST_PROFILE_ARN : await resolveKiroProfileArn(managementAuth));
|
|
4966
|
+
runtimeRegion = getKiroRegionFromProfileArn(profileArn) ?? region;
|
|
4967
|
+
endpoint = new URL("generateAssistantResponse", getKiroEndpoints(runtimeRegion).runtime).toString();
|
|
4586
4968
|
await abortableDelay(exponentialBackoff(retryCount - 1, 500, MAX_RETRY_DELAY), signal);
|
|
4587
4969
|
break;
|
|
4588
4970
|
}
|
|
4971
|
+
const errorMeta = {
|
|
4972
|
+
reasonCode: extractKiroReasonCode(errText),
|
|
4973
|
+
retryAfterMs: parseRetryAfterMs(response.headers),
|
|
4974
|
+
providerAttempts: { credentialRefresh: credentialRefreshTotal, capacity: capacityRetryTotal }
|
|
4975
|
+
};
|
|
4589
4976
|
if (isNonRetryableBodyError(errText) || isCapacityError(errText)) {
|
|
4590
|
-
throw new
|
|
4977
|
+
throw new KiroApiError(`Kiro API error: ${errText || safeStatusText}`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4591
4978
|
}
|
|
4592
4979
|
if (isTooBigError(response.status, errText)) {
|
|
4593
|
-
throw new
|
|
4980
|
+
throw new KiroApiError(`Kiro API error: context_length_exceeded (${response.status} ${errText})`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4594
4981
|
}
|
|
4595
|
-
throw new
|
|
4982
|
+
throw new KiroApiError(`Kiro API error: ${response.status} ${safeStatusText} ${errText}`, response.status, errorMeta.reasonCode, errorMeta.retryAfterMs, errorMeta.providerAttempts);
|
|
4596
4983
|
}
|
|
4597
4984
|
break;
|
|
4598
4985
|
}
|
|
@@ -4606,7 +4993,8 @@ ${systemPrompt}` : ""}`;
|
|
|
4606
4993
|
throw new Error("No response body");
|
|
4607
4994
|
assembler.beginAttempt();
|
|
4608
4995
|
const { frames, outcome } = readKiroEventStream(response.body, {
|
|
4609
|
-
firstTokenTimeoutMs: model.firstTokenTimeout ?? firstTokenTimeoutForModel(model.id)
|
|
4996
|
+
firstTokenTimeoutMs: model.firstTokenTimeout ?? firstTokenTimeoutForModel(model.id),
|
|
4997
|
+
signal
|
|
4610
4998
|
});
|
|
4611
4999
|
for await (const frame of frames) {
|
|
4612
5000
|
assembler.handle(frame);
|
|
@@ -4616,6 +5004,11 @@ ${systemPrompt}` : ""}`;
|
|
|
4616
5004
|
if (outcome.firstTokenTimedOut || outcome.idleTimedOut || outcome.error) {
|
|
4617
5005
|
if (retryCount < maxRetries) {
|
|
4618
5006
|
retryCount++;
|
|
5007
|
+
if (outcome.errorData && debugEnabled()) {
|
|
5008
|
+
debugLog("stream.error.typed", [outcome.errorData]);
|
|
5009
|
+
}
|
|
5010
|
+
assembler.discard();
|
|
5011
|
+
yield* assembler.takeEvents();
|
|
4619
5012
|
await abortableDelay(exponentialBackoff(retryCount - 1, 1e3, MAX_RETRY_DELAY), signal);
|
|
4620
5013
|
continue;
|
|
4621
5014
|
}
|
|
@@ -4625,7 +5018,13 @@ ${systemPrompt}` : ""}`;
|
|
|
4625
5018
|
}
|
|
4626
5019
|
const summary = assembler.endTurn();
|
|
4627
5020
|
yield* assembler.takeEvents();
|
|
4628
|
-
|
|
5021
|
+
const degenerate = summary.isEmpty || summary.isEchoLoop;
|
|
5022
|
+
if (summary.isEchoLoop)
|
|
5023
|
+
echoAttempts++;
|
|
5024
|
+
else if (degenerate)
|
|
5025
|
+
emptyAttempts++;
|
|
5026
|
+
let errorMessage;
|
|
5027
|
+
if (degenerate) {
|
|
4629
5028
|
const mayRetry = retryCount < maxRetries && (!summary.isEchoLoop || request.canDiscardEmittedBlocks === true);
|
|
4630
5029
|
if (mayRetry) {
|
|
4631
5030
|
retryCount++;
|
|
@@ -4637,15 +5036,39 @@ ${systemPrompt}` : ""}`;
|
|
|
4637
5036
|
}
|
|
4638
5037
|
if (summary.isEchoLoop) {
|
|
4639
5038
|
assembler.stripEcho();
|
|
4640
|
-
|
|
5039
|
+
const alsoEmpty = emptyAttempts > 0 ? ` (plus ${describeAttempts(emptyAttempts)} with no text at all)` : "";
|
|
5040
|
+
console.warn(`[kiro-core] Echo loop persisted across ${describeAttempts(echoAttempts)}${alsoEmpty} \u2014 stripping "Continue" response (${summary.responseText.length} chars)`);
|
|
5041
|
+
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
5042
|
} else {
|
|
4642
|
-
|
|
5043
|
+
const alsoEchoed = echoAttempts > 0 ? ` (plus ${describeAttempts(echoAttempts)} that echoed the continuation prompt)` : "";
|
|
5044
|
+
console.warn(`[kiro-core] Empty response on ${describeAttempts(emptyAttempts)}${alsoEchoed}, retry budget exhausted \u2014 returning stopReason:"${summary.stopReason}" to avoid agent loop stall`);
|
|
5045
|
+
errorMessage = `Kiro returned no text and no tool calls on ${describeAttempts(emptyAttempts)}${alsoEchoed}; retry budget exhausted, ${describeReturnedContent(assembler.contentKinds())} with stopReason:"${summary.stopReason}"`;
|
|
4643
5046
|
}
|
|
4644
5047
|
}
|
|
4645
|
-
|
|
5048
|
+
if (summary.droppedToolCalls.length > 0) {
|
|
5049
|
+
const names = describeDroppedToolNames(summary.droppedToolCalls);
|
|
5050
|
+
const one = summary.droppedToolCalls.length === 1;
|
|
5051
|
+
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}"`;
|
|
5052
|
+
errorMessage = errorMessage ? `${errorMessage}. ${dropDiagnostic}` : dropDiagnostic;
|
|
5053
|
+
}
|
|
5054
|
+
const { stopReason, usage, wireUsage, metering } = assembler.complete();
|
|
4646
5055
|
yield* assembler.takeEvents();
|
|
5056
|
+
if (!errorMessage) {
|
|
5057
|
+
const estimatedRead = applyCacheEstimate(conversationId, usage, wireUsage, usageTracking);
|
|
5058
|
+
if (estimatedRead > 0) {
|
|
5059
|
+
debugLog("usage.estimate", {
|
|
5060
|
+
conversationId,
|
|
5061
|
+
estimatedRead,
|
|
5062
|
+
input: usage.input,
|
|
5063
|
+
cacheRead: usage.cacheRead
|
|
5064
|
+
});
|
|
5065
|
+
}
|
|
5066
|
+
const estimatedCost = estimateKiroCreditCost(usageTracking, metering);
|
|
5067
|
+
if (estimatedCost !== void 0)
|
|
5068
|
+
usage.cost.total = estimatedCost;
|
|
5069
|
+
}
|
|
4647
5070
|
yield { type: "usage", usage };
|
|
4648
|
-
yield { type: "done", stopReason };
|
|
5071
|
+
yield { type: "done", stopReason, ...errorMessage ? { errorMessage } : {} };
|
|
4649
5072
|
return;
|
|
4650
5073
|
}
|
|
4651
5074
|
}
|
|
@@ -5023,10 +5446,20 @@ function streamKiroForOmp(model, context, options) {
|
|
|
5023
5446
|
if (event.usage.contextPercent !== void 0) {
|
|
5024
5447
|
output.usage.contextPercent = event.usage.contextPercent;
|
|
5025
5448
|
}
|
|
5449
|
+
if (event.usage.credits !== void 0) {
|
|
5450
|
+
output.usage.credits = event.usage.credits;
|
|
5451
|
+
}
|
|
5452
|
+
if (event.usage.creditUnit !== void 0) {
|
|
5453
|
+
output.usage.creditUnit = event.usage.creditUnit;
|
|
5454
|
+
}
|
|
5455
|
+
if (event.usage.cacheEstimated !== void 0) {
|
|
5456
|
+
output.usage.cacheEstimated = event.usage.cacheEstimated;
|
|
5457
|
+
}
|
|
5026
5458
|
break;
|
|
5027
5459
|
}
|
|
5028
5460
|
case "done":
|
|
5029
5461
|
output.stopReason = event.stopReason;
|
|
5462
|
+
if (event.errorMessage) output.errorMessage = event.errorMessage;
|
|
5030
5463
|
stream.push({ type: "done", reason: event.stopReason, message: output });
|
|
5031
5464
|
break;
|
|
5032
5465
|
}
|