@remnic/core 1.0.0 → 1.0.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.
Files changed (49) hide show
  1. package/dist/access-cli.js +10 -9
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +1 -1
  4. package/dist/access-mcp.d.ts +1 -1
  5. package/dist/access-schema.d.ts +40 -40
  6. package/dist/access-service.d.ts +1 -1
  7. package/dist/bootstrap.d.ts +1 -1
  8. package/dist/calibration.js +3 -2
  9. package/dist/calibration.js.map +1 -1
  10. package/dist/causal-consolidation.js +3 -2
  11. package/dist/causal-consolidation.js.map +1 -1
  12. package/dist/{chunk-QFQVZOGA.js → chunk-6UJQNRIO.js} +2 -2
  13. package/dist/{chunk-CDW777AI.js → chunk-LP47L3ZX.js} +2 -2
  14. package/dist/{chunk-LU3GQNDQ.js → chunk-M5ZBBBJI.js} +12 -1
  15. package/dist/chunk-M5ZBBBJI.js.map +1 -0
  16. package/dist/chunk-OOSWAUYB.js +47 -0
  17. package/dist/chunk-OOSWAUYB.js.map +1 -0
  18. package/dist/{chunk-YAPUAHAY.js → chunk-OTFNI3OO.js} +32 -32
  19. package/dist/{chunk-TKO4HZCK.js → chunk-UYSKNO6E.js} +1 -1
  20. package/dist/{chunk-KT4NEUNF.js → chunk-XUHI52HK.js} +80 -22
  21. package/dist/chunk-XUHI52HK.js.map +1 -0
  22. package/dist/cli.d.ts +2 -2
  23. package/dist/cli.js +1 -1
  24. package/dist/{engine-P26JFSVY.js → engine-2A6J4XEX.js} +2 -2
  25. package/dist/explicit-capture.d.ts +1 -1
  26. package/dist/extraction.js +4 -3
  27. package/dist/fallback-llm.d.ts +22 -3
  28. package/dist/fallback-llm.js +3 -2
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +10 -9
  31. package/dist/index.js.map +1 -1
  32. package/dist/models-json.d.ts +17 -0
  33. package/dist/models-json.js +12 -0
  34. package/dist/models-json.js.map +1 -0
  35. package/dist/orchestrator.d.ts +1 -1
  36. package/dist/orchestrator.js +10 -9
  37. package/dist/resolve-provider-secret.d.ts +29 -1
  38. package/dist/resolve-provider-secret.js +3 -1
  39. package/dist/schemas.d.ts +42 -42
  40. package/dist/summarizer.js +4 -3
  41. package/package.json +2 -1
  42. package/dist/chunk-KT4NEUNF.js.map +0 -1
  43. package/dist/chunk-LU3GQNDQ.js.map +0 -1
  44. package/dist/{chunk-QFQVZOGA.js.map → chunk-6UJQNRIO.js.map} +0 -0
  45. package/dist/{chunk-CDW777AI.js.map → chunk-LP47L3ZX.js.map} +0 -0
  46. package/dist/{chunk-YAPUAHAY.js.map → chunk-OTFNI3OO.js.map} +0 -0
  47. package/dist/{chunk-TKO4HZCK.js.map → chunk-UYSKNO6E.js.map} +0 -0
  48. package/dist/{engine-P26JFSVY.js.map → engine-2A6J4XEX.js.map} +0 -0
  49. package/dist/{orchestrator-zTa-Qo-1.d.ts → orchestrator-CIvLFHx3.d.ts} +2 -2
