@remnic/plugin-openclaw 1.0.32 → 1.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -90,7 +90,7 @@ import {
90
90
  parseOperatorAwareConsolidationResponse,
91
91
  renderExtensionsFooter,
92
92
  resolveExtensionsRoot
93
- } from "./chunk-HI5HX3S7.js";
93
+ } from "./chunk-NDZNURDM.js";
94
94
  import {
95
95
  BoxBuilder,
96
96
  countRecallTokenOverlap,
@@ -115,7 +115,7 @@ import {
115
115
  CompoundingEngine,
116
116
  SharedContextManager,
117
117
  defaultTierMigrationCycleBudget
118
- } from "./chunk-UVQXEQBQ.js";
118
+ } from "./chunk-7NMHI4IC.js";
119
119
  import {
120
120
  ZodError,
121
121
  external_exports
@@ -132,7 +132,7 @@ import {
132
132
  buildChatCompletionTokenLimit,
133
133
  findGatewayRuntimeModules,
134
134
  shouldAssumeOpenAiChatCompletions
135
- } from "./chunk-24MGN4E3.js";
135
+ } from "./chunk-7NUFIRM3.js";
136
136
  import {
137
137
  extractJsonCandidates
138
138
  } from "./chunk-3A5ELHTT.js";
@@ -202,15 +202,13 @@ import {
202
202
  listConnectorStates,
203
203
  readConnectorState,
204
204
  writeConnectorState
205
- } from "./chunk-37NKFWSO.js";
206
- import {
207
- expandTildePath
208
- } from "./chunk-OEI7GLV2.js";
205
+ } from "./chunk-VRGUUHBV.js";
209
206
  import {
207
+ expandTildePath,
210
208
  mergeEnv,
211
209
  readEnvVar,
212
210
  resolveHomeDir
213
- } from "./chunk-I6B2W2IY.js";
211
+ } from "./chunk-TDRJVMUP.js";
214
212
  import {
215
213
  __export
216
214
  } from "./chunk-MLKGABMK.js";
@@ -5917,7 +5915,9 @@ var ExtractionEngine = class {
5917
5915
  log.warn("no OpenAI API key \u2014 direct OpenAI client disabled; local and gateway fallback paths remain available");
5918
5916
  }
5919
5917
  this.localLlm = localLlm ?? new LocalLlmClient(config, modelRegistry);
5920
- this.fallbackLlm = new FallbackLlmClient(gatewayConfig);
5918
+ this.fallbackLlm = new FallbackLlmClient(gatewayConfig, {
5919
+ workspaceDir: config.workspaceDir
5920
+ });
5921
5921
  this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
