@securecoms/agent-bridge 0.8.0 → 0.9.0

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/bin.js CHANGED
@@ -27,6 +27,8 @@ function loadConfig(opts) {
27
27
  let memoryProvider;
28
28
  let memoryBaseDir;
29
29
  let memoryAgent;
30
+ let memoryWorkspaceDir;
31
+ let memoryFactsCharBudget;
30
32
  if (memProvRaw === "none") {
31
33
  memoryProvider = "none";
32
34
  } else if (memProvRaw === "hermes") {
@@ -40,6 +42,10 @@ function loadConfig(opts) {
40
42
  memoryBaseDir = typeof bd === "string" && bd ? bd : "~/.openclaw";
41
43
  const ag = oc?.agent;
42
44
  memoryAgent = typeof ag === "string" && ag ? ag : void 0;
45
+ const wd = oc?.workspace_dir;
46
+ memoryWorkspaceDir = typeof wd === "string" && wd ? wd : void 0;
47
+ const fb = oc?.facts_char_budget;
48
+ memoryFactsCharBudget = typeof fb === "number" && Number.isInteger(fb) && fb >= 0 ? fb : void 0;
43
49
  } else {
44
50
  memoryProvider = "securecoms";
45
51
  }
@@ -56,7 +62,9 @@ function loadConfig(opts) {
56
62
  rateLimitRefillPerMinute,
57
63
  memoryProvider,
58
64
  memoryBaseDir,
59
- memoryAgent
65
+ memoryAgent,
66
+ memoryWorkspaceDir,
67
+ memoryFactsCharBudget
60
68
  };
61
69
  }
62
70
  function arg(argv, flag) {
@@ -3947,7 +3955,7 @@ function loadPackageMeta(importMetaUrl) {
3947
3955
 
3948
3956
  // src/bridge-agent.ts
3949
3957
  import { promises as fsp } from "node:fs";
3950
- import { join as join7, dirname as dirname3 } from "node:path";
3958
+ import { join as join8, dirname as dirname3 } from "node:path";
3951
3959
 
3952
3960
  // src/latency.ts
3953
3961
  var DEFAULT_CAPACITY = 1024;
@@ -4460,29 +4468,153 @@ function readRecentTurns(baseDir, agent, sessionId, k) {
4460
4468
  return k > 0 ? turns.slice(-k) : [];
4461
4469
  }
4462
4470
 
4471
+ // src/memory/openclaw-workspace-facts.ts
4472
+ import { readdirSync, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
4473
+ import { join as join7 } from "node:path";
4474
+ var DEFAULT_FACTS_BUDGET = 8e3;
4475
+ var MEMORY_MD_CAP = 6e3;
4476
+ var MIN_FRAGMENT = 200;
4477
+ var MAX_SOURCE_BYTES = 1024 * 1024;
4478
+ var DAILY_RE = /^\d{4}-\d{2}-\d{2}\.md$/;
4479
+ function resolveWorkspaceDir(baseDir, agent, override) {
4480
+ if (override) return expandHome(override);
4481
+ const base = expandHome(baseDir);
4482
+ const isMain2 = agent === "" || agent === "main";
4483
+ try {
4484
+ const cfg = JSON.parse(readFileSync5(join7(base, "openclaw.json"), "utf8"));
4485
+ const agents = cfg?.agents;
4486
+ if (agents && typeof agents === "object") {
4487
+ const list = Array.isArray(agents.list) ? agents.list : [];
4488
+ const wanted = isMain2 ? "main" : agent;
4489
+ const entry = list.find((e) => e && typeof e === "object" && e.id === wanted);
4490
+ const ws = entry?.workspace;
4491
+ if (typeof ws === "string" && ws) return expandHome(ws);
4492
+ const def = agents.defaults?.workspace;
4493
+ if (typeof def === "string" && def) return expandHome(def);
4494
+ }
4495
+ } catch {
4496
+ }
4497
+ return isMain2 ? join7(base, "workspace") : join7(base, `workspace-${agent}`);
4498
+ }
4499
+ var TRUNC = "\u2026[truncated]";
4500
+ function headSlice(s, n) {
4501
+ if (s.length <= n) return { text: s, clipped: false };
4502
+ let out = s.slice(0, n);
4503
+ const last = out.charCodeAt(out.length - 1);
4504
+ if (last >= 55296 && last <= 56319) out = out.slice(0, -1);
4505
+ return { text: out, clipped: true };
4506
+ }
4507
+ function tailSlice(s, n) {
4508
+ if (s.length <= n) return { text: s, clipped: false };
4509
+ let out = s.slice(s.length - n);
4510
+ const first = out.charCodeAt(0);
4511
+ if (first >= 56320 && first <= 57343) out = out.slice(1);
4512
+ return { text: out, clipped: true };
4513
+ }
4514
+ function readBounded(path) {
4515
+ if (statSync2(path).size > MAX_SOURCE_BYTES) return { text: null, oversize: true };
4516
+ return { text: readFileSync5(path, "utf8"), oversize: false };
4517
+ }
4518
+ function readWorkspaceFacts(baseDir, agent, opts) {
4519
+ const raw = opts?.charBudget;
4520
+ const budget = typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? raw : DEFAULT_FACTS_BUDGET;
4521
+ if (budget === 0) return { facts: [], truncated: false, missing: false };
4522
+ const dir = resolveWorkspaceDir(baseDir, agent, opts?.workspaceDir);
4523
+ const facts = [];
4524
+ let truncated = false;
4525
+ let remaining = budget;
4526
+ try {
4527
+ const r = readBounded(join7(dir, "MEMORY.md"));
4528
+ if (r.oversize) truncated = true;
4529
+ else if (r.text && r.text.trim()) {
4530
+ const { text, clipped } = headSlice(r.text, Math.min(MEMORY_MD_CAP, budget));
4531
+ truncated ||= clipped;
4532
+ facts.push(`workspace MEMORY.md:
4533
+ ${text}${clipped ? `
4534
+ ${TRUNC}` : ""}`);
4535
+ remaining -= text.length;
4536
+ }
4537
+ } catch {
4538
+ }
4539
+ try {
4540
+ const dailies = readdirSync(join7(dir, "memory")).filter((f) => DAILY_RE.test(f)).sort().reverse().slice(0, 2);
4541
+ for (const f of dailies) {
4542
+ if (remaining < MIN_FRAGMENT) {
4543
+ truncated = true;
4544
+ break;
4545
+ }
4546
+ let r;
4547
+ try {
4548
+ r = readBounded(join7(dir, "memory", f));
4549
+ } catch {
4550
+ continue;
4551
+ }
4552
+ if (r.oversize) {
4553
+ truncated = true;
4554
+ continue;
4555
+ }
4556
+ if (!r.text || !r.text.trim()) continue;
4557
+ const { text, clipped } = tailSlice(r.text, remaining);
4558
+ truncated ||= clipped;
4559
+ facts.push(`workspace memory/${f} (daily):
4560
+ ${clipped ? `${TRUNC}
4561
+ ` : ""}${text}`);
4562
+ remaining -= text.length;
4563
+ }
4564
+ } catch {
4565
+ }
4566
+ return { facts, truncated, missing: facts.length === 0 };
4567
+ }
4568
+
4463
4569
  // src/memory/openclaw-provider.ts
4464
4570
  var DEFAULT_K2 = 200;
4465
4571
  var OpenClawMemoryProvider = class {
4466
- constructor(store, baseDir, agent) {
4572
+ // gauge: last successful returned total, including prefixes/markers
4573
+ constructor(store, baseDir, agent, factsOpts) {
4467
4574
  this.store = store;
4468
4575
  this.baseDir = baseDir;
4469
4576
  this.agent = agent;
4577
+ this.factsOpts = factsOpts;
4470
4578
  }
4471
4579
  noSession = 0;
4472
4580
  readFailed = 0;
4581
+ factsMissing = 0;
4582
+ // absence-shaped: resolved path missing or zero sources (per-call)
4583
+ factsReadFailed = 0;
4584
+ // anything THROWN out of the facts computation
4585
+ factsTruncated = 0;
4586
+ // budget clipped/dropped a source (incl. the 1MB skip)
4587
+ factsChars = 0;
4473
4588
  async record(input) {
4474
4589
  if (input.modality !== "voice") return { seq: 0, deduped: true };
4475
4590
  return this.store.recordMemory({ ...input, text: `[voice] ${input.text}` });
4476
4591
  }
4477
4592
  async context(conversationId, limit) {
4478
4593
  const k = limit ?? DEFAULT_K2;
4594
+ let wsFacts = [];
4595
+ try {
4596
+ const r = readWorkspaceFacts(this.baseDir, this.agent, {
4597
+ workspaceDir: this.factsOpts?.workspaceDir,
4598
+ charBudget: this.factsOpts?.factsCharBudget
4599
+ });
4600
+ wsFacts = r.facts;
4601
+ if (r.missing) this.factsMissing++;
4602
+ if (r.truncated) this.factsTruncated++;
4603
+ this.factsChars = r.facts.reduce((n, f) => n + f.length, 0);
4604
+ } catch {
4605
+ this.factsReadFailed++;
4606
+ }
4607
+ const withFacts = (res) => ({
4608
+ recent: res.recent,
4609
+ facts: [...wsFacts, ...res.facts]
4610
+ });
4479
4611
  const voice = await this.store.memoryContext(conversationId, k);
4480
4612
  let textTurns = [];
4481
4613
  try {
4482
4614
  const sid = resolveOwnerDmSession(this.baseDir, this.agent);
4483
4615
  if (!sid) {
4484
4616
  this.noSession++;
4485
- return voice;
4617
+ return withFacts(voice);
4486
4618
  }
4487
4619
  textTurns = readRecentTurns(this.baseDir, this.agent, sid, k).map((t) => ({
4488
4620
  seq: 0,
@@ -4492,7 +4624,7 @@ var OpenClawMemoryProvider = class {
4492
4624
  }));
4493
4625
  } catch {
4494
4626
  this.readFailed++;
4495
- return voice;
4627
+ return withFacts(voice);
4496
4628
  }
4497
4629
  const tagged = [
4498
4630
  ...textTurns.map((t, i) => ({ ...t, _src: 0, _i: i })),
@@ -4511,10 +4643,17 @@ var OpenClawMemoryProvider = class {
4511
4643
  text: t.text,
4512
4644
  ts: t.ts
4513
4645
  }));
4514
- return { recent, facts: voice.facts };
4646
+ return withFacts({ recent, facts: voice.facts });
4515
4647
  }
4516
4648
  stats() {
4517
- return { openclaw_no_session: this.noSession, openclaw_read_failed: this.readFailed };
4649
+ return {
4650
+ openclaw_no_session: this.noSession,
4651
+ openclaw_read_failed: this.readFailed,
4652
+ openclaw_facts_missing: this.factsMissing,
4653
+ openclaw_facts_read_failed: this.factsReadFailed,
4654
+ openclaw_facts_truncated: this.factsTruncated,
4655
+ openclaw_facts_chars: this.factsChars
4656
+ };
4518
4657
  }
4519
4658
  };
4520
4659
 
@@ -4538,10 +4677,10 @@ var NullMemory = class {
4538
4677
  return { recent: [], facts: [] };
4539
4678
  }
4540
4679
  };
4541
- function createMemoryProvider(provider, store, baseDir, agent) {
4680
+ function createMemoryProvider(provider, store, baseDir, agent, openclawFacts) {
4542
4681
  if (provider === "none") return new NullMemory();
4543
4682
  if (provider === "hermes") return new HermesMemoryProvider(baseDir ?? "~/.hermes");
4544
- if (provider === "openclaw") return new OpenClawMemoryProvider(store, baseDir ?? "~/.openclaw", agent ?? "");
4683
+ if (provider === "openclaw") return new OpenClawMemoryProvider(store, baseDir ?? "~/.openclaw", agent ?? "", openclawFacts);
4545
4684
  return new SecureComsLocalMemory(store);
4546
4685
  }
4547
4686
 
@@ -4649,7 +4788,10 @@ var BridgeAgent = class _BridgeAgent {
4649
4788
  identityId: cfg.identityId,
4650
4789
  cipherFor: () => new KeyedInboxCipher(deriveMlsStoreKey(seed))
4651
4790
  });
4652
- this.memory = createMemoryProvider(this.cfg.memoryProvider, this.store, this.cfg.memoryBaseDir, this.cfg.memoryAgent);
4791
+ this.memory = createMemoryProvider(this.cfg.memoryProvider, this.store, this.cfg.memoryBaseDir, this.cfg.memoryAgent, {
4792
+ workspaceDir: this.cfg.memoryWorkspaceDir,
4793
+ factsCharBudget: this.cfg.memoryFactsCharBudget
4794
+ });
4653
4795
  this.provider = new MlsGroupKeyProvider({
4654
4796
  store: this.store,
4655
4797
  backend: this.backend,
@@ -4729,7 +4871,7 @@ var BridgeAgent = class _BridgeAgent {
4729
4871
  const j = await res.json();
4730
4872
  return String(j.attachment_id);
4731
4873
  };
4732
- this.attachmentsDirImpl = deps.attachmentsDir ?? join7(dirname3(cfg.storePath), "attachments");
4874
+ this.attachmentsDirImpl = deps.attachmentsDir ?? join8(dirname3(cfg.storePath), "attachments");
4733
4875
  this.action = {
4734
4876
  begin: (channelId) => this.actionBegin(channelId),
4735
4877
  start: (opts) => this.actionStart(opts),
@@ -6257,11 +6399,11 @@ var BridgeAgent = class _BridgeAgent {
6257
6399
 
6258
6400
  // src/auth.ts
6259
6401
  import { randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
6260
- import { existsSync, readFileSync as readFileSync5, writeFileSync } from "node:fs";
6402
+ import { existsSync, readFileSync as readFileSync6, writeFileSync } from "node:fs";
6261
6403
  function resolveToken(opts) {
6262
6404
  if (opts.token) return opts.token;
6263
6405
  const f = opts.tokenFile;
6264
- if (f && existsSync(f)) return readFileSync5(f, "utf8").trim();
6406
+ if (f && existsSync(f)) return readFileSync6(f, "utf8").trim();
6265
6407
  const tok = randomBytes3(32).toString("base64url");
6266
6408
  if (f) writeFileSync(f, tok, { mode: 384 });
6267
6409
  return tok;
@@ -6832,8 +6974,8 @@ async function handleInbound(sock, agent, data, inflight) {
6832
6974
  }
6833
6975
 
6834
6976
  // src/bin.ts
6835
- import { readFileSync as readFileSync7, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, rmSync, existsSync as existsSync2, realpathSync, readdirSync, statSync as statSync2 } from "node:fs";
6836
- import { join as join11, dirname as dirname7, isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
6977
+ import { readFileSync as readFileSync8, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, rmSync, existsSync as existsSync2, realpathSync, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
6978
+ import { join as join12, dirname as dirname7, isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
6837
6979
  import { fileURLToPath as fileURLToPath2 } from "node:url";
6838
6980
  import { homedir as homedir2, userInfo } from "node:os";
6839
6981
  import { spawnSync } from "node:child_process";
@@ -7042,10 +7184,10 @@ function uninstallService(input, deps) {
7042
7184
  }
7043
7185
 
7044
7186
  // src/service/install-prep.ts
7045
- import { join as join9 } from "node:path";
7187
+ import { join as join10 } from "node:path";
7046
7188
 
7047
7189
  // src/service/wire.ts
7048
- import { join as join8, dirname as dirname5 } from "node:path";
7190
+ import { join as join9, dirname as dirname5 } from "node:path";
7049
7191
  import { fileURLToPath } from "node:url";
7050
7192
 
7051
7193
  // src/service/hermes-config.ts
@@ -7211,7 +7353,7 @@ function connectorTargetDir(home, harness) {
7211
7353
  }
7212
7354
  function connectorsSrcDir(importMetaUrl, harness) {
7213
7355
  const pkgRoot = dirname5(dirname5(fileURLToPath(importMetaUrl)));
7214
- return join8(pkgRoot, "connectors", harness);
7356
+ return join9(pkgRoot, "connectors", harness);
7215
7357
  }
7216
7358
  function hermesConfigPath(home) {
7217
7359
  return `${home}/.hermes/config.yaml`;
@@ -7430,10 +7572,10 @@ function assertReadableCredential(absPath, deps) {
7430
7572
  return { deviceId: json2.device_id, identityId: json2.identity_id, issuedAt };
7431
7573
  }
7432
7574
  function durableDir(home, slug) {
7433
- return join9(home, `securecoms-agent-${slug}`);
7575
+ return join10(home, `securecoms-agent-${slug}`);
7434
7576
  }
7435
7577
  function durableCredentialPath(home, slug) {
7436
- return join9(durableDir(home, slug), `${slug}.json`);
7578
+ return join10(durableDir(home, slug), `${slug}.json`);
7437
7579
  }
7438
7580
  function takeCustody(args2, deps) {
7439
7581
  const dir = durableDir(args2.home, args2.slug);
@@ -7480,7 +7622,7 @@ function readSiblingDefs(dir, prefix, deps) {
7480
7622
  for (const n of names) {
7481
7623
  if (!n.startsWith(prefix)) continue;
7482
7624
  try {
7483
- out.push(deps.readFile(join9(dir, n)));
7625
+ out.push(deps.readFile(join10(dir, n)));
7484
7626
  } catch {
7485
7627
  }
7486
7628
  }
@@ -7676,29 +7818,29 @@ function renderStatusTable(rows) {
7676
7818
  import {
7677
7819
  chmodSync,
7678
7820
  mkdirSync,
7679
- readFileSync as readFileSync6,
7821
+ readFileSync as readFileSync7,
7680
7822
  renameSync,
7681
7823
  unlinkSync,
7682
7824
  writeFileSync as writeFileSync2
7683
7825
  } from "node:fs";
7684
7826
  import { randomUUID } from "node:crypto";
7685
- import { join as join10 } from "node:path";
7827
+ import { join as join11 } from "node:path";
7686
7828
  var REAL_FS = {
7687
7829
  mkdir: (p, mode) => mkdirSync(p, { recursive: true, mode }),
7688
7830
  chmod: (p, mode) => chmodSync(p, mode),
7689
7831
  writeFile: (p, data, mode) => writeFileSync2(p, data, { mode }),
7690
7832
  rename: (a, b) => renameSync(a, b),
7691
- readFile: (p) => readFileSync6(p, "utf8"),
7833
+ readFile: (p) => readFileSync7(p, "utf8"),
7692
7834
  unlink: (p) => unlinkSync(p)
7693
7835
  };
7694
7836
  function securecomsDir(home) {
7695
- return join10(home, ".securecoms");
7837
+ return join11(home, ".securecoms");
7696
7838
  }
7697
7839
  function connectionsDir(home) {
7698
- return join10(securecomsDir(home), "connections");
7840
+ return join11(securecomsDir(home), "connections");
7699
7841
  }
7700
7842
  function connectionFilePath(home, identityId) {
7701
- return join10(connectionsDir(home), `${identityId}.json`);
7843
+ return join11(connectionsDir(home), `${identityId}.json`);
7702
7844
  }
7703
7845
  function newInstanceId() {
7704
7846
  return randomUUID();
@@ -7813,7 +7955,7 @@ function realResolveDeps() {
7813
7955
  }
7814
7956
  function realPrepDeps() {
7815
7957
  return {
7816
- readFile: (p) => readFileSync7(p, "utf8"),
7958
+ readFile: (p) => readFileSync8(p, "utf8"),
7817
7959
  writeFileMode: (p, data, mode) => writeFileSync3(p, data, { mode }),
7818
7960
  mkdirp: (p, mode) => {
7819
7961
  mkdirSync2(p, { recursive: true, mode: mode ?? 493 });
@@ -7822,7 +7964,7 @@ function realPrepDeps() {
7822
7964
  realpath: (p) => realpathSync(p),
7823
7965
  listDir: (p) => {
7824
7966
  try {
7825
- return readdirSync(p);
7967
+ return readdirSync2(p);
7826
7968
  } catch {
7827
7969
  return [];
7828
7970
  }
@@ -7864,12 +8006,12 @@ function realReadFleet() {
7864
8006
  home: homedir2(),
7865
8007
  listDir: (p) => {
7866
8008
  try {
7867
- return readdirSync(p);
8009
+ return readdirSync2(p);
7868
8010
  } catch {
7869
8011
  return [];
7870
8012
  }
7871
8013
  },
7872
- readFile: (p) => readFileSync7(p, "utf8")
8014
+ readFile: (p) => readFileSync8(p, "utf8")
7873
8015
  });
7874
8016
  }
7875
8017
  function runStatus() {
@@ -7892,43 +8034,43 @@ function runStatus() {
7892
8034
  function realCopyConnector(srcDir, dstDir, harness) {
7893
8035
  const allowedExt = CONNECTOR_FILE_EXTENSIONS[harness];
7894
8036
  mkdirSync2(dstDir, { recursive: true });
7895
- for (const name of readdirSync(srcDir)) {
7896
- const srcPath = join11(srcDir, name);
7897
- if (statSync2(srcPath).isDirectory()) {
8037
+ for (const name of readdirSync2(srcDir)) {
8038
+ const srcPath = join12(srcDir, name);
8039
+ if (statSync3(srcPath).isDirectory()) {
7898
8040
  if (CONNECTOR_SKIP_DIRS.has(name)) continue;
7899
- realCopyConnector(srcPath, join11(dstDir, name), harness);
8041
+ realCopyConnector(srcPath, join12(dstDir, name), harness);
7900
8042
  continue;
7901
8043
  }
7902
8044
  if (name.includes(".test.")) continue;
7903
8045
  if (!allowedExt.some((ext) => name.endsWith(ext))) continue;
7904
- writeFileSync3(join11(dstDir, name), readFileSync7(srcPath));
8046
+ writeFileSync3(join12(dstDir, name), readFileSync8(srcPath));
7905
8047
  }
7906
8048
  }
7907
8049
  function realWriteBinding(dstDir, identityId) {
7908
8050
  mkdirSync2(dstDir, { recursive: true });
7909
- writeFileSync3(join11(dstDir, "securecoms.binding.json"), JSON.stringify({ identity_id: identityId }) + "\n", { mode: 384 });
8051
+ writeFileSync3(join12(dstDir, "securecoms.binding.json"), JSON.stringify({ identity_id: identityId }) + "\n", { mode: 384 });
7910
8052
  }
7911
8053
  function realReadBinding(dstDir) {
7912
8054
  try {
7913
- const parsed = JSON.parse(readFileSync7(join11(dstDir, "securecoms.binding.json"), "utf8"));
8055
+ const parsed = JSON.parse(readFileSync8(join12(dstDir, "securecoms.binding.json"), "utf8"));
7914
8056
  return parsed.identity_id ?? null;
7915
8057
  } catch {
7916
8058
  return null;
7917
8059
  }
7918
8060
  }
7919
8061
  function realRemoveBinding(dstDir) {
7920
- rmSync(join11(dstDir, "securecoms.binding.json"), { force: true });
8062
+ rmSync(join12(dstDir, "securecoms.binding.json"), { force: true });
7921
8063
  }
7922
8064
  function realStatDir(p) {
7923
8065
  try {
7924
- return statSync2(p).isDirectory();
8066
+ return statSync3(p).isDirectory();
7925
8067
  } catch {
7926
8068
  return false;
7927
8069
  }
7928
8070
  }
7929
8071
  function realReadHermesConfig(p) {
7930
8072
  try {
7931
- return readFileSync7(p, "utf8");
8073
+ return readFileSync8(p, "utf8");
7932
8074
  } catch {
7933
8075
  return null;
7934
8076
  }
@@ -8087,11 +8229,11 @@ async function main() {
8087
8229
  `);
8088
8230
  process.exit(1);
8089
8231
  }
8090
- const tokenFile = daemon.tokenFile ?? join11(dirname7(credentialPath), "bridge-token");
8232
+ const tokenFile = daemon.tokenFile ?? join12(dirname7(credentialPath), "bridge-token");
8091
8233
  const token = resolveToken({ tokenFile, token: daemon.token });
8092
8234
  const agent = new BridgeAgent(cfg);
8093
8235
  await agent.start();
8094
- const tls = daemon.tls ? { cert: readFileSync7(daemon.tlsCert, "utf8"), key: readFileSync7(daemon.tlsKey, "utf8") } : void 0;
8236
+ const tls = daemon.tls ? { cert: readFileSync8(daemon.tlsCert, "utf8"), key: readFileSync8(daemon.tlsKey, "utf8") } : void 0;
8095
8237
  const { server, closeAllSseStreams } = createHttpServer(agent, { token, allowOrigins: daemon.allowOrigins, tls, websocket: true });
8096
8238
  const agentWs = attachAgentWebSocket(server, agent, { token, allowOrigins: daemon.allowOrigins });
8097
8239
  let down = false;
@@ -842,6 +842,10 @@ export declare class BridgeAgent {
842
842
  hermes_write_failed?: number;
843
843
  openclaw_no_session?: number;
844
844
  openclaw_read_failed?: number;
845
+ openclaw_facts_missing?: number;
846
+ openclaw_facts_read_failed?: number;
847
+ openclaw_facts_truncated?: number;
848
+ openclaw_facts_chars?: number;
845
849
  };
846
850
  /**
847
851
  * Loopback observability snapshot served at GET /v1/metrics.
package/dist/config.d.ts CHANGED
@@ -23,6 +23,10 @@ export interface BridgeConfig {
23
23
  memoryBaseDir?: string;
24
24
  /** For memoryProvider="openclaw": the OpenClaw agent dir slug, e.g. "cortina" (→ <base_dir>/agents/<agent>/). */
25
25
  memoryAgent?: string;
26
+ /** For memoryProvider="openclaw": explicit workspace dir override; wins over openclaw.json (spec D4 rung 1). */
27
+ memoryWorkspaceDir?: string;
28
+ /** For memoryProvider="openclaw": total facts cap in UTF-16 code units. 0 = facts kill switch (preserved via ?? downstream, never ||). Absent/junk → provider default 8000. */
29
+ memoryFactsCharBudget?: number;
26
30
  }
27
31
  export declare const REQUIRED: readonly ["api_key", "identity_id", "device_id", "signing_private_key", "enclave_id", "api_base"];
28
32
  export declare function loadConfig(opts: {
@@ -34,7 +34,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
34
34
  message_id: z.ZodOptional<z.ZodString>;
35
35
  idempotency_key: z.ZodOptional<z.ZodString>;
36
36
  }, "strip", z.ZodTypeAny, {
37
- role: "peer" | "agent";
37
+ role: "agent" | "peer";
38
38
  text: string;
39
39
  conversation_id: string;
40
40
  modality: "text" | "voice";
@@ -42,7 +42,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
42
42
  idempotency_key?: string | undefined;
43
43
  peer_id?: string | undefined;
44
44
  }, {
45
- role: "peer" | "agent";
45
+ role: "agent" | "peer";
46
46
  text: string;
47
47
  conversation_id: string;
48
48
  modality: "text" | "voice";
@@ -50,7 +50,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
50
50
  idempotency_key?: string | undefined;
51
51
  peer_id?: string | undefined;
52
52
  }>, {
53
- role: "peer" | "agent";
53
+ role: "agent" | "peer";
54
54
  text: string;
55
55
  conversation_id: string;
56
56
  modality: "text" | "voice";
@@ -58,7 +58,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
58
58
  idempotency_key?: string | undefined;
59
59
  peer_id?: string | undefined;
60
60
  }, {
61
- role: "peer" | "agent";
61
+ role: "agent" | "peer";
62
62
  text: string;
63
63
  conversation_id: string;
64
64
  modality: "text" | "voice";
package/dist/index.js CHANGED
@@ -3811,7 +3811,7 @@ function loadPackageMeta(importMetaUrl) {
3811
3811
 
3812
3812
  // src/bridge-agent.ts
3813
3813
  import { promises as fsp } from "node:fs";
3814
- import { join as join5, dirname } from "node:path";
3814
+ import { join as join6, dirname } from "node:path";
3815
3815
 
3816
3816
  // src/latency.ts
3817
3817
  var DEFAULT_CAPACITY = 1024;
@@ -4324,29 +4324,153 @@ function readRecentTurns(baseDir, agent, sessionId, k) {
4324
4324
  return k > 0 ? turns.slice(-k) : [];
4325
4325
  }
4326
4326
 
4327
+ // src/memory/openclaw-workspace-facts.ts
4328
+ import { readdirSync, readFileSync as readFileSync4, statSync } from "node:fs";
4329
+ import { join as join5 } from "node:path";
4330
+ var DEFAULT_FACTS_BUDGET = 8e3;
4331
+ var MEMORY_MD_CAP = 6e3;
4332
+ var MIN_FRAGMENT = 200;
4333
+ var MAX_SOURCE_BYTES = 1024 * 1024;
4334
+ var DAILY_RE = /^\d{4}-\d{2}-\d{2}\.md$/;
4335
+ function resolveWorkspaceDir(baseDir, agent, override) {
4336
+ if (override) return expandHome(override);
4337
+ const base = expandHome(baseDir);
4338
+ const isMain = agent === "" || agent === "main";
4339
+ try {
4340
+ const cfg = JSON.parse(readFileSync4(join5(base, "openclaw.json"), "utf8"));
4341
+ const agents = cfg?.agents;
4342
+ if (agents && typeof agents === "object") {
4343
+ const list = Array.isArray(agents.list) ? agents.list : [];
4344
+ const wanted = isMain ? "main" : agent;
4345
+ const entry = list.find((e) => e && typeof e === "object" && e.id === wanted);
4346
+ const ws = entry?.workspace;
4347
+ if (typeof ws === "string" && ws) return expandHome(ws);
4348
+ const def = agents.defaults?.workspace;
4349
+ if (typeof def === "string" && def) return expandHome(def);
4350
+ }
4351
+ } catch {
4352
+ }
4353
+ return isMain ? join5(base, "workspace") : join5(base, `workspace-${agent}`);
4354
+ }
4355
+ var TRUNC = "\u2026[truncated]";
4356
+ function headSlice(s, n) {
4357
+ if (s.length <= n) return { text: s, clipped: false };
4358
+ let out = s.slice(0, n);
4359
+ const last = out.charCodeAt(out.length - 1);
4360
+ if (last >= 55296 && last <= 56319) out = out.slice(0, -1);
4361
+ return { text: out, clipped: true };
4362
+ }
4363
+ function tailSlice(s, n) {
4364
+ if (s.length <= n) return { text: s, clipped: false };
4365
+ let out = s.slice(s.length - n);
4366
+ const first = out.charCodeAt(0);
4367
+ if (first >= 56320 && first <= 57343) out = out.slice(1);
4368
+ return { text: out, clipped: true };
4369
+ }
4370
+ function readBounded(path) {
4371
+ if (statSync(path).size > MAX_SOURCE_BYTES) return { text: null, oversize: true };
4372
+ return { text: readFileSync4(path, "utf8"), oversize: false };
4373
+ }
4374
+ function readWorkspaceFacts(baseDir, agent, opts) {
4375
+ const raw = opts?.charBudget;
4376
+ const budget = typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? raw : DEFAULT_FACTS_BUDGET;
4377
+ if (budget === 0) return { facts: [], truncated: false, missing: false };
4378
+ const dir = resolveWorkspaceDir(baseDir, agent, opts?.workspaceDir);
4379
+ const facts = [];
4380
+ let truncated = false;
4381
+ let remaining = budget;
4382
+ try {
4383
+ const r = readBounded(join5(dir, "MEMORY.md"));
4384
+ if (r.oversize) truncated = true;
4385
+ else if (r.text && r.text.trim()) {
4386
+ const { text, clipped } = headSlice(r.text, Math.min(MEMORY_MD_CAP, budget));
4387
+ truncated ||= clipped;
4388
+ facts.push(`workspace MEMORY.md:
4389
+ ${text}${clipped ? `
4390
+ ${TRUNC}` : ""}`);
4391
+ remaining -= text.length;
4392
+ }
4393
+ } catch {
4394
+ }
4395
+ try {
4396
+ const dailies = readdirSync(join5(dir, "memory")).filter((f) => DAILY_RE.test(f)).sort().reverse().slice(0, 2);
4397
+ for (const f of dailies) {
4398
+ if (remaining < MIN_FRAGMENT) {
4399
+ truncated = true;
4400
+ break;
4401
+ }
4402
+ let r;
4403
+ try {
4404
+ r = readBounded(join5(dir, "memory", f));
4405
+ } catch {
4406
+ continue;
4407
+ }
4408
+ if (r.oversize) {
4409
+ truncated = true;
4410
+ continue;
4411
+ }
4412
+ if (!r.text || !r.text.trim()) continue;
4413
+ const { text, clipped } = tailSlice(r.text, remaining);
4414
+ truncated ||= clipped;
4415
+ facts.push(`workspace memory/${f} (daily):
4416
+ ${clipped ? `${TRUNC}
4417
+ ` : ""}${text}`);
4418
+ remaining -= text.length;
4419
+ }
4420
+ } catch {
4421
+ }
4422
+ return { facts, truncated, missing: facts.length === 0 };
4423
+ }
4424
+
4327
4425
  // src/memory/openclaw-provider.ts
4328
4426
  var DEFAULT_K2 = 200;
4329
4427
  var OpenClawMemoryProvider = class {
4330
- constructor(store, baseDir, agent) {
4428
+ // gauge: last successful returned total, including prefixes/markers
4429
+ constructor(store, baseDir, agent, factsOpts) {
4331
4430
  this.store = store;
4332
4431
  this.baseDir = baseDir;
4333
4432
  this.agent = agent;
4433
+ this.factsOpts = factsOpts;
4334
4434
  }
4335
4435
  noSession = 0;
4336
4436
  readFailed = 0;
4437
+ factsMissing = 0;
4438
+ // absence-shaped: resolved path missing or zero sources (per-call)
4439
+ factsReadFailed = 0;
4440
+ // anything THROWN out of the facts computation
4441
+ factsTruncated = 0;
4442
+ // budget clipped/dropped a source (incl. the 1MB skip)
4443
+ factsChars = 0;
4337
4444
  async record(input) {
4338
4445
  if (input.modality !== "voice") return { seq: 0, deduped: true };
4339
4446
  return this.store.recordMemory({ ...input, text: `[voice] ${input.text}` });
4340
4447
  }
4341
4448
  async context(conversationId, limit) {
4342
4449
  const k = limit ?? DEFAULT_K2;
4450
+ let wsFacts = [];
4451
+ try {
4452
+ const r = readWorkspaceFacts(this.baseDir, this.agent, {
4453
+ workspaceDir: this.factsOpts?.workspaceDir,
4454
+ charBudget: this.factsOpts?.factsCharBudget
4455
+ });
4456
+ wsFacts = r.facts;
4457
+ if (r.missing) this.factsMissing++;
4458
+ if (r.truncated) this.factsTruncated++;
4459
+ this.factsChars = r.facts.reduce((n, f) => n + f.length, 0);
4460
+ } catch {
4461
+ this.factsReadFailed++;
4462
+ }
4463
+ const withFacts = (res) => ({
4464
+ recent: res.recent,
4465
+ facts: [...wsFacts, ...res.facts]
4466
+ });
4343
4467
  const voice = await this.store.memoryContext(conversationId, k);
4344
4468
  let textTurns = [];
4345
4469
  try {
4346
4470
  const sid = resolveOwnerDmSession(this.baseDir, this.agent);
4347
4471
  if (!sid) {
4348
4472
  this.noSession++;
4349
- return voice;
4473
+ return withFacts(voice);
4350
4474
  }
4351
4475
  textTurns = readRecentTurns(this.baseDir, this.agent, sid, k).map((t) => ({
4352
4476
  seq: 0,
@@ -4356,7 +4480,7 @@ var OpenClawMemoryProvider = class {
4356
4480
  }));
4357
4481
  } catch {
4358
4482
  this.readFailed++;
4359
- return voice;
4483
+ return withFacts(voice);
4360
4484
  }
4361
4485
  const tagged = [
4362
4486
  ...textTurns.map((t, i) => ({ ...t, _src: 0, _i: i })),
@@ -4375,10 +4499,17 @@ var OpenClawMemoryProvider = class {
4375
4499
  text: t.text,
4376
4500
  ts: t.ts
4377
4501
  }));
4378
- return { recent, facts: voice.facts };
4502
+ return withFacts({ recent, facts: voice.facts });
4379
4503
  }
4380
4504
  stats() {
4381
- return { openclaw_no_session: this.noSession, openclaw_read_failed: this.readFailed };
4505
+ return {
4506
+ openclaw_no_session: this.noSession,
4507
+ openclaw_read_failed: this.readFailed,
4508
+ openclaw_facts_missing: this.factsMissing,
4509
+ openclaw_facts_read_failed: this.factsReadFailed,
4510
+ openclaw_facts_truncated: this.factsTruncated,
4511
+ openclaw_facts_chars: this.factsChars
4512
+ };
4382
4513
  }
4383
4514
  };
4384
4515
 
@@ -4402,10 +4533,10 @@ var NullMemory = class {
4402
4533
  return { recent: [], facts: [] };
4403
4534
  }
4404
4535
  };
4405
- function createMemoryProvider(provider, store, baseDir, agent) {
4536
+ function createMemoryProvider(provider, store, baseDir, agent, openclawFacts) {
4406
4537
  if (provider === "none") return new NullMemory();
4407
4538
  if (provider === "hermes") return new HermesMemoryProvider(baseDir ?? "~/.hermes");
4408
- if (provider === "openclaw") return new OpenClawMemoryProvider(store, baseDir ?? "~/.openclaw", agent ?? "");
4539
+ if (provider === "openclaw") return new OpenClawMemoryProvider(store, baseDir ?? "~/.openclaw", agent ?? "", openclawFacts);
4409
4540
  return new SecureComsLocalMemory(store);
4410
4541
  }
4411
4542
 
@@ -4513,7 +4644,10 @@ var BridgeAgent = class _BridgeAgent {
4513
4644
  identityId: cfg.identityId,
4514
4645
  cipherFor: () => new KeyedInboxCipher(deriveMlsStoreKey(seed))
4515
4646
  });
4516
- this.memory = createMemoryProvider(this.cfg.memoryProvider, this.store, this.cfg.memoryBaseDir, this.cfg.memoryAgent);
4647
+ this.memory = createMemoryProvider(this.cfg.memoryProvider, this.store, this.cfg.memoryBaseDir, this.cfg.memoryAgent, {
4648
+ workspaceDir: this.cfg.memoryWorkspaceDir,
4649
+ factsCharBudget: this.cfg.memoryFactsCharBudget
4650
+ });
4517
4651
  this.provider = new MlsGroupKeyProvider({
4518
4652
  store: this.store,
4519
4653
  backend: this.backend,
@@ -4593,7 +4727,7 @@ var BridgeAgent = class _BridgeAgent {
4593
4727
  const j = await res.json();
4594
4728
  return String(j.attachment_id);
4595
4729
  };
4596
- this.attachmentsDirImpl = deps.attachmentsDir ?? join5(dirname(cfg.storePath), "attachments");
4730
+ this.attachmentsDirImpl = deps.attachmentsDir ?? join6(dirname(cfg.storePath), "attachments");
4597
4731
  this.action = {
4598
4732
  begin: (channelId) => this.actionBegin(channelId),
4599
4733
  start: (opts) => this.actionStart(opts),
@@ -6120,13 +6254,13 @@ var BridgeAgent = class _BridgeAgent {
6120
6254
  };
6121
6255
 
6122
6256
  // src/config.ts
6123
- import { readFileSync as readFileSync4, statSync } from "node:fs";
6124
- import { dirname as dirname2, join as join6 } from "node:path";
6257
+ import { readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
6258
+ import { dirname as dirname2, join as join7 } from "node:path";
6125
6259
  var REQUIRED = ["api_key", "identity_id", "device_id", "signing_private_key", "enclave_id", "api_base"];
6126
6260
  function loadConfig(opts) {
6127
- const raw = readFileSync4(opts.credentialPath, "utf8");
6261
+ const raw = readFileSync5(opts.credentialPath, "utf8");
6128
6262
  try {
6129
- const mode = statSync(opts.credentialPath).mode & 511;
6263
+ const mode = statSync2(opts.credentialPath).mode & 511;
6130
6264
  if (mode & 63) process.stderr.write(`[bridge] WARNING: credential file ${opts.credentialPath} permission ${mode.toString(8)} is not 0600 \u2014 tighten it (chmod 600).
6131
6265
  `);
6132
6266
  } catch {
@@ -6138,7 +6272,7 @@ function loadConfig(opts) {
6138
6272
  throw new Error("credential file is not valid JSON");
6139
6273
  }
6140
6274
  for (const k of REQUIRED) if (typeof json2[k] !== "string" || !json2[k]) throw new Error(`credential file missing required field: ${k}`);
6141
- const storePath = opts.storePath ?? join6(dirname2(opts.credentialPath), "bridge-state.db");
6275
+ const storePath = opts.storePath ?? join7(dirname2(opts.credentialPath), "bridge-state.db");
6142
6276
  const agentName = typeof json2.agent_name === "string" && json2.agent_name ? json2.agent_name : typeof json2.display_name === "string" && json2.display_name ? json2.display_name : void 0;
6143
6277
  const rateLimitCapacity = typeof json2.rate_limit_capacity === "number" ? json2.rate_limit_capacity : 20;
6144
6278
  const rateLimitRefillPerMinute = typeof json2.rate_limit_refill_per_minute === "number" ? json2.rate_limit_refill_per_minute : 20;
@@ -6146,6 +6280,8 @@ function loadConfig(opts) {
6146
6280
  let memoryProvider;
6147
6281
  let memoryBaseDir;
6148
6282
  let memoryAgent;
6283
+ let memoryWorkspaceDir;
6284
+ let memoryFactsCharBudget;
6149
6285
  if (memProvRaw === "none") {
6150
6286
  memoryProvider = "none";
6151
6287
  } else if (memProvRaw === "hermes") {
@@ -6159,6 +6295,10 @@ function loadConfig(opts) {
6159
6295
  memoryBaseDir = typeof bd === "string" && bd ? bd : "~/.openclaw";
6160
6296
  const ag = oc?.agent;
6161
6297
  memoryAgent = typeof ag === "string" && ag ? ag : void 0;
6298
+ const wd = oc?.workspace_dir;
6299
+ memoryWorkspaceDir = typeof wd === "string" && wd ? wd : void 0;
6300
+ const fb = oc?.facts_char_budget;
6301
+ memoryFactsCharBudget = typeof fb === "number" && Number.isInteger(fb) && fb >= 0 ? fb : void 0;
6162
6302
  } else {
6163
6303
  memoryProvider = "securecoms";
6164
6304
  }
@@ -6175,7 +6315,9 @@ function loadConfig(opts) {
6175
6315
  rateLimitRefillPerMinute,
6176
6316
  memoryProvider,
6177
6317
  memoryBaseDir,
6178
- memoryAgent
6318
+ memoryAgent,
6319
+ memoryWorkspaceDir,
6320
+ memoryFactsCharBudget
6179
6321
  };
6180
6322
  }
6181
6323
  function arg(argv, flag) {
@@ -6219,11 +6361,11 @@ import { z } from "zod";
6219
6361
 
6220
6362
  // src/auth.ts
6221
6363
  import { randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
6222
- import { existsSync, readFileSync as readFileSync5, writeFileSync } from "node:fs";
6364
+ import { existsSync, readFileSync as readFileSync6, writeFileSync } from "node:fs";
6223
6365
  function resolveToken(opts) {
6224
6366
  if (opts.token) return opts.token;
6225
6367
  const f = opts.tokenFile;
6226
- if (f && existsSync(f)) return readFileSync5(f, "utf8").trim();
6368
+ if (f && existsSync(f)) return readFileSync6(f, "utf8").trim();
6227
6369
  const tok = randomBytes3(32).toString("base64url");
6228
6370
  if (f) writeFileSync(f, tok, { mode: 384 });
6229
6371
  return tok;
@@ -1,5 +1,9 @@
1
1
  import type { MemoryProvider } from "./provider.js";
2
2
  import type { SqliteMlsStateStore, MemoryRecordInput, MemoryContextResult } from "@agentvault/connect-mls-store";
3
+ export interface OpenClawFactsOptions {
4
+ workspaceDir?: string;
5
+ factsCharBudget?: number;
6
+ }
3
7
  /**
4
8
  * MemoryProvider for an OpenClaw-hosted agent (Cortina). context() merges
5
9
  * OpenClaw's own text history (read-only, plain session .jsonl) with the
@@ -12,9 +16,14 @@ export declare class OpenClawMemoryProvider implements MemoryProvider {
12
16
  private readonly store;
13
17
  private readonly baseDir;
14
18
  private readonly agent;
19
+ private readonly factsOpts?;
15
20
  private noSession;
16
21
  private readFailed;
17
- constructor(store: SqliteMlsStateStore, baseDir: string, agent: string);
22
+ private factsMissing;
23
+ private factsReadFailed;
24
+ private factsTruncated;
25
+ private factsChars;
26
+ constructor(store: SqliteMlsStateStore, baseDir: string, agent: string, factsOpts?: OpenClawFactsOptions | undefined);
18
27
  record(input: MemoryRecordInput): Promise<{
19
28
  seq: number;
20
29
  deduped: boolean;
@@ -0,0 +1,38 @@
1
+ /** Spec D2 constants — pinned so tests are deterministic. "Chars" = UTF-16 code units. */
2
+ export declare const DEFAULT_FACTS_BUDGET = 8000;
3
+ export declare const MEMORY_MD_CAP = 6000;
4
+ export declare const MIN_FRAGMENT = 200;
5
+ export declare const MAX_SOURCE_BYTES: number;
6
+ /**
7
+ * Resolve the agent's OpenClaw workspace dir (spec D4). Ladder, first hit wins:
8
+ * 1. explicit override (credential workspace_dir) — operator beats everything;
9
+ * 2. openclaw.json, resolved the way OpenClaw itself would:
10
+ * 2a. agents.list entry with id===agent and a NON-EMPTY string workspace (verbatim,
11
+ * never case-transformed — the live config declares "workspace-cortina" for an
12
+ * on-disk "workspace-Cortina" and works only because APFS is case-insensitive);
13
+ * 2b. else agents.defaults.workspace when it is a non-empty string (covers main,
14
+ * whose live entry has the workspace key ABSENT, and named agents w/o one);
15
+ * 3. derivation, LAST resort (openclaw.json missing/malformed/silent):
16
+ * main/"" → <base>/workspace, else <base>/workspace-<agent> verbatim.
17
+ * Empty agent is treated as "main" throughout (the factory passes agent ?? "").
18
+ * Total: always returns a path; existence is checked at read time, fail-safe.
19
+ */
20
+ export declare function resolveWorkspaceDir(baseDir: string, agent: string, override?: string): string;
21
+ export interface WorkspaceFactsResult {
22
+ /** 0..3 provenance-prefixed facts: MEMORY.md first, then dailies newest-first. */
23
+ facts: string[];
24
+ /** True when the budget clipped or dropped any source (includes the >1MB skip). */
25
+ truncated: boolean;
26
+ /** True when the resolved workspace yielded zero usable sources. False on budget-0 kill switch. */
27
+ missing: boolean;
28
+ }
29
+ /**
30
+ * Read the workspace facts (spec D1-D3). READ-ONLY, total: never throws for any
31
+ * filesystem state — absence degrades to fewer/zero facts. Only MEMORY.md and
32
+ * memory/\d{4}-\d{2}-\d{2}\.md under the resolved dir are ever opened.
33
+ * Budget accounting is content-only; prefixes and markers are exempt (audit M2).
34
+ */
35
+ export declare function readWorkspaceFacts(baseDir: string, agent: string, opts?: {
36
+ workspaceDir?: string;
37
+ charBudget?: number;
38
+ }): WorkspaceFactsResult;
@@ -1,4 +1,5 @@
1
1
  import type { SqliteMlsStateStore, MemoryRecordInput, MemoryContextResult } from "@agentvault/connect-mls-store";
2
+ import type { OpenClawFactsOptions } from "./openclaw-provider.js";
2
3
  export interface MemoryProvider {
3
4
  record(input: MemoryRecordInput): Promise<{
4
5
  seq: number;
@@ -26,4 +27,4 @@ export declare class NullMemory implements MemoryProvider {
26
27
  }>;
27
28
  context(): Promise<MemoryContextResult>;
28
29
  }
29
- export declare function createMemoryProvider(provider: "securecoms" | "none" | "hermes" | "openclaw", store: SqliteMlsStateStore, baseDir?: string, agent?: string): MemoryProvider;
30
+ export declare function createMemoryProvider(provider: "securecoms" | "none" | "hermes" | "openclaw", store: SqliteMlsStateStore, baseDir?: string, agent?: string, openclawFacts?: OpenClawFactsOptions): MemoryProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@securecoms/agent-bridge",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",