pagegraph 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -41
- package/dist/anthropic-messages-TqKpKmfW.js +1067 -0
- package/dist/anthropic-messages-TqKpKmfW.js.map +1 -0
- package/dist/audit.d.ts +2 -0
- package/dist/audit.js +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/azure-openai-responses-DJjBLwoI.js +231 -0
- package/dist/azure-openai-responses-DJjBLwoI.js.map +1 -0
- package/dist/cli.js +10487 -38044
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js +41 -0
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js.map +1 -0
- package/dist/config.d.ts +6 -6
- package/dist/config.js.map +1 -1
- package/dist/diagnostics-Wt5faNDM.js +108 -0
- package/dist/diagnostics-Wt5faNDM.js.map +1 -0
- package/dist/dist-cFoAzruL.js +4794 -0
- package/dist/dist-cFoAzruL.js.map +1 -0
- package/dist/env-api-keys-C-OA0yM-.js +124 -0
- package/dist/env-api-keys-C-OA0yM-.js.map +1 -0
- package/dist/error-body-CyiejW4b.js +103 -0
- package/dist/error-body-CyiejW4b.js.map +1 -0
- package/dist/github-copilot-headers-CEpMOpQF.js +24 -0
- package/dist/github-copilot-headers-CEpMOpQF.js.map +1 -0
- package/dist/google-generative-ai-BxABKIKO.js +330 -0
- package/dist/google-generative-ai-BxABKIKO.js.map +1 -0
- package/dist/google-shared-0gpM2jFi.js +19471 -0
- package/dist/google-shared-0gpM2jFi.js.map +1 -0
- package/dist/google-vertex-D8Eb5cbu.js +376 -0
- package/dist/google-vertex-D8Eb5cbu.js.map +1 -0
- package/dist/hash-Dp7EzZUo.js +18 -0
- package/dist/hash-Dp7EzZUo.js.map +1 -0
- package/dist/headers-BRNMVpzu.js +19 -0
- package/dist/headers-BRNMVpzu.js.map +1 -0
- package/dist/json-parse-C10znB7l.js +383 -0
- package/dist/json-parse-C10znB7l.js.map +1 -0
- package/dist/mistral-conversations-CvaqBWjR.js +690 -0
- package/dist/mistral-conversations-CvaqBWjR.js.map +1 -0
- package/dist/models-DcT5qOEL.js +1203 -0
- package/dist/models-DcT5qOEL.js.map +1 -0
- package/dist/node-Ccvru9GE.js +26 -0
- package/dist/node-Ccvru9GE.js.map +1 -0
- package/dist/node-MEosBOF2.js +2403 -0
- package/dist/node-MEosBOF2.js.map +1 -0
- package/dist/openai-BCBEd2eO.js +17350 -0
- package/dist/openai-BCBEd2eO.js.map +1 -0
- package/dist/openai-codex-responses-vJqxeeRC.js +1268 -0
- package/dist/openai-codex-responses-vJqxeeRC.js.map +1 -0
- package/dist/openai-completions-Cb_fRAbI.js +989 -0
- package/dist/openai-completions-Cb_fRAbI.js.map +1 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js +10 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js.map +1 -0
- package/dist/openai-responses-sDuh82G5.js +268 -0
- package/dist/openai-responses-sDuh82G5.js.map +1 -0
- package/dist/openai-responses-shared-mhuo1Jov.js +599 -0
- package/dist/openai-responses-shared-mhuo1Jov.js.map +1 -0
- package/dist/openrouter-images-CRmBkzpX.js +127 -0
- package/dist/openrouter-images-CRmBkzpX.js.map +1 -0
- package/dist/pi-D3mMmYey.js +56805 -0
- package/dist/pi-D3mMmYey.js.map +1 -0
- package/dist/pi-messages-CejiVYvO.js +308 -0
- package/dist/pi-messages-CejiVYvO.js.map +1 -0
- package/dist/provider-env-t38GK5FF.js +39 -0
- package/dist/provider-env-t38GK5FF.js.map +1 -0
- package/dist/provider-retry-DzKoh1X7.js +80 -0
- package/dist/provider-retry-DzKoh1X7.js.map +1 -0
- package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
- package/dist/sanitize-unicode-Ds14l9Om.js +28 -0
- package/dist/sanitize-unicode-Ds14l9Om.js.map +1 -0
- package/dist/sdk-C9_wiO6w.js +12503 -0
- package/dist/sdk-C9_wiO6w.js.map +1 -0
- package/dist/state-BuJP_3Lr.js +28102 -0
- package/dist/state-BuJP_3Lr.js.map +1 -0
- package/dist/system-one-shared-Dl10ZF7Z.js +167 -0
- package/dist/system-one-shared-Dl10ZF7Z.js.map +1 -0
- package/dist/transform-messages-BLJ8EfK6.js +468 -0
- package/dist/transform-messages-BLJ8EfK6.js.map +1 -0
- package/dist/typesafe-system-one-CwEWMV8P.js +25 -0
- package/dist/typesafe-system-one-CwEWMV8P.js.map +1 -0
- package/package.json +4 -8
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { t as getProviderEnvValue } from "./provider-env-t38GK5FF.js";
|
|
2
|
+
//#region node_modules/@earendil-works/pi-ai/dist/env-api-keys.js
|
|
3
|
+
var __rewriteRelativeImportExtension = function(path, preserveJsx) {
|
|
4
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
5
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
6
|
+
});
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
let _existsSync = null;
|
|
10
|
+
let _homedir = null;
|
|
11
|
+
let _join = null;
|
|
12
|
+
const dynamicImport = (specifier) => import(__rewriteRelativeImportExtension(specifier));
|
|
13
|
+
const NODE_FS_SPECIFIER = "node:fs";
|
|
14
|
+
const NODE_OS_SPECIFIER = "node:os";
|
|
15
|
+
const NODE_PATH_SPECIFIER = "node:path";
|
|
16
|
+
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
|
17
|
+
dynamicImport(NODE_FS_SPECIFIER).then((m) => {
|
|
18
|
+
_existsSync = m.existsSync;
|
|
19
|
+
});
|
|
20
|
+
dynamicImport(NODE_OS_SPECIFIER).then((m) => {
|
|
21
|
+
_homedir = m.homedir;
|
|
22
|
+
});
|
|
23
|
+
dynamicImport(NODE_PATH_SPECIFIER).then((m) => {
|
|
24
|
+
_join = m.join;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const ANTHROPIC_AUTH_TOKEN_ENV = "ANTHROPIC_AUTH_TOKEN";
|
|
28
|
+
const ANTHROPIC_OAUTH_TOKEN_ENV = "ANTHROPIC_OAUTH_TOKEN";
|
|
29
|
+
const ANTHROPIC_API_KEY_ENV = "ANTHROPIC_API_KEY";
|
|
30
|
+
const ANTHROPIC_FEDERATION_RULE_ID_ENV = "ANTHROPIC_FEDERATION_RULE_ID";
|
|
31
|
+
const ANTHROPIC_ORGANIZATION_ID_ENV = "ANTHROPIC_ORGANIZATION_ID";
|
|
32
|
+
const ANTHROPIC_SERVICE_ACCOUNT_ID_ENV = "ANTHROPIC_SERVICE_ACCOUNT_ID";
|
|
33
|
+
const ANTHROPIC_IDENTITY_TOKEN_FILE_ENV = "ANTHROPIC_IDENTITY_TOKEN_FILE";
|
|
34
|
+
const ANTHROPIC_WORKSPACE_ID_ENV = "ANTHROPIC_WORKSPACE_ID";
|
|
35
|
+
let cachedVertexAdcCredentialsExists = null;
|
|
36
|
+
function hasVertexAdcCredentials(env) {
|
|
37
|
+
const explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;
|
|
38
|
+
if (explicitCredentialsPath) return _existsSync ? _existsSync(explicitCredentialsPath) : false;
|
|
39
|
+
if (cachedVertexAdcCredentialsExists === null) {
|
|
40
|
+
if (!_existsSync || !_homedir || !_join) {
|
|
41
|
+
if (!(typeof process !== "undefined" && (process.versions?.node || process.versions?.bun))) cachedVertexAdcCredentialsExists = false;
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const gacPath = getProviderEnvValue("GOOGLE_APPLICATION_CREDENTIALS", env);
|
|
45
|
+
if (gacPath) cachedVertexAdcCredentialsExists = _existsSync(gacPath);
|
|
46
|
+
else cachedVertexAdcCredentialsExists = _existsSync(_join(_homedir(), ".config", "gcloud", "application_default_credentials.json"));
|
|
47
|
+
}
|
|
48
|
+
return cachedVertexAdcCredentialsExists;
|
|
49
|
+
}
|
|
50
|
+
function getApiKeyEnvVars(provider) {
|
|
51
|
+
if (provider === "github-copilot") return ["COPILOT_GITHUB_TOKEN"];
|
|
52
|
+
if (provider === "anthropic") return [
|
|
53
|
+
ANTHROPIC_AUTH_TOKEN_ENV,
|
|
54
|
+
ANTHROPIC_OAUTH_TOKEN_ENV,
|
|
55
|
+
ANTHROPIC_API_KEY_ENV
|
|
56
|
+
];
|
|
57
|
+
const envVar = {
|
|
58
|
+
"ant-ling": "ANT_LING_API_KEY",
|
|
59
|
+
"qwen-token-plan": "QWEN_TOKEN_PLAN_API_KEY",
|
|
60
|
+
"qwen-token-plan-cn": "QWEN_TOKEN_PLAN_CN_API_KEY",
|
|
61
|
+
"qwen-token-plan-individual": "QWEN_TOKEN_PLAN_API_KEY",
|
|
62
|
+
openai: "OPENAI_API_KEY",
|
|
63
|
+
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
|
64
|
+
nvidia: "NVIDIA_API_KEY",
|
|
65
|
+
deepseek: "DEEPSEEK_API_KEY",
|
|
66
|
+
google: "GEMINI_API_KEY",
|
|
67
|
+
"google-vertex": "GOOGLE_CLOUD_API_KEY",
|
|
68
|
+
groq: "GROQ_API_KEY",
|
|
69
|
+
cerebras: "CEREBRAS_API_KEY",
|
|
70
|
+
xai: "XAI_API_KEY",
|
|
71
|
+
typesafe: "TYPESAFE_API_KEY",
|
|
72
|
+
radius: "RADIUS_API_KEY",
|
|
73
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
74
|
+
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
|
|
75
|
+
zai: "ZAI_API_KEY",
|
|
76
|
+
"zai-coding-cn": "ZAI_CODING_CN_API_KEY",
|
|
77
|
+
mistral: "MISTRAL_API_KEY",
|
|
78
|
+
minimax: "MINIMAX_API_KEY",
|
|
79
|
+
"minimax-cn": "MINIMAX_CN_API_KEY",
|
|
80
|
+
moonshotai: "MOONSHOT_API_KEY",
|
|
81
|
+
"moonshotai-cn": "MOONSHOT_API_KEY",
|
|
82
|
+
huggingface: "HF_TOKEN",
|
|
83
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
84
|
+
together: "TOGETHER_API_KEY",
|
|
85
|
+
baseten: "BASETEN_API_KEY",
|
|
86
|
+
opencode: "OPENCODE_API_KEY",
|
|
87
|
+
"opencode-go": "OPENCODE_API_KEY",
|
|
88
|
+
"kimi-coding": "KIMI_API_KEY",
|
|
89
|
+
meta: "META_API_KEY",
|
|
90
|
+
"cloudflare-workers-ai": "CLOUDFLARE_API_KEY",
|
|
91
|
+
"cloudflare-ai-gateway": "CLOUDFLARE_API_KEY",
|
|
92
|
+
xiaomi: "XIAOMI_API_KEY",
|
|
93
|
+
"xiaomi-token-plan-cn": "XIAOMI_TOKEN_PLAN_CN_API_KEY",
|
|
94
|
+
"xiaomi-token-plan-ams": "XIAOMI_TOKEN_PLAN_AMS_API_KEY",
|
|
95
|
+
"xiaomi-token-plan-sgp": "XIAOMI_TOKEN_PLAN_SGP_API_KEY"
|
|
96
|
+
}[provider];
|
|
97
|
+
return envVar ? [envVar] : void 0;
|
|
98
|
+
}
|
|
99
|
+
function findEnvKeys(provider, env) {
|
|
100
|
+
const envVars = getApiKeyEnvVars(provider);
|
|
101
|
+
if (!envVars) return void 0;
|
|
102
|
+
const found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));
|
|
103
|
+
return found.length > 0 ? found : void 0;
|
|
104
|
+
}
|
|
105
|
+
function getEnvApiKey(provider, env) {
|
|
106
|
+
const envKeys = findEnvKeys(provider, env);
|
|
107
|
+
if (envKeys?.[0]) {
|
|
108
|
+
const apiKeyEnv = provider === "anthropic" ? envKeys.find((key) => key !== ANTHROPIC_AUTH_TOKEN_ENV) : envKeys[0];
|
|
109
|
+
if (apiKeyEnv) return getProviderEnvValue(apiKeyEnv, env);
|
|
110
|
+
}
|
|
111
|
+
if (provider === "google-vertex") {
|
|
112
|
+
const hasCredentials = hasVertexAdcCredentials(env);
|
|
113
|
+
const hasProject = !!(getProviderEnvValue("GOOGLE_CLOUD_PROJECT", env) || getProviderEnvValue("GCLOUD_PROJECT", env));
|
|
114
|
+
const hasLocation = !!getProviderEnvValue("GOOGLE_CLOUD_LOCATION", env);
|
|
115
|
+
if (hasCredentials && hasProject && hasLocation) return "<authenticated>";
|
|
116
|
+
}
|
|
117
|
+
if (provider === "amazon-bedrock") {
|
|
118
|
+
if (getProviderEnvValue("AWS_PROFILE", env) || getProviderEnvValue("AWS_ACCESS_KEY_ID", env) && getProviderEnvValue("AWS_SECRET_ACCESS_KEY", env) || getProviderEnvValue("AWS_BEARER_TOKEN_BEDROCK", env) || getProviderEnvValue("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", env) || getProviderEnvValue("AWS_CONTAINER_CREDENTIALS_FULL_URI", env) || getProviderEnvValue("AWS_WEB_IDENTITY_TOKEN_FILE", env)) return "<authenticated>";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { ANTHROPIC_OAUTH_TOKEN_ENV as a, ANTHROPIC_WORKSPACE_ID_ENV as c, ANTHROPIC_IDENTITY_TOKEN_FILE_ENV as i, findEnvKeys as l, ANTHROPIC_AUTH_TOKEN_ENV as n, ANTHROPIC_ORGANIZATION_ID_ENV as o, ANTHROPIC_FEDERATION_RULE_ID_ENV as r, ANTHROPIC_SERVICE_ACCOUNT_ID_ENV as s, ANTHROPIC_API_KEY_ENV as t, getEnvApiKey as u };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=env-api-keys-C-OA0yM-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-api-keys-C-OA0yM-.js","names":[],"sources":["../node_modules/@earendil-works/pi-ai/dist/env-api-keys.js"],"sourcesContent":["var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n};\n// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _existsSync = null;\nlet _homedir = null;\nlet _join = null;\nconst dynamicImport = (specifier) => import(__rewriteRelativeImportExtension(specifier));\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n dynamicImport(NODE_FS_SPECIFIER).then((m) => {\n _existsSync = m.existsSync;\n });\n dynamicImport(NODE_OS_SPECIFIER).then((m) => {\n _homedir = m.homedir;\n });\n dynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n _join = m.join;\n });\n}\nimport { getProviderEnvValue } from \"./utils/provider-env.js\";\nexport const ANTHROPIC_AUTH_TOKEN_ENV = \"ANTHROPIC_AUTH_TOKEN\";\nexport const ANTHROPIC_OAUTH_TOKEN_ENV = \"ANTHROPIC_OAUTH_TOKEN\";\nexport const ANTHROPIC_API_KEY_ENV = \"ANTHROPIC_API_KEY\";\nexport const ANTHROPIC_FEDERATION_RULE_ID_ENV = \"ANTHROPIC_FEDERATION_RULE_ID\";\nexport const ANTHROPIC_ORGANIZATION_ID_ENV = \"ANTHROPIC_ORGANIZATION_ID\";\nexport const ANTHROPIC_SERVICE_ACCOUNT_ID_ENV = \"ANTHROPIC_SERVICE_ACCOUNT_ID\";\nexport const ANTHROPIC_IDENTITY_TOKEN_FILE_ENV = \"ANTHROPIC_IDENTITY_TOKEN_FILE\";\nexport const ANTHROPIC_WORKSPACE_ID_ENV = \"ANTHROPIC_WORKSPACE_ID\";\nlet cachedVertexAdcCredentialsExists = null;\nfunction hasVertexAdcCredentials(env) {\n const explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;\n if (explicitCredentialsPath) {\n return _existsSync ? _existsSync(explicitCredentialsPath) : false;\n }\n if (cachedVertexAdcCredentialsExists === null) {\n // If node modules haven't loaded yet (async import race at startup),\n // return false WITHOUT caching so the next call retries once they're ready.\n // Only cache false permanently in a browser environment where fs is never available.\n if (!_existsSync || !_homedir || !_join) {\n const isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n if (!isNode) {\n // Definitively in a browser — safe to cache false permanently\n cachedVertexAdcCredentialsExists = false;\n }\n return false;\n }\n // Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n const gacPath = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n if (gacPath) {\n cachedVertexAdcCredentialsExists = _existsSync(gacPath);\n }\n else {\n // Fall back to default ADC path (lazy evaluation)\n cachedVertexAdcCredentialsExists = _existsSync(_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"));\n }\n }\n return cachedVertexAdcCredentialsExists;\n}\nfunction getApiKeyEnvVars(provider) {\n if (provider === \"github-copilot\") {\n return [\"COPILOT_GITHUB_TOKEN\"];\n }\n // ANTHROPIC_AUTH_TOKEN participates in env discovery/status, but\n // getEnvApiKey() skips it because requests must pass it as Authorization: Bearer.\n if (provider === \"anthropic\") {\n return [ANTHROPIC_AUTH_TOKEN_ENV, ANTHROPIC_OAUTH_TOKEN_ENV, ANTHROPIC_API_KEY_ENV];\n }\n const envMap = {\n \"ant-ling\": \"ANT_LING_API_KEY\",\n \"qwen-token-plan\": \"QWEN_TOKEN_PLAN_API_KEY\",\n \"qwen-token-plan-cn\": \"QWEN_TOKEN_PLAN_CN_API_KEY\",\n \"qwen-token-plan-individual\": \"QWEN_TOKEN_PLAN_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n \"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n nvidia: \"NVIDIA_API_KEY\",\n deepseek: \"DEEPSEEK_API_KEY\",\n google: \"GEMINI_API_KEY\",\n \"google-vertex\": \"GOOGLE_CLOUD_API_KEY\",\n groq: \"GROQ_API_KEY\",\n cerebras: \"CEREBRAS_API_KEY\",\n xai: \"XAI_API_KEY\",\n typesafe: \"TYPESAFE_API_KEY\",\n radius: \"RADIUS_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n \"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n zai: \"ZAI_API_KEY\",\n \"zai-coding-cn\": \"ZAI_CODING_CN_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n minimax: \"MINIMAX_API_KEY\",\n \"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n moonshotai: \"MOONSHOT_API_KEY\",\n \"moonshotai-cn\": \"MOONSHOT_API_KEY\",\n huggingface: \"HF_TOKEN\",\n fireworks: \"FIREWORKS_API_KEY\",\n together: \"TOGETHER_API_KEY\",\n baseten: \"BASETEN_API_KEY\",\n opencode: \"OPENCODE_API_KEY\",\n \"opencode-go\": \"OPENCODE_API_KEY\",\n \"kimi-coding\": \"KIMI_API_KEY\",\n meta: \"META_API_KEY\",\n \"cloudflare-workers-ai\": \"CLOUDFLARE_API_KEY\",\n \"cloudflare-ai-gateway\": \"CLOUDFLARE_API_KEY\",\n xiaomi: \"XIAOMI_API_KEY\",\n \"xiaomi-token-plan-cn\": \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"xiaomi-token-plan-ams\": \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"xiaomi-token-plan-sgp\": \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n };\n const envVar = envMap[provider];\n return envVar ? [envVar] : undefined;\n}\nexport function findEnvKeys(provider, env) {\n const envVars = getApiKeyEnvVars(provider);\n if (!envVars)\n return undefined;\n const found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));\n return found.length > 0 ? found : undefined;\n}\nexport function getEnvApiKey(provider, env) {\n const envKeys = findEnvKeys(provider, env);\n if (envKeys?.[0]) {\n const apiKeyEnv = provider === \"anthropic\" ? envKeys.find((key) => key !== ANTHROPIC_AUTH_TOKEN_ENV) : envKeys[0];\n if (apiKeyEnv)\n return getProviderEnvValue(apiKeyEnv, env);\n }\n // Vertex AI supports either an explicit API key or Application Default Credentials.\n // Auth is configured via `gcloud auth application-default login`.\n if (provider === \"google-vertex\") {\n const hasCredentials = hasVertexAdcCredentials(env);\n const hasProject = !!(getProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", env) || getProviderEnvValue(\"GCLOUD_PROJECT\", env));\n const hasLocation = !!getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", env);\n if (hasCredentials && hasProject && hasLocation) {\n return \"<authenticated>\";\n }\n }\n if (provider === \"amazon-bedrock\") {\n // Amazon Bedrock supports multiple credential sources:\n // 1. AWS_PROFILE - named profile from ~/.aws/credentials\n // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n // 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock bearer token\n // 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n // 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n // 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n if (getProviderEnvValue(\"AWS_PROFILE\", env) ||\n (getProviderEnvValue(\"AWS_ACCESS_KEY_ID\", env) && getProviderEnvValue(\"AWS_SECRET_ACCESS_KEY\", env)) ||\n getProviderEnvValue(\"AWS_BEARER_TOKEN_BEDROCK\", env) ||\n getProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\", env) ||\n getProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\", env) ||\n getProviderEnvValue(\"AWS_WEB_IDENTITY_TOKEN_FILE\", env)) {\n return \"<authenticated>\";\n }\n }\n return undefined;\n}\n//# sourceMappingURL=env-api-keys.js.map"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/error-body.js
|
|
2
|
+
const MAX_PROVIDER_ERROR_BODY_CHARS = 4e3;
|
|
3
|
+
function normalizeProviderError(error) {
|
|
4
|
+
if (!(error instanceof Error)) return {
|
|
5
|
+
message: safeJsonStringify(error),
|
|
6
|
+
messageCarriesBody: false
|
|
7
|
+
};
|
|
8
|
+
const sdkError = error;
|
|
9
|
+
const status = extractStatus(sdkError);
|
|
10
|
+
const body = extractBody(sdkError);
|
|
11
|
+
const messageCarriesBody = body === void 0 || error.message.includes(body);
|
|
12
|
+
return {
|
|
13
|
+
status,
|
|
14
|
+
body,
|
|
15
|
+
message: error.message,
|
|
16
|
+
messageCarriesBody
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Probe the HTTP status, first numeric hit wins, in SDK-field order:
|
|
21
|
+
* `statusCode` (Mistral) → `status` (`openai`, `@google/genai`) →
|
|
22
|
+
* `$metadata.httpStatusCode` (Bedrock) → `$response.statusCode` (Bedrock).
|
|
23
|
+
*/
|
|
24
|
+
function extractStatus(error) {
|
|
25
|
+
if (typeof error.statusCode === "number") return error.statusCode;
|
|
26
|
+
if (typeof error.status === "number") return error.status;
|
|
27
|
+
if (typeof error.$metadata?.httpStatusCode === "number") return error.$metadata.httpStatusCode;
|
|
28
|
+
if (typeof error.$response?.statusCode === "number") return error.$response.statusCode;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Probe the raw body reason, first usable hit wins, in SDK-field order:
|
|
32
|
+
* `body` string (Mistral) → `error` parsed JSON body object (`openai` SDK's
|
|
33
|
+
* `this.error`) → `$response.body` (Bedrock). Empty objects and unread response
|
|
34
|
+
* streams are treated as no body so they do not surface as `"{}"` or serialized
|
|
35
|
+
* stream internals. The chosen body is truncated to the cap.
|
|
36
|
+
*/
|
|
37
|
+
function extractBody(error) {
|
|
38
|
+
const bodyText = pickBodyText(error);
|
|
39
|
+
if (bodyText === void 0) return void 0;
|
|
40
|
+
const trimmed = bodyText.trim();
|
|
41
|
+
if (trimmed.length === 0) return void 0;
|
|
42
|
+
return truncateErrorText(trimmed, MAX_PROVIDER_ERROR_BODY_CHARS);
|
|
43
|
+
}
|
|
44
|
+
function pickBodyText(error) {
|
|
45
|
+
if (typeof error.body === "string") return error.body;
|
|
46
|
+
if (isPlainNonEmptyObject(error.error)) return safeJsonStringify(error.error);
|
|
47
|
+
const responseBody = error.$response?.body;
|
|
48
|
+
if (typeof responseBody === "string") return responseBody;
|
|
49
|
+
if (isReadableStreamLike(responseBody)) return void 0;
|
|
50
|
+
if (isPlainNonEmptyObject(responseBody)) return safeJsonStringify(responseBody);
|
|
51
|
+
}
|
|
52
|
+
function isReadableStreamLike(value) {
|
|
53
|
+
return typeof value === "object" && value !== null && "pipe" in value && typeof value.pipe === "function";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Only a PLAIN object counts as an HTTP body. SDK error fields can hold class
|
|
57
|
+
* instances instead of parsed bodies — AWS SDK v3's `$response.body` is an
|
|
58
|
+
* HTTP stream/response wrapper object, and stringifying one produced garbage
|
|
59
|
+
* like `{"_events":...}` as the "body", which then REPLACED `error.message`
|
|
60
|
+
* in the composed display string. `error.message` is where the SDK puts the
|
|
61
|
+
* real deserialized exception text ("Input is too long...", schema validation
|
|
62
|
+
* details, ...), so the one useful string was discarded for noise. A class
|
|
63
|
+
* instance yields no body, `messageCarriesBody` stays true, and the real
|
|
64
|
+
* message survives. Complements the `pipe` sniffing above: web
|
|
65
|
+
* ReadableStreams (pipeTo/pipeThrough, no `pipe`) and non-stream SDK wrapper
|
|
66
|
+
* classes fail the prototype check, while parsed JSON bodies (plain objects
|
|
67
|
+
* by construction) still pass.
|
|
68
|
+
*/
|
|
69
|
+
function isPlainNonEmptyObject(value) {
|
|
70
|
+
if (typeof value !== "object" || value === null) return false;
|
|
71
|
+
const proto = Object.getPrototypeOf(value);
|
|
72
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
73
|
+
return Object.keys(value).length > 0;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Compose a display string from a normalized error. When the message already
|
|
77
|
+
* carries the body (Anthropic / `@google/genai` happy path) or no body/status
|
|
78
|
+
* was extracted, the message is returned unchanged. Otherwise the status and
|
|
79
|
+
* body are surfaced, with an optional provider prefix.
|
|
80
|
+
*
|
|
81
|
+
* - no prefix: `"<status>: <body>"`
|
|
82
|
+
* - prefix: `"<prefix> (<status>): <body>"`
|
|
83
|
+
*/
|
|
84
|
+
function formatProviderError(norm, prefix) {
|
|
85
|
+
if (norm.messageCarriesBody || norm.status === void 0 || norm.body === void 0) return prefix !== void 0 && norm.status !== void 0 ? `${prefix} (${norm.status}): ${norm.message}` : norm.message;
|
|
86
|
+
return prefix !== void 0 ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;
|
|
87
|
+
}
|
|
88
|
+
function truncateErrorText(text, maxChars) {
|
|
89
|
+
if (text.length <= maxChars) return text;
|
|
90
|
+
return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
|
|
91
|
+
}
|
|
92
|
+
function safeJsonStringify(value) {
|
|
93
|
+
try {
|
|
94
|
+
const serialized = JSON.stringify(value);
|
|
95
|
+
return serialized === void 0 ? String(value) : serialized;
|
|
96
|
+
} catch {
|
|
97
|
+
return String(value);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { normalizeProviderError as n, formatProviderError as t };
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=error-body-CyiejW4b.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-body-CyiejW4b.js","names":[],"sources":["../node_modules/@earendil-works/pi-ai/dist/utils/error-body.js"],"sourcesContent":["// Shared normalization for provider HTTP error objects.\n//\n// Endpoints behind a proxy / gateway may return a non-2xx response whose body\n// the provider SDK cannot fold into `error.message`. The SDK error object still\n// carries the HTTP status and the raw/parsed body, but under SDK-specific field\n// names. Provider catch blocks that read only `error.message` therefore drop\n// the body and surface opaque messages like `\"403 status code (no body)\"` or\n// collapse to `\"Unknown: UnknownError\"`.\n//\n// `normalizeProviderError` probes the known SDK field shapes (Mistral,\n// `openai`, `@google/genai`, AWS Bedrock) and returns a struct each provider\n// composes into its display string. The `messageCarriesBody` flag captures the\n// Anthropic / `@google/genai` happy path where the SDK already folded the body\n// into the message, so providers can preserve it without double-printing.\nexport const MAX_PROVIDER_ERROR_BODY_CHARS = 4000;\nexport function normalizeProviderError(error) {\n if (!(error instanceof Error)) {\n return { message: safeJsonStringify(error), messageCarriesBody: false };\n }\n const sdkError = error;\n const status = extractStatus(sdkError);\n const body = extractBody(sdkError);\n const messageCarriesBody = body === undefined || error.message.includes(body);\n return {\n status,\n body,\n message: error.message,\n messageCarriesBody,\n };\n}\n/**\n * Probe the HTTP status, first numeric hit wins, in SDK-field order:\n * `statusCode` (Mistral) → `status` (`openai`, `@google/genai`) →\n * `$metadata.httpStatusCode` (Bedrock) → `$response.statusCode` (Bedrock).\n */\nfunction extractStatus(error) {\n if (typeof error.statusCode === \"number\")\n return error.statusCode;\n if (typeof error.status === \"number\")\n return error.status;\n if (typeof error.$metadata?.httpStatusCode === \"number\")\n return error.$metadata.httpStatusCode;\n if (typeof error.$response?.statusCode === \"number\")\n return error.$response.statusCode;\n return undefined;\n}\n/**\n * Probe the raw body reason, first usable hit wins, in SDK-field order:\n * `body` string (Mistral) → `error` parsed JSON body object (`openai` SDK's\n * `this.error`) → `$response.body` (Bedrock). Empty objects and unread response\n * streams are treated as no body so they do not surface as `\"{}\"` or serialized\n * stream internals. The chosen body is truncated to the cap.\n */\nfunction extractBody(error) {\n const bodyText = pickBodyText(error);\n if (bodyText === undefined)\n return undefined;\n const trimmed = bodyText.trim();\n if (trimmed.length === 0)\n return undefined;\n return truncateErrorText(trimmed, MAX_PROVIDER_ERROR_BODY_CHARS);\n}\nfunction pickBodyText(error) {\n if (typeof error.body === \"string\")\n return error.body;\n if (isPlainNonEmptyObject(error.error))\n return safeJsonStringify(error.error);\n const responseBody = error.$response?.body;\n if (typeof responseBody === \"string\")\n return responseBody;\n if (isReadableStreamLike(responseBody))\n return undefined;\n if (isPlainNonEmptyObject(responseBody))\n return safeJsonStringify(responseBody);\n return undefined;\n}\nfunction isReadableStreamLike(value) {\n return typeof value === \"object\" && value !== null && \"pipe\" in value && typeof value.pipe === \"function\";\n}\n/**\n * Only a PLAIN object counts as an HTTP body. SDK error fields can hold class\n * instances instead of parsed bodies — AWS SDK v3's `$response.body` is an\n * HTTP stream/response wrapper object, and stringifying one produced garbage\n * like `{\"_events\":...}` as the \"body\", which then REPLACED `error.message`\n * in the composed display string. `error.message` is where the SDK puts the\n * real deserialized exception text (\"Input is too long...\", schema validation\n * details, ...), so the one useful string was discarded for noise. A class\n * instance yields no body, `messageCarriesBody` stays true, and the real\n * message survives. Complements the `pipe` sniffing above: web\n * ReadableStreams (pipeTo/pipeThrough, no `pipe`) and non-stream SDK wrapper\n * classes fail the prototype check, while parsed JSON bodies (plain objects\n * by construction) still pass.\n */\nfunction isPlainNonEmptyObject(value) {\n if (typeof value !== \"object\" || value === null)\n return false;\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null)\n return false;\n return Object.keys(value).length > 0;\n}\n/**\n * Compose a display string from a normalized error. When the message already\n * carries the body (Anthropic / `@google/genai` happy path) or no body/status\n * was extracted, the message is returned unchanged. Otherwise the status and\n * body are surfaced, with an optional provider prefix.\n *\n * - no prefix: `\"<status>: <body>\"`\n * - prefix: `\"<prefix> (<status>): <body>\"`\n */\nexport function formatProviderError(norm, prefix) {\n if (norm.messageCarriesBody || norm.status === undefined || norm.body === undefined) {\n return prefix !== undefined && norm.status !== undefined\n ? `${prefix} (${norm.status}): ${norm.message}`\n : norm.message;\n }\n return prefix !== undefined ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;\n}\nexport function truncateErrorText(text, maxChars) {\n if (text.length <= maxChars)\n return text;\n return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;\n}\nexport function safeJsonStringify(value) {\n try {\n const serialized = JSON.stringify(value);\n return serialized === undefined ? String(value) : serialized;\n }\n catch {\n return String(value);\n }\n}\n//# sourceMappingURL=error-body.js.map"],"x_google_ignoreList":[0],"mappings":";AAcA,MAAa,gCAAgC;AAC7C,SAAgB,uBAAuB,OAAO;CAC1C,IAAI,EAAE,iBAAiB,QACnB,OAAO;EAAE,SAAS,kBAAkB,KAAK;EAAG,oBAAoB;CAAM;CAE1E,MAAM,WAAW;CACjB,MAAM,SAAS,cAAc,QAAQ;CACrC,MAAM,OAAO,YAAY,QAAQ;CACjC,MAAM,qBAAqB,SAAS,KAAA,KAAa,MAAM,QAAQ,SAAS,IAAI;CAC5E,OAAO;EACH;EACA;EACA,SAAS,MAAM;EACf;CACJ;AACJ;;;;;;AAMA,SAAS,cAAc,OAAO;CAC1B,IAAI,OAAO,MAAM,eAAe,UAC5B,OAAO,MAAM;CACjB,IAAI,OAAO,MAAM,WAAW,UACxB,OAAO,MAAM;CACjB,IAAI,OAAO,MAAM,WAAW,mBAAmB,UAC3C,OAAO,MAAM,UAAU;CAC3B,IAAI,OAAO,MAAM,WAAW,eAAe,UACvC,OAAO,MAAM,UAAU;AAE/B;;;;;;;;AAQA,SAAS,YAAY,OAAO;CACxB,MAAM,WAAW,aAAa,KAAK;CACnC,IAAI,aAAa,KAAA,GACb,OAAO,KAAA;CACX,MAAM,UAAU,SAAS,KAAK;CAC9B,IAAI,QAAQ,WAAW,GACnB,OAAO,KAAA;CACX,OAAO,kBAAkB,SAAS,6BAA6B;AACnE;AACA,SAAS,aAAa,OAAO;CACzB,IAAI,OAAO,MAAM,SAAS,UACtB,OAAO,MAAM;CACjB,IAAI,sBAAsB,MAAM,KAAK,GACjC,OAAO,kBAAkB,MAAM,KAAK;CACxC,MAAM,eAAe,MAAM,WAAW;CACtC,IAAI,OAAO,iBAAiB,UACxB,OAAO;CACX,IAAI,qBAAqB,YAAY,GACjC,OAAO,KAAA;CACX,IAAI,sBAAsB,YAAY,GAClC,OAAO,kBAAkB,YAAY;AAE7C;AACA,SAAS,qBAAqB,OAAO;CACjC,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,SAAS,OAAO,MAAM,SAAS;AACnG;;;;;;;;;;;;;;;AAeA,SAAS,sBAAsB,OAAO;CAClC,IAAI,OAAO,UAAU,YAAY,UAAU,MACvC,OAAO;CACX,MAAM,QAAQ,OAAO,eAAe,KAAK;CACzC,IAAI,UAAU,OAAO,aAAa,UAAU,MACxC,OAAO;CACX,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS;AACvC;;;;;;;;;;AAUA,SAAgB,oBAAoB,MAAM,QAAQ;CAC9C,IAAI,KAAK,sBAAsB,KAAK,WAAW,KAAA,KAAa,KAAK,SAAS,KAAA,GACtE,OAAO,WAAW,KAAA,KAAa,KAAK,WAAW,KAAA,IACzC,GAAG,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,YACpC,KAAK;CAEf,OAAO,WAAW,KAAA,IAAY,GAAG,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,SAAS,GAAG,KAAK,OAAO,IAAI,KAAK;AACvG;AACA,SAAgB,kBAAkB,MAAM,UAAU;CAC9C,IAAI,KAAK,UAAU,UACf,OAAO;CACX,OAAO,GAAG,KAAK,MAAM,GAAG,QAAQ,EAAE,iBAAiB,KAAK,SAAS,SAAS;AAC9E;AACA,SAAgB,kBAAkB,OAAO;CACrC,IAAI;EACA,MAAM,aAAa,KAAK,UAAU,KAAK;EACvC,OAAO,eAAe,KAAA,IAAY,OAAO,KAAK,IAAI;CACtD,QACM;EACF,OAAO,OAAO,KAAK;CACvB;AACJ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js
|
|
2
|
+
function inferCopilotInitiator(messages) {
|
|
3
|
+
const last = messages[messages.length - 1];
|
|
4
|
+
return last && last.role !== "user" ? "agent" : "user";
|
|
5
|
+
}
|
|
6
|
+
function hasCopilotVisionInput(messages) {
|
|
7
|
+
return messages.some((msg) => {
|
|
8
|
+
if (msg.role === "user" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
|
|
9
|
+
if (msg.role === "toolResult" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
|
|
10
|
+
return false;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function buildCopilotDynamicHeaders(params) {
|
|
14
|
+
const headers = {
|
|
15
|
+
"X-Initiator": inferCopilotInitiator(params.messages),
|
|
16
|
+
"Openai-Intent": "conversation-edits"
|
|
17
|
+
};
|
|
18
|
+
if (params.hasImages) headers["Copilot-Vision-Request"] = "true";
|
|
19
|
+
return headers;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { hasCopilotVisionInput as n, buildCopilotDynamicHeaders as t };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=github-copilot-headers-CEpMOpQF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-copilot-headers-CEpMOpQF.js","names":[],"sources":["../node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js"],"sourcesContent":["// Copilot expects X-Initiator to indicate whether the request is user-initiated\n// or agent-initiated (e.g. follow-up after assistant/tool messages).\nexport function inferCopilotInitiator(messages) {\n const last = messages[messages.length - 1];\n return last && last.role !== \"user\" ? \"agent\" : \"user\";\n}\n// Copilot requires Copilot-Vision-Request header when sending images\nexport function hasCopilotVisionInput(messages) {\n return messages.some((msg) => {\n if (msg.role === \"user\" && Array.isArray(msg.content)) {\n return msg.content.some((c) => c.type === \"image\");\n }\n if (msg.role === \"toolResult\" && Array.isArray(msg.content)) {\n return msg.content.some((c) => c.type === \"image\");\n }\n return false;\n });\n}\nexport function buildCopilotDynamicHeaders(params) {\n const headers = {\n \"X-Initiator\": inferCopilotInitiator(params.messages),\n \"Openai-Intent\": \"conversation-edits\",\n };\n if (params.hasImages) {\n headers[\"Copilot-Vision-Request\"] = \"true\";\n }\n return headers;\n}\n//# sourceMappingURL=github-copilot-headers.js.map"],"x_google_ignoreList":[0],"mappings":";AAEA,SAAgB,sBAAsB,UAAU;CAC5C,MAAM,OAAO,SAAS,SAAS,SAAS;CACxC,OAAO,QAAQ,KAAK,SAAS,SAAS,UAAU;AACpD;AAEA,SAAgB,sBAAsB,UAAU;CAC5C,OAAO,SAAS,MAAM,QAAQ;EAC1B,IAAI,IAAI,SAAS,UAAU,MAAM,QAAQ,IAAI,OAAO,GAChD,OAAO,IAAI,QAAQ,MAAM,MAAM,EAAE,SAAS,OAAO;EAErD,IAAI,IAAI,SAAS,gBAAgB,MAAM,QAAQ,IAAI,OAAO,GACtD,OAAO,IAAI,QAAQ,MAAM,MAAM,EAAE,SAAS,OAAO;EAErD,OAAO;CACX,CAAC;AACL;AACA,SAAgB,2BAA2B,QAAQ;CAC/C,MAAM,UAAU;EACZ,eAAe,sBAAsB,OAAO,QAAQ;EACpD,iBAAiB;CACrB;CACA,IAAI,OAAO,WACP,QAAQ,4BAA4B;CAExC,OAAO;AACX"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { a as AssistantMessageEventStream } from "./diagnostics-Wt5faNDM.js";
|
|
2
|
+
import { S as getSystemMessageText, d as getCurrentTools, n as clampThinkingLevel, o as collapseSystemMessages, p as getInitialSystemMessage, t as calculateCost } from "./models-DcT5qOEL.js";
|
|
3
|
+
import { n as providerHeadersToRecord } from "./headers-BRNMVpzu.js";
|
|
4
|
+
import { p as getPiUserAgent, r as buildBaseOptions } from "./transform-messages-BLJ8EfK6.js";
|
|
5
|
+
import { t as sanitizeSurrogates } from "./sanitize-unicode-Ds14l9Om.js";
|
|
6
|
+
import { n as normalizeProviderError, t as formatProviderError } from "./error-body-CyiejW4b.js";
|
|
7
|
+
import { a as mapStopReason, c as retainThoughtSignature, d as toGoogleSdkThinkingLevel, f as toGoogleThinkingLevel, i as isThinkingPart, l as retryGoogleRequest, m as GoogleGenAI, n as convertTools, o as resolveGoogleFunctionCallingMode, p as usesGoogleThinkingLevel, r as getDisabledGoogleThinkingConfig, s as resolveGoogleThinkingLevel, t as convertMessages, u as supportsGoogleStrictToolSampling } from "./google-shared-0gpM2jFi.js";
|
|
8
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js
|
|
9
|
+
let toolCallCounter = 0;
|
|
10
|
+
const stream = (model, context, options) => {
|
|
11
|
+
const stream = new AssistantMessageEventStream();
|
|
12
|
+
const normalizedContext = collapseSystemMessages(context);
|
|
13
|
+
(async () => {
|
|
14
|
+
const output = {
|
|
15
|
+
role: "assistant",
|
|
16
|
+
content: [],
|
|
17
|
+
api: "google-generative-ai",
|
|
18
|
+
provider: model.provider,
|
|
19
|
+
model: model.id,
|
|
20
|
+
usage: {
|
|
21
|
+
input: 0,
|
|
22
|
+
output: 0,
|
|
23
|
+
cacheRead: 0,
|
|
24
|
+
cacheWrite: 0,
|
|
25
|
+
totalTokens: 0,
|
|
26
|
+
cost: {
|
|
27
|
+
input: 0,
|
|
28
|
+
output: 0,
|
|
29
|
+
cacheRead: 0,
|
|
30
|
+
cacheWrite: 0,
|
|
31
|
+
total: 0
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
stopReason: "pending",
|
|
35
|
+
timestamp: Date.now()
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
if (options?.fetch && options.fetch !== globalThis.fetch) throw new Error("Custom fetch is not supported by the Google Generative AI adapter");
|
|
39
|
+
const apiKey = options?.apiKey;
|
|
40
|
+
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
41
|
+
const client = createClient(model, apiKey, options?.headers);
|
|
42
|
+
let params = buildParams(model, normalizedContext, options);
|
|
43
|
+
const nextParams = await options?.onPayload?.(params, model);
|
|
44
|
+
if (nextParams !== void 0) params = nextParams;
|
|
45
|
+
const googleStream = await retryGoogleRequest(() => client.models.generateContentStream(params), options);
|
|
46
|
+
stream.push({
|
|
47
|
+
type: "start",
|
|
48
|
+
partial: output
|
|
49
|
+
});
|
|
50
|
+
let currentBlock = null;
|
|
51
|
+
const blocks = output.content;
|
|
52
|
+
const blockIndex = () => blocks.length - 1;
|
|
53
|
+
for await (const chunk of googleStream) {
|
|
54
|
+
await options?.onProviderStreamEvent?.(chunk, model);
|
|
55
|
+
output.responseId ||= chunk.responseId;
|
|
56
|
+
const candidate = chunk.candidates?.[0];
|
|
57
|
+
if (candidate?.content?.parts) for (const part of candidate.content.parts) {
|
|
58
|
+
if (part.text !== void 0) {
|
|
59
|
+
const isThinking = isThinkingPart(part);
|
|
60
|
+
if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
|
|
61
|
+
if (currentBlock) if (currentBlock.type === "text") stream.push({
|
|
62
|
+
type: "text_end",
|
|
63
|
+
contentIndex: blocks.length - 1,
|
|
64
|
+
content: currentBlock.text,
|
|
65
|
+
partial: output
|
|
66
|
+
});
|
|
67
|
+
else stream.push({
|
|
68
|
+
type: "thinking_end",
|
|
69
|
+
contentIndex: blockIndex(),
|
|
70
|
+
content: currentBlock.thinking,
|
|
71
|
+
partial: output
|
|
72
|
+
});
|
|
73
|
+
if (isThinking) {
|
|
74
|
+
currentBlock = {
|
|
75
|
+
type: "thinking",
|
|
76
|
+
thinking: "",
|
|
77
|
+
thinkingSignature: void 0
|
|
78
|
+
};
|
|
79
|
+
output.content.push(currentBlock);
|
|
80
|
+
stream.push({
|
|
81
|
+
type: "thinking_start",
|
|
82
|
+
contentIndex: blockIndex(),
|
|
83
|
+
partial: output
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
currentBlock = {
|
|
87
|
+
type: "text",
|
|
88
|
+
text: ""
|
|
89
|
+
};
|
|
90
|
+
output.content.push(currentBlock);
|
|
91
|
+
stream.push({
|
|
92
|
+
type: "text_start",
|
|
93
|
+
contentIndex: blockIndex(),
|
|
94
|
+
partial: output
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (currentBlock.type === "thinking") {
|
|
99
|
+
currentBlock.thinking += part.text;
|
|
100
|
+
currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
|
|
101
|
+
stream.push({
|
|
102
|
+
type: "thinking_delta",
|
|
103
|
+
contentIndex: blockIndex(),
|
|
104
|
+
delta: part.text,
|
|
105
|
+
partial: output
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
currentBlock.text += part.text;
|
|
109
|
+
currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
|
|
110
|
+
stream.push({
|
|
111
|
+
type: "text_delta",
|
|
112
|
+
contentIndex: blockIndex(),
|
|
113
|
+
delta: part.text,
|
|
114
|
+
partial: output
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (part.functionCall) {
|
|
119
|
+
if (currentBlock) {
|
|
120
|
+
if (currentBlock.type === "text") stream.push({
|
|
121
|
+
type: "text_end",
|
|
122
|
+
contentIndex: blockIndex(),
|
|
123
|
+
content: currentBlock.text,
|
|
124
|
+
partial: output
|
|
125
|
+
});
|
|
126
|
+
else stream.push({
|
|
127
|
+
type: "thinking_end",
|
|
128
|
+
contentIndex: blockIndex(),
|
|
129
|
+
content: currentBlock.thinking,
|
|
130
|
+
partial: output
|
|
131
|
+
});
|
|
132
|
+
currentBlock = null;
|
|
133
|
+
}
|
|
134
|
+
const providedId = part.functionCall.id;
|
|
135
|
+
const toolCall = {
|
|
136
|
+
type: "toolCall",
|
|
137
|
+
id: !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId) ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}` : providedId,
|
|
138
|
+
name: part.functionCall.name || "",
|
|
139
|
+
arguments: part.functionCall.args ?? {},
|
|
140
|
+
...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
|
|
141
|
+
};
|
|
142
|
+
output.content.push(toolCall);
|
|
143
|
+
stream.push({
|
|
144
|
+
type: "toolcall_start",
|
|
145
|
+
contentIndex: blockIndex(),
|
|
146
|
+
partial: output
|
|
147
|
+
});
|
|
148
|
+
stream.push({
|
|
149
|
+
type: "toolcall_delta",
|
|
150
|
+
contentIndex: blockIndex(),
|
|
151
|
+
delta: JSON.stringify(toolCall.arguments),
|
|
152
|
+
partial: output
|
|
153
|
+
});
|
|
154
|
+
stream.push({
|
|
155
|
+
type: "toolcall_end",
|
|
156
|
+
contentIndex: blockIndex(),
|
|
157
|
+
toolCall,
|
|
158
|
+
partial: output
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (candidate?.finishReason) {
|
|
163
|
+
output.rawStopReason = candidate.finishReason;
|
|
164
|
+
output.stopReason = mapStopReason(candidate.finishReason);
|
|
165
|
+
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") output.stopReason = "toolUse";
|
|
166
|
+
}
|
|
167
|
+
if (chunk.usageMetadata) {
|
|
168
|
+
output.usage = {
|
|
169
|
+
input: (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),
|
|
170
|
+
output: (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),
|
|
171
|
+
cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,
|
|
172
|
+
cacheWrite: 0,
|
|
173
|
+
reasoning: chunk.usageMetadata.thoughtsTokenCount || 0,
|
|
174
|
+
totalTokens: chunk.usageMetadata.totalTokenCount || 0,
|
|
175
|
+
cost: {
|
|
176
|
+
input: 0,
|
|
177
|
+
output: 0,
|
|
178
|
+
cacheRead: 0,
|
|
179
|
+
cacheWrite: 0,
|
|
180
|
+
total: 0
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
calculateCost(model, output.usage);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (currentBlock) if (currentBlock.type === "text") stream.push({
|
|
187
|
+
type: "text_end",
|
|
188
|
+
contentIndex: blockIndex(),
|
|
189
|
+
content: currentBlock.text,
|
|
190
|
+
partial: output
|
|
191
|
+
});
|
|
192
|
+
else stream.push({
|
|
193
|
+
type: "thinking_end",
|
|
194
|
+
contentIndex: blockIndex(),
|
|
195
|
+
content: currentBlock.thinking,
|
|
196
|
+
partial: output
|
|
197
|
+
});
|
|
198
|
+
if (options?.signal?.aborted) throw new Error("Request was aborted");
|
|
199
|
+
if (output.stopReason === "pending") throw new Error("Google stream ended without a finish reason");
|
|
200
|
+
if (output.stopReason === "aborted" || output.stopReason === "error") {
|
|
201
|
+
const errorMessage = output.rawStopReason ? `Provider stopped with: ${output.rawStopReason}` : "An unknown error occurred";
|
|
202
|
+
throw new Error(errorMessage);
|
|
203
|
+
}
|
|
204
|
+
stream.push({
|
|
205
|
+
type: "done",
|
|
206
|
+
reason: output.stopReason,
|
|
207
|
+
message: output
|
|
208
|
+
});
|
|
209
|
+
stream.end();
|
|
210
|
+
} catch (error) {
|
|
211
|
+
for (const block of output.content) if ("index" in block) delete block.index;
|
|
212
|
+
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
213
|
+
output.errorMessage = formatProviderError(normalizeProviderError(error));
|
|
214
|
+
stream.push({
|
|
215
|
+
type: "error",
|
|
216
|
+
reason: output.stopReason,
|
|
217
|
+
error: output
|
|
218
|
+
});
|
|
219
|
+
stream.end();
|
|
220
|
+
}
|
|
221
|
+
})();
|
|
222
|
+
return stream;
|
|
223
|
+
};
|
|
224
|
+
const streamSimple = (model, context, options) => {
|
|
225
|
+
const apiKey = options?.apiKey;
|
|
226
|
+
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
227
|
+
const base = {
|
|
228
|
+
...buildBaseOptions(model, context, options, apiKey),
|
|
229
|
+
toolChoice: options?.toolChoice
|
|
230
|
+
};
|
|
231
|
+
if (!options?.reasoning) return stream(model, context, {
|
|
232
|
+
...base,
|
|
233
|
+
thinking: { enabled: false }
|
|
234
|
+
});
|
|
235
|
+
const clampedReasoning = clampThinkingLevel(model, options.reasoning);
|
|
236
|
+
if (clampedReasoning === "off") return stream(model, context, {
|
|
237
|
+
...base,
|
|
238
|
+
thinking: { enabled: false }
|
|
239
|
+
});
|
|
240
|
+
const resolvedLevel = resolveGoogleThinkingLevel(model, clampedReasoning);
|
|
241
|
+
if (usesGoogleThinkingLevel(model)) return stream(model, context, {
|
|
242
|
+
...base,
|
|
243
|
+
thinking: {
|
|
244
|
+
enabled: true,
|
|
245
|
+
level: toGoogleThinkingLevel(resolvedLevel)
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return stream(model, context, {
|
|
249
|
+
...base,
|
|
250
|
+
thinking: {
|
|
251
|
+
enabled: true,
|
|
252
|
+
budgetTokens: getGoogleBudget(model, resolvedLevel, options.thinkingBudgets)
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
function createClient(model, apiKey, optionsHeaders) {
|
|
257
|
+
const httpOptions = {};
|
|
258
|
+
if (model.baseUrl) {
|
|
259
|
+
httpOptions.baseUrl = model.baseUrl;
|
|
260
|
+
httpOptions.apiVersion = "";
|
|
261
|
+
}
|
|
262
|
+
const headers = providerHeadersToRecord({
|
|
263
|
+
"User-Agent": getPiUserAgent(),
|
|
264
|
+
...model.headers,
|
|
265
|
+
...optionsHeaders
|
|
266
|
+
});
|
|
267
|
+
if (headers) httpOptions.headers = headers;
|
|
268
|
+
return new GoogleGenAI({
|
|
269
|
+
apiKey,
|
|
270
|
+
httpOptions: Object.keys(httpOptions).length > 0 ? httpOptions : void 0
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function buildParams(model, context, options = {}) {
|
|
274
|
+
const contents = convertMessages(model, context);
|
|
275
|
+
const initialSystemMessage = getInitialSystemMessage(context.messages);
|
|
276
|
+
const currentTools = getCurrentTools(context.messages);
|
|
277
|
+
const generationConfig = {};
|
|
278
|
+
if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
|
|
279
|
+
if (options.maxTokens !== void 0) generationConfig.maxOutputTokens = options.maxTokens;
|
|
280
|
+
const supportsStrictMode = supportsGoogleStrictToolSampling(model.id);
|
|
281
|
+
const functionCallingMode = currentTools.length > 0 ? resolveGoogleFunctionCallingMode(currentTools, options.toolChoice, supportsStrictMode) : void 0;
|
|
282
|
+
const systemInstruction = initialSystemMessage ? getSystemMessageText(initialSystemMessage) : "";
|
|
283
|
+
const config = {
|
|
284
|
+
...Object.keys(generationConfig).length > 0 && generationConfig,
|
|
285
|
+
...systemInstruction && { systemInstruction: sanitizeSurrogates(systemInstruction) },
|
|
286
|
+
...currentTools.length > 0 && { tools: convertTools(currentTools, false, supportsStrictMode) },
|
|
287
|
+
...functionCallingMode !== void 0 && { toolConfig: { functionCallingConfig: { mode: functionCallingMode } } }
|
|
288
|
+
};
|
|
289
|
+
if (options.thinking?.enabled && model.reasoning) {
|
|
290
|
+
const thinkingConfig = { includeThoughts: true };
|
|
291
|
+
if (options.thinking.level !== void 0) thinkingConfig.thinkingLevel = toGoogleSdkThinkingLevel(options.thinking.level);
|
|
292
|
+
else if (options.thinking.budgetTokens !== void 0) thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
|
|
293
|
+
config.thinkingConfig = thinkingConfig;
|
|
294
|
+
} else if (model.reasoning && options.thinking && !options.thinking.enabled) config.thinkingConfig = getDisabledGoogleThinkingConfig(model);
|
|
295
|
+
if (options.signal) {
|
|
296
|
+
if (options.signal.aborted) throw new Error("Request aborted");
|
|
297
|
+
config.abortSignal = options.signal;
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
model: model.id,
|
|
301
|
+
contents,
|
|
302
|
+
config
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function getGoogleBudget(model, level, customBudgets) {
|
|
306
|
+
if (customBudgets?.[level] !== void 0) return customBudgets[level];
|
|
307
|
+
if (model.id.includes("2.5-pro")) return {
|
|
308
|
+
minimal: 128,
|
|
309
|
+
low: 2048,
|
|
310
|
+
medium: 8192,
|
|
311
|
+
high: 32768
|
|
312
|
+
}[level];
|
|
313
|
+
if (model.id.includes("2.5-flash-lite")) return {
|
|
314
|
+
minimal: 512,
|
|
315
|
+
low: 2048,
|
|
316
|
+
medium: 8192,
|
|
317
|
+
high: 24576
|
|
318
|
+
}[level];
|
|
319
|
+
if (model.id.includes("2.5-flash")) return {
|
|
320
|
+
minimal: 128,
|
|
321
|
+
low: 2048,
|
|
322
|
+
medium: 8192,
|
|
323
|
+
high: 24576
|
|
324
|
+
}[level];
|
|
325
|
+
return -1;
|
|
326
|
+
}
|
|
327
|
+
//#endregion
|
|
328
|
+
export { stream, streamSimple };
|
|
329
|
+
|
|
330
|
+
//# sourceMappingURL=google-generative-ai-BxABKIKO.js.map
|