@@ -9,6 +9,7 @@ import {
9
9
  import path from "path";
10
10
  import os from "os";
11
11
  var _resolveApiKeyForProvider = null;
12
+ var _getRuntimeAuthForModel = null;
12
13
  var _resolverLoaded = false;
13
14
  var _resolverNextRetryAt = 0;
14
15
  var RESOLVER_RETRY_BACKOFF_MS = 6e4;
@@ -32,6 +33,10 @@ async function getGatewayResolver() {
32
33
  const mod = await import(importUrl);
33
34
  if (typeof mod.resolveApiKeyForProvider === "function") {
34
35
  _resolveApiKeyForProvider = mod.resolveApiKeyForProvider;
36
+ if (typeof mod.getRuntimeAuthForModel === "function") {
37
+ _getRuntimeAuthForModel = mod.getRuntimeAuthForModel;
38
+ log.debug("loaded gateway getRuntimeAuthForModel from runtime module");
39
+ }
35
40
  _resolverLoaded = true;
36
41
  log.debug("loaded gateway resolveApiKeyForProvider from runtime module");
37
42
  return _resolveApiKeyForProvider;
@@ -138,15 +143,21 @@ function resolveFromEnv(providerId) {
138
143
  }
139
144
  return void 0;
140
145
  }
146
+ async function getGatewayRuntimeAuthForModel() {
147
+ await getGatewayResolver();
148
+ return _getRuntimeAuthForModel;
149
+ }
141
150
  function clearSecretCache() {
142
151
  resolvedCache.clear();
143
152
  _resolveApiKeyForProvider = null;
153
+ _getRuntimeAuthForModel = null;
144
154
  _resolverLoaded = false;
145
155
  _resolverNextRetryAt = 0;
146
156
  }
147
157
 
148
158
  export {
149
159
  resolveProviderApiKey,
160
+ getGatewayRuntimeAuthForModel,
150
161
  clearSecretCache
151
162
  };
152
- //# sourceMappingURL=chunk-LU3GQNDQ.js.map
163
+ //# sourceMappingURL=chunk-M5ZBBBJI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resolve-provider-secret.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport { readEnvVar } from \"./runtime/env.js\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\n/**\n * Resolve a provider API key using OpenClaw's own auth resolution system.\n *\n * This module delegates to the gateway's `resolveApiKeyForProvider()` function,\n * which handles all secret reference formats (SecretRef objects, auth profiles,\n * \"secretref-managed\" markers, environment variables, etc.) using the same\n * codepath the gateway uses for its own agent sessions.\n *\n * For plain-text API keys, a fast path returns them directly without\n * involving the gateway auth system.\n *\n * Results are cached per provider for the gateway process lifetime.\n */\n\ntype ResolveApiKeyFn = (params: {\n provider: string;\n cfg?: unknown;\n agentDir?: string;\n}) => Promise<{ apiKey?: string; source?: string; mode?: string } | null>;\n\n/**\n * Resolve request-ready auth for a model, including provider-owned transforms\n * (e.g., OAuth token exchange, base URL override for openai-codex).\n */\nexport type GetRuntimeAuthForModelFn = (params: {\n model: { provider: string; id: string; api?: string; baseUrl?: string };\n cfg?: unknown;\n workspaceDir?: string;\n}) => Promise<{\n apiKey?: string;\n baseUrl?: string;\n source?: string;\n mode?: string;\n profileId?: string;\n} | null>;\n\nlet _resolveApiKeyForProvider: ResolveApiKeyFn | null = null;\nlet _getRuntimeAuthForModel: GetRuntimeAuthForModelFn | null = null;\nlet _resolverLoaded = false;\nlet _resolverNextRetryAt = 0;\nconst RESOLVER_RETRY_BACKOFF_MS = 60_000; // 1 minute between retries after first failure\nconst resolvedCache = new Map<string, string | undefined>();\n\n/**\n * Lazily load the gateway's resolveApiKeyForProvider function.\n * Returns null if not available (e.g., running outside the gateway process).\n */\nasync function getGatewayResolver(): Promise<ResolveApiKeyFn | null> {\n if (_resolverLoaded) {\n return _resolveApiKeyForProvider;\n }\n // Backoff: don't re-scan filesystem on every call when module wasn't found.\n // After a failure, wait RESOLVER_RETRY_BACKOFF_MS before trying again.\n if (_resolverNextRetryAt > 0 && Date.now() < _resolverNextRetryAt) {\n return null;\n }\n\n try {\n // The gateway bundles this in a runtime chunk — import it dynamically.\n // This import path is stable across gateway versions since it's a named runtime export.\n const candidates = [\n // Try glob-matching the runtime module name (hash varies per build)\n ...await findRuntimeModules(),\n ];\n\n const { pathToFileURL } = await import(\"node:url\");\n for (const candidate of candidates) {\n try {\n // Convert native path to file:// URL for cross-platform ESM import compatibility\n const importUrl = pathToFileURL(candidate).href;\n const mod = await import(importUrl);\n if (typeof mod.resolveApiKeyForProvider === \"function\") {\n _resolveApiKeyForProvider = mod.resolveApiKeyForProvider;\n if (typeof mod.getRuntimeAuthForModel === \"function\") {\n _getRuntimeAuthForModel = mod.getRuntimeAuthForModel;\n log.debug(\"loaded gateway getRuntimeAuthForModel from runtime module\");\n }\n _resolverLoaded = true;\n log.debug(\"loaded gateway resolveApiKeyForProvider from runtime module\");\n return _resolveApiKeyForProvider;\n }\n } catch {\n // Try next candidate\n }\n }\n } catch {\n // Silent\n }\n\n // Backoff before retrying — avoid repeated fs scanning.\n // Retries after RESOLVER_RETRY_BACKOFF_MS so the resolver can\n // recover if the gateway restarts or the module becomes available.\n _resolverNextRetryAt = Date.now() + RESOLVER_RETRY_BACKOFF_MS;\n log.debug(`gateway resolveApiKeyForProvider not available — will retry after ${RESOLVER_RETRY_BACKOFF_MS / 1000}s`);\n return null;\n}\n\n/**\n * Find the gateway's model-auth runtime module by scanning the dist directory.\n * Uses require.resolve to find the openclaw package regardless of install method.\n */\nasync function findRuntimeModules(): Promise<string[]> {\n const { readdirSync } = await import(\"node:fs\");\n const { createRequire } = await import(\"node:module\");\n const candidates: string[] = [];\n\n // Discover the openclaw dist directory from the installed package,\n // regardless of how it was installed (Homebrew, npm global, local, etc.)\n const distDirs: string[] = [];\n\n try {\n // require.resolve finds the package from the current process context\n const req = createRequire(import.meta.url);\n const openclawMain = req.resolve(\"openclaw\");\n const openclawDist = path.join(path.dirname(openclawMain), \"..\", \"dist\");\n if (openclawDist) distDirs.push(path.resolve(openclawDist));\n } catch {\n // openclaw not resolvable from plugin context — try alternate paths\n }\n\n // Fallback: infer from the running process (gateway runs from its own dist/)\n // Use fs.realpathSync to resolve symlinks (e.g., /usr/local/bin/openclaw → actual path)\n try {\n const { realpathSync } = await import(\"node:fs\");\n const mainScript = process.argv[1];\n if (mainScript) {\n const realScript = realpathSync(mainScript);\n if (realScript.includes(\"openclaw\")) {\n const distDir = path.dirname(realScript);\n if (!distDirs.includes(distDir)) distDirs.push(distDir);\n }\n }\n } catch {\n // Silent\n }\n\n for (const dir of distDirs) {\n try {\n const files = readdirSync(dir);\n for (const f of files) {\n if (f.startsWith(\"runtime-model-auth.runtime-\") && f.endsWith(\".js\")) {\n candidates.push(path.join(dir, f));\n }\n }\n } catch {\n // Directory doesn't exist — skip\n }\n }\n\n return candidates;\n}\n\n/**\n * Resolve a provider API key from various OpenClaw formats.\n *\n * Resolution order:\n * 1. Plain-text string → returned immediately\n * 2. Gateway's resolveApiKeyForProvider → handles all secret ref formats\n * 3. Environment variable fallback (PROVIDER_NAME_API_KEY)\n * 4. undefined → provider is skipped in the fallback chain\n */\nexport async function resolveProviderApiKey(\n providerId: string,\n apiKeyValue: unknown,\n gatewayConfig?: unknown,\n agentDir?: string,\n): Promise<string | undefined> {\n // Check cache first\n const cacheKey = `provider:${providerId}`;\n if (resolvedCache.has(cacheKey)) {\n return resolvedCache.get(cacheKey);\n }\n\n let resolved: string | undefined;\n\n // Fast path: plain-text string that looks like an actual API key\n if (typeof apiKeyValue === \"string\" && apiKeyValue.trim().length > 0) {\n // Skip known non-API-key markers used by the gateway for auth modes\n // that don't use bearer tokens (OAuth, local endpoints, GCP credentials)\n if (\n apiKeyValue === \"secretref-managed\" ||\n apiKeyValue.endsWith(\"-oauth\") ||\n apiKeyValue.endsWith(\"-local\") ||\n apiKeyValue === \"lm-studio\" ||\n apiKeyValue.startsWith(\"gcp-\")\n ) {\n // Fall through to gateway resolver / env var fallback\n } else {\n resolved = apiKeyValue;\n resolvedCache.set(cacheKey, resolved);\n return resolved;\n }\n }\n\n // The API key is either a SecretRef object, \"secretref-managed\", or empty.\n // Try the gateway's own auth resolution system first.\n const resolver = await getGatewayResolver();\n if (resolver) {\n try {\n const resolvedAgentDir = agentDir ?? path.join(os.homedir(), \".openclaw\", \"agents\", \"main\", \"agent\");\n const auth = await resolver({ provider: providerId, cfg: gatewayConfig, agentDir: resolvedAgentDir });\n if (auth?.apiKey) {\n resolved = auth.apiKey;\n log.debug(`resolved API key for provider \"${providerId}\" via gateway auth (source: ${auth.source ?? \"unknown\"}, mode: ${auth.mode ?? \"unknown\"})`);\n resolvedCache.set(cacheKey, resolved);\n return resolved;\n }\n } catch (err) {\n log.debug(\n `gateway auth resolution failed for provider \"${providerId}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n // Environment variable fallback\n resolved = resolveFromEnv(providerId);\n if (resolved) {\n log.debug(`resolved API key for provider \"${providerId}\" from environment variable`);\n } else {\n log.debug(`could not resolve API key for provider \"${providerId}\" — skipping`);\n }\n\n // Only cache successful resolutions — failures are retried on next call\n // so providers can recover after transient issues (e.g., 1Password agent restart)\n if (resolved) {\n resolvedCache.set(cacheKey, resolved);\n }\n return resolved;\n}\n\n/**\n * Try to resolve an API key from environment variables.\n */\nfunction resolveFromEnv(providerId: string): string | undefined {\n const normalized = providerId.toUpperCase().replace(/[^A-Z0-9]/g, \"_\");\n const candidates = [\n `${normalized}_API_KEY`,\n `${normalized}_TOKEN`,\n ];\n for (const envVar of candidates) {\n const value = readEnvVar(envVar);\n if (value && value.trim().length > 0) {\n return value.trim();\n }\n }\n return undefined;\n}\n\n/**\n * Get the gateway's getRuntimeAuthForModel function, if available.\n * This resolves request-ready auth including provider-owned transforms\n * (OAuth token exchange, base URL override for codex/copilot/etc.).\n * Must be called after at least one resolveProviderApiKey() call to\n * trigger the lazy module load.\n */\nexport async function getGatewayRuntimeAuthForModel(): Promise<GetRuntimeAuthForModelFn | null> {\n // Ensure the runtime module has been loaded\n await getGatewayResolver();\n return _getRuntimeAuthForModel;\n}\n\n/**\n * Clear the resolution cache (useful for testing or key rotation).\n */\nexport function clearSecretCache(): void {\n resolvedCache.clear();\n _resolveApiKeyForProvider = null;\n _getRuntimeAuthForModel = null;\n _resolverLoaded = false;\n _resolverNextRetryAt = 0;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,47 @@
1
+ import {
2
+ log
3
+ } from "./chunk-KWBU5S5U.js";
4
+
5
+ // src/models-json.ts
6
+ import { readFileSync } from "fs";
7
+ import { join } from "path";
8
+ import { homedir } from "os";
9
+ var _cachedProviders = null;
10
+ var _loadAttempted = false;
11
+ function loadModelsJsonProviders() {
12
+ if (_loadAttempted) {
13
+ return _cachedProviders ?? {};
14
+ }
15
+ _loadAttempted = true;
16
+ try {
17
+ const modelsPath = join(homedir(), ".openclaw", "agents", "main", "agent", "models.json");
18
+ const raw = readFileSync(modelsPath, "utf-8");
19
+ const parsed = JSON.parse(raw);
20
+ const providers = parsed?.providers;
21
+ if (providers && typeof providers === "object" && !Array.isArray(providers)) {
22
+ _cachedProviders = providers;
23
+ log.debug(`loaded ${Object.keys(_cachedProviders).length} providers from models.json`);
24
+ return _cachedProviders;
25
+ }
26
+ } catch (err) {
27
+ log.debug(
28
+ `could not load models.json: ${err instanceof Error ? err.message : String(err)}`
29
+ );
30
+ }
31
+ return {};
32
+ }
33
+ function clearModelsJsonCache() {
34
+ _cachedProviders = null;
35
+ _loadAttempted = false;
36
+ }
37
+ function __setModelsJsonForTest(providers) {
38
+ _cachedProviders = providers;
39
+ _loadAttempted = true;
40
+ }
41
+
42
+ export {
43
+ loadModelsJsonProviders,
44
+ clearModelsJsonCache,
45
+ __setModelsJsonForTest
46
+ };
47
+ //# sourceMappingURL=chunk-OOSWAUYB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/models-json.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { log } from \"./logger.js\";\nimport type { ModelProviderConfig } from \"./types.js\";\n\n/**\n * Read the gateway's materialized models.json to get the full provider map,\n * including built-in providers (openai-codex, google-vertex, etc.) that are\n * not declared in the user's openclaw.json but are registered by gateway\n * plugins at runtime.\n *\n * The gateway writes models.json to ~/.openclaw/agents/main/agent/models.json\n * with all providers merged: user-defined (from openclaw.json) + built-in\n * (from plugin catalogs). Each entry has the correct baseUrl, api format,\n * and auth mode for that provider.\n *\n * Results are cached for the process lifetime since models.json only changes\n * when the gateway restarts or `openclaw models` commands run.\n */\n\nlet _cachedProviders: Record<string, ModelProviderConfig> | null = null;\nlet _loadAttempted = false;\n\n/**\n * Load the full providers map from the gateway's models.json.\n * Returns an empty object if the file doesn't exist or can't be parsed.\n */\nexport function loadModelsJsonProviders(): Record<string, ModelProviderConfig> {\n if (_loadAttempted) {\n return _cachedProviders ?? {};\n }\n _loadAttempted = true;\n\n try {\n const modelsPath = join(homedir(), \".openclaw\", \"agents\", \"main\", \"agent\", \"models.json\");\n const raw = readFileSync(modelsPath, \"utf-8\");\n const parsed = JSON.parse(raw);\n const providers = parsed?.providers;\n\n if (providers && typeof providers === \"object\" && !Array.isArray(providers)) {\n _cachedProviders = providers as Record<string, ModelProviderConfig>;\n log.debug(`loaded ${Object.keys(_cachedProviders).length} providers from models.json`);\n return _cachedProviders;\n }\n } catch (err) {\n log.debug(\n `could not load models.json: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {};\n}\n\n/**\n * Clear the cached providers (useful for testing).\n */\nexport function clearModelsJsonCache(): void {\n _cachedProviders = null;\n _loadAttempted = false;\n}\n\n/**\n * Inject a providers map for testing, bypassing file I/O.\n */\nexport function __setModelsJsonForTest(providers: Record<string, ModelProviderConfig>): void {\n _cachedProviders = providers;\n _loadAttempted = true;\n}\n"],"mappings":";;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AACrB,SAAS,eAAe;AAmBxB,IAAI,mBAA+D;AACnE,IAAI,iBAAiB;AAMd,SAAS,0BAA+D;AAC7E,MAAI,gBAAgB;AAClB,WAAO,oBAAoB,CAAC;AAAA,EAC9B;AACA,mBAAiB;AAEjB,MAAI;AACF,UAAM,aAAa,KAAK,QAAQ,GAAG,aAAa,UAAU,QAAQ,SAAS,aAAa;AACxF,UAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAM,YAAY,QAAQ;AAE1B,QAAI,aAAa,OAAO,cAAc,YAAY,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC3E,yBAAmB;AACnB,UAAI,MAAM,UAAU,OAAO,KAAK,gBAAgB,EAAE,MAAM,6BAA6B;AACrF,aAAO;AAAA,IACT;AAAA,EACF,SAAS,KAAK;AACZ,QAAI;AAAA,MACF,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACjF;AAAA,EACF;AAEA,SAAO,CAAC;AACV;AAKO,SAAS,uBAA6B;AAC3C,qBAAmB;AACnB,mBAAiB;AACnB;AAKO,SAAS,uBAAuB,WAAsD;AAC3F,qBAAmB;AACnB,mBAAiB;AACnB;","names":[]}
@@ -1,13 +1,13 @@
1
+ import {
2
+ CompoundingEngine,
3
+ SharedContextManager,
4
+ defaultTierMigrationCycleBudget
5
+ } from "./chunk-UYSKNO6E.js";
1
6
  import {
2
7
  applyUtilityPromotionRuntimePolicy,
3
8
  applyUtilityRankingRuntimeDelta,
4
9
  loadUtilityRuntimeValues
5
10
  } from "./chunk-IFFFR3MR.js";
6
- import {
7
- CompoundingEngine,
8
- SharedContextManager,
9
- defaultTierMigrationCycleBudget
10
- } from "./chunk-TKO4HZCK.js";
11
11
  import {
12
12
  TierMigrationExecutor
13
13
  } from "./chunk-Z5AAYHUC.js";
@@ -25,25 +25,7 @@ import {
25
25
  } from "./chunk-ZKYI7UVO.js";
26
26
  import {
27
27
  HourlySummarizer
28
- } from "./chunk-CDW777AI.js";
29
- import {
30
- applyRuntimeRetrievalPolicy
31
- } from "./chunk-G3AG3KZN.js";
32
- import {
33
- buildConsolidationPrompt,
34
- findSimilarClusters,
35
- parseConsolidationResponse
36
- } from "./chunk-2CJCWDMR.js";
37
- import {
38
- findUnresolvedEntityRefs
39
- } from "./chunk-X7XN6YU4.js";
40
- import {
41
- RelevanceStore
42
- } from "./chunk-BRK4ODMI.js";
43
- import {
44
- RerankCache,
45
- rerankLocalOrNoop
46
- } from "./chunk-C7VW7C3F.js";
28
+ } from "./chunk-LP47L3ZX.js";
47
29
  import {
48
30
  mergeWithAgentResults,
49
31
  runDirectAgent,
@@ -62,6 +44,29 @@ import {
62
44
  recencyWindowFromPrompt,
63
45
  resolvePromptTagPrefilterAsync
64
46
  } from "./chunk-V3RXWQIE.js";
47
+ import {
48
+ applyRuntimeRetrievalPolicy
49
+ } from "./chunk-G3AG3KZN.js";
50
+ import {
51
+ buildConsolidationPrompt,
52
+ findSimilarClusters,
53
+ parseConsolidationResponse
54
+ } from "./chunk-2CJCWDMR.js";
55
+ import {
56
+ LastRecallStore,
57
+ TierMigrationStatusStore,
58
+ clampGraphRecallExpandedEntries
59
+ } from "./chunk-HG2NKWR2.js";
60
+ import {
61
+ findUnresolvedEntityRefs
62
+ } from "./chunk-X7XN6YU4.js";
63
+ import {
64
+ RelevanceStore
65
+ } from "./chunk-BRK4ODMI.js";
66
+ import {
67
+ RerankCache,
68
+ rerankLocalOrNoop
69
+ } from "./chunk-C7VW7C3F.js";
65
70
  import {
66
71
  buildQmdRecallCacheKey,
67
72
  getCachedQmdRecall,
@@ -70,11 +75,6 @@ import {
70
75
  import {
71
76
  createRecallSectionMetricRecorder
72
77
  } from "./chunk-L5RPWGFK.js";
73
- import {
74
- LastRecallStore,
75
- TierMigrationStatusStore,
76
- clampGraphRecallExpandedEntries
77
- } from "./chunk-HG2NKWR2.js";
78
78
  import {
79
79
  NegativeExampleStore
80
80
  } from "./chunk-GJR6D6KC.js";
@@ -89,7 +89,7 @@ import {
89
89
  } from "./chunk-WWIQTB2Y.js";
90
90
  import {
91
91
  ExtractionEngine
92
- } from "./chunk-QFQVZOGA.js";
92
+ } from "./chunk-6UJQNRIO.js";
93
93
  import {
94
94
  parseMemoryActionEligibilityContext
95
95
  } from "./chunk-MWGVGUIS.js";
@@ -199,7 +199,7 @@ import {
199
199
  } from "./chunk-XYIK4LF6.js";
200
200
  import {
201
201
  FallbackLlmClient
202
- } from "./chunk-KT4NEUNF.js";
202
+ } from "./chunk-XUHI52HK.js";
203
203
  import {
204
204
  BoxBuilder
205
205
  } from "./chunk-M5KEYE5E.js";
@@ -10758,4 +10758,4 @@ export {
10758
10758
  resolvePersistedMemoryRelativePath,
10759
10759
  Orchestrator
10760
10760
  };
10761
- //# sourceMappingURL=chunk-YAPUAHAY.js.map
10761
+ //# sourceMappingURL=chunk-OTFNI3OO.js.map
@@ -1849,4 +1849,4 @@ export {
1849
1849
  defaultTierMigrationCycleBudget,
1850
1850
  CompoundingEngine
1851
1851
  };
1852
- //# sourceMappingURL=chunk-TKO4HZCK.js.map
1852
+ //# sourceMappingURL=chunk-UYSKNO6E.js.map
@@ -1,6 +1,10 @@
1
1
  import {
2
+ getGatewayRuntimeAuthForModel,
2
3
  resolveProviderApiKey
3
- } from "./chunk-LU3GQNDQ.js";
4
+ } from "./chunk-M5ZBBBJI.js";
5
+ import {
6
+ loadModelsJsonProviders
7
+ } from "./chunk-OOSWAUYB.js";
4
8
  import {
5
9
  buildChatCompletionTokenLimit,
6
10
  shouldAssumeOpenAiChatCompletions
@@ -122,8 +126,7 @@ var FallbackLlmClient = class {
122
126
  */
123
127
  getModelChain(agentId) {
124
128
  const chain = [];
125
- const providers = this.gatewayConfig?.models?.providers;
126
- if (!providers) return chain;
129
+ const providers = this.gatewayConfig?.models?.providers ?? {};
127
130
  let modelConfig;
128
131
  if (agentId) {
129
132
  const persona = this.gatewayConfig?.agents?.list?.find(
@@ -171,7 +174,7 @@ var FallbackLlmClient = class {
171
174
  }
172
175
  const providerId = parts[0];
173
176
  const modelId = parts.slice(1).join("/");
174
- const providerConfig = providers[providerId];
177
+ const providerConfig = providers[providerId] ?? this.resolveFromModelsJson(providerId);
175
178
  if (!providerConfig) {
176
179
  log.warn(`fallback LLM: provider not found: ${providerId}`);
177
180
  return null;
@@ -179,36 +182,91 @@ var FallbackLlmClient = class {
179
182
  return { providerId, modelId, providerConfig, modelString };
180
183
  }
181
184
  /**
182
- * Resolve the API key for a provider, handling OpenClaw secret ref formats.
183
- * Results are cached per provider so exec calls only happen once.
185
+ * Look up a provider from the gateway's materialized models.json, which
186
+ * contains all providers including built-in ones (openai-codex, google-vertex,
187
+ * etc.) that aren't in the user's openclaw.json but are registered by
188
+ * gateway plugins. Returns null if the provider isn't found there either.
184
189
  */
185
- async resolveApiKey(providerId, providerConfig) {
186
- return resolveProviderApiKey(providerId, providerConfig.apiKey, this.gatewayConfig);
190
+ resolveFromModelsJson(providerId) {
191
+ const allProviders = loadModelsJsonProviders();
192
+ const config = allProviders[providerId];
193
+ if (config) {
194
+ log.debug(`fallback LLM: resolved provider "${providerId}" from models.json (api: ${config.api ?? "default"})`);
195
+ return config;
196
+ }
197
+ return null;
187
198
  }
188
199
  /**
189
200
  * Try to call a single model.
201
+ *
202
+ * Uses the gateway's native getRuntimeAuthForModel when available — this
203
+ * handles all provider-specific auth transforms (OAuth token exchange,
204
+ * base URL overrides for codex/copilot/etc.) through the same codepath
205
+ * the gateway itself uses. Falls back to resolveProviderApiKey for
206
+ * simpler providers or when the runtime module isn't loaded.
190
207
  */
191
208
  async tryModel(model, messages, options) {
209
+ const runtimeAuth = await this.resolveRuntimeAuth(model);
210
+ const effectiveBaseUrl = runtimeAuth?.baseUrl ?? model.providerConfig.baseUrl;
211
+ const resolvedApiKey = runtimeAuth?.apiKey ?? await this.resolveFallbackApiKey(model);
192
212
  const rawKey = model.providerConfig.apiKey;
193
213
  const needsResolution = rawKey === "secretref-managed" || typeof rawKey === "object" && rawKey !== null;
194
- const resolvedApiKey = await this.resolveApiKey(model.providerId, model.providerConfig);
195
214
  if (needsResolution && !resolvedApiKey) {
196
215
  throw new Error(`API key for provider "${model.providerId}" could not be resolved from secret ref`);
197
216
  }
198
- const configWithResolvedKey = resolvedApiKey ? { ...model.providerConfig, apiKey: resolvedApiKey } : model.providerConfig;
199
- switch (model.providerConfig.api) {
200
- case "anthropic-messages":
201
- return await this.callAnthropic(configWithResolvedKey, model.modelId, messages, options);
202
- case "openai-completions":
203
- default:
204
- return await this.callOpenAI(
205
- configWithResolvedKey,
206
- model.modelId,
207
- messages,
208
- options,
209
- shouldAssumeOpenAiChatCompletions(model.providerConfig.baseUrl)
217
+ const effectiveConfig = {
218
+ ...model.providerConfig,
219
+ baseUrl: effectiveBaseUrl,
220
+ ...resolvedApiKey ? { apiKey: resolvedApiKey } : {}
221
+ };
222
+ if (model.providerConfig.api === "anthropic-messages") {
223
+ return await this.callAnthropic(effectiveConfig, model.modelId, messages, options);
224
+ }
225
+ return await this.callOpenAI(
226
+ effectiveConfig,
227
+ model.modelId,
228
+ messages,
229
+ options,
230
+ shouldAssumeOpenAiChatCompletions(effectiveConfig.baseUrl)
231
+ );
232
+ }
233
+ /**
234
+ * Resolve request-ready auth through the gateway's native runtime, which
235
+ * handles provider-specific transforms (OAuth token exchange for codex/copilot,
236
+ * base URL rewrite, etc.). Returns null if the runtime isn't available.
237
+ */
238
+ async resolveRuntimeAuth(model) {
239
+ try {
240
+ const getRuntimeAuth = await getGatewayRuntimeAuthForModel();
241
+ if (!getRuntimeAuth) return null;
242
+ const result = await getRuntimeAuth({
243
+ model: {
244
+ provider: model.providerId,
245
+ id: model.modelId,
246
+ api: model.providerConfig.api,
247
+ baseUrl: model.providerConfig.baseUrl
248
+ },
249
+ cfg: this.gatewayConfig
250
+ });
251
+ if (result?.apiKey || result?.baseUrl) {
252
+ log.debug(
253
+ `fallback LLM: resolved runtime auth for "${model.modelString}" (source: ${result.source ?? "unknown"}, mode: ${result.mode ?? "unknown"})`
210
254
  );
255
+ return { apiKey: result.apiKey, baseUrl: result.baseUrl };
256
+ }
257
+ } catch (err) {
258
+ log.debug(
259
+ `fallback LLM: gateway runtime auth failed for "${model.modelString}": ${err instanceof Error ? err.message : String(err)}`
260
+ );
211
261
  }
262
+ return null;
263
+ }
264
+ /**
265
+ * Resolve API key through the existing provider-level resolution (env vars,
266
+ * secret refs, etc.). Used as fallback when gateway runtime auth isn't available.
267
+ */
268
+ async resolveFallbackApiKey(model) {
269
+ return resolveProviderApiKey(model.providerId, model.providerConfig.apiKey, this.gatewayConfig);
212
270
  }
213
271
  /**
214
272
  * Call OpenAI-compatible API.
@@ -312,4 +370,4 @@ var FallbackLlmClient = class {
312
370
  export {
313
371
  FallbackLlmClient
314
372
  };
315
- //# sourceMappingURL=chunk-KT4NEUNF.js.map
373
+ //# sourceMappingURL=chunk-XUHI52HK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fallback-llm.ts"],"sourcesContent":["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, getGatewayRuntimeAuthForModel } from \"./resolve-provider-secret.js\";\nimport { loadModelsJsonProviders } from \"./models-json.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.debug(`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 // 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 // Look up explicit config first; fall back to the gateway's materialized\n // models.json which contains built-in providers (openai-codex, etc.)\n const providerConfig = providers[providerId] ?? this.resolveFromModelsJson(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 * Look up a provider from the gateway's materialized models.json, which\n * contains all providers including built-in ones (openai-codex, google-vertex,\n * etc.) that aren't in the user's openclaw.json but are registered by\n * gateway plugins. Returns null if the provider isn't found there either.\n */\n private resolveFromModelsJson(providerId: string): ModelProviderConfig | null {\n const allProviders = loadModelsJsonProviders();\n const config = allProviders[providerId];\n if (config) {\n log.debug(`fallback LLM: resolved provider \"${providerId}\" from models.json (api: ${config.api ?? \"default\"})`);\n return config;\n }\n return null;\n }\n\n /**\n * Try to call a single model.\n *\n * Uses the gateway's native getRuntimeAuthForModel when available — this\n * handles all provider-specific auth transforms (OAuth token exchange,\n * base URL overrides for codex/copilot/etc.) through the same codepath\n * the gateway itself uses. Falls back to resolveProviderApiKey for\n * simpler providers or when the runtime module isn't loaded.\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 // Try the gateway's native runtime auth first — it handles all provider-\n // specific transforms (OAuth exchange, base URL rewrite, etc.)\n const runtimeAuth = await this.resolveRuntimeAuth(model);\n const effectiveBaseUrl = runtimeAuth?.baseUrl ?? model.providerConfig.baseUrl;\n const resolvedApiKey = runtimeAuth?.apiKey ?? await this.resolveFallbackApiKey(model);\n\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 if (needsResolution && !resolvedApiKey) {\n throw new Error(`API key for provider \"${model.providerId}\" could not be resolved from secret ref`);\n }\n\n const effectiveConfig: ModelProviderConfig = {\n ...model.providerConfig,\n baseUrl: effectiveBaseUrl,\n ...(resolvedApiKey ? { apiKey: resolvedApiKey } : {}),\n };\n\n if (model.providerConfig.api === \"anthropic-messages\") {\n return await this.callAnthropic(effectiveConfig, model.modelId, messages, options);\n }\n\n // For OpenAI-compatible APIs (openai-completions, openai-responses,\n // openai-codex-responses, ollama, etc.) and unknown formats, use\n // OpenAI chat completions — the gateway's runtime auth resolver returns\n // request-ready base URL and credentials for most providers.\n return await this.callOpenAI(\n effectiveConfig,\n model.modelId,\n messages,\n options,\n shouldAssumeOpenAiChatCompletions(effectiveConfig.baseUrl),\n );\n }\n\n /**\n * Resolve request-ready auth through the gateway's native runtime, which\n * handles provider-specific transforms (OAuth token exchange for codex/copilot,\n * base URL rewrite, etc.). Returns null if the runtime isn't available.\n */\n private async resolveRuntimeAuth(\n model: ModelRef,\n ): Promise<{ apiKey?: string; baseUrl?: string } | null> {\n try {\n const getRuntimeAuth = await getGatewayRuntimeAuthForModel();\n if (!getRuntimeAuth) return null;\n\n const result = await getRuntimeAuth({\n model: {\n provider: model.providerId,\n id: model.modelId,\n api: model.providerConfig.api,\n baseUrl: model.providerConfig.baseUrl,\n },\n cfg: this.gatewayConfig,\n });\n\n if (result?.apiKey || result?.baseUrl) {\n log.debug(\n `fallback LLM: resolved runtime auth for \"${model.modelString}\" (source: ${result.source ?? \"unknown\"}, mode: ${result.mode ?? \"unknown\"})`,\n );\n return { apiKey: result.apiKey, baseUrl: result.baseUrl };\n }\n } catch (err) {\n log.debug(\n `fallback LLM: gateway runtime auth failed for \"${model.modelString}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n return null;\n }\n\n /**\n * Resolve API key through the existing provider-level resolution (env vars,\n * secret refs, etc.). Used as fallback when gateway runtime auth isn't available.\n */\n private async resolveFallbackApiKey(model: ModelRef): Promise<string | undefined> {\n return resolveProviderApiKey(model.providerId, model.providerConfig.apiKey, this.gatewayConfig);\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":";;;;;;;;;;;;;;;;;;;AAwCO,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EAER,YAAY,eAA+B;AACzC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAA2B;AACrC,UAAM,SAAS,KAAK,cAAc,OAAO;AACzC,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eACJ,UACA,UAA8B,CAAC,GACM;AACrC,UAAM,SAAS,KAAK,cAAc,QAAQ,OAAO;AACjD,QAAI,OAAO,WAAW,GAAG;AACvB,UAAI,KAAK,+CAA+C;AACxD,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,YAAiD;AAEhE,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,cAAM,QAAQ,OAAO,CAAC;AACtB,cAAM,aAAa,IAAI;AAEvB,YAAI;AACF,gBAAM,SAAS,MAAM,KAAK,SAAS,OAAO,UAAU,OAAO;AAC3D,cAAI,QAAQ;AACV,gBAAI,YAAY;AACd,kBAAI,MAAM,iCAAiC,MAAM,WAAW,cAAc,CAAC,GAAG;AAAA,YAChF;AACA,mBAAO;AAAA,cACL,SAAS,OAAO;AAAA,cAChB,WAAW,MAAM;AAAA,cACjB,OAAO,OAAO;AAAA,YAChB;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AACZ,gBAAM,WAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAChE,cAAI,MAAM,iBAAiB,MAAM,WAAW,YAAY,QAAQ,mBAAmB;AAAA,QAErF;AAAA,MACF;AAEA,UAAI,KAAK,qBAAqB,OAAO,MAAM,yBAAyB;AACpE,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,QAAQ,cAAc,UAAU;AACzC,UAAI,QAAQ,aAAa,GAAG;AAC1B,YAAI,KAAK,gDAAgD;AACzD,eAAO;AAAA,MACT;AACA,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,QAAQ,KAAK;AAAA,UACxB,SAAS;AAAA,UACT,IAAI,QAAc,CAAC,YAAY;AAC7B,4BAAgB,WAAW,MAAM;AAC/B,kBAAI,KAAK,iCAAiC,QAAQ,SAAS,IAAI;AAC/D,sBAAQ,IAAI;AAAA,YACd,GAAG,QAAQ,SAAS;AAAA,UACtB,CAAC;AAAA,QACH,CAAC;AAAA,MACH,UAAE;AACA,YAAI,cAAe,cAAa,aAAa;AAAA,MAC/C;AAAA,IACF;AAEA,WAAO,MAAM,SAAS;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBACJ,UACA,QACA,UAA8B,CAAC,GACZ;AACnB,UAAM,WAAW,MAAM,KAAK,wBAAwB,UAAU,QAAQ,OAAO;AAC7E,WAAO,UAAU,UAAU;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,wBACJ,UACA,QACA,UAA8B,CAAC,GACmB;AAClD,UAAM,WAAW,MAAM,KAAK,eAAe,UAAU,OAAO;AAC5D,QAAI,CAAC,UAAU,QAAS,QAAO;AAE/B,QAAI;AACF,YAAM,aAAa,sBAAsB,SAAS,OAAO;AACzD,iBAAW,KAAK,YAAY;AAC1B,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,CAAC;AAC3B,iBAAO,EAAE,QAAQ,OAAO,MAAM,MAAM,GAAG,WAAW,SAAS,UAAU;AAAA,QACvE,QAAQ;AAAA,QAER;AAAA,MACF;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,KAAK,oDAAoD,GAAG;AAChE,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,cAAc,SAA8B;AAClD,UAAM,QAAoB,CAAC;AAC3B,UAAM,YAAY,KAAK,eAAe,QAAQ,aAAa,CAAC;AAG5D,QAAI;AAEJ,QAAI,SAAS;AACX,YAAM,UAAU,KAAK,eAAe,QAAQ,MAAM;AAAA,QAChD,CAAC,MAAM,EAAE,OAAO;AAAA,MAClB;AACA,UAAI,SAAS,OAAO;AAClB,sBAAc,QAAQ;AACtB,YAAI,MAAM,sCAAsC,OAAO,eAAe;AAAA,MACxE,OAAO;AACL,YAAI;AAAA,UACF,gCAAgC,OAAO;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,aAAa;AAChB,oBAAc,KAAK,eAAe,QAAQ,UAAU;AAAA,IACtD;AAGA,UAAM,eAAyB,CAAC;AAEhC,QAAI,aAAa,SAAS;AACxB,mBAAa,KAAK,YAAY,OAAO;AAAA,IACvC;AAEA,QAAI,MAAM,QAAQ,aAAa,SAAS,GAAG;AACzC,iBAAW,MAAM,YAAY,WAAW;AACtC,YAAI,OAAO,OAAO,YAAY,CAAC,aAAa,SAAS,EAAE,GAAG;AACxD,uBAAa,KAAK,EAAE;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAGA,eAAW,eAAe,cAAc;AACtC,YAAM,WAAW,KAAK,iBAAiB,aAAa,SAAS;AAC7D,UAAI,UAAU;AACZ,cAAM,KAAK,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,iBACN,aACA,WACiB;AAEjB,UAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,QAAI,MAAM,SAAS,GAAG;AACpB,UAAI,KAAK,uCAAuC,WAAW,EAAE;AAC7D,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,MAAM,CAAC;AAC1B,UAAM,UAAU,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAIvC,UAAM,iBAAiB,UAAU,UAAU,KAAK,KAAK,sBAAsB,UAAU;AACrF,QAAI,CAAC,gBAAgB;AACnB,UAAI,KAAK,qCAAqC,UAAU,EAAE;AAC1D,aAAO;AAAA,IACT;AAEA,WAAO,EAAE,YAAY,SAAS,gBAAgB,YAAY;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBAAsB,YAAgD;AAC5E,UAAM,eAAe,wBAAwB;AAC7C,UAAM,SAAS,aAAa,UAAU;AACtC,QAAI,QAAQ;AACV,UAAI,MAAM,oCAAoC,UAAU,4BAA4B,OAAO,OAAO,SAAS,GAAG;AAC9G,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,SACZ,OACA,UACA,SAC2E;AAG3E,UAAM,cAAc,MAAM,KAAK,mBAAmB,KAAK;AACvD,UAAM,mBAAmB,aAAa,WAAW,MAAM,eAAe;AACtE,UAAM,iBAAiB,aAAa,UAAU,MAAM,KAAK,sBAAsB,KAAK;AAIpF,UAAM,SAAS,MAAM,eAAe;AACpC,UAAM,kBAAkB,WAAW,uBAC7B,OAAO,WAAW,YAAY,WAAW;AAC/C,QAAI,mBAAmB,CAAC,gBAAgB;AACtC,YAAM,IAAI,MAAM,yBAAyB,MAAM,UAAU,yCAAyC;AAAA,IACpG;AAEA,UAAM,kBAAuC;AAAA,MAC3C,GAAG,MAAM;AAAA,MACT,SAAS;AAAA,MACT,GAAI,iBAAiB,EAAE,QAAQ,eAAe,IAAI,CAAC;AAAA,IACrD;AAEA,QAAI,MAAM,eAAe,QAAQ,sBAAsB;AACrD,aAAO,MAAM,KAAK,cAAc,iBAAiB,MAAM,SAAS,UAAU,OAAO;AAAA,IACnF;AAMA,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,kCAAkC,gBAAgB,OAAO;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,mBACZ,OACuD;AACvD,QAAI;AACF,YAAM,iBAAiB,MAAM,8BAA8B;AAC3D,UAAI,CAAC,eAAgB,QAAO;AAE5B,YAAM,SAAS,MAAM,eAAe;AAAA,QAClC,OAAO;AAAA,UACL,UAAU,MAAM;AAAA,UAChB,IAAI,MAAM;AAAA,UACV,KAAK,MAAM,eAAe;AAAA,UAC1B,SAAS,MAAM,eAAe;AAAA,QAChC;AAAA,QACA,KAAK,KAAK;AAAA,MACZ,CAAC;AAED,UAAI,QAAQ,UAAU,QAAQ,SAAS;AACrC,YAAI;AAAA,UACF,4CAA4C,MAAM,WAAW,cAAc,OAAO,UAAU,SAAS,WAAW,OAAO,QAAQ,SAAS;AAAA,QAC1I;AACA,eAAO,EAAE,QAAQ,OAAO,QAAQ,SAAS,OAAO,QAAQ;AAAA,MAC1D;AAAA,IACF,SAAS,KAAK;AACZ,UAAI;AAAA,QACF,kDAAkD,MAAM,WAAW,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3H;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,sBAAsB,OAA8C;AAChF,WAAO,sBAAsB,MAAM,YAAY,MAAM,eAAe,QAAQ,KAAK,aAAa;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WACZ,QACA,SACA,UACA,SACA,cAC2E;AAC3E,UAAM,OAAO,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAC7C,UAAM,MAAM,KAAK,SAAS,KAAK,IAC3B,GAAG,IAAI,sBACP,GAAG,IAAI;AAEX,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,GAAG,OAAO;AAAA,IACZ;AAGA,QAAI,OAAO,UAAU,OAAO,OAAO,WAAW,UAAU;AACtD,UAAI,OAAO,eAAe,OAAO;AAC/B,gBAAQ,eAAe,IAAI,UAAU,OAAO,MAAM;AAAA,MACpD;AAAA,IACF;AAEA,UAAM,OAAO;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA,aAAa,QAAQ,eAAe;AAAA,MACpC,GAAG,8BAA8B,SAAS,QAAQ,aAAa,MAAM;AAAA,QACnE;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,qBAAqB,SAAS,MAAM,IAAI,KAAK,EAAE;AAAA,IACjE;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAalC,UAAM,UAAU,KAAK,UAAU,CAAC,GAAG,SAAS;AAC5C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,KAAK,QACR;AAAA,QACE,aAAa,KAAK,MAAM;AAAA,QACxB,cAAc,KAAK,MAAM;AAAA,QACzB,aAAa,KAAK,MAAM;AAAA,MAC1B,IACA;AAAA,IACN;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cACZ,QACA,SACA,UACA,SAC2E;AAC3E,UAAM,MAAM,GAAG,OAAO,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAEhD,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,qBAAqB;AAAA,MACrB,GAAG,OAAO;AAAA,IACZ;AAGA,QAAI,OAAO,UAAU,OAAO,OAAO,WAAW,UAAU;AACtD,cAAQ,WAAW,IAAI,OAAO;AAAA,IAChC;AAGA,UAAM,gBAAgB,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG;AACjE,UAAM,oBAAoB,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAGpE,UAAM,oBAAoB,kBAAkB,IAAI,CAAC,OAAO;AAAA,MACtD,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,IACb,EAAE;AAEF,UAAM,OAAgC;AAAA,MACpC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY,QAAQ,aAAa;AAAA,MACjC,aAAa,QAAQ,eAAe;AAAA,IACtC;AAEA,QAAI,eAAe;AACjB,WAAK,SAAS;AAAA,IAChB;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,wBAAwB,SAAS,MAAM,IAAI,KAAK,EAAE;AAAA,IACpE;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAWlC,UAAM,UAAU,KAAK,UAAU,CAAC,GAAG;AACnC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,KAAK,QACR;AAAA,QACE,aAAa,KAAK,MAAM;AAAA,QACxB,cAAc,KAAK,MAAM;AAAA,QACzB,cAAc,KAAK,MAAM,gBAAgB,MAAM,KAAK,MAAM,iBAAiB;AAAA,MAC7E,IACA;AAAA,IACN;AAAA,EACF;AACF;","names":[]}
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as ReplaySource, a as ReplayWarning, b as ReplayTurn, O as Orchestrator, C as CompoundingPromotionReport } from './orchestrator-zTa-Qo-1.js';
1
+ import { R as ReplaySource, a as ReplayWarning, b as ReplayTurn, O as Orchestrator, C as CompoundingPromotionReport } from './orchestrator-CIvLFHx3.js';
2
2
  import { M as MemoryGovernanceRunResult, a as MemoryGovernanceSummary, b as MemoryGovernanceMetrics, c as MemoryGovernanceQualityScore, d as MemoryGovernanceReviewQueueEntry, e as MemoryGovernanceAppliedAction, f as MemoryGovernanceTransitionReport, g as MemoryGovernanceManifest, h as MemoryGovernanceRestoreManifest, R as RestoreMemoryGovernanceRunResult } from './memory-projection-store-NxMkbocT.js';
3
3
  import { MemoryStatus, MemoryFile, BehaviorSignalEvent, MemoryActionEvent, MemoryLifecycleEvent } from './types.js';
4
4
  import { Readable, Writable } from 'node:stream';
@@ -634,7 +634,7 @@ declare function runMemoryGovernanceReportCliCommand(options: MemoryGovernanceRe
634
634
  declare function runMemoryGovernanceRestoreCliCommand(options: MemoryGovernanceRestoreCliCommandOptions): Promise<RestoreMemoryGovernanceRunResult>;
635
635
  declare function runMemoryReviewDispositionCliCommand(options: MemoryReviewDispositionCliCommandOptions): Promise<{
636
636
  memoryId: string;
637
- status: "active" | "pending_review" | "rejected" | "quarantined";
637
+ status: "active" | "pending_review" | "quarantined" | "rejected";
638
638
  reasonCode: string | undefined;
639
639
  }>;
640
640
  declare function runMigrateObservationsCliCommand(options: MigrateObservationsCliCommandOptions): Promise<MigrateObservationsResult>;
package/dist/cli.js CHANGED
@@ -3643,7 +3643,7 @@ async function runSemanticRulePromoteCliCommand(options) {
3643
3643
  });
3644
3644
  }
3645
3645
  async function runCompoundingPromoteCliCommand(options) {
3646
- const { CompoundingEngine } = await import("./engine-P26JFSVY.js");
3646
+ const { CompoundingEngine } = await import("./engine-2A6J4XEX.js");
3647
3647
  const config = parseConfig({
3648
3648
  memoryDir: options.memoryDir,
3649
3649
  qmdEnabled: false,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CompoundingEngine,
3
3
  defaultTierMigrationCycleBudget
4
- } from "./chunk-TKO4HZCK.js";
4
+ } from "./chunk-UYSKNO6E.js";
5
5
  import "./chunk-QWUUMMIK.js";
6
6
  import "./chunk-U4PV25RD.js";
7
7
  import "./chunk-ESSMF2FR.js";
@@ -16,4 +16,4 @@ export {
16
16
  CompoundingEngine,
17
17
  defaultTierMigrationCycleBudget
18
18
  };
19
- //# sourceMappingURL=engine-P26JFSVY.js.map
19
+ //# sourceMappingURL=engine-2A6J4XEX.js.map
@@ -1,4 +1,4 @@
1
- import { O as Orchestrator } from './orchestrator-zTa-Qo-1.js';
1
+ import { O as Orchestrator } from './orchestrator-CIvLFHx3.js';
2
2
  import { MemoryCategory, PluginConfig } from './types.js';
3
3
  import './buffer.js';
4
4
  import './storage.js';
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ExtractionEngine
3
- } from "./chunk-QFQVZOGA.js";
3
+ } from "./chunk-6UJQNRIO.js";
4
4
  import "./chunk-MWGVGUIS.js";
5
5
  import "./chunk-763GUIOU.js";
6
6
  import "./chunk-ONRU4L2N.js";
@@ -8,8 +8,9 @@ import "./chunk-MDDAA2AO.js";
8
8
  import "./chunk-2PO5ZRKV.js";
9
9
  import "./chunk-VEWZZM3H.js";
10
10
  import "./chunk-LK6SGL53.js";
11
- import "./chunk-KT4NEUNF.js";
12
- import "./chunk-LU3GQNDQ.js";
11
+ import "./chunk-XUHI52HK.js";
12
+ import "./chunk-M5ZBBBJI.js";
13
+ import "./chunk-OOSWAUYB.js";
13
14
  import "./chunk-Y27UJK6V.js";
14
15
  import "./chunk-UZB5KHKX.js";
15
16
  import "./chunk-MARWOCVP.js";
@@ -74,14 +74,33 @@ declare class FallbackLlmClient {
74
74
  */
75
75
  private parseModelString;
76
76
  /**
77
- * Resolve the API key for a provider, handling OpenClaw secret ref formats.
78
- * Results are cached per provider so exec calls only happen once.
77
+ * Look up a provider from the gateway's materialized models.json, which
78
+ * contains all providers including built-in ones (openai-codex, google-vertex,
79
+ * etc.) that aren't in the user's openclaw.json but are registered by
80
+ * gateway plugins. Returns null if the provider isn't found there either.
79
81
  */
80
- private resolveApiKey;
82
+ private resolveFromModelsJson;
81
83
  /**
82
84
  * Try to call a single model.
85
+ *
86
+ * Uses the gateway's native getRuntimeAuthForModel when available — this
87
+ * handles all provider-specific auth transforms (OAuth token exchange,
88
+ * base URL overrides for codex/copilot/etc.) through the same codepath
89
+ * the gateway itself uses. Falls back to resolveProviderApiKey for
90
+ * simpler providers or when the runtime module isn't loaded.
83
91
  */
84
92
  private tryModel;
93
+ /**
94
+ * Resolve request-ready auth through the gateway's native runtime, which
95
+ * handles provider-specific transforms (OAuth token exchange for codex/copilot,
96
+ * base URL rewrite, etc.). Returns null if the runtime isn't available.
97
+ */
98
+ private resolveRuntimeAuth;
99
+ /**
100
+ * Resolve API key through the existing provider-level resolution (env vars,
101
+ * secret refs, etc.). Used as fallback when gateway runtime auth isn't available.
102
+ */
103
+ private resolveFallbackApiKey;
85
104
  /**
86
105
  * Call OpenAI-compatible API.
87
106
  */
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  FallbackLlmClient
3
- } from "./chunk-KT4NEUNF.js";
4
- import "./chunk-LU3GQNDQ.js";
3
+ } from "./chunk-XUHI52HK.js";
4
+ import "./chunk-M5ZBBBJI.js";
5
+ import "./chunk-OOSWAUYB.js";
5
6
  import "./chunk-Y27UJK6V.js";
6
7
  import "./chunk-UZB5KHKX.js";
7
8
  import "./chunk-MARWOCVP.js";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { parseConfig } from './config.js';
2
- export { O as Orchestrator, d as defaultWorkspaceDir, s as sanitizeSessionKeyForFilename } from './orchestrator-zTa-Qo-1.js';
2
+ export { O as Orchestrator, d as defaultWorkspaceDir, s as sanitizeSessionKeyForFilename } from './orchestrator-CIvLFHx3.js';
3
3
  export { StorageManager } from './storage.js';
4
4
  export { ExtractionEngine } from './extraction.js';
5
5
  export { QmdClient } from './qmd.js';
package/dist/index.js CHANGED
@@ -14,32 +14,32 @@ import {
14
14
  migrateFromEngram,
15
15
  rollbackFromEngramMigration,
16
16
  sanitizeSessionKeyForFilename
17
- } from "./chunk-YAPUAHAY.js";
17
+ } from "./chunk-OTFNI3OO.js";
18
+ import "./chunk-UYSKNO6E.js";
18
19
  import "./chunk-IFFFR3MR.js";
19
- import "./chunk-TKO4HZCK.js";
20
20
  import "./chunk-Z5AAYHUC.js";
21
21
  import "./chunk-4A24LIM2.js";
22
22
  import "./chunk-TPB3I2AC.js";
23
23
  import "./chunk-UHGBNIOS.js";
24
24
  import "./chunk-ZKYI7UVO.js";
25
- import "./chunk-CDW777AI.js";
25
+ import "./chunk-LP47L3ZX.js";
26
26
  import "./chunk-ETOW6ACV.js";
27
+ import "./chunk-GPGBSNKM.js";
28
+ import "./chunk-V3RXWQIE.js";
27
29
  import "./chunk-G3AG3KZN.js";
28
30
  import "./chunk-2CJCWDMR.js";
31
+ import "./chunk-HG2NKWR2.js";
29
32
  import "./chunk-X7XN6YU4.js";
30
33
  import "./chunk-BRK4ODMI.js";
31
34
  import "./chunk-C7VW7C3F.js";
32
- import "./chunk-GPGBSNKM.js";
33
- import "./chunk-V3RXWQIE.js";
34
35
  import "./chunk-YCN4BVDK.js";
35
36
  import "./chunk-L5RPWGFK.js";
36
- import "./chunk-HG2NKWR2.js";
37
37
  import "./chunk-GJR6D6KC.js";
38
38
  import "./chunk-H63EDPFJ.js";
39
39
  import "./chunk-WWIQTB2Y.js";
40
40
  import {
41
41
  ExtractionEngine
42
- } from "./chunk-QFQVZOGA.js";
42
+ } from "./chunk-6UJQNRIO.js";
43
43
  import "./chunk-MWGVGUIS.js";
44
44
  import "./chunk-763GUIOU.js";
45
45
  import "./chunk-ONRU4L2N.js";
@@ -93,8 +93,9 @@ import {
93
93
  } from "./chunk-YNI4S5WT.js";
94
94
  import "./chunk-DORBM6OB.js";
95
95
  import "./chunk-XYIK4LF6.js";
96
- import "./chunk-KT4NEUNF.js";
97
- import "./chunk-LU3GQNDQ.js";
96
+ import "./chunk-XUHI52HK.js";
97
+ import "./chunk-M5ZBBBJI.js";
98
+ import "./chunk-OOSWAUYB.js";
98
99
  import "./chunk-Y27UJK6V.js";
99
100
  import "./chunk-UZB5KHKX.js";
100
101
  import "./chunk-M5KEYE5E.js";