5922
5922
  if (config.modelSource === "gateway") {
5923
5923
  log.debug(
@@ -14039,7 +14039,9 @@ var HourlySummarizer = class {
14039
14039
  this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
14040
14040
  this.transcript = transcript;
14041
14041
  this.localLlm = new LocalLlmClient(config, this.modelRegistry);
14042
- this.fallbackLlm = new FallbackLlmClient(gatewayConfig);
14042
+ this.fallbackLlm = new FallbackLlmClient(gatewayConfig, {
14043
+ workspaceDir: config.workspaceDir
14044
+ });
14043
14045
  if (!gatewayConfig?.agents?.defaults?.model?.primary && !config.localLlmEnabled && config.modelSource !== "gateway") {
14044
14046
  log.warn("no gateway default AI and local LLM disabled \u2014 hourly summarization disabled");
14045
14047
  }
@@ -23513,6 +23515,7 @@ async function collectTurnReferenceEvidence(options) {
23513
23515
  await collectContentLabelReferenceEvidence({
23514
23516
  engine: options.engine,
23515
23517
  sessionId: options.sessionId,
23518
+ query: options.query,
23516
23519
  references,
23517
23520
  evidenceItems: options.evidenceItems,
23518
23521
  seenTurns: options.seenTurns
@@ -23565,7 +23568,9 @@ async function collectContentLabelReferenceEvidence(options) {
23565
23568
  if (appendedWindows >= CONTENT_LABEL_MAX_PAIRED_WINDOWS_PER_REFERENCE) {
23566
23569
  break;
23567
23570
  }
23568
- const { fromTurn, toTurn } = contentLabelEvidenceWindow(hit);
23571
+ const { fromTurn, toTurn } = contentLabelEvidenceWindow(hit, {
23572
+ includeSuccessor: hasSuccessorTrajectoryIntent(options.query)
23573
+ });
23569
23574
  const expanded = await options.engine.expandContext(
23570
23575
  hit.session_id,
23571
23576
  fromTurn,
@@ -23644,18 +23649,75 @@ function nearestTurnDistance(turnIndex, candidates) {
23644
23649
  }
23645
23650
  return nearest;
23646
23651
  }
23647
- function contentLabelEvidenceWindow(hit) {
23652
+ function contentLabelEvidenceWindow(hit, options = {}) {
23653
+ const successorTurns = options.includeSuccessor === true ? 2 : 0;
23648
23654
  if (hit.labelKind === "action") {
23649
23655
  return {
23650
23656
  fromTurn: Math.max(0, hit.turn_index - 1),
23651
- toTurn: hit.turn_index + 1
23657
+ toTurn: hit.turn_index + 1 + successorTurns
23652
23658
  };
23653
23659
  }
23654
23660
  return {
23655
23661
  fromTurn: Math.max(0, hit.turn_index - 1),
23656
- toTurn: hit.turn_index
23662
+ toTurn: hit.turn_index + successorTurns
23657
23663
  };
23658
23664
  }
23665
+ function hasSuccessorTrajectoryIntent(query) {
23666
+ const raw = query.toLowerCase();
23667
+ const normalized = raw.replace(/[^a-z0-9]+/g, " ").trim();
23668
+ if ([
23669
+ /\bafter\s+(?:step|action|observation|turn)\s+\d+\b/,
23670
+ /\b(?:next|following|subsequent|successor)\s+(?:step|action|observation|turn)\b/,
23671
+ /\b(?:step|action|observation|turn)\s+\d+\s+(?:then|and then)\b/,
23672
+ /\bwhat\s+(?:happened|came|occurred)\s+next\b/
23673
+ ].some((pattern) => pattern.test(normalized))) {
23674
+ return true;
23675
+ }
23676
+ if (!hasLoopExitIntent(normalized)) {
23677
+ return false;
23678
+ }
23679
+ if (!hasBoundedTrajectoryReference(raw)) {
23680
+ return true;
23681
+ }
23682
+ return !asksForActionInsideBoundedRange(normalized) && hasNamedTrajectoryActionCue(normalized);
23683
+ }
23684
+ function hasBoundedTrajectoryReference(query) {
23685
+ return hasBoundedTrajectoryRange(query) || hasSingleTrajectoryReference(query);
23686
+ }
23687
+ function hasLoopExitIntent(normalizedQuery) {
23688
+ const exitVerbs = "(?:breaks?|breaking|broke|ends?|ending|ended|stops?|stopping|stopped)";
23689
+ const loopNouns = "(?:loop|cycle|pattern|sequence)";
23690
+ return [
23691
+ new RegExp(
23692
+ `\\b${exitVerbs}\\s+(?:out\\s+of\\s+)?(?:this|that|the|a|an)?\\s*${loopNouns}\\b`
23693
+ ),
23694
+ new RegExp(
23695
+ `\\b${loopNouns}\\s+(?:${exitVerbs}|is\\s+${exitVerbs}|was\\s+${exitVerbs})\\b`
23696
+ )
23697
+ ].some((pattern) => pattern.test(normalizedQuery));
23698
+ }
23699
+ function hasBoundedTrajectoryRange(query) {
23700
+ return [
23701
+ /\b(?:between|from|in|during|within)\s+(?:steps?|actions?|observations?|turns?)\s+#?\d+\s*(?:-|\u2013|\u2014|\bto\b|\bthrough\b|\bthru\b|\band\b)\s*(?:(?:steps?|actions?|observations?|turns?)\s+)?#?\d+\b/,
23702
+ /\b(?:steps?|actions?|observations?|turns?)\s+#?\d+\s*(?:-|\u2013|\u2014|\bto\b|\bthrough\b|\bthru\b)\s*(?:(?:steps?|actions?|observations?|turns?)\s+)?#?\d+\b/
23703
+ ].some((pattern) => pattern.test(query));
23704
+ }
23705
+ function hasSingleTrajectoryReference(query) {
23706
+ return /\b(?:in|during|within|at|on)?\s*(?:steps?|actions?|observations?|turns?)\s+#?\d+\b/.test(
23707
+ query
23708
+ );
23709
+ }
23710
+ function asksForActionInsideBoundedRange(normalizedQuery) {
23711
+ return /\b(?:which|what)\s+(?:single\s+)?(?:action|move|step|maneuver)\s+(?:broke|breaks|breaking|ended|ends|stopped|stops|mattered|accomplished|advanced)\b/.test(
23712
+ normalizedQuery
23713
+ );
23714
+ }
23715
+ function hasNamedTrajectoryActionCue(normalizedQuery) {
23716
+ const actions = "(?:up|down|left|right|wait|stay|push|pull|open|close|use|enter|exit)";
23717
+ return new RegExp(
23718
+ `\\b(?:${actions}\\s+(?:action|move|step|maneuver)|(?:action|move|step|maneuver)\\s+${actions})\\b`
23719
+ ).test(normalizedQuery);
23720
+ }
23659
23721
  function contentHasReferenceLabel(content, labelKind, referenceNumber) {
23660
23722
  const label = labelKind === "action" ? "Action" : "Observation";
23661
23723
  const escapedNumber = String(referenceNumber).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -25134,6 +25196,16 @@ function resolveObjectiveStateStoreDir(memoryDir, overrideDir) {
25134
25196
  }
25135
25197
  return path29.join(memoryDir, "state", "objective-state");
25136
25198
  }
25199
+ function objectiveStateStoreOverrideForNamespace(options) {
25200
+ const configured = options.configuredStoreDir?.trim();
25201
+ if (!configured) return void 0;
25202
+ if (!options.namespacesEnabled) return configured;
25203
+ const defaultStoreDir = path29.join(options.memoryDir, "state", "objective-state");
25204
+ if (path29.resolve(configured) === path29.resolve(defaultStoreDir)) {
25205
+ return void 0;
25206
+ }
25207
+ return path29.join(configured, "namespaces", options.namespace);
25208
+ }
25137
25209
  function validateObjectiveStateSnapshot(raw) {
25138
25210
  if (!isRecord(raw)) throw new Error("objective-state snapshot must be an object");
25139
25211
  if (raw.schemaVersion !== 1) throw new Error("schemaVersion must be 1");
@@ -27468,8 +27540,12 @@ function parseOpenAiMessageParts(input, _options = {}) {
27468
27540
  }
27469
27541
  if (type === "function_call") {
27470
27542
  const toolName = asNonEmptyString(item.name ?? item.tool_name);
27543
+ const callId = asNonEmptyString(item.call_id ?? item.callId);
27544
+ const itemId = asNonEmptyString(item.id);
27471
27545
  const payload = {
27472
- id: item.id ?? item.call_id,
27546
+ id: callId ?? itemId,
27547
+ ...callId ? { call_id: callId } : {},
27548
+ ...itemId && itemId !== callId ? { response_item_id: itemId } : {},
27473
27549
  name: toolName,
27474
27550
  arguments: parseMaybeJson(item.arguments)
27475
27551
  };
@@ -27478,7 +27554,14 @@ function parseOpenAiMessageParts(input, _options = {}) {
27478
27554
  }
27479
27555
  if (type === "function_call_output") {
27480
27556
  const output = asNonEmptyString(item.output) ?? JSON.stringify(sanitizePayload(item.output ?? item));
27481
- parts.push(makePart("tool_result", { id: item.id ?? item.call_id, output }, {
27557
+ const callId = asNonEmptyString(item.call_id ?? item.callId);
27558
+ const itemId = asNonEmptyString(item.id);
27559
+ parts.push(makePart("tool_result", {
27560
+ id: callId ?? itemId,
27561
+ ...callId ? { call_id: callId } : {},
27562
+ ...itemId && itemId !== callId ? { response_item_id: itemId } : {},
27563
+ output
27564
+ }, {
27482
27565
  filePath: firstFilePath(output)
27483
27566
  }));
27484
27567
  continue;
@@ -27517,7 +27600,12 @@ function parseAnthropicMessageParts(input, _options = {}) {
27517
27600
  if (type === "tool_result") {
27518
27601
  const content = block.content;
27519
27602
  const rendered = renderUnknownContent(content);
27520
- parts.push(makePart("tool_result", { id: block.tool_use_id, content: sanitizePayload(content) }, {
27603
+ parts.push(makePart("tool_result", {
27604
+ id: block.tool_use_id,
27605
+ content: sanitizePayload(content),
27606
+ ...typeof block.is_error === "boolean" ? { is_error: block.is_error } : {},
27607
+ ...typeof block.isError === "boolean" ? { isError: block.isError } : {}
27608
+ }, {
27521
27609
  filePath: firstFilePath(rendered)
27522
27610
  }));
27523
27611
  continue;
@@ -27560,7 +27648,7 @@ function parseOpenClawMessageParts(input, options = {}) {
27560
27648
  })
27561
27649
  ]);
27562
27650
  }
27563
- const rendered = options.renderedContent ?? asNonEmptyString(obj.content);
27651
+ const rendered = options.allowRenderedFallback === false ? null : options.renderedContent ?? asNonEmptyString(obj.content);
27564
27652
  return rendered ? withOrdinals(partsFromRenderedText(rendered)) : [];
27565
27653
  }
27566
27654
  function partsFromRenderedText(text) {
@@ -27648,6 +27736,9 @@ function withRenderedFallback(parts, options) {
27648
27736
  return parts.length > 0 ? parts : renderedFallbackParts(options);
27649
27737
  }
27650
27738
  function renderedFallbackParts(options) {
27739
+ if (options.allowRenderedFallback === false) {
27740
+ return [];
27741
+ }
27651
27742
  const rendered = asNonEmptyString(options.renderedContent);
27652
27743
  return rendered ? partsFromRenderedText(rendered) : [];
27653
27744
  }
@@ -29091,7 +29182,8 @@ ${preview}`,
29091
29182
  return {
29092
29183
  totalMessages: this.archive.getMessageCount(sessionId),
29093
29184
  totalSummaryNodes: this.dag.getNodeCount(sessionId),
29094
- maxDepth: this.dag.getMaxDepth(sessionId)
29185
+ maxDepth: this.dag.getMaxDepth(sessionId),
29186
+ maxTurnIndex: this.archive.getMaxTurnIndex(sessionId)
29095
29187
  };
29096
29188
  }
29097
29189
  return {
@@ -34221,7 +34313,9 @@ var Orchestrator = class _Orchestrator {
34221
34313
  client.disableThinking = true;
34222
34314
  return client;
34223
34315
  })() : this.localLlm;
34224
- this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
34316
+ this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig, {
34317
+ workspaceDir: config.workspaceDir
34318
+ }) : null;
34225
34319
  if (config.modelSource === "gateway") {
34226
34320
  log.debug(
34227
34321
  `orchestrator: gateway model source active` + (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") + (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : "")
@@ -34247,17 +34341,19 @@ var Orchestrator = class _Orchestrator {
34247
34341
  const summarizeFn = async (text, targetTokens, aggressive) => {
34248
34342
  const instructionText = aggressive ? `Compress the following into bullet points. One bullet per distinct fact or decision. Maximum ${targetTokens} tokens total. No prose.` : `Compress the following conversation segment into a dense summary. Preserve: decisions made, code artifacts mentioned, errors encountered, open questions, and any commitments or next-steps. Omit: pleasantries, restatements, and anything the agent would not need to recall later. Output a single paragraph, maximum ${targetTokens} tokens.`;
34249
34343
  try {
34250
- const result = await this.localLlm.chatCompletion(
34251
- [
34252
- { role: "system", content: instructionText },
34253
- { role: "user", content: text.slice(0, 12e3) }
34254
- ],
34255
- {
34256
- maxTokens: targetTokens * 2,
34257
- operation: "lcm-summarize",
34258
- priority: "background"
34259
- }
34260
- );
34344
+ const messages = [
34345
+ { role: "system", content: instructionText },
34346
+ { role: "user", content: text.slice(0, 12e3) }
34347
+ ];
34348
+ const result = this.config.modelSource === "gateway" && this._fastGatewayLlm ? await this._fastGatewayLlm.chatCompletion(messages, {
34349
+ maxTokens: targetTokens * 2,
34350
+ timeoutMs: this.config.localLlmFastTimeoutMs,
34351
+ agentId: this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0
34352
+ }) : await this.localLlm.chatCompletion(messages, {
34353
+ maxTokens: targetTokens * 2,
34354
+ operation: "lcm-summarize",
34355
+ priority: "background"
34356
+ });
34261
34357
  return result?.content ?? null;
34262
34358
  } catch {
34263
34359
  return null;
@@ -35195,14 +35291,16 @@ ${doc.content}` : doc.content,
35195
35291
  );
35196
35292
  return result;
35197
35293
  }
35198
- const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-EGB622FE.js");
35294
+ const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-33SPYXQY.js");
35199
35295
  const useGateway = this.config.modelSource === "gateway";
35200
35296
  const modelSetting = this.config.semanticConsolidationModel;
35201
35297
  if (modelSetting === "fast" && this.fastLlm && !useGateway) {
35202
35298
  log.info("[semantic-consolidation] using fast local LLM for synthesis");
35203
35299
  }
35204
35300
  const gatewayAgentId = useGateway ? modelSetting === "fast" && this.config.fastGatewayAgentId ? this.config.fastGatewayAgentId : this.config.gatewayAgentId || void 0 : void 0;
35205
- const llm = new FallbackLlmClient2(this.config.gatewayConfig);
35301
+ const llm = new FallbackLlmClient2(this.config.gatewayConfig, {
35302
+ workspaceDir: this.config.workspaceDir
35303
+ });
35206
35304
  if (!llm.isAvailable(gatewayAgentId) && !(modelSetting === "fast" && this.fastLlm && !useGateway)) {
35207
35305
  log.warn(
35208
35306
  "[semantic-consolidation] no LLM available \u2014 skipping synthesis"
@@ -35356,7 +35454,9 @@ ${doc.content}` : doc.content,
35356
35454
  if (this.config.peerProfileReasonerEnabled) {
35357
35455
  try {
35358
35456
  const { runPeerProfileReasoner } = await import("./peers-KRFXWRQ6.js");
35359
- const llm2 = new FallbackLlmClient2(this.config.gatewayConfig);
35457
+ const llm2 = new FallbackLlmClient2(this.config.gatewayConfig, {
35458
+ workspaceDir: this.config.workspaceDir
35459
+ });
35360
35460
  const peerResult = await runPeerProfileReasoner({
35361
35461
  memoryDir: targetStorage.dir,
35362
35462
  enabled: true,
@@ -37825,13 +37925,27 @@ ${lines.join("\n\n")}`;
37825
37925
  });
37826
37926
  return null;
37827
37927
  }
37828
- const results = await searchObjectiveStateSnapshots({
37829
- memoryDir: this.config.memoryDir,
37830
- objectiveStateStoreDir: this.config.objectiveStateStoreDir,
37831
- query: retrievalQuery,
37832
- maxResults,
37833
- sessionKey
37834
- });
37928
+ const objectiveStateSearches = await Promise.all(
37929
+ recallNamespaces.map(async (namespace) => {
37930
+ const storage = this.config.namespacesEnabled ? await this.getStorage(namespace) : null;
37931
+ return searchObjectiveStateSnapshots({
37932
+ memoryDir: this.config.namespacesEnabled ? storage.dir : this.config.memoryDir,
37933
+ objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({
37934
+ memoryDir: this.config.memoryDir,
37935
+ configuredStoreDir: this.config.objectiveStateStoreDir,
37936
+ namespacesEnabled: this.config.namespacesEnabled,
37937
+ namespace
37938
+ }),
37939
+ query: retrievalQuery,
37940
+ maxResults,
37941
+ sessionKey
37942
+ });
37943
+ })
37944
+ );
37945
+ const results = objectiveStateSearches.flat().sort((left, right) => {
37946
+ if (right.score !== left.score) return right.score - left.score;
37947
+ return right.snapshot.recordedAt.localeCompare(left.snapshot.recordedAt);
37948
+ }).slice(0, maxResults);
37835
37949
  recordRecallSectionMetric({
37836
37950
  section: "objectiveState",
37837
37951
  priority: "core",
@@ -37960,7 +38074,7 @@ ${lines.join("\n\n")}`;
37960
38074
  return null;
37961
38075
  }
37962
38076
  try {
37963
- const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-V6NBBNCD.js");
38077
+ const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-JD4AU7FB.js");
37964
38078
  const rules = await getCalibrationRulesForRecall(this.config.memoryDir);
37965
38079
  if (rules.length === 0) {
37966
38080
  recordRecallSectionMetric({
@@ -41418,7 +41532,9 @@ ${normalized}`).digest("hex");
41418
41532
  judgeCandidates,
41419
41533
  this.config,
41420
41534
  this.localLlm,
41421
- new FallbackLlmClient(this.config.gatewayConfig),
41535
+ new FallbackLlmClient(this.config.gatewayConfig, {
41536
+ workspaceDir: this.config.workspaceDir
41537
+ }),
41422
41538
  this.judgeVerdictCache,
41423
41539
  this.judgeDeferCounts,
41424
41540
  judgeTelemetryHandler
@@ -55209,6 +55325,639 @@ async function recordMemoryOutcome(storage, input) {
55209
55325
  });
55210
55326
  }
55211
55327
 
55328
+ // ../remnic-core/src/objective-state-writers.ts
55329
+ import crypto2 from "crypto";
55330
+ var rawProviderParts = /* @__PURE__ */ new WeakSet();
55331
+ function markRawProviderParts(parts) {
55332
+ for (const part of parts) {
55333
+ rawProviderParts.add(part);
55334
+ }
55335
+ return parts;
55336
+ }
55337
+ function isRawProviderPart(part) {
55338
+ return rawProviderParts.has(part);
55339
+ }
55340
+ function hashSha256(value) {
55341
+ return crypto2.createHash("sha256").update(value).digest("hex");
55342
+ }
55343
+ function isRecord4(value) {
55344
+ return typeof value === "object" && value !== null && !Array.isArray(value);
55345
+ }
55346
+ function optionalString2(value) {
55347
+ if (typeof value !== "string") return void 0;
55348
+ const trimmed = value.trim();
55349
+ return trimmed.length > 0 ? trimmed : void 0;
55350
+ }
55351
+ function toolNameTokens(toolName) {
55352
+ if (!toolName) return [];
55353
+ return toolName.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
55354
+ }
55355
+ function normalizedToolName(toolName) {
55356
+ return toolNameTokens(toolName).join("_");
55357
+ }
55358
+ function parseToolArguments(value) {
55359
+ if (isRecord4(value)) return value;
55360
+ if (typeof value !== "string") return void 0;
55361
+ try {
55362
+ const parsed = JSON.parse(value);
55363
+ return isRecord4(parsed) ? parsed : void 0;
55364
+ } catch {
55365
+ return void 0;
55366
+ }
55367
+ }
55368
+ function stableStringify2(value) {
55369
+ if (Array.isArray(value)) {
55370
+ return `[${value.map((entry) => stableStringify2(entry)).join(",")}]`;
55371
+ }
55372
+ if (isRecord4(value)) {
55373
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(value[key])}`).join(",")}}`;
55374
+ }
55375
+ return JSON.stringify(value) ?? String(value);
55376
+ }
55377
+ function extractTextContent(value) {
55378
+ if (typeof value === "string") return value.trim();
55379
+ if (Array.isArray(value)) {
55380
+ return value.map((block) => {
55381
+ if (typeof block === "string") return block.trim();
55382
+ if (isRecord4(block) && block.type === "text" && typeof block.text === "string") {
55383
+ return block.text.trim();
55384
+ }
55385
+ return "";
55386
+ }).filter((item) => item.length > 0).join("\n");
55387
+ }
55388
+ if (isRecord4(value)) {
55389
+ return JSON.stringify(value);
55390
+ }
55391
+ return "";
55392
+ }
55393
+ function parseToolResultPayload(content) {
55394
+ const text = extractTextContent(content);
55395
+ if (text.length === 0) return void 0;
55396
+ try {
55397
+ return JSON.parse(text);
55398
+ } catch {
55399
+ return text;
55400
+ }
55401
+ }
55402
+ function resultHash(value) {
55403
+ if (value === void 0) return void 0;
55404
+ const canonical = typeof value === "string" ? value : stableStringify2(value);
55405
+ if (!canonical || canonical.length === 0) return void 0;
55406
+ return `sha256:${hashSha256(canonical)}`;
55407
+ }
55408
+ function getToolCallContexts(messages) {
55409
+ const contexts = /* @__PURE__ */ new Map();
55410
+ for (const message of messages) {
55411
+ if (message.role !== "assistant") continue;
55412
+ const toolCalls = message.tool_calls ?? message.toolCalls;
55413
+ if (!Array.isArray(toolCalls)) continue;
55414
+ for (const call of toolCalls) {
55415
+ if (!isRecord4(call)) continue;
55416
+ const toolCallId = optionalString2(call.id) ?? optionalString2(call.toolCallId);
55417
+ if (!toolCallId) continue;
55418
+ const fn = isRecord4(call.function) ? call.function : void 0;
55419
+ const toolName = optionalString2(fn?.name) ?? optionalString2(call.name);
55420
+ const args = parseToolArguments(fn?.arguments) ?? parseToolArguments(call.arguments) ?? parseToolArguments(call.args) ?? parseToolArguments(call.input);
55421
+ contexts.set(toolCallId, { toolCallId, toolName, args });
55422
+ }
55423
+ }
55424
+ return contexts;
55425
+ }
55426
+ function toolCallIdForMessage(message) {
55427
+ return optionalString2(message.tool_call_id) ?? optionalString2(message.toolCallId) ?? optionalString2(message.tool_use_id) ?? optionalString2(message.toolUseId);
55428
+ }
55429
+ function toolNameForMessage(message, context) {
55430
+ return optionalString2(message.name) ?? optionalString2(message.toolName) ?? optionalString2(message.tool) ?? context?.toolName;
55431
+ }
55432
+ function pickString(args, keys) {
55433
+ if (!args) return void 0;
55434
+ for (const key of keys) {
55435
+ const value = optionalString2(args[key]);
55436
+ if (value) return value;
55437
+ }
55438
+ return void 0;
55439
+ }
55440
+ function pickFirstStringArrayValue(args, key) {
55441
+ const value = args?.[key];
55442
+ if (!Array.isArray(value)) return void 0;
55443
+ for (const item of value) {
55444
+ const candidate = optionalString2(item);
55445
+ if (candidate) return candidate;
55446
+ }
55447
+ return void 0;
55448
+ }
55449
+ function fileScopeFromArgs(args) {
55450
+ const destinationPath = pickString(args, ["destination", "dest", "targetPath", "target", "to"]) ?? pickString(args, ["path", "filePath", "workspacePath", "projectPath"]) ?? pickFirstStringArrayValue(args, "paths");
55451
+ const sourcePath = pickString(args, ["source", "src", "from", "oldPath"]);
55452
+ const scope = destinationPath ?? sourcePath;
55453
+ return { scope, sourcePath, destinationPath };
55454
+ }
55455
+ function fileContentHash(args) {
55456
+ const content = pickString(args, ["content", "patch", "diff", "text", "value"]) ?? args?.updates;
55457
+ return resultHash(content);
55458
+ }
55459
+ function inferOutcome(message, parsedPayload) {
55460
+ if (message.isError === true) return "failure";
55461
+ if (isRecord4(parsedPayload)) {
55462
+ if (parsedPayload.partial === true || parsedPayload.status === "partial") return "partial";
55463
+ if (parsedPayload.success === false || parsedPayload.ok === false) return "failure";
55464
+ if (parsedPayload.success === true || parsedPayload.ok === true) return "success";
55465
+ if (typeof parsedPayload.exitCode === "number") {
55466
+ return parsedPayload.exitCode === 0 ? "success" : "failure";
55467
+ }
55468
+ if (optionalString2(parsedPayload.error)) return "failure";
55469
+ if (parsedPayload.status === "error" || parsedPayload.status === "failed") return "failure";
55470
+ if (parsedPayload.status === "ok" || parsedPayload.status === "success") return "success";
55471
+ const outputText = [
55472
+ optionalString2(parsedPayload.stdout),
55473
+ optionalString2(parsedPayload.stderr)
55474
+ ].filter((entry) => entry !== void 0).join("\n");
55475
+ if (outputText) {
55476
+ const outputOutcome = inferOutcome({}, outputText);
55477
+ if (outputOutcome !== "unknown") return outputOutcome;
55478
+ }
55479
+ }
55480
+ if (typeof parsedPayload === "string") {
55481
+ const lowered = parsedPayload.toLowerCase();
55482
+ const loweredForFailure = lowered.replace(/\b(?:previously\s+)?failed tests?\s+now\s+pass(?:ed|es)?\b/g, "");
55483
+ const hasZeroCountMarker = /\b(?:0|no)\s+(?:errors?|failures?|exceptions?|timeouts?)\b/.test(lowered);
55484
+ const loweredForFailureCounts = loweredForFailure.replace(/\b(?:0|no)\s+errors?\b/g, "").replace(/\b(?:0|no)\s+failures?\b/g, "").replace(/\b(?:0|no)\s+exceptions?\b/g, "").replace(/\b(?:0|no)\s+timeouts?\b/g, "");
55485
+ const hasNonZeroErrorCounts = /\b[1-9]\d*\s+errors?\b/.test(loweredForFailureCounts);
55486
+ const hasNegatedSuccessMarkers = /\b(?:not|did not|didn't|doesn't|isn't|aren't|wasn't|weren't|won't|can't|couldn't|shouldn't|wouldn't)\s+(?:ok|pass|passed|passes|succeeded|success)\b/.test(loweredForFailure);
55487
+ const hasSuccessMarkers = /\b(success|succeeded|pass|passes|passed|ok)\b/.test(lowered) || hasZeroCountMarker;
55488
+ const hasFailureMarkers = hasNegatedSuccessMarkers || /\b(exceptions?|failed|failures?|fatal|timeouts?|timed out)\b/.test(loweredForFailureCounts) || hasNonZeroErrorCounts || /\berrors?\b/.test(loweredForFailureCounts) || /\b[a-z]+error\b/.test(loweredForFailureCounts) || /\b[a-z]+exception\b/.test(loweredForFailureCounts);
55489
+ if (hasFailureMarkers) return "failure";
55490
+ if (hasSuccessMarkers) return "success";
55491
+ }
55492
+ return "unknown";
55493
+ }
55494
+ function isProcessTool(toolName, args) {
55495
+ const tokens = toolNameTokens(toolName);
55496
+ const normalizedName = normalizedToolName(toolName);
55497
+ if (pickString(args, ["cmd", "command", "script"])) return true;
55498
+ return ["exec", "shell", "bash", "terminal", "run_command", "exec_command"].some(
55499
+ (token) => token.includes("_") ? normalizedName === token : tokens.includes(token)
55500
+ );
55501
+ }
55502
+ function isFileTool(toolName, args) {
55503
+ const tokens = toolNameTokens(toolName);
55504
+ const fileScope = fileScopeFromArgs(args);
55505
+ if (fileScope.scope) return true;
55506
+ return ["file", "path", "patch", "directory", "mkdir", "rename", "move"].some(
55507
+ (token) => tokens.includes(token)
55508
+ );
55509
+ }
55510
+ function inferFileChangeKind(toolName, outcome) {
55511
+ if (outcome === "failure") return "failed";
55512
+ const tokens = toolNameTokens(toolName);
55513
+ if (["delete", "remove", "unlink"].some((token) => tokens.includes(token))) return "deleted";
55514
+ if (["create", "mkdir", "new"].some((token) => tokens.includes(token))) return "created";
55515
+ if (["write", "edit", "patch", "update", "append", "move", "rename"].some((token) => tokens.includes(token))) {
55516
+ return "updated";
55517
+ }
55518
+ return "observed";
55519
+ }
55520
+ function buildFileValueRefs(args, changeKind) {
55521
+ const { sourcePath, destinationPath, scope } = fileScopeFromArgs(args);
55522
+ const contentHash = fileContentHash(args);
55523
+ if (changeKind === "failed") {
55524
+ if (sourcePath && destinationPath && sourcePath !== destinationPath) {
55525
+ return {
55526
+ before: { ref: sourcePath },
55527
+ after: { ref: destinationPath }
55528
+ };
55529
+ }
55530
+ return {
55531
+ before: sourcePath ? { ref: sourcePath } : void 0,
55532
+ after: scope ? { ref: scope } : void 0
55533
+ };
55534
+ }
55535
+ if (changeKind === "deleted") {
55536
+ return {
55537
+ before: scope ? { exists: true, ref: scope } : void 0,
55538
+ after: { exists: false }
55539
+ };
55540
+ }
55541
+ if (changeKind === "created") {
55542
+ return {
55543
+ after: {
55544
+ exists: true,
55545
+ ref: scope,
55546
+ valueHash: contentHash
55547
+ }
55548
+ };
55549
+ }
55550
+ if (sourcePath && destinationPath && sourcePath !== destinationPath) {
55551
+ return {
55552
+ before: { exists: true, ref: sourcePath },
55553
+ after: {
55554
+ exists: true,
55555
+ ref: destinationPath
55556
+ }
55557
+ };
55558
+ }
55559
+ return {
55560
+ after: {
55561
+ exists: true,
55562
+ ref: scope,
55563
+ valueHash: contentHash
55564
+ }
55565
+ };
55566
+ }
55567
+ function summarizeSnapshot(kind, changeKind, toolName, scope) {
55568
+ const action = changeKind === "executed" ? "Executed" : changeKind === "failed" ? "Failed" : changeKind === "created" ? "Created" : changeKind === "deleted" ? "Deleted" : changeKind === "updated" ? "Updated" : "Observed";
55569
+ if (kind === "process") return `${action} process via ${toolName}: ${scope}`;
55570
+ if (kind === "file") return `${action} file via ${toolName}: ${scope}`;
55571
+ return `${action} tool result from ${toolName}: ${scope}`;
55572
+ }
55573
+ function buildGenericToolAfterRef(outcome, parsedPayload) {
55574
+ const valueHash = resultHash(parsedPayload);
55575
+ return valueHash ? { valueHash } : { exists: outcome !== "failure" };
55576
+ }
55577
+ function snapshotIdFor(sessionKey, recordedAt, index, toolName, scope, stableKey2) {
55578
+ const digest = crypto2.createHash("sha256").update(
55579
+ stableKey2 ? `${sessionKey}|${recordedAt}|${index}|${toolName}|${scope}|stable|${stableKey2}` : `${sessionKey}|${recordedAt}|${index}|${toolName}|${scope}`
55580
+ ).digest("hex").slice(0, 12);
55581
+ return `obj-${digest}`;
55582
+ }
55583
+ function objectiveStatePartsForObservedMessage(message) {
55584
+ if (message.role === "user") {
55585
+ const explicitParts2 = Array.isArray(message.parts) && message.parts.length > 0 ? sanitizeUserRoleToolResultParts(message.parts) : [];
55586
+ if (Array.isArray(message.parts) && message.parts.length > 0) {
55587
+ const rawParts2 = userRawToolResultParts(message);
55588
+ return mergeObservedEvidenceParts(explicitParts2, rawParts2);
55589
+ }
55590
+ return userRawToolResultParts(message);
55591
+ }
55592
+ if (message.role !== "assistant") {
55593
+ return [];
55594
+ }
55595
+ const explicitParts = Array.isArray(message.parts) && message.parts.length > 0 ? message.parts : [];
55596
+ const rawParts = assistantRawObjectiveStateParts(message);
55597
+ return mergeObservedEvidenceParts(explicitParts, rawParts);
55598
+ }
55599
+ function userRawToolResultParts(message) {
55600
+ const rawContent = message.rawContent ?? message.content;
55601
+ if (!containsProviderToolResultBlock(rawContent)) {
55602
+ return [];
55603
+ }
55604
+ return markRawProviderParts(
55605
+ sanitizeUserRoleToolResultParts(parseMessageParts(rawContent, {
55606
+ sourceFormat: message.sourceFormat,
55607
+ allowRenderedFallback: false
55608
+ }))
55609
+ );
55610
+ }
55611
+ function assistantRawObjectiveStateParts(message) {
55612
+ if (message.rawContent === void 0 || message.rawContent === null) {
55613
+ return [];
55614
+ }
55615
+ return markRawProviderParts(parseMessageParts(message.rawContent, {
55616
+ sourceFormat: message.sourceFormat,
55617
+ allowRenderedFallback: false
55618
+ }));
55619
+ }
55620
+ function mergeObservedEvidenceParts(explicitParts, rawParts) {
55621
+ if (explicitParts.length === 0) return rawParts;
55622
+ if (rawParts.length === 0) return explicitParts;
55623
+ const merged = [...explicitParts];
55624
+ const seen = new Set(
55625
+ explicitParts.filter(isObjectiveStateEvidencePart).map(objectiveStateEvidencePartKey)
55626
+ );
55627
+ for (const part of rawParts) {
55628
+ if (!isObjectiveStateEvidencePart(part)) continue;
55629
+ const key = objectiveStateEvidencePartKey(part);
55630
+ if (seen.has(key)) continue;
55631
+ seen.add(key);
55632
+ merged.push(part);
55633
+ }
55634
+ return merged;
55635
+ }
55636
+ function isObjectiveStateEvidencePart(part) {
55637
+ return part.kind === "tool_call" || part.kind === "tool_result" || part.kind === "file_write" || part.kind === "patch";
55638
+ }
55639
+ function objectiveStateEvidencePartKey(part) {
55640
+ const id = partToolCallId(part);
55641
+ if (id) return `${part.kind}:id:${id}`;
55642
+ const toolName = partToolName(part) ?? "";
55643
+ const filePath = partFilePath(part) ?? "";
55644
+ return `${part.kind}:shape:${toolName}:${filePath}:${stableStringify2(partPayload(part))}`;
55645
+ }
55646
+ function flattenObservedParts(messages) {
55647
+ const entries = [];
55648
+ messages.forEach((message, messageIndex) => {
55649
+ const parts = objectiveStatePartsForObservedMessage(message);
55650
+ parts.forEach((part, partIndex) => {
55651
+ entries.push({ messageIndex, partIndex, part });
55652
+ });
55653
+ });
55654
+ return entries.sort((a, b) => {
55655
+ if (a.messageIndex !== b.messageIndex) return a.messageIndex - b.messageIndex;
55656
+ const aOrdinal = typeof a.part.ordinal === "number" ? a.part.ordinal : a.partIndex;
55657
+ const bOrdinal = typeof b.part.ordinal === "number" ? b.part.ordinal : b.partIndex;
55658
+ if (aOrdinal !== bOrdinal) return aOrdinal - bOrdinal;
55659
+ return a.partIndex - b.partIndex;
55660
+ });
55661
+ }
55662
+ function sanitizeUserRoleToolResultParts(parts) {
55663
+ return parts.filter((part) => part.kind === "tool_result").map((part) => {
55664
+ const payload = { ...partPayload(part) };
55665
+ delete payload.name;
55666
+ delete payload.tool;
55667
+ delete payload.toolName;
55668
+ delete payload.tool_name;
55669
+ return {
55670
+ ...part,
55671
+ toolName: null,
55672
+ tool_name: null,
55673
+ payload
55674
+ };
55675
+ });
55676
+ }
55677
+ function containsProviderToolResultBlock(value) {
55678
+ if (Array.isArray(value)) {
55679
+ return value.some(containsProviderToolResultBlock);
55680
+ }
55681
+ if (!isRecord4(value)) return false;
55682
+ const type = optionalString2(value.type ?? value.kind);
55683
+ if (type === "tool_result" || type === "function_call_output") {
55684
+ return true;
55685
+ }
55686
+ return containsProviderToolResultBlock(value.content) || containsProviderToolResultBlock(value.output) || containsProviderToolResultBlock(value.items);
55687
+ }
55688
+ function partPayload(part) {
55689
+ return isRecord4(part.payload) ? part.payload : {};
55690
+ }
55691
+ function partToolCallId(part) {
55692
+ const payload = partPayload(part);
55693
+ return optionalString2(payload.call_id) ?? optionalString2(payload.callId) ?? optionalString2(payload.id) ?? optionalString2(payload.tool_call_id) ?? optionalString2(payload.toolCallId) ?? optionalString2(payload.tool_use_id) ?? optionalString2(payload.toolUseId);
55694
+ }
55695
+ function partToolName(part) {
55696
+ const payload = partPayload(part);
55697
+ return optionalString2(part.toolName) ?? optionalString2(part.tool_name) ?? optionalString2(payload.name) ?? optionalString2(payload.toolName) ?? optionalString2(payload.tool_name) ?? (part.kind === "patch" ? "apply_patch" : void 0) ?? (part.kind === "file_write" ? "file_write" : void 0);
55698
+ }
55699
+ function partFilePath(part) {
55700
+ const payload = partPayload(part);
55701
+ return optionalString2(part.filePath) ?? optionalString2(part.file_path) ?? optionalString2(payload.path) ?? optionalString2(payload.filePath) ?? optionalString2(payload.file_path);
55702
+ }
55703
+ function syntheticPartId(options) {
55704
+ const digest = hashSha256(
55705
+ [
55706
+ options.sessionKey,
55707
+ String(options.messageIndex),
55708
+ String(options.part.ordinal ?? options.partIndex),
55709
+ options.part.kind,
55710
+ optionalString2(options.part.toolName) ?? "",
55711
+ optionalString2(options.part.tool_name) ?? "",
55712
+ optionalString2(options.part.filePath) ?? "",
55713
+ optionalString2(options.part.file_path) ?? "",
55714
+ stableStringify2(options.part.payload)
55715
+ ].join("|")
55716
+ ).slice(0, 12);
55717
+ return `part-${digest}`;
55718
+ }
55719
+ function toolArgumentsFromPart(part) {
55720
+ const payload = partPayload(part);
55721
+ const parsedArgs = parseToolArguments(payload.arguments) ?? parseToolArguments(payload.input) ?? parseToolArguments(payload.args) ?? parseToolArguments(payload.params) ?? payload;
55722
+ const args = { ...parsedArgs };
55723
+ const filePath = partFilePath(part);
55724
+ if (filePath && !pickString(args, ["path", "filePath", "file_path"])) {
55725
+ args.path = filePath;
55726
+ }
55727
+ if (part.kind === "patch" && !pickString(args, ["patch", "diff", "text"])) {
55728
+ const text = optionalString2(payload.text) ?? optionalString2(payload.patch);
55729
+ if (text) args.patch = text;
55730
+ }
55731
+ return args;
55732
+ }
55733
+ function toolResultContentFromPart(part) {
55734
+ const payload = partPayload(part);
55735
+ if ("output" in payload) return payload.output;
55736
+ if ("content" in payload) return payload.content;
55737
+ if ("result" in payload) return payload.result;
55738
+ if ("value" in payload) return payload.value;
55739
+ return payload;
55740
+ }
55741
+ function inlineToolResultContentFromPart(part) {
55742
+ const payload = partPayload(part);
55743
+ if (hasDefinedPayloadKey(payload, "output")) return payload.output;
55744
+ if (hasDefinedPayloadKey(payload, "result")) return payload.result;
55745
+ if (part.kind === "tool_result" && hasDefinedPayloadKey(payload, "value")) {
55746
+ return payload.value;
55747
+ }
55748
+ const statusPayload = {};
55749
+ for (const key of ["exitCode", "ok", "success", "error", "stdout", "stderr"]) {
55750
+ if (hasDefinedPayloadKey(payload, key)) {
55751
+ statusPayload[key] = payload[key];
55752
+ }
55753
+ }
55754
+ return Object.keys(statusPayload).length > 0 ? statusPayload : payload;
55755
+ }
55756
+ function hasDefinedPayloadKey(payload, key) {
55757
+ return Object.prototype.hasOwnProperty.call(payload, key) && payload[key] !== void 0;
55758
+ }
55759
+ function partHasInlineToolResult(part) {
55760
+ const payload = partPayload(part);
55761
+ return hasDefinedPayloadKey(payload, "output") || hasDefinedPayloadKey(payload, "result") || part.kind === "tool_result" && hasDefinedPayloadKey(payload, "value") || hasDefinedPayloadKey(payload, "exitCode") || hasDefinedPayloadKey(payload, "ok") || hasDefinedPayloadKey(payload, "success") || hasDefinedPayloadKey(payload, "error") || hasDefinedPayloadKey(payload, "stdout") || hasDefinedPayloadKey(payload, "stderr");
55762
+ }
55763
+ function toolResultIsError(part) {
55764
+ const payload = partPayload(part);
55765
+ return payload.isError === true || payload.is_error === true || payload.ok === false || payload.success === false || optionalString2(payload.error) !== void 0;
55766
+ }
55767
+ function buildSyntheticAssistantToolCall(id, toolName, args) {
55768
+ return {
55769
+ role: "assistant",
55770
+ tool_calls: [
55771
+ {
55772
+ id,
55773
+ function: {
55774
+ name: toolName,
55775
+ arguments: JSON.stringify(args)
55776
+ }
55777
+ }
55778
+ ]
55779
+ };
55780
+ }
55781
+ function observedPartsToAgentMessages(options) {
55782
+ const entries = flattenObservedParts(options.messages);
55783
+ const resultIds = new Set(
55784
+ entries.filter((entry) => entry.part.kind === "tool_result").map((entry) => partToolCallId(entry.part)).filter((id) => id !== void 0)
55785
+ );
55786
+ const synthetic = [];
55787
+ let pendingIdlessToolCallId;
55788
+ for (let entryIndex = 0; entryIndex < entries.length; entryIndex += 1) {
55789
+ const entry = entries[entryIndex];
55790
+ const { part } = entry;
55791
+ if (part.kind === "tool_call" || part.kind === "file_write" || part.kind === "patch") {
55792
+ const toolName = partToolName(part);
55793
+ if (!toolName) continue;
55794
+ const observedToolCallId = partToolCallId(part);
55795
+ const id = observedToolCallId ?? syntheticPartId({
55796
+ sessionKey: options.sessionKey,
55797
+ messageIndex: entry.messageIndex,
55798
+ partIndex: entry.partIndex,
55799
+ part
55800
+ });
55801
+ const args = toolArgumentsFromPart(part);
55802
+ synthetic.push(buildSyntheticAssistantToolCall(id, toolName, args));
55803
+ const nextEntry = entries[entryIndex + 1];
55804
+ const nextIsIdlessToolResult = nextEntry?.part.kind === "tool_result" && partToolCallId(nextEntry.part) === void 0;
55805
+ pendingIdlessToolCallId = nextIsIdlessToolResult ? id : void 0;
55806
+ const hasSeparateToolResult = resultIds.has(id) || nextIsIdlessToolResult;
55807
+ if (partHasInlineToolResult(part) && !hasSeparateToolResult) {
55808
+ synthetic.push({
55809
+ role: "tool",
55810
+ tool_call_id: id,
55811
+ name: toolName,
55812
+ content: inlineToolResultContentFromPart(part),
55813
+ ...toolResultIsError(part) ? { isError: true } : {}
55814
+ });
55815
+ pendingIdlessToolCallId = void 0;
55816
+ continue;
55817
+ }
55818
+ if ((part.kind === "file_write" || part.kind === "patch") && !nextIsIdlessToolResult && !resultIds.has(id) && !isRawProviderPart(part)) {
55819
+ synthetic.push({
55820
+ role: "tool",
55821
+ tool_call_id: id,
55822
+ name: toolName,
55823
+ content: { ok: true, source: "message_part" }
55824
+ });
55825
+ pendingIdlessToolCallId = void 0;
55826
+ }
55827
+ continue;
55828
+ }
55829
+ if (part.kind === "tool_result") {
55830
+ const id = partToolCallId(part) ?? pendingIdlessToolCallId;
55831
+ const toolName = partToolName(part);
55832
+ synthetic.push({
55833
+ role: "tool",
55834
+ ...id ? { tool_call_id: id } : {},
55835
+ ...toolName ? { name: toolName } : {},
55836
+ content: toolResultContentFromPart(part),
55837
+ ...toolResultIsError(part) ? { isError: true } : {}
55838
+ });
55839
+ pendingIdlessToolCallId = void 0;
55840
+ }
55841
+ }
55842
+ return synthetic;
55843
+ }
55844
+ function deriveObjectiveStateSnapshotsFromAgentMessages(options) {
55845
+ const toolCallsById = getToolCallContexts(options.messages);
55846
+ const snapshots = [];
55847
+ for (const message of options.messages) {
55848
+ if (message.role !== "tool") continue;
55849
+ const toolCallId = toolCallIdForMessage(message);
55850
+ const context = toolCallId ? toolCallsById.get(toolCallId) : void 0;
55851
+ const toolName = toolNameForMessage(message, context);
55852
+ if (!toolName) continue;
55853
+ const parsedPayload = parseToolResultPayload(message.content);
55854
+ const outcome = inferOutcome(message, parsedPayload);
55855
+ const args = context?.args;
55856
+ const command = pickString(args, ["cmd", "command", "script"]);
55857
+ let kind = "tool";
55858
+ let changeKind = outcome === "failure" ? "failed" : "observed";
55859
+ let scope = toolName;
55860
+ let before;
55861
+ let after;
55862
+ if (isProcessTool(toolName, args)) {
55863
+ kind = "process";
55864
+ changeKind = outcome === "failure" ? "failed" : "executed";
55865
+ scope = command ?? toolName;
55866
+ after = { exists: outcome !== "failure", valueHash: resultHash(parsedPayload) };
55867
+ } else if (isFileTool(toolName, args)) {
55868
+ kind = "file";
55869
+ changeKind = inferFileChangeKind(toolName, outcome);
55870
+ const fileScope = fileScopeFromArgs(args);
55871
+ scope = fileScope.scope ?? toolName;
55872
+ const refs = buildFileValueRefs(args, changeKind);
55873
+ before = refs.before;
55874
+ after = refs.after;
55875
+ } else {
55876
+ after = buildGenericToolAfterRef(outcome, parsedPayload);
55877
+ }
55878
+ snapshots.push({
55879
+ schemaVersion: 1,
55880
+ snapshotId: snapshotIdFor(
55881
+ options.sessionKey,
55882
+ options.recordedAt,
55883
+ snapshots.length,
55884
+ toolName,
55885
+ scope,
55886
+ toolCallId
55887
+ ),
55888
+ recordedAt: options.recordedAt,
55889
+ sessionKey: options.sessionKey,
55890
+ source: "tool_result",
55891
+ kind,
55892
+ changeKind,
55893
+ scope,
55894
+ summary: summarizeSnapshot(kind, changeKind, toolName, scope),
55895
+ toolName,
55896
+ command,
55897
+ outcome,
55898
+ before,
55899
+ after,
55900
+ tags: ["agent-end", `tool:${toolName}`],
55901
+ metadata: toolCallId ? { toolCallId } : void 0
55902
+ });
55903
+ }
55904
+ return snapshots;
55905
+ }
55906
+ function deriveObjectiveStateSnapshotsFromObservedMessages(options) {
55907
+ const syntheticMessages = observedPartsToAgentMessages({
55908
+ sessionKey: options.sessionKey,
55909
+ messages: options.messages
55910
+ });
55911
+ if (syntheticMessages.length === 0) return [];
55912
+ return deriveObjectiveStateSnapshotsFromAgentMessages({
55913
+ sessionKey: options.sessionKey,
55914
+ recordedAt: options.recordedAt,
55915
+ messages: syntheticMessages
55916
+ });
55917
+ }
55918
+ async function recordObjectiveStateSnapshotsFromAgentMessages(options) {
55919
+ if (!options.objectiveStateMemoryEnabled || !options.objectiveStateSnapshotWritesEnabled) {
55920
+ return { snapshots: [], filePaths: [] };
55921
+ }
55922
+ const snapshots = deriveObjectiveStateSnapshotsFromAgentMessages({
55923
+ sessionKey: options.sessionKey,
55924
+ recordedAt: options.recordedAt,
55925
+ messages: options.messages
55926
+ });
55927
+ const filePaths = [];
55928
+ for (const snapshot of snapshots) {
55929
+ filePaths.push(
55930
+ await recordObjectiveStateSnapshot({
55931
+ memoryDir: options.memoryDir,
55932
+ objectiveStateStoreDir: options.objectiveStateStoreDir,
55933
+ snapshot
55934
+ })
55935
+ );
55936
+ }
55937
+ return { snapshots, filePaths };
55938
+ }
55939
+ async function recordObjectiveStateSnapshotsFromObservedMessages(options) {
55940
+ if (!options.objectiveStateMemoryEnabled || !options.objectiveStateSnapshotWritesEnabled) {
55941
+ return { snapshots: [], filePaths: [] };
55942
+ }
55943
+ const snapshots = deriveObjectiveStateSnapshotsFromObservedMessages({
55944
+ sessionKey: options.sessionKey,
55945
+ recordedAt: options.recordedAt,
55946
+ messages: options.messages
55947
+ });
55948
+ const filePaths = [];
55949
+ for (const snapshot of snapshots) {
55950
+ filePaths.push(
55951
+ await recordObjectiveStateSnapshot({
55952
+ memoryDir: options.memoryDir,
55953
+ objectiveStateStoreDir: options.objectiveStateStoreDir,
55954
+ snapshot
55955
+ })
55956
+ );
55957
+ }
55958
+ return { snapshots, filePaths };
55959
+ }
55960
+
55212
55961
  // ../remnic-core/src/access-service.ts
55213
55962
  var EngramAccessInputError = class extends Error {
55214
55963
  };
@@ -55431,6 +56180,24 @@ var EngramAccessService = class {
55431
56180
  }
55432
56181
  return resolved;
55433
56182
  }
56183
+ async objectiveStateStoreLocationForNamespace(namespace) {
56184
+ if (!this.orchestrator.config.namespacesEnabled) {
56185
+ return {
56186
+ memoryDir: this.orchestrator.config.memoryDir,
56187
+ objectiveStateStoreDir: this.orchestrator.config.objectiveStateStoreDir
56188
+ };
56189
+ }
56190
+ const storage = await this.orchestrator.getStorage(namespace);
56191
+ return {
56192
+ memoryDir: storage.dir,
56193
+ objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({
56194
+ memoryDir: this.orchestrator.config.memoryDir,
56195
+ configuredStoreDir: this.orchestrator.config.objectiveStateStoreDir,
56196
+ namespacesEnabled: this.orchestrator.config.namespacesEnabled,
56197
+ namespace
56198
+ })
56199
+ };
56200
+ }
55434
56201
  resolveReadableNamespace(namespace, principal) {
55435
56202
  const resolved = this.resolveNamespace(namespace);
55436
56203
  const namespacesEnabled = this.orchestrator.config.namespacesEnabled;
@@ -57160,16 +57927,54 @@ var EngramAccessService = class {
57160
57927
  throw new EngramAccessInputError(`invalid message role: ${msg.role} (expected 'user' or 'assistant')`);
57161
57928
  }
57162
57929
  }
57930
+ const hasExplicitNamespace = typeof request.namespace === "string" && request.namespace.trim().length > 0;
57931
+ const principal = this.resolveWritePrincipal(
57932
+ request.sessionKey,
57933
+ request.authenticatedPrincipal
57934
+ );
57163
57935
  const namespace = this.resolveWritableNamespace(
57164
57936
  request.namespace,
57165
57937
  request.sessionKey,
57166
57938
  request.authenticatedPrincipal
57167
57939
  );
57940
+ const shouldWriteObjectiveState = this.orchestrator.config.objectiveStateMemoryEnabled === true && this.orchestrator.config.objectiveStateSnapshotWritesEnabled === true;
57941
+ const objectiveStateBaseNamespace = hasExplicitNamespace ? namespace : defaultNamespaceForPrincipal(principal, this.orchestrator.config);
57942
+ if (shouldWriteObjectiveState && !hasExplicitNamespace && !canWriteNamespace(
57943
+ principal,
57944
+ objectiveStateBaseNamespace,
57945
+ this.orchestrator.config
57946
+ )) {
57947
+ throw new EngramAccessInputError(
57948
+ `namespace is not writable: ${objectiveStateBaseNamespace}`
57949
+ );
57950
+ }
57168
57951
  await this.maybeAttachCodingContext(request.sessionKey, {
57169
57952
  cwd: request.cwd,
57170
57953
  projectTag: request.projectTag
57171
57954
  });
57955
+ const objectiveStateNamespace = hasExplicitNamespace ? namespace : this.orchestrator.applyCodingNamespaceOverlay(
57956
+ request.sessionKey,
57957
+ objectiveStateBaseNamespace
57958
+ );
57172
57959
  const lcmSessionKey = namespace !== this.orchestrator.config.defaultNamespace ? `${namespace}:${request.sessionKey}` : request.sessionKey;
57960
+ if (shouldWriteObjectiveState) {
57961
+ try {
57962
+ const objectiveStateLocation = await this.objectiveStateStoreLocationForNamespace(
57963
+ objectiveStateNamespace
57964
+ );
57965
+ await recordObjectiveStateSnapshotsFromObservedMessages({
57966
+ memoryDir: objectiveStateLocation.memoryDir,
57967
+ objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
57968
+ objectiveStateMemoryEnabled: this.orchestrator.config.objectiveStateMemoryEnabled,
57969
+ objectiveStateSnapshotWritesEnabled: this.orchestrator.config.objectiveStateSnapshotWritesEnabled,
57970
+ sessionKey: request.sessionKey,
57971
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
57972
+ messages: request.messages
57973
+ });
57974
+ } catch (err) {
57975
+ log.error(`access-observe objective-state snapshot write failed: ${err}`);
57976
+ }
57977
+ }
57173
57978
  let lcmArchived = false;
57174
57979
  if (this.orchestrator.lcmEngine && this.orchestrator.lcmEngine.enabled) {
57175
57980
  try {
@@ -64305,7 +65110,7 @@ async function runSemanticRulePromoteCliCommand(options) {
64305
65110
  });
64306
65111
  }
64307
65112
  async function runCompoundingPromoteCliCommand(options) {
64308
- const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-XPEZBXIQ.js");
65113
+ const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-57HLTQBN.js");
64309
65114
  const config = parseConfig({
64310
65115
  memoryDir: options.memoryDir,
64311
65116
  qmdEnabled: false,
@@ -67153,7 +67958,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
67153
67958
  return;
67154
67959
  }
67155
67960
  const cfg = orchestrator.config.connectors;
67156
- const { readConnectorState: readConnectorState2, writeConnectorState: writeConnectorState2 } = await import("./state-store-LP5BO6SF.js");
67961
+ const { readConnectorState: readConnectorState2, writeConnectorState: writeConnectorState2 } = await import("./state-store-N6TFBFSP.js");
67157
67962
  const sharedIngestFn = async (docs) => {
67158
67963
  const fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
67159
67964
  const turns = docs.map((doc) => ({
@@ -69690,7 +70495,7 @@ Legacy identity-anchor files are untouched. Verify the migration result`);
69690
70495
  }
69691
70496
  if (typeof options.trace === "string" && options.trace.length > 0) {
69692
70497
  const { replayTrace, parseSpeedFlag } = await import("./trace-NJESSGH7.js");
69693
- const { expandTildePath: expandTildePath2 } = await import("./path-5LCUBAAZ.js");
70498
+ const { expandTildePath: expandTildePath2 } = await import("./path-JIEGNWFL.js");
69694
70499
  const tracePath = expandTildePath2(options.trace);
69695
70500
  let speed;
69696
70501
  try {
@@ -69721,7 +70526,7 @@ Legacy identity-anchor files are untouched. Verify the migration result`);
69721
70526
  let recorder = null;
69722
70527
  if (typeof options.recordTrace === "string" && options.recordTrace.length > 0) {
69723
70528
  const { openTraceRecorder } = await import("./trace-NJESSGH7.js");
69724
- const { expandTildePath: expandTildePath2 } = await import("./path-5LCUBAAZ.js");
70529
+ const { expandTildePath: expandTildePath2 } = await import("./path-JIEGNWFL.js");
69725
70530
  recorder = await openTraceRecorder(
69726
70531
  expandTildePath2(options.recordTrace)
69727
70532
  );
@@ -69773,309 +70578,6 @@ function parseDuration(duration) {
69773
70578
  return total || 12;
69774
70579
  }
69775
70580
 
69776
- // ../remnic-core/src/objective-state-writers.ts
69777
- import crypto2 from "crypto";
69778
- function hashSha256(value) {
69779
- return crypto2.createHash("sha256").update(value).digest("hex");
69780
- }
69781
- function isRecord4(value) {
69782
- return typeof value === "object" && value !== null && !Array.isArray(value);
69783
- }
69784
- function optionalString2(value) {
69785
- if (typeof value !== "string") return void 0;
69786
- const trimmed = value.trim();
69787
- return trimmed.length > 0 ? trimmed : void 0;
69788
- }
69789
- function toolNameTokens(toolName) {
69790
- if (!toolName) return [];
69791
- return toolName.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
69792
- }
69793
- function normalizedToolName(toolName) {
69794
- return toolNameTokens(toolName).join("_");
69795
- }
69796
- function parseToolArguments(value) {
69797
- if (isRecord4(value)) return value;
69798
- if (typeof value !== "string") return void 0;
69799
- try {
69800
- const parsed = JSON.parse(value);
69801
- return isRecord4(parsed) ? parsed : void 0;
69802
- } catch {
69803
- return void 0;
69804
- }
69805
- }
69806
- function extractTextContent(value) {
69807
- if (typeof value === "string") return value.trim();
69808
- if (Array.isArray(value)) {
69809
- return value.map((block) => {
69810
- if (typeof block === "string") return block.trim();
69811
- if (isRecord4(block) && block.type === "text" && typeof block.text === "string") {
69812
- return block.text.trim();
69813
- }
69814
- return "";
69815
- }).filter((item) => item.length > 0).join("\n");
69816
- }
69817
- if (isRecord4(value)) {
69818
- return JSON.stringify(value);
69819
- }
69820
- return "";
69821
- }
69822
- function parseToolResultPayload(content) {
69823
- const text = extractTextContent(content);
69824
- if (text.length === 0) return void 0;
69825
- try {
69826
- return JSON.parse(text);
69827
- } catch {
69828
- return text;
69829
- }
69830
- }
69831
- function resultHash(value) {
69832
- if (value === void 0) return void 0;
69833
- const canonical = typeof value === "string" ? value : JSON.stringify(value);
69834
- if (!canonical || canonical.length === 0) return void 0;
69835
- return `sha256:${hashSha256(canonical)}`;
69836
- }
69837
- function getToolCallContexts(messages) {
69838
- const contexts = /* @__PURE__ */ new Map();
69839
- for (const message of messages) {
69840
- if (message.role !== "assistant") continue;
69841
- const toolCalls = message.tool_calls ?? message.toolCalls;
69842
- if (!Array.isArray(toolCalls)) continue;
69843
- for (const call of toolCalls) {
69844
- if (!isRecord4(call)) continue;
69845
- const toolCallId = optionalString2(call.id) ?? optionalString2(call.toolCallId);
69846
- if (!toolCallId) continue;
69847
- const fn = isRecord4(call.function) ? call.function : void 0;
69848
- const toolName = optionalString2(fn?.name) ?? optionalString2(call.name);
69849
- const args = parseToolArguments(fn?.arguments) ?? parseToolArguments(call.arguments) ?? parseToolArguments(call.args) ?? parseToolArguments(call.input);
69850
- contexts.set(toolCallId, { toolCallId, toolName, args });
69851
- }
69852
- }
69853
- return contexts;
69854
- }
69855
- function toolCallIdForMessage(message) {
69856
- return optionalString2(message.tool_call_id) ?? optionalString2(message.toolCallId) ?? optionalString2(message.tool_use_id) ?? optionalString2(message.toolUseId);
69857
- }
69858
- function toolNameForMessage(message, context) {
69859
- return optionalString2(message.name) ?? optionalString2(message.toolName) ?? optionalString2(message.tool) ?? context?.toolName;
69860
- }
69861
- function pickString(args, keys) {
69862
- if (!args) return void 0;
69863
- for (const key of keys) {
69864
- const value = optionalString2(args[key]);
69865
- if (value) return value;
69866
- }
69867
- return void 0;
69868
- }
69869
- function pickFirstStringArrayValue(args, key) {
69870
- const value = args?.[key];
69871
- if (!Array.isArray(value)) return void 0;
69872
- for (const item of value) {
69873
- const candidate = optionalString2(item);
69874
- if (candidate) return candidate;
69875
- }
69876
- return void 0;
69877
- }
69878
- function fileScopeFromArgs(args) {
69879
- const destinationPath = pickString(args, ["destination", "dest", "targetPath", "target", "to"]) ?? pickString(args, ["path", "filePath", "workspacePath", "projectPath"]) ?? pickFirstStringArrayValue(args, "paths");
69880
- const sourcePath = pickString(args, ["source", "src", "from", "oldPath"]);
69881
- const scope = destinationPath ?? sourcePath;
69882
- return { scope, sourcePath, destinationPath };
69883
- }
69884
- function fileContentHash(args) {
69885
- const content = pickString(args, ["content", "patch", "diff", "text", "value"]) ?? args?.updates;
69886
- return resultHash(content);
69887
- }
69888
- function inferOutcome(message, parsedPayload) {
69889
- if (message.isError === true) return "failure";
69890
- if (isRecord4(parsedPayload)) {
69891
- if (parsedPayload.partial === true || parsedPayload.status === "partial") return "partial";
69892
- if (parsedPayload.success === false || parsedPayload.ok === false) return "failure";
69893
- if (parsedPayload.success === true || parsedPayload.ok === true) return "success";
69894
- if (typeof parsedPayload.exitCode === "number") {
69895
- return parsedPayload.exitCode === 0 ? "success" : "failure";
69896
- }
69897
- if (optionalString2(parsedPayload.error)) return "failure";
69898
- if (parsedPayload.status === "error" || parsedPayload.status === "failed") return "failure";
69899
- if (parsedPayload.status === "ok" || parsedPayload.status === "success") return "success";
69900
- }
69901
- if (typeof parsedPayload === "string") {
69902
- const lowered = parsedPayload.toLowerCase();
69903
- const loweredForFailure = lowered.replace(/\b(?:previously\s+)?failed tests?\s+now\s+pass(?:ed|es)?\b/g, "");
69904
- const hasZeroCountMarker = /\b(?:0|no)\s+(?:errors?|failures?|exceptions?|timeouts?)\b/.test(lowered);
69905
- const loweredForFailureCounts = loweredForFailure.replace(/\b(?:0|no)\s+errors?\b/g, "").replace(/\b(?:0|no)\s+failures?\b/g, "").replace(/\b(?:0|no)\s+exceptions?\b/g, "").replace(/\b(?:0|no)\s+timeouts?\b/g, "");
69906
- const hasNonZeroErrorCounts = /\b[1-9]\d*\s+errors?\b/.test(loweredForFailureCounts);
69907
- const hasNegatedSuccessMarkers = /\b(?:not|did not|didn't|doesn't|isn't|aren't|wasn't|weren't|won't|can't|couldn't|shouldn't|wouldn't)\s+(?:ok|pass|passed|passes|succeeded|success)\b/.test(loweredForFailure);
69908
- const hasSuccessMarkers = /\b(success|succeeded|pass|passes|passed|ok)\b/.test(lowered) || hasZeroCountMarker;
69909
- const hasFailureMarkers = hasNegatedSuccessMarkers || /\b(exceptions?|failed|failures?|fatal|timeouts?|timed out)\b/.test(loweredForFailureCounts) || hasNonZeroErrorCounts || /\berrors?\b/.test(loweredForFailureCounts) || /\b[a-z]+error\b/.test(loweredForFailureCounts) || /\b[a-z]+exception\b/.test(loweredForFailureCounts);
69910
- if (hasFailureMarkers) return "failure";
69911
- if (hasSuccessMarkers) return "success";
69912
- }
69913
- return "unknown";
69914
- }
69915
- function isProcessTool(toolName, args) {
69916
- const tokens = toolNameTokens(toolName);
69917
- const normalizedName = normalizedToolName(toolName);
69918
- if (pickString(args, ["cmd", "command", "script"])) return true;
69919
- return ["exec", "shell", "bash", "terminal", "run_command", "exec_command"].some(
69920
- (token) => token.includes("_") ? normalizedName === token : tokens.includes(token)
69921
- );
69922
- }
69923
- function isFileTool(toolName, args) {
69924
- const tokens = toolNameTokens(toolName);
69925
- const fileScope = fileScopeFromArgs(args);
69926
- if (fileScope.scope) return true;
69927
- return ["file", "path", "patch", "directory", "mkdir", "rename", "move"].some(
69928
- (token) => tokens.includes(token)
69929
- );
69930
- }
69931
- function inferFileChangeKind(toolName, outcome) {
69932
- if (outcome === "failure") return "failed";
69933
- const tokens = toolNameTokens(toolName);
69934
- if (["delete", "remove", "unlink"].some((token) => tokens.includes(token))) return "deleted";
69935
- if (["create", "mkdir", "new"].some((token) => tokens.includes(token))) return "created";
69936
- if (["write", "edit", "patch", "update", "append", "move", "rename"].some((token) => tokens.includes(token))) {
69937
- return "updated";
69938
- }
69939
- return "observed";
69940
- }
69941
- function buildFileValueRefs(args, changeKind) {
69942
- const { sourcePath, destinationPath, scope } = fileScopeFromArgs(args);
69943
- const contentHash = fileContentHash(args);
69944
- if (changeKind === "failed") {
69945
- if (sourcePath && destinationPath && sourcePath !== destinationPath) {
69946
- return {
69947
- before: { ref: sourcePath },
69948
- after: { ref: destinationPath }
69949
- };
69950
- }
69951
- return {
69952
- before: sourcePath ? { ref: sourcePath } : void 0,
69953
- after: scope ? { ref: scope } : void 0
69954
- };
69955
- }
69956
- if (changeKind === "deleted") {
69957
- return {
69958
- before: scope ? { exists: true, ref: scope } : void 0,
69959
- after: { exists: false }
69960
- };
69961
- }
69962
- if (changeKind === "created") {
69963
- return {
69964
- after: {
69965
- exists: true,
69966
- ref: scope,
69967
- valueHash: contentHash
69968
- }
69969
- };
69970
- }
69971
- if (sourcePath && destinationPath && sourcePath !== destinationPath) {
69972
- return {
69973
- before: { exists: true, ref: sourcePath },
69974
- after: {
69975
- exists: true,
69976
- ref: destinationPath
69977
- }
69978
- };
69979
- }
69980
- return {
69981
- after: {
69982
- exists: true,
69983
- ref: scope,
69984
- valueHash: contentHash
69985
- }
69986
- };
69987
- }
69988
- function summarizeSnapshot(kind, changeKind, toolName, scope) {
69989
- const action = changeKind === "executed" ? "Executed" : changeKind === "failed" ? "Failed" : changeKind === "created" ? "Created" : changeKind === "deleted" ? "Deleted" : changeKind === "updated" ? "Updated" : "Observed";
69990
- if (kind === "process") return `${action} process via ${toolName}: ${scope}`;
69991
- if (kind === "file") return `${action} file via ${toolName}: ${scope}`;
69992
- return `${action} tool result from ${toolName}: ${scope}`;
69993
- }
69994
- function buildGenericToolAfterRef(outcome, parsedPayload) {
69995
- const valueHash = resultHash(parsedPayload);
69996
- return valueHash ? { valueHash } : { exists: outcome !== "failure" };
69997
- }
69998
- function snapshotIdFor(sessionKey, recordedAt, index, toolName, scope) {
69999
- const digest = crypto2.createHash("sha256").update(`${sessionKey}|${recordedAt}|${index}|${toolName}|${scope}`).digest("hex").slice(0, 12);
70000
- return `obj-${digest}`;
70001
- }
70002
- function deriveObjectiveStateSnapshotsFromAgentMessages(options) {
70003
- const toolCallsById = getToolCallContexts(options.messages);
70004
- const snapshots = [];
70005
- for (const message of options.messages) {
70006
- if (message.role !== "tool") continue;
70007
- const toolCallId = toolCallIdForMessage(message);
70008
- const context = toolCallId ? toolCallsById.get(toolCallId) : void 0;
70009
- const toolName = toolNameForMessage(message, context);
70010
- if (!toolName) continue;
70011
- const parsedPayload = parseToolResultPayload(message.content);
70012
- const outcome = inferOutcome(message, parsedPayload);
70013
- const args = context?.args;
70014
- const command = pickString(args, ["cmd", "command", "script"]);
70015
- let kind = "tool";
70016
- let changeKind = outcome === "failure" ? "failed" : "observed";
70017
- let scope = toolName;
70018
- let before;
70019
- let after;
70020
- if (isProcessTool(toolName, args)) {
70021
- kind = "process";
70022
- changeKind = outcome === "failure" ? "failed" : "executed";
70023
- scope = command ?? toolName;
70024
- after = { exists: outcome !== "failure", valueHash: resultHash(parsedPayload) };
70025
- } else if (isFileTool(toolName, args)) {
70026
- kind = "file";
70027
- changeKind = inferFileChangeKind(toolName, outcome);
70028
- const fileScope = fileScopeFromArgs(args);
70029
- scope = fileScope.scope ?? toolName;
70030
- const refs = buildFileValueRefs(args, changeKind);
70031
- before = refs.before;
70032
- after = refs.after;
70033
- } else {
70034
- after = buildGenericToolAfterRef(outcome, parsedPayload);
70035
- }
70036
- snapshots.push({
70037
- schemaVersion: 1,
70038
- snapshotId: snapshotIdFor(options.sessionKey, options.recordedAt, snapshots.length, toolName, scope),
70039
- recordedAt: options.recordedAt,
70040
- sessionKey: options.sessionKey,
70041
- source: "tool_result",
70042
- kind,
70043
- changeKind,
70044
- scope,
70045
- summary: summarizeSnapshot(kind, changeKind, toolName, scope),
70046
- toolName,
70047
- command,
70048
- outcome,
70049
- before,
70050
- after,
70051
- tags: ["agent-end", `tool:${toolName}`],
70052
- metadata: toolCallId ? { toolCallId } : void 0
70053
- });
70054
- }
70055
- return snapshots;
70056
- }
70057
- async function recordObjectiveStateSnapshotsFromAgentMessages(options) {
70058
- if (!options.objectiveStateMemoryEnabled || !options.objectiveStateSnapshotWritesEnabled) {
70059
- return { snapshots: [], filePaths: [] };
70060
- }
70061
- const snapshots = deriveObjectiveStateSnapshotsFromAgentMessages({
70062
- sessionKey: options.sessionKey,
70063
- recordedAt: options.recordedAt,
70064
- messages: options.messages
70065
- });
70066
- const filePaths = [];
70067
- for (const snapshot of snapshots) {
70068
- filePaths.push(
70069
- await recordObjectiveStateSnapshot({
70070
- memoryDir: options.memoryDir,
70071
- objectiveStateStoreDir: options.objectiveStateStoreDir,
70072
- snapshot
70073
- })
70074
- );
70075
- }
70076
- return { snapshots, filePaths };
70077
- }
70078
-
70079
70581
  // ../../src/qmd-availability-probe.ts
70080
70582
  async function probeQmdAvailability(host) {
70081
70583
  const qmd = host?.qmd;
@@ -72993,6 +73495,16 @@ function tryDefinePluginEntry(def) {
72993
73495
  }
72994
73496
  }
72995
73497
  var sdkCaps;
73498
+ var NON_RUNTIME_REGISTRATION_MODES = /* @__PURE__ */ new Set([
73499
+ "discovery",
73500
+ "tool-discovery",
73501
+ "setup-only",
73502
+ "setup-runtime",
73503
+ "cli-metadata"
73504
+ ]);
73505
+ function isNonRuntimeRegistrationMode(mode) {
73506
+ return typeof mode === "string" && NON_RUNTIME_REGISTRATION_MODES.has(mode);
73507
+ }
72996
73508
  var pluginDefinition = {
72997
73509
  id: PLUGIN_ID,
72998
73510
  name: "Remnic (Local Memory)",
@@ -73003,6 +73515,16 @@ var pluginDefinition = {
73003
73515
  const serviceId = typeof registerThis?.id === "string" && registerThis.id.trim().length > 0 ? registerThis.id : PLUGIN_ID;
73004
73516
  const keys = buildServiceKeys(serviceId);
73005
73517
  initLogger(api.logger, false);
73518
+ sdkCaps = detectSdkCapabilities(api);
73519
+ log.info(
73520
+ `SDK detection: version=${sdkCaps.sdkVersion}, beforePromptBuild=${sdkCaps.hasBeforePromptBuild}, memoryPromptSection=${sdkCaps.hasRegisterMemoryPromptSection}, memoryCapability=${sdkCaps.hasRegisterMemoryCapability}, typedHooks=${sdkCaps.hasTypedHooks}`
73521
+ );
73522
+ if (isNonRuntimeRegistrationMode(sdkCaps.registrationMode)) {
73523
+ log.info(
73524
+ `registrationMode=${sdkCaps.registrationMode} \u2014 skipping runtime initialization`
73525
+ );
73526
+ return;
73527
+ }
73006
73528
  const disableRegisterMigration = readEnvVar("REMNIC_DISABLE_REGISTER_MIGRATION") === "1" || readEnvVar("OPENCLAW_ENGRAM_DISABLE_REGISTER_MIGRATION") === "1";
73007
73529
  if (!disableRegisterMigration) {
73008
73530
  const migrationPromise = globalThis[ENGRAM_MIGRATION_PROMISE] ??= migrateFromEngram({
@@ -73013,14 +73535,6 @@ var pluginDefinition = {
73013
73535
  });
73014
73536
  void migrationPromise;
73015
73537
  }
73016
- sdkCaps = detectSdkCapabilities(api);
73017
- log.info(
73018
- `SDK detection: version=${sdkCaps.sdkVersion}, beforePromptBuild=${sdkCaps.hasBeforePromptBuild}, memoryPromptSection=${sdkCaps.hasRegisterMemoryPromptSection}, memoryCapability=${sdkCaps.hasRegisterMemoryCapability}, typedHooks=${sdkCaps.hasTypedHooks}`
73019
- );
73020
- if (sdkCaps.registrationMode === "setup-only") {
73021
- log.info("registrationMode=setup-only \u2014 skipping full initialization");
73022
- return;
73023
- }
73024
73538
  const fileConfig = loadPluginConfigFromFile(serviceId);
73025
73539
  const cfg = parseConfig({
73026
73540
  ...fileConfig,
@@ -74468,9 +74982,16 @@ Keep the reflection grounded in the evidence below.
74468
74982
  }
74469
74983
  }
74470
74984
  try {
74985
+ const objectiveStateNamespace = orchestrator.config.namespacesEnabled && typeof orchestrator.resolveSelfNamespace === "function" ? orchestrator.resolveSelfNamespace(sessionKey) : orchestrator.config.defaultNamespace;
74986
+ const objectiveStateStorage = orchestrator.config.namespacesEnabled && typeof orchestrator.getStorageForNamespace === "function" ? await orchestrator.getStorageForNamespace(objectiveStateNamespace) : null;
74471
74987
  await recordObjectiveStateSnapshotsFromAgentMessages({
74472
- memoryDir: orchestrator.config.memoryDir,
74473
- objectiveStateStoreDir: orchestrator.config.objectiveStateStoreDir,
74988
+ memoryDir: objectiveStateStorage?.dir ?? orchestrator.config.memoryDir,
74989
+ objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({
74990
+ memoryDir: orchestrator.config.memoryDir,
74991
+ configuredStoreDir: orchestrator.config.objectiveStateStoreDir,
74992
+ namespacesEnabled: orchestrator.config.namespacesEnabled,
74993
+ namespace: objectiveStateNamespace
74994
+ }),
74474
74995
  objectiveStateMemoryEnabled: orchestrator.config.objectiveStateMemoryEnabled,
74475
74996
  objectiveStateSnapshotWritesEnabled: orchestrator.config.objectiveStateSnapshotWritesEnabled,
74476
74997
  sessionKey,