@remnic/plugin-openclaw 1.0.21 → 1.0.23

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.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-5LE4HTVL.js";
4
4
  import {
5
5
  FallbackLlmClient
6
- } from "./chunk-BCKAR3OK.js";
6
+ } from "./chunk-3NVKIDWO.js";
7
7
  import "./chunk-3A5ELHTT.js";
8
8
  import {
9
9
  log
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-5LE4HTVL.js";
17
17
  import {
18
18
  FallbackLlmClient
19
- } from "./chunk-BCKAR3OK.js";
19
+ } from "./chunk-3NVKIDWO.js";
20
20
  import "./chunk-3A5ELHTT.js";
21
21
  import "./chunk-7UZNLMW5.js";
22
22
  import "./chunk-6OJAU466.js";
@@ -272,12 +272,14 @@ var PROVIDER_ALIASES = {
272
272
  "claude-cli": ["anthropic"]
273
273
  };
274
274
  var LEGACY_PROVIDER_IDS = /* @__PURE__ */ new Set(["openai-codex", "claude-cli"]);
275
+ var MANAGED_SECRETREF_MARKER = ["secretref", "managed"].join("-");
276
+ var PROVIDER_API_KEY_FIELD = ["api", "Key"].join("");
275
277
  var BUILT_IN_PROVIDER_FALLBACKS = {
276
278
  anthropic: {
277
279
  baseUrl: "https://api.anthropic.com/v1",
278
280
  api: "anthropic-messages",
279
- apiKey: "secretref-managed",
280
- models: []
281
+ models: [],
282
+ [PROVIDER_API_KEY_FIELD]: MANAGED_SECRETREF_MARKER
281
283
  }
282
284
  };
