@joshuaswarren/openclaw-engram 9.1.18 → 9.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +3 -3
- package/dist/{calibration-WQM24F3Z.js → calibration-OOOYE2ID.js} +2 -2
- package/dist/{causal-consolidation-GNGU4MUV.js → causal-consolidation-BDMZMX2D.js} +2 -2
- package/dist/{chunk-AVOL6JGC.js → chunk-KIA3HVQD.js} +82 -12
- package/dist/chunk-KIA3HVQD.js.map +1 -0
- package/dist/{chunk-HOO364J6.js → chunk-KZMICTC7.js} +5 -5
- package/dist/{chunk-IEFSMVQV.js → chunk-OLJAEA5I.js} +3 -3
- package/dist/{engine-CNQZ35RB.js → engine-63EMTVP7.js} +2 -2
- package/dist/{fallback-llm-GF6NMVWP.js → fallback-llm-46JU5PST.js} +2 -2
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-AVOL6JGC.js.map +0 -1
- /package/dist/{calibration-WQM24F3Z.js.map → calibration-OOOYE2ID.js.map} +0 -0
- /package/dist/{causal-consolidation-GNGU4MUV.js.map → causal-consolidation-BDMZMX2D.js.map} +0 -0
- /package/dist/{chunk-HOO364J6.js.map → chunk-KZMICTC7.js.map} +0 -0
- /package/dist/{chunk-IEFSMVQV.js.map → chunk-OLJAEA5I.js.map} +0 -0
- /package/dist/{engine-CNQZ35RB.js.map → engine-63EMTVP7.js.map} +0 -0
- /package/dist/{fallback-llm-GF6NMVWP.js.map → fallback-llm-46JU5PST.js.map} +0 -0
package/dist/access-cli.js
CHANGED
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
EngramAccessService,
|
|
4
4
|
Orchestrator,
|
|
5
5
|
parseConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-KZMICTC7.js";
|
|
7
|
+
import "./chunk-OLJAEA5I.js";
|
|
8
8
|
import "./chunk-IMMYYNXG.js";
|
|
9
9
|
import "./chunk-DTCQ2KEX.js";
|
|
10
10
|
import "./chunk-6KX4XLQJ.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-KIA3HVQD.js";
|
|
12
12
|
import "./chunk-MKM2BCQH.js";
|
|
13
13
|
import "./chunk-DEIBZP3O.js";
|
|
14
14
|
import "./chunk-SSIIJJKA.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// openclaw-engram: Local-first memory plugin
|
|
2
2
|
import {
|
|
3
3
|
FallbackLlmClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KIA3HVQD.js";
|
|
5
5
|
import {
|
|
6
6
|
listJsonFiles
|
|
7
7
|
} from "./chunk-DEIBZP3O.js";
|
|
@@ -233,4 +233,4 @@ export {
|
|
|
233
233
|
runCalibrationIfEnabled,
|
|
234
234
|
synthesizeCalibrationRules
|
|
235
235
|
};
|
|
236
|
-
//# sourceMappingURL=calibration-
|
|
236
|
+
//# sourceMappingURL=calibration-OOOYE2ID.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// openclaw-engram: Local-first memory plugin
|
|
2
2
|
import {
|
|
3
3
|
FallbackLlmClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KIA3HVQD.js";
|
|
5
5
|
import {
|
|
6
6
|
readChainIndex,
|
|
7
7
|
resolveChainsDir
|
|
@@ -203,4 +203,4 @@ export {
|
|
|
203
203
|
deriveCausalPromotionCandidates,
|
|
204
204
|
synthesizeCausalPreferencesViaLlm
|
|
205
205
|
};
|
|
206
|
-
//# sourceMappingURL=causal-consolidation-
|
|
206
|
+
//# sourceMappingURL=causal-consolidation-BDMZMX2D.js.map
|
|
@@ -100,6 +100,34 @@ import { readFileSync, existsSync } from "fs";
|
|
|
100
100
|
import path from "path";
|
|
101
101
|
import os from "os";
|
|
102
102
|
var resolvedCache = /* @__PURE__ */ new Map();
|
|
103
|
+
var DEFAULT_OP_VAULT = "OpenClaw";
|
|
104
|
+
var OP_SERVICE_ACCOUNT_TOKEN_PATH = path.join(os.homedir(), ".openclaw", "secrets", "op-service-account-token");
|
|
105
|
+
var OP_VAULT_PATH = path.join(os.homedir(), ".openclaw", "secrets", "op-vault-name");
|
|
106
|
+
function getOpVault() {
|
|
107
|
+
try {
|
|
108
|
+
if (existsSync(OP_VAULT_PATH)) {
|
|
109
|
+
const vault = readFileSync(OP_VAULT_PATH, "utf-8").trim();
|
|
110
|
+
if (vault) return vault;
|
|
111
|
+
}
|
|
112
|
+
} catch {
|
|
113
|
+
}
|
|
114
|
+
return process.env.OP_VAULT ?? DEFAULT_OP_VAULT;
|
|
115
|
+
}
|
|
116
|
+
function buildOpEnv() {
|
|
117
|
+
if (process.env.OP_SERVICE_ACCOUNT_TOKEN) {
|
|
118
|
+
return process.env;
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
if (existsSync(OP_SERVICE_ACCOUNT_TOKEN_PATH)) {
|
|
122
|
+
const token = readFileSync(OP_SERVICE_ACCOUNT_TOKEN_PATH, "utf-8").trim();
|
|
123
|
+
if (token) {
|
|
124
|
+
return { ...process.env, OP_SERVICE_ACCOUNT_TOKEN: token };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
return process.env;
|
|
130
|
+
}
|
|
103
131
|
async function resolveProviderApiKey(providerId, apiKeyValue, gatewayConfig) {
|
|
104
132
|
if (typeof apiKeyValue === "string") {
|
|
105
133
|
if (apiKeyValue === "secretref-managed") {
|
|
@@ -157,11 +185,13 @@ function resolveExecSecret(ref) {
|
|
|
157
185
|
return void 0;
|
|
158
186
|
}
|
|
159
187
|
const args = ref.args ?? (ref.provider === "op" ? ["read", ref.id] : [ref.id]);
|
|
188
|
+
const env = ref.provider === "op" ? buildOpEnv() : process.env;
|
|
160
189
|
try {
|
|
161
190
|
const result = execFileSync(command, args, {
|
|
162
191
|
encoding: "utf-8",
|
|
163
|
-
timeout:
|
|
164
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
192
|
+
timeout: 15e3,
|
|
193
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
194
|
+
env
|
|
165
195
|
}).trim();
|
|
166
196
|
return result || void 0;
|
|
167
197
|
} catch (err) {
|
|
@@ -171,6 +201,55 @@ function resolveExecSecret(ref) {
|
|
|
171
201
|
}
|
|
172
202
|
function resolveFileSecret(ref) {
|
|
173
203
|
if (ref.provider === "op") {
|
|
204
|
+
const env = buildOpEnv();
|
|
205
|
+
if (ref.id.startsWith("op://")) {
|
|
206
|
+
try {
|
|
207
|
+
const result = execFileSync("op", ["read", ref.id], {
|
|
208
|
+
encoding: "utf-8",
|
|
209
|
+
timeout: 15e3,
|
|
210
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
211
|
+
env
|
|
212
|
+
}).trim();
|
|
213
|
+
return result || void 0;
|
|
214
|
+
} catch {
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
const itemName = ref.id.replace(/^\//, "");
|
|
218
|
+
const vault = getOpVault();
|
|
219
|
+
try {
|
|
220
|
+
const result = execFileSync("op", [
|
|
221
|
+
"item",
|
|
222
|
+
"get",
|
|
223
|
+
itemName,
|
|
224
|
+
"--vault",
|
|
225
|
+
vault,
|
|
226
|
+
"--fields",
|
|
227
|
+
"credential",
|
|
228
|
+
"--format",
|
|
229
|
+
"json"
|
|
230
|
+
], {
|
|
231
|
+
encoding: "utf-8",
|
|
232
|
+
timeout: 15e3,
|
|
233
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
234
|
+
env
|
|
235
|
+
}).trim();
|
|
236
|
+
if (result) {
|
|
237
|
+
try {
|
|
238
|
+
const parsed = JSON.parse(result);
|
|
239
|
+
const field = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
240
|
+
const value = field?.value ?? field;
|
|
241
|
+
if (typeof value === "string" && value.length > 0) {
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
} catch {
|
|
245
|
+
if (result.length > 0 && !result.startsWith("{") && !result.startsWith("[")) {
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
} catch {
|
|
251
|
+
}
|
|
252
|
+
}
|
|
174
253
|
const secretsDir = path.join(os.homedir(), ".openclaw", "secrets");
|
|
175
254
|
const filePath = path.join(secretsDir, ref.id.replace(/^\//, ""));
|
|
176
255
|
if (existsSync(filePath)) {
|
|
@@ -179,15 +258,6 @@ function resolveFileSecret(ref) {
|
|
|
179
258
|
} catch {
|
|
180
259
|
}
|
|
181
260
|
}
|
|
182
|
-
try {
|
|
183
|
-
const result = execFileSync("op", ["read", ref.id], {
|
|
184
|
-
encoding: "utf-8",
|
|
185
|
-
timeout: 1e4,
|
|
186
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
187
|
-
}).trim();
|
|
188
|
-
return result || void 0;
|
|
189
|
-
} catch {
|
|
190
|
-
}
|
|
191
261
|
} else {
|
|
192
262
|
const filePath = path.isAbsolute(ref.id) ? ref.id : path.join(os.homedir(), ".openclaw", "secrets", ref.id.replace(/^\//, ""));
|
|
193
263
|
if (existsSync(filePath)) {
|
|
@@ -597,4 +667,4 @@ export {
|
|
|
597
667
|
buildChatCompletionTokenLimit,
|
|
598
668
|
FallbackLlmClient
|
|
599
669
|
};
|
|
600
|
-
//# sourceMappingURL=chunk-
|
|
670
|
+
//# sourceMappingURL=chunk-KIA3HVQD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/json-extract.ts","../src/openai-chat-compat.ts","../src/resolve-provider-secret.ts","../src/fallback-llm.ts"],"sourcesContent":["/**\n * Utilities for extracting JSON payloads from LLM outputs.\n *\n * We see common failure modes:\n * - \"Here's an example: {..}\\nHere's the real answer: {..}\" (multiple JSON blocks)\n * - fenced ```json blocks\n * - leading/trailing prose around JSON\n *\n * These helpers attempt multiple candidates and let callers validate with schemas.\n */\n\nexport function stripCodeFences(text: string): string {\n return text.replace(/```(?:json)?\\s*([\\s\\S]*?)```/gi, (_m, inner) => String(inner).trim());\n}\n\nexport function extractJsonCandidates(text: string): string[] {\n const trimmed = text.trim();\n const cleaned = stripCodeFences(trimmed);\n const candidates: string[] = [];\n\n if (cleaned.length > 0) candidates.push(cleaned);\n candidates.push(...scanBalancedJsonBlocks(cleaned));\n\n // Legacy regex fallback (single object)\n const objMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (objMatch) candidates.push(objMatch[0]);\n\n const seen = new Set<string>();\n return candidates\n .map((c) => c.trim())\n .filter((c) => c.length > 0)\n .filter((c) => {\n if (seen.has(c)) return false;\n seen.add(c);\n return true;\n });\n}\n\nfunction scanBalancedJsonBlocks(text: string): string[] {\n const out: string[] = [];\n const opens = new Set([\"{\", \"[\"]);\n const closes: Record<string, string> = { \"{\": \"}\", \"[\": \"]\" };\n\n for (let i = 0; i < text.length; i++) {\n const start = text[i];\n if (!opens.has(start)) continue;\n\n const expectedClose = closes[start];\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (let j = i; j < text.length; j++) {\n const ch = text[j];\n\n if (inString) {\n if (escape) {\n escape = false;\n } else if (ch === \"\\\\\") {\n escape = true;\n } else if (ch === \"\\\"\") {\n inString = false;\n }\n continue;\n }\n\n if (ch === \"\\\"\") {\n inString = true;\n continue;\n }\n\n if (ch === start) depth++;\n if (ch === expectedClose) depth--;\n\n if (depth === 0) {\n out.push(text.slice(i, j + 1).trim());\n i = j;\n break;\n }\n }\n }\n\n return out;\n}\n\n","function normalizedModel(model: string): string {\n return model.trim().toLowerCase();\n}\n\nfunction matchesModelFamily(normalized: string, familyPattern: RegExp): boolean {\n return familyPattern.test(normalized);\n}\n\nexport function shouldAssumeOpenAiChatCompletions(baseUrl?: string): boolean {\n if (!baseUrl) return true;\n try {\n return new URL(baseUrl).hostname.toLowerCase() === \"api.openai.com\";\n } catch {\n return false;\n }\n}\n\nexport function usesMaxCompletionTokens(model: string, options?: { assumeOpenAI?: boolean }): boolean {\n const normalized = normalizedModel(model);\n if (options?.assumeOpenAI !== true) return false;\n if (matchesModelFamily(normalized, /^gpt-5(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^gpt-4o(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^gpt-4\\.1(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^o1(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^o3(?:$|[-.])/)) return true;\n return matchesModelFamily(normalized, /^o4-mini(?:$|[-.])/);\n}\n\nexport function buildChatCompletionTokenLimit(\n model: string,\n maxTokens: number,\n options?: { assumeOpenAI?: boolean },\n): { max_tokens: number } | { max_completion_tokens: number } {\n const safeMaxTokens = Math.max(0, Math.floor(maxTokens));\n if (usesMaxCompletionTokens(model, options)) {\n return { max_completion_tokens: safeMaxTokens };\n }\n return { max_tokens: safeMaxTokens };\n}\n","import { log } from \"./logger.js\";\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\n/**\n * Secret reference object format used by OpenClaw's models.json.\n */\ninterface SecretRef {\n source: \"exec\" | \"file\" | \"env\";\n provider?: string;\n id: string;\n command?: string;\n args?: string[];\n}\n\n/**\n * Auth profile entry from agent auth-profiles.json files.\n */\ninterface AuthProfile {\n type?: string;\n provider?: string;\n token?: string | SecretRef;\n access?: string;\n apiKey?: string;\n}\n\nconst resolvedCache = new Map<string, string | null>();\nconst DEFAULT_OP_VAULT = \"OpenClaw\";\nconst OP_SERVICE_ACCOUNT_TOKEN_PATH = path.join(os.homedir(), \".openclaw\", \"secrets\", \"op-service-account-token\");\nconst OP_VAULT_PATH = path.join(os.homedir(), \".openclaw\", \"secrets\", \"op-vault-name\");\n\nfunction getOpVault(): string {\n try {\n if (existsSync(OP_VAULT_PATH)) {\n const vault = readFileSync(OP_VAULT_PATH, \"utf-8\").trim();\n if (vault) return vault;\n }\n } catch { /* silent */ }\n return process.env.OP_VAULT ?? DEFAULT_OP_VAULT;\n}\n\n/**\n * Build an env object with the 1Password service account token set,\n * so op CLI works without desktop app integration.\n */\nfunction buildOpEnv(): NodeJS.ProcessEnv {\n // If already set in env, use it\n if (process.env.OP_SERVICE_ACCOUNT_TOKEN) {\n return process.env;\n }\n // Read from the standard OpenClaw secrets file\n try {\n if (existsSync(OP_SERVICE_ACCOUNT_TOKEN_PATH)) {\n const token = readFileSync(OP_SERVICE_ACCOUNT_TOKEN_PATH, \"utf-8\").trim();\n if (token) {\n return { ...process.env, OP_SERVICE_ACCOUNT_TOKEN: token };\n }\n }\n } catch {\n // Silent — fall through to default env\n }\n return process.env;\n}\n\n/**\n * Resolve a provider API key from various OpenClaw secret formats.\n *\n * Supported formats:\n * - Plain string (not a marker) → used as-is\n * - SecretRef object (`{ source, provider, id }`) → resolved via exec/file/env\n * - `\"secretref-managed\"` → looked up from auth profiles and openclaw.json auth config\n * - `\"minimax-oauth\"`, `\"ollama-local\"`, etc. → treated as non-secret markers, skipped\n *\n * Results are cached per provider to avoid repeated exec calls.\n */\nexport async function resolveProviderApiKey(\n providerId: string,\n apiKeyValue: unknown,\n gatewayConfig?: { auth?: { profiles?: Record<string, unknown> } },\n): Promise<string | undefined> {\n // Fast path: plain string that isn't a marker\n if (typeof apiKeyValue === \"string\") {\n if (apiKeyValue === \"secretref-managed\") {\n return resolveSecretRefManaged(providerId, gatewayConfig);\n }\n // Known non-secret markers — skip\n if (\n apiKeyValue.endsWith(\"-oauth\") ||\n apiKeyValue.endsWith(\"-local\") ||\n apiKeyValue === \"lm-studio\" ||\n apiKeyValue.startsWith(\"gcp-\")\n ) {\n return undefined;\n }\n // Looks like an actual key\n return apiKeyValue;\n }\n\n // SecretRef object\n if (isSecretRefObject(apiKeyValue)) {\n return resolveSecretRef(providerId, apiKeyValue as SecretRef);\n }\n\n return undefined;\n}\n\nfunction isSecretRefObject(value: unknown): value is SecretRef {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"source\" in value &&\n \"id\" in value &&\n typeof (value as SecretRef).source === \"string\" &&\n typeof (value as SecretRef).id === \"string\"\n );\n}\n\nasync function resolveSecretRef(\n providerId: string,\n ref: SecretRef,\n): Promise<string | undefined> {\n const cacheKey = `ref:${ref.source}:${ref.provider ?? \"\"}:${ref.id}:${ref.command ?? \"\"}:${(ref.args ?? []).join(\",\")}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined) {\n // Don't cache failures permanently — only cache successes\n if (cached !== null) return cached;\n }\n\n let resolved: string | undefined;\n\n try {\n switch (ref.source) {\n case \"exec\":\n resolved = resolveExecSecret(ref);\n break;\n case \"file\":\n resolved = resolveFileSecret(ref);\n break;\n case \"env\":\n resolved = process.env[ref.id] ?? undefined;\n break;\n }\n } catch (err) {\n log.warn(\n `secret resolution failed for provider \"${providerId}\" (${ref.source}/${ref.provider}): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Only cache successful resolutions; failures are retried next time\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n }\n\n if (resolved) {\n log.debug(`resolved API key for provider \"${providerId}\" via ${ref.source}/${ref.provider ?? \"default\"}`);\n }\n\n return resolved;\n}\n\nfunction resolveExecSecret(ref: SecretRef): string | undefined {\n const command = ref.command ?? (ref.provider === \"op\" ? \"op\" : undefined);\n if (!command) {\n log.warn(`exec secret ref has no command and provider \"${ref.provider}\" is not a known exec provider`);\n return undefined;\n }\n\n // Use execFileSync (not execSync) to avoid shell injection —\n // arguments are passed as an array, never interpolated into a shell string.\n const args = ref.args ?? (ref.provider === \"op\" ? [\"read\", ref.id] : [ref.id]);\n const env = ref.provider === \"op\" ? buildOpEnv() : process.env;\n try {\n const result = execFileSync(command, args, {\n encoding: \"utf-8\",\n timeout: 15_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env,\n }).trim();\n return result || undefined;\n } catch (err) {\n log.warn(`exec secret resolution failed (${command}): ${err instanceof Error ? err.message : String(err)}`);\n return undefined;\n }\n}\n\nfunction resolveFileSecret(ref: SecretRef): string | undefined {\n if (ref.provider === \"op\") {\n // OpenClaw's auto-migrate-secrets stores API keys as 1Password items.\n // ref.id can be:\n // - An item title (e.g., \"/agent-models-fireworks-apiKey\") → use `op item get`\n // - An op:// URI (e.g., \"op://vault/item/field\") → use `op read`\n const env = buildOpEnv();\n\n if (ref.id.startsWith(\"op://\")) {\n // Direct op:// secret reference — use `op read`\n try {\n const result = execFileSync(\"op\", [\"read\", ref.id], {\n encoding: \"utf-8\",\n timeout: 15_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env,\n }).trim();\n return result || undefined;\n } catch {\n // Silent — op may not be available\n }\n } else {\n // Item title — use `op item get` with vault\n const itemName = ref.id.replace(/^\\//, \"\");\n const vault = getOpVault();\n try {\n const result = execFileSync(\"op\", [\n \"item\", \"get\", itemName,\n \"--vault\", vault,\n \"--fields\", \"credential\",\n \"--format\", \"json\",\n ], {\n encoding: \"utf-8\",\n timeout: 15_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env,\n }).trim();\n if (result) {\n try {\n const parsed = JSON.parse(result);\n // op returns various shapes:\n // - Single field object: {\"value\": \"sk-...\", ...}\n // - Array of field objects: [{\"value\": \"sk-...\", ...}]\n // - Plain string (older op versions)\n const field = Array.isArray(parsed) ? parsed[0] : parsed;\n const value = field?.value ?? field;\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n } catch {\n if (result.length > 0 && !result.startsWith(\"{\") && !result.startsWith(\"[\")) {\n return result;\n }\n }\n }\n } catch {\n // Silent — op may not be available or item not found\n }\n }\n\n // Fallback: try reading from a local secrets file\n const secretsDir = path.join(os.homedir(), \".openclaw\", \"secrets\");\n const filePath = path.join(secretsDir, ref.id.replace(/^\\//, \"\"));\n if (existsSync(filePath)) {\n try {\n return readFileSync(filePath, \"utf-8\").trim() || undefined;\n } catch {\n // Silent\n }\n }\n } else {\n // Non-OP file provider: treat ref.id as a file path (absolute or relative to secrets dir)\n const filePath = path.isAbsolute(ref.id)\n ? ref.id\n : path.join(os.homedir(), \".openclaw\", \"secrets\", ref.id.replace(/^\\//, \"\"));\n if (existsSync(filePath)) {\n try {\n return readFileSync(filePath, \"utf-8\").trim() || undefined;\n } catch {\n // Silent\n }\n }\n }\n\n return undefined;\n}\n\nfunction resolveSecretRefManaged(\n providerId: string,\n gatewayConfig?: { auth?: { profiles?: Record<string, unknown> } },\n): string | undefined {\n const cacheKey = `managed:${providerId}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n let resolved: string | undefined;\n\n // Look up auth profiles for this provider\n const profiles = gatewayConfig?.auth?.profiles;\n if (profiles) {\n // Try provider:default, provider:manual, etc.\n const candidates = [\n `${providerId}:default`,\n `${providerId}:manual`,\n providerId,\n ];\n\n for (const profileKey of candidates) {\n const raw = profiles[profileKey];\n if (!raw || typeof raw !== \"object\") continue;\n const profile = raw as AuthProfile;\n\n // Token-based auth\n if (profile.token) {\n if (typeof profile.token === \"string\" && !profile.token.startsWith(\"{\")) {\n resolved = profile.token;\n break;\n }\n if (isSecretRefObject(profile.token)) {\n // Synchronously resolve — this is at init time\n try {\n resolved = resolveSecretRefSync(providerId, profile.token as SecretRef);\n } catch {\n // Continue to next profile\n }\n if (resolved) break;\n }\n }\n\n // API key auth\n if (profile.apiKey && typeof profile.apiKey === \"string\") {\n resolved = profile.apiKey;\n break;\n }\n\n // Access token (OAuth)\n if (profile.access && typeof profile.access === \"string\") {\n resolved = profile.access;\n break;\n }\n }\n }\n\n // Fall back to environment variables\n if (!resolved) {\n const envCandidates = [\n `${providerId.toUpperCase().replace(/-/g, \"_\")}_API_KEY`,\n `${providerId.toUpperCase().replace(/-/g, \"_\")}_TOKEN`,\n ];\n for (const envVar of envCandidates) {\n if (process.env[envVar]) {\n resolved = process.env[envVar];\n break;\n }\n }\n }\n\n // Only cache successful resolutions; failures are retried next time\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n log.debug(`resolved managed API key for provider \"${providerId}\" via auth profile`);\n } else {\n log.debug(`could not resolve managed API key for provider \"${providerId}\"`);\n }\n\n return resolved;\n}\n\nfunction resolveSecretRefSync(\n providerId: string,\n ref: SecretRef,\n): string | undefined {\n const cacheKey = `ref:${ref.source}:${ref.provider ?? \"\"}:${ref.id}:${ref.command ?? \"\"}:${(ref.args ?? []).join(\",\")}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n let resolved: string | undefined;\n\n try {\n switch (ref.source) {\n case \"exec\":\n resolved = resolveExecSecret(ref);\n break;\n case \"file\":\n resolved = resolveFileSecret(ref);\n break;\n case \"env\":\n resolved = process.env[ref.id] ?? undefined;\n break;\n }\n } catch (err) {\n log.warn(\n `sync secret resolution failed for provider \"${providerId}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n }\n return resolved;\n}\n\n/**\n * Clear the resolution cache (useful for testing or key rotation).\n */\nexport function clearSecretCache(): void {\n resolvedCache.clear();\n}\n","import { log } from \"./logger.js\";\nimport type { GatewayConfig, ModelProviderConfig, AgentPersona } from \"./types.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport {\n buildChatCompletionTokenLimit,\n shouldAssumeOpenAiChatCompletions,\n} from \"./openai-chat-compat.js\";\nimport { resolveProviderApiKey } from \"./resolve-provider-secret.js\";\n\nexport interface FallbackLlmOptions {\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n /** Override which agent persona's model chain to use (by ID from agents.list[]). */\n agentId?: string;\n}\n\nexport interface FallbackLlmResponse {\n content: string;\n modelUsed: string;\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n };\n}\n\ninterface ModelRef {\n providerId: string;\n modelId: string;\n providerConfig: ModelProviderConfig;\n modelString: string;\n}\n\n/**\n * Generic fallback LLM client that uses the gateway's default AI configuration\n * and walks through the full fallback chain (primary + fallbacks).\n * Supports OpenAI and Anthropic API formats.\n */\nexport class FallbackLlmClient {\n private gatewayConfig: GatewayConfig | undefined;\n\n constructor(gatewayConfig?: GatewayConfig) {\n this.gatewayConfig = gatewayConfig;\n }\n\n /**\n * Check if fallback is available (gateway config has at least one model).\n */\n isAvailable(agentId?: string): boolean {\n const models = this.getModelChain(agentId);\n return models.length > 0;\n }\n\n /**\n * Make a chat completion request using the gateway's default AI chain.\n * Tries primary first, then each fallback in order.\n * When agentId is provided, uses that agent persona's model chain instead of defaults.\n */\n async chatCompletion(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions = {},\n ): Promise<FallbackLlmResponse | null> {\n const models = this.getModelChain(options.agentId);\n if (models.length === 0) {\n log.warn(\"fallback LLM: no models configured in gateway\");\n return null;\n }\n\n const runChain = async (): Promise<FallbackLlmResponse | null> => {\n // Try each model in the chain\n for (let i = 0; i < models.length; i++) {\n const model = models[i];\n const isFallback = i > 0;\n\n try {\n const result = await this.tryModel(model, messages, options);\n if (result) {\n if (isFallback) {\n log.info(`fallback LLM: succeeded using ${model.modelString} (fallback ${i})`);\n }\n return {\n content: result.content,\n modelUsed: model.modelString,\n usage: result.usage,\n };\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n log.debug(`fallback LLM: ${model.modelString} failed (${errorMsg}), trying next...`);\n // Continue to next model in chain\n }\n }\n\n log.warn(`fallback LLM: all ${models.length} models in chain failed`);\n return null;\n };\n\n if (typeof options.timeoutMs === \"number\") {\n if (options.timeoutMs <= 0) {\n log.warn(\"fallback LLM: timed out before request started\");\n return null;\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n runChain(),\n new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => {\n log.warn(`fallback LLM: timed out after ${options.timeoutMs}ms`);\n resolve(null);\n }, options.timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n return await runChain();\n }\n\n /**\n * Make a request with structured output (Zod schema).\n * Returns parsed JSON or null on failure.\n */\n async parseWithSchema<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<T | null> {\n const detailed = await this.parseWithSchemaDetailed(messages, schema, options);\n return detailed?.result ?? null;\n }\n\n /**\n * Like parseWithSchema but also returns the model that was used,\n * so callers can emit accurate trace events.\n */\n async parseWithSchemaDetailed<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<{ result: T; modelUsed: string } | null> {\n const response = await this.chatCompletion(messages, options);\n if (!response?.content) return null;\n\n try {\n const candidates = extractJsonCandidates(response.content);\n for (const c of candidates) {\n try {\n const parsed = JSON.parse(c);\n return { result: schema.parse(parsed), modelUsed: response.modelUsed };\n } catch {\n // keep trying other candidates\n }\n }\n return null;\n } catch (err) {\n log.warn(\"fallback LLM: failed to parse structured output:\", err);\n return null;\n }\n }\n\n /**\n * Get the full model chain from gateway config.\n * Returns array of models in order: [primary, fallback1, fallback2, ...]\n *\n * When agentId is provided, looks up the matching entry in agents.list[]\n * and uses that persona's model chain. Falls back to agents.defaults.model\n * if agentId is not found or not provided.\n */\n private getModelChain(agentId?: string): ModelRef[] {\n const chain: ModelRef[] = [];\n const providers = this.gatewayConfig?.models?.providers;\n\n if (!providers) return chain;\n\n // Resolve the model config: agent persona chain or global defaults\n let modelConfig: { primary?: string; fallbacks?: string[] } | undefined;\n\n if (agentId) {\n const persona = this.gatewayConfig?.agents?.list?.find(\n (a) => a.id === agentId,\n );\n if (persona?.model) {\n modelConfig = persona.model;\n log.debug(`fallback LLM: using agent persona \"${agentId}\" model chain`);\n } else {\n log.warn(\n `fallback LLM: agent persona \"${agentId}\" not found or has no model config, falling back to defaults`,\n );\n }\n }\n\n if (!modelConfig) {\n modelConfig = this.gatewayConfig?.agents?.defaults?.model;\n }\n\n // Build list of model strings: primary + fallbacks\n const modelStrings: string[] = [];\n\n if (modelConfig?.primary) {\n modelStrings.push(modelConfig.primary);\n }\n\n if (Array.isArray(modelConfig?.fallbacks)) {\n for (const fb of modelConfig.fallbacks) {\n if (typeof fb === \"string\" && !modelStrings.includes(fb)) {\n modelStrings.push(fb);\n }\n }\n }\n\n // Parse each model string and look up provider config\n for (const modelString of modelStrings) {\n const modelRef = this.parseModelString(modelString, providers);\n if (modelRef) {\n chain.push(modelRef);\n }\n }\n\n return chain;\n }\n\n /**\n * Parse a \"provider/model\" string and look up its config.\n */\n private parseModelString(\n modelString: string,\n providers: Record<string, ModelProviderConfig>,\n ): ModelRef | null {\n // Parse \"provider/model\" format (e.g., \"openai/gpt-5.2\", \"anthropic/claude-opus-4-6\")\n const parts = modelString.split(\"/\");\n if (parts.length < 2) {\n log.warn(`fallback LLM: invalid model format: ${modelString}`);\n return null;\n }\n\n const providerId = parts[0];\n const modelId = parts.slice(1).join(\"/\"); // Handle cases like \"openai/gpt-5.2-turbo\"\n\n const providerConfig = providers[providerId];\n if (!providerConfig) {\n log.warn(`fallback LLM: provider not found: ${providerId}`);\n return null;\n }\n\n return { providerId, modelId, providerConfig, modelString };\n }\n\n /**\n * Resolve the API key for a provider, handling OpenClaw secret ref formats.\n * Results are cached per provider so exec calls only happen once.\n */\n private async resolveApiKey(\n providerId: string,\n providerConfig: ModelProviderConfig,\n ): Promise<string | undefined> {\n return resolveProviderApiKey(\n providerId,\n providerConfig.apiKey,\n this.gatewayConfig as { auth?: { profiles?: Record<string, unknown> } } | undefined,\n );\n }\n\n /**\n * Try to call a single model.\n */\n private async tryModel(\n model: ModelRef,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n // Resolve the API key from secret refs before making the call.\n // If the raw key looks like an unresolved secret ref and resolution fails,\n // skip this provider entirely so the chain falls through to the next.\n const rawKey = model.providerConfig.apiKey;\n const needsResolution = rawKey === \"secretref-managed\"\n || (typeof rawKey === \"object\" && rawKey !== null);\n const resolvedApiKey = await this.resolveApiKey(model.providerId, model.providerConfig);\n\n if (needsResolution && !resolvedApiKey) {\n throw new Error(`API key for provider \"${model.providerId}\" could not be resolved from secret ref`);\n }\n\n const configWithResolvedKey = resolvedApiKey\n ? { ...model.providerConfig, apiKey: resolvedApiKey }\n : model.providerConfig;\n\n switch (model.providerConfig.api) {\n case \"anthropic-messages\":\n return await this.callAnthropic(configWithResolvedKey, model.modelId, messages, options);\n case \"openai-completions\":\n default:\n return await this.callOpenAI(\n configWithResolvedKey,\n model.modelId,\n messages,\n options,\n shouldAssumeOpenAiChatCompletions(model.providerConfig.baseUrl),\n );\n }\n }\n\n /**\n * Call OpenAI-compatible API.\n */\n private async callOpenAI(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n assumeOpenAI: boolean,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/chat/completions`\n : `${base}/v1/chat/completions`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n\n // Handle auth — apiKey is already resolved to a string by tryModel()\n if (config.apiKey && typeof config.apiKey === \"string\") {\n if (config.authHeader !== false) {\n headers[\"Authorization\"] = `Bearer ${config.apiKey}`;\n }\n }\n\n const body = {\n model: modelId,\n messages,\n temperature: options.temperature ?? 0.3,\n ...buildChatCompletionTokenLimit(modelId, options.maxTokens ?? 4096, {\n assumeOpenAI,\n }),\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n choices: Array<{\n message: {\n content: string;\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"Empty response from OpenAI API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Call Anthropic Messages API.\n */\n private async callAnthropic(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const url = `${config.baseUrl.replace(/\\/$/, \"\")}/messages`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n ...config.headers,\n };\n\n // Handle auth - Anthropic uses x-api-key header (apiKey resolved by tryModel)\n if (config.apiKey && typeof config.apiKey === \"string\") {\n headers[\"x-api-key\"] = config.apiKey;\n }\n\n // Extract system message (Anthropic handles it separately)\n const systemMessage = messages.find((m) => m.role === \"system\")?.content;\n const nonSystemMessages = messages.filter((m) => m.role !== \"system\");\n\n // Convert messages to Anthropic format\n const anthropicMessages = nonSystemMessages.map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const body: Record<string, unknown> = {\n model: modelId,\n messages: anthropicMessages,\n max_tokens: options.maxTokens ?? 4096,\n temperature: options.temperature ?? 0.3,\n };\n\n if (systemMessage) {\n body.system = systemMessage;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Anthropic API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n content: Array<{\n type: string;\n text: string;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const content = data.content?.[0]?.text;\n if (!content) {\n throw new Error(\"Empty response from Anthropic API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: (data.usage.input_tokens ?? 0) + (data.usage.output_tokens ?? 0),\n }\n : undefined,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
CompoundingEngine,
|
|
4
4
|
SharedContextManager,
|
|
5
5
|
defaultTierMigrationCycleBudget
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OLJAEA5I.js";
|
|
7
7
|
import {
|
|
8
8
|
searchCausalTrajectories
|
|
9
9
|
} from "./chunk-IMMYYNXG.js";
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
buildChatCompletionTokenLimit,
|
|
37
37
|
extractJsonCandidates,
|
|
38
38
|
shouldAssumeOpenAiChatCompletions
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-KIA3HVQD.js";
|
|
40
40
|
import {
|
|
41
41
|
BoxBuilder,
|
|
42
42
|
assertIsoRecordedAt,
|
|
@@ -22309,7 +22309,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
22309
22309
|
);
|
|
22310
22310
|
return result;
|
|
22311
22311
|
}
|
|
22312
|
-
const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-
|
|
22312
|
+
const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-46JU5PST.js");
|
|
22313
22313
|
const useGateway = this.config.modelSource === "gateway";
|
|
22314
22314
|
const modelSetting = this.config.semanticConsolidationModel;
|
|
22315
22315
|
if (modelSetting === "fast" && this.fastLlm && !useGateway) {
|
|
@@ -24546,7 +24546,7 @@ ${trimmedBody}`;
|
|
|
24546
24546
|
return null;
|
|
24547
24547
|
}
|
|
24548
24548
|
try {
|
|
24549
|
-
const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-
|
|
24549
|
+
const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-OOOYE2ID.js");
|
|
24550
24550
|
const rules = await getCalibrationRulesForRecall(this.config.memoryDir);
|
|
24551
24551
|
if (rules.length === 0) {
|
|
24552
24552
|
recordRecallSectionMetric({
|
|
@@ -31534,4 +31534,4 @@ export {
|
|
|
31534
31534
|
EngramAccessInputError,
|
|
31535
31535
|
EngramAccessService
|
|
31536
31536
|
};
|
|
31537
|
-
//# sourceMappingURL=chunk-
|
|
31537
|
+
//# sourceMappingURL=chunk-KZMICTC7.js.map
|
|
@@ -830,7 +830,7 @@ var CompoundingEngine = class {
|
|
|
830
830
|
let promotionCandidates = this.config.compoundingSemanticEnabled ? this.derivePromotionCandidates(outcomeSummary, mistakes.registry, rubrics) : [];
|
|
831
831
|
if (this.config.cmcConsolidationEnabled) {
|
|
832
832
|
try {
|
|
833
|
-
const { deriveCausalPromotionCandidates } = await import("./causal-consolidation-
|
|
833
|
+
const { deriveCausalPromotionCandidates } = await import("./causal-consolidation-BDMZMX2D.js");
|
|
834
834
|
const causalCandidates = await deriveCausalPromotionCandidates({
|
|
835
835
|
memoryDir: this.config.memoryDir,
|
|
836
836
|
causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,
|
|
@@ -851,7 +851,7 @@ var CompoundingEngine = class {
|
|
|
851
851
|
}
|
|
852
852
|
if (this.config.calibrationEnabled) {
|
|
853
853
|
try {
|
|
854
|
-
const { runCalibrationConsolidation } = await import("./calibration-
|
|
854
|
+
const { runCalibrationConsolidation } = await import("./calibration-OOOYE2ID.js");
|
|
855
855
|
const calRules = await runCalibrationConsolidation({
|
|
856
856
|
memoryDir: this.config.memoryDir,
|
|
857
857
|
gatewayConfig: this.config.gatewayConfig,
|
|
@@ -1839,4 +1839,4 @@ export {
|
|
|
1839
1839
|
defaultTierMigrationCycleBudget,
|
|
1840
1840
|
CompoundingEngine
|
|
1841
1841
|
};
|
|
1842
|
-
//# sourceMappingURL=chunk-
|
|
1842
|
+
//# sourceMappingURL=chunk-OLJAEA5I.js.map
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CompoundingEngine,
|
|
4
4
|
defaultTierMigrationCycleBudget
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OLJAEA5I.js";
|
|
6
6
|
import "./chunk-DTCQ2KEX.js";
|
|
7
7
|
import "./chunk-SSIIJJKA.js";
|
|
8
8
|
export {
|
|
9
9
|
CompoundingEngine,
|
|
10
10
|
defaultTierMigrationCycleBudget
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=engine-
|
|
12
|
+
//# sourceMappingURL=engine-63EMTVP7.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// openclaw-engram: Local-first memory plugin
|
|
2
2
|
import {
|
|
3
3
|
FallbackLlmClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KIA3HVQD.js";
|
|
5
5
|
import "./chunk-SSIIJJKA.js";
|
|
6
6
|
export {
|
|
7
7
|
FallbackLlmClient
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=fallback-llm-
|
|
9
|
+
//# sourceMappingURL=fallback-llm-46JU5PST.js.map
|
package/dist/index.js
CHANGED
|
@@ -83,8 +83,8 @@ import {
|
|
|
83
83
|
validateRouteTarget,
|
|
84
84
|
validateWorkProductLedgerEntry,
|
|
85
85
|
wrapWorkLayerContext
|
|
86
|
-
} from "./chunk-
|
|
87
|
-
import "./chunk-
|
|
86
|
+
} from "./chunk-KZMICTC7.js";
|
|
87
|
+
import "./chunk-OLJAEA5I.js";
|
|
88
88
|
import {
|
|
89
89
|
getCausalTrajectoryStoreStatus
|
|
90
90
|
} from "./chunk-IMMYYNXG.js";
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
import {
|
|
112
112
|
analyzeGraphHealth
|
|
113
113
|
} from "./chunk-6KX4XLQJ.js";
|
|
114
|
-
import "./chunk-
|
|
114
|
+
import "./chunk-KIA3HVQD.js";
|
|
115
115
|
import {
|
|
116
116
|
assertIsoRecordedAt,
|
|
117
117
|
assertSafePathSegment,
|
|
@@ -9441,7 +9441,7 @@ async function runSemanticRulePromoteCliCommand(options) {
|
|
|
9441
9441
|
});
|
|
9442
9442
|
}
|
|
9443
9443
|
async function runCompoundingPromoteCliCommand(options) {
|
|
9444
|
-
const { CompoundingEngine } = await import("./engine-
|
|
9444
|
+
const { CompoundingEngine } = await import("./engine-63EMTVP7.js");
|
|
9445
9445
|
const config = parseConfig({
|
|
9446
9446
|
memoryDir: options.memoryDir,
|
|
9447
9447
|
qmdEnabled: false,
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/json-extract.ts","../src/openai-chat-compat.ts","../src/resolve-provider-secret.ts","../src/fallback-llm.ts"],"sourcesContent":["/**\n * Utilities for extracting JSON payloads from LLM outputs.\n *\n * We see common failure modes:\n * - \"Here's an example: {..}\\nHere's the real answer: {..}\" (multiple JSON blocks)\n * - fenced ```json blocks\n * - leading/trailing prose around JSON\n *\n * These helpers attempt multiple candidates and let callers validate with schemas.\n */\n\nexport function stripCodeFences(text: string): string {\n return text.replace(/```(?:json)?\\s*([\\s\\S]*?)```/gi, (_m, inner) => String(inner).trim());\n}\n\nexport function extractJsonCandidates(text: string): string[] {\n const trimmed = text.trim();\n const cleaned = stripCodeFences(trimmed);\n const candidates: string[] = [];\n\n if (cleaned.length > 0) candidates.push(cleaned);\n candidates.push(...scanBalancedJsonBlocks(cleaned));\n\n // Legacy regex fallback (single object)\n const objMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (objMatch) candidates.push(objMatch[0]);\n\n const seen = new Set<string>();\n return candidates\n .map((c) => c.trim())\n .filter((c) => c.length > 0)\n .filter((c) => {\n if (seen.has(c)) return false;\n seen.add(c);\n return true;\n });\n}\n\nfunction scanBalancedJsonBlocks(text: string): string[] {\n const out: string[] = [];\n const opens = new Set([\"{\", \"[\"]);\n const closes: Record<string, string> = { \"{\": \"}\", \"[\": \"]\" };\n\n for (let i = 0; i < text.length; i++) {\n const start = text[i];\n if (!opens.has(start)) continue;\n\n const expectedClose = closes[start];\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (let j = i; j < text.length; j++) {\n const ch = text[j];\n\n if (inString) {\n if (escape) {\n escape = false;\n } else if (ch === \"\\\\\") {\n escape = true;\n } else if (ch === \"\\\"\") {\n inString = false;\n }\n continue;\n }\n\n if (ch === \"\\\"\") {\n inString = true;\n continue;\n }\n\n if (ch === start) depth++;\n if (ch === expectedClose) depth--;\n\n if (depth === 0) {\n out.push(text.slice(i, j + 1).trim());\n i = j;\n break;\n }\n }\n }\n\n return out;\n}\n\n","function normalizedModel(model: string): string {\n return model.trim().toLowerCase();\n}\n\nfunction matchesModelFamily(normalized: string, familyPattern: RegExp): boolean {\n return familyPattern.test(normalized);\n}\n\nexport function shouldAssumeOpenAiChatCompletions(baseUrl?: string): boolean {\n if (!baseUrl) return true;\n try {\n return new URL(baseUrl).hostname.toLowerCase() === \"api.openai.com\";\n } catch {\n return false;\n }\n}\n\nexport function usesMaxCompletionTokens(model: string, options?: { assumeOpenAI?: boolean }): boolean {\n const normalized = normalizedModel(model);\n if (options?.assumeOpenAI !== true) return false;\n if (matchesModelFamily(normalized, /^gpt-5(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^gpt-4o(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^gpt-4\\.1(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^o1(?:$|[-.])/)) return true;\n if (matchesModelFamily(normalized, /^o3(?:$|[-.])/)) return true;\n return matchesModelFamily(normalized, /^o4-mini(?:$|[-.])/);\n}\n\nexport function buildChatCompletionTokenLimit(\n model: string,\n maxTokens: number,\n options?: { assumeOpenAI?: boolean },\n): { max_tokens: number } | { max_completion_tokens: number } {\n const safeMaxTokens = Math.max(0, Math.floor(maxTokens));\n if (usesMaxCompletionTokens(model, options)) {\n return { max_completion_tokens: safeMaxTokens };\n }\n return { max_tokens: safeMaxTokens };\n}\n","import { log } from \"./logger.js\";\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\n/**\n * Secret reference object format used by OpenClaw's models.json.\n */\ninterface SecretRef {\n source: \"exec\" | \"file\" | \"env\";\n provider?: string;\n id: string;\n command?: string;\n args?: string[];\n}\n\n/**\n * Auth profile entry from agent auth-profiles.json files.\n */\ninterface AuthProfile {\n type?: string;\n provider?: string;\n token?: string | SecretRef;\n access?: string;\n apiKey?: string;\n}\n\nconst resolvedCache = new Map<string, string | null>();\n\n/**\n * Resolve a provider API key from various OpenClaw secret formats.\n *\n * Supported formats:\n * - Plain string (not a marker) → used as-is\n * - SecretRef object (`{ source, provider, id }`) → resolved via exec/file/env\n * - `\"secretref-managed\"` → looked up from auth profiles and openclaw.json auth config\n * - `\"minimax-oauth\"`, `\"ollama-local\"`, etc. → treated as non-secret markers, skipped\n *\n * Results are cached per provider to avoid repeated exec calls.\n */\nexport async function resolveProviderApiKey(\n providerId: string,\n apiKeyValue: unknown,\n gatewayConfig?: { auth?: { profiles?: Record<string, unknown> } },\n): Promise<string | undefined> {\n // Fast path: plain string that isn't a marker\n if (typeof apiKeyValue === \"string\") {\n if (apiKeyValue === \"secretref-managed\") {\n return resolveSecretRefManaged(providerId, gatewayConfig);\n }\n // Known non-secret markers — skip\n if (\n apiKeyValue.endsWith(\"-oauth\") ||\n apiKeyValue.endsWith(\"-local\") ||\n apiKeyValue === \"lm-studio\" ||\n apiKeyValue.startsWith(\"gcp-\")\n ) {\n return undefined;\n }\n // Looks like an actual key\n return apiKeyValue;\n }\n\n // SecretRef object\n if (isSecretRefObject(apiKeyValue)) {\n return resolveSecretRef(providerId, apiKeyValue as SecretRef);\n }\n\n return undefined;\n}\n\nfunction isSecretRefObject(value: unknown): value is SecretRef {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"source\" in value &&\n \"id\" in value &&\n typeof (value as SecretRef).source === \"string\" &&\n typeof (value as SecretRef).id === \"string\"\n );\n}\n\nasync function resolveSecretRef(\n providerId: string,\n ref: SecretRef,\n): Promise<string | undefined> {\n const cacheKey = `ref:${ref.source}:${ref.provider ?? \"\"}:${ref.id}:${ref.command ?? \"\"}:${(ref.args ?? []).join(\",\")}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined) {\n // Don't cache failures permanently — only cache successes\n if (cached !== null) return cached;\n }\n\n let resolved: string | undefined;\n\n try {\n switch (ref.source) {\n case \"exec\":\n resolved = resolveExecSecret(ref);\n break;\n case \"file\":\n resolved = resolveFileSecret(ref);\n break;\n case \"env\":\n resolved = process.env[ref.id] ?? undefined;\n break;\n }\n } catch (err) {\n log.warn(\n `secret resolution failed for provider \"${providerId}\" (${ref.source}/${ref.provider}): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Only cache successful resolutions; failures are retried next time\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n }\n\n if (resolved) {\n log.debug(`resolved API key for provider \"${providerId}\" via ${ref.source}/${ref.provider ?? \"default\"}`);\n }\n\n return resolved;\n}\n\nfunction resolveExecSecret(ref: SecretRef): string | undefined {\n const command = ref.command ?? (ref.provider === \"op\" ? \"op\" : undefined);\n if (!command) {\n log.warn(`exec secret ref has no command and provider \"${ref.provider}\" is not a known exec provider`);\n return undefined;\n }\n\n // Use execFileSync (not execSync) to avoid shell injection —\n // arguments are passed as an array, never interpolated into a shell string.\n const args = ref.args ?? (ref.provider === \"op\" ? [\"read\", ref.id] : [ref.id]);\n try {\n const result = execFileSync(command, args, {\n encoding: \"utf-8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n return result || undefined;\n } catch (err) {\n log.warn(`exec secret resolution failed (${command}): ${err instanceof Error ? err.message : String(err)}`);\n return undefined;\n }\n}\n\nfunction resolveFileSecret(ref: SecretRef): string | undefined {\n if (ref.provider === \"op\") {\n // Try reading from the OpenClaw secrets directory\n const secretsDir = path.join(os.homedir(), \".openclaw\", \"secrets\");\n const filePath = path.join(secretsDir, ref.id.replace(/^\\//, \"\"));\n if (existsSync(filePath)) {\n try {\n return readFileSync(filePath, \"utf-8\").trim() || undefined;\n } catch {\n // Fall through to op exec\n }\n }\n\n // Fall back to `op read` via execFileSync (no shell injection)\n try {\n const result = execFileSync(\"op\", [\"read\", ref.id], {\n encoding: \"utf-8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n return result || undefined;\n } catch {\n // Silent — op may not be available\n }\n } else {\n // Non-OP file provider: treat ref.id as a file path (absolute or relative to secrets dir)\n const filePath = path.isAbsolute(ref.id)\n ? ref.id\n : path.join(os.homedir(), \".openclaw\", \"secrets\", ref.id.replace(/^\\//, \"\"));\n if (existsSync(filePath)) {\n try {\n return readFileSync(filePath, \"utf-8\").trim() || undefined;\n } catch {\n // Silent\n }\n }\n }\n\n return undefined;\n}\n\nfunction resolveSecretRefManaged(\n providerId: string,\n gatewayConfig?: { auth?: { profiles?: Record<string, unknown> } },\n): string | undefined {\n const cacheKey = `managed:${providerId}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n let resolved: string | undefined;\n\n // Look up auth profiles for this provider\n const profiles = gatewayConfig?.auth?.profiles;\n if (profiles) {\n // Try provider:default, provider:manual, etc.\n const candidates = [\n `${providerId}:default`,\n `${providerId}:manual`,\n providerId,\n ];\n\n for (const profileKey of candidates) {\n const raw = profiles[profileKey];\n if (!raw || typeof raw !== \"object\") continue;\n const profile = raw as AuthProfile;\n\n // Token-based auth\n if (profile.token) {\n if (typeof profile.token === \"string\" && !profile.token.startsWith(\"{\")) {\n resolved = profile.token;\n break;\n }\n if (isSecretRefObject(profile.token)) {\n // Synchronously resolve — this is at init time\n try {\n resolved = resolveSecretRefSync(providerId, profile.token as SecretRef);\n } catch {\n // Continue to next profile\n }\n if (resolved) break;\n }\n }\n\n // API key auth\n if (profile.apiKey && typeof profile.apiKey === \"string\") {\n resolved = profile.apiKey;\n break;\n }\n\n // Access token (OAuth)\n if (profile.access && typeof profile.access === \"string\") {\n resolved = profile.access;\n break;\n }\n }\n }\n\n // Fall back to environment variables\n if (!resolved) {\n const envCandidates = [\n `${providerId.toUpperCase().replace(/-/g, \"_\")}_API_KEY`,\n `${providerId.toUpperCase().replace(/-/g, \"_\")}_TOKEN`,\n ];\n for (const envVar of envCandidates) {\n if (process.env[envVar]) {\n resolved = process.env[envVar];\n break;\n }\n }\n }\n\n // Only cache successful resolutions; failures are retried next time\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n log.debug(`resolved managed API key for provider \"${providerId}\" via auth profile`);\n } else {\n log.debug(`could not resolve managed API key for provider \"${providerId}\"`);\n }\n\n return resolved;\n}\n\nfunction resolveSecretRefSync(\n providerId: string,\n ref: SecretRef,\n): string | undefined {\n const cacheKey = `ref:${ref.source}:${ref.provider ?? \"\"}:${ref.id}:${ref.command ?? \"\"}:${(ref.args ?? []).join(\",\")}`;\n const cached = resolvedCache.get(cacheKey);\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n let resolved: string | undefined;\n\n try {\n switch (ref.source) {\n case \"exec\":\n resolved = resolveExecSecret(ref);\n break;\n case \"file\":\n resolved = resolveFileSecret(ref);\n break;\n case \"env\":\n resolved = process.env[ref.id] ?? undefined;\n break;\n }\n } catch (err) {\n log.warn(\n `sync secret resolution failed for provider \"${providerId}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n }\n return resolved;\n}\n\n/**\n * Clear the resolution cache (useful for testing or key rotation).\n */\nexport function clearSecretCache(): void {\n resolvedCache.clear();\n}\n","import { log } from \"./logger.js\";\nimport type { GatewayConfig, ModelProviderConfig, AgentPersona } from \"./types.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport {\n buildChatCompletionTokenLimit,\n shouldAssumeOpenAiChatCompletions,\n} from \"./openai-chat-compat.js\";\nimport { resolveProviderApiKey } from \"./resolve-provider-secret.js\";\n\nexport interface FallbackLlmOptions {\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n /** Override which agent persona's model chain to use (by ID from agents.list[]). */\n agentId?: string;\n}\n\nexport interface FallbackLlmResponse {\n content: string;\n modelUsed: string;\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n };\n}\n\ninterface ModelRef {\n providerId: string;\n modelId: string;\n providerConfig: ModelProviderConfig;\n modelString: string;\n}\n\n/**\n * Generic fallback LLM client that uses the gateway's default AI configuration\n * and walks through the full fallback chain (primary + fallbacks).\n * Supports OpenAI and Anthropic API formats.\n */\nexport class FallbackLlmClient {\n private gatewayConfig: GatewayConfig | undefined;\n\n constructor(gatewayConfig?: GatewayConfig) {\n this.gatewayConfig = gatewayConfig;\n }\n\n /**\n * Check if fallback is available (gateway config has at least one model).\n */\n isAvailable(agentId?: string): boolean {\n const models = this.getModelChain(agentId);\n return models.length > 0;\n }\n\n /**\n * Make a chat completion request using the gateway's default AI chain.\n * Tries primary first, then each fallback in order.\n * When agentId is provided, uses that agent persona's model chain instead of defaults.\n */\n async chatCompletion(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions = {},\n ): Promise<FallbackLlmResponse | null> {\n const models = this.getModelChain(options.agentId);\n if (models.length === 0) {\n log.warn(\"fallback LLM: no models configured in gateway\");\n return null;\n }\n\n const runChain = async (): Promise<FallbackLlmResponse | null> => {\n // Try each model in the chain\n for (let i = 0; i < models.length; i++) {\n const model = models[i];\n const isFallback = i > 0;\n\n try {\n const result = await this.tryModel(model, messages, options);\n if (result) {\n if (isFallback) {\n log.info(`fallback LLM: succeeded using ${model.modelString} (fallback ${i})`);\n }\n return {\n content: result.content,\n modelUsed: model.modelString,\n usage: result.usage,\n };\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n log.debug(`fallback LLM: ${model.modelString} failed (${errorMsg}), trying next...`);\n // Continue to next model in chain\n }\n }\n\n log.warn(`fallback LLM: all ${models.length} models in chain failed`);\n return null;\n };\n\n if (typeof options.timeoutMs === \"number\") {\n if (options.timeoutMs <= 0) {\n log.warn(\"fallback LLM: timed out before request started\");\n return null;\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n runChain(),\n new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => {\n log.warn(`fallback LLM: timed out after ${options.timeoutMs}ms`);\n resolve(null);\n }, options.timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n return await runChain();\n }\n\n /**\n * Make a request with structured output (Zod schema).\n * Returns parsed JSON or null on failure.\n */\n async parseWithSchema<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<T | null> {\n const detailed = await this.parseWithSchemaDetailed(messages, schema, options);\n return detailed?.result ?? null;\n }\n\n /**\n * Like parseWithSchema but also returns the model that was used,\n * so callers can emit accurate trace events.\n */\n async parseWithSchemaDetailed<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<{ result: T; modelUsed: string } | null> {\n const response = await this.chatCompletion(messages, options);\n if (!response?.content) return null;\n\n try {\n const candidates = extractJsonCandidates(response.content);\n for (const c of candidates) {\n try {\n const parsed = JSON.parse(c);\n return { result: schema.parse(parsed), modelUsed: response.modelUsed };\n } catch {\n // keep trying other candidates\n }\n }\n return null;\n } catch (err) {\n log.warn(\"fallback LLM: failed to parse structured output:\", err);\n return null;\n }\n }\n\n /**\n * Get the full model chain from gateway config.\n * Returns array of models in order: [primary, fallback1, fallback2, ...]\n *\n * When agentId is provided, looks up the matching entry in agents.list[]\n * and uses that persona's model chain. Falls back to agents.defaults.model\n * if agentId is not found or not provided.\n */\n private getModelChain(agentId?: string): ModelRef[] {\n const chain: ModelRef[] = [];\n const providers = this.gatewayConfig?.models?.providers;\n\n if (!providers) return chain;\n\n // Resolve the model config: agent persona chain or global defaults\n let modelConfig: { primary?: string; fallbacks?: string[] } | undefined;\n\n if (agentId) {\n const persona = this.gatewayConfig?.agents?.list?.find(\n (a) => a.id === agentId,\n );\n if (persona?.model) {\n modelConfig = persona.model;\n log.debug(`fallback LLM: using agent persona \"${agentId}\" model chain`);\n } else {\n log.warn(\n `fallback LLM: agent persona \"${agentId}\" not found or has no model config, falling back to defaults`,\n );\n }\n }\n\n if (!modelConfig) {\n modelConfig = this.gatewayConfig?.agents?.defaults?.model;\n }\n\n // Build list of model strings: primary + fallbacks\n const modelStrings: string[] = [];\n\n if (modelConfig?.primary) {\n modelStrings.push(modelConfig.primary);\n }\n\n if (Array.isArray(modelConfig?.fallbacks)) {\n for (const fb of modelConfig.fallbacks) {\n if (typeof fb === \"string\" && !modelStrings.includes(fb)) {\n modelStrings.push(fb);\n }\n }\n }\n\n // Parse each model string and look up provider config\n for (const modelString of modelStrings) {\n const modelRef = this.parseModelString(modelString, providers);\n if (modelRef) {\n chain.push(modelRef);\n }\n }\n\n return chain;\n }\n\n /**\n * Parse a \"provider/model\" string and look up its config.\n */\n private parseModelString(\n modelString: string,\n providers: Record<string, ModelProviderConfig>,\n ): ModelRef | null {\n // Parse \"provider/model\" format (e.g., \"openai/gpt-5.2\", \"anthropic/claude-opus-4-6\")\n const parts = modelString.split(\"/\");\n if (parts.length < 2) {\n log.warn(`fallback LLM: invalid model format: ${modelString}`);\n return null;\n }\n\n const providerId = parts[0];\n const modelId = parts.slice(1).join(\"/\"); // Handle cases like \"openai/gpt-5.2-turbo\"\n\n const providerConfig = providers[providerId];\n if (!providerConfig) {\n log.warn(`fallback LLM: provider not found: ${providerId}`);\n return null;\n }\n\n return { providerId, modelId, providerConfig, modelString };\n }\n\n /**\n * Resolve the API key for a provider, handling OpenClaw secret ref formats.\n * Results are cached per provider so exec calls only happen once.\n */\n private async resolveApiKey(\n providerId: string,\n providerConfig: ModelProviderConfig,\n ): Promise<string | undefined> {\n return resolveProviderApiKey(\n providerId,\n providerConfig.apiKey,\n this.gatewayConfig as { auth?: { profiles?: Record<string, unknown> } } | undefined,\n );\n }\n\n /**\n * Try to call a single model.\n */\n private async tryModel(\n model: ModelRef,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n // Resolve the API key from secret refs before making the call.\n // If the raw key looks like an unresolved secret ref and resolution fails,\n // skip this provider entirely so the chain falls through to the next.\n const rawKey = model.providerConfig.apiKey;\n const needsResolution = rawKey === \"secretref-managed\"\n || (typeof rawKey === \"object\" && rawKey !== null);\n const resolvedApiKey = await this.resolveApiKey(model.providerId, model.providerConfig);\n\n if (needsResolution && !resolvedApiKey) {\n throw new Error(`API key for provider \"${model.providerId}\" could not be resolved from secret ref`);\n }\n\n const configWithResolvedKey = resolvedApiKey\n ? { ...model.providerConfig, apiKey: resolvedApiKey }\n : model.providerConfig;\n\n switch (model.providerConfig.api) {\n case \"anthropic-messages\":\n return await this.callAnthropic(configWithResolvedKey, model.modelId, messages, options);\n case \"openai-completions\":\n default:\n return await this.callOpenAI(\n configWithResolvedKey,\n model.modelId,\n messages,\n options,\n shouldAssumeOpenAiChatCompletions(model.providerConfig.baseUrl),\n );\n }\n }\n\n /**\n * Call OpenAI-compatible API.\n */\n private async callOpenAI(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n assumeOpenAI: boolean,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/chat/completions`\n : `${base}/v1/chat/completions`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n\n // Handle auth — apiKey is already resolved to a string by tryModel()\n if (config.apiKey && typeof config.apiKey === \"string\") {\n if (config.authHeader !== false) {\n headers[\"Authorization\"] = `Bearer ${config.apiKey}`;\n }\n }\n\n const body = {\n model: modelId,\n messages,\n temperature: options.temperature ?? 0.3,\n ...buildChatCompletionTokenLimit(modelId, options.maxTokens ?? 4096, {\n assumeOpenAI,\n }),\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n choices: Array<{\n message: {\n content: string;\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"Empty response from OpenAI API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Call Anthropic Messages API.\n */\n private async callAnthropic(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const url = `${config.baseUrl.replace(/\\/$/, \"\")}/messages`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n ...config.headers,\n };\n\n // Handle auth - Anthropic uses x-api-key header (apiKey resolved by tryModel)\n if (config.apiKey && typeof config.apiKey === \"string\") {\n headers[\"x-api-key\"] = config.apiKey;\n }\n\n // Extract system message (Anthropic handles it separately)\n const systemMessage = messages.find((m) => m.role === \"system\")?.content;\n const nonSystemMessages = messages.filter((m) => m.role !== \"system\");\n\n // Convert messages to Anthropic format\n const anthropicMessages = nonSystemMessages.map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const body: Record<string, unknown> = {\n model: modelId,\n messages: anthropicMessages,\n max_tokens: options.maxTokens ?? 4096,\n temperature: options.temperature ?? 0.3,\n };\n\n if (systemMessage) {\n body.system = systemMessage;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Anthropic API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n content: Array<{\n type: string;\n text: string;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const content = data.content?.[0]?.text;\n if (!content) {\n throw new Error(\"Empty response from Anthropic API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: (data.usage.input_tokens ?? 0) + (data.usage.output_tokens ?? 0),\n }\n : undefined,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|