@remnic/core 1.1.9 → 1.1.10

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 (204) hide show
  1. package/dist/access-cli.js +35 -32
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +8 -7
  4. package/dist/access-http.js +17 -14
  5. package/dist/access-mcp.d.ts +8 -7
  6. package/dist/access-mcp.js +16 -13
  7. package/dist/{access-service-BJCIjVRY.d.ts → access-service-BTTNyo1i.d.ts} +5 -3
  8. package/dist/access-service.d.ts +8 -7
  9. package/dist/access-service.js +15 -12
  10. package/dist/active-memory-bridge.d.ts +2 -1
  11. package/dist/active-recall.d.ts +2 -1
  12. package/dist/behavior-learner.d.ts +2 -1
  13. package/dist/behavior-signals.d.ts +2 -1
  14. package/dist/bootstrap.d.ts +7 -6
  15. package/dist/briefing.d.ts +3 -2
  16. package/dist/briefing.js +3 -3
  17. package/dist/buffer-surprise-report.d.ts +2 -1
  18. package/dist/buffer.d.ts +3 -2
  19. package/dist/calibration.d.ts +4 -1
  20. package/dist/calibration.js +10 -5
  21. package/dist/calibration.js.map +1 -1
  22. package/dist/causal-behavior.d.ts +2 -1
  23. package/dist/causal-consolidation.d.ts +5 -2
  24. package/dist/causal-consolidation.js +14 -8
  25. package/dist/causal-consolidation.js.map +1 -1
  26. package/dist/{chunk-ICULSMDG.js → chunk-2YMTO4ZJ.js} +2 -2
  27. package/dist/{chunk-XL3UCAZA.js → chunk-363MWCD3.js} +35 -35
  28. package/dist/{chunk-PHQH2VUO.js → chunk-36CTNQY7.js} +7 -7
  29. package/dist/{chunk-XN4D6Z7X.js → chunk-4DXC6HQQ.js} +5 -3
  30. package/dist/chunk-4DXC6HQQ.js.map +1 -0
  31. package/dist/{chunk-OWGGXPKV.js → chunk-57QNCUEZ.js} +5 -5
  32. package/dist/{chunk-FPWUENQH.js → chunk-5GCNE7CN.js} +90 -486
  33. package/dist/chunk-5GCNE7CN.js.map +1 -0
  34. package/dist/{chunk-LOBRX7VD.js → chunk-5UM2VJ6D.js} +12 -1
  35. package/dist/chunk-5UM2VJ6D.js.map +1 -0
  36. package/dist/{chunk-KMWZXT5T.js → chunk-6XA7UN4Z.js} +2 -2
  37. package/dist/{chunk-G6NX57V2.js → chunk-C5HUWVH2.js} +2 -2
  38. package/dist/{chunk-NN3TS5BM.js → chunk-D54LZC5L.js} +4 -4
  39. package/dist/{chunk-3VRIIII5.js → chunk-ERUDW6DU.js} +65 -5
  40. package/dist/chunk-ERUDW6DU.js.map +1 -0
  41. package/dist/{chunk-U4SZXGEO.js → chunk-EYNQTST2.js} +2 -2
  42. package/dist/chunk-HJYHRE4S.js +647 -0
  43. package/dist/chunk-HJYHRE4S.js.map +1 -0
  44. package/dist/{chunk-M3DK45UM.js → chunk-I6BQZSML.js} +4 -4
  45. package/dist/chunk-IBX3VFOM.js +446 -0
  46. package/dist/chunk-IBX3VFOM.js.map +1 -0
  47. package/dist/{chunk-G3G3LY22.js → chunk-KBYWQWSB.js} +7 -7
  48. package/dist/chunk-KWBPHZUU.js +83 -0
  49. package/dist/chunk-KWBPHZUU.js.map +1 -0
  50. package/dist/{chunk-CTYRIJ5E.js → chunk-LIO5X3CM.js} +2 -2
  51. package/dist/{chunk-MJLUHRSF.js → chunk-MCC6KDQF.js} +2 -2
  52. package/dist/{chunk-J3P6WSFZ.js → chunk-O4XJUPSF.js} +2 -2
  53. package/dist/{chunk-6OAQEOGV.js → chunk-PB5KW5PL.js} +2 -2
  54. package/dist/{chunk-Y3VT6ZCP.js → chunk-PHNGXFQ6.js} +5 -3
  55. package/dist/chunk-PHNGXFQ6.js.map +1 -0
  56. package/dist/{chunk-2MVUXO4H.js → chunk-RXTFCYQF.js} +2 -2
  57. package/dist/{chunk-Q7FJ5ZHM.js → chunk-S3IP6R6K.js} +8 -2
  58. package/dist/{chunk-Q7FJ5ZHM.js.map → chunk-S3IP6R6K.js.map} +1 -1
  59. package/dist/{chunk-ET4BL42V.js → chunk-VQXK37XA.js} +1 -1
  60. package/dist/{chunk-ET4BL42V.js.map → chunk-VQXK37XA.js.map} +1 -1
  61. package/dist/{chunk-FLBYSB2V.js → chunk-VX2IUQFE.js} +94 -8
  62. package/dist/chunk-VX2IUQFE.js.map +1 -0
  63. package/dist/{chunk-QPLYTPYL.js → chunk-WGK4VHGP.js} +77 -15
  64. package/dist/chunk-WGK4VHGP.js.map +1 -0
  65. package/dist/{chunk-7SFAENUZ.js → chunk-WTFWLUSX.js} +2 -2
  66. package/dist/{chunk-A6PGANSE.js → chunk-Y5KDIOKF.js} +3 -3
  67. package/dist/{chunk-KIF7QNKL.js → chunk-Z5S5HNGY.js} +5 -3
  68. package/dist/chunk-Z5S5HNGY.js.map +1 -0
  69. package/dist/{chunk-BIHCWSWA.js → chunk-ZL4S7ARC.js} +3 -3
  70. package/dist/{cli-BojuyOOp.d.ts → cli-BrEwQTnW.d.ts} +4 -4
  71. package/dist/cli.d.ts +9 -8
  72. package/dist/cli.js +27 -25
  73. package/dist/codex-cli-fallback.d.ts +44 -0
  74. package/dist/codex-cli-fallback.js +12 -0
  75. package/dist/{codex-materialize-YVC2wb6n.d.ts → codex-materialize-CQlLTzke.d.ts} +1 -1
  76. package/dist/compression-optimizer.d.ts +2 -1
  77. package/dist/config.d.ts +2 -1
  78. package/dist/consolidation-provenance-check.d.ts +3 -2
  79. package/dist/consolidation-undo.d.ts +3 -2
  80. package/dist/day-summary.d.ts +2 -1
  81. package/dist/delinearize.d.ts +2 -1
  82. package/dist/direct-answer-wiring.d.ts +2 -1
  83. package/dist/direct-answer.d.ts +2 -1
  84. package/dist/embedding-fallback.d.ts +2 -1
  85. package/dist/{engine-EDFFOWDD.js → engine-FOC3IJLA.js} +4 -4
  86. package/dist/entity-retrieval.d.ts +3 -2
  87. package/dist/entity-retrieval.js +3 -3
  88. package/dist/entity-schema.d.ts +2 -1
  89. package/dist/explicit-capture.d.ts +7 -6
  90. package/dist/explicit-cue-recall.js +1 -1
  91. package/dist/extraction-judge-telemetry.d.ts +2 -1
  92. package/dist/extraction-judge-training.d.ts +2 -1
  93. package/dist/extraction-judge.d.ts +2 -1
  94. package/dist/extraction.d.ts +2 -1
  95. package/dist/extraction.js +6 -4
  96. package/dist/fallback-llm.d.ts +8 -1
  97. package/dist/fallback-llm.js +5 -3
  98. package/dist/identity-continuity.d.ts +2 -1
  99. package/dist/importance.d.ts +2 -1
  100. package/dist/index-1qIcnbG1.d.ts +34 -0
  101. package/dist/index.d.ts +15 -13
  102. package/dist/index.js +57 -50
  103. package/dist/index.js.map +1 -1
  104. package/dist/intent.d.ts +2 -1
  105. package/dist/lifecycle.d.ts +2 -1
  106. package/dist/live-connectors-runner.d.ts +2 -1
  107. package/dist/local-llm.d.ts +2 -1
  108. package/dist/memory-action-policy.d.ts +2 -1
  109. package/dist/memory-cache.d.ts +2 -1
  110. package/dist/{memory-governance-AAQPBZEP.js → memory-governance-F3QOJGEY.js} +4 -4
  111. package/dist/memory-governance-F3QOJGEY.js.map +1 -0
  112. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  113. package/dist/{memory-projection-store-BW8u5U0u.d.ts → memory-projection-store-CY8TU40w.d.ts} +1 -1
  114. package/dist/memory-projection-store.d.ts +3 -2
  115. package/dist/memory-worth-outcomes.d.ts +3 -2
  116. package/dist/models-json.d.ts +2 -1
  117. package/dist/native-knowledge.d.ts +2 -1
  118. package/dist/objective-state-writers.d.ts +23 -1
  119. package/dist/objective-state-writers.js +10 -306
  120. package/dist/objective-state-writers.js.map +1 -1
  121. package/dist/objective-state.d.ts +7 -1
  122. package/dist/objective-state.js +3 -1
  123. package/dist/operator-toolkit.d.ts +3 -2
  124. package/dist/operator-toolkit.js +6 -6
  125. package/dist/{orchestrator-CYqmqxco.d.ts → orchestrator-6IvQ-Phj.d.ts} +4 -3
  126. package/dist/orchestrator.d.ts +7 -6
  127. package/dist/orchestrator.js +29 -27
  128. package/dist/patterns-cli.d.ts +2 -1
  129. package/dist/policy-runtime.d.ts +2 -1
  130. package/dist/{port-Br27H8dy.d.ts → port-B6VEDIkC.d.ts} +1 -1
  131. package/dist/qmd-recall-cache.d.ts +3 -2
  132. package/dist/qmd.d.ts +3 -2
  133. package/dist/recall-disclosure-escalation.d.ts +2 -1
  134. package/dist/recall-explain-renderer.d.ts +2 -1
  135. package/dist/recall-explain-renderer.js +3 -3
  136. package/dist/recall-state.d.ts +2 -1
  137. package/dist/recall-tag-filter.d.ts +2 -1
  138. package/dist/recall-xray-cli.d.ts +2 -1
  139. package/dist/recall-xray-cli.js +4 -4
  140. package/dist/recall-xray-renderer.d.ts +2 -1
  141. package/dist/recall-xray-renderer.js +3 -3
  142. package/dist/recall-xray.d.ts +2 -1
  143. package/dist/recall-xray.js +2 -2
  144. package/dist/resolve-auth-token.d.ts +2 -1
  145. package/dist/resolve-provider-secret.d.ts +2 -1
  146. package/dist/resolve-provider-secret.js +3 -1
  147. package/dist/resume-bundles.js +3 -3
  148. package/dist/retrieval-agents.d.ts +3 -2
  149. package/dist/retrieval-tiers.d.ts +2 -1
  150. package/dist/{semantic-consolidation-GPcLr9BQ.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +2 -2
  151. package/dist/semantic-consolidation.d.ts +4 -3
  152. package/dist/semantic-consolidation.js +3 -3
  153. package/dist/semantic-rule-promotion.js +3 -3
  154. package/dist/semantic-rule-verifier.d.ts +2 -1
  155. package/dist/semantic-rule-verifier.js +3 -3
  156. package/dist/session-observer-bands.d.ts +2 -1
  157. package/dist/session-observer-state.d.ts +2 -1
  158. package/dist/signal.d.ts +2 -1
  159. package/dist/storage.d.ts +3 -2
  160. package/dist/storage.js +2 -2
  161. package/dist/summarizer.d.ts +2 -1
  162. package/dist/summarizer.js +6 -4
  163. package/dist/summary-snapshot.d.ts +2 -1
  164. package/dist/temporal-supersession.d.ts +3 -2
  165. package/dist/temporal-validity.d.ts +2 -1
  166. package/dist/threading.d.ts +2 -1
  167. package/dist/tier-migration.d.ts +4 -3
  168. package/dist/tier-routing.d.ts +2 -1
  169. package/dist/topics.d.ts +2 -1
  170. package/dist/transcript.d.ts +2 -1
  171. package/dist/types.d.ts +2693 -1
  172. package/dist/types.js +1 -1
  173. package/dist/utility-runtime.d.ts +2 -1
  174. package/dist/verified-recall.js +3 -3
  175. package/package.json +1 -1
  176. package/dist/chunk-3VRIIII5.js.map +0 -1
  177. package/dist/chunk-FLBYSB2V.js.map +0 -1
  178. package/dist/chunk-FPWUENQH.js.map +0 -1
  179. package/dist/chunk-KIF7QNKL.js.map +0 -1
  180. package/dist/chunk-LOBRX7VD.js.map +0 -1
  181. package/dist/chunk-QPLYTPYL.js.map +0 -1
  182. package/dist/chunk-XN4D6Z7X.js.map +0 -1
  183. package/dist/chunk-Y3VT6ZCP.js.map +0 -1
  184. package/dist/types-Bmp9ssU2.d.ts +0 -2714
  185. /package/dist/{chunk-ICULSMDG.js.map → chunk-2YMTO4ZJ.js.map} +0 -0
  186. /package/dist/{chunk-XL3UCAZA.js.map → chunk-363MWCD3.js.map} +0 -0
  187. /package/dist/{chunk-PHQH2VUO.js.map → chunk-36CTNQY7.js.map} +0 -0
  188. /package/dist/{chunk-OWGGXPKV.js.map → chunk-57QNCUEZ.js.map} +0 -0
  189. /package/dist/{chunk-KMWZXT5T.js.map → chunk-6XA7UN4Z.js.map} +0 -0
  190. /package/dist/{chunk-G6NX57V2.js.map → chunk-C5HUWVH2.js.map} +0 -0
  191. /package/dist/{chunk-NN3TS5BM.js.map → chunk-D54LZC5L.js.map} +0 -0
  192. /package/dist/{chunk-U4SZXGEO.js.map → chunk-EYNQTST2.js.map} +0 -0
  193. /package/dist/{chunk-M3DK45UM.js.map → chunk-I6BQZSML.js.map} +0 -0
  194. /package/dist/{chunk-G3G3LY22.js.map → chunk-KBYWQWSB.js.map} +0 -0
  195. /package/dist/{chunk-CTYRIJ5E.js.map → chunk-LIO5X3CM.js.map} +0 -0
  196. /package/dist/{chunk-MJLUHRSF.js.map → chunk-MCC6KDQF.js.map} +0 -0
  197. /package/dist/{chunk-J3P6WSFZ.js.map → chunk-O4XJUPSF.js.map} +0 -0
  198. /package/dist/{chunk-6OAQEOGV.js.map → chunk-PB5KW5PL.js.map} +0 -0
  199. /package/dist/{chunk-2MVUXO4H.js.map → chunk-RXTFCYQF.js.map} +0 -0
  200. /package/dist/{chunk-7SFAENUZ.js.map → chunk-WTFWLUSX.js.map} +0 -0
  201. /package/dist/{chunk-A6PGANSE.js.map → chunk-Y5KDIOKF.js.map} +0 -0
  202. /package/dist/{chunk-BIHCWSWA.js.map → chunk-ZL4S7ARC.js.map} +0 -0
  203. /package/dist/{engine-EDFFOWDD.js.map → codex-cli-fallback.js.map} +0 -0
  204. /package/dist/{memory-governance-AAQPBZEP.js.map → engine-FOC3IJLA.js.map} +0 -0
@@ -1,23 +1,33 @@
1
1
  import {
2
2
  getGatewayRuntimeAuthForModel,
3
3
  resolveProviderApiKey
4
- } from "./chunk-Q7FJ5ZHM.js";
5
- import {
6
- loadModelsJsonProviders
7
- } from "./chunk-7SI52C65.js";
4
+ } from "./chunk-S3IP6R6K.js";
8
5
  import {
9
6
  buildChatCompletionTemperature,
10
7
  buildChatCompletionTokenLimit,
11
8
  shouldAssumeOpenAiChatCompletions
12
9
  } from "./chunk-L2EXJQJP.js";
