@remnic/plugin-openclaw 9.54.3 → 9.54.5

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
@@ -214,6 +214,49 @@ import {
214
214
 
215
215
  // ../../src/tools.ts
216
216
  import { runMemoryGovernance } from "@remnic/core/maintenance/memory-governance";
217
+
218
+ // ../../src/memory-action-target.ts
219
+ import { isSupportPassportPrivateMemory } from "@remnic/core";
220
+ function clampUnitInterval(value, fallback) {
221
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
222
+ if (value < 0) return 0;
223
+ if (value > 1) return 1;
224
+ return value;
225
+ }
226
+ function normalizeEligibilitySource(value) {
227
+ switch (value) {
228
+ case "extraction":
229
+ case "consolidation":
230
+ case "replay":
231
+ case "manual":
232
+ return value;
233
+ default:
234
+ return "unknown";
235
+ }
236
+ }
237
+ function deriveMemoryActionPolicyEligibility(memory) {
238
+ if (!memory) return void 0;
239
+ const frontmatter = memory.frontmatter;
240
+ return {
241
+ confidence: clampUnitInterval(frontmatter.confidence, 0),
242
+ lifecycleState: frontmatter.status === "archived" ? "archived" : frontmatter.lifecycleState ?? "candidate",
243
+ importance: clampUnitInterval(frontmatter.importance?.score, 0),
244
+ source: normalizeEligibilitySource(frontmatter.source)
245
+ };
246
+ }
247
+ async function readReferencedMemoryForPolicyEligibility(storage, memoryId) {
248
+ if (!memoryId) return void 0;
249
+ const direct = await storage.getMemoryById?.(memoryId);
250
+ if (direct) return direct;
251
+ const active = (await storage.readAllMemories?.())?.find((memory) => memory.frontmatter.id === memoryId);
252
+ if (active) return active;
253
+ return (await storage.readArchivedMemories?.())?.find((memory) => memory.frontmatter.id === memoryId);
254
+ }
255
+ function blocksSupportPassportMutation(action, memory) {
256
+ return (action === "update_note" || action === "discard" || action === "link_graph") && Boolean(memory && isSupportPassportPrivateMemory(memory));
257
+ }
258
+
259
+ // ../../src/tools.ts
217
260
  function toolResult(text) {
218
261
  return { content: [{ type: "text", text }], details: void 0 };
219
262
  }
@@ -232,12 +275,6 @@ function asNonEmptyString(value) {
232
275
  function normalizeToolNamespace(value) {
233
276
  return asNonEmptyString(value);
234
277
  }
235
- function clampUnitInterval(value, fallback) {
236
- if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
237
- if (value < 0) return 0;
238
- if (value > 1) return 1;
239
- return value;
240
- }
241
278
  function normalizeProfilingReportLimit(value) {
242
279
  if (value === void 0) return 5;
243
280
  if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value)) {
@@ -252,43 +289,7 @@ function normalizeMemorySearchResultLimit(value) {
252
289
  }
253
290
  return Math.min(Math.max(value, 1), 50);
254
291
  }
255
- function normalizeMemoryActionEligibilitySource(value) {
256
- switch (value) {
257
- case "extraction":
258
- case "consolidation":
259
- case "replay":
260
- case "manual":
261
- return value;
262
- default:
263
- return "unknown";
264
- }
265
- }
266
- function deriveMemoryActionPolicyEligibility(memory) {
267
- if (!memory) return void 0;
268
- const frontmatter = memory.frontmatter;
269
- return {
270
- confidence: clampUnitInterval(frontmatter.confidence, 0),
271
- lifecycleState: frontmatter.status === "archived" ? "archived" : frontmatter.lifecycleState ?? "candidate",
272
- importance: clampUnitInterval(frontmatter.importance?.score, 0),
273
- source: normalizeMemoryActionEligibilitySource(frontmatter.source)
274
- };
275
- }
276
- async function readReferencedMemoryForPolicyEligibility(storage, memoryId) {
277
- if (!memoryId) return void 0;
278
- if (typeof storage.getMemoryById === "function") {
279
- const direct = await storage.getMemoryById(memoryId);
280
- if (direct) return direct;
281
- }
282
- if (typeof storage.readAllMemories === "function") {
283
- const active = (await storage.readAllMemories()).find((memory) => memory.frontmatter.id === memoryId);
284
- if (active) return active;
285
- }
286
- if (typeof storage.readArchivedMemories === "function") {
287
- const archived = (await storage.readArchivedMemories()).find((memory) => memory.frontmatter.id === memoryId);
288
- if (archived) return archived;
289
- }
290
- return void 0;
291
- }
292
+ var MEMORY_SEARCH_CANDIDATE_CAP = 25e3;
292
293
  var WORK_TASK_STATUSES = /* @__PURE__ */ new Set(["todo", "in_progress", "blocked", "done", "cancelled"]);
293
294
  var WORK_TASK_PRIORITIES = /* @__PURE__ */ new Set(["low", "medium", "high"]);
294
295
  var WORK_PROJECT_STATUSES = /* @__PURE__ */ new Set(["active", "on_hold", "completed", "archived"]);
@@ -568,12 +569,39 @@ Best for:
568
569
  const { query, maxResults, collection, namespace } = params;
569
570
  const namespaceFilter = namespace && namespace.length > 0 ? namespace : void 0;
570
571
  const resultLimit = normalizeMemorySearchResultLimit(maxResults);
571
- const filtered = collection === "global" && !namespaceFilter ? (await orchestrator.qmd.searchGlobal(query, resultLimit)).slice(0, resultLimit) : await orchestrator.searchAcrossNamespaces({
572
+ const searchCandidates = async (limit) => collection === "global" && !namespaceFilter ? await orchestrator.qmd.searchGlobal(query, limit) : await orchestrator.searchAcrossNamespaces({
572
573
  query,
573
574
  namespaces: namespaceFilter ? [namespaceFilter] : void 0,
574
- maxResults: resultLimit,
575
+ maxResults: limit,
575
576
  mode: "search"
576
577
  });
578
+ let candidateLimit = resultLimit;
579
+ const privateVisibilityCache = /* @__PURE__ */ new Map();
580
+ let candidates = await searchCandidates(candidateLimit);
581
+ let filtered = await orchestrator.filterPrivateSearchResults(
582
+ candidates,
583
+ namespaceFilter ? [namespaceFilter] : [],
584
+ false,
585
+ privateVisibilityCache
586
+ );
587
+ while (filtered.length < resultLimit && candidates.length >= candidateLimit && candidateLimit < MEMORY_SEARCH_CANDIDATE_CAP) {
588
+ const nextCandidateLimit = Math.min(
589
+ MEMORY_SEARCH_CANDIDATE_CAP,
590
+ Math.max(candidateLimit + 16, candidateLimit * 2)
591
+ );
592
+ if (nextCandidateLimit === candidateLimit) break;
593
+ const nextCandidates = await searchCandidates(nextCandidateLimit);
594
+ if (nextCandidates.length <= candidates.length) break;
595
+ candidateLimit = nextCandidateLimit;
596
+ candidates = nextCandidates;
597
+ filtered = await orchestrator.filterPrivateSearchResults(
598
+ candidates,
599
+ namespaceFilter ? [namespaceFilter] : [],
600
+ false,
601
+ privateVisibilityCache
602
+ );
603
+ }
604
+ filtered = filtered.slice(0, resultLimit);
577
605
  if (filtered.length === 0) {
578
606
  return toolResult(`No memories found matching: "${query}"`);
579
607
  }
@@ -1600,6 +1628,19 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
1600
1628
  }
1601
1629
  const storage = typeof orchestrator.getStorage === "function" ? await orchestrator.getStorage(ns) : orchestrator.storage;
1602
1630
  const referencedMemory = await readReferencedMemoryForPolicyEligibility(storage, memoryIdValue);
1631
+ if (blocksSupportPassportMutation(action, referencedMemory)) {
1632
+ await orchestrator.appendMemoryActionEvent({
1633
+ ...baseEvent,
1634
+ outcome: "failed",
1635
+ status: "rejected",
1636
+ dryRun: dryRun === true,
1637
+ outputMemoryIds: [],
1638
+ reason: "validation: support passport records require the owner surface"
1639
+ });
1640
+ return toolResult(
1641
+ "Validation failed: support passport records can only be changed through the support passport owner surface."
1642
+ );
1643
+ }
1603
1644
  const structuredEvent = {
1604
1645
  ...baseEvent,
1605
1646
  outcome: outcome ?? "applied",
@@ -5870,7 +5911,7 @@ function readUnitAuthToken(source) {
5870
5911
  }).authToken
5871
5912
  };
5872
5913
  }