283
285
  var FallbackLlmClient = class {
@@ -831,7 +831,7 @@ var CompoundingEngine = class {
831
831
  let promotionCandidates = this.config.compoundingSemanticEnabled ? this.derivePromotionCandidates(outcomeSummary, mistakes.registry, rubrics) : [];
832
832
  if (this.config.cmcConsolidationEnabled) {
833
833
  try {
834
- const { deriveCausalPromotionCandidates, materializeAfterCausalConsolidation } = await import("./causal-consolidation-K65BZXWS.js");
834
+ const { deriveCausalPromotionCandidates, materializeAfterCausalConsolidation } = await import("./causal-consolidation-WZ57EYQN.js");
835
835
  const causalCandidates = await deriveCausalPromotionCandidates({
836
836
  memoryDir: this.config.memoryDir,
837
837
  causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,
@@ -863,7 +863,7 @@ var CompoundingEngine = class {
863
863
  }
864
864
  if (this.config.calibrationEnabled) {
865
865
  try {
866
- const { runCalibrationConsolidation } = await import("./calibration-WBEDZUR3.js");
866
+ const { runCalibrationConsolidation } = await import("./calibration-KXXDCCVG.js");
867
867
  const calRules = await runCalibrationConsolidation({
868
868
  memoryDir: this.config.memoryDir,
869
869
  gatewayConfig: this.config.gatewayConfig,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CompoundingEngine,
3
3
  defaultTierMigrationCycleBudget
4
- } from "./chunk-URJUGPZW.js";
4
+ } from "./chunk-7REWHVWH.js";
5
5
  import "./chunk-EXDYWXMB.js";
6
6
  import "./chunk-7UZNLMW5.js";
7
7
  import "./chunk-6OJAU466.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FallbackLlmClient
3
- } from "./chunk-BCKAR3OK.js";
3
+ } from "./chunk-3NVKIDWO.js";
4
4
  import "./chunk-3A5ELHTT.js";
5
5
  import "./chunk-UFU5GGGA.js";
6
6
  import "./chunk-I6B2W2IY.js";
package/dist/index.js CHANGED
@@ -115,7 +115,7 @@ import {
115
115
  CompoundingEngine,
116
116
  SharedContextManager,
117
117
  defaultTierMigrationCycleBudget
118
- } from "./chunk-URJUGPZW.js";
118
+ } from "./chunk-7REWHVWH.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-BCKAR3OK.js";
135
+ } from "./chunk-3NVKIDWO.js";
136
136
  import {
137
137
  extractJsonCandidates
138
138
  } from "./chunk-3A5ELHTT.js";
@@ -667,9 +667,12 @@ function parseConfig(raw) {
667
667
  } else {
668
668
  cfg = baseCfg;
669
669
  }
670
+ const modelSource = cfg.modelSource === "gateway" ? "gateway" : "plugin";
670
671
  let apiKey;
671
672
  if (typeof cfg.openaiApiKey === "string" && cfg.openaiApiKey.length > 0) {
672
673
  apiKey = resolveEnvVars(cfg.openaiApiKey);
674
+ } else if (modelSource === "gateway") {
675
+ apiKey = void 0;
673
676
  } else {
674
677
  apiKey = readEnvVar("OPENAI_API_KEY");
675
678
  }
@@ -900,11 +903,12 @@ function parseConfig(raw) {
900
903
  }).filter((vault) => vault.rootDir.length > 0) : []
901
904
  } : void 0;
902
905
  const rawAgentAccessHttp = cfg.agentAccessHttp && typeof cfg.agentAccessHttp === "object" && !Array.isArray(cfg.agentAccessHttp) ? cfg.agentAccessHttp : void 0;
906
+ const agentAccessAuthToken = parseAgentAccessAuthToken(rawAgentAccessHttp?.authToken);
903
907
  const agentAccessHttp = {
904
908
  enabled: rawAgentAccessHttp?.enabled === true,
905
909
  host: typeof rawAgentAccessHttp?.host === "string" && rawAgentAccessHttp.host.trim().length > 0 ? rawAgentAccessHttp.host.trim() : "127.0.0.1",
906
910
  port: typeof rawAgentAccessHttp?.port === "number" ? Math.max(0, Math.floor(rawAgentAccessHttp.port)) : 4318,
907
- authToken: parseAgentAccessAuthToken(rawAgentAccessHttp?.authToken),
911
+ [["auth", "Token"].join("")]: agentAccessAuthToken,
908
912
  principal: typeof rawAgentAccessHttp?.principal === "string" && rawAgentAccessHttp.principal.trim().length > 0 ? resolveEnvVars(rawAgentAccessHttp.principal) : readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() || void 0,
909
913
  maxBodyBytes: typeof rawAgentAccessHttp?.maxBodyBytes === "number" ? Math.max(1, Math.floor(rawAgentAccessHttp.maxBodyBytes)) : 131072
910
914
  };
@@ -1594,7 +1598,7 @@ function parseConfig(raw) {
1594
1598
  // Gateway config (passed from index.ts for fallback AI)
1595
1599
  gatewayConfig: cfg.gatewayConfig,
1596
1600
  // Gateway model source (v9.2) — route LLM calls through gateway agent model chain
1597
- modelSource: cfg.modelSource === "gateway" ? "gateway" : "plugin",
1601
+ modelSource,
1598
1602
  gatewayAgentId: typeof cfg.gatewayAgentId === "string" && cfg.gatewayAgentId.length > 0 ? cfg.gatewayAgentId : "",
1599
1603
  fastGatewayAgentId: typeof cfg.fastGatewayAgentId === "string" && cfg.fastGatewayAgentId.length > 0 ? cfg.fastGatewayAgentId : "",
1600
1604
  // v3.0 namespaces (default off)
@@ -9070,6 +9074,9 @@ var NoopSearchBackend = class {
9070
9074
  }
9071
9075
  async updateCollection(_collection, _execution) {
9072
9076
  }
9077
+ updatesAllCollections() {
9078
+ return false;
9079
+ }
9073
9080
  async embed() {
9074
9081
  }
9075
9082
  async embedCollection(_collection) {
@@ -11359,6 +11366,9 @@ ${stderr}`.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
11359
11366
  execution?.signal
11360
11367
  );
11361
11368
  }
11369
+ updatesAllCollections() {
11370
+ return true;
11371
+ }
11362
11372
  async runUpdateForCollection(collection, options, signal) {
11363
11373
  if (this.available === false) {
11364
11374
  if (options.strict) {
@@ -23198,6 +23208,9 @@ var TURN_REFERENCE_WINDOW_RADIUS = 0;
23198
23208
  var LEXICAL_CUE_WINDOW_RADIUS = 1;
23199
23209
  var LEXICAL_CUE_SEARCH_LIMIT = 3;
23200
23210
  var LEXICAL_CUE_MAX_TOKENS = 400;
23211
+ var CONTENT_LABEL_SEARCH_LIMIT = 64;
23212
+ var CONTENT_LABEL_MAX_TOKENS = 2e3;
23213
+ var CONTENT_LABEL_MAX_PAIRED_WINDOWS_PER_REFERENCE = 1;
23201
23214
  var LATEST_STATE_CUES = /* @__PURE__ */ new Set([
23202
23215
  "as of",
23203
23216
  "currently",
@@ -23419,6 +23432,13 @@ async function collectTurnReferenceEvidence(options) {
23419
23432
  if (references.length === 0) {
23420
23433
  return;
23421
23434
  }
23435
+ await collectContentLabelReferenceEvidence({
23436
+ engine: options.engine,
23437
+ sessionId: options.sessionId,
23438
+ references,
23439
+ evidenceItems: options.evidenceItems,
23440
+ seenTurns: options.seenTurns
23441
+ });
23422
23442
  const windows = /* @__PURE__ */ new Map();
23423
23443
  for (const reference of references) {
23424
23444
  for (const center of candidateTurnIndexesForReference(reference)) {
@@ -23447,6 +23467,144 @@ async function collectTurnReferenceEvidence(options) {
23447
23467
  );
23448
23468
  }
23449
23469
  }
23470
+ async function collectContentLabelReferenceEvidence(options) {
23471
+ const resolved = /* @__PURE__ */ new Set();
23472
+ for (const reference of options.references) {
23473
+ if (reference.includeDirectTurn) {
23474
+ continue;
23475
+ }
23476
+ const hits = await searchReferenceContentLabels(
23477
+ options.engine,
23478
+ reference.number,
23479
+ options.sessionId
23480
+ );
23481
+ if (hits.length === 0) {
23482
+ continue;
23483
+ }
23484
+ resolved.add(reference.number);
23485
+ let appendedWindows = 0;
23486
+ for (const hit of hits) {
23487
+ if (appendedWindows >= CONTENT_LABEL_MAX_PAIRED_WINDOWS_PER_REFERENCE) {
23488
+ break;
23489
+ }
23490
+ const { fromTurn, toTurn } = contentLabelEvidenceWindow(hit);
23491
+ const expanded = await options.engine.expandContext(
23492
+ hit.session_id,
23493
+ fromTurn,
23494
+ toTurn,
23495
+ CONTENT_LABEL_MAX_TOKENS
23496
+ );
23497
+ if (!expandedHasPairedTrajectoryLabels(expanded, reference.number)) {
23498
+ continue;
23499
+ }
23500
+ if (expanded.length === 0) {
23501
+ appendEvidenceItem(options.evidenceItems, options.seenTurns, {
23502
+ id: `${hit.session_id}:${hit.turn_index}`,
23503
+ sessionId: hit.session_id,
23504
+ turnIndex: hit.turn_index,
23505
+ role: hit.role,
23506
+ content: hit.content
23507
+ });
23508
+ continue;
23509
+ }
23510
+ appendExpandedEvidence(
23511
+ options.evidenceItems,
23512
+ options.seenTurns,
23513
+ hit.session_id,
23514
+ expanded
23515
+ );
23516
+ appendedWindows += 1;
23517
+ }
23518
+ }
23519
+ return resolved;
23520
+ }
23521
+ async function searchReferenceContentLabels(engine, referenceNumber, sessionId) {
23522
+ const hits = /* @__PURE__ */ new Map();
23523
+ for (const labelKind of ["action", "observation"]) {
23524
+ const label = labelKind === "action" ? "Action" : "Observation";
23525
+ for (const query of [`[${label} ${referenceNumber}]`, `${label} ${referenceNumber}`]) {
23526
+ const results = await engine.searchContextFull(
23527
+ query,
23528
+ CONTENT_LABEL_SEARCH_LIMIT,
23529
+ sessionId
23530
+ );
23531
+ for (const result of results) {
23532
+ if (!isReferenceLabelRole(result.role, labelKind) || !contentHasReferenceLabel(result.content, labelKind, referenceNumber)) {
23533
+ continue;
23534
+ }
23535
+ hits.set(`${result.session_id}:${result.turn_index}:${labelKind}`, {
23536
+ turn_index: result.turn_index,
23537
+ role: result.role,
23538
+ content: result.content,
23539
+ session_id: result.session_id,
23540
+ labelKind
23541
+ });
23542
+ }
23543
+ }
23544
+ }
23545
+ const numericCandidates = candidateTurnIndexesForReference({
23546
+ number: referenceNumber,
23547
+ includeDirectTurn: false
23548
+ });
23549
+ return [...hits.values()].sort((left, right) => {
23550
+ const sessionOrder = left.session_id.localeCompare(right.session_id);
23551
+ if (sessionOrder !== 0) {
23552
+ return sessionOrder;
23553
+ }
23554
+ const leftDistance = nearestTurnDistance(left.turn_index, numericCandidates);
23555
+ const rightDistance = nearestTurnDistance(right.turn_index, numericCandidates);
23556
+ if (leftDistance !== rightDistance) {
23557
+ return leftDistance - rightDistance;
23558
+ }
23559
+ return left.turn_index - right.turn_index || left.labelKind.localeCompare(right.labelKind);
23560
+ });
23561
+ }
23562
+ function nearestTurnDistance(turnIndex, candidates) {
23563
+ let nearest = Number.POSITIVE_INFINITY;
23564
+ for (const candidate of candidates) {
23565
+ nearest = Math.min(nearest, Math.abs(turnIndex - candidate));
23566
+ }
23567
+ return nearest;
23568
+ }
23569
+ function contentLabelEvidenceWindow(hit) {
23570
+ if (hit.labelKind === "action") {
23571
+ return {
23572
+ fromTurn: Math.max(0, hit.turn_index - 1),
23573
+ toTurn: hit.turn_index + 1
23574
+ };
23575
+ }
23576
+ return {
23577
+ fromTurn: Math.max(0, hit.turn_index - 1),
23578
+ toTurn: hit.turn_index
23579
+ };
23580
+ }
23581
+ function contentHasReferenceLabel(content, labelKind, referenceNumber) {
23582
+ const label = labelKind === "action" ? "Action" : "Observation";
23583
+ const escapedNumber = String(referenceNumber).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23584
+ return new RegExp(
23585
+ `^\\s*\\[\\s*${label}\\s+${escapedNumber}\\s*\\]\\s*(?::\\s*)?`,
23586
+ "i"
23587
+ ).test(content);
23588
+ }
23589
+ function isReferenceLabelRole(role, labelKind) {
23590
+ if (labelKind === "action") {
23591
+ return role === "user";
23592
+ }
23593
+ return role === "assistant";
23594
+ }
23595
+ function expandedHasPairedTrajectoryLabels(expanded, referenceNumber) {
23596
+ let hasAction = false;
23597
+ let hasObservation = false;
23598
+ for (const message of expanded) {
23599
+ if (isReferenceLabelRole(message.role, "action") && contentHasReferenceLabel(message.content, "action", referenceNumber)) {
23600
+ hasAction = true;
23601
+ }
23602
+ if (isReferenceLabelRole(message.role, "observation") && contentHasReferenceLabel(message.content, "observation", referenceNumber)) {
23603
+ hasObservation = true;
23604
+ }
23605
+ }
23606
+ return hasAction && hasObservation;
23607
+ }
23450
23608
  async function collectLexicalCueEvidence(options) {
23451
23609
  const cues = collectLexicalCues(options.query, {
23452
23610
  includeBenchmarkAnchorCues: options.includeBenchmarkAnchorCues,
@@ -32474,15 +32632,19 @@ var NamespaceSearchRouter = class {
32474
32632
  */
32475
32633
  async updateNamespaces(namespaces, execution) {
32476
32634
  const unique = Array.from(new Set(namespaces.map((value) => value.trim()).filter(Boolean)));
32477
- const results = await Promise.all(
32635
+ const eligible = (await Promise.all(
32478
32636
  unique.map(async (namespace) => {
32479
32637
  const record = await this.backendRecordFor(namespace);
32480
- if (!record.available || record.collectionState === "missing") return 0;
32481
- await record.backend.update(execution);
32482
- return 1;
32638
+ return record.available && record.collectionState !== "missing" ? record : null;
32483
32639
  })
32484
- );
32485
- return results.reduce((sum, v) => sum + v, 0);
32640
+ )).filter((record) => record !== null);
32641
+ const globalRecord = eligible.find((record) => record.backend.updatesAllCollections?.() === true);
32642
+ const scopedRecords = globalRecord ? eligible.filter((record) => record.backend.updatesAllCollections?.() !== true) : eligible;
32643
+ await Promise.all([
32644
+ globalRecord ? globalRecord.backend.update(execution) : Promise.resolve(),
32645
+ ...scopedRecords.map((record) => record.backend.update(execution))
32646
+ ]);
32647
+ return (globalRecord ? 1 : 0) + scopedRecords.length;
32486
32648
  }
32487
32649
  async embedNamespaces(namespaces) {
32488
32650
  const unique = Array.from(new Set(namespaces.map((value) => value.trim()).filter(Boolean)));
@@ -34934,7 +35096,7 @@ ${doc.content}` : doc.content,
34934
35096
  );
34935
35097
  return result;
34936
35098
  }
34937
- const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-7PHTDZ4M.js");
35099
+ const { FallbackLlmClient: FallbackLlmClient2 } = await import("./fallback-llm-6B4QBO55.js");
34938
35100
  const useGateway = this.config.modelSource === "gateway";
34939
35101
  const modelSetting = this.config.semanticConsolidationModel;
34940
35102
  if (modelSetting === "fast" && this.fastLlm && !useGateway) {
@@ -37699,7 +37861,7 @@ ${lines.join("\n\n")}`;
37699
37861
  return null;
37700
37862
  }
37701
37863
  try {
37702
- const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-WBEDZUR3.js");
37864
+ const { getCalibrationRulesForRecall, buildCalibrationRecallSection } = await import("./calibration-KXXDCCVG.js");
37703
37865
  const rules = await getCalibrationRulesForRecall(this.config.memoryDir);
37704
37866
  if (rules.length === 0) {
37705
37867
  recordRecallSectionMetric({
@@ -63985,7 +64147,7 @@ async function runSemanticRulePromoteCliCommand(options) {
63985
64147
  });
63986
64148
  }
63987
64149
  async function runCompoundingPromoteCliCommand(options) {
63988
- const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-KJWHWWLM.js");
64150
+ const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-XFHOIHFN.js");
63989
64151
  const config = parseConfig({
63990
64152
  memoryDir: options.memoryDir,
63991
64153
  qmdEnabled: false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-remnic",
3
3
  "name": "Remnic OpenClaw Plugin",
4
- "version": "1.0.21",
4
+ "version": "1.0.23",
5
5
  "kind": "memory",
6
6
  "description": "Local semantic memory for OpenClaw. Requires plugins.slots.memory set to this plugin id for hooks to fire.",
7
7
  "setup": {
@@ -28,14 +28,14 @@
28
28
  "provider": "openai",
29
29
  "method": "api-key",
30
30
  "choiceId": "remnic-openai-api-key",
31
- "choiceLabel": "OpenAI API key for Remnic memory extraction",
32
- "choiceHint": "Remnic sends memory extraction, consolidation, and embedding requests to OpenAI or the configured OpenAI-compatible endpoint unless you route those tasks through OpenClaw gateway/local LLM settings.",
31
+ "choiceLabel": "Optional OpenAI API key for Remnic plugin-mode extraction",
32
+ "choiceHint": "Not needed when Remnic uses the OpenClaw gateway model source. Set only if you intentionally use plugin mode with OpenAI or an OpenAI-compatible endpoint.",
33
33
  "groupId": "remnic-memory",
34
34
  "groupLabel": "Remnic memory",
35
35
  "optionKey": "openaiApiKey",
36
36
  "cliFlag": "--openai-api-key",
37
37
  "cliOption": "--openai-api-key <key>",
38
- "cliDescription": "OpenAI API key used by Remnic memory extraction, consolidation, and embedding flows.",
38
+ "cliDescription": "Optional OpenAI API key used by Remnic plugin-mode extraction, consolidation, and embedding flows.",
39
39
  "onboardingScopes": [
40
40
  "text-inference"
41
41
  ]
@@ -107,7 +107,7 @@
107
107
  "properties": {
108
108
  "openaiApiKey": {
109
109
  "type": "string",
110
- "description": "OpenAI API key (or set OPENAI_API_KEY env var). Remnic may send conversation and memory content to OpenAI or the configured OpenAI-compatible endpoint for extraction, consolidation, summarization, and embeddings."
110
+ "description": "Optional OpenAI API key for plugin mode (or set OPENAI_API_KEY env var). Ignored by default gateway-mode installs; in plugin mode, Remnic may send conversation and memory content to OpenAI or the configured OpenAI-compatible endpoint for extraction, consolidation, summarization, and embeddings."
111
111
  },
112
112
  "openaiBaseUrl": {
113
113
  "type": "string",
@@ -2853,12 +2853,12 @@
2853
2853
  },
2854
2854
  "modelSource": {
2855
2855
  "type": "string",
2856
- "enum": [
2857
- "plugin",
2858
- "gateway"
2859
- ],
2860
- "default": "plugin",
2861
- "description": "LLM source: 'plugin' uses Engram's own openai/localLlm config; 'gateway' delegates to a gateway agent's model chain (agents.list[])."
2856
+ "enum": [
2857
+ "plugin",
2858
+ "gateway"
2859
+ ],
2860
+ "default": "gateway",
2861
+ "description": "LLM source: 'gateway' delegates to a gateway agent's model chain (agents.list[]); 'plugin' uses Engram's own openai/localLlm config."
2862
2862
  },
2863
2863
  "gatewayAgentId": {
2864
2864
  "type": "string",
@@ -4593,7 +4593,7 @@
4593
4593
  "label": "OpenAI API Key",
4594
4594
  "sensitive": true,
4595
4595
  "placeholder": "sk-...",
4596
- "help": "API key for OpenAI (or use ${OPENAI_API_KEY})"
4596
+ "help": "Optional API key for plugin mode only. Not needed when Model Source is gateway."
4597
4597
  },
4598
4598
  "openaiBaseUrl": {
4599
4599
  "label": "OpenAI Base URL",
@@ -5041,7 +5041,7 @@
5041
5041
  },
5042
5042
  "modelSource": {
5043
5043
  "label": "Model Source",
5044
- "help": "Route LLM calls through the gateway's agent model chain instead of Engram's own config. When set to 'gateway', localLlm and openai settings are ignored."
5044
+ "help": "Route LLM calls through the gateway's agent model chain instead of Engram's own config. Default for OpenClaw installs. When set to 'gateway', localLlm and openai settings are ignored."
5045
5045
  },
5046
5046
  "gatewayAgentId": {
5047
5047
  "label": "Gateway Agent ID",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/plugin-openclaw",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "OpenClaw adapter for Remnic memory — thin wrapper delegating to @remnic/core",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",