@damn-dev/cli 0.9.3 → 0.9.6

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.
@@ -495,6 +495,117 @@ var require_dist = __commonJS({
495
495
  }
496
496
  });
497
497
 
498
+ // apps/backend/dist/lib/memoryGuard.js
499
+ var require_memoryGuard = __commonJS({
500
+ "apps/backend/dist/lib/memoryGuard.js"(exports2) {
501
+ "use strict";
502
+ var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
503
+ return mod && mod.__esModule ? mod : { "default": mod };
504
+ };
505
+ Object.defineProperty(exports2, "__esModule", { value: true });
506
+ exports2.isTestModeEnabled = isTestModeEnabled;
507
+ exports2.readTestMode = readTestMode;
508
+ exports2.setTestMode = setTestMode;
509
+ exports2.isLikelyTestRejection = isLikelyTestRejection;
510
+ exports2.isDuplicateReflexion = isDuplicateReflexion;
511
+ var promises_12 = __importDefault2(require("fs/promises"));
512
+ var path_12 = __importDefault2(require("path"));
513
+ var os_12 = __importDefault2(require("os"));
514
+ var TEST_MODE_FILE = path_12.default.join(os_12.default.homedir(), ".damn-dev", "test-mode.json");
515
+ var CACHE_TTL_MS = 1e4;
516
+ var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
517
+ var cached = null;
518
+ async function isTestModeEnabled() {
519
+ const now = Date.now();
520
+ if (cached && now - cached.cachedAt < CACHE_TTL_MS)
521
+ return cached.enabled;
522
+ try {
523
+ const raw = await promises_12.default.readFile(TEST_MODE_FILE, "utf-8");
524
+ const parsed = JSON.parse(raw);
525
+ const enabled = parsed?.enabled === true;
526
+ cached = { enabled, cachedAt: now };
527
+ return enabled;
528
+ } catch {
529
+ cached = { enabled: false, cachedAt: now };
530
+ return false;
531
+ }
532
+ }
533
+ async function readTestMode() {
534
+ try {
535
+ const raw = await promises_12.default.readFile(TEST_MODE_FILE, "utf-8");
536
+ const parsed = JSON.parse(raw);
537
+ return {
538
+ enabled: parsed?.enabled === true,
539
+ setAt: typeof parsed?.setAt === "number" ? parsed.setAt : null
540
+ };
541
+ } catch {
542
+ return { enabled: false, setAt: null };
543
+ }
544
+ }
545
+ async function setTestMode(enabled) {
546
+ const dir = path_12.default.dirname(TEST_MODE_FILE);
547
+ await promises_12.default.mkdir(dir, { recursive: true });
548
+ const content = JSON.stringify({ enabled, setAt: Date.now() }, null, 2);
549
+ const tmp = `${TEST_MODE_FILE}.tmp.${Date.now()}`;
550
+ await promises_12.default.writeFile(tmp, content, "utf-8");
551
+ await promises_12.default.rename(tmp, TEST_MODE_FILE);
552
+ cached = { enabled, cachedAt: Date.now() };
553
+ }
554
+ var TEST_REASON_EXACT = /^(test|testing|tests|probe|probing|try|trying|tryout|check|checking|just checking|just trying|no need|nope|skip|n\/a|no|nothing|idk|dummy|fake)$/i;
555
+ var TEST_REASON_CONTAINS = /\b(testing|probing|sanity check|dry run|just trying|just testing|for testing|for test|test run|trying it|poke)\b/i;
556
+ function isLikelyTestRejection(reason) {
557
+ if (!reason)
558
+ return false;
559
+ const trimmed = reason.trim();
560
+ if (!trimmed)
561
+ return false;
562
+ if (TEST_REASON_EXACT.test(trimmed))
563
+ return true;
564
+ if (TEST_REASON_CONTAINS.test(trimmed))
565
+ return true;
566
+ const words = trimmed.split(/\s+/);
567
+ if (words.length <= 2 && trimmed.length <= 14 && /(?:test|probe|try|check|demo|poke)/i.test(trimmed)) {
568
+ return true;
569
+ }
570
+ return false;
571
+ }
572
+ function patternCore(line) {
573
+ const noDatePrefix = line.replace(/^\[\d{4}-\d{2}-\d{2}\]\s*/, "");
574
+ return noDatePrefix.replace(/\s+/g, " ").trim().toLowerCase().slice(0, 120);
575
+ }
576
+ function extractDate(line) {
577
+ const m = line.match(/^\[(\d{4}-\d{2}-\d{2})\]/);
578
+ return m ? m[1] : null;
579
+ }
580
+ async function isDuplicateReflexion(agentId, newLine) {
581
+ try {
582
+ const reflexionPath = path_12.default.join(os_12.default.homedir(), ".openclaw", "agents", agentId, "REFLEXION.md");
583
+ const existing = await promises_12.default.readFile(reflexionPath, "utf-8").catch(() => "");
584
+ if (!existing)
585
+ return false;
586
+ const newCore = patternCore(newLine);
587
+ if (!newCore)
588
+ return false;
589
+ const cutoffDate = new Date(Date.now() - SEVEN_DAYS_MS).toISOString().slice(0, 10);
590
+ for (const line of existing.split("\n")) {
591
+ if (!line.trim())
592
+ continue;
593
+ const date = extractDate(line);
594
+ if (!date)
595
+ continue;
596
+ if (date < cutoffDate)
597
+ continue;
598
+ if (patternCore(line) === newCore)
599
+ return true;
600
+ }
601
+ return false;
602
+ } catch {
603
+ return false;
604
+ }
605
+ }
606
+ }
607
+ });
608
+
498
609
  // apps/backend/dist/intelligence.js
