@remnic/plugin-openclaw 9.65.1 → 9.65.3

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
@@ -3180,7 +3180,7 @@ __reExport(access_http_exports, access_http_star);
3180
3180
  import * as access_http_star from "@remnic/core/access-http";
3181
3181
 
3182
3182
  // ../../src/index.ts
3183
- import path10 from "path";
3183
+ import path11 from "path";
3184
3184
  import os from "os";
3185
3185
 
3186
3186
  // ../../src/opik-exporter.ts
@@ -4443,8 +4443,8 @@ function parseProcessedMarkerChunks(rawChunks) {
4443
4443
  }
4444
4444
  async function readProcessedMarker(markerPath) {
4445
4445
  try {
4446
- const stat2 = await lstat2(markerPath);
4447
- if (stat2.isSymbolicLink() || !stat2.isFile()) return void 0;
4446
+ const stat3 = await lstat2(markerPath);
4447
+ if (stat3.isSymbolicLink() || !stat3.isFile()) return void 0;
4448
4448
  return parseProcessedMarker(await readFile(markerPath, "utf8"));
4449
4449
  } catch (error) {
4450
4450
  if (error?.code === "ENOENT") return void 0;
@@ -4501,8 +4501,8 @@ function isMeaningfulFlushPlanContent(content) {
4501
4501
  }
4502
4502
  async function isSafeFlushPlanAppendTarget(flushPlanPath) {
4503
4503
  try {
4504
- const stat2 = await lstat2(flushPlanPath);
4505
- return !stat2.isSymbolicLink() && stat2.isFile();
4504
+ const stat3 = await lstat2(flushPlanPath);
4505
+ return !stat3.isSymbolicLink() && stat3.isFile();
4506
4506
  } catch (error) {
4507
4507
  if (error?.code === "ENOENT") return true;
4508
4508
  throw error;
@@ -4603,21 +4603,21 @@ async function validateFlushPlanLocation(params) {
4603
4603
  let currentPath = workspaceRoot;
4604
4604
  for (const segment of parentSegments) {
4605
4605
  currentPath = path2.join(currentPath, segment);
4606
- let stat2;
4606
+ let stat3;
4607
4607
  try {
4608
- stat2 = await lstat2(currentPath);
4608
+ stat3 = await lstat2(currentPath);
4609
4609
  } catch (error) {
4610
4610
  if (error?.code === "ENOENT") break;
4611
4611
  throw error;
4612
4612
  }
4613
- if (stat2.isSymbolicLink()) {
4613
+ if (stat3.isSymbolicLink()) {
4614
4614
  return {
4615
4615
  status: "skipped",
4616
4616
  path: params.flushPlanPath,
4617
4617
  reason: "flush plan parent path contains a symlink"
4618
4618
  };
4619
4619
  }
4620
- if (!stat2.isDirectory()) {
4620
+ if (!stat3.isDirectory()) {
4621
4621
  return {
4622
4622
  status: "skipped",
4623
4623
  path: params.flushPlanPath,
@@ -4663,14 +4663,14 @@ async function recoverInterruptedCleanupSnapshots(params) {
4663
4663
  if (error?.code !== "ENOENT") throw error;
4664
4664
  }
4665
4665
  for (const cleanupPath of cleanupPaths) {
4666
- let stat2;
4666
+ let stat3;
4667
4667
  try {
4668
- stat2 = await lstat2(cleanupPath);
4668
+ stat3 = await lstat2(cleanupPath);
4669
4669
  } catch (error) {
4670
4670
  if (error?.code === "ENOENT") continue;
4671
4671
  throw error;
4672
4672
  }
4673
- if (stat2.isSymbolicLink() || !stat2.isFile()) {
4673
+ if (stat3.isSymbolicLink() || !stat3.isFile()) {
4674
4674
  params.logger?.warn(
4675
4675
  `OpenClaw flush-plan cleanup recovery skipped unsafe snapshot ${path2.basename(cleanupPath)}`
4676
4676
  );
@@ -5002,23 +5002,23 @@ function buildFlushPlanImportTurns(params) {
5002
5002
  );
5003
5003
  }
5004
5004
  async function readFlushPlanSnapshot(flushPlanPath) {
5005
- let stat2;
5005
+ let stat3;
5006
5006
  try {
5007
- stat2 = await lstat2(flushPlanPath);
5007
+ stat3 = await lstat2(flushPlanPath);
5008
5008
  } catch (error) {
5009
5009
  if (error?.code === "ENOENT") {
5010
5010
  return { status: "missing", path: flushPlanPath };
5011
5011
  }
5012
5012
  throw error;
5013
5013
  }
5014
- if (stat2.isSymbolicLink()) {
5014
+ if (stat3.isSymbolicLink()) {
5015
5015
  return {
5016
5016
  status: "skipped",
5017
5017
  path: flushPlanPath,
5018
5018
  reason: "flush plan path is a symlink"
5019
5019
  };
5020
5020
  }
5021
- if (!stat2.isFile()) {
5021
+ if (!stat3.isFile()) {
5022
5022
  return {
5023
5023
  status: "skipped",
5024
5024
  path: flushPlanPath,
@@ -5088,8 +5088,8 @@ async function removeProcessedFlushPlanContent(params) {
5088
5088
  const processedBytes = Buffer.byteLength(params.processedContent, "utf8");
5089
5089
  let cleanupPath;
5090
5090
  try {
5091
- const stat2 = await lstat2(params.flushPlanPath);
5092
- if (stat2.isSymbolicLink()) {
5091
+ const stat3 = await lstat2(params.flushPlanPath);
5092
+ if (stat3.isSymbolicLink()) {
5093
5093
  return {
5094
5094
  status: "processed_cleanup_deferred",
5095
5095
  path: params.flushPlanPath,
@@ -5097,7 +5097,7 @@ async function removeProcessedFlushPlanContent(params) {
5097
5097
  reason: "flush plan path became a symlink before cleanup"
5098
5098
  };
5099
5099
  }
5100
- if (!stat2.isFile()) {
5100
+ if (!stat3.isFile()) {
5101
5101
  return {
5102
5102
  status: "processed_cleanup_deferred",
5103
5103
  path: params.flushPlanPath,
@@ -5395,7 +5395,7 @@ async function processOpenClawFlushPlanFile(params) {
5395
5395
  }
5396
5396
 
5397
5397
  // src/delegate-runtime.ts
5398
- import path8 from "path";
5398
+ import path9 from "path";
5399
5399
  import {
5400
5400
  renderMemoryContextPrompt
5401
5401
  } from "@remnic/core";
@@ -6902,12 +6902,93 @@ function daemonTargetFor(bridge) {
6902
6902
  }
6903
6903
 
6904
6904
  // src/delegate-flush-plan-ingest.ts
6905
- import { constants } from "fs";
6906
- import { lstat as lstat3, open, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
6907
- import path7 from "path";
6905
+ import { constants as constants2 } from "fs";
6906
+ import { lstat as lstat4, open as open2, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
6907
+ import path8 from "path";
6908
6908
  import { log as log4 } from "@remnic/core/logger";
6909
6909
  import { withHeldFileLock } from "@remnic/core/utils/serialize-mutations";
6910
6910
 
6911
+ // src/delegate-flush-plan-directory.ts
6912
+ import { constants } from "fs";
6913
+ import { lstat as lstat3, open, stat as stat2 } from "fs/promises";
6914
+ import path7 from "path";
6915
+ function buildSnapshotPaths(planPath) {
6916
+ return {
6917
+ plan: planPath,
6918
+ inflight: `${planPath}.inflight`,
6919
+ rotating: `${planPath}.rotating`,
6920
+ oversized: `${planPath}.oversized`,
6921
+ lock: `${planPath}.lock`,
6922
+ oversizedLabel: `${planPath}.oversized`
6923
+ };
6924
+ }
6925
+ function descriptorDirectoryRoot(platform = process.platform) {
6926
+ if (platform === "linux") return "/proc/self/fd";
6927
+ if (platform === "darwin" || platform === "freebsd" || platform === "openbsd") return "/dev/fd";
6928
+ return void 0;
6929
+ }
6930
+ async function pinSnapshotDirectory(paths, options = {}) {
6931
+ const descriptorRoot = options.descriptorRoot ?? descriptorDirectoryRoot();
6932
+ if (descriptorRoot === void 0) return { kind: "unsupported" };
6933
+ const directory = path7.dirname(paths.plan);
6934
+ let before;
6935
+ try {
6936
+ before = await lstat3(directory);
6937
+ } catch {
6938
+ return { kind: "unstable" };
6939
+ }
6940
+ if (before.isSymbolicLink() || !before.isDirectory()) return { kind: "unstable" };
6941
+ let handle;
6942
+ try {
6943
+ handle = await open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
6944
+ } catch {
6945
+ return { kind: "unstable" };
6946
+ }
6947
+ try {
6948
+ const opened = await handle.stat();
6949
+ const after = await lstat3(directory);
6950
+ if (!opened.isDirectory() || after.isSymbolicLink() || !after.isDirectory() || !isSameInode(before, opened) || !isSameInode(after, opened)) {
6951
+ await closeQuietly(handle);
6952
+ return { kind: "unstable" };
6953
+ }
6954
+ const pinnedDirectory = path7.join(descriptorRoot, String(handle.fd));
6955
+ let anchored;
6956
+ try {
6957
+ anchored = await stat2(pinnedDirectory);
6958
+ } catch {
6959
+ await closeQuietly(handle);
6960
+ return { kind: "unsupported" };
6961
+ }
6962
+ if (!anchored.isDirectory() || !isSameInode(anchored, opened)) {
6963
+ await closeQuietly(handle);
6964
+ return { kind: "unsupported" };
6965
+ }
6966
+ return {
6967
+ kind: "pinned",
6968
+ paths: {
6969
+ ...paths,
6970
+ plan: anchoredChild(pinnedDirectory, paths.plan),
6971
+ inflight: anchoredChild(pinnedDirectory, paths.inflight),
6972
+ rotating: anchoredChild(pinnedDirectory, paths.rotating),
6973
+ oversized: anchoredChild(pinnedDirectory, paths.oversized)
6974
+ },
6975
+ close: () => closeQuietly(handle)
6976
+ };
6977
+ } catch (err) {
6978
+ await closeQuietly(handle);
6979
+ throw err;
6980
+ }
6981
+ }
6982
+ function anchoredChild(pinnedDirectory, realPath) {
6983
+ return path7.join(pinnedDirectory, path7.basename(realPath));
6984
+ }
6985
+ function isSameInode(left, right) {
6986
+ return left.dev === right.dev && left.ino === right.ino;
6987
+ }
6988
+ async function closeQuietly(handle) {
6989
+ await handle.close().catch(() => void 0);
6990
+ }
6991
+
6911
6992
  // src/memory-flush-plan.ts
6912
6993
  var DEFAULT_MAX_TURN_CHARS = 8e3;
6913
6994
  var MIN_MAX_TURN_CHARS = 1e3;
@@ -6993,17 +7074,11 @@ var MAX_RECLAIM_PASSES = 4;
6993
7074
  async function ingestFlushPlanNotes(options) {
6994
7075
  if (options.workspaceDir === void 0) return;
6995
7076
  const workspaceDir = options.workspaceDir;
6996
- const planPath = path7.join(
7077
+ const planPath = path8.join(
6997
7078
  workspaceDir,
6998
7079
  ...buildMemoryFlushPlan({ serviceId: options.serviceId }).relativePath.split("/")
6999
7080
  );
7000
- const paths = {
7001
- plan: planPath,
7002
- inflight: `${planPath}.inflight`,
7003
- rotating: `${planPath}.rotating`,
7004
- oversized: `${planPath}.oversized`,
7005
- lock: `${planPath}.lock`
7006
- };
7081
+ const paths = buildSnapshotPaths(planPath);
7007
7082
  for (const candidate of [paths.plan, paths.inflight, paths.rotating, paths.oversized]) {
7008
7083
  if (await isLinkFreeUnder(workspaceDir, candidate)) continue;
7009
7084
  log4.warn(
@@ -7029,7 +7104,18 @@ async function ingestFlushPlanNotes(options) {
7029
7104
  );
7030
7105
  return;
7031
7106
  }
7032
- await ingestUnderLock(options, paths, lock);
7107
+ const pinned = await pinSnapshotDirectory(paths);
7108
+ if (pinned.kind === "unstable") {
7109
+ log4.warn(
7110
+ `[${options.serviceId}] flush-plan ingestion skipped: the snapshot directory changed identity while it was being opened`
7111
+ );
7112
+ return;
7113
+ }
7114
+ try {
7115
+ await ingestUnderLock(options, pinned.kind === "pinned" ? pinned.paths : paths, lock);
7116
+ } finally {
7117
+ if (pinned.kind === "pinned") await pinned.close();
7118
+ }
7033
7119
  }
7034
7120
  );
7035
7121
  }
@@ -7189,9 +7275,9 @@ async function quarantineOversizedLine(paths, pending, serviceId) {
7189
7275
  const breakAt = pending.indexOf("\n");
7190
7276
  const line = breakAt === -1 ? pending : pending.slice(0, breakAt + 1);
7191
7277
  const rest = breakAt === -1 ? "" : pending.slice(breakAt + 1);
7192
- const handle = await open(
7278
+ const handle = await open2(
7193
7279
  paths.oversized,
7194
- constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND | constants.O_NOFOLLOW,
7280
+ constants2.O_WRONLY | constants2.O_CREAT | constants2.O_APPEND | constants2.O_NOFOLLOW,
7195
7281
  384
7196
7282
  );
7197
7283
  try {
@@ -7201,14 +7287,14 @@ async function quarantineOversizedLine(paths, pending, serviceId) {
7201
7287
  await handle.close();
7202
7288
  }
7203
7289
  log4.warn(
7204
- `[${serviceId}] a flush-plan note exceeds the daemon's body limit; moved it to ${paths.oversized} so the remaining notes can drain`
7290
+ `[${serviceId}] a flush-plan note exceeds the daemon's body limit; moved it to ${paths.oversizedLabel} so the remaining notes can drain`
7205
7291
  );
7206
7292
  return rest;
7207
7293
  }
7208
7294
  async function readIfPresent(filePath) {
7209
7295
  let handle;
7210
7296
  try {
7211
- handle = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
7297
+ handle = await open2(filePath, constants2.O_RDONLY | constants2.O_NOFOLLOW);
7212
7298
  return await handle.readFile("utf8");
7213
7299
  } catch (err) {
7214
7300
  if (err?.code === "ENOENT") return void 0;
@@ -7249,18 +7335,18 @@ function chunkOnLineBoundaries(text, limit) {
7249
7335
  return chunks;
7250
7336
  }
7251
7337
  async function isLinkFreeUnder(root, target) {
7252
- const relative = path7.relative(root, target);
7253
- if (relative.startsWith("..") || path7.isAbsolute(relative)) return false;
7338
+ const relative = path8.relative(root, target);
7339
+ if (relative.startsWith("..") || path8.isAbsolute(relative)) return false;
7254
7340
  let current = root;
7255
7341
  try {
7256
- if ((await lstat3(current)).isSymbolicLink()) return false;
7342
+ if ((await lstat4(current)).isSymbolicLink()) return false;
7257
7343
  } catch {
7258
7344
  return true;
7259
7345
  }
7260
- for (const segment of relative.split(path7.sep)) {
7261
- current = path7.join(current, segment);
7346
+ for (const segment of relative.split(path8.sep)) {
7347
+ current = path8.join(current, segment);
7262
7348
  try {
7263
- if ((await lstat3(current)).isSymbolicLink()) return false;
7349
+ if ((await lstat4(current)).isSymbolicLink()) return false;
7264
7350
  } catch {
7265
7351
  return true;
7266
7352
  }
@@ -8521,7 +8607,7 @@ var queueDelegateNamespaceMigration = (bindingPath, sessionKey, operation) => {
8521
8607
  return run;
8522
8608
  };
8523
8609
  function createDelegateNamespaceBindingStore(memoryDir, serviceId, isLegacyAdapterActive) {
8524
- const bindingPath = (pluginId) => path8.join(memoryDir, "state", "plugins", pluginId, "session-namespace-bindings.json");
8610
+ const bindingPath = (pluginId) => path9.join(memoryDir, "state", "plugins", pluginId, "session-namespace-bindings.json");
8525
8611
  const primaryPath = bindingPath(serviceId);
8526
8612
  const primary = createFileSessionNamespaceBindingStore(primaryPath);
8527
8613
  if (serviceId !== REMNIC_OPENCLAW_PLUGIN_ID) return primary;
@@ -8695,9 +8781,9 @@ function maybeRegisterDelegateRuntime(api, options, deps = { checkHealth: checkD
8695
8781
  delegateBoundApis.add(api);
8696
8782
  }
8697
8783
  const toggleStore = options.sessionTogglesEnabled ? createFileToggleStore(
8698
- path8.join(options.memoryDir, "state", "plugins", options.serviceId, "session-toggles.json"),
8784
+ path9.join(options.memoryDir, "state", "plugins", options.serviceId, "session-toggles.json"),
8699
8785
  {
8700
- secondaryReadOnlyPath: options.respectBundledActiveMemoryToggle ? path8.join(options.memoryDir, "state", "plugins", "active-memory", "session-toggles.json") : void 0
8786
+ secondaryReadOnlyPath: options.respectBundledActiveMemoryToggle ? path9.join(options.memoryDir, "state", "plugins", "active-memory", "session-toggles.json") : void 0
8701
8787
  }
8702
8788
  ) : null;
8703
8789
  const target = daemonTargetFor(bridge);
@@ -8870,23 +8956,23 @@ __export(resolve_provider_secret_exports, {
8870
8956
  findGatewayRuntimeModules: () => findGatewayRuntimeModules
8871
8957
  });
8872
8958
  __reExport(resolve_provider_secret_exports, resolve_provider_secret_star);
8873
- import path9 from "path";
8959
+ import path10 from "path";
8874
8960
  import * as resolve_provider_secret_star from "@remnic/core/resolve-provider-secret";
8875
8961
  async function findGatewayRuntimeModules(filePrefix) {
8876
8962
  const { existsSync, readFileSync, readdirSync, realpathSync: realpathSync2 } = await import("fs");
8877
8963
  const { createRequire: createRequire2 } = await import("module");
8878
8964
  const candidates = [];
8879
8965
  const isWithinRoot = (root, candidate) => {
8880
- const relative = path9.relative(root, candidate);
8881
- return relative.length === 0 || !relative.startsWith("..") && !path9.isAbsolute(relative);
8966
+ const relative = path10.relative(root, candidate);
8967
+ return relative.length === 0 || !relative.startsWith("..") && !path10.isAbsolute(relative);
8882
8968
  };
8883
8969
  let packageRoot;
8884
8970
  try {
8885
8971
  const req = createRequire2(import.meta.url);
8886
8972
  const openclawEntrypoint = realpathSync2(req.resolve("openclaw"));
8887
- let currentDir = path9.dirname(openclawEntrypoint);
8973
+ let currentDir = path10.dirname(openclawEntrypoint);
8888
8974
  while (true) {
8889
- const packageJsonPath = path9.join(currentDir, "package.json");
8975
+ const packageJsonPath = path10.join(currentDir, "package.json");
8890
8976
  if (existsSync(packageJsonPath)) {
8891
8977
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
8892
8978
  if (packageJson.name !== "openclaw") {
@@ -8895,7 +8981,7 @@ async function findGatewayRuntimeModules(filePrefix) {
8895
8981
  packageRoot = realpathSync2(currentDir);
8896
8982
  break;
8897
8983
  }
8898
- const parent = path9.dirname(currentDir);
8984
+ const parent = path10.dirname(currentDir);
8899
8985
  if (parent === currentDir) {
8900
8986
  return [];
8901
8987
  }
@@ -8905,14 +8991,14 @@ async function findGatewayRuntimeModules(filePrefix) {
8905
8991
  return [];
8906
8992
  }
8907
8993
  try {
8908
- const distDir = realpathSync2(path9.join(packageRoot, "dist"));
8994
+ const distDir = realpathSync2(path10.join(packageRoot, "dist"));
8909
8995
  if (!isWithinRoot(packageRoot, distDir)) {
8910
8996
  return [];
8911
8997
  }
8912
8998
  const files = readdirSync(distDir);
8913
8999
  for (const f of files) {
8914
9000
  if (f.startsWith(filePrefix) && f.endsWith(".js")) {
8915
- const candidate = realpathSync2(path9.join(distDir, f));
9001
+ const candidate = realpathSync2(path10.join(distDir, f));
8916
9002
  if (isWithinRoot(packageRoot, candidate) && isWithinRoot(distDir, candidate)) {
8917
9003
  candidates.push(candidate);
8918
9004
  }
@@ -9255,7 +9341,7 @@ function resolveOpenClawConfigFilePath() {
9255
9341
  if (explicitConfigPath && explicitConfigPath.length > 0) {
9256
9342
  return expandTildePath4(explicitConfigPath);
9257
9343
  }
9258
- return path10.join(resolveHomeDir3(), ".openclaw", "openclaw.json");
9344
+ return path11.join(resolveHomeDir3(), ".openclaw", "openclaw.json");
9259
9345
  }
9260
9346
  function coerceRawConfigBoolean(value) {
9261
9347
  if (typeof value === "boolean") return value;
@@ -9302,7 +9388,7 @@ function readPluginHooksPolicy(apiConfig, pluginId) {
9302
9388
  }
9303
9389
  async function maybeRegisterLiveConnectorCron(orchestrator) {
9304
9390
  if (!hasEnabledLiveConnectorConfig(orchestrator.config.connectors)) return;
9305
- const jobsPath = path10.join(resolveHomeDir3(), ".openclaw", "cron", "jobs.json");
9391
+ const jobsPath = path11.join(resolveHomeDir3(), ".openclaw", "cron", "jobs.json");
9306
9392
  try {
9307
9393
  if (!fileExistsNow(jobsPath)) {
9308
9394
  logger_exports.log.debug("live connectors cron: jobs.json not found, skipping auto-register");
@@ -9871,9 +9957,9 @@ var pluginDefinition = {
9871
9957
  emitLegacyTools: cfg.emitLegacyTools
9872
9958
  });
9873
9959
  globalThis[keys.ACCESS_HTTP_SERVER] = accessHttpServer;
9874
- const pluginStateDir = path10.join(cfg.memoryDir, "state", "plugins", serviceId);
9875
- const togglePrimaryPath = path10.join(pluginStateDir, "session-toggles.json");
9876
- const toggleSecondaryPath = cfg.respectBundledActiveMemoryToggle ? path10.join(cfg.memoryDir, "state", "plugins", "active-memory", "session-toggles.json") : void 0;
9960
+ const pluginStateDir = path11.join(cfg.memoryDir, "state", "plugins", serviceId);
9961
+ const togglePrimaryPath = path11.join(pluginStateDir, "session-toggles.json");
9962
+ const toggleSecondaryPath = cfg.respectBundledActiveMemoryToggle ? path11.join(cfg.memoryDir, "state", "plugins", "active-memory", "session-toggles.json") : void 0;
9877
9963
  const sessionToggleStore = createFileToggleStore2(togglePrimaryPath, {
9878
9964
  secondaryReadOnlyPath: toggleSecondaryPath
9879
9965
  });
@@ -9895,11 +9981,11 @@ var pluginDefinition = {
9895
9981
  }
9896
9982
  function resolveDreamJournalPath(runtimeWorkspaceDir) {
9897
9983
  const workspaceRoot = resolveWorkspaceRoot(runtimeWorkspaceDir);
9898
- return path10.isAbsolute(cfg.dreaming.journalPath) ? cfg.dreaming.journalPath : path10.join(workspaceRoot, cfg.dreaming.journalPath);
9984
+ return path11.isAbsolute(cfg.dreaming.journalPath) ? cfg.dreaming.journalPath : path11.join(workspaceRoot, cfg.dreaming.journalPath);
9899
9985
  }
9900
9986
  function resolveHeartbeatJournalPath(runtimeWorkspaceDir) {
9901
9987
  const workspaceRoot = resolveWorkspaceRoot(runtimeWorkspaceDir);
9902
- return path10.isAbsolute(cfg.heartbeat.journalPath) ? cfg.heartbeat.journalPath : path10.join(workspaceRoot, cfg.heartbeat.journalPath);
9988
+ return path11.isAbsolute(cfg.heartbeat.journalPath) ? cfg.heartbeat.journalPath : path11.join(workspaceRoot, cfg.heartbeat.journalPath);
9903
9989
  }
9904
9990
  const existingFlushPlanProcessingChains = globalThis[keys.FLUSH_PLAN_PROCESSING_CHAINS];
9905
9991
  const flushPlanProcessingChains = existingFlushPlanProcessingChains instanceof Map ? existingFlushPlanProcessingChains : /* @__PURE__ */ new Map();
@@ -10176,7 +10262,7 @@ Keep the reflection grounded in the evidence below.
10176
10262
  timeoutMs: cfg.activeRecallTimeoutMs,
10177
10263
  cacheTtlMs: cfg.activeRecallCacheTtlMs,
10178
10264
  persistTranscripts: cfg.activeRecallPersistTranscripts,
10179
- transcriptDir: path10.isAbsolute(cfg.activeRecallTranscriptDir) ? cfg.activeRecallTranscriptDir : path10.join(pluginStateDir, cfg.activeRecallTranscriptDir),
10265
+ transcriptDir: path11.isAbsolute(cfg.activeRecallTranscriptDir) ? cfg.activeRecallTranscriptDir : path11.join(pluginStateDir, cfg.activeRecallTranscriptDir),
10180
10266
  entityGraphDepth: cfg.activeRecallEntityGraphDepth,
10181
10267
  includeCausalTrajectories: cfg.activeRecallIncludeCausalTrajectories,
10182
10268
  includeDaySummary: cfg.activeRecallIncludeDaySummary,
@@ -11725,7 +11811,7 @@ Keep the reflection grounded in the evidence below.
11725
11811
  `session reset via API for ${sessionKey}, new sessionId=${result.sessionId}`
11726
11812
  );
11727
11813
  const safeSessionKey = sanitizeSessionKeyForFilename(sessionKey);
11728
- const signalPath = path10.join(
11814
+ const signalPath = path11.join(
11729
11815
  workspaceDir,
11730
11816
  `.compaction-reset-signal-${safeSessionKey}`
11731
11817
  );
@@ -11944,7 +12030,7 @@ Keep the reflection grounded in the evidence below.
11944
12030
  }
11945
12031
  async function ensureHourlySummaryCron(api2) {
11946
12032
  const jobId = "engram-hourly-summary";
11947
- const cronFilePath = path10.join(
12033
+ const cronFilePath = path11.join(
11948
12034
  os.homedir(),
11949
12035
  ".openclaw",
11950
12036
  "cron",
@@ -12003,32 +12089,32 @@ Keep the reflection grounded in the evidence below.
12003
12089
  };
12004
12090
  const normalizeCorpusPath = (value) => value.trim().replace(/\\/g, "/").replace(/^\.\//, "");
12005
12091
  const pathIsInside = (root, candidate) => {
12006
- const relative = path10.relative(root, candidate);
12007
- return relative === "" || !relative.startsWith("..") && !path10.isAbsolute(relative);
12092
+ const relative = path11.relative(root, candidate);
12093
+ return relative === "" || !relative.startsWith("..") && !path11.isAbsolute(relative);
12008
12094
  };
12009
12095
  const corpusPathCandidates = (rawPath, storageDir) => {
12010
12096
  const candidates = /* @__PURE__ */ new Set();
12011
12097
  const trimmed = rawPath.trim();
12012
12098
  if (!trimmed) return [];
12013
12099
  candidates.add(normalizeCorpusPath(trimmed));
12014
- if (path10.isAbsolute(trimmed)) {
12015
- const absolutePath = path10.resolve(trimmed);
12016
- const absoluteStorageDir = path10.resolve(storageDir);
12100
+ if (path11.isAbsolute(trimmed)) {
12101
+ const absolutePath = path11.resolve(trimmed);
12102
+ const absoluteStorageDir = path11.resolve(storageDir);
12017
12103
  if (pathIsInside(absoluteStorageDir, absolutePath)) {
12018
- candidates.add(normalizeCorpusPath(path10.relative(absoluteStorageDir, absolutePath)));
12104
+ candidates.add(normalizeCorpusPath(path11.relative(absoluteStorageDir, absolutePath)));
12019
12105
  }
12020
12106
  }
12021
- candidates.add(path10.basename(trimmed));
12107
+ candidates.add(path11.basename(trimmed));
12022
12108
  return [...candidates].filter((candidate) => candidate.length > 0);
12023
12109
  };
12024
12110
  const displayCorpusPath = (rawPath, storageDir) => {
12025
12111
  const trimmed = rawPath.trim();
12026
12112
  if (!trimmed) return "";
12027
- if (path10.isAbsolute(trimmed)) {
12028
- const absolutePath = path10.resolve(trimmed);
12029
- const absoluteStorageDir = path10.resolve(storageDir);
12113
+ if (path11.isAbsolute(trimmed)) {
12114
+ const absolutePath = path11.resolve(trimmed);
12115
+ const absoluteStorageDir = path11.resolve(storageDir);
12030
12116
  if (pathIsInside(absoluteStorageDir, absolutePath)) {
12031
- return normalizeCorpusPath(path10.relative(absoluteStorageDir, absolutePath));
12117
+ return normalizeCorpusPath(path11.relative(absoluteStorageDir, absolutePath));
12032
12118
  }
12033
12119
  }
12034
12120
  return normalizeCorpusPath(trimmed);
@@ -12542,9 +12628,9 @@ function truncateMetadataValue(value, maxChars) {
12542
12628
  return value.length <= maxChars ? value : value.slice(0, maxChars);
12543
12629
  }
12544
12630
  async function resolveFlushPlanProcessingChainKey(workspaceRoot) {
12545
- const lexicalRoot = path10.resolve(workspaceRoot);
12631
+ const lexicalRoot = path11.resolve(workspaceRoot);
12546
12632
  try {
12547
- return path10.resolve(await realPathLater(lexicalRoot));
12633
+ return path11.resolve(await realPathLater(lexicalRoot));
12548
12634
  } catch {
12549
12635
  return lexicalRoot;
12550
12636
  }