mirror of
https://github.com/cline/cline.git
synced 2026-10-29 17:42:34 +08:00
fix: SAP AI Core uses AI SDK community provider (CLINE-2307) (#11075)
This commit is contained in:
@@ -42,6 +42,9 @@ pnpm-lock.yaml
|
||||
# Session files / User data
|
||||
.cline/data
|
||||
.cline/tmp
|
||||
.cline/**/managed.json
|
||||
.cline/**/bundle.json
|
||||
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
getDefaultAwsRegion,
|
||||
type ProviderConfigValues,
|
||||
resolveProviderConfigAwsRegion,
|
||||
resolveProviderConfigSap,
|
||||
updateProviderConfigValue,
|
||||
} from "../../utils/provider-config-values";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
@@ -316,6 +317,11 @@ const DEFAULT_FIELD_LABELS: Partial<Record<ProviderConfigFieldKey, string>> = {
|
||||
baseUrl: "Base URL",
|
||||
awsRegion: "AWS Region",
|
||||
awsProfile: "AWS Profile Name",
|
||||
sapClientId: "Client ID",
|
||||
sapClientSecret: "Client Secret",
|
||||
sapTokenUrl: "Token URL",
|
||||
sapResourceGroup: "Resource Group",
|
||||
sapDeploymentId: "Deployment ID",
|
||||
};
|
||||
|
||||
const DEFAULT_FIELD_PLACEHOLDERS: Partial<
|
||||
@@ -325,6 +331,11 @@ const DEFAULT_FIELD_PLACEHOLDERS: Partial<
|
||||
baseUrl: "",
|
||||
awsRegion: "us-east-1",
|
||||
awsProfile: "default",
|
||||
sapClientId: "sb-...|xsuaa_std!b...",
|
||||
sapClientSecret: "SAP AI Core client secret",
|
||||
sapTokenUrl: "https://<subdomain>.authentication.sap.hana.ondemand.com",
|
||||
sapResourceGroup: "default",
|
||||
sapDeploymentId: "",
|
||||
};
|
||||
|
||||
/** Render order for cycling focus with Tab. */
|
||||
@@ -333,6 +344,11 @@ const FIELD_ORDER: ProviderConfigFieldKey[] = [
|
||||
"baseUrl",
|
||||
"apiKey",
|
||||
"awsProfile",
|
||||
"sapClientId",
|
||||
"sapClientSecret",
|
||||
"sapTokenUrl",
|
||||
"sapResourceGroup",
|
||||
"sapDeploymentId",
|
||||
];
|
||||
|
||||
export type ProviderConfigInputFields = Partial<
|
||||
@@ -391,6 +407,19 @@ export function ProviderConfigInputContent(
|
||||
initial.apiKey = existingSettings?.apiKey?.trim() ?? "";
|
||||
if (config.fields.awsProfile)
|
||||
initial.awsProfile = existingSettings?.aws?.profile?.trim() ?? "";
|
||||
if (config.fields.sapClientId)
|
||||
initial.sapClientId = existingSettings?.sap?.clientId?.trim() ?? "";
|
||||
if (config.fields.sapClientSecret)
|
||||
initial.sapClientSecret =
|
||||
existingSettings?.sap?.clientSecret?.trim() ?? "";
|
||||
if (config.fields.sapTokenUrl)
|
||||
initial.sapTokenUrl = existingSettings?.sap?.tokenUrl?.trim() ?? "";
|
||||
if (config.fields.sapResourceGroup)
|
||||
initial.sapResourceGroup =
|
||||
existingSettings?.sap?.resourceGroup?.trim() ?? "default";
|
||||
if (config.fields.sapDeploymentId)
|
||||
initial.sapDeploymentId =
|
||||
existingSettings?.sap?.deploymentId?.trim() ?? "";
|
||||
return initial;
|
||||
});
|
||||
|
||||
@@ -402,6 +431,12 @@ export function ProviderConfigInputContent(
|
||||
const apiKey = values.apiKey?.trim();
|
||||
const awsProfile = values.awsProfile?.trim();
|
||||
const hasAwsFields = config.fields.awsRegion || config.fields.awsProfile;
|
||||
const hasSapFields =
|
||||
config.fields.sapClientId ||
|
||||
config.fields.sapClientSecret ||
|
||||
config.fields.sapTokenUrl ||
|
||||
config.fields.sapResourceGroup ||
|
||||
config.fields.sapDeploymentId;
|
||||
saveLocalProviderSettings(providerSettingsManager, {
|
||||
providerId,
|
||||
apiKey: config.fields.apiKey ? apiKey : undefined,
|
||||
@@ -413,6 +448,7 @@ export function ProviderConfigInputContent(
|
||||
profile: apiKey ? undefined : awsProfile || undefined,
|
||||
}
|
||||
: undefined,
|
||||
sap: hasSapFields ? resolveProviderConfigSap(values) : undefined,
|
||||
});
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
getDefaultAwsRegion,
|
||||
resolveProviderConfigAwsRegion,
|
||||
resolveProviderConfigSap,
|
||||
updateProviderConfigValue,
|
||||
} from "./provider-config-values";
|
||||
|
||||
@@ -64,4 +65,22 @@ describe("provider config values", () => {
|
||||
}),
|
||||
).toBe("us-west-2");
|
||||
});
|
||||
|
||||
it("resolves SAP AI Core field values into SAP settings", () => {
|
||||
expect(
|
||||
resolveProviderConfigSap({
|
||||
sapClientId: " client ",
|
||||
sapClientSecret: " secret ",
|
||||
sapTokenUrl: " https://auth.example ",
|
||||
sapResourceGroup: " default ",
|
||||
sapDeploymentId: " deployment ",
|
||||
}),
|
||||
).toEqual({
|
||||
clientId: "client",
|
||||
clientSecret: "secret",
|
||||
tokenUrl: "https://auth.example",
|
||||
resourceGroup: "default",
|
||||
deploymentId: "deployment",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,6 +20,27 @@ export function resolveProviderConfigAwsRegion(
|
||||
return values.awsRegion?.trim() || getDefaultAwsRegion(values.awsProfile);
|
||||
}
|
||||
|
||||
export function resolveProviderConfigSap(values: ProviderConfigValues):
|
||||
| {
|
||||
clientId?: string;
|
||||
clientSecret?: string;
|
||||
tokenUrl?: string;
|
||||
resourceGroup?: string;
|
||||
deploymentId?: string;
|
||||
}
|
||||
| undefined {
|
||||
const sap = {
|
||||
clientId: values.sapClientId?.trim() || undefined,
|
||||
clientSecret: values.sapClientSecret?.trim() || undefined,
|
||||
tokenUrl: values.sapTokenUrl?.trim() || undefined,
|
||||
resourceGroup: values.sapResourceGroup?.trim() || undefined,
|
||||
deploymentId: values.sapDeploymentId?.trim() || undefined,
|
||||
};
|
||||
return Object.values(sap).some((value) => value !== undefined)
|
||||
? sap
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function updateProviderConfigValue(
|
||||
previous: ProviderConfigValues,
|
||||
field: ProviderConfigFieldKey,
|
||||
|
||||
@@ -28,13 +28,14 @@ import {
|
||||
useSearchableList,
|
||||
} from "../../components/searchable-list";
|
||||
import { palette } from "../../palette";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
getDefaultAwsRegion,
|
||||
resolveProviderConfigAwsRegion,
|
||||
updateProviderConfigValue,
|
||||
type ProviderConfigValues,
|
||||
resolveProviderConfigAwsRegion,
|
||||
resolveProviderConfigSap,
|
||||
updateProviderConfigValue,
|
||||
} from "../../utils/provider-config-values";
|
||||
import { getProviderSection } from "../../utils/provider-sections";
|
||||
import {
|
||||
isOnboardingOAuthProviderId,
|
||||
type OnboardingOAuthProviderId,
|
||||
@@ -392,6 +393,24 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
if (config.fields.awsProfile) {
|
||||
initialValues.awsProfile = existing?.aws?.profile?.trim() ?? "";
|
||||
}
|
||||
if (config.fields.sapClientId) {
|
||||
initialValues.sapClientId = existing?.sap?.clientId?.trim() ?? "";
|
||||
}
|
||||
if (config.fields.sapClientSecret) {
|
||||
initialValues.sapClientSecret =
|
||||
existing?.sap?.clientSecret?.trim() ?? "";
|
||||
}
|
||||
if (config.fields.sapTokenUrl) {
|
||||
initialValues.sapTokenUrl = existing?.sap?.tokenUrl?.trim() ?? "";
|
||||
}
|
||||
if (config.fields.sapResourceGroup) {
|
||||
initialValues.sapResourceGroup =
|
||||
existing?.sap?.resourceGroup?.trim() ?? "default";
|
||||
}
|
||||
if (config.fields.sapDeploymentId) {
|
||||
initialValues.sapDeploymentId =
|
||||
existing?.sap?.deploymentId?.trim() ?? "";
|
||||
}
|
||||
setByoValues(initialValues);
|
||||
|
||||
// Focus the first visible field
|
||||
@@ -426,6 +445,12 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
const apiKey = byoValues.apiKey?.trim();
|
||||
const awsProfile = byoValues.awsProfile?.trim();
|
||||
const hasAwsFields = byoFields.awsRegion || byoFields.awsProfile;
|
||||
const hasSapFields =
|
||||
byoFields.sapClientId ||
|
||||
byoFields.sapClientSecret ||
|
||||
byoFields.sapTokenUrl ||
|
||||
byoFields.sapResourceGroup ||
|
||||
byoFields.sapDeploymentId;
|
||||
|
||||
saveLocalProviderSettings(providerSettingsManager, {
|
||||
providerId: activeProviderId,
|
||||
@@ -438,6 +463,7 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
profile: apiKey ? undefined : awsProfile || undefined,
|
||||
}
|
||||
: undefined,
|
||||
sap: hasSapFields ? resolveProviderConfigSap(byoValues) : undefined,
|
||||
});
|
||||
// Emit a single `user.provider_configured` event mirroring the
|
||||
// `{ provider }` payload shape used by the auth funnel. The save above
|
||||
|
||||
@@ -6,4 +6,9 @@ export const FIELD_ORDER: ProviderConfigFieldKey[] = [
|
||||
"baseUrl",
|
||||
"apiKey",
|
||||
"awsProfile",
|
||||
"sapClientId",
|
||||
"sapClientSecret",
|
||||
"sapTokenUrl",
|
||||
"sapResourceGroup",
|
||||
"sapDeploymentId",
|
||||
];
|
||||
|
||||
@@ -224,6 +224,11 @@ const DEFAULT_FIELD_LABELS: Partial<Record<ProviderConfigFieldKey, string>> = {
|
||||
baseUrl: "Base URL",
|
||||
awsRegion: "AWS Region",
|
||||
awsProfile: "AWS Profile Name",
|
||||
sapClientId: "Client ID",
|
||||
sapClientSecret: "Client Secret",
|
||||
sapTokenUrl: "Token URL",
|
||||
sapResourceGroup: "Resource Group",
|
||||
sapDeploymentId: "Deployment ID",
|
||||
};
|
||||
|
||||
const DEFAULT_FIELD_PLACEHOLDERS: Partial<
|
||||
@@ -233,6 +238,11 @@ const DEFAULT_FIELD_PLACEHOLDERS: Partial<
|
||||
baseUrl: "",
|
||||
awsRegion: "us-east-1",
|
||||
awsProfile: "default",
|
||||
sapClientId: "sb-...|xsuaa_std!b...",
|
||||
sapClientSecret: "SAP AI Core client secret",
|
||||
sapTokenUrl: "https://<subdomain>.authentication.sap.hana.ondemand.com",
|
||||
sapResourceGroup: "default",
|
||||
sapDeploymentId: "",
|
||||
};
|
||||
|
||||
export function OnboardingProviderConfigScreen(props: {
|
||||
|
||||
@@ -142,6 +142,7 @@ describe("provider readiness", () => {
|
||||
expect(
|
||||
isProviderSettingsUsable("sapaicore", {
|
||||
provider: "sapaicore",
|
||||
baseUrl: "https://api.ai.example.invalid",
|
||||
sap: {
|
||||
clientId: "client",
|
||||
clientSecret: "secret",
|
||||
@@ -149,5 +150,15 @@ describe("provider readiness", () => {
|
||||
},
|
||||
} satisfies ProviderSettings),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isProviderSettingsUsable("sapaicore", {
|
||||
provider: "sapaicore",
|
||||
sap: {
|
||||
clientId: "client",
|
||||
clientSecret: "secret",
|
||||
tokenUrl: "https://example.com/token",
|
||||
},
|
||||
} satisfies ProviderSettings),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,7 +45,8 @@ function hasSapCredentials(settings: ProviderSettings): boolean {
|
||||
return (
|
||||
hasText(sap?.clientId) &&
|
||||
hasText(sap?.clientSecret) &&
|
||||
hasText(sap?.tokenUrl)
|
||||
hasText(sap?.tokenUrl) &&
|
||||
hasText(settings.baseUrl)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,6 +69,9 @@ export function isProviderSettingsUsable(
|
||||
hasAwsRegion(settings)
|
||||
);
|
||||
}
|
||||
if (normalizedProviderId === "sapaicore") {
|
||||
return hasSapCredentials(settings);
|
||||
}
|
||||
if (getPersistedProviderApiKey(normalizedProviderId, settings)) {
|
||||
return true;
|
||||
}
|
||||
@@ -84,9 +88,6 @@ export function isProviderSettingsUsable(
|
||||
if (normalizedProviderId === "azure") {
|
||||
return hasAzureCredentials(settings);
|
||||
}
|
||||
if (normalizedProviderId === "sapaicore") {
|
||||
return hasSapCredentials(settings);
|
||||
}
|
||||
if (!fields.fields.baseUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+121
-2
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"apps/cli": {
|
||||
"name": "@cline/cli",
|
||||
"version": "3.0.11",
|
||||
"version": "3.0.13",
|
||||
"bin": {
|
||||
"cline": "src/index.ts",
|
||||
},
|
||||
@@ -350,6 +350,7 @@
|
||||
"@ai-sdk/provider": "^3.0.8",
|
||||
"@aws-sdk/credential-providers": "^3.922.0",
|
||||
"@cline/shared": "workspace:*",
|
||||
"@jerome-benoit/sap-ai-provider": "^4.6.0",
|
||||
"@langfuse/otel": "^4.0.0",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/sdk-trace-node": "^2.6.1",
|
||||
@@ -614,6 +615,10 @@
|
||||
|
||||
"@cline/vscode": ["@cline/vscode@workspace:apps/examples/vscode"],
|
||||
|
||||
"@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
|
||||
|
||||
"@dabh/diagnostics": ["@dabh/diagnostics@2.0.8", "", { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q=="],
|
||||
|
||||
"@date-fns/tz": ["@date-fns/tz@1.5.0", "", {}, "sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg=="],
|
||||
|
||||
"@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="],
|
||||
@@ -810,6 +815,8 @@
|
||||
|
||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"@jerome-benoit/sap-ai-provider": ["@jerome-benoit/sap-ai-provider@4.6.9", "", { "dependencies": { "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.26", "@sap-ai-sdk/foundation-models": "^2.10.0", "@sap-ai-sdk/orchestration": "^2.10.0", "zod": "^4.4.2" }, "peerDependencies": { "ai": "^5.0.0 || ^6.0.0" } }, "sha512-z+ayDBasD2/PB4iAO6Lp6myQ96KZYjN/gBX3WAisaFKcCeRIsJyzHcBQh26lDu0cpzAybRmI5XUrWzn3nRaqgA=="],
|
||||
|
||||
"@jest/expect-utils": ["@jest/expect-utils@29.7.0", "", { "dependencies": { "jest-get-type": "^29.6.3" } }, "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA=="],
|
||||
|
||||
"@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
|
||||
@@ -1186,6 +1193,30 @@
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
||||
|
||||
"@sap-ai-sdk/ai-api": ["@sap-ai-sdk/ai-api@2.11.0", "", { "dependencies": { "@sap-ai-sdk/core": "^2.11.0", "@sap-cloud-sdk/connectivity": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0" } }, "sha512-KmBSIJfwSv7MlVFbNbZx9RQXT9P2hYvBQKPmAwURXc6Vh+UfNi1F2b45Nt8Yi90z+HFw0lsazgVN5wgav+qFGQ=="],
|
||||
|
||||
"@sap-ai-sdk/core": ["@sap-ai-sdk/core@2.11.0", "", { "dependencies": { "@sap-cloud-sdk/connectivity": "^4.7.0", "@sap-cloud-sdk/http-client": "^4.7.0", "@sap-cloud-sdk/openapi": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0" } }, "sha512-6xJ0X88vi/eDG159rDs4S/g8Y6Gq9/B4O21oimIPccSJQF7WIB2+2Z4lFKTSBem/5E3FfxqknIZ/5bPX+/6lHA=="],
|
||||
|
||||
"@sap-ai-sdk/foundation-models": ["@sap-ai-sdk/foundation-models@2.11.0", "", { "dependencies": { "@sap-ai-sdk/ai-api": "^2.11.0", "@sap-ai-sdk/core": "^2.11.0", "@sap-cloud-sdk/connectivity": "^4.7.0", "@sap-cloud-sdk/http-client": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0" } }, "sha512-AYRzR2+RA+9yCGzLymdUjcNPVDosXxHQrbFYNEcGicpYZu/Gy0WOc1GU/FCywfdqa0mGphSRpGCT+eduXLA1pw=="],
|
||||
|
||||
"@sap-ai-sdk/orchestration": ["@sap-ai-sdk/orchestration@2.11.0", "", { "dependencies": { "@sap-ai-sdk/ai-api": "^2.11.0", "@sap-ai-sdk/core": "^2.11.0", "@sap-ai-sdk/prompt-registry": "^2.11.0", "@sap-cloud-sdk/util": "^4.6.0", "yaml": "^2.9.0" } }, "sha512-UR/erV97rtuEUXPGgMeDPmr3Yn2DLF5duQcvd4BleZ4bOSorarIj6igEd8XnBnGpSvcMCIgs5B6J2Vvi7E3+Ag=="],
|
||||
|
||||
"@sap-ai-sdk/prompt-registry": ["@sap-ai-sdk/prompt-registry@2.11.0", "", { "dependencies": { "@sap-ai-sdk/core": "^2.11.0", "zod": "^4.4.3" } }, "sha512-1WrqGjwHltF/aOXoNDPYtvvaprQarPsKZUC0wSMeC6XZokoYvjvHNrltLm1IFygpjTr8yma45JJkKcwV1qzvDg=="],
|
||||
|
||||
"@sap-cloud-sdk/connectivity": ["@sap-cloud-sdk/connectivity@4.7.0", "", { "dependencies": { "@sap-cloud-sdk/resilience": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0", "@sap/xsenv": "^6.2.0", "@sap/xssec": "^4.13.0", "async-retry": "^1.3.3", "axios": "^1.15.0", "jks-js": "^1.1.6", "jsonwebtoken": "^9.0.3", "safe-stable-stringify": "^2.5.0" } }, "sha512-+EgdTpGi3ZomPuv/ab+bWQIxUfJvownW2MzdYSvX7hkEkmKJfod0O6ja2OqC+OJBLm1TE0JpbJ6AcCkqeZYuOg=="],
|
||||
|
||||
"@sap-cloud-sdk/http-client": ["@sap-cloud-sdk/http-client@4.7.0", "", { "dependencies": { "@sap-cloud-sdk/connectivity": "^4.7.0", "@sap-cloud-sdk/resilience": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0", "axios": "^1.15.0" } }, "sha512-7+S6ru7SrnyKA2MGimX09oix0EVwmPGcCAz0TRwFZVnglU+VTRmZ8QdcwcVTR26E9YhkR4OVl6EK7jb2Z0OxfQ=="],
|
||||
|
||||
"@sap-cloud-sdk/openapi": ["@sap-cloud-sdk/openapi@4.7.0", "", { "dependencies": { "@sap-cloud-sdk/connectivity": "^4.7.0", "@sap-cloud-sdk/http-client": "^4.7.0", "@sap-cloud-sdk/resilience": "^4.7.0", "@sap-cloud-sdk/util": "^4.7.0", "axios": "^1.15.0" } }, "sha512-OKTEGVScCRsfgL9Lk/bEKcGnyfq0GgruXuZfsxoMbTqbe2f9X/fgHgXIWQEkTuXQplkrSDiNFRyvl0n/ON9Ycg=="],
|
||||
|
||||
"@sap-cloud-sdk/resilience": ["@sap-cloud-sdk/resilience@4.7.0", "", { "dependencies": { "@sap-cloud-sdk/util": "^4.7.0", "async-retry": "^1.3.3", "axios": "^1.15.0", "opossum": "^9.0.0" } }, "sha512-L6PV49nNyZHnTNFbvaufadm+qOhaammXLXkDQmD7WIzMjhiYMqa/obK3NJoohe/kZ7q73jPB2vdLsAqopqTh0A=="],
|
||||
|
||||
"@sap-cloud-sdk/util": ["@sap-cloud-sdk/util@4.7.0", "", { "dependencies": { "axios": "^1.15.0", "logform": "^2.7.0", "voca": "^1.4.1", "winston": "^3.19.0", "winston-transport": "^4.9.0" } }, "sha512-nWJXMdM0Pcx/ipM2+5BvSciQKyCc0LAAO+acCOAQp65SA4HEQ2Odp9yxidY4ijW42TVp3fSMBvGwVjbWWx9Uew=="],
|
||||
|
||||
"@sap/xsenv": ["@sap/xsenv@6.2.1", "", { "dependencies": { "debug": "4.4.3", "node-cache": "^5.1.2", "verror": "1.10.1" } }, "sha512-R1p7VdD3N3jvdkL8av4vLqF+cTQihTz9mCqqF+oa9rVZvgLaCb4ODyZ1dln5/fBgg1OSuch0ESxu3AqZrXVknw=="],
|
||||
|
||||
"@sap/xssec": ["@sap/xssec@4.13.0", "", { "dependencies": { "debug": "^4.4.3", "jwt-decode": "^4" } }, "sha512-8e+bU+OyAIpAGXQanOopZa5YEK+yHKw84dhhihcCotF40MSNFbVHjQ4xM5hf4QndlqDGfXIuvXmoOMuDATa/gA=="],
|
||||
|
||||
"@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="],
|
||||
|
||||
"@sapphire/shapeshift": ["@sapphire/shapeshift@4.0.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg=="],
|
||||
@@ -1246,6 +1277,8 @@
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.3.4", "", { "dependencies": { "@smithy/core": "^3.24.4", "tslib": "^2.6.2" } }, "sha512-s8lfXcv+5C2GjBwGUBqFLgNmhyp9/n4TSKbOzKlIqJ/x0L/zwIxjNBC6DN4xUy59NvOrsiZI1t3tWi4ADUDyNw=="],
|
||||
|
||||
"@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@streamdown/cjk": ["@streamdown/cjk@1.0.3", "", { "dependencies": { "remark-cjk-friendly": "^2.0.1", "remark-cjk-friendly-gfm-strikethrough": "^2.0.1", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-WRg8HR/gHbBoTgsMd91OKFUClIoDcEFVofJvluvEAyjx3KpU0aGgD9tGDqHkHj14ShoMSkX0IYetWGegTcwIJw=="],
|
||||
@@ -1470,6 +1503,8 @@
|
||||
|
||||
"@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
|
||||
|
||||
"@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="],
|
||||
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||
@@ -1580,10 +1615,18 @@
|
||||
|
||||
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
|
||||
|
||||
"asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="],
|
||||
|
||||
"assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="],
|
||||
|
||||
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
|
||||
|
||||
"ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
|
||||
|
||||
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
|
||||
|
||||
"async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="],
|
||||
@@ -1686,16 +1729,22 @@
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
|
||||
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
|
||||
|
||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||
|
||||
"cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="],
|
||||
|
||||
"code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="],
|
||||
|
||||
"color": ["color@5.0.3", "", { "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" } }, "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-string": ["color-string@2.1.4", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg=="],
|
||||
|
||||
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
@@ -1716,6 +1765,8 @@
|
||||
|
||||
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="],
|
||||
|
||||
"cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
|
||||
|
||||
"cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
|
||||
@@ -1878,6 +1929,8 @@
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
"enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="],
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.22.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A=="],
|
||||
@@ -1968,6 +2021,8 @@
|
||||
|
||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||
|
||||
"extsprintf": ["extsprintf@1.4.1", "", {}, "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-equals": ["fast-equals@5.4.0", "", {}, "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw=="],
|
||||
@@ -1994,6 +2049,8 @@
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="],
|
||||
|
||||
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||
|
||||
"figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
|
||||
@@ -2012,6 +2069,8 @@
|
||||
|
||||
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
|
||||
|
||||
"fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
@@ -2224,6 +2283,8 @@
|
||||
|
||||
"jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
|
||||
|
||||
"jks-js": ["jks-js@1.1.7", "", { "dependencies": { "node-forge": "^1.4.0", "node-int64": "^0.4.0", "node-rsa": "^1.1.1" } }, "sha512-BeiDRKsAi1NwEwgx2JB/9/0tar5BNGIv+foGm1G5GgiyR35s/iUnfd/BWqYd16mLDD8qTaAVBrIcOOuVqXJZNQ=="],
|
||||
|
||||
"jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
|
||||
|
||||
"jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
|
||||
@@ -2258,10 +2319,14 @@
|
||||
|
||||
"jsonrepair": ["jsonrepair@3.14.0", "", { "bin": { "jsonrepair": "bin/cli.js" } }, "sha512-tWPGKMZf/8UPim+fcW2EfcQ/d/7aKUrP6IECz9G3Tu6Q5dX0orSleqJ9z6sSw7qrQkjF8/Edo4DvsWBZ8H+HNg=="],
|
||||
|
||||
"jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="],
|
||||
|
||||
"jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
|
||||
|
||||
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
||||
|
||||
"jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="],
|
||||
|
||||
"katex": ["katex@0.16.47", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
@@ -2270,6 +2335,8 @@
|
||||
|
||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
||||
|
||||
"kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="],
|
||||
|
||||
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
@@ -2312,14 +2379,30 @@
|
||||
|
||||
"lodash-es": ["lodash-es@4.18.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
|
||||
|
||||
"lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="],
|
||||
|
||||
"lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="],
|
||||
|
||||
"lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="],
|
||||
|
||||
"lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="],
|
||||
|
||||
"lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
|
||||
|
||||
"lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
|
||||
|
||||
"lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="],
|
||||
|
||||
"log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
|
||||
|
||||
"log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
|
||||
|
||||
"logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="],
|
||||
|
||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||
|
||||
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
||||
@@ -2490,16 +2573,24 @@
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"node-cache": ["node-cache@5.1.2", "", { "dependencies": { "clone": "2.x" } }, "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg=="],
|
||||
|
||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||
|
||||
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||
|
||||
"node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="],
|
||||
|
||||
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
||||
|
||||
"node-machine-id": ["node-machine-id@1.1.12", "", {}, "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ=="],
|
||||
|
||||
"node-pty": ["node-pty@1.2.0-beta.11", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-THcUyu1WwdgoIyUvgXOZ70EOMXzheGa0q3tbEb5kUIfKgcpBJ+AJ9Q1kq0bKtYmQzr77usXiTORZTLmAUQlnoQ=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="],
|
||||
|
||||
"node-rsa": ["node-rsa@1.1.1", "", { "dependencies": { "asn1": "^0.2.4" } }, "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
@@ -2518,6 +2609,8 @@
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="],
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
|
||||
"oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="],
|
||||
@@ -2528,6 +2621,8 @@
|
||||
|
||||
"opentui-spinner": ["opentui-spinner@0.0.6", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-xupLOeVQEAXEvVJCvHkfX6fChDWmJIPHe5jyUrVb8+n4XVTX8mBNhitFfB9v2ZbkC1H2UwPab/ElePHoW37NcA=="],
|
||||
|
||||
"opossum": ["opossum@9.0.0", "", {}, "sha512-K76U0QkxOfUZamneQuzz+AP0fyfTJcCplZ2oZL93nxeupuJbN4s6uFNbmVCt4eWqqGqRnnowdFuBicJ1fLMVxw=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
"ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
|
||||
@@ -2686,7 +2781,7 @@
|
||||
|
||||
"react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
|
||||
|
||||
"readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
|
||||
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="],
|
||||
|
||||
@@ -2826,6 +2921,8 @@
|
||||
|
||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="],
|
||||
|
||||
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
|
||||
|
||||
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
||||
@@ -2888,6 +2985,8 @@
|
||||
|
||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||
|
||||
"text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="],
|
||||
|
||||
"thread-stream": ["thread-stream@4.2.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ=="],
|
||||
|
||||
"three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="],
|
||||
@@ -2922,6 +3021,8 @@
|
||||
|
||||
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
|
||||
|
||||
"triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="],
|
||||
|
||||
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
|
||||
|
||||
"ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],
|
||||
@@ -3006,6 +3107,8 @@
|
||||
|
||||
"vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
|
||||
|
||||
"verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="],
|
||||
|
||||
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
||||
|
||||
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
|
||||
@@ -3018,6 +3121,8 @@
|
||||
|
||||
"vitest": ["vitest@4.1.7", "", { "dependencies": { "@vitest/expect": "4.1.7", "@vitest/mocker": "4.1.7", "@vitest/pretty-format": "4.1.7", "@vitest/runner": "4.1.7", "@vitest/snapshot": "4.1.7", "@vitest/spy": "4.1.7", "@vitest/utils": "4.1.7", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.7", "@vitest/browser-preview": "4.1.7", "@vitest/browser-webdriverio": "4.1.7", "@vitest/coverage-istanbul": "4.1.7", "@vitest/coverage-v8": "4.1.7", "@vitest/ui": "4.1.7", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA=="],
|
||||
|
||||
"voca": ["voca@1.4.1", "", {}, "sha512-NJC/BzESaHT1p4B5k4JykxedeltmNbau4cummStd4RjFojgq/kLew5TzYge9N2geeWyI2w8T30wUET5v+F7ZHA=="],
|
||||
|
||||
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
||||
|
||||
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
|
||||
@@ -3030,6 +3135,10 @@
|
||||
|
||||
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
||||
|
||||
"winston": ["winston@3.19.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA=="],
|
||||
|
||||
"winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"workerpool": ["workerpool@9.3.4", "", {}, "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg=="],
|
||||
@@ -3256,6 +3365,8 @@
|
||||
|
||||
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||
|
||||
"async-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
||||
|
||||
"axios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||
|
||||
"cli-truncate/string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="],
|
||||
@@ -3268,6 +3379,10 @@
|
||||
|
||||
"cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
|
||||
|
||||
"color/color-convert": ["color-convert@3.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg=="],
|
||||
|
||||
"color-string/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="],
|
||||
|
||||
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
|
||||
@@ -3378,6 +3493,8 @@
|
||||
|
||||
"react-jsx-parser/@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="],
|
||||
|
||||
"readable-web-to-node-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
|
||||
|
||||
"restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
||||
|
||||
"restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
@@ -3462,6 +3579,8 @@
|
||||
|
||||
"cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"color/color-convert/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="],
|
||||
|
||||
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="],
|
||||
|
||||
@@ -110,6 +110,25 @@ describe("getProviderConfigFields", () => {
|
||||
expect(result.fields.awsProfile?.optional).toBe(true);
|
||||
});
|
||||
|
||||
it("returns SAP AI Core client credential fields instead of a generic API key", () => {
|
||||
const result = getProviderConfigFields("sapaicore");
|
||||
expect(result.providerId).toBe("sapaicore");
|
||||
expect(result.authMethod).toBe("api-key");
|
||||
expect(result.description).toMatch(/not a generic API key/i);
|
||||
expect(Object.keys(result.fields)).toEqual([
|
||||
"baseUrl",
|
||||
"sapClientId",
|
||||
"sapClientSecret",
|
||||
"sapTokenUrl",
|
||||
"sapResourceGroup",
|
||||
"sapDeploymentId",
|
||||
]);
|
||||
expect(result.fields.apiKey).toBeUndefined();
|
||||
expect(result.fields.baseUrl?.label).toBe("AI Core Base URL");
|
||||
expect(result.fields.sapResourceGroup?.optional).toBe(true);
|
||||
expect(result.fields.sapDeploymentId?.optional).toBe(true);
|
||||
});
|
||||
|
||||
it("falls back to a single api-key field for unknown providers", () => {
|
||||
const result = getProviderConfigFields("not-a-real-provider");
|
||||
expect(result.authMethod).toBe("api-key");
|
||||
|
||||
@@ -5,7 +5,12 @@ export type ProviderConfigFieldKey =
|
||||
| "apiKey"
|
||||
| "baseUrl"
|
||||
| "awsRegion"
|
||||
| "awsProfile";
|
||||
| "awsProfile"
|
||||
| "sapClientId"
|
||||
| "sapClientSecret"
|
||||
| "sapTokenUrl"
|
||||
| "sapResourceGroup"
|
||||
| "sapDeploymentId";
|
||||
|
||||
export interface ProviderConfigFieldRequirement {
|
||||
defaultValue?: string;
|
||||
@@ -30,6 +35,11 @@ const FIELD_KEYS: ProviderConfigFieldKey[] = [
|
||||
"baseUrl",
|
||||
"awsRegion",
|
||||
"awsProfile",
|
||||
"sapClientId",
|
||||
"sapClientSecret",
|
||||
"sapTokenUrl",
|
||||
"sapResourceGroup",
|
||||
"sapDeploymentId",
|
||||
];
|
||||
|
||||
interface ProviderConfigFieldMetadata {
|
||||
@@ -71,6 +81,39 @@ const PROVIDER_CONFIG_FIELD_METADATA: Partial<
|
||||
},
|
||||
},
|
||||
},
|
||||
sapaicore: {
|
||||
mode: "replace",
|
||||
description:
|
||||
"SAP AI Core uses OAuth client credentials and an AI Core API URL, not a generic API key.",
|
||||
fields: {
|
||||
baseUrl: {
|
||||
label: "AI Core Base URL",
|
||||
placeholder: "https://api.ai.<region>.aws.ml.hana.ondemand.com",
|
||||
},
|
||||
sapClientId: {
|
||||
label: "Client ID",
|
||||
placeholder: "sb-...|xsuaa_std!b...",
|
||||
},
|
||||
sapClientSecret: {
|
||||
label: "Client Secret",
|
||||
placeholder: "SAP AI Core client secret",
|
||||
},
|
||||
sapTokenUrl: {
|
||||
label: "Token URL",
|
||||
placeholder: "https://<subdomain>.authentication.sap.hana.ondemand.com",
|
||||
},
|
||||
sapResourceGroup: {
|
||||
label: "Resource Group",
|
||||
placeholder: "default",
|
||||
optional: true,
|
||||
},
|
||||
sapDeploymentId: {
|
||||
label: "Deployment ID",
|
||||
placeholder: "SAP AI Core deployment id",
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function mergeFields(
|
||||
|
||||
@@ -352,6 +352,122 @@ describe("migrateLegacyProviderSettings", () => {
|
||||
});
|
||||
expect(manager.read().providers.bedrock?.tokenSource).toBe("migration");
|
||||
});
|
||||
|
||||
it("migrates legacy SAP AI Core credentials into SAP provider settings", () => {
|
||||
const tempDir = mkdtempSync(
|
||||
path.join(os.tmpdir(), "core-legacy-provider-"),
|
||||
);
|
||||
tempDirs.push(tempDir);
|
||||
const providersPath = path.join(tempDir, "settings", "providers.json");
|
||||
const manager = new ProviderSettingsManager({ filePath: providersPath });
|
||||
|
||||
writeFileSync(
|
||||
path.join(tempDir, "globalState.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
mode: "act",
|
||||
actModeApiProvider: "sapaicore",
|
||||
actModeApiModelId: "anthropic--claude-4.6-sonnet",
|
||||
sapAiCoreBaseUrl: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
sapAiCoreTokenUrl:
|
||||
"https://example.authentication.sap.hana.ondemand.com",
|
||||
sapAiResourceGroup: "default",
|
||||
sapAiCoreUseOrchestrationMode: true,
|
||||
actModeSapAiCoreDeploymentId: "deployment-id",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeFileSync(
|
||||
path.join(tempDir, "secrets.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
sapAiCoreClientId: "sap-client",
|
||||
sapAiCoreClientSecret: "sap-secret",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
const result = migrateLegacyProviderSettings({
|
||||
providerSettingsManager: manager,
|
||||
dataDir: tempDir,
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
migrated: true,
|
||||
providerCount: 1,
|
||||
lastUsedProvider: "sapaicore",
|
||||
});
|
||||
expect(manager.getProviderSettings("sapaicore")).toEqual({
|
||||
provider: "sapaicore",
|
||||
model: "anthropic--claude-4.6-sonnet",
|
||||
baseUrl: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
sap: {
|
||||
clientId: "sap-client",
|
||||
clientSecret: "sap-secret",
|
||||
tokenUrl: "https://example.authentication.sap.hana.ondemand.com",
|
||||
resourceGroup: "default",
|
||||
deploymentId: "deployment-id",
|
||||
useOrchestrationMode: true,
|
||||
},
|
||||
});
|
||||
expect(manager.read().providers.sapaicore?.tokenSource).toBe("migration");
|
||||
});
|
||||
|
||||
it("detects SAP AI Core legacy files even when provider mode is absent", () => {
|
||||
const tempDir = mkdtempSync(
|
||||
path.join(os.tmpdir(), "core-legacy-provider-"),
|
||||
);
|
||||
tempDirs.push(tempDir);
|
||||
const providersPath = path.join(tempDir, "settings", "providers.json");
|
||||
const manager = new ProviderSettingsManager({ filePath: providersPath });
|
||||
|
||||
writeFileSync(
|
||||
path.join(tempDir, "globalState.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
sapAiCoreBaseUrl: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
sapAiCoreTokenUrl:
|
||||
"https://example.authentication.sap.hana.ondemand.com",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeFileSync(
|
||||
path.join(tempDir, "secrets.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
sapAiCoreClientId: "sap-client",
|
||||
sapAiCoreClientSecret: "sap-secret",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
const result = migrateLegacyProviderSettings({
|
||||
providerSettingsManager: manager,
|
||||
dataDir: tempDir,
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
migrated: true,
|
||||
lastUsedProvider: "sapaicore",
|
||||
});
|
||||
expect(manager.getProviderSettings("sapaicore")).toMatchObject({
|
||||
provider: "sapaicore",
|
||||
baseUrl: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
sap: {
|
||||
clientId: "sap-client",
|
||||
clientSecret: "sap-secret",
|
||||
tokenUrl: "https://example.authentication.sap.hana.ondemand.com",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
|
||||
@@ -460,7 +460,6 @@ function buildLegacyProviderSettings(
|
||||
aihubmix: legacySecrets.aihubmixApiKey,
|
||||
nousResearch: legacySecrets.nousResearchApiKey,
|
||||
oca: legacySecrets.ocaApiKey,
|
||||
sapaicore: legacySecrets.sapAiCoreClientId,
|
||||
};
|
||||
|
||||
const providerSpecific: Partial<ProviderSettings> = {};
|
||||
@@ -674,6 +673,16 @@ function collectCandidateProviderIds(
|
||||
}
|
||||
if (trimNonEmpty(legacySecrets.clineApiKey)) candidates.add("cline");
|
||||
if (trimNonEmpty(legacySecrets.ocaApiKey)) candidates.add("oca");
|
||||
if (
|
||||
trimNonEmpty(legacySecrets.sapAiCoreClientId) ||
|
||||
trimNonEmpty(legacySecrets.sapAiCoreClientSecret) ||
|
||||
trimNonEmpty(legacyGlobalState.sapAiCoreTokenUrl) ||
|
||||
trimNonEmpty(legacyGlobalState.sapAiCoreBaseUrl) ||
|
||||
trimNonEmpty(legacyGlobalState.sapAiResourceGroup) ||
|
||||
legacyGlobalState.sapAiCoreUseOrchestrationMode !== undefined
|
||||
) {
|
||||
candidates.add("sapaicore");
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,9 @@
|
||||
|
||||
## Next Release
|
||||
|
||||
- SAP AI Core uses AI SDK community provider @jerome-benoit/sap-ai-provider https://ai-sdk.dev/providers/community-providers/sap-ai
|
||||
|
||||
## 0.0.42
|
||||
|
||||
- Supports Bedrock bearer API keys, direct IAM credentials, AWS profiles, and the default AWS SDK credential chain
|
||||
- Routes Z.AI GLM thinking through provider metadata while preserving generic thinking suppression for non-GLM Z.AI custom models
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
"@ai-sdk/provider": "^3.0.8",
|
||||
"@aws-sdk/credential-providers": "^3.922.0",
|
||||
"@cline/shared": "workspace:*",
|
||||
"@jerome-benoit/sap-ai-provider": "^4.6.0",
|
||||
"@langfuse/otel": "^4.0.0",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/sdk-trace-node": "^2.6.1",
|
||||
|
||||
@@ -857,6 +857,12 @@ async function createProviderModule(
|
||||
const { createDifyProviderModule } = await import("./vendors/community");
|
||||
return createDifyProviderModule(config);
|
||||
}
|
||||
case "sapaicore": {
|
||||
const { createSapAiCoreProviderModule } = await import(
|
||||
"./vendors/community"
|
||||
);
|
||||
return createSapAiCoreProviderModule(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,3 +1000,4 @@ export const createClaudeCodeProvider = createAiSdkProvider("claude-code");
|
||||
export const createOpenAICodexProvider = createAiSdkProvider("openai-codex");
|
||||
export const createOpenCodeProvider = createAiSdkProvider("opencode");
|
||||
export const createDifyProvider = createAiSdkProvider("dify");
|
||||
export const createSapAiCoreProvider = createAiSdkProvider("sapaicore");
|
||||
|
||||
@@ -63,6 +63,10 @@ async function loadFamilyFactory(
|
||||
const module = await import("./ai-sdk");
|
||||
return module.createDifyProvider;
|
||||
}
|
||||
case "sap-ai-core": {
|
||||
const module = await import("./ai-sdk");
|
||||
return module.createSapAiCoreProvider;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ export type ProviderFamily =
|
||||
| "claude-code"
|
||||
| "openai-codex"
|
||||
| "opencode"
|
||||
| "dify";
|
||||
| "dify"
|
||||
| "sap-ai-core";
|
||||
|
||||
export interface BuiltinSpec {
|
||||
id: string;
|
||||
@@ -245,6 +246,7 @@ function inferClient(spec: BuiltinSpec): ProviderClient {
|
||||
case "openai-codex":
|
||||
case "opencode":
|
||||
case "dify":
|
||||
case "sap-ai-core":
|
||||
return "ai-sdk-community";
|
||||
default:
|
||||
return "openai-compatible";
|
||||
@@ -638,18 +640,6 @@ const OPENAI_COMPATIBLE_SPECS: BuiltinSpec[] = [
|
||||
modelsFactory: () => ({}),
|
||||
defaults: { baseUrl: "https://api.asksage.ai/server" },
|
||||
},
|
||||
{
|
||||
id: "sapaicore",
|
||||
name: "SAP AI Core",
|
||||
description: "SAP AI Core inference and orchestration platform",
|
||||
family: "openai-compatible",
|
||||
client: "ai-sdk-community",
|
||||
capabilities: ["tools", "reasoning", "prompt-cache"],
|
||||
defaultModelId: "anthropic--claude-3.5-sonnet",
|
||||
apiKeyEnv: ["AICORE_SERVICE_KEY", "VCAP_SERVICES"],
|
||||
modelsProviderId: "sapaicore",
|
||||
metadata: ANTHROPIC_ROUTING_METADATA,
|
||||
},
|
||||
];
|
||||
|
||||
export const BUILTIN_SPECS: BuiltinSpec[] = [
|
||||
@@ -801,6 +791,18 @@ export const BUILTIN_SPECS: BuiltinSpec[] = [
|
||||
apiKeyEnv: ["DIFY_API_KEY"],
|
||||
modelsFactory: () => ({}),
|
||||
},
|
||||
{
|
||||
id: "sapaicore",
|
||||
name: "SAP AI Core",
|
||||
description: "SAP AI Core inference and orchestration platform",
|
||||
family: "sap-ai-core",
|
||||
client: "ai-sdk-community",
|
||||
capabilities: ["tools", "reasoning", "prompt-cache"],
|
||||
defaultModelId: "anthropic--claude-3.5-sonnet",
|
||||
apiKeyEnv: ["AICORE_SERVICE_KEY", "VCAP_SERVICES"],
|
||||
modelsProviderId: "sapaicore",
|
||||
metadata: ANTHROPIC_ROUTING_METADATA,
|
||||
},
|
||||
...OPENAI_COMPATIBLE_SPECS,
|
||||
];
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
createOpenAICompatibleProvider,
|
||||
createOpenAIProvider,
|
||||
createOpenCodeProvider,
|
||||
createSapAiCoreProvider,
|
||||
createVertexProvider,
|
||||
} from "./ai-sdk";
|
||||
import { BUILTIN_PROVIDER_REGISTRATIONS } from "./builtins-runtime";
|
||||
@@ -160,6 +161,8 @@ function resolveFactory(
|
||||
return createOpenCodeProvider;
|
||||
case "dify":
|
||||
return createDifyProvider;
|
||||
case "sapaicore":
|
||||
return createSapAiCoreProvider;
|
||||
default:
|
||||
return createOpenAICompatibleProvider;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createOpenAICompatibleProvider, createOpenAIProvider } from "./ai-sdk";
|
||||
import {
|
||||
createOpenAICompatibleProvider,
|
||||
createOpenAIProvider,
|
||||
createSapAiCoreProvider,
|
||||
} from "./ai-sdk";
|
||||
import { BUILTIN_PROVIDER_REGISTRATIONS } from "./builtins-runtime";
|
||||
import { createGateway } from "./gateway";
|
||||
import { BUILT_IN_PROVIDER_IDS, normalizeProviderId } from "./ids";
|
||||
@@ -120,4 +124,20 @@ describe("provider-ids", () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("routes SAP AI Core through the SAP AI SDK provider factory", async () => {
|
||||
await expect(getProvider("sapaicore")).resolves.toMatchObject({
|
||||
id: "sapaicore",
|
||||
name: "SAP AI Core",
|
||||
client: "ai-sdk-community",
|
||||
defaultModelId: "anthropic--claude-3.5-sonnet",
|
||||
});
|
||||
|
||||
const registration = BUILTIN_PROVIDER_REGISTRATIONS.find(
|
||||
(item) => item.manifest.id === "sapaicore",
|
||||
);
|
||||
await expect(registration?.loadProvider?.()).resolves.toMatchObject({
|
||||
createProvider: createSapAiCoreProvider,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,8 @@ export type AiSdkProviderOptionsTarget =
|
||||
| "claude-code"
|
||||
| "openai-codex"
|
||||
| "opencode"
|
||||
| "dify";
|
||||
| "dify"
|
||||
| "sapaicore";
|
||||
|
||||
export type ProviderOptionSuppression = {
|
||||
genericThinking?: boolean;
|
||||
@@ -83,6 +84,8 @@ export function inferProviderOptionsTarget(
|
||||
return "opencode";
|
||||
case "dify":
|
||||
return "dify";
|
||||
case "sapaicore":
|
||||
return "sapaicore";
|
||||
default:
|
||||
return "openai-compatible";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { createSapAiCoreProviderModule } from "./community";
|
||||
|
||||
const originalServiceKey = process.env.AICORE_SERVICE_KEY;
|
||||
|
||||
describe("createSapAiCoreProviderModule", () => {
|
||||
afterEach(() => {
|
||||
if (originalServiceKey === undefined) {
|
||||
delete process.env.AICORE_SERVICE_KEY;
|
||||
} else {
|
||||
process.env.AICORE_SERVICE_KEY = originalServiceKey;
|
||||
}
|
||||
});
|
||||
|
||||
it("passes SAP credentials as a provider destination without mutating process env", async () => {
|
||||
process.env.AICORE_SERVICE_KEY = "existing-service-key";
|
||||
|
||||
const provider = await createSapAiCoreProviderModule({
|
||||
providerId: "sapaicore",
|
||||
baseUrl: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
options: {
|
||||
clientId: "sap-client",
|
||||
clientSecret: "sap-secret",
|
||||
tokenUrl: "https://auth.example",
|
||||
deploymentId: "deployment-id",
|
||||
},
|
||||
});
|
||||
|
||||
const model = provider.model("anthropic--claude-4.6-sonnet") as {
|
||||
config?: { destination?: Record<string, unknown> };
|
||||
};
|
||||
|
||||
expect(process.env.AICORE_SERVICE_KEY).toBe("existing-service-key");
|
||||
expect(model.config?.destination).toMatchObject({
|
||||
authentication: "OAuth2ClientCredentials",
|
||||
clientId: "sap-client",
|
||||
clientSecret: "sap-secret",
|
||||
tokenServiceUrl: "https://auth.example/oauth/token",
|
||||
url: "https://api.ai.example.aws.ml.hana.ondemand.com",
|
||||
});
|
||||
});
|
||||
|
||||
it("fails fast for partial explicit SAP configuration", async () => {
|
||||
await expect(
|
||||
createSapAiCoreProviderModule({
|
||||
providerId: "sapaicore",
|
||||
options: {
|
||||
clientId: "sap-client",
|
||||
clientSecret: "sap-secret",
|
||||
tokenUrl: "https://auth.example",
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(/baseUrl/);
|
||||
});
|
||||
});
|
||||
@@ -1,10 +1,15 @@
|
||||
import type { GatewayResolvedProviderConfig } from "@cline/shared";
|
||||
import type { SAPAIProviderSettings } from "@jerome-benoit/sap-ai-provider";
|
||||
import { createClaudeCode } from "ai-sdk-provider-claude-code";
|
||||
import { createCodexExec } from "ai-sdk-provider-codex-cli";
|
||||
import { createDifyProvider } from "dify-ai-provider";
|
||||
import { resolveApiKey } from "../http";
|
||||
import type { ProviderFactoryResult } from "./types";
|
||||
|
||||
type SapAiProviderModule = typeof import("@jerome-benoit/sap-ai-provider");
|
||||
type SapDestination = NonNullable<SAPAIProviderSettings["destination"]>;
|
||||
const SAP_AI_PROVIDER_PACKAGE = "@jerome-benoit/sap-ai-provider";
|
||||
|
||||
function readOptions(
|
||||
config: GatewayResolvedProviderConfig,
|
||||
): Record<string, unknown> {
|
||||
@@ -95,3 +100,108 @@ export async function createDifyProviderModule(
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function readStringOption(
|
||||
options: Record<string, unknown>,
|
||||
key: string,
|
||||
): string | undefined {
|
||||
const value = options[key];
|
||||
return typeof value === "string" && value.trim().length > 0
|
||||
? value.trim()
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeSapTokenServiceUrl(tokenUrl: string): string {
|
||||
const trimmed = tokenUrl.replace(/\/+$/, "");
|
||||
return /\/oauth\/token$/i.test(trimmed) ? trimmed : `${trimmed}/oauth/token`;
|
||||
}
|
||||
|
||||
function hasExplicitSapConnectionConfig(
|
||||
config: GatewayResolvedProviderConfig,
|
||||
options: Record<string, unknown>,
|
||||
): boolean {
|
||||
return Boolean(
|
||||
config.apiKey?.trim() ||
|
||||
config.baseUrl?.trim() ||
|
||||
readStringOption(options, "clientId") ||
|
||||
readStringOption(options, "clientSecret") ||
|
||||
readStringOption(options, "tokenUrl"),
|
||||
);
|
||||
}
|
||||
|
||||
function buildSapDestination(
|
||||
config: GatewayResolvedProviderConfig,
|
||||
options: Record<string, unknown>,
|
||||
): SapDestination | undefined {
|
||||
const clientId = readStringOption(options, "clientId");
|
||||
const clientSecret =
|
||||
readStringOption(options, "clientSecret") ?? config.apiKey?.trim();
|
||||
const tokenUrl = readStringOption(options, "tokenUrl");
|
||||
const baseUrl = config.baseUrl?.trim();
|
||||
if (!clientId || !clientSecret || !tokenUrl || !baseUrl) {
|
||||
if (!hasExplicitSapConnectionConfig(config, options)) {
|
||||
return undefined;
|
||||
}
|
||||
const missing = [
|
||||
!clientId ? "sap.clientId" : undefined,
|
||||
!clientSecret ? "sap.clientSecret" : undefined,
|
||||
!tokenUrl ? "sap.tokenUrl" : undefined,
|
||||
!baseUrl ? "baseUrl" : undefined,
|
||||
].filter(Boolean);
|
||||
throw new Error(
|
||||
`SAP AI Core provider is missing required configuration: ${missing.join(
|
||||
", ",
|
||||
)}.`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
authentication: "OAuth2ClientCredentials" as const,
|
||||
clientId,
|
||||
clientSecret,
|
||||
name: config.providerId,
|
||||
tokenServiceUrl: normalizeSapTokenServiceUrl(tokenUrl),
|
||||
url: baseUrl.replace(/\/+$/, ""),
|
||||
} satisfies SapDestination;
|
||||
}
|
||||
|
||||
function resolveSapApi(options: Record<string, unknown>) {
|
||||
const api = options.api;
|
||||
if (api === "orchestration" || api === "foundation-models") {
|
||||
return api;
|
||||
}
|
||||
if (options.useOrchestrationMode === false) {
|
||||
return "foundation-models";
|
||||
}
|
||||
return "orchestration";
|
||||
}
|
||||
|
||||
async function importSapAiProvider(): Promise<SapAiProviderModule> {
|
||||
const specifier: string = SAP_AI_PROVIDER_PACKAGE;
|
||||
return import(specifier) as Promise<SapAiProviderModule>;
|
||||
}
|
||||
|
||||
export async function createSapAiCoreProviderModule(
|
||||
config: GatewayResolvedProviderConfig,
|
||||
): Promise<ProviderFactoryResult> {
|
||||
const options = readOptions(config);
|
||||
const destination = buildSapDestination(config, options);
|
||||
|
||||
const { createSAPAIProvider } = await importSapAiProvider();
|
||||
const deploymentId = readStringOption(options, "deploymentId");
|
||||
const provider = createSAPAIProvider({
|
||||
name: config.providerId,
|
||||
...(deploymentId
|
||||
? { deploymentId }
|
||||
: { resourceGroup: readStringOption(options, "resourceGroup") }),
|
||||
api: resolveSapApi(options),
|
||||
...(destination ? { destination } : {}),
|
||||
...(typeof options.defaultSettings === "object" &&
|
||||
options.defaultSettings !== null &&
|
||||
!Array.isArray(options.defaultSettings)
|
||||
? { defaultSettings: options.defaultSettings }
|
||||
: {}),
|
||||
});
|
||||
return {
|
||||
model: (modelId) => provider(modelId),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user