10
+ import {
11
+ loadModelsJsonProviders
12
+ } from "./chunk-7SI52C65.js";
13
13
  import {
14
14
  extractJsonCandidates
15
15
  } from "./chunk-UZB5KHKX.js";
16
+ import {
17
+ callCodexCliFallback
18
+ } from "./chunk-KWBPHZUU.js";
19
+ import {
20
+ expandTildePath
21
+ } from "./chunk-IXEJRKCZ.js";
22
+ import {
23
+ resolveHomeDir
24
+ } from "./chunk-MARWOCVP.js";
16
25
  import {
17
26
  log
18
27
  } from "./chunk-2ODBA7MQ.js";
19
28
 
20
29
  // src/fallback-llm.ts
30
+ import path from "path";
21
31
  var PROVIDER_ALIASES = {
22
32
  "openai-codex": ["codex"],
23
33
  codex: ["openai-codex"],
@@ -39,7 +49,10 @@ var FallbackLlmClient = class {
39
49
  runtimeContext;
40
50
  constructor(gatewayConfig, runtimeContext = {}) {
41
51
  this.gatewayConfig = gatewayConfig;
42
- this.runtimeContext = runtimeContext;
52
+ this.runtimeContext = {
53
+ ...runtimeContext,
54
+ workspaceDir: normalizeRuntimePath(runtimeContext.workspaceDir) ?? readGatewayWorkspaceDir(gatewayConfig) ?? defaultOpenClawWorkspaceDir()
55
+ };
43
56
  }
44
57
  /**
45
58
  * Check if fallback is available (gateway config has at least one model).
@@ -270,9 +283,9 @@ var FallbackLlmClient = class {
270
283
  * simpler providers or when the runtime module isn't loaded.
271
284
  */
272
285
  async tryModel(model, messages, options) {
273
- const runtimeAuth = await this.resolveRuntimeAuth(model);
286
+ const runtimeAuth = model.providerConfig.api === "codex-cli" ? null : await this.resolveRuntimeAuth(model);
274
287
  const effectiveBaseUrl = runtimeAuth?.baseUrl ?? model.providerConfig.baseUrl;
275
- const resolvedApiKey = runtimeAuth?.apiKey ?? await this.resolveFallbackApiKey(model);
288
+ const resolvedApiKey = runtimeAuth?.apiKey ?? (model.providerConfig.api === "codex-cli" && model.providerConfig.apiKey === void 0 ? void 0 : await this.resolveFallbackApiKey(model));
276
289
  const rawKey = model.providerConfig.apiKey;
277
290
  const needsResolution = rawKey === "secretref-managed" || typeof rawKey === "object" && rawKey !== null;
278
291
  if (needsResolution && !resolvedApiKey) {
@@ -286,6 +299,17 @@ var FallbackLlmClient = class {
286
299
  if (model.providerConfig.api === "anthropic-messages") {
287
300
  return await this.callAnthropic(effectiveConfig, model.modelId, messages, options);
288
301
  }
302
+ if (model.providerConfig.api === "codex-cli") {
303
+ return await callCodexCliFallback(
304
+ effectiveConfig,
305
+ model.modelId,
306
+ messages,
307
+ { timeoutMs: options.timeoutMs }
308
+ );
309
+ }
310
+ if (model.providerConfig.api === "ollama-chat") {
311
+ return await this.callOllamaChat(effectiveConfig, model.modelId, messages, options);
312
+ }
289
313
  if (model.providerConfig.api === "openai-responses" || model.providerConfig.api === "openai-codex-responses" || model.providerConfig.api === "azure-openai-responses") {
290
314
  return await this.callOpenAIResponses(
291
315
  effectiveConfig,
@@ -394,6 +418,55 @@ var FallbackLlmClient = class {
394
418
  } : void 0
395
419
  };
396
420
  }
421
+ /**
422
+ * Call Ollama's native /api/chat transport. This lets benchmark-isolated
423
+ * gateway configs route Remnic's own internal LLM calls to Ollama Cloud
424
+ * without requiring an OpenAI-compatible shim.
425
+ */
426
+ async callOllamaChat(config, modelId, messages, options) {
427
+ const base = config.baseUrl.replace(/\/$/, "");
428
+ const url = base.endsWith("/api") ? `${base}/chat` : `${base}/api/chat`;
429
+ const headers = {
430
+ "Content-Type": "application/json",
431
+ ...config.headers
432
+ };
433
+ if (config.apiKey && typeof config.apiKey === "string" && config.authHeader !== false) {
434
+ headers.Authorization = `Bearer ${config.apiKey}`;
435
+ }
436
+ const response = await fetch(url, {
437
+ method: "POST",
438
+ headers,
439
+ body: JSON.stringify({
440
+ model: modelId,
441
+ messages,
442
+ stream: false,
443
+ ...config.disableThinking ? { think: false } : {},
444
+ options: {
445
+ temperature: options.temperature ?? 0.3,
446
+ num_predict: options.maxTokens ?? 4096
447
+ }
448
+ })
449
+ });
450
+ if (!response.ok) {
451
+ const error = await response.text();
452
+ throw new Error(`Ollama API error: ${response.status} ${error}`);
453
+ }
454
+ const data = await response.json();
455
+ const content = data.message?.content ?? data.response;
456
+ if (!content) {
457
+ throw new Error("Empty response from Ollama API");
458
+ }
459
+ const inputTokens = data.prompt_eval_count ?? 0;
460
+ const outputTokens = data.eval_count ?? 0;
461
+ return {
462
+ content,
463
+ usage: {
464
+ inputTokens,
465
+ outputTokens,
466
+ totalTokens: inputTokens + outputTokens
467
+ }
468
+ };
469
+ }
397
470
  /**
398
471
  * Call an OpenAI-compatible Responses API.
399
472
  */
@@ -502,6 +575,19 @@ var FallbackLlmClient = class {
502
575
  };
503
576
  }
504
577
  };
578
+ function normalizeRuntimePath(value) {
579
+ if (typeof value !== "string") return void 0;
580
+ const trimmed = value.trim();
581
+ return trimmed.length > 0 ? expandTildePath(trimmed) : void 0;
582
+ }
583
+ function readGatewayWorkspaceDir(gatewayConfig) {
584
+ if (!gatewayConfig || typeof gatewayConfig !== "object") return void 0;
585
+ const raw = gatewayConfig;
586
+ return normalizeRuntimePath(raw.workspaceDir) ?? normalizeRuntimePath(raw.workspacePath) ?? normalizeRuntimePath(raw.workspace);
587
+ }
588
+ function defaultOpenClawWorkspaceDir() {
589
+ return path.join(resolveHomeDir(), ".openclaw", "workspace");
590
+ }
505
591
  function extractResponsesOutputText(data) {
506
592
  if (typeof data.output_text === "string" && data.output_text.trim().length > 0) {
507
593
  return data.output_text;
@@ -524,4 +610,4 @@ function extractResponsesOutputText(data) {
524
610
  export {
525
611
  FallbackLlmClient
526
612
  };
527
- //# sourceMappingURL=chunk-FLBYSB2V.js.map
613
+ //# sourceMappingURL=chunk-VX2IUQFE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fallback-llm.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport path from \"node:path\";\nimport type { GatewayConfig, ModelProviderConfig, AgentPersona } from \"./types.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport {\n buildChatCompletionTemperature,\n buildChatCompletionTokenLimit,\n shouldAssumeOpenAiChatCompletions,\n} from \"./openai-chat-compat.js\";\nimport { resolveProviderApiKey, getGatewayRuntimeAuthForModel } from \"./resolve-provider-secret.js\";\nimport { loadModelsJsonProviders } from \"./models-json.js\";\nimport { callCodexCliFallback } from \"./codex-cli-fallback.js\";\nimport { resolveHomeDir } from \"./runtime/env.js\";\nimport { expandTildePath } from \"./utils/path.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\nexport interface FallbackLlmRuntimeContext {\n agentDir?: string;\n workspaceDir?: string;\n}\n\ninterface ModelRef {\n providerId: string;\n modelId: string;\n providerConfig: ModelProviderConfig;\n modelString: string;\n}\n\nconst PROVIDER_ALIASES: Record<string, readonly string[]> = {\n \"openai-codex\": [\"codex\"],\n codex: [\"openai-codex\"],\n \"claude-cli\": [\"anthropic\"],\n};\n\nconst LEGACY_PROVIDER_IDS = new Set([\"openai-codex\", \"claude-cli\"]);\n\nconst MANAGED_SECRETREF_MARKER = [\"secretref\", \"managed\"].join(\"-\");\nconst PROVIDER_API_KEY_FIELD = [\"api\", \"Key\"].join(\"\") as keyof ModelProviderConfig;\n\nconst BUILT_IN_PROVIDER_FALLBACKS: Record<string, ModelProviderConfig> = {\n anthropic: {\n baseUrl: \"https://api.anthropic.com/v1\",\n api: \"anthropic-messages\",\n models: [],\n [PROVIDER_API_KEY_FIELD]: MANAGED_SECRETREF_MARKER,\n },\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 private runtimeContext: FallbackLlmRuntimeContext;\n\n constructor(\n gatewayConfig?: GatewayConfig,\n runtimeContext: FallbackLlmRuntimeContext = {},\n ) {\n this.gatewayConfig = gatewayConfig;\n this.runtimeContext = {\n ...runtimeContext,\n workspaceDir:\n normalizeRuntimePath(runtimeContext.workspaceDir) ??\n readGatewayWorkspaceDir(gatewayConfig) ??\n defaultOpenClawWorkspaceDir(),\n };\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 requestedProviderId = parts[0];\n const modelId = parts.slice(1).join(\"/\"); // Handle cases like \"openai/gpt-5.2-turbo\"\n\n // Respect the active gateway config first so profile-local overrides and\n // credentials win. Fall back to the materialized models.json only when\n // the provider is absent from the loaded config (for built-in providers\n // registered by the gateway at runtime).\n const resolvedProvider = this.resolveProviderConfig(requestedProviderId, providers);\n const providerConfig = resolvedProvider?.config;\n if (!providerConfig) {\n log.warn(\n `fallback LLM: provider not found: ${requestedProviderId} ` +\n `(tried: ${this.providerResolutionCandidates(requestedProviderId).join(\", \")})`,\n );\n return null;\n }\n\n return {\n providerId: resolvedProvider.providerId,\n modelId,\n providerConfig,\n modelString,\n };\n }\n\n private resolveProviderConfig(\n providerId: string,\n providers: Record<string, ModelProviderConfig>,\n ): { providerId: string; config: ModelProviderConfig } | null {\n const candidates = this.providerResolutionCandidates(providerId);\n const aliasCandidates = candidates.filter((candidate) => candidate !== providerId);\n const fallbackCandidates = LEGACY_PROVIDER_IDS.has(providerId)\n ? [...aliasCandidates, providerId]\n : [providerId, ...aliasCandidates];\n for (const candidate of candidates) {\n const config = providers[candidate];\n if (config) {\n if (candidate !== providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via alias \"${candidate}\"`);\n }\n return { providerId: candidate, config };\n }\n }\n for (const candidate of fallbackCandidates) {\n const config = this.resolveFromModelsJson(candidate);\n if (config) {\n if (candidate !== providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via models.json alias \"${candidate}\"`);\n }\n return { providerId: candidate, config };\n }\n const builtInConfig = BUILT_IN_PROVIDER_FALLBACKS[candidate];\n if (builtInConfig) {\n if (candidate === providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved from built-in defaults`);\n return { providerId, config: builtInConfig };\n }\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via built-in alias \"${candidate}\"`);\n return { providerId: candidate, config: builtInConfig };\n }\n }\n return null;\n }\n\n private providerResolutionCandidates(providerId: string): string[] {\n const candidates = [providerId, ...(PROVIDER_ALIASES[providerId] ?? [])];\n return [...new Set(candidates)];\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 = model.providerConfig.api === \"codex-cli\"\n ? null\n : await this.resolveRuntimeAuth(model);\n const effectiveBaseUrl = runtimeAuth?.baseUrl ?? model.providerConfig.baseUrl;\n const resolvedApiKey = runtimeAuth?.apiKey\n ?? (\n model.providerConfig.api === \"codex-cli\" && model.providerConfig.apiKey === undefined\n ? undefined\n : await this.resolveFallbackApiKey(model)\n );\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 if (model.providerConfig.api === \"codex-cli\") {\n return await callCodexCliFallback(\n effectiveConfig,\n model.modelId,\n messages,\n { timeoutMs: options.timeoutMs },\n );\n }\n\n if (model.providerConfig.api === \"ollama-chat\") {\n return await this.callOllamaChat(effectiveConfig, model.modelId, messages, options);\n }\n\n if (\n model.providerConfig.api === \"openai-responses\" ||\n model.providerConfig.api === \"openai-codex-responses\" ||\n model.providerConfig.api === \"azure-openai-responses\"\n ) {\n return await this.callOpenAIResponses(\n effectiveConfig,\n model.modelId,\n messages,\n options,\n );\n }\n\n // For OpenAI-compatible chat-completions APIs (openai-completions,\n // ollama, etc.) and unknown formats, use chat completions — the gateway's\n // runtime auth resolver returns request-ready base URL and credentials for\n // 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 workspaceDir: this.runtimeContext.workspaceDir,\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(\n model.providerId,\n model.providerConfig.apiKey,\n this.gatewayConfig,\n this.runtimeContext.agentDir,\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 ...buildChatCompletionTemperature(modelId, options.temperature ?? 0.3, {\n assumeOpenAI,\n }),\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 Ollama's native /api/chat transport. This lets benchmark-isolated\n * gateway configs route Remnic's own internal LLM calls to Ollama Cloud\n * without requiring an OpenAI-compatible shim.\n */\n private async callOllamaChat(\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 base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/api\") ? `${base}/chat` : `${base}/api/chat`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n if (config.apiKey && typeof config.apiKey === \"string\" && config.authHeader !== false) {\n headers.Authorization = `Bearer ${config.apiKey}`;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n model: modelId,\n messages,\n stream: false,\n ...(config.disableThinking ? { think: false } : {}),\n options: {\n temperature: options.temperature ?? 0.3,\n num_predict: options.maxTokens ?? 4096,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Ollama API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n message?: { content?: string };\n response?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n };\n const content = data.message?.content ?? data.response;\n if (!content) {\n throw new Error(\"Empty response from Ollama API\");\n }\n\n const inputTokens = data.prompt_eval_count ?? 0;\n const outputTokens = data.eval_count ?? 0;\n return {\n content,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n };\n }\n\n /**\n * Call an OpenAI-compatible Responses API.\n */\n private async callOpenAIResponses(\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 base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/responses`\n : `${base}/v1/responses`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n\n if (config.apiKey && typeof config.apiKey === \"string\" && config.authHeader !== false) {\n headers[\"Authorization\"] = `Bearer ${config.apiKey}`;\n }\n\n const instructions = messages\n .filter((message) => message.role === \"system\")\n .map((message) => message.content)\n .join(\"\\n\\n\")\n .trim();\n const input = messages\n .filter((message) => message.role !== \"system\")\n .map((message) => ({\n role: message.role,\n content: [{\n type: message.role === \"assistant\" ? \"output_text\" : \"input_text\",\n text: message.content,\n }],\n }));\n\n const body: Record<string, unknown> = {\n model: modelId,\n input,\n max_output_tokens: Math.max(0, Math.floor(options.maxTokens ?? 4096)),\n ...buildChatCompletionTemperature(modelId, options.temperature ?? 0.3, {\n assumeOpenAI: shouldAssumeOpenAiChatCompletions(config.baseUrl),\n }),\n };\n if (instructions.length > 0) {\n body.instructions = instructions;\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 Responses API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n output_text?: string;\n output?: Array<{\n type?: string;\n text?: string;\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const outputText = extractResponsesOutputText(data);\n if (!outputText) {\n throw new Error(\"Empty response from OpenAI Responses API\");\n }\n\n return {\n content: outputText,\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_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 base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/messages`\n : `${base}/v1/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\nfunction normalizeRuntimePath(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? expandTildePath(trimmed) : undefined;\n}\n\nfunction readGatewayWorkspaceDir(gatewayConfig: GatewayConfig | undefined): string | undefined {\n if (!gatewayConfig || typeof gatewayConfig !== \"object\") return undefined;\n const raw = gatewayConfig as Record<string, unknown>;\n return (\n normalizeRuntimePath(raw.workspaceDir) ??\n normalizeRuntimePath(raw.workspacePath) ??\n normalizeRuntimePath(raw.workspace)\n );\n}\n\nfunction defaultOpenClawWorkspaceDir(): string {\n return path.join(resolveHomeDir(), \".openclaw\", \"workspace\");\n}\n\nfunction extractResponsesOutputText(data: {\n output_text?: string;\n output?: Array<{\n type?: string;\n text?: string;\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n }>;\n}): string | null {\n if (typeof data.output_text === \"string\" && data.output_text.trim().length > 0) {\n return data.output_text;\n }\n\n const chunks: string[] = [];\n for (const item of data.output ?? []) {\n if (typeof item.text === \"string\" && item.text.trim().length > 0) {\n chunks.push(item.text);\n }\n for (const part of item.content ?? []) {\n if (\n (part.type === \"output_text\" || part.type === \"text\") &&\n typeof part.text === \"string\" &&\n part.text.trim().length > 0\n ) {\n chunks.push(part.text);\n }\n }\n }\n\n const joined = chunks.join(\"\\n\").trim();\n return joined.length > 0 ? joined : null;\n}\n"],"mappings":"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","names":[]}
@@ -6,12 +6,12 @@ import {
6
6
  normalizeTags,
7
7
  parseTagMatch
8
8
  } from "./chunk-BT7NVCML.js";
9
+ import {
10
+ toRecallExplainJson
11
+ } from "./chunk-O4XJUPSF.js";
9
12
  import {
10
13
  decideDisclosureEscalation
11
14
  } from "./chunk-H7XKCNR6.js";
12
- import {
13
- toRecallExplainJson
14
- } from "./chunk-J3P6WSFZ.js";
15
15
  import {
16
16
  buildProposedActions,
17
17
  buildQualityScore,
@@ -19,11 +19,11 @@ import {
19
19
  listMemoryGovernanceRuns,
20
20
  readMemoryGovernanceRunArtifact,
21
21
  runMemoryGovernance
22
- } from "./chunk-U4SZXGEO.js";
22
+ } from "./chunk-EYNQTST2.js";
23
23
  import {
24
24
  clusterByKey,
25
25
  resolveGitContext
26
- } from "./chunk-NN3TS5BM.js";
26
+ } from "./chunk-D54LZC5L.js";
27
27
  import {
28
28
  getTrustZoneStoreStatus,
29
29
  isTrustZoneName,
@@ -35,24 +35,30 @@ import {
35
35
  } from "./chunk-EQINRHYR.js";
36
36
  import {
37
37
  estimateRecallTokens
38
- } from "./chunk-ICULSMDG.js";
38
+ } from "./chunk-2YMTO4ZJ.js";
39
39
  import {
40
40
  recordMemoryOutcome
41
41
  } from "./chunk-EIR5VLIH.js";
42
+ import {
43
+ recordObjectiveStateSnapshotsFromObservedMessages
44
+ } from "./chunk-HJYHRE4S.js";
45
+ import {
46
+ objectiveStateStoreOverrideForNamespace
47
+ } from "./chunk-5UM2VJ6D.js";
42
48
  import {
43
49
  buildGraphSnapshot
44
50
  } from "./chunk-PCUKNJAZ.js";
45
- import {
46
- persistExplicitCapture,
47
- queueExplicitCaptureForReview,
48
- validateExplicitCaptureInput
49
- } from "./chunk-GVPWB7EY.js";
50
51
  import {
51
52
  wrapWorkLayerContext
52
53
  } from "./chunk-EEQLFRUM.js";
53
54
  import {
54
55
  formatProfileTraceAscii
55
56
  } from "./chunk-NBNN5GOB.js";
57
+ import {
58
+ persistExplicitCapture,
59
+ queueExplicitCaptureForReview,
60
+ validateExplicitCaptureInput
61
+ } from "./chunk-GVPWB7EY.js";
56
62
  import {
57
63
  buildProcedurePersistBody,
58
64
  normalizeProcedureSteps
@@ -79,14 +85,14 @@ import {
79
85
  buildBriefing,
80
86
  parseBriefingFocus,
81
87
  parseBriefingWindow
82
- } from "./chunk-7SFAENUZ.js";
88
+ } from "./chunk-WTFWLUSX.js";
83
89
  import {
84
90
  parseEntityFile
85
- } from "./chunk-MJLUHRSF.js";
91
+ } from "./chunk-MCC6KDQF.js";
86
92
  import {
87
93
  DEFAULT_RECALL_DISCLOSURE,
88
94
  isRecallDisclosure
89
- } from "./chunk-ET4BL42V.js";
95
+ } from "./chunk-VQXK37XA.js";
90
96
  import {
91
97
  inferMemoryStatus,
92
98
  toMemoryPathRel
@@ -1160,6 +1166,24 @@ var EngramAccessService = class {
1160
1166
  }
1161
1167
  return resolved;
1162
1168
  }
1169
+ async objectiveStateStoreLocationForNamespace(namespace) {
1170
+ if (!this.orchestrator.config.namespacesEnabled) {
1171
+ return {
1172
+ memoryDir: this.orchestrator.config.memoryDir,
1173
+ objectiveStateStoreDir: this.orchestrator.config.objectiveStateStoreDir
1174
+ };
1175
+ }
1176
+ const storage = await this.orchestrator.getStorage(namespace);
1177
+ return {
1178
+ memoryDir: storage.dir,
1179
+ objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({
1180
+ memoryDir: this.orchestrator.config.memoryDir,
1181
+ configuredStoreDir: this.orchestrator.config.objectiveStateStoreDir,
1182
+ namespacesEnabled: this.orchestrator.config.namespacesEnabled,
1183
+ namespace
1184
+ })
1185
+ };
1186
+ }
1163
1187
  resolveReadableNamespace(namespace, principal) {
1164
1188
  const resolved = this.resolveNamespace(namespace);
1165
1189
  const namespacesEnabled = this.orchestrator.config.namespacesEnabled;
@@ -2889,16 +2913,54 @@ var EngramAccessService = class {
2889
2913
  throw new EngramAccessInputError(`invalid message role: ${msg.role} (expected 'user' or 'assistant')`);
2890
2914
  }
2891
2915
  }
2916
+ const hasExplicitNamespace = typeof request.namespace === "string" && request.namespace.trim().length > 0;
2917
+ const principal = this.resolveWritePrincipal(
2918
+ request.sessionKey,
2919
+ request.authenticatedPrincipal
2920
+ );
2892
2921
  const namespace = this.resolveWritableNamespace(
2893
2922
  request.namespace,
2894
2923
  request.sessionKey,
2895
2924
  request.authenticatedPrincipal
2896
2925
  );
2926
+ const shouldWriteObjectiveState = this.orchestrator.config.objectiveStateMemoryEnabled === true && this.orchestrator.config.objectiveStateSnapshotWritesEnabled === true;
2927
+ const objectiveStateBaseNamespace = hasExplicitNamespace ? namespace : defaultNamespaceForPrincipal(principal, this.orchestrator.config);
2928
+ if (shouldWriteObjectiveState && !hasExplicitNamespace && !canWriteNamespace(
2929
+ principal,
2930
+ objectiveStateBaseNamespace,
2931
+ this.orchestrator.config
2932
+ )) {
2933
+ throw new EngramAccessInputError(
2934
+ `namespace is not writable: ${objectiveStateBaseNamespace}`
2935
+ );
2936
+ }
2897
2937
  await this.maybeAttachCodingContext(request.sessionKey, {
2898
2938
  cwd: request.cwd,
2899
2939
  projectTag: request.projectTag
2900
2940
  });
2941
+ const objectiveStateNamespace = hasExplicitNamespace ? namespace : this.orchestrator.applyCodingNamespaceOverlay(
2942
+ request.sessionKey,
2943
+ objectiveStateBaseNamespace
2944
+ );
2901
2945
  const lcmSessionKey = namespace !== this.orchestrator.config.defaultNamespace ? `${namespace}:${request.sessionKey}` : request.sessionKey;
2946
+ if (shouldWriteObjectiveState) {
2947
+ try {
2948
+ const objectiveStateLocation = await this.objectiveStateStoreLocationForNamespace(
2949
+ objectiveStateNamespace
2950
+ );
2951
+ await recordObjectiveStateSnapshotsFromObservedMessages({
2952
+ memoryDir: objectiveStateLocation.memoryDir,
2953
+ objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
2954
+ objectiveStateMemoryEnabled: this.orchestrator.config.objectiveStateMemoryEnabled,
2955
+ objectiveStateSnapshotWritesEnabled: this.orchestrator.config.objectiveStateSnapshotWritesEnabled,
2956
+ sessionKey: request.sessionKey,
2957
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
2958
+ messages: request.messages
2959
+ });
2960
+ } catch (err) {
2961
+ log.error(`access-observe objective-state snapshot write failed: ${err}`);
2962
+ }
2963
+ }
2902
2964
  let lcmArchived = false;
2903
2965
  if (this.orchestrator.lcmEngine && this.orchestrator.lcmEngine.enabled) {
2904
2966
  try {
@@ -4227,4 +4289,4 @@ export {
4227
4289
  shapeMemorySummary,
4228
4290
  EngramAccessService
4229
4291
  };
4230
- //# sourceMappingURL=chunk-QPLYTPYL.js.map
4292
+ //# sourceMappingURL=chunk-WGK4VHGP.js.map