5873
- function readServiceEndpoints() {
5914
+ function readServiceEndpoints(exists = fileExists) {
5874
5915
  const homeDir = resolveHomeDir();
5875
5916
  const unitPaths = [
5876
5917
  ...LAUNCHD_SERVICE_PATHS.map((segments) => {
@@ -5882,12 +5923,12 @@ function readServiceEndpoints() {
5882
5923
  ...resolveSystemUnitSources(
5883
5924
  systemdUserUnitDirs(homeDir),
5884
5925
  SYSTEMD_UNIT_NAMES,
5885
- fileExists
5926
+ exists
5886
5927
  ).map((source) => ({ ...source, userScoped: true })),
5887
5928
  // For a SYSTEM unit the base file and its overrides can live in different
5888
5929
  // load-path directories: a packaged unit under `/usr/lib` customized by
5889
5930
  // `systemctl edit`, which writes `/etc/systemd/system/<unit>.d/*.conf`.
5890
- ...resolveSystemUnitSources(SYSTEMD_SYSTEM_UNIT_DIRS, SYSTEMD_SYSTEM_UNIT_NAMES, fileExists).map(
5931
+ ...resolveSystemUnitSources(SYSTEMD_SYSTEM_UNIT_DIRS, SYSTEMD_SYSTEM_UNIT_NAMES, exists).map(
5891
5932
  (source) => ({ ...source, userScoped: false })
5892
5933
  )
5893
5934
  ];
@@ -6286,7 +6327,7 @@ function readServerBlock(candidate) {
6286
6327
  ...typeof authToken === "string" && authToken.length > 0 ? { authToken } : {}
6287
6328
  };
6288
6329
  }
6289
- function daemonEndpointCandidates() {
6330
+ function daemonEndpointCandidates(unitExists) {
6290
6331
  const envHost = readCompatEnv("REMNIC_HOST", "ENGRAM_HOST");
6291
6332
  const envPort = coerceDaemonPort(readCompatEnv("REMNIC_PORT", "ENGRAM_PORT"));
6292
6333
  const candidates = [];
@@ -6334,7 +6375,7 @@ function daemonEndpointCandidates() {
6334
6375
  if (server !== void 0) add(server.host, server.port, candidate);
6335
6376
  };
6336
6377
  if (envConfigPath !== void 0) addConfigCandidate(envConfigPath);
6337
- for (const unit of readServiceEndpoints()) {
6378
+ for (const unit of readServiceEndpoints(unitExists)) {
6338
6379
  const server = unit.configPath === void 0 ? {} : readServerBlock(unit.configPath) ?? {};
6339
6380
  add(
6340
6381
  unit.host ?? server.host,
@@ -6363,7 +6404,7 @@ function readDaemonPort() {
6363
6404
  return readDaemonServerConfig().port ?? DEFAULT_PORT;
6364
6405
  }
6365
6406
  function detectDaemonBridgeMode(options) {
6366
- const endpoints = daemonEndpointCandidates();
6407
+ const endpoints = daemonEndpointCandidates(options.unitExists);
6367
6408
  const primary = endpoints[0] ?? { host: readDaemonHost(), port: readDaemonPort(), token: "" };
6368
6409
  const embedded = {
6369
6410
  mode: "embedded",
@@ -8403,9 +8444,11 @@ function buildTurnFingerprint(input) {
8403
8444
  import { planRecallMode } from "@remnic/core/intent";
8404
8445
  import {
8405
8446
  expandTildePath as expandTildePath4,
8447
+ isSupportPassportPrivateMemory as isSupportPassportPrivateMemory2,
8406
8448
  renderMemoryContextPrompt as renderSharedMemoryContextPrompt,
8407
8449
  resolveAgentAccessAuthToken,
8408
- resolvePrincipal
8450
+ resolvePrincipal,
8451
+ searchWithGenericExclusion
8409
8452
  } from "@remnic/core";
8410
8453
  import {
8411
8454
  normalizeHostEmbeddingVector,
@@ -10671,17 +10714,27 @@ Keep the reflection grounded in the evidence below.
10671
10714
  async search(query, opts) {
10672
10715
  const namespace = typeof orchestrator.resolveSelfNamespace === "function" ? orchestrator.resolveSelfNamespace(opts?.sessionKey) : void 0;
10673
10716
  const resolvedMode = opts?.qmdSearchModeOverride === "vsearch" ? "vector" : opts?.qmdSearchModeOverride === "query" ? "search" : opts?.qmdSearchModeOverride ?? "search";
10674
- const rawResults = await orchestrator.searchAcrossNamespaces({
10675
- query,
10676
- maxResults: opts?.maxResults,
10677
- namespaces: namespace ? [namespace] : void 0,
10678
- mode: resolvedMode
10717
+ const requestedMaxResults = typeof opts?.maxResults === "number" && Number.isFinite(opts.maxResults) ? Math.max(0, Math.floor(opts.maxResults)) : void 0;
10718
+ const minScore = typeof opts?.minScore === "number" && Number.isFinite(opts.minScore) ? opts.minScore : void 0;
10719
+ const visibleResults = await searchWithGenericExclusion({
10720
+ budget: requestedMaxResults ?? Number.MAX_SAFE_INTEGER,
10721
+ sendInitialLimit: requestedMaxResults !== void 0,
10722
+ search: (limit) => orchestrator.searchAcrossNamespaces({
10723
+ query,
10724
+ ...limit !== void 0 ? { maxResults: limit } : {},
10725
+ namespaces: namespace ? [namespace] : void 0,
10726
+ mode: resolvedMode
10727
+ }),
10728
+ filterPrivate: async (results) => {
10729
+ const visible = await orchestrator.filterPrivateSearchResults(
10730
+ results,
10731
+ namespace ? [namespace] : []
10732
+ );
10733
+ return minScore === void 0 ? visible : visible.filter((result) => result.score >= minScore);
10734
+ },
10735
+ isExcluded: (resultPath) => isMemoryArtifactPath(resultPath)
10679
10736
  });
10680
- return rawResults.filter((result) => {
10681
- const candidate = result;
10682
- const p = typeof candidate.path === "string" ? candidate.path : typeof candidate.id === "string" ? candidate.id : "";
10683
- return !isMemoryArtifactPath(p);
10684
- }).map((result, index) => {
10737
+ return visibleResults.map((result, index) => {
10685
10738
  const candidate = result;
10686
10739
  const rawPath = typeof candidate.path === "string" ? candidate.path : typeof candidate.id === "string" ? candidate.id : `memory-${index + 1}`;
10687
10740
  const absolutePath = readScope.absolutize(rawPath);
@@ -10697,13 +10750,20 @@ Keep the reflection grounded in the evidence below.
10697
10750
  source: isSessionsMemoryPath(normalizedPath) ? "sessions" : "memory",
10698
10751
  citation: normalizedPath
10699
10752
  };
10700
- }).filter(
10701
- (result) => typeof opts?.minScore === "number" && Number.isFinite(opts.minScore) ? result.score >= opts.minScore : true
10702
- );
10753
+ });
10703
10754
  },
10704
10755
  async readFile(params) {
10705
10756
  const requestedPath = readScope.normalizeWorkspacePath(params.relPath);
10706
10757
  const absolutePath = await readScope.resolveReadablePath(params.relPath);
10758
+ const visible = await orchestrator.filterPrivateSearchResults([{
10759
+ docid: absolutePath,
10760
+ path: absolutePath,
10761
+ snippet: "",
10762
+ score: 0
10763
+ }], [], true);
10764
+ if (visible.length === 0) {
10765
+ throw new Error(`memory read excluded (private record): ${params.relPath}`);
10766
+ }
10707
10767
  const text = await readTextFileLater(absolutePath);
10708
10768
  const allLines = text.split(/\r?\n/);
10709
10769
  const from = typeof params.from === "number" ? Math.max(1, Math.floor(params.from)) : 1;
@@ -11594,17 +11654,22 @@ Keep the reflection grounded in the evidence below.
11594
11654
  const agentSessionKey = typeof params === "object" ? params.agentSessionKey : void 0;
11595
11655
  const namespace = typeof orchestrator.resolveSelfNamespace === "function" ? orchestrator.resolveSelfNamespace(agentSessionKey) : void 0;
11596
11656
  try {
11597
- const rawResults = await orchestrator.searchAcrossNamespaces({
11598
- query,
11599
- maxResults,
11600
- namespaces: namespace ? [namespace] : void 0,
11601
- mode: "search"
11657
+ const visibleResults = await searchWithGenericExclusion({
11658
+ budget: maxResults,
11659
+ sendInitialLimit: true,
11660
+ search: (limit) => orchestrator.searchAcrossNamespaces({
11661
+ query,
11662
+ ...limit !== void 0 ? { maxResults: limit } : {},
11663
+ namespaces: namespace ? [namespace] : void 0,
11664
+ mode: "search"
11665
+ }),
11666
+ filterPrivate: (results) => orchestrator.filterPrivateSearchResults(
11667
+ results,
11668
+ namespace ? [namespace] : []
11669
+ ),
11670
+ isExcluded: (resultPath) => isMemoryArtifactPath(resultPath)
11602
11671
  });
11603
- return rawResults.filter((result) => {
11604
- const candidate = result;
11605
- const p = typeof candidate.path === "string" ? candidate.path : typeof candidate.id === "string" ? candidate.id : "";
11606
- return !isMemoryArtifactPath(p);
11607
- }).map((result, index) => {
11672
+ return visibleResults.map((result, index) => {
11608
11673
  const candidate = result;
11609
11674
  const lookupPath = typeof candidate.path === "string" ? candidate.path : typeof candidate.id === "string" ? candidate.id : `remnic-memory-${index + 1}`;
11610
11675
  const startLine = typeof candidate.startLine === "number" && Number.isFinite(candidate.startLine) ? Math.max(1, Math.floor(candidate.startLine)) : 1;
@@ -11642,7 +11707,7 @@ Keep the reflection grounded in the evidence below.
11642
11707
  const resolved = await readMemoryByLookup(lookup, agentSessionKey);
11643
11708
  if (!resolved) return null;
11644
11709
  const { memory, displayPath } = resolved;
11645
- if (isMemoryArtifactPath(displayPath) || isMemoryArtifactPath(memory.path)) {
11710
+ if (isMemoryArtifactPath(displayPath) || isMemoryArtifactPath(memory.path) || isSupportPassportPrivateMemory2(memory)) {
11646
11711
  return null;
11647
11712
  }
11648
11713
  const allLines = memory.content.split(/\r?\n/);