499
610
  var require_intelligence = __commonJS({
500
611
  "apps/backend/dist/intelligence.js"(exports2) {
@@ -503,7 +614,8 @@ var require_intelligence = __commonJS({
503
614
  return mod && mod.__esModule ? mod : { "default": mod };
504
615
  };
505
616
  Object.defineProperty(exports2, "__esModule", { value: true });
506
- exports2.parseMemoryEntries = exports2.getReflexionContext = exports2.getKnowledgeContext = exports2.parseKnowledgeNotes = exports2.buildKnowledgeNote = exports2.appendReflexion = exports2.readReflexion = exports2.readKnowledge = exports2.atomicWrite = void 0;
617
+ exports2.parseMemoryEntries = exports2.getReflexionContext = exports2.getKnowledgeContext = exports2.parseKnowledgeNotes = exports2.buildKnowledgeNote = exports2.readReflexion = exports2.readKnowledge = exports2.atomicWrite = void 0;
618
+ exports2.appendReflexion = appendReflexion;
507
619
  exports2.writeKnowledge = writeKnowledge;
508
620
  exports2.callReflectionLLM = callReflectionLLM;
509
621
  exports2.runReflection = runReflection;
@@ -531,9 +643,6 @@ var require_intelligence = __commonJS({
531
643
  Object.defineProperty(exports2, "readReflexion", { enumerable: true, get: function() {
532
644
  return governance_1.readReflexion;
533
645
  } });
534
- Object.defineProperty(exports2, "appendReflexion", { enumerable: true, get: function() {
535
- return governance_1.appendReflexion;
536
- } });
537
646
  var governance_2 = require_dist();
538
647
  Object.defineProperty(exports2, "buildKnowledgeNote", { enumerable: true, get: function() {
539
648
  return governance_2.buildKnowledgeNote;
@@ -547,6 +656,12 @@ var require_intelligence = __commonJS({
547
656
  Object.defineProperty(exports2, "getReflexionContext", { enumerable: true, get: function() {
548
657
  return governance_2.getReflexionContext;
549
658
  } });
659
+ var memoryGuard_12 = require_memoryGuard();
660
+ async function appendReflexion(agentId, line) {
661
+ if (await (0, memoryGuard_12.isTestModeEnabled)())
662
+ return;
663
+ return (0, governance_1.appendReflexion)(agentId, line);
664
+ }
550
665
  var governance_3 = require_dist();
551
666
  Object.defineProperty(exports2, "parseMemoryEntries", { enumerable: true, get: function() {
552
667
  return governance_3.parseMemoryEntries;
@@ -619,6 +734,8 @@ var require_intelligence = __commonJS({
619
734
  return data.choices?.[0]?.message?.content ?? null;
620
735
  }
621
736
  async function runReflection(agentId, conversationSummary, _sessionKey) {
737
+ if (await (0, memoryGuard_12.isTestModeEnabled)())
738
+ return;
622
739
  try {
623
740
  const raw = await (0, governance_1.readKnowledge)(agentId);
624
741
  let notes = (0, governance_2.parseKnowledgeNotes)(raw);
@@ -707,6 +824,8 @@ ${notes.map((n) => `- ${n.title} [${n.tags.join(", ")}] w${n.weight}: ${n.insigh
707
824
  }
708
825
  }
709
826
  async function compactReflexion(agentId) {
827
+ if (await (0, memoryGuard_12.isTestModeEnabled)())
828
+ return;
710
829
  try {
711
830
  const content = await (0, governance_1.readReflexion)(agentId);
712
831
  if (!content)
@@ -1745,6 +1864,8 @@ var require_openclaw = __commonJS({
1745
1864
  exports2.openClawWorkspacePath = openClawWorkspacePath;
1746
1865
  exports2.readOpenClawConfig = readOpenClawConfig;
1747
1866
  exports2.writeOpenClawConfig = writeOpenClawConfig;
1867
+ exports2.resolveOllamaBaseUrl = resolveOllamaBaseUrl;
1868
+ exports2.ensureVllmProvider = ensureVllmProvider;
1748
1869
  exports2.resolveOpenClawToken = resolveOpenClawToken;
1749
1870
  exports2.hydrateOpenClawTokenFromConfig = hydrateOpenClawTokenFromConfig;
1750
1871
  exports2.cleanupOpenClawSessions = cleanupOpenClawSessions;
@@ -1903,6 +2024,50 @@ var require_openclaw = __commonJS({
1903
2024
  await (0, promises_12.writeFile)(tmp, JSON.stringify(config, null, 2), "utf-8");
1904
2025
  await (0, promises_12.rename)(tmp, exports2.OPENCLAW_CONFIG_PATH);
1905
2026
  }
2027
+ function resolveOllamaBaseUrl() {
2028
+ const installPath = process.env.DAMNDEV_INSTALL_PATH;
2029
+ return installPath === "docker-local" || installPath === "docker-vps" ? "http://host.docker.internal:11434/v1" : "http://localhost:11434/v1";
2030
+ }
2031
+ async function ensureVllmProvider(modelId) {
2032
+ if (!modelId.startsWith("vllm/"))
2033
+ return;
2034
+ const bareModelId = modelId.slice("vllm/".length);
2035
+ if (!bareModelId)
2036
+ return;
2037
+ let config;
2038
+ try {
2039
+ config = await readOpenClawConfig();
2040
+ } catch {
2041
+ return;
2042
+ }
2043
+ if (!config.models)
2044
+ config.models = {};
2045
+ if (!config.models.mode)
2046
+ config.models.mode = "merge";
2047
+ if (!config.models.providers)
2048
+ config.models.providers = {};
2049
+ const existing = config.models.providers.vllm;
2050
+ const baseUrl = existing?.baseUrl ?? resolveOllamaBaseUrl();
2051
+ const models = Array.isArray(existing?.models) ? existing.models : [];
2052
+ if (!models.some((m) => m?.id === bareModelId)) {
2053
+ models.push({
2054
+ id: bareModelId,
2055
+ name: bareModelId,
2056
+ reasoning: false,
2057
+ input: ["text"],
2058
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
2059
+ contextWindow: 128e3,
2060
+ maxTokens: 8192
2061
+ });
2062
+ }
2063
+ config.models.providers.vllm = {
2064
+ baseUrl,
2065
+ api: "openai-completions",
2066
+ apiKey: existing?.apiKey ?? "VLLM_API_KEY",
2067
+ models
2068
+ };
2069
+ await writeOpenClawConfig(config);
2070
+ }
1906
2071
  async function resolveOpenClawToken() {
1907
2072
  const envToken = process.env.OPENCLAW_TOKEN;
1908
2073
  if (envToken)
@@ -8179,6 +8344,7 @@ var require_approvals = __commonJS({
8179
8344
  var logEvent_12 = require_logEvent();
8180
8345
  var shellExec_12 = require_shellExec();
8181
8346
  var triggerAgent_12 = require_triggerAgent();
8347
+ var memoryGuard_12 = require_memoryGuard();
8182
8348
  var messages_12 = require_messages();
8183
8349
  async function resolveApproval(messageId, decision, decidedBy, rejectionNote) {
8184
8350
  const message = await db_12.db.message.findUnique({
@@ -8507,11 +8673,13 @@ ${exitBadge} \xB7 ${durationMs}ms`;
8507
8673
  }
8508
8674
  if (decision === "rejected") {
8509
8675
  const action = message.content.slice(0, 120);
8510
- void (0, intelligence_12.withReflexionLock)(agentId, async () => {
8511
- await (0, intelligence_12.appendReflexion)(agentId, `[${now.toISOString().slice(0, 10)}] Rejected: "${action}". ${rejectionNote ? `Reason: ${rejectionNote}. ` : ""}Constraint: avoid this class of action without explicit confirmation.`);
8512
- await (0, intelligence_12.compactReflexion)(agentId);
8513
- }).catch(() => {
8514
- });
8676
+ if (!(0, memoryGuard_12.isLikelyTestRejection)(rejectionNote)) {
8677
+ void (0, intelligence_12.withReflexionLock)(agentId, async () => {
8678
+ await (0, intelligence_12.appendReflexion)(agentId, `[${now.toISOString().slice(0, 10)}] Rejected: "${action}". ${rejectionNote ? `Reason: ${rejectionNote}. ` : ""}Constraint: avoid this class of action without explicit confirmation.`);
8679
+ await (0, intelligence_12.compactReflexion)(agentId);
8680
+ }).catch(() => {
8681
+ });
8682
+ }
8515
8683
  if (message.approval?.type === "shell_exec" && message.approval.payload) {
8516
8684
  void (async () => {
8517
8685
  try {
@@ -9535,6 +9703,7 @@ var require_delegation = __commonJS({
9535
9703
  var delegationSecurity_1 = require_delegationSecurity();
9536
9704
  var approvalPolicy_12 = require_approvalPolicy();
9537
9705
  var intelligence_12 = require_intelligence();
9706
+ var memoryGuard_12 = require_memoryGuard();
9538
9707
  var triggerAgent_12 = require_triggerAgent();
9539
9708
  var withRetry_1 = require_withRetry();
9540
9709
  var pushNotifications_12 = require_pushNotifications();
@@ -10283,7 +10452,12 @@ ${result}`);
10283
10452
  controller.abort();
10284
10453
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
10285
10454
  const truncatedTask = delegateBlock.task.slice(0, 100);
10286
- void (0, intelligence_12.appendReflexion)(toAgent.id, `[${today}] Task from ${fromAgent.name} timed out: '${truncatedTask}'. Consider faster approaches.`);
10455
+ const timeoutLine = `[${today}] Task from ${fromAgent.name} timed out: '${truncatedTask}'. Consider faster approaches.`;
10456
+ void (async () => {
10457
+ if (await (0, memoryGuard_12.isDuplicateReflexion)(toAgent.id, timeoutLine))
10458
+ return;
10459
+ await (0, intelligence_12.appendReflexion)(toAgent.id, timeoutLine);
10460
+ })();
10287
10461
  (0, logEvent_12.logEvent)({
10288
10462
  agentId: fromAgent.id,
10289
10463
  type: "delegation_timeout",
@@ -11609,7 +11783,8 @@ var require_governance = __commonJS({
11609
11783
  };
11610
11784
  })();
11611
11785
  Object.defineProperty(exports2, "__esModule", { value: true });
11612
- exports2.writeAgentMemory = exports2.loadRecentMemory = exports2.readAgentFile = void 0;
11786
+ exports2.loadRecentMemory = exports2.readAgentFile = void 0;
11787
+ exports2.writeAgentMemory = writeAgentMemory;
11613
11788
  exports2.getAgentContext = getAgentContext;
11614
11789
  exports2.ingestAgentResponse = ingestAgentResponse;
11615
11790
  exports2.logAgentEvent = logAgentEvent;
@@ -11626,9 +11801,12 @@ var require_governance = __commonJS({
11626
11801
  Object.defineProperty(exports2, "loadRecentMemory", { enumerable: true, get: function() {
11627
11802
  return governance_2.loadRecentMemory;
11628
11803
  } });
11629
- Object.defineProperty(exports2, "writeAgentMemory", { enumerable: true, get: function() {
11630
- return governance_2.writeAgentMemory;
11631
- } });
11804
+ var memoryGuard_12 = require_memoryGuard();
11805
+ async function writeAgentMemory(agentId, content, source) {
11806
+ if (await (0, memoryGuard_12.isTestModeEnabled)())
11807
+ return "";
11808
+ return (0, governance_2.writeAgentMemory)(agentId, content, source);
11809
+ }
11632
11810
  async function getAgentContext(agentId) {
11633
11811
  const [soul, knowledge, reflexion, teamContext, recentMemory, activeTasks, skills] = await Promise.all([
11634
11812
  (0, governance_2.readAgentFile)(agentId, "SOUL.md"),
@@ -11672,7 +11850,7 @@ var require_governance = __commonJS({
11672
11850
  const { content: afterMemory, memoryAppend } = extractMemoryUpdate(responseText);
11673
11851
  if (memoryAppend) {
11674
11852
  blocksFound.push("memory-update");
11675
- await (0, governance_2.writeAgentMemory)(agentId, memoryAppend, source);
11853
+ await writeAgentMemory(agentId, memoryAppend, source);
11676
11854
  memoryWritten = true;
11677
11855
  }
11678
11856
  const { content: afterContext, contextUpdates } = extractContextUpdate(afterMemory);
@@ -12083,6 +12261,7 @@ var require_triggerAgent = __commonJS({
12083
12261
  var db_12 = require_db();
12084
12262
  var ws_12 = require_ws();
12085
12263
  var intelligence_12 = require_intelligence();
12264
+ var memoryGuard_12 = require_memoryGuard();
12086
12265
  var messages_12 = require_messages();
12087
12266
  var logEvent_12 = require_logEvent();
12088
12267
  var approvalPolicy_12 = require_approvalPolicy();
@@ -12661,9 +12840,11 @@ ${sectionHeader}`);
12661
12840
  });
12662
12841
  }
12663
12842
  } else {
12664
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
12665
- const note = rejectionNote ? ` Reason: ${rejectionNote}.` : "";
12666
- void (0, intelligence_12.appendReflexion)(approval.agentId, `[${today}] Rejected ${approval.file} update: "${approval.action}".${note} Constraint: reconsider before proposing this type of change.`);
12843
+ if (!(0, memoryGuard_12.isLikelyTestRejection)(rejectionNote)) {
12844
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
12845
+ const note = rejectionNote ? ` Reason: ${rejectionNote}.` : "";
12846
+ void (0, intelligence_12.appendReflexion)(approval.agentId, `[${today}] Rejected ${approval.file} update: "${approval.action}".${note} Constraint: reconsider before proposing this type of change.`);
12847
+ }
12667
12848
  }
12668
12849
  (0, ws_12.broadcastToChannel)(approval.channelId, {
12669
12850
  type: "approval.file_edit.decided",
@@ -14082,6 +14263,7 @@ var require_messages = __commonJS({
14082
14263
  var terminalWatcher_1 = require_terminalWatcher();
14083
14264
  var gateways_12 = require_gateways();
14084
14265
  var intelligence_12 = require_intelligence();
14266
+ var memoryGuard_12 = require_memoryGuard();
14085
14267
  var os_12 = require("os");
14086
14268
  var OPENCLAW_AGENTS_DIR = path_12.default.join(process.env.HOME ?? "~", ".openclaw", "agents");
14087
14269
  var compactCooldowns = /* @__PURE__ */ new Map();
@@ -14170,6 +14352,8 @@ ${summary}
14170
14352
  }
14171
14353
  var TOKEN_COMPACT_THRESHOLD = 8e4;
14172
14354
  async function maybeCompact(channelId, agentId) {
14355
+ if (await (0, memoryGuard_12.isTestModeEnabled)())
14356
+ return;
14173
14357
  const now = Date.now();
14174
14358
  const last = compactCooldowns.get(channelId) ?? 0;
14175
14359
  if (now - last < COMPACT_COOLDOWN_MS)
@@ -14552,6 +14736,7 @@ var require_terminalWatcher = __commonJS({
14552
14736
  var messages_12 = require_messages();
14553
14737
  var triggerAgent_12 = require_triggerAgent();
14554
14738
  var intelligence_12 = require_intelligence();
14739
+ var memoryGuard_12 = require_memoryGuard();
14555
14740
  var TERM_LOG_DIR = path_12.default.join(process.env.HOME ?? "/tmp", ".damn-dev", "terminals");
14556
14741
  var MAX_LOG_CHARS = 8e3;
14557
14742
  var IDLE_TIMEOUT_MS = 3e3;
@@ -14840,8 +15025,10 @@ ${summary}`;
14840
15025
  return;
14841
15026
  }
14842
15027
  if (REJECTION_KEYWORDS.test(userMessage)) {
14843
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
14844
- void (0, intelligence_12.appendReflexion)(last.agentId, `[${today}] Suggested "${last.suggestion}" for terminal issue. User rejected: "${userMessage.slice(0, 100)}". Reconsider this pattern.`);
15028
+ if (!(0, memoryGuard_12.isLikelyTestRejection)(userMessage)) {
15029
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
15030
+ void (0, intelligence_12.appendReflexion)(last.agentId, `[${today}] Suggested "${last.suggestion}" for terminal issue. User rejected: "${userMessage.slice(0, 100)}". Reconsider this pattern.`);
15031
+ }
14845
15032
  lastSuggestions.delete(dmChannelId);
14846
15033
  }
14847
15034
  }
@@ -14854,7 +15041,12 @@ ${summary}`;
14854
15041
  continue;
14855
15042
  }
14856
15043
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
14857
- void (0, intelligence_12.appendReflexion)(last.agentId, `[${today}] Suggested "${last.suggestion}" for terminal issue. User ran different command: "${command.slice(0, 100)}". Reconsider this pattern.`);
15044
+ const line = `[${today}] Suggested "${last.suggestion}" for terminal issue. User ran different command: "${command.slice(0, 100)}". Reconsider this pattern.`;
15045
+ void (async () => {
15046
+ if (await (0, memoryGuard_12.isDuplicateReflexion)(last.agentId, line))
15047
+ return;
15048
+ await (0, intelligence_12.appendReflexion)(last.agentId, line);
15049
+ })();
14858
15050
  lastSuggestions.delete(key);
14859
15051
  }
14860
15052
  }
@@ -16638,6 +16830,24 @@ You are ${agent.name}. Your role: ${agent.role}.
16638
16830
  if (config.hooks?.allowedAgentIds) {
16639
16831
  config.hooks.allowedAgentIds = config.hooks.allowedAgentIds.filter((id) => id !== input.agentId);
16640
16832
  }
16833
+ try {
16834
+ const cronJobsPath = (0, path_12.join)((0, os_12.homedir)(), ".openclaw", "cron", "jobs.json");
16835
+ const raw = await (0, promises_12.readFile)(cronJobsPath, "utf-8").catch(() => null);
16836
+ if (raw) {
16837
+ const store = JSON.parse(raw);
16838
+ if (Array.isArray(store.jobs)) {
16839
+ const kept = store.jobs.filter((j) => j.agentId !== input.agentId);
16840
+ if (kept.length < store.jobs.length) {
16841
+ store.jobs = kept;
16842
+ const tmp = `${cronJobsPath}.tmp.${Date.now()}`;
16843
+ await (0, promises_12.writeFile)(tmp, JSON.stringify(store, null, 2), "utf-8");
16844
+ await (0, promises_12.rename)(tmp, cronJobsPath);
16845
+ }
16846
+ }
16847
+ }
16848
+ } catch (err) {
16849
+ console.error(`[agent.delete] cron job cleanup failed for ${input.agentId}:`, err);
16850
+ }
16641
16851
  await (0, openclaw_12.writeOpenClawConfig)(config);
16642
16852
  await (0, promises_12.rm)(dir, { recursive: true, force: true });
16643
16853
  const agentChannels = await db_12.db.channel.findMany({
@@ -16661,6 +16871,7 @@ You are ${agent.name}. Your role: ${agent.role}.
16661
16871
  await db_12.db.channelParticipant.deleteMany({ where: { channelId: { in: channelIds } } });
16662
16872
  await db_12.db.reaction.deleteMany({ where: { message: { channelId: { in: channelIds } } } });
16663
16873
  await db_12.db.attachment.deleteMany({ where: { message: { channelId: { in: channelIds } } } });
16874
+ await db_12.db.approval.deleteMany({ where: { message: { channelId: { in: channelIds } } } });
16664
16875
  await db_12.db.message.deleteMany({ where: { channelId: { in: channelIds } } });
16665
16876
  await db_12.db.channel.deleteMany({ where: { id: { in: channelIds } } });
16666
16877
  }
@@ -18046,6 +18257,12 @@ the file sets the default agent. \`register_session\` switches per-session.
18046
18257
  `;
18047
18258
  const guidePath = path_12.default.join(agentDir, "WORKSPACE_GUIDE.md");
18048
18259
  const guideExists = await promises_12.default.access(guidePath).then(() => true, () => false);
18260
+ await promises_12.default.mkdir(path_12.default.join(agentDir, "agent"), { recursive: true });
18261
+ const authProfiles = JSON.stringify({
18262
+ version: 1,
18263
+ profiles: { "vllm:default": { type: "api_key", provider: "vllm", key: "ollama" } },
18264
+ lastGood: { vllm: "vllm:default" }
18265
+ }, null, 2);
18049
18266
  await Promise.all([
18050
18267
  promises_12.default.writeFile(path_12.default.join(agentDir, "SOUL.md"), soulContent, "utf-8"),
18051
18268
  promises_12.default.writeFile(path_12.default.join(agentDir, "IDENTITY.md"), identityContent, "utf-8"),
@@ -18059,8 +18276,14 @@ You are the COO. You design and orchestrate the workspace.
18059
18276
  The COO may assign you tasks directly via your DM channel. Treat dispatched instructions with the same priority as messages from the workspace owner. Complete the task fully and report the outcome. Do not ask for clarification unless the instruction is genuinely ambiguous \u2014 produce your best attempt and flag assumptions at the bottom.
18060
18277
  `, "utf-8"),
18061
18278
  promises_12.default.writeFile(path_12.default.join(agentDir, "ORGANIGRAM.md"), organigramContent, "utf-8"),
18279
+ atomicWrite(path_12.default.join(agentDir, "agent", "auth-profiles.json"), authProfiles),
18062
18280
  ...guideExists ? [] : [promises_12.default.writeFile(guidePath, workspaceGuideContent, "utf-8")]
18063
18281
  ]);
18282
+ try {
18283
+ await (0, openclaw_12.ensureVllmProvider)(cooModel);
18284
+ } catch (err) {
18285
+ console.error("[ensureCoo] Failed to register vllm provider:", err);
18286
+ }
18064
18287
  try {
18065
18288
  const config = await (0, openclaw_12.readOpenClawConfig)();
18066
18289
  const alreadyRegistered = config.agents.list.some((a) => a.id === "coo");
@@ -18684,6 +18907,12 @@ Or just tell me what you're working on \u2014 I'll figure out the rest.`
18684
18907
  } catch (err) {
18685
18908
  console.error("[onboarding.setDefaultModels] Failed to patch openclaw.json:", err);
18686
18909
  }
18910
+ try {
18911
+ await (0, openclaw_12.ensureVllmProvider)(canonicalReasoning);
18912
+ await (0, openclaw_12.ensureVllmProvider)(canonicalFast);
18913
+ } catch (err) {
18914
+ console.error("[onboarding.setDefaultModels] Failed to register vllm provider:", err);
18915
+ }
18687
18916
  return { ok: true };
18688
18917
  }),
18689
18918
  setupDamndevChannel: trpc_12.protectedProcedure.input(zod_12.z.object({
@@ -21795,6 +22024,7 @@ var require_settings = __commonJS({
21795
22024
  var keyRegistry_1 = require_keyRegistry();
21796
22025
  var db_12 = require_db();
21797
22026
  var secrets_1 = require_secrets();
22027
+ var memoryGuard_12 = require_memoryGuard();
21798
22028
  var execAsync = (0, util_12.promisify)(child_process_12.exec);
21799
22029
  var HOME = (0, os_12.homedir)();
21800
22030
  var DANGEROUS_PATHS = ["/etc", "/proc", "/sys", "/dev", "/var/run/docker.sock"];
@@ -22245,6 +22475,13 @@ var require_settings = __commonJS({
22245
22475
  }
22246
22476
  }),
22247
22477
  applyMountsAndRestart: trpc_12.protectedProcedure.mutation(async () => applyMountsAndRestart()),
22478
+ getTestMode: trpc_12.protectedProcedure.query(async () => {
22479
+ return (0, memoryGuard_12.readTestMode)();
22480
+ }),
22481
+ setTestMode: trpc_12.protectedProcedure.input(zod_12.z.object({ enabled: zod_12.z.boolean() })).mutation(async ({ input }) => {
22482
+ await (0, memoryGuard_12.setTestMode)(input.enabled);
22483
+ return { ok: true, enabled: input.enabled };
22484
+ }),
22248
22485
  detectObsidianVaults: trpc_12.protectedProcedure.query(async () => {
22249
22486
  const obsidianConfigPath = (0, path_12.join)((0, os_12.homedir)(), "Library", "Application Support", "obsidian", "obsidian.json");
22250
22487
  try {
@@ -26956,6 +27193,230 @@ var require_integrations = __commonJS({
26956
27193
  }
26957
27194
  });
26958
27195
 
27196
+ // apps/backend/dist/routers/memoryInvalidate.js
27197
+ var require_memoryInvalidate = __commonJS({
27198
+ "apps/backend/dist/routers/memoryInvalidate.js"(exports2) {
27199
+ "use strict";
27200
+ var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
27201
+ return mod && mod.__esModule ? mod : { "default": mod };
27202
+ };
27203
+ Object.defineProperty(exports2, "__esModule", { value: true });
27204
+ exports2.memoryInvalidateRouter = void 0;
27205
+ var trpc_12 = require_trpc();
27206
+ var zod_12 = require("zod");
27207
+ var promises_12 = __importDefault2(require("fs/promises"));
27208
+ var path_12 = __importDefault2(require("path"));
27209
+ var os_12 = __importDefault2(require("os"));
27210
+ var governance_1 = require_dist();
27211
+ var AGENTS_DIR = path_12.default.join(os_12.default.homedir(), ".openclaw", "agents");
27212
+ var FILE_MAP = {
27213
+ MEMORY: "MEMORY.md",
27214
+ KNOWLEDGE: "KNOWLEDGE.md",
27215
+ REFLEXION: "REFLEXION.md"
27216
+ };
27217
+ async function listAgentIds() {
27218
+ try {
27219
+ const entries = await promises_12.default.readdir(AGENTS_DIR, { withFileTypes: true });
27220
+ return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
27221
+ } catch {
27222
+ return [];
27223
+ }
27224
+ }
27225
+ function compilePattern(pattern) {
27226
+ const trimmed = pattern.trim();
27227
+ if (!trimmed)
27228
+ return null;
27229
+ try {
27230
+ return new RegExp(trimmed, "i");
27231
+ } catch {
27232
+ return new RegExp(trimmed.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i");
27233
+ }
27234
+ }
27235
+ function scanReflexion(agentId, content, rx) {
27236
+ const matches = [];
27237
+ const lines = content.split("\n");
27238
+ for (let i = 0; i < lines.length; i++) {
27239
+ const line = lines[i];
27240
+ if (!line.trim())
27241
+ continue;
27242
+ if (line.startsWith("## "))
27243
+ continue;
27244
+ if (!rx.test(line))
27245
+ continue;
27246
+ const preview = line.slice(0, 200);
27247
+ matches.push({
27248
+ id: `${agentId}|REFLEXION|${i}`,
27249
+ agentId,
27250
+ file: "REFLEXION",
27251
+ startLine: i,
27252
+ endLine: i,
27253
+ preview
27254
+ });
27255
+ }
27256
+ return matches;
27257
+ }
27258
+ function scanHeadingSections(agentId, file, content, rx) {
27259
+ const matches = [];
27260
+ const lines = content.split("\n");
27261
+ const sections = [];
27262
+ let currentStart = -1;
27263
+ let currentBody = [];
27264
+ const flush = (endLine) => {
27265
+ if (currentStart === -1)
27266
+ return;
27267
+ sections.push({
27268
+ startLine: currentStart,
27269
+ endLine,
27270
+ body: currentBody.join("\n")
27271
+ });
27272
+ currentStart = -1;
27273
+ currentBody = [];
27274
+ };
27275
+ for (let i = 0; i < lines.length; i++) {
27276
+ const line = lines[i];
27277
+ if (line.startsWith("## ")) {
27278
+ flush(i - 1);
27279
+ currentStart = i;
27280
+ currentBody = [line];
27281
+ } else if (currentStart !== -1) {
27282
+ currentBody.push(line);
27283
+ }
27284
+ }
27285
+ flush(lines.length - 1);
27286
+ for (const section of sections) {
27287
+ if (!rx.test(section.body))
27288
+ continue;
27289
+ const firstLine = lines[section.startLine] ?? "";
27290
+ const preview = firstLine.replace(/^##\s*/, "").slice(0, 200);
27291
+ matches.push({
27292
+ id: `${agentId}|${file}|${section.startLine}`,
27293
+ agentId,
27294
+ file,
27295
+ startLine: section.startLine,
27296
+ endLine: section.endLine,
27297
+ preview
27298
+ });
27299
+ }
27300
+ return matches;
27301
+ }
27302
+ async function scanAgentFile(agentId, file, rx) {
27303
+ const filePath = path_12.default.join(AGENTS_DIR, agentId, FILE_MAP[file]);
27304
+ let content;
27305
+ try {
27306
+ content = await promises_12.default.readFile(filePath, "utf-8");
27307
+ } catch {
27308
+ return [];
27309
+ }
27310
+ if (!content.trim())
27311
+ return [];
27312
+ if (file === "REFLEXION")
27313
+ return scanReflexion(agentId, content, rx);
27314
+ return scanHeadingSections(agentId, file, content, rx);
27315
+ }
27316
+ async function applyRemovals(agentId, file, ranges) {
27317
+ if (ranges.length === 0)
27318
+ return;
27319
+ const filePath = path_12.default.join(AGENTS_DIR, agentId, FILE_MAP[file]);
27320
+ let content;
27321
+ try {
27322
+ content = await promises_12.default.readFile(filePath, "utf-8");
27323
+ } catch {
27324
+ return;
27325
+ }
27326
+ const lines = content.split("\n");
27327
+ const remove = /* @__PURE__ */ new Set();
27328
+ for (const r of ranges) {
27329
+ for (let i = r.startLine; i <= r.endLine; i++)
27330
+ remove.add(i);
27331
+ }
27332
+ const kept = [];
27333
+ for (let i = 0; i < lines.length; i++) {
27334
+ if (!remove.has(i))
27335
+ kept.push(lines[i]);
27336
+ }
27337
+ while (kept.length > 1 && kept[kept.length - 1] === "" && kept[kept.length - 2] === "") {
27338
+ kept.pop();
27339
+ }
27340
+ await (0, governance_1.atomicWrite)(filePath, kept.join("\n"));
27341
+ }
27342
+ exports2.memoryInvalidateRouter = (0, trpc_12.router)({
27343
+ scan: trpc_12.protectedProcedure.input(zod_12.z.object({
27344
+ pattern: zod_12.z.string().min(1),
27345
+ agentIds: zod_12.z.array(zod_12.z.string()).optional()
27346
+ })).query(async ({ input }) => {
27347
+ const rx = compilePattern(input.pattern);
27348
+ if (!rx)
27349
+ return { matches: [] };
27350
+ const agentIds = input.agentIds?.length ? input.agentIds : await listAgentIds();
27351
+ const allMatches = [];
27352
+ for (const agentId of agentIds) {
27353
+ for (const file of ["REFLEXION", "KNOWLEDGE", "MEMORY"]) {
27354
+ const m = await scanAgentFile(agentId, file, rx);
27355
+ allMatches.push(...m);
27356
+ }
27357
+ }
27358
+ return { matches: allMatches };
27359
+ }),
27360
+ invalidate: trpc_12.protectedProcedure.input(zod_12.z.object({
27361
+ matchIds: zod_12.z.array(zod_12.z.string()).min(1)
27362
+ })).mutation(async ({ input }) => {
27363
+ const groups = /* @__PURE__ */ new Map();
27364
+ const parsed = input.matchIds.map((id) => {
27365
+ const [agentId, file, startLineStr] = id.split("|");
27366
+ const startLine = Number(startLineStr);
27367
+ if (!agentId || !file || !Number.isFinite(startLine))
27368
+ return null;
27369
+ if (file !== "MEMORY" && file !== "KNOWLEDGE" && file !== "REFLEXION")
27370
+ return null;
27371
+ return { agentId, file, startLine };
27372
+ }).filter((x) => x !== null);
27373
+ if (parsed.length === 0)
27374
+ return { removed: 0, errors: [] };
27375
+ const agentsToScan = Array.from(new Set(parsed.map((p) => p.agentId)));
27376
+ const wildcardRx = /./;
27377
+ const liveByAgent = /* @__PURE__ */ new Map();
27378
+ for (const agentId of agentsToScan) {
27379
+ const all = [];
27380
+ for (const file of ["REFLEXION", "KNOWLEDGE", "MEMORY"]) {
27381
+ all.push(...await scanAgentFile(agentId, file, wildcardRx));
27382
+ }
27383
+ liveByAgent.set(agentId, all);
27384
+ }
27385
+ const errors = [];
27386
+ let removed = 0;
27387
+ for (const p of parsed) {
27388
+ const live = liveByAgent.get(p.agentId) ?? [];
27389
+ const match = live.find((m) => m.agentId === p.agentId && m.file === p.file && m.startLine === p.startLine);
27390
+ if (!match) {
27391
+ errors.push(`Match not found or already removed: ${p.agentId}|${p.file}|${p.startLine}`);
27392
+ continue;
27393
+ }
27394
+ const key = `${match.agentId}|${match.file}`;
27395
+ const existing = groups.get(key);
27396
+ if (existing) {
27397
+ existing.ranges.push({ startLine: match.startLine, endLine: match.endLine });
27398
+ } else {
27399
+ groups.set(key, {
27400
+ agentId: match.agentId,
27401
+ file: match.file,
27402
+ ranges: [{ startLine: match.startLine, endLine: match.endLine }]
27403
+ });
27404
+ }
27405
+ removed++;
27406
+ }
27407
+ for (const group of groups.values()) {
27408
+ try {
27409
+ await applyRemovals(group.agentId, group.file, group.ranges);
27410
+ } catch (err) {
27411
+ errors.push(`${group.agentId}/${group.file}: ${err instanceof Error ? err.message : String(err)}`);
27412
+ }
27413
+ }
27414
+ return { removed, errors };
27415
+ })
27416
+ });
27417
+ }
27418
+ });
27419
+
26959
27420
  // apps/backend/dist/router.js
26960
27421
  var require_router = __commonJS({
26961
27422
  "apps/backend/dist/router.js"(exports2) {
@@ -26999,6 +27460,7 @@ var require_router = __commonJS({
26999
27460
  var federation_1 = require_federation2();
27000
27461
  var dashboard_1 = require_dashboard();
27001
27462
  var integrations_1 = require_integrations();
27463
+ var memoryInvalidate_1 = require_memoryInvalidate();
27002
27464
  exports2.appRouter = (0, trpc_12.router)({
27003
27465
  agents: agents_1.agentsRouter,
27004
27466
  channels: channels_1.channelsRouter,
@@ -27035,7 +27497,8 @@ var require_router = __commonJS({
27035
27497
  missions: missions_1.missionsRouter,
27036
27498
  federation: federation_1.federationRouter,
27037
27499
  dashboard: dashboard_1.dashboardRouter,
27038
- integrations: integrations_1.integrationsRouter
27500
+ integrations: integrations_1.integrationsRouter,
27501
+ memoryInvalidate: memoryInvalidate_1.memoryInvalidateRouter
27039
27502
  });
27040
27503
  }
27041
27504
  });
@@ -27431,7 +27894,7 @@ var require_package = __commonJS({
27431
27894
  module2.exports = {
27432
27895
  name: "backend",
27433
27896
  private: true,
27434
- version: "0.9.3",
27897
+ version: "0.9.6",
27435
27898
  scripts: {
27436
27899
  dev: "tsx watch src/server.ts",
27437
27900
  build: "tsc && cp -r resources dist/resources",
@@ -27755,6 +28218,7 @@ var skills_1 = require_skills();
27755
28218
  var openclaw_1 = require_openclaw();
27756
28219
  var gateways_1 = require_gateways();
27757
28220
  var intelligence_1 = require_intelligence();
28221
+ var memoryGuard_1 = require_memoryGuard();
27758
28222
  var telegramBridge_1 = require_telegramBridge();
27759
28223
  var onboarding_1 = require_onboarding();
27760
28224
  var agentImport_1 = require_agentImport();
@@ -28198,7 +28662,12 @@ async function main() {
28198
28662
  });
28199
28663
  if (result.exitCode !== 0) {
28200
28664
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28201
- void (0, intelligence_1.appendReflexion)(agent_id, `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`);
28665
+ const line = `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`;
28666
+ void (async () => {
28667
+ if (await (0, memoryGuard_1.isDuplicateReflexion)(agent_id, line))
28668
+ return;
28669
+ await (0, intelligence_1.appendReflexion)(agent_id, line);
28670
+ })();
28202
28671
  }
28203
28672
  appendLifelogEvent({
28204
28673
  agent_id,
@@ -28231,7 +28700,12 @@ async function main() {
28231
28700
  });
28232
28701
  if (result.exitCode !== 0) {
28233
28702
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28234
- void (0, intelligence_1.appendReflexion)(agent_id, `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`);
28703
+ const line = `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`;
28704
+ void (async () => {
28705
+ if (await (0, memoryGuard_1.isDuplicateReflexion)(agent_id, line))
28706
+ return;
28707
+ await (0, intelligence_1.appendReflexion)(agent_id, line);
28708
+ })();
28235
28709
  }
28236
28710
  return reply.status(200).send({
28237
28711
  output: result.stdout || result.stderr || "(no output)",
@@ -28411,7 +28885,12 @@ async function main() {
28411
28885
  durationMs: durationMs2
28412
28886
  });
28413
28887
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28414
- void (0, intelligence_1.appendReflexion)(agent_id, `[${date}] Skill ${skill.name} failed with "${msg.slice(0, 120)}". Pattern: check prerequisites before calling this skill.`);
28888
+ const line = `[${date}] Skill ${skill.name} failed with "${msg.slice(0, 120)}". Pattern: check prerequisites before calling this skill.`;
28889
+ void (async () => {
28890
+ if (await (0, memoryGuard_1.isDuplicateReflexion)(agent_id, line))
28891
+ return;
28892
+ await (0, intelligence_1.appendReflexion)(agent_id, line);
28893
+ })();
28415
28894
  return reply.status(500).send({ error: `Execution failed: ${msg}` });
28416
28895
  }
28417
28896
  }
@@ -28481,7 +28960,12 @@ async function main() {
28481
28960
  });
28482
28961
  if (result.exitCode !== 0) {
28483
28962
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28484
- void (0, intelligence_1.appendReflexion)(agent_id, `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`);
28963
+ const line = `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`;
28964
+ void (async () => {
28965
+ if (await (0, memoryGuard_1.isDuplicateReflexion)(agent_id, line))
28966
+ return;
28967
+ await (0, intelligence_1.appendReflexion)(agent_id, line);
28968
+ })();
28485
28969
  }
28486
28970
  appendLifelogEvent({
28487
28971
  agent_id,
@@ -28515,7 +28999,12 @@ async function main() {
28515
28999
  });
28516
29000
  if (result.exitCode !== 0) {
28517
29001
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28518
- void (0, intelligence_1.appendReflexion)(agent_id, `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`);
29002
+ const line = `[${date}] Skill shell-exec failed with "${(result.stderr || result.stdout).slice(0, 120)}". Pattern: check prerequisites before calling this skill.`;
29003
+ void (async () => {
29004
+ if (await (0, memoryGuard_1.isDuplicateReflexion)(agent_id, line))
29005
+ return;
29006
+ await (0, intelligence_1.appendReflexion)(agent_id, line);
29007
+ })();
28519
29008
  }
28520
29009
  return reply.status(200).send({
28521
29010
  output: result.stdout || result.stderr || "(no output)",