aiden-runtime 3.19.4 → 3.19.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26650,7 +26650,7 @@ var require_websocket_server = __commonJS({
26650
26650
  var VERSION;
26651
26651
  var init_version = __esm({
26652
26652
  "core/version.ts"() {
26653
- VERSION = "3.19.4";
26653
+ VERSION = "3.19.5";
26654
26654
  }
26655
26655
  });
26656
26656
 
@@ -99759,6 +99759,7 @@ var init_modelRegistry = __esm({
99759
99759
  var router_exports = {};
99760
99760
  __export(router_exports, {
99761
99761
  assessComplexity: () => assessComplexity,
99762
+ diagnoseProviderPool: () => diagnoseProviderPool,
99762
99763
  enterDegradedMode: () => enterDegradedMode,
99763
99764
  exitDegradedMode: () => exitDegradedMode,
99764
99765
  getLocalModels: () => getLocalModels,
@@ -99873,6 +99874,51 @@ function autoResetExpiredLimits() {
99873
99874
  if (changed) saveConfig(config2);
99874
99875
  return changed;
99875
99876
  }
99877
+ function diagnoseProviderPool() {
99878
+ const config2 = loadConfig();
99879
+ const allApis = mergeCustomProviders(config2.providers.apis);
99880
+ const enabled = allApis.filter((a) => a.enabled);
99881
+ const disabledCount = allApis.length - enabled.length;
99882
+ let noKey = 0, rateLimited = 0;
99883
+ for (const a of enabled) {
99884
+ if (a.rateLimited) {
99885
+ rateLimited++;
99886
+ continue;
99887
+ }
99888
+ if (a.provider === "custom") continue;
99889
+ const k = a.key.startsWith("env:") ? process.env[a.key.replace("env:", "")] || "" : a.key;
99890
+ if (k.length === 0) noKey++;
99891
+ }
99892
+ const active = enabled.length - noKey - rateLimited;
99893
+ if (active > 0)
99894
+ return { state: "ok", noKeyCount: noKey, rateLimitedCount: rateLimited, disabledCount, enabledCount: enabled.length, message: "" };
99895
+ if (noKey > 0 && rateLimited === 0)
99896
+ return {
99897
+ state: "unconfigured",
99898
+ noKeyCount: noKey,
99899
+ rateLimitedCount: 0,
99900
+ disabledCount,
99901
+ enabledCount: enabled.length,
99902
+ message: "No API keys configured - add keys in Settings > API Keys or set env vars"
99903
+ };
99904
+ if (rateLimited > 0 && noKey === 0)
99905
+ return {
99906
+ state: "rate-limited",
99907
+ noKeyCount: 0,
99908
+ rateLimitedCount: rateLimited,
99909
+ disabledCount,
99910
+ enabledCount: enabled.length,
99911
+ message: `All ${rateLimited} cloud provider(s) rate-limited - retrying automatically`
99912
+ };
99913
+ return {
99914
+ state: "mixed",
99915
+ noKeyCount: noKey,
99916
+ rateLimitedCount: rateLimited,
99917
+ disabledCount,
99918
+ enabledCount: enabled.length,
99919
+ message: `${noKey} provider(s) have no key, ${rateLimited} rate-limited`
99920
+ };
99921
+ }
99876
99922
  function getNextAvailableAPI() {
99877
99923
  autoResetExpiredLimits();
99878
99924
  const config2 = loadConfig();
@@ -99883,7 +99929,11 @@ function getNextAvailableAPI() {
99883
99929
  const resolvedKey = api.key.startsWith("env:") ? process.env[api.key.replace("env:", "")] || "" : api.key;
99884
99930
  return resolvedKey.length > 0;
99885
99931
  });
99886
- if (!available.length) return null;
99932
+ if (!available.length) {
99933
+ const diag = diagnoseProviderPool();
99934
+ if (diag.message) console.log(`[Router] ${diag.message}`);
99935
+ return null;
99936
+ }
99887
99937
  const primary = config2.primaryProvider;
99888
99938
  const scored = available.map((api) => {
99889
99939
  const avgMs = responseTimesMs.get(api.name) ?? 2e3;
@@ -100036,7 +100086,8 @@ function getModelForTask(task, message) {
100036
100086
  return resolveKey(chosen);
100037
100087
  }
100038
100088
  const model = getOllamaModelForTask(task === "planner" ? "planner" : "responder");
100039
- console.log(`[Router] ${task}: all cloud providers rate-limited - using Ollama ${model}`);
100089
+ const diag = diagnoseProviderPool();
100090
+ console.log(`[Router] ${task}: ${diag.message || "all cloud providers unavailable"} - using Ollama ${model}`);
100040
100091
  return { apiKey: "", model, providerName: "ollama", apiName: "ollama" };
100041
100092
  }
100042
100093
  if (task === "executor") {
@@ -100045,7 +100096,8 @@ function getModelForTask(task, message) {
100045
100096
  if (api) return resolveKey(api);
100046
100097
  }
100047
100098
  const model = getOllamaModelForTask("executor");
100048
- console.log(`[Router] Executor: all cloud providers unavailable - falling back to Ollama ${model}`);
100099
+ const diag = diagnoseProviderPool();
100100
+ console.log(`[Router] Executor: ${diag.message || "all cloud providers unavailable"} - falling back to Ollama ${model}`);
100049
100101
  return { apiKey: "", model, providerName: "ollama", apiName: "ollama" };
100050
100102
  }
100051
100103
  if (available.length > 0) return resolveKey(available[0]);
@@ -100069,7 +100121,8 @@ function getSmartProvider() {
100069
100121
  }
100070
100122
  if (config2.routing?.fallbackToOllama !== false) {
100071
100123
  const model2 = getOllamaModelForTask("responder");
100072
- console.log(`[Router] All APIs unavailable \u2014 falling back to Ollama ${model2}`);
100124
+ const diag = diagnoseProviderPool();
100125
+ console.log(`[Router] ${diag.message || "All APIs unavailable"} - falling back to Ollama ${model2}`);
100073
100126
  return { provider: ollamaProvider, model: model2, userName, apiName: "ollama" };
100074
100127
  }
100075
100128
  const model = getOllamaModelForTask("responder");
@@ -100111,7 +100164,7 @@ function enterDegradedMode(reason) {
100111
100164
  }
100112
100165
  return {
100113
100166
  mode: "degraded",
100114
- message: `I'm temporarily running in limited mode \u2014 my AI providers are at capacity. I can still:
100167
+ message: `I'm temporarily running in limited mode \u2014 ${diagnoseProviderPool().state === "unconfigured" ? "no API keys are configured" : "my AI providers are at capacity"}. I can still:
100115
100168
  \u2022 Search your files and memory
100116
100169
  \u2022 Run scheduled tasks
100117
100170
  \u2022 Execute shell commands and scripts
@@ -365359,7 +365412,7 @@ ${summaryInput}`,
365359
365412
  if (!parsed) {
365360
365413
  console.warn("[Planner] All LLM attempts failed \u2014 respond fallback (going through guard)");
365361
365414
  parsed = {
365362
- plan: [{ step: 1, tool: "respond", input: { message: buildDiagnostic({ tool: "planner", error: "All LLM attempts failed", retries: 3, suggestion: "Provider chain may be rate-limited. Try again in 1\u20132 minutes or rephrase your request." }) }, description: "Fallback response" }],
365415
+ plan: [{ step: 1, tool: "respond", input: { message: buildDiagnostic({ tool: "planner", error: "All LLM attempts failed", retries: 3, suggestion: diagnoseProviderPool().state === "unconfigured" ? "No API keys configured. Add keys in Settings > API Keys, or start Ollama for local inference." : "Provider chain is rate-limited. Try again in 1-2 minutes or rephrase your request." }) }, description: "Fallback response" }],
365363
365416
  requires_execution: true,
365364
365417
  goal: message
365365
365418
  };
@@ -365491,7 +365544,7 @@ Fix these issues and output a corrected JSON plan.`
365491
365544
  tool: "planner",
365492
365545
  error: "Could not generate tool plan for action intent",
365493
365546
  retries: 1,
365494
- suggestion: "Provider chain may be rate-limited. Try again in 1\u20132 minutes or use a more specific instruction."
365547
+ suggestion: diagnoseProviderPool().state === "unconfigured" ? "No API keys configured. Add keys in Settings > API Keys, or start Ollama for local inference." : "Provider chain is rate-limited. Try again in 1-2 minutes or use a more specific instruction."
365495
365548
  });
365496
365549
  }
365497
365550
  if (guardMatch) {
@@ -366599,7 +366652,8 @@ Respond naturally based on these real results only. Show the actual output, not
366599
366652
  parts.push(
366600
366653
  `Failed: ${failures.map((r) => `${r.tool} \u2014 ${r.error || "unknown error"}`).join("; ")}.`
366601
366654
  );
366602
- parts.push("(All language providers are currently unavailable \u2014 full response cannot be generated.)");
366655
+ const poolDiag = diagnoseProviderPool();
366656
+ parts.push(`(${poolDiag.state === "unconfigured" ? "No API keys configured - add keys in Settings > API Keys" : "All language providers are currently unavailable"} - full response cannot be generated.)`);
366603
366657
  onToken(parts.join(" "));
366604
366658
  return;
366605
366659
  }
@@ -390371,6 +390425,368 @@ var init_hybridSearch = __esm({
390371
390425
  }
390372
390426
  });
390373
390427
 
390428
+ // core/memoryIds.ts
390429
+ function _ensureDir() {
390430
+ fs45.mkdirSync(MEM_DIR, { recursive: true });
390431
+ }
390432
+ function _readSeq() {
390433
+ try {
390434
+ if (!fs45.existsSync(SEQUENCE_FILE)) return 0;
390435
+ const d = JSON.parse(fs45.readFileSync(SEQUENCE_FILE, "utf-8"));
390436
+ return typeof d.next === "number" ? d.next : 0;
390437
+ } catch {
390438
+ return 0;
390439
+ }
390440
+ }
390441
+ function _writeSeq(n) {
390442
+ _ensureDir();
390443
+ fs45.writeFileSync(SEQUENCE_FILE, JSON.stringify({ next: n }), "utf-8");
390444
+ }
390445
+ function nextId() {
390446
+ const n = _readSeq();
390447
+ _writeSeq(n + 1);
390448
+ return `mem_${String(n + 1).padStart(6, "0")}`;
390449
+ }
390450
+ function appendRecord(record2) {
390451
+ _ensureDir();
390452
+ fs45.appendFileSync(RECORDS_FILE, JSON.stringify(record2) + "\n", "utf-8");
390453
+ }
390454
+ function loadAllRecords() {
390455
+ try {
390456
+ if (!fs45.existsSync(RECORDS_FILE)) return [];
390457
+ return fs45.readFileSync(RECORDS_FILE, "utf-8").split("\n").filter((l2) => l2.trim()).map((l2) => {
390458
+ try {
390459
+ return JSON.parse(l2);
390460
+ } catch {
390461
+ return null;
390462
+ }
390463
+ }).filter((r) => r !== null);
390464
+ } catch {
390465
+ return [];
390466
+ }
390467
+ }
390468
+ function loadRecordById(id) {
390469
+ const all3 = loadAllRecords();
390470
+ return all3.find((r) => r.id === id) ?? null;
390471
+ }
390472
+ function removeRecords(predicate) {
390473
+ const all3 = loadAllRecords();
390474
+ const kept = all3.filter((r) => !predicate(r));
390475
+ const removed = all3.length - kept.length;
390476
+ if (removed > 0) {
390477
+ _ensureDir();
390478
+ fs45.writeFileSync(
390479
+ RECORDS_FILE,
390480
+ kept.map((r) => JSON.stringify(r)).join("\n") + (kept.length ? "\n" : ""),
390481
+ "utf-8"
390482
+ );
390483
+ }
390484
+ return removed;
390485
+ }
390486
+ function assignId(partial2) {
390487
+ const record2 = {
390488
+ id: partial2.id ?? nextId(),
390489
+ timestamp: partial2.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
390490
+ type: partial2.type ?? "observation",
390491
+ content: partial2.content ?? "",
390492
+ summary: partial2.summary ?? _autoSummary(partial2.content ?? ""),
390493
+ sessionId: partial2.sessionId,
390494
+ tags: partial2.tags,
390495
+ entityRefs: partial2.entityRefs
390496
+ };
390497
+ appendRecord(record2);
390498
+ return record2;
390499
+ }
390500
+ function _autoSummary(content) {
390501
+ const first = content.split("\n").find((l2) => l2.trim()) ?? content;
390502
+ return first.slice(0, 100).trim();
390503
+ }
390504
+ function runMigrationIfNeeded() {
390505
+ if (fs45.existsSync(RECORDS_FILE)) return 0;
390506
+ _ensureDir();
390507
+ const records = [];
390508
+ try {
390509
+ const raw = fs45.readFileSync(path47.join(MEM_DIR, "memory.json"), "utf-8");
390510
+ const parsed = JSON.parse(raw);
390511
+ const items = Array.isArray(parsed) ? parsed : parsed.value ?? [];
390512
+ for (const item of items) {
390513
+ const v = item.value ?? {};
390514
+ const content = [
390515
+ v.goal ? `Goal: ${v.goal}` : "",
390516
+ v.result ? `Result: ${String(v.result).slice(0, 800)}` : "",
390517
+ v.role ? `Role: ${v.role}` : ""
390518
+ ].filter(Boolean).join("\n");
390519
+ if (!content) continue;
390520
+ records.push({
390521
+ timestamp: item.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
390522
+ type: item.tags?.includes("task") ? "interaction" : "observation",
390523
+ content,
390524
+ summary: _autoSummary(v.goal ?? v.result ?? content),
390525
+ tags: item.tags ?? []
390526
+ });
390527
+ }
390528
+ } catch {
390529
+ }
390530
+ try {
390531
+ const raw = fs45.readFileSync(
390532
+ path47.join(process.cwd(), "workspace", "conversation-memory.json"),
390533
+ "utf-8"
390534
+ );
390535
+ const parsed = JSON.parse(raw);
390536
+ const msgs = parsed.messages ?? [];
390537
+ for (const msg of msgs) {
390538
+ if (msg.role !== "assistant") continue;
390539
+ const content = String(msg.content ?? "").trim();
390540
+ if (content.length < 20) continue;
390541
+ records.push({
390542
+ timestamp: msg.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
390543
+ type: "interaction",
390544
+ content: content.slice(0, 1e3),
390545
+ summary: _autoSummary(content),
390546
+ sessionId: msg.sessionId,
390547
+ tags: ["conversation"]
390548
+ });
390549
+ }
390550
+ } catch {
390551
+ }
390552
+ try {
390553
+ const raw = fs45.readFileSync(path47.join(MEM_DIR, "MEMORY_INDEX.md"), "utf-8");
390554
+ const lines = raw.split("\n").filter((l2) => l2.startsWith("- "));
390555
+ for (const line of lines) {
390556
+ const cleaned = line.replace(/^-\s*/, "").trim();
390557
+ if (cleaned.length < 10) continue;
390558
+ records.push({
390559
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
390560
+ type: "fact",
390561
+ content: cleaned,
390562
+ summary: cleaned.slice(0, 100),
390563
+ tags: ["index"]
390564
+ });
390565
+ }
390566
+ } catch {
390567
+ }
390568
+ records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
390569
+ let count = 0;
390570
+ for (const rec of records) {
390571
+ const id = nextId();
390572
+ const record2 = { id, ...rec };
390573
+ appendRecord(record2);
390574
+ count++;
390575
+ }
390576
+ return count;
390577
+ }
390578
+ var fs45, path47, MEM_DIR, SEQUENCE_FILE, RECORDS_FILE;
390579
+ var init_memoryIds = __esm({
390580
+ "core/memoryIds.ts"() {
390581
+ fs45 = __toESM(require("fs"));
390582
+ path47 = __toESM(require("path"));
390583
+ MEM_DIR = path47.join(process.cwd(), "workspace", "memory");
390584
+ SEQUENCE_FILE = path47.join(MEM_DIR, "sequence.json");
390585
+ RECORDS_FILE = path47.join(MEM_DIR, "records.jsonl");
390586
+ }
390587
+ });
390588
+
390589
+ // core/slashAsTool.ts
390590
+ var slashAsTool_exports = {};
390591
+ __export(slashAsTool_exports, {
390592
+ SLASH_MIRROR_TOOL_NAMES: () => SLASH_MIRROR_TOOL_NAMES,
390593
+ registerSlashMirrorTools: () => registerSlashMirrorTools,
390594
+ toolMemoryForget: () => toolMemoryForget,
390595
+ toolMemoryStore: () => toolMemoryStore
390596
+ });
390597
+ function loadLessonsText() {
390598
+ try {
390599
+ if (import_fs40.default.existsSync(LESSONS_PATH2)) return import_fs40.default.readFileSync(LESSONS_PATH2, "utf-8").trim();
390600
+ } catch {
390601
+ }
390602
+ return "";
390603
+ }
390604
+ async function toolStatus(_2) {
390605
+ const uptimeSec = Math.floor(process.uptime());
390606
+ const ramMB = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
390607
+ const sessions = conversationMemory.getSessions().length;
390608
+ const lines = [
390609
+ "SYSTEM STATUS",
390610
+ `Uptime ${Math.floor(uptimeSec / 60)}m ${uptimeSec % 60}s`,
390611
+ `RAM ${ramMB} MB`,
390612
+ `Sessions ${sessions}`,
390613
+ `Platform ${import_os4.default.platform()} ${import_os4.default.arch()}`,
390614
+ `Node ${process.version}`
390615
+ ];
390616
+ return { success: true, output: lines.join("\n") };
390617
+ }
390618
+ async function toolAnalytics(_2) {
390619
+ const stats = learningMemory.getStats();
390620
+ const lines = [
390621
+ "LEARNING ANALYTICS",
390622
+ `Total tasks ${stats.total}`,
390623
+ `Success rate ${stats.successRate}%`,
390624
+ `Avg duration ${stats.avgDuration}ms`
390625
+ ];
390626
+ return { success: true, output: lines.join("\n") };
390627
+ }
390628
+ async function toolSpend(_2) {
390629
+ try {
390630
+ const summary = costTracker.getDailySummary();
390631
+ const byProvider = Object.entries(summary.byProvider || {}).map(([p, c]) => ` ${p}: $${c.toFixed(4)}`).join("\n");
390632
+ const lines = [
390633
+ `SPEND \u2014 ${summary.date}`,
390634
+ `Total $${summary.totalUSD.toFixed(4)}`,
390635
+ `User $${summary.userUSD.toFixed(4)}`,
390636
+ `System $${summary.systemUSD.toFixed(4)}`,
390637
+ byProvider ? `By provider:
390638
+ ${byProvider}` : ""
390639
+ ].filter(Boolean);
390640
+ return { success: true, output: lines.join("\n") };
390641
+ } catch {
390642
+ return { success: true, output: "Spend data unavailable." };
390643
+ }
390644
+ }
390645
+ async function toolMemoryShow(_2) {
390646
+ const facts = conversationMemory.getFacts();
390647
+ const history2 = conversationMemory.getRecentHistory();
390648
+ const lines = [
390649
+ "MEMORY FACTS",
390650
+ facts.lastFilesCreated.length ? `Files created : ${facts.lastFilesCreated.join(", ")}` : "",
390651
+ facts.lastSearchQueries.length ? `Last searches : ${facts.lastSearchQueries.join(", ")}` : "",
390652
+ facts.lastToolsUsed.length ? `Last tools : ${facts.lastToolsUsed.join(", ")}` : "",
390653
+ facts.mentionedEntities.length ? `Topics : ${facts.mentionedEntities.slice(-10).join(", ")}` : "",
390654
+ "",
390655
+ `Recent exchanges: ${history2.length}`,
390656
+ ...history2.slice(-3).map(
390657
+ (e) => e.userMessage ? ` User: ${e.userMessage.slice(0, 80)}` : ""
390658
+ ).filter(Boolean)
390659
+ ].filter((l2) => l2 !== void 0);
390660
+ return { success: true, output: lines.join("\n") };
390661
+ }
390662
+ async function toolLessons(_2) {
390663
+ const lessons = loadLessonsText();
390664
+ if (!lessons) return { success: true, output: "No lessons recorded yet." };
390665
+ return { success: true, output: `LESSONS (permanent failure rules):
390666
+ ${lessons}` };
390667
+ }
390668
+ async function toolSkillsList(_2) {
390669
+ const skills = skillLoader.loadAll();
390670
+ if (skills.length === 0) return { success: true, output: "No skills loaded." };
390671
+ const lines = [
390672
+ `SKILLS (${skills.length} loaded)`,
390673
+ ...skills.map((s) => ` ${s.name.padEnd(20)} ${s.description || ""}`)
390674
+ ];
390675
+ return { success: true, output: lines.join("\n") };
390676
+ }
390677
+ async function toolToolsList(_2) {
390678
+ const { TOOLS: TOOLS3 } = await Promise.resolve().then(() => (init_toolRegistry(), toolRegistry_exports));
390679
+ const names = Object.keys(TOOLS3).sort();
390680
+ return { success: true, output: `TOOLS (${names.length}):
390681
+ ${names.join(", ")}` };
390682
+ }
390683
+ async function toolWhoami(_2) {
390684
+ const cfg = loadConfig();
390685
+ const userName = cfg.userName || process.env.USERNAME || import_os4.default.userInfo().username || "User";
390686
+ const homeDir = import_os4.default.homedir();
390687
+ const lines = [
390688
+ "USER PROFILE",
390689
+ `Name ${userName}`,
390690
+ `Home ${homeDir}`,
390691
+ `Platform ${import_os4.default.platform()}`
390692
+ ];
390693
+ return { success: true, output: lines.join("\n") };
390694
+ }
390695
+ async function toolChannelsStatus(_2) {
390696
+ try {
390697
+ const cfg = loadConfig();
390698
+ const apis = cfg?.providers?.apis || [];
390699
+ const lines = [
390700
+ "PROVIDER CHANNELS",
390701
+ ...apis.map((api) => {
390702
+ const key2 = String(api.key || "");
390703
+ const hasKey = key2.startsWith("env:") ? !!(process.env[key2.replace("env:", "")] || "").trim() : key2.trim().length > 0;
390704
+ const status = !api.enabled ? "disabled" : api.rateLimited ? "rate-limited" : hasKey ? "active" : "no key";
390705
+ return ` ${(api.name || api.provider || "").padEnd(20)} ${api.model || ""} [${status}]`;
390706
+ })
390707
+ ];
390708
+ return { success: true, output: lines.join("\n") };
390709
+ } catch {
390710
+ return { success: true, output: "Provider status unavailable." };
390711
+ }
390712
+ }
390713
+ async function toolMemoryStore(input) {
390714
+ const fact = String(
390715
+ input?.fact || input?.content || input?.text || input?.preference || input?.value || input?.memory || input?.note || input?.data || input?.information || input?.detail || input?.message || input?.entry || input?.record || (input && typeof input === "object" ? Object.values(input).find((v) => typeof v === "string" && v.trim().length > 0) : "") || ""
390716
+ ).trim();
390717
+ if (!fact) return { success: false, output: 'No fact provided. Pass { fact: "the thing to remember" }' };
390718
+ const record2 = assignId({
390719
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
390720
+ type: input?.type ?? "fact",
390721
+ content: fact,
390722
+ summary: fact.slice(0, 100),
390723
+ tags: Array.isArray(input?.tags) ? input.tags : []
390724
+ });
390725
+ return { success: true, output: `Stored as ${record2.id}: ${record2.summary}` };
390726
+ }
390727
+ async function toolMemoryForget(input) {
390728
+ const keyword = String(
390729
+ input?.fact || input?.keyword || input?.content || input?.text || input?.query || input?.topic || input?.subject || (input && typeof input === "object" ? Object.values(input).find((v) => typeof v === "string" && v.trim().length > 0) : "") || ""
390730
+ ).trim().toLowerCase();
390731
+ if (!keyword)
390732
+ return { success: false, output: 'No keyword provided. Pass { fact: "thing to forget" }' };
390733
+ const removed = removeRecords(
390734
+ (r) => r.content.toLowerCase().includes(keyword) || r.summary.toLowerCase().includes(keyword)
390735
+ );
390736
+ if (removed === 0)
390737
+ return { success: true, output: `No memory entries matched "${keyword}".` };
390738
+ return { success: true, output: `Removed ${removed} memory entry(s) matching "${keyword}".` };
390739
+ }
390740
+ async function toolGoals(_2) {
390741
+ const summary = getActiveGoalsSummary();
390742
+ return { success: true, output: summary ? `ACTIVE GOALS:
390743
+ ${summary}` : "No active goals." };
390744
+ }
390745
+ function registerSlashMirrorTools() {
390746
+ const isDebug = (process.env.AIDEN_LOG_LEVEL || "info") === "debug";
390747
+ for (const { name, description, fn } of MIRROR_TOOLS) {
390748
+ registerExternalTool(name, fn, "slash-mirror");
390749
+ if (isDebug) {
390750
+ console.log("[SlashAsTool] Registered mirror tool: " + name + " \u2014 " + description);
390751
+ }
390752
+ }
390753
+ if (!isDebug) {
390754
+ console.log("[SlashAsTool] Registered " + MIRROR_TOOLS.length + " mirror tools (AIDEN_LOG_LEVEL=debug for detail)");
390755
+ }
390756
+ }
390757
+ var import_fs40, import_path42, import_os4, LESSONS_PATH2, MIRROR_TOOLS, SLASH_MIRROR_TOOL_NAMES;
390758
+ var init_slashAsTool = __esm({
390759
+ "core/slashAsTool.ts"() {
390760
+ import_fs40 = __toESM(require("fs"));
390761
+ import_path42 = __toESM(require("path"));
390762
+ import_os4 = __toESM(require("os"));
390763
+ init_toolRegistry();
390764
+ init_memoryIds();
390765
+ init_conversationMemory();
390766
+ init_learningMemory();
390767
+ init_skillLoader();
390768
+ init_costTracker();
390769
+ init_goalTracker();
390770
+ init_providers();
390771
+ LESSONS_PATH2 = import_path42.default.join(process.cwd(), "workspace", "LESSONS.md");
390772
+ MIRROR_TOOLS = [
390773
+ { name: "status", description: "Show system status: uptime, RAM, session count", fn: toolStatus },
390774
+ { name: "analytics", description: "Show learning analytics: task count, success rate", fn: toolAnalytics },
390775
+ { name: "spend", description: "Show today's token cost and spend by provider", fn: toolSpend },
390776
+ { name: "memory_show", description: "Show conversation memory facts and recent history", fn: toolMemoryShow },
390777
+ { name: "memory_store", description: 'Persist a fact or preference to permanent memory (records.jsonl) right now. Pass { fact: "..." }', fn: toolMemoryStore },
390778
+ { name: "memory_forget", description: 'Remove a fact or preference from permanent memory (records.jsonl). Pass { fact: "thing to forget" }', fn: toolMemoryForget },
390779
+ { name: "lessons", description: "Show permanent failure rules learned from past tasks", fn: toolLessons },
390780
+ { name: "skills_list", description: "List all loaded skills with descriptions", fn: toolSkillsList },
390781
+ { name: "tools_list", description: "List all registered tool names", fn: toolToolsList },
390782
+ { name: "whoami", description: "Show current user profile: name, home dir, platform", fn: toolWhoami },
390783
+ { name: "channels_status", description: "Show provider channel status: active, disabled, no-key", fn: toolChannelsStatus },
390784
+ { name: "goals", description: "Show currently active goals", fn: toolGoals }
390785
+ ];
390786
+ SLASH_MIRROR_TOOL_NAMES = MIRROR_TOOLS.map((t) => t.name);
390787
+ }
390788
+ });
390789
+
390374
390790
  // core/clarifyBus.ts
390375
390791
  var clarifyBus_exports = {};
390376
390792
  __export(clarifyBus_exports, {
@@ -390500,15 +390916,15 @@ __export(cronManager_exports, {
390500
390916
  });
390501
390917
  function save() {
390502
390918
  try {
390503
- if (!fs45.existsSync(DATA_DIR)) fs45.mkdirSync(DATA_DIR, { recursive: true });
390504
- fs45.writeFileSync(DATA_FILE, JSON.stringify(Array.from(jobs.values()), null, 2), "utf8");
390919
+ if (!fs47.existsSync(DATA_DIR)) fs47.mkdirSync(DATA_DIR, { recursive: true });
390920
+ fs47.writeFileSync(DATA_FILE, JSON.stringify(Array.from(jobs.values()), null, 2), "utf8");
390505
390921
  } catch {
390506
390922
  }
390507
390923
  }
390508
390924
  function loadJobs() {
390509
390925
  try {
390510
- if (!fs45.existsSync(DATA_FILE)) return;
390511
- const data = JSON.parse(fs45.readFileSync(DATA_FILE, "utf8"));
390926
+ if (!fs47.existsSync(DATA_FILE)) return;
390927
+ const data = JSON.parse(fs47.readFileSync(DATA_FILE, "utf8"));
390512
390928
  for (const job of data) {
390513
390929
  jobs.set(job.id, job);
390514
390930
  const num = parseInt(job.id, 10);
@@ -390626,17 +391042,17 @@ async function triggerJob(id) {
390626
391042
  return false;
390627
391043
  }
390628
391044
  }
390629
- var fs45, path47, os4, jobs, timers, jobSeq, DATA_DIR, DATA_FILE;
391045
+ var fs47, path49, os5, jobs, timers, jobSeq, DATA_DIR, DATA_FILE;
390630
391046
  var init_cronManager = __esm({
390631
391047
  "core/cronManager.ts"() {
390632
- fs45 = __toESM(require("fs"));
390633
- path47 = __toESM(require("path"));
390634
- os4 = __toESM(require("os"));
391048
+ fs47 = __toESM(require("fs"));
391049
+ path49 = __toESM(require("path"));
391050
+ os5 = __toESM(require("os"));
390635
391051
  jobs = /* @__PURE__ */ new Map();
390636
391052
  timers = /* @__PURE__ */ new Map();
390637
391053
  jobSeq = 1;
390638
- DATA_DIR = path47.join(os4.homedir(), ".aiden");
390639
- DATA_FILE = path47.join(DATA_DIR, "cron_jobs.json");
391054
+ DATA_DIR = path49.join(os5.homedir(), ".aiden");
391055
+ DATA_FILE = path49.join(DATA_DIR, "cron_jobs.json");
390640
391056
  }
390641
391057
  });
390642
391058
 
@@ -390662,10 +391078,10 @@ async function analyzeImage(imageSource, prompt = "Describe this image in detail
390662
391078
  let base64Data = "";
390663
391079
  let mediaType = "image/jpeg";
390664
391080
  if (!isUrl) {
390665
- const absPath = path48.isAbsolute(imageSource) ? imageSource : path48.resolve(process.cwd(), imageSource);
390666
- const buf = fs46.readFileSync(absPath);
391081
+ const absPath = path50.isAbsolute(imageSource) ? imageSource : path50.resolve(process.cwd(), imageSource);
391082
+ const buf = fs48.readFileSync(absPath);
390667
391083
  base64Data = buf.toString("base64");
390668
- mediaType = extToMediaType(path48.extname(absPath));
391084
+ mediaType = extToMediaType(path50.extname(absPath));
390669
391085
  }
390670
391086
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
390671
391087
  if (anthropicKey) {
@@ -390745,11 +391161,11 @@ async function analyzeImage(imageSource, prompt = "Describe this image in detail
390745
391161
  throw new Error(`vision_analyze: all providers exhausted. ${e.message}`);
390746
391162
  }
390747
391163
  }
390748
- var fs46, path48;
391164
+ var fs48, path50;
390749
391165
  var init_visionAnalyze = __esm({
390750
391166
  "core/visionAnalyze.ts"() {
390751
- fs46 = __toESM(require("fs"));
390752
- path48 = __toESM(require("path"));
391167
+ fs48 = __toESM(require("fs"));
391168
+ path50 = __toESM(require("path"));
390753
391169
  init_axios2();
390754
391170
  }
390755
391171
  });
@@ -390757,9 +391173,9 @@ var init_visionAnalyze = __esm({
390757
391173
  // core/dreamEngine.ts
390758
391174
  function acquireLock() {
390759
391175
  try {
390760
- import_fs40.default.mkdirSync(import_path42.default.dirname(LOCK_FILE), { recursive: true });
390761
- if (import_fs40.default.existsSync(LOCK_FILE)) {
390762
- const raw = JSON.parse(import_fs40.default.readFileSync(LOCK_FILE, "utf-8"));
391176
+ import_fs41.default.mkdirSync(import_path43.default.dirname(LOCK_FILE), { recursive: true });
391177
+ if (import_fs41.default.existsSync(LOCK_FILE)) {
391178
+ const raw = JSON.parse(import_fs41.default.readFileSync(LOCK_FILE, "utf-8"));
390763
391179
  const alive = isPidAlive(raw.pid);
390764
391180
  if (alive) {
390765
391181
  console.log(`[DreamEngine] Lock held by PID ${raw.pid} \u2014 skipping`);
@@ -390768,7 +391184,7 @@ function acquireLock() {
390768
391184
  console.log(`[DreamEngine] Stale lock (PID ${raw.pid} dead) \u2014 stealing`);
390769
391185
  }
390770
391186
  const data = { pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
390771
- import_fs40.default.writeFileSync(LOCK_FILE, JSON.stringify(data));
391187
+ import_fs41.default.writeFileSync(LOCK_FILE, JSON.stringify(data));
390772
391188
  return true;
390773
391189
  } catch {
390774
391190
  return false;
@@ -390778,9 +391194,9 @@ function releaseLock(prevMtime) {
390778
391194
  try {
390779
391195
  if (prevMtime !== void 0) {
390780
391196
  const now = Date.now() / 1e3;
390781
- import_fs40.default.utimesSync(LOCK_FILE, now, now);
391197
+ import_fs41.default.utimesSync(LOCK_FILE, now, now);
390782
391198
  } else {
390783
- import_fs40.default.unlinkSync(LOCK_FILE);
391199
+ import_fs41.default.unlinkSync(LOCK_FILE);
390784
391200
  }
390785
391201
  } catch {
390786
391202
  }
@@ -390795,8 +391211,8 @@ function isPidAlive(pid) {
390795
391211
  }
390796
391212
  function getLockMtime() {
390797
391213
  try {
390798
- if (!import_fs40.default.existsSync(LOCK_FILE)) return 0;
390799
- return import_fs40.default.statSync(LOCK_FILE).mtimeMs;
391214
+ if (!import_fs41.default.existsSync(LOCK_FILE)) return 0;
391215
+ return import_fs41.default.statSync(LOCK_FILE).mtimeMs;
390800
391216
  } catch {
390801
391217
  return 0;
390802
391218
  }
@@ -390808,11 +391224,11 @@ function checkTimeGate(lockMtime) {
390808
391224
  }
390809
391225
  function checkSessionGate(lockMtime) {
390810
391226
  try {
390811
- if (!import_fs40.default.existsSync(SESSIONS_DIR3)) return false;
391227
+ if (!import_fs41.default.existsSync(SESSIONS_DIR3)) return false;
390812
391228
  const cutoff = lockMtime || 0;
390813
- const newSessions = import_fs40.default.readdirSync(SESSIONS_DIR3).filter((f) => f.endsWith(".md")).filter((f) => {
391229
+ const newSessions = import_fs41.default.readdirSync(SESSIONS_DIR3).filter((f) => f.endsWith(".md")).filter((f) => {
390814
391230
  try {
390815
- return import_fs40.default.statSync(import_path42.default.join(SESSIONS_DIR3, f)).mtimeMs > cutoff;
391231
+ return import_fs41.default.statSync(import_path43.default.join(SESSIONS_DIR3, f)).mtimeMs > cutoff;
390816
391232
  } catch {
390817
391233
  return false;
390818
391234
  }
@@ -390828,8 +391244,8 @@ function allGatesPass() {
390828
391244
  }
390829
391245
  async function phaseOrient() {
390830
391246
  try {
390831
- const indexContent = import_fs40.default.existsSync(INDEX_PATH2) ? import_fs40.default.readFileSync(INDEX_PATH2, "utf-8") : "(empty)";
390832
- const memFiles = import_fs40.default.existsSync(MEMORY_DIR3) ? import_fs40.default.readdirSync(MEMORY_DIR3).filter((f) => f.endsWith(".md") && f !== "MEMORY_INDEX.md") : [];
391247
+ const indexContent = import_fs41.default.existsSync(INDEX_PATH2) ? import_fs41.default.readFileSync(INDEX_PATH2, "utf-8") : "(empty)";
391248
+ const memFiles = import_fs41.default.existsSync(MEMORY_DIR3) ? import_fs41.default.readdirSync(MEMORY_DIR3).filter((f) => f.endsWith(".md") && f !== "MEMORY_INDEX.md") : [];
390833
391249
  return `MEMORY DIRECTORY (${memFiles.length} files):
390834
391250
  ${memFiles.join("\n")}
390835
391251
 
@@ -390841,10 +391257,10 @@ ${indexContent.slice(0, 2e3)}`;
390841
391257
  }
390842
391258
  async function phaseGather(lockMtime) {
390843
391259
  try {
390844
- if (!import_fs40.default.existsSync(SESSIONS_DIR3)) return "(no sessions)";
390845
- const recentSessions = import_fs40.default.readdirSync(SESSIONS_DIR3).filter((f) => f.endsWith(".md")).filter((f) => {
391260
+ if (!import_fs41.default.existsSync(SESSIONS_DIR3)) return "(no sessions)";
391261
+ const recentSessions = import_fs41.default.readdirSync(SESSIONS_DIR3).filter((f) => f.endsWith(".md")).filter((f) => {
390846
391262
  try {
390847
- return import_fs40.default.statSync(import_path42.default.join(SESSIONS_DIR3, f)).mtimeMs > lockMtime;
391263
+ return import_fs41.default.statSync(import_path43.default.join(SESSIONS_DIR3, f)).mtimeMs > lockMtime;
390848
391264
  } catch {
390849
391265
  return false;
390850
391266
  }
@@ -390852,7 +391268,7 @@ async function phaseGather(lockMtime) {
390852
391268
  if (recentSessions.length === 0) return "(no new sessions)";
390853
391269
  const excerpts = recentSessions.map((f) => {
390854
391270
  try {
390855
- const content = import_fs40.default.readFileSync(import_path42.default.join(SESSIONS_DIR3, f), "utf-8");
391271
+ const content = import_fs41.default.readFileSync(import_path43.default.join(SESSIONS_DIR3, f), "utf-8");
390856
391272
  return `=== ${f} ===
390857
391273
  ${content.slice(0, 800)}`;
390858
391274
  } catch {
@@ -390902,11 +391318,11 @@ Rules:
390902
391318
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
390903
391319
  for (const item of items) {
390904
391320
  if (!item.filename || !item.content) continue;
390905
- const filePath = import_path42.default.join(MEMORY_DIR3, item.filename);
391321
+ const filePath = import_path43.default.join(MEMORY_DIR3, item.filename);
390906
391322
  let created = now;
390907
- if (import_fs40.default.existsSync(filePath)) {
391323
+ if (import_fs41.default.existsSync(filePath)) {
390908
391324
  try {
390909
- const existing = import_fs40.default.readFileSync(filePath, "utf-8");
391325
+ const existing = import_fs41.default.readFileSync(filePath, "utf-8");
390910
391326
  const m2 = existing.match(/^created:\s*(.+)$/m);
390911
391327
  if (m2) created = m2[1].trim();
390912
391328
  } catch {
@@ -390922,7 +391338,7 @@ updated: ${now}
390922
391338
  ${item.content.trim()}
390923
391339
  `;
390924
391340
  try {
390925
- import_fs40.default.writeFileSync(filePath, fileContent, "utf-8");
391341
+ import_fs41.default.writeFileSync(filePath, fileContent, "utf-8");
390926
391342
  filesUpdated++;
390927
391343
  } catch {
390928
391344
  }
@@ -390935,10 +391351,10 @@ ${item.content.trim()}
390935
391351
  }
390936
391352
  async function phasePrune(filesUpdated) {
390937
391353
  try {
390938
- if (!import_fs40.default.existsSync(MEMORY_DIR3)) return;
390939
- const files = import_fs40.default.readdirSync(MEMORY_DIR3).filter((f) => f.endsWith(".md") && f !== "MEMORY_INDEX.md").map((f) => {
391354
+ if (!import_fs41.default.existsSync(MEMORY_DIR3)) return;
391355
+ const files = import_fs41.default.readdirSync(MEMORY_DIR3).filter((f) => f.endsWith(".md") && f !== "MEMORY_INDEX.md").map((f) => {
390940
391356
  try {
390941
- const content = import_fs40.default.readFileSync(import_path42.default.join(MEMORY_DIR3, f), "utf-8");
391357
+ const content = import_fs41.default.readFileSync(import_path43.default.join(MEMORY_DIR3, f), "utf-8");
390942
391358
  const titleM = content.match(/^title:\s*(.+)$/m);
390943
391359
  const sumM = content.match(/---\n+([\s\S]+?)(?:\n\n|$)/);
390944
391360
  const title = titleM ? titleM[1].trim() : f.replace(".md", "");
@@ -390948,7 +391364,7 @@ async function phasePrune(filesUpdated) {
390948
391364
  return null;
390949
391365
  }
390950
391366
  }).filter((l2) => l2 !== null).slice(0, 100);
390951
- import_fs40.default.writeFileSync(INDEX_PATH2, files.join("\n") + "\n", "utf-8");
391367
+ import_fs41.default.writeFileSync(INDEX_PATH2, files.join("\n") + "\n", "utf-8");
390952
391368
  console.log(`[DreamEngine] Pruned index to ${files.length} entries (${filesUpdated} files updated)`);
390953
391369
  } catch (e) {
390954
391370
  console.error("[DreamEngine] Prune phase failed:", e.message);
@@ -390966,7 +391382,7 @@ async function runDream() {
390966
391382
  let sessionsReviewed = 0;
390967
391383
  let filesUpdated = 0;
390968
391384
  try {
390969
- import_fs40.default.mkdirSync(MEMORY_DIR3, { recursive: true });
391385
+ import_fs41.default.mkdirSync(MEMORY_DIR3, { recursive: true });
390970
391386
  console.log("[DreamEngine] Phase 1: Orient");
390971
391387
  const orientData = await phaseOrient();
390972
391388
  console.log("[DreamEngine] Phase 2: Gather");
@@ -390996,9 +391412,9 @@ async function runDream() {
390996
391412
  try {
390997
391413
  if (prevMtime > 0) {
390998
391414
  const t = prevMtime / 1e3;
390999
- import_fs40.default.utimesSync(LOCK_FILE, t, t);
391415
+ import_fs41.default.utimesSync(LOCK_FILE, t, t);
391000
391416
  } else {
391001
- import_fs40.default.unlinkSync(LOCK_FILE);
391417
+ import_fs41.default.unlinkSync(LOCK_FILE);
391002
391418
  }
391003
391419
  } catch {
391004
391420
  }
@@ -391008,17 +391424,17 @@ function checkAndRunDream() {
391008
391424
  if (!allGatesPass()) return;
391009
391425
  runDream().catch((e) => console.error("[DreamEngine] Unhandled error:", e.message));
391010
391426
  }
391011
- var import_fs40, import_path42, LOCK_FILE, MEMORY_DIR3, SESSIONS_DIR3, INDEX_PATH2, GATE_HOURS, GATE_SESSIONS;
391427
+ var import_fs41, import_path43, LOCK_FILE, MEMORY_DIR3, SESSIONS_DIR3, INDEX_PATH2, GATE_HOURS, GATE_SESSIONS;
391012
391428
  var init_dreamEngine = __esm({
391013
391429
  "core/dreamEngine.ts"() {
391014
- import_fs40 = __toESM(require("fs"));
391015
- import_path42 = __toESM(require("path"));
391430
+ import_fs41 = __toESM(require("fs"));
391431
+ import_path43 = __toESM(require("path"));
391016
391432
  init_auxiliaryClient();
391017
391433
  init_auditTrail();
391018
- LOCK_FILE = import_path42.default.join(process.cwd(), "workspace", "dream.lock");
391019
- MEMORY_DIR3 = import_path42.default.join(process.cwd(), "workspace", "memory");
391020
- SESSIONS_DIR3 = import_path42.default.join(process.cwd(), "workspace", "sessions");
391021
- INDEX_PATH2 = import_path42.default.join(MEMORY_DIR3, "MEMORY_INDEX.md");
391434
+ LOCK_FILE = import_path43.default.join(process.cwd(), "workspace", "dream.lock");
391435
+ MEMORY_DIR3 = import_path43.default.join(process.cwd(), "workspace", "memory");
391436
+ SESSIONS_DIR3 = import_path43.default.join(process.cwd(), "workspace", "sessions");
391437
+ INDEX_PATH2 = import_path43.default.join(MEMORY_DIR3, "MEMORY_INDEX.md");
391022
391438
  GATE_HOURS = 24;
391023
391439
  GATE_SESSIONS = 5;
391024
391440
  }
@@ -391031,11 +391447,11 @@ __export(patternDetector_exports, {
391031
391447
  getPatternSummary: () => getPatternSummary
391032
391448
  });
391033
391449
  async function detectPatterns() {
391034
- if (!(0, import_fs41.existsSync)(SESSION_DIR)) return [];
391450
+ if (!(0, import_fs42.existsSync)(SESSION_DIR)) return [];
391035
391451
  const messages = [];
391036
- for (const file of (0, import_fs41.readdirSync)(SESSION_DIR).slice(-30)) {
391452
+ for (const file of (0, import_fs42.readdirSync)(SESSION_DIR).slice(-30)) {
391037
391453
  try {
391038
- const content = (0, import_fs41.readFileSync)((0, import_path43.join)(SESSION_DIR, file), "utf8");
391454
+ const content = (0, import_fs42.readFileSync)((0, import_path44.join)(SESSION_DIR, file), "utf8");
391039
391455
  if (file.endsWith(".json")) {
391040
391456
  const session = JSON.parse(content);
391041
391457
  (session.messages ?? []).filter((m2) => m2.role === "user").forEach((m2) => messages.push({
@@ -391071,12 +391487,12 @@ function getPatternSummary(patterns) {
391071
391487
  if (patterns.length === 0) return "";
391072
391488
  return "Detected usage patterns:\n" + patterns.slice(0, 3).map((p) => `- ${p.description} (${p.frequency})`).join("\n");
391073
391489
  }
391074
- var import_fs41, import_path43, SESSION_DIR;
391490
+ var import_fs42, import_path44, SESSION_DIR;
391075
391491
  var init_patternDetector = __esm({
391076
391492
  "core/patternDetector.ts"() {
391077
- import_fs41 = require("fs");
391078
- import_path43 = require("path");
391079
- SESSION_DIR = (0, import_path43.join)(process.cwd(), "workspace", "sessions");
391493
+ import_fs42 = require("fs");
391494
+ import_path44 = require("path");
391495
+ SESSION_DIR = (0, import_path44.join)(process.cwd(), "workspace", "sessions");
391080
391496
  }
391081
391497
  });
391082
391498
 
@@ -391094,8 +391510,8 @@ __export(scheduler_exports, {
391094
391510
  function loadHeartbeatConfig() {
391095
391511
  const isDebug = (process.env.AIDEN_LOG_LEVEL || "info") === "debug";
391096
391512
  try {
391097
- if (!import_fs42.default.existsSync(HEARTBEAT_PATH)) return;
391098
- const content = import_fs42.default.readFileSync(HEARTBEAT_PATH, "utf-8");
391513
+ if (!import_fs43.default.existsSync(HEARTBEAT_PATH)) return;
391514
+ const content = import_fs43.default.readFileSync(HEARTBEAT_PATH, "utf-8");
391099
391515
  const sections = content.split(/^## /m).slice(1);
391100
391516
  let loaded = 0;
391101
391517
  for (const section of sections) {
@@ -391190,8 +391606,8 @@ function cronMatchesNow(cronExpr) {
391190
391606
  }
391191
391607
  function _rsave() {
391192
391608
  try {
391193
- if (!import_fs42.default.existsSync(_RDATA_DIR)) import_fs42.default.mkdirSync(_RDATA_DIR, { recursive: true });
391194
- import_fs42.default.writeFileSync(_RDATA_FILE, JSON.stringify(Array.from(_reminders.values()), null, 2), "utf8");
391609
+ if (!import_fs43.default.existsSync(_RDATA_DIR)) import_fs43.default.mkdirSync(_RDATA_DIR, { recursive: true });
391610
+ import_fs43.default.writeFileSync(_RDATA_FILE, JSON.stringify(Array.from(_reminders.values()), null, 2), "utf8");
391195
391611
  } catch {
391196
391612
  }
391197
391613
  }
@@ -391249,11 +391665,11 @@ function cancelReminder(id) {
391249
391665
  }
391250
391666
  function initReminderScheduler() {
391251
391667
  try {
391252
- if (!import_fs42.default.existsSync(_RDATA_FILE)) {
391668
+ if (!import_fs43.default.existsSync(_RDATA_FILE)) {
391253
391669
  console.log("[Reminders] No saved reminders");
391254
391670
  return;
391255
391671
  }
391256
- const stored = JSON.parse(import_fs42.default.readFileSync(_RDATA_FILE, "utf8"));
391672
+ const stored = JSON.parse(import_fs43.default.readFileSync(_RDATA_FILE, "utf8"));
391257
391673
  const now = Date.now();
391258
391674
  let loaded = 0;
391259
391675
  for (const r of stored) {
@@ -391273,18 +391689,18 @@ function initReminderScheduler() {
391273
391689
  console.error("[Reminders] Init error:", e.message);
391274
391690
  }
391275
391691
  }
391276
- var import_fs42, import_path44, os5, TASKS_PATH, HEARTBEAT_PATH, Scheduler, scheduler, _reminders, _rtimers, _rseq, _RDATA_DIR, _RDATA_FILE;
391692
+ var import_fs43, import_path45, os6, TASKS_PATH, HEARTBEAT_PATH, Scheduler, scheduler, _reminders, _rtimers, _rseq, _RDATA_DIR, _RDATA_FILE;
391277
391693
  var init_scheduler = __esm({
391278
391694
  "core/scheduler.ts"() {
391279
- import_fs42 = __toESM(require("fs"));
391280
- import_path44 = __toESM(require("path"));
391695
+ import_fs43 = __toESM(require("fs"));
391696
+ import_path45 = __toESM(require("path"));
391281
391697
  init_morningBriefing();
391282
391698
  init_dreamEngine();
391283
391699
  init_goalTracker();
391284
391700
  init_patternDetector();
391285
- os5 = __toESM(require("os"));
391286
- TASKS_PATH = import_path44.default.join(process.cwd(), "workspace", "scheduled-tasks.json");
391287
- HEARTBEAT_PATH = import_path44.default.join(process.cwd(), "workspace", "HEARTBEAT.md");
391701
+ os6 = __toESM(require("os"));
391702
+ TASKS_PATH = import_path45.default.join(process.cwd(), "workspace", "scheduled-tasks.json");
391703
+ HEARTBEAT_PATH = import_path45.default.join(process.cwd(), "workspace", "HEARTBEAT.md");
391288
391704
  Scheduler = class _Scheduler {
391289
391705
  constructor() {
391290
391706
  this.tasks = [];
@@ -391351,8 +391767,8 @@ var init_scheduler = __esm({
391351
391767
  const ACTIVE_START = 8;
391352
391768
  const ACTIVE_END = 23;
391353
391769
  if (hour < ACTIVE_START || hour >= ACTIVE_END) return;
391354
- if (!import_fs42.default.existsSync(HEARTBEAT_PATH)) return;
391355
- const checklist = import_fs42.default.readFileSync(HEARTBEAT_PATH, "utf-8").trim();
391770
+ if (!import_fs43.default.existsSync(HEARTBEAT_PATH)) return;
391771
+ const checklist = import_fs43.default.readFileSync(HEARTBEAT_PATH, "utf-8").trim();
391356
391772
  if (!checklist) return;
391357
391773
  let heartbeatPrompt = checklist;
391358
391774
  const goalsSummary = getActiveGoalsSummary();
@@ -391493,8 +391909,8 @@ var init_scheduler = __esm({
391493
391909
  }
391494
391910
  load() {
391495
391911
  try {
391496
- if (!import_fs42.default.existsSync(TASKS_PATH)) return;
391497
- const raw = import_fs42.default.readFileSync(TASKS_PATH, "utf-8");
391912
+ if (!import_fs43.default.existsSync(TASKS_PATH)) return;
391913
+ const raw = import_fs43.default.readFileSync(TASKS_PATH, "utf-8");
391498
391914
  this.tasks = JSON.parse(raw);
391499
391915
  const enabled = this.tasks.filter((t) => t.enabled);
391500
391916
  enabled.forEach((t) => this.scheduleTask(t));
@@ -391508,8 +391924,8 @@ var init_scheduler = __esm({
391508
391924
  }
391509
391925
  save() {
391510
391926
  try {
391511
- import_fs42.default.mkdirSync(import_path44.default.dirname(TASKS_PATH), { recursive: true });
391512
- import_fs42.default.writeFileSync(TASKS_PATH, JSON.stringify(this.tasks, null, 2));
391927
+ import_fs43.default.mkdirSync(import_path45.default.dirname(TASKS_PATH), { recursive: true });
391928
+ import_fs43.default.writeFileSync(TASKS_PATH, JSON.stringify(this.tasks, null, 2));
391513
391929
  } catch (e) {
391514
391930
  console.warn(`[Scheduler] Failed to save tasks: ${e.message}`);
391515
391931
  }
@@ -391519,8 +391935,8 @@ var init_scheduler = __esm({
391519
391935
  _reminders = /* @__PURE__ */ new Map();
391520
391936
  _rtimers = /* @__PURE__ */ new Map();
391521
391937
  _rseq = 1;
391522
- _RDATA_DIR = import_path44.default.join(os5.homedir(), ".aiden");
391523
- _RDATA_FILE = import_path44.default.join(_RDATA_DIR, "scheduled.json");
391938
+ _RDATA_DIR = import_path45.default.join(os6.homedir(), ".aiden");
391939
+ _RDATA_FILE = import_path45.default.join(_RDATA_DIR, "scheduled.json");
391524
391940
  }
391525
391941
  });
391526
391942
 
@@ -391601,15 +392017,15 @@ function isCommandAllowed(cmd) {
391601
392017
  return { allowed: false, needsApproval: true };
391602
392018
  }
391603
392019
  function cleanOldBrowserProfiles() {
391604
- if (!import_fs43.default.existsSync(BROWSER_DATA_DIR)) return;
392020
+ if (!import_fs44.default.existsSync(BROWSER_DATA_DIR)) return;
391605
392021
  const cutoff = Date.now() - 24 * 60 * 60 * 1e3;
391606
392022
  try {
391607
- for (const entry of import_fs43.default.readdirSync(BROWSER_DATA_DIR)) {
391608
- const fullPath = import_path45.default.join(BROWSER_DATA_DIR, entry);
392023
+ for (const entry of import_fs44.default.readdirSync(BROWSER_DATA_DIR)) {
392024
+ const fullPath = import_path46.default.join(BROWSER_DATA_DIR, entry);
391609
392025
  try {
391610
- const stat = import_fs43.default.statSync(fullPath);
392026
+ const stat = import_fs44.default.statSync(fullPath);
391611
392027
  if (stat.mtimeMs < cutoff) {
391612
- import_fs43.default.rmSync(fullPath, { recursive: true, force: true });
392028
+ import_fs44.default.rmSync(fullPath, { recursive: true, force: true });
391613
392029
  console.log(`[Browser] Cleaned old profile: ${entry}`);
391614
392030
  }
391615
392031
  } catch {
@@ -391639,15 +392055,15 @@ function setProgressEmitter(fn) {
391639
392055
  _emitProgress = fn;
391640
392056
  }
391641
392057
  function resolveWritePath(rawPath, opts) {
391642
- const home = opts?.home ?? import_os4.default.homedir();
392058
+ const home = opts?.home ?? import_os5.default.homedir();
391643
392059
  const cwd = opts?.cwd ?? process.cwd();
391644
- const user = process.env.USERNAME || process.env.USER || import_os4.default.userInfo().username || "User";
391645
- let p = rawPath.replace(/^~[\/\\]/, home + import_path45.default.sep).replace(/^Desktop[\/\\]/i, import_path45.default.join(home, "Desktop") + import_path45.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${user}/`);
391646
- const resolved = /^[A-Za-z]:[/\\]/.test(p) || p.startsWith("/") ? p : import_path45.default.join(cwd, p);
392060
+ const user = process.env.USERNAME || process.env.USER || import_os5.default.userInfo().username || "User";
392061
+ let p = rawPath.replace(/^~[\/\\]/, home + import_path46.default.sep).replace(/^Desktop[\/\\]/i, import_path46.default.join(home, "Desktop") + import_path46.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${user}/`);
392062
+ const resolved = /^[A-Za-z]:[/\\]/.test(p) || p.startsWith("/") ? p : import_path46.default.join(cwd, p);
391647
392063
  const allowedRoots = [
391648
392064
  cwd,
391649
- import_path45.default.join(home, "Desktop"),
391650
- import_path45.default.join(home, "Documents")
392065
+ import_path46.default.join(home, "Desktop"),
392066
+ import_path46.default.join(home, "Documents")
391651
392067
  ];
391652
392068
  const norm = (s) => s.toLowerCase().replace(/\//g, "\\").replace(/\\$/, "");
391653
392069
  const nr = norm(resolved);
@@ -391882,14 +392298,14 @@ function getToolsForCategories(categories) {
391882
392298
  }
391883
392299
  return Array.from(tools);
391884
392300
  }
391885
- var import_child_process13, import_util10, import_fs43, import_path45, import_os4, import_minimatch2, execAsync8, PROTECTED_FILES2, DENIED_PATHS, DENIED_COMMANDS, activeWatchers, SHELL_DANGEROUS_PATTERNS, PROTECTED_PATH_PATTERNS, CODE_DESTRUCTIVE_NODE, CODE_DESTRUCTIVE_PYTHON, SHELL_ALLOWLIST, BROWSER_DATA_DIR, TOOL_TIMEOUTS, _emitProgress, APP_ALIASES, DISPLAY_ALIASES, TOOLS, externalTools, externalToolsMeta, _generation, TOOL_DESCRIPTIONS, TOOL_NAMES_ONLY, TOOL_TIERS, TOOL_CATEGORIES, TOOL_REGISTRY, registryNames, registryDescriptions, registryTiers, registryCategories, registryTimeouts, registryAllowedTools, registryValidTools, registryNoRetrySet, registryParallelSafeSet, registrySequentialOnlySet, registryMcpSafeList, registryMcpDestructiveList;
392301
+ var import_child_process13, import_util10, import_fs44, import_path46, import_os5, import_minimatch2, execAsync8, PROTECTED_FILES2, DENIED_PATHS, DENIED_COMMANDS, activeWatchers, SHELL_DANGEROUS_PATTERNS, PROTECTED_PATH_PATTERNS, CODE_DESTRUCTIVE_NODE, CODE_DESTRUCTIVE_PYTHON, SHELL_ALLOWLIST, BROWSER_DATA_DIR, TOOL_TIMEOUTS, _emitProgress, APP_ALIASES, DISPLAY_ALIASES, TOOLS, externalTools, externalToolsMeta, _generation, TOOL_DESCRIPTIONS, TOOL_NAMES_ONLY, TOOL_TIERS, TOOL_CATEGORIES, TOOL_REGISTRY, registryNames, registryDescriptions, registryTiers, registryCategories, registryTimeouts, registryAllowedTools, registryValidTools, registryNoRetrySet, registryParallelSafeSet, registrySequentialOnlySet, registryMcpSafeList, registryMcpDestructiveList;
391886
392302
  var init_toolRegistry = __esm({
391887
392303
  "core/toolRegistry.ts"() {
391888
392304
  import_child_process13 = require("child_process");
391889
392305
  import_util10 = require("util");
391890
- import_fs43 = __toESM(require("fs"));
391891
- import_path45 = __toESM(require("path"));
391892
- import_os4 = __toESM(require("os"));
392306
+ import_fs44 = __toESM(require("fs"));
392307
+ import_path46 = __toESM(require("path"));
392308
+ import_os5 = __toESM(require("os"));
391893
392309
  init_paths();
391894
392310
  init_computerControl();
391895
392311
  init_webSearch();
@@ -392061,7 +392477,7 @@ var init_toolRegistry = __esm({
392061
392477
  // 16. Windows window management
392062
392478
  /^(start|explorer)\b/i
392063
392479
  ];
392064
- BROWSER_DATA_DIR = import_path45.default.join(getUserDataDir(), "browser-profiles");
392480
+ BROWSER_DATA_DIR = import_path46.default.join(getUserDataDir(), "browser-profiles");
392065
392481
  try {
392066
392482
  cleanOldBrowserProfiles();
392067
392483
  } catch {
@@ -392404,9 +392820,9 @@ stderr: ${sr.stderr}` : "")).trim() || "(completed)";
392404
392820
  return { success: false, output: "", error: "Blocked: this command pattern is not allowed. Dangerous operations require explicit user approval." };
392405
392821
  }
392406
392822
  }
392407
- const tmpFile = import_path45.default.join(process.cwd(), "workspace", `tmp_${Date.now()}.ps1`);
392408
- import_fs43.default.mkdirSync(import_path45.default.dirname(tmpFile), { recursive: true });
392409
- import_fs43.default.writeFileSync(tmpFile, script2);
392823
+ const tmpFile = import_path46.default.join(process.cwd(), "workspace", `tmp_${Date.now()}.ps1`);
392824
+ import_fs44.default.mkdirSync(import_path46.default.dirname(tmpFile), { recursive: true });
392825
+ import_fs44.default.writeFileSync(tmpFile, script2);
392410
392826
  try {
392411
392827
  const { stdout, stderr } = await execAsync8(
392412
392828
  `powershell.exe -ExecutionPolicy Bypass -File "${tmpFile}"`,
@@ -392417,7 +392833,7 @@ stderr: ${sr.stderr}` : "")).trim() || "(completed)";
392417
392833
  return { success: false, output: "", error: e.message };
392418
392834
  } finally {
392419
392835
  try {
392420
- import_fs43.default.unlinkSync(tmpFile);
392836
+ import_fs44.default.unlinkSync(tmpFile);
392421
392837
  } catch {
392422
392838
  }
392423
392839
  }
@@ -392521,9 +392937,9 @@ stderr: ${sr.stderr}` : "")).trim() || "(completed)";
392521
392937
  }
392522
392938
  try {
392523
392939
  const resolved = resolveWritePath(filePath);
392524
- import_fs43.default.mkdirSync(import_path45.default.dirname(resolved), { recursive: true });
392525
- import_fs43.default.writeFileSync(resolved, content, "utf-8");
392526
- const written = import_fs43.default.existsSync(resolved);
392940
+ import_fs44.default.mkdirSync(import_path46.default.dirname(resolved), { recursive: true });
392941
+ import_fs44.default.writeFileSync(resolved, content, "utf-8");
392942
+ const written = import_fs44.default.existsSync(resolved);
392527
392943
  return {
392528
392944
  success: written,
392529
392945
  output: written ? `Written and verified: ${resolved} (${content.length} chars)` : "Write failed"
@@ -392547,10 +392963,10 @@ stderr: ${sr.stderr}` : "")).trim() || "(completed)";
392547
392963
  try {
392548
392964
  const _user = process.env.USERNAME || process.env.USER || require("os").userInfo().username || "User";
392549
392965
  const _home = require("os").homedir();
392550
- filePath = filePath.replace(/^~[\/\\]/i, _home + import_path45.default.sep).replace(/^Desktop[\/\\]/i, import_path45.default.join(_home, "Desktop") + import_path45.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${_user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${_user}/`);
392551
- const resolved = filePath.match(/^[A-Z]:/i) || filePath.startsWith("/") ? filePath : import_path45.default.join(process.cwd(), filePath);
392552
- if (!import_fs43.default.existsSync(resolved)) return { success: false, output: "", error: `Not found: ${resolved}` };
392553
- return { success: true, output: import_fs43.default.readFileSync(resolved, "utf-8").slice(0, 5e3) };
392966
+ filePath = filePath.replace(/^~[\/\\]/i, _home + import_path46.default.sep).replace(/^Desktop[\/\\]/i, import_path46.default.join(_home, "Desktop") + import_path46.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${_user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${_user}/`);
392967
+ const resolved = filePath.match(/^[A-Z]:/i) || filePath.startsWith("/") ? filePath : import_path46.default.join(process.cwd(), filePath);
392968
+ if (!import_fs44.default.existsSync(resolved)) return { success: false, output: "", error: `Not found: ${resolved}` };
392969
+ return { success: true, output: import_fs44.default.readFileSync(resolved, "utf-8").slice(0, 5e3) };
392554
392970
  } catch (e) {
392555
392971
  return { success: false, output: "", error: e.message };
392556
392972
  }
@@ -392560,9 +392976,9 @@ stderr: ${sr.stderr}` : "")).trim() || "(completed)";
392560
392976
  try {
392561
392977
  const _user = process.env.USERNAME || process.env.USER || require("os").userInfo().username || "User";
392562
392978
  const _home = require("os").homedir();
392563
- dirPath = dirPath.replace(/^~[\/\\]/i, _home + import_path45.default.sep).replace(/^Desktop[\/\\]?$/i, import_path45.default.join(_home, "Desktop")).replace(/^Desktop[\/\\]/i, import_path45.default.join(_home, "Desktop") + import_path45.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${_user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${_user}/`);
392564
- const resolved = dirPath.match(/^[A-Z]:/i) ? dirPath : import_path45.default.join(process.cwd(), dirPath);
392565
- return { success: true, output: import_fs43.default.readdirSync(resolved).join("\n") };
392979
+ dirPath = dirPath.replace(/^~[\/\\]/i, _home + import_path46.default.sep).replace(/^Desktop[\/\\]?$/i, import_path46.default.join(_home, "Desktop")).replace(/^Desktop[\/\\]/i, import_path46.default.join(_home, "Desktop") + import_path46.default.sep).replace(/^C:\\Users\\Aiden\\/i, `C:\\Users\\${_user}\\`).replace(/^C:\/Users\/Aiden\//i, `C:/Users/${_user}/`);
392980
+ const resolved = dirPath.match(/^[A-Z]:/i) ? dirPath : import_path46.default.join(process.cwd(), dirPath);
392981
+ return { success: true, output: import_fs44.default.readdirSync(resolved).join("\n") };
392566
392982
  } catch (e) {
392567
392983
  return { success: false, output: "", error: e.message };
392568
392984
  }
@@ -392584,9 +393000,9 @@ stderr: ${sr.stderr}` : "")).trim() || "Script completed with no output";
392584
393000
  console.warn("[Sandbox] auto-mode fell back to host:", sandboxErr.message);
392585
393001
  }
392586
393002
  }
392587
- const tmp = import_path45.default.join(process.cwd(), "workspace", `py_${Date.now()}.py`);
392588
- import_fs43.default.mkdirSync(import_path45.default.dirname(tmp), { recursive: true });
392589
- import_fs43.default.writeFileSync(tmp, script2);
393003
+ const tmp = import_path46.default.join(process.cwd(), "workspace", `py_${Date.now()}.py`);
393004
+ import_fs44.default.mkdirSync(import_path46.default.dirname(tmp), { recursive: true });
393005
+ import_fs44.default.writeFileSync(tmp, script2);
392590
393006
  const showProgress = process.env.AIDEN_SHOW_TOOL_OUTPUT !== "false";
392591
393007
  return new Promise((resolve8) => {
392592
393008
  let stdout = "";
@@ -392612,7 +393028,7 @@ stderr: ${sr.stderr}` : "")).trim() || "Script completed with no output";
392612
393028
  proc.on("close", (code) => {
392613
393029
  clearTimeout(timer);
392614
393030
  try {
392615
- import_fs43.default.unlinkSync(tmp);
393031
+ import_fs44.default.unlinkSync(tmp);
392616
393032
  } catch {
392617
393033
  }
392618
393034
  const output = (stdout || stderr || "").trim() || "Script completed with no output";
@@ -392625,9 +393041,9 @@ stderr: ${sr.stderr}` : "")).trim() || "Script completed with no output";
392625
393041
  if (!script2) return { success: false, output: "", error: "No script" };
392626
393042
  const nodeGuard = scanCodeForDestructivePaths(script2, "node");
392627
393043
  if (nodeGuard.denied) return { success: false, output: "", error: nodeGuard.reason };
392628
- const tmp = import_path45.default.join(process.cwd(), "workspace", `js_${Date.now()}.js`);
392629
- import_fs43.default.mkdirSync(import_path45.default.dirname(tmp), { recursive: true });
392630
- import_fs43.default.writeFileSync(tmp, script2);
393044
+ const tmp = import_path46.default.join(process.cwd(), "workspace", `js_${Date.now()}.js`);
393045
+ import_fs44.default.mkdirSync(import_path46.default.dirname(tmp), { recursive: true });
393046
+ import_fs44.default.writeFileSync(tmp, script2);
392631
393047
  try {
392632
393048
  const { stdout, stderr } = await execAsync8(`node "${tmp}"`, {
392633
393049
  timeout: 6e4,
@@ -392638,7 +393054,7 @@ stderr: ${sr.stderr}` : "")).trim() || "Script completed with no output";
392638
393054
  return { success: false, output: e.stdout || "", error: `Node error: ${e.message}` };
392639
393055
  } finally {
392640
393056
  try {
392641
- import_fs43.default.unlinkSync(tmp);
393057
+ import_fs44.default.unlinkSync(tmp);
392642
393058
  } catch {
392643
393059
  }
392644
393060
  }
@@ -393455,7 +393871,7 @@ public class AidenVolSet {
393455
393871
  const stop = !!p.stop;
393456
393872
  if (!rawFolder) return { success: false, output: "", error: "No folder specified" };
393457
393873
  const userName = process.env.USERPROFILE || process.env.HOME || "";
393458
- const folderPath = rawFolder.replace(/%USERPROFILE%/gi, userName).replace(/^~[\/\\]/, userName + import_path45.default.sep);
393874
+ const folderPath = rawFolder.replace(/%USERPROFILE%/gi, userName).replace(/^~[\/\\]/, userName + import_path46.default.sep);
393459
393875
  if (stop) {
393460
393876
  const watcher2 = activeWatchers.get(folderPath);
393461
393877
  if (watcher2) {
@@ -393466,20 +393882,20 @@ public class AidenVolSet {
393466
393882
  return { success: false, output: `No active watcher for: ${folderPath}` };
393467
393883
  }
393468
393884
  if (!goal) return { success: false, output: "", error: "No goal specified" };
393469
- if (!import_fs43.default.existsSync(folderPath)) return { success: false, output: "", error: `Folder not found: ${folderPath}` };
393885
+ if (!import_fs44.default.existsSync(folderPath)) return { success: false, output: "", error: `Folder not found: ${folderPath}` };
393470
393886
  const existing = activeWatchers.get(folderPath);
393471
393887
  if (existing) {
393472
393888
  existing.close();
393473
393889
  activeWatchers.delete(folderPath);
393474
393890
  }
393475
- const watcher = import_fs43.default.watch(folderPath, async (eventType, filename) => {
393891
+ const watcher = import_fs44.default.watch(folderPath, async (eventType, filename) => {
393476
393892
  if (eventType !== "rename" || !filename) return;
393477
- const fullPath = import_path45.default.join(folderPath, filename);
393893
+ const fullPath = import_path46.default.join(folderPath, filename);
393478
393894
  await new Promise((r) => setTimeout(r, 500));
393479
- if (!import_fs43.default.existsSync(fullPath)) return;
393895
+ if (!import_fs44.default.existsSync(fullPath)) return;
393480
393896
  let isFile2 = false;
393481
393897
  try {
393482
- isFile2 = import_fs43.default.statSync(fullPath).isFile();
393898
+ isFile2 = import_fs44.default.statSync(fullPath).isFile();
393483
393899
  } catch {
393484
393900
  return;
393485
393901
  }
@@ -393750,28 +394166,28 @@ ${formatted}` };
393750
394166
  });
393751
394167
  return 2 * n / (sa.size + sb.size + 1e-3);
393752
394168
  };
393753
- const skillFolders = ["learned", "approved", "installed"].map((f) => import_path45.default.join(cwd, "workspace", "skills", f)).filter((d) => import_fs43.default.existsSync(d));
394169
+ const skillFolders = ["learned", "approved", "installed"].map((f) => import_path46.default.join(cwd, "workspace", "skills", f)).filter((d) => import_fs44.default.existsSync(d));
393754
394170
  if (skillFolders.length === 0) return { success: false, output: "", error: "No skills yet" };
393755
394171
  let best = { score: 0, dir: "", name: "" };
393756
394172
  for (const folder of skillFolders) {
393757
- for (const entry of import_fs43.default.readdirSync(folder, { withFileTypes: true })) {
394173
+ for (const entry of import_fs44.default.readdirSync(folder, { withFileTypes: true })) {
393758
394174
  if (!entry.isDirectory()) continue;
393759
- const metaPath2 = import_path45.default.join(folder, entry.name, "meta.json");
394175
+ const metaPath2 = import_path46.default.join(folder, entry.name, "meta.json");
393760
394176
  let taskPattern = entry.name;
393761
394177
  try {
393762
- const meta = JSON.parse(import_fs43.default.readFileSync(metaPath2, "utf-8"));
394178
+ const meta = JSON.parse(import_fs44.default.readFileSync(metaPath2, "utf-8"));
393763
394179
  taskPattern = meta.taskPattern || meta.description || entry.name;
393764
394180
  } catch {
393765
394181
  }
393766
394182
  const score = Math.max(dice(query, entry.name), dice(query, taskPattern));
393767
- if (score > best.score) best = { score, dir: import_path45.default.join(folder, entry.name), name: entry.name };
394183
+ if (score > best.score) best = { score, dir: import_path46.default.join(folder, entry.name), name: entry.name };
393768
394184
  }
393769
394185
  }
393770
394186
  const THRESHOLD = 0.25;
393771
394187
  if (best.score < THRESHOLD) return { success: false, output: "", error: `No matching skill found (best: ${best.name} @ ${best.score.toFixed(2)})` };
393772
- const skillPath = import_path45.default.join(best.dir, "SKILL.md");
393773
- if (!import_fs43.default.existsSync(skillPath)) return { success: false, output: "", error: `Skill "${best.name}" has no SKILL.md` };
393774
- const content = import_fs43.default.readFileSync(skillPath, "utf-8");
394188
+ const skillPath = import_path46.default.join(best.dir, "SKILL.md");
394189
+ if (!import_fs44.default.existsSync(skillPath)) return { success: false, output: "", error: `Skill "${best.name}" has no SKILL.md` };
394190
+ const content = import_fs44.default.readFileSync(skillPath, "utf-8");
393775
394191
  return { success: true, output: `[Skill: ${best.name} \u2014 match score ${best.score.toFixed(2)}]
393776
394192
 
393777
394193
  ${content}` };
@@ -393878,6 +394294,20 @@ ${content}` };
393878
394294
  return { success: false, output: "", error: e.message };
393879
394295
  }
393880
394296
  },
394297
+ // ── memory_store — persist a fact to permanent memory ──
394298
+ memory_store: async (p) => {
394299
+ const fact = p.fact || p.text || p.content || "";
394300
+ if (!fact) return { success: false, output: "", error: "No fact provided" };
394301
+ const { toolMemoryStore: toolMemoryStore2 } = await Promise.resolve().then(() => (init_slashAsTool(), slashAsTool_exports));
394302
+ return toolMemoryStore2(p);
394303
+ },
394304
+ // ── memory_forget — remove a fact from permanent memory ──
394305
+ memory_forget: async (p) => {
394306
+ const fact = p.fact || p.keyword || p.text || "";
394307
+ if (!fact) return { success: false, output: "", error: "No fact provided" };
394308
+ const { toolMemoryForget: toolMemoryForget2 } = await Promise.resolve().then(() => (init_slashAsTool(), slashAsTool_exports));
394309
+ return toolMemoryForget2(p);
394310
+ },
393881
394311
  // ── clarify — ask the user a multi-choice or free-text question mid-task ──
393882
394312
  clarify: async (p) => {
393883
394313
  const question = p.question || p.q || "";
@@ -402514,12 +402944,12 @@ function buildFrontmatter(meta) {
402514
402944
  async function writeSkillDraft(draft, targetDir) {
402515
402945
  const cwd = process.cwd();
402516
402946
  const id = sanitizeSkillId(draft.name);
402517
- const baseDir = targetDir === "installed" ? import_path52.default.join(cwd, "skills", "installed") : import_path52.default.join(cwd, "skills", "learned", "pending");
402518
- const dir = import_path52.default.join(baseDir, id);
402519
- if (import_fs50.default.existsSync(dir)) {
402947
+ const baseDir = targetDir === "installed" ? import_path53.default.join(cwd, "skills", "installed") : import_path53.default.join(cwd, "skills", "learned", "pending");
402948
+ const dir = import_path53.default.join(baseDir, id);
402949
+ if (import_fs51.default.existsSync(dir)) {
402520
402950
  throw new Error(`Skill "${id}" already exists at ${dir}. Use a different name or delete the existing draft.`);
402521
402951
  }
402522
- import_fs50.default.mkdirSync(dir, { recursive: true });
402952
+ import_fs51.default.mkdirSync(dir, { recursive: true });
402523
402953
  const frontmatter = buildFrontmatter({
402524
402954
  name: draft.name,
402525
402955
  description: draft.description,
@@ -402539,8 +402969,8 @@ async function writeSkillDraft(draft, targetDir) {
402539
402969
 
402540
402970
  ${header}${body}
402541
402971
  `;
402542
- const filePath = import_path52.default.join(dir, "SKILL.md");
402543
- import_fs50.default.writeFileSync(filePath, fileContent, "utf-8");
402972
+ const filePath = import_path53.default.join(dir, "SKILL.md");
402973
+ import_fs51.default.writeFileSync(filePath, fileContent, "utf-8");
402544
402974
  const meta = {
402545
402975
  id,
402546
402976
  name: draft.name,
@@ -402550,7 +402980,7 @@ ${header}${body}
402550
402980
  createdAt: timestamp2,
402551
402981
  enabled: false
402552
402982
  };
402553
- import_fs50.default.writeFileSync(import_path52.default.join(dir, "meta.json"), JSON.stringify(meta, null, 2) + "\n", "utf-8");
402983
+ import_fs51.default.writeFileSync(import_path53.default.join(dir, "meta.json"), JSON.stringify(meta, null, 2) + "\n", "utf-8");
402554
402984
  const toolCalls = draft.sourceDetails?.toolCalls ?? [];
402555
402985
  const toolNames = Array.isArray(toolCalls) ? toolCalls.map((t) => t.tool ?? t).filter(Boolean) : [];
402556
402986
  const skillJson = {
@@ -402566,54 +402996,54 @@ ${header}${body}
402566
402996
  tags: draft.tags?.length ? draft.tags : inferTags(toolNames, draft.content),
402567
402997
  created: timestamp2
402568
402998
  };
402569
- import_fs50.default.writeFileSync(import_path52.default.join(dir, "skill.json"), JSON.stringify(skillJson, null, 2) + "\n", "utf-8");
402999
+ import_fs51.default.writeFileSync(import_path53.default.join(dir, "skill.json"), JSON.stringify(skillJson, null, 2) + "\n", "utf-8");
402570
403000
  return { id, filePath, dir };
402571
403001
  }
402572
403002
  function approveDraft(id) {
402573
403003
  const cwd = process.cwd();
402574
- const pendDir = import_path52.default.join(cwd, "skills", "learned", "pending", id);
402575
- const approDir = import_path52.default.join(cwd, "skills", "learned", "approved", id);
402576
- if (!import_fs50.default.existsSync(pendDir)) throw new Error(`Pending skill "${id}" not found`);
402577
- if (import_fs50.default.existsSync(approDir)) throw new Error(`Approved skill "${id}" already exists`);
402578
- const skillFile = import_path52.default.join(pendDir, "SKILL.md");
402579
- if (import_fs50.default.existsSync(skillFile)) {
402580
- let content = import_fs50.default.readFileSync(skillFile, "utf-8");
403004
+ const pendDir = import_path53.default.join(cwd, "skills", "learned", "pending", id);
403005
+ const approDir = import_path53.default.join(cwd, "skills", "learned", "approved", id);
403006
+ if (!import_fs51.default.existsSync(pendDir)) throw new Error(`Pending skill "${id}" not found`);
403007
+ if (import_fs51.default.existsSync(approDir)) throw new Error(`Approved skill "${id}" already exists`);
403008
+ const skillFile = import_path53.default.join(pendDir, "SKILL.md");
403009
+ if (import_fs51.default.existsSync(skillFile)) {
403010
+ let content = import_fs51.default.readFileSync(skillFile, "utf-8");
402581
403011
  content = content.replace(/^enabled:\s*false/m, "enabled: true");
402582
- import_fs50.default.writeFileSync(skillFile, content, "utf-8");
403012
+ import_fs51.default.writeFileSync(skillFile, content, "utf-8");
402583
403013
  }
402584
- import_fs50.default.mkdirSync(import_path52.default.join(cwd, "skills", "learned", "approved"), { recursive: true });
402585
- import_fs50.default.renameSync(pendDir, approDir);
403014
+ import_fs51.default.mkdirSync(import_path53.default.join(cwd, "skills", "learned", "approved"), { recursive: true });
403015
+ import_fs51.default.renameSync(pendDir, approDir);
402586
403016
  return approDir;
402587
403017
  }
402588
403018
  function rejectDraft(id) {
402589
403019
  const cwd = process.cwd();
402590
- const pendDir = import_path52.default.join(cwd, "skills", "learned", "pending", id);
402591
- if (!import_fs50.default.existsSync(pendDir)) throw new Error(`Pending skill "${id}" not found`);
403020
+ const pendDir = import_path53.default.join(cwd, "skills", "learned", "pending", id);
403021
+ if (!import_fs51.default.existsSync(pendDir)) throw new Error(`Pending skill "${id}" not found`);
402592
403022
  let meta = { id };
402593
403023
  try {
402594
- meta = JSON.parse(import_fs50.default.readFileSync(import_path52.default.join(pendDir, "meta.json"), "utf-8"));
403024
+ meta = JSON.parse(import_fs51.default.readFileSync(import_path53.default.join(pendDir, "meta.json"), "utf-8"));
402595
403025
  } catch {
402596
403026
  }
402597
- import_fs50.default.rmSync(pendDir, { recursive: true, force: true });
402598
- const rejLog = import_path52.default.join(cwd, "skills", "learned", ".rejected.json");
403027
+ import_fs51.default.rmSync(pendDir, { recursive: true, force: true });
403028
+ const rejLog = import_path53.default.join(cwd, "skills", "learned", ".rejected.json");
402599
403029
  let log = [];
402600
403030
  try {
402601
- log = JSON.parse(import_fs50.default.readFileSync(rejLog, "utf-8"));
403031
+ log = JSON.parse(import_fs51.default.readFileSync(rejLog, "utf-8"));
402602
403032
  } catch {
402603
403033
  }
402604
403034
  log.push({ ...meta, rejectedAt: (/* @__PURE__ */ new Date()).toISOString() });
402605
- import_fs50.default.writeFileSync(rejLog, JSON.stringify(log, null, 2) + "\n", "utf-8");
403035
+ import_fs51.default.writeFileSync(rejLog, JSON.stringify(log, null, 2) + "\n", "utf-8");
402606
403036
  }
402607
403037
  function setSkillEnabled(filePath, enabled) {
402608
- if (!import_fs50.default.existsSync(filePath)) throw new Error(`Skill file not found: ${filePath}`);
402609
- let content = import_fs50.default.readFileSync(filePath, "utf-8");
403038
+ if (!import_fs51.default.existsSync(filePath)) throw new Error(`Skill file not found: ${filePath}`);
403039
+ let content = import_fs51.default.readFileSync(filePath, "utf-8");
402610
403040
  if (/^enabled:/m.test(content)) {
402611
403041
  content = content.replace(/^enabled:\s*(true|false)/m, `enabled: ${enabled}`);
402612
403042
  } else {
402613
403043
  content = content.replace(/^(version:.+)$/m, `$1
402614
403044
  enabled: ${enabled}`);
402615
403045
  }
402616
- import_fs50.default.writeFileSync(filePath, content, "utf-8");
403046
+ import_fs51.default.writeFileSync(filePath, content, "utf-8");
402617
403047
  }
402618
403048
  function tokenSimilarity(a, b) {
402619
403049
  const tok = (s) => new Set(
@@ -402639,22 +403069,22 @@ async function writeSkillFromTask(args) {
402639
403069
  if (!success || toolsUsed.length < 2) return null;
402640
403070
  try {
402641
403071
  const cwd = process.cwd();
402642
- const learnedDir = import_path52.default.join(cwd, "workspace", "skills", "learned");
402643
- import_fs50.default.mkdirSync(learnedDir, { recursive: true });
403072
+ const learnedDir = import_path53.default.join(cwd, "workspace", "skills", "learned");
403073
+ import_fs51.default.mkdirSync(learnedDir, { recursive: true });
402644
403074
  const skillName = skillNameFromMessage(userMessage);
402645
- if (import_fs50.default.existsSync(learnedDir)) {
402646
- for (const entry of import_fs50.default.readdirSync(learnedDir, { withFileTypes: true })) {
403075
+ if (import_fs51.default.existsSync(learnedDir)) {
403076
+ for (const entry of import_fs51.default.readdirSync(learnedDir, { withFileTypes: true })) {
402647
403077
  if (!entry.isDirectory()) continue;
402648
403078
  const existingName = entry.name.replace(/_/g, " ");
402649
403079
  if (tokenSimilarity(skillName.replace(/_/g, " "), existingName) > 0.8) {
402650
- const metaPath2 = import_path52.default.join(learnedDir, entry.name, "meta.json");
402651
- if (import_fs50.default.existsSync(metaPath2)) {
403080
+ const metaPath2 = import_path53.default.join(learnedDir, entry.name, "meta.json");
403081
+ if (import_fs51.default.existsSync(metaPath2)) {
402652
403082
  try {
402653
- const meta = JSON.parse(import_fs50.default.readFileSync(metaPath2, "utf-8"));
403083
+ const meta = JSON.parse(import_fs51.default.readFileSync(metaPath2, "utf-8"));
402654
403084
  meta.successCount = (meta.successCount || 1) + 1;
402655
403085
  meta.lastUsed = Date.now();
402656
403086
  meta.confidence = Math.min(0.99, meta.successCount / (meta.successCount + (meta.failCount || 0) + 1));
402657
- import_fs50.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
403087
+ import_fs51.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
402658
403088
  } catch {
402659
403089
  }
402660
403090
  }
@@ -402662,22 +403092,22 @@ async function writeSkillFromTask(args) {
402662
403092
  }
402663
403093
  }
402664
403094
  }
402665
- const skillDir = import_path52.default.join(learnedDir, skillName);
402666
- if (import_fs50.default.existsSync(skillDir)) {
402667
- const metaPath2 = import_path52.default.join(skillDir, "meta.json");
402668
- if (import_fs50.default.existsSync(metaPath2)) {
403095
+ const skillDir = import_path53.default.join(learnedDir, skillName);
403096
+ if (import_fs51.default.existsSync(skillDir)) {
403097
+ const metaPath2 = import_path53.default.join(skillDir, "meta.json");
403098
+ if (import_fs51.default.existsSync(metaPath2)) {
402669
403099
  try {
402670
- const meta = JSON.parse(import_fs50.default.readFileSync(metaPath2, "utf-8"));
403100
+ const meta = JSON.parse(import_fs51.default.readFileSync(metaPath2, "utf-8"));
402671
403101
  meta.successCount = (meta.successCount || 1) + 1;
402672
403102
  meta.lastUsed = Date.now();
402673
403103
  meta.confidence = Math.min(0.99, meta.successCount / (meta.successCount + (meta.failCount || 0) + 1));
402674
- import_fs50.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
403104
+ import_fs51.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
402675
403105
  } catch {
402676
403106
  }
402677
403107
  }
402678
403108
  return null;
402679
403109
  }
402680
- import_fs50.default.mkdirSync(skillDir, { recursive: true });
403110
+ import_fs51.default.mkdirSync(skillDir, { recursive: true });
402681
403111
  const title = toTitleCase(skillName);
402682
403112
  const descSnippet = userMessage.slice(0, 100).replace(/\n/g, " ");
402683
403113
  const toolList = toolsUsed.join(", ");
@@ -402733,9 +403163,9 @@ async function writeSkillFromTask(args) {
402733
403163
  tags: inferTags(toolsUsed, userMessage),
402734
403164
  created: (/* @__PURE__ */ new Date()).toISOString()
402735
403165
  };
402736
- import_fs50.default.writeFileSync(import_path52.default.join(skillDir, "SKILL.md"), skillMd, "utf-8");
402737
- import_fs50.default.writeFileSync(import_path52.default.join(skillDir, "meta.json"), JSON.stringify(metaJson, null, 2) + "\n", "utf-8");
402738
- import_fs50.default.writeFileSync(import_path52.default.join(skillDir, "skill.json"), JSON.stringify(taskSkillJson, null, 2) + "\n", "utf-8");
403166
+ import_fs51.default.writeFileSync(import_path53.default.join(skillDir, "SKILL.md"), skillMd, "utf-8");
403167
+ import_fs51.default.writeFileSync(import_path53.default.join(skillDir, "meta.json"), JSON.stringify(metaJson, null, 2) + "\n", "utf-8");
403168
+ import_fs51.default.writeFileSync(import_path53.default.join(skillDir, "skill.json"), JSON.stringify(taskSkillJson, null, 2) + "\n", "utf-8");
402739
403169
  console.log(`[SkillWriter] Wrote skill "${skillName}" \u2192 ${skillDir}`);
402740
403170
  return { skillName, path: skillDir };
402741
403171
  } catch (err) {
@@ -402745,22 +403175,22 @@ async function writeSkillFromTask(args) {
402745
403175
  }
402746
403176
  function listPending() {
402747
403177
  const cwd = process.cwd();
402748
- const pendDir = import_path52.default.join(cwd, "skills", "learned", "pending");
402749
- if (!import_fs50.default.existsSync(pendDir)) return [];
402750
- return import_fs50.default.readdirSync(pendDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => {
403178
+ const pendDir = import_path53.default.join(cwd, "skills", "learned", "pending");
403179
+ if (!import_fs51.default.existsSync(pendDir)) return [];
403180
+ return import_fs51.default.readdirSync(pendDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => {
402751
403181
  try {
402752
- const meta = JSON.parse(import_fs50.default.readFileSync(import_path52.default.join(pendDir, e.name, "meta.json"), "utf-8"));
403182
+ const meta = JSON.parse(import_fs51.default.readFileSync(import_path53.default.join(pendDir, e.name, "meta.json"), "utf-8"));
402753
403183
  return { id: e.name, name: meta.name || e.name, description: meta.description || "", source: meta.source || "", createdAt: meta.createdAt || "" };
402754
403184
  } catch {
402755
403185
  return { id: e.name, name: e.name, description: "", source: "unknown", createdAt: "" };
402756
403186
  }
402757
403187
  });
402758
403188
  }
402759
- var import_fs50, import_path52, STOP_WORDS2;
403189
+ var import_fs51, import_path53, STOP_WORDS2;
402760
403190
  var init_skillWriter = __esm({
402761
403191
  "core/skillWriter.ts"() {
402762
- import_fs50 = __toESM(require("fs"));
402763
- import_path52 = __toESM(require("path"));
403192
+ import_fs51 = __toESM(require("fs"));
403193
+ import_path53 = __toESM(require("path"));
402764
403194
  STOP_WORDS2 = /* @__PURE__ */ new Set([
402765
403195
  "a",
402766
403196
  "an",
@@ -1048654,12 +1049084,12 @@ init_contextHandoff();
1048654
1049084
  // core/voiceInput.ts
1048655
1049085
  var import_child_process14 = require("child_process");
1048656
1049086
  var import_util11 = require("util");
1048657
- var import_fs44 = __toESM(require("fs"));
1048658
- var import_path46 = __toESM(require("path"));
1049087
+ var import_fs45 = __toESM(require("fs"));
1049088
+ var import_path47 = __toESM(require("path"));
1048659
1049089
  var execAsync9 = (0, import_util11.promisify)(import_child_process14.exec);
1048660
- var WORKSPACE5 = import_path46.default.join(process.cwd(), "workspace");
1049090
+ var WORKSPACE5 = import_path47.default.join(process.cwd(), "workspace");
1048661
1049091
  function ensureWorkspace4() {
1048662
- if (!import_fs44.default.existsSync(WORKSPACE5)) import_fs44.default.mkdirSync(WORKSPACE5, { recursive: true });
1049092
+ if (!import_fs45.default.existsSync(WORKSPACE5)) import_fs45.default.mkdirSync(WORKSPACE5, { recursive: true });
1048663
1049093
  }
1048664
1049094
  async function checkVoiceAvailable() {
1048665
1049095
  try {
@@ -1048682,8 +1049112,8 @@ segments, info = model.transcribe("${normalizedPath}", beam_size=5)
1048682
1049112
  text = " ".join([segment.text for segment in segments])
1048683
1049113
  print(text.strip())
1048684
1049114
  `.trim();
1048685
- const tmpScript = import_path46.default.join(WORKSPACE5, `whisper_${Date.now()}.py`);
1048686
- import_fs44.default.writeFileSync(tmpScript, pythonScript);
1049115
+ const tmpScript = import_path47.default.join(WORKSPACE5, `whisper_${Date.now()}.py`);
1049116
+ import_fs45.default.writeFileSync(tmpScript, pythonScript);
1048687
1049117
  try {
1048688
1049118
  const { stdout } = await execAsync9(`python "${tmpScript}"`, { timeout: 3e4 });
1048689
1049119
  return stdout.trim();
@@ -1048691,14 +1049121,14 @@ print(text.strip())
1048691
1049121
  throw new Error(`Transcription failed: ${e.message}`);
1048692
1049122
  } finally {
1048693
1049123
  try {
1048694
- import_fs44.default.unlinkSync(tmpScript);
1049124
+ import_fs45.default.unlinkSync(tmpScript);
1048695
1049125
  } catch {
1048696
1049126
  }
1048697
1049127
  }
1048698
1049128
  }
1048699
1049129
  async function recordAudio2(durationMs = 5e3) {
1048700
1049130
  ensureWorkspace4();
1048701
- const outputPath = import_path46.default.join(WORKSPACE5, `recording_${Date.now()}.wav`);
1049131
+ const outputPath = import_path47.default.join(WORKSPACE5, `recording_${Date.now()}.wav`);
1048702
1049132
  const outputPathFwd = outputPath.replace(/\\/g, "\\\\");
1048703
1049133
  const psScript = `
1048704
1049134
  Add-Type -TypeDefinition @"
@@ -1048729,8 +1049159,8 @@ public class AudioRecorder {
1048729
1049159
  [AudioRecorder]::Record("${outputPathFwd}", ${durationMs})
1048730
1049160
  Write-Output "${outputPath}"
1048731
1049161
  `.trim();
1048732
- const psFile2 = import_path46.default.join(WORKSPACE5, `record_${Date.now()}.ps1`);
1048733
- import_fs44.default.writeFileSync(psFile2, psScript);
1049162
+ const psFile2 = import_path47.default.join(WORKSPACE5, `record_${Date.now()}.ps1`);
1049163
+ import_fs45.default.writeFileSync(psFile2, psScript);
1048734
1049164
  try {
1048735
1049165
  await execAsync9(
1048736
1049166
  `powershell.exe -ExecutionPolicy Bypass -File "${psFile2}"`,
@@ -1048741,7 +1049171,7 @@ Write-Output "${outputPath}"
1048741
1049171
  throw new Error(`Recording failed: ${e.message}`);
1048742
1049172
  } finally {
1048743
1049173
  try {
1048744
- import_fs44.default.unlinkSync(psFile2);
1049174
+ import_fs45.default.unlinkSync(psFile2);
1048745
1049175
  } catch {
1048746
1049176
  }
1048747
1049177
  }
@@ -1048750,13 +1049180,13 @@ Write-Output "${outputPath}"
1048750
1049180
  // core/voiceOutput.ts
1048751
1049181
  var import_child_process15 = require("child_process");
1048752
1049182
  var import_util12 = require("util");
1048753
- var import_fs45 = __toESM(require("fs"));
1048754
- var import_path47 = __toESM(require("path"));
1049183
+ var import_fs46 = __toESM(require("fs"));
1049184
+ var import_path48 = __toESM(require("path"));
1048755
1049185
  var execAsync10 = (0, import_util12.promisify)(import_child_process15.exec);
1048756
- var WORKSPACE6 = import_path47.default.join(process.cwd(), "workspace");
1049186
+ var WORKSPACE6 = import_path48.default.join(process.cwd(), "workspace");
1048757
1049187
  var DEFAULT_VOICE2 = "en-US-AriaNeural";
1048758
1049188
  function ensureWorkspace5() {
1048759
- if (!import_fs45.default.existsSync(WORKSPACE6)) import_fs45.default.mkdirSync(WORKSPACE6, { recursive: true });
1049189
+ if (!import_fs46.default.existsSync(WORKSPACE6)) import_fs46.default.mkdirSync(WORKSPACE6, { recursive: true });
1048760
1049190
  }
1048761
1049191
  async function checkTTSAvailable() {
1048762
1049192
  try {
@@ -1048782,7 +1049212,7 @@ function cleanForTTS2(text) {
1048782
1049212
  }
1048783
1049213
  async function speakEdgeTTS(text, voice) {
1048784
1049214
  ensureWorkspace5();
1048785
- const audioPath = import_path47.default.join(WORKSPACE6, `tts_${Date.now()}.mp3`);
1049215
+ const audioPath = import_path48.default.join(WORKSPACE6, `tts_${Date.now()}.mp3`);
1048786
1049216
  const audioFwd = audioPath.replace(/\\/g, "/");
1048787
1049217
  const escapedText = text.replace(/"/g, '\\"').replace(/'/g, "\\'");
1048788
1049218
  const scriptContent = `
@@ -1048794,11 +1049224,11 @@ async def main():
1048794
1049224
  await communicate.save("${audioFwd}")
1048795
1049225
  asyncio.run(main())
1048796
1049226
  `.trim();
1048797
- const tmpScript = import_path47.default.join(WORKSPACE6, `tts_gen_${Date.now()}.py`);
1048798
- import_fs45.default.writeFileSync(tmpScript, scriptContent);
1049227
+ const tmpScript = import_path48.default.join(WORKSPACE6, `tts_gen_${Date.now()}.py`);
1049228
+ import_fs46.default.writeFileSync(tmpScript, scriptContent);
1048799
1049229
  try {
1048800
1049230
  await execAsync10(`python "${tmpScript}"`, { timeout: 15e3 });
1048801
- if (!import_fs45.default.existsSync(audioPath)) return false;
1049231
+ if (!import_fs46.default.existsSync(audioPath)) return false;
1048802
1049232
  execAsync10(
1048803
1049233
  `powershell -Command "Add-Type -AssemblyName presentationCore; $mp = New-Object System.Windows.Media.MediaPlayer; $mp.Open([uri]'${audioPath.replace(/\\/g, "\\\\")}'); $mp.Play(); Start-Sleep -Seconds 6; $mp.Stop(); $mp.Close()"`,
1048804
1049234
  { timeout: 15e3 }
@@ -1048808,7 +1049238,7 @@ asyncio.run(main())
1048808
1049238
  });
1048809
1049239
  setTimeout(() => {
1048810
1049240
  try {
1048811
- import_fs45.default.unlinkSync(audioPath);
1049241
+ import_fs46.default.unlinkSync(audioPath);
1048812
1049242
  } catch {
1048813
1049243
  }
1048814
1049244
  }, 12e3);
@@ -1048817,7 +1049247,7 @@ asyncio.run(main())
1048817
1049247
  return false;
1048818
1049248
  } finally {
1048819
1049249
  try {
1048820
- import_fs45.default.unlinkSync(tmpScript);
1049250
+ import_fs46.default.unlinkSync(tmpScript);
1048821
1049251
  } catch {
1048822
1049252
  }
1048823
1049253
  }
@@ -1048847,13 +1049277,13 @@ init_planTool();
1048847
1049277
  init_taskState();
1048848
1049278
 
1048849
1049279
  // core/taskQueue.ts
1048850
- var import_fs46 = require("fs");
1048851
- var import_path48 = require("path");
1049280
+ var import_fs47 = require("fs");
1049281
+ var import_path49 = require("path");
1048852
1049282
  var TaskQueue = class {
1048853
1049283
  constructor(workspaceDir, chatEndpoint) {
1048854
1049284
  this.queue = [];
1048855
1049285
  this.isProcessing = false;
1048856
- this.savePath = (0, import_path48.join)(workspaceDir, "task_queue.json");
1049286
+ this.savePath = (0, import_path49.join)(workspaceDir, "task_queue.json");
1048857
1049287
  this.chatEndpoint = chatEndpoint;
1048858
1049288
  this.load();
1048859
1049289
  for (const task of this.queue) {
@@ -1048930,8 +1049360,8 @@ var TaskQueue = class {
1048930
1049360
  // ── Persistence ───────────────────────────────────────────
1048931
1049361
  load() {
1048932
1049362
  try {
1048933
- if ((0, import_fs46.existsSync)(this.savePath)) {
1048934
- this.queue = JSON.parse((0, import_fs46.readFileSync)(this.savePath, "utf8"));
1049363
+ if ((0, import_fs47.existsSync)(this.savePath)) {
1049364
+ this.queue = JSON.parse((0, import_fs47.readFileSync)(this.savePath, "utf8"));
1048935
1049365
  }
1048936
1049366
  } catch {
1048937
1049367
  this.queue = [];
@@ -1048939,32 +1049369,32 @@ var TaskQueue = class {
1048939
1049369
  }
1048940
1049370
  save() {
1048941
1049371
  try {
1048942
- (0, import_fs46.mkdirSync)((0, import_path48.dirname)(this.savePath), { recursive: true });
1048943
- (0, import_fs46.writeFileSync)(this.savePath, JSON.stringify(this.queue, null, 2));
1049372
+ (0, import_fs47.mkdirSync)((0, import_path49.dirname)(this.savePath), { recursive: true });
1049373
+ (0, import_fs47.writeFileSync)(this.savePath, JSON.stringify(this.queue, null, 2));
1048944
1049374
  } catch {
1048945
1049375
  }
1048946
1049376
  }
1048947
1049377
  };
1048948
1049378
  var taskQueue = new TaskQueue(
1048949
- (0, import_path48.join)(process.cwd(), "workspace"),
1049379
+ (0, import_path49.join)(process.cwd(), "workspace"),
1048950
1049380
  "http://localhost:4200/api/chat"
1048951
1049381
  );
1048952
1049382
 
1048953
1049383
  // core/taskRecovery.ts
1048954
- var import_path49 = __toESM(require("path"));
1048955
- var import_fs47 = __toESM(require("fs"));
1048956
- var TASKS_DIR2 = import_path49.default.join(process.cwd(), "workspace", "tasks");
1049384
+ var import_path50 = __toESM(require("path"));
1049385
+ var import_fs48 = __toESM(require("fs"));
1049386
+ var TASKS_DIR2 = import_path50.default.join(process.cwd(), "workspace", "tasks");
1048957
1049387
  var MAX_TASK_AGE_MS = 2 * 60 * 60 * 1e3;
1048958
1049388
  async function recoverTasks() {
1048959
- if (!import_fs47.default.existsSync(TASKS_DIR2)) {
1049389
+ if (!import_fs48.default.existsSync(TASKS_DIR2)) {
1048960
1049390
  console.log("[Recovery] No task directory found \u2014 skipping");
1048961
1049391
  return;
1048962
1049392
  }
1048963
1049393
  let taskDirs;
1048964
1049394
  try {
1048965
- taskDirs = import_fs47.default.readdirSync(TASKS_DIR2).filter((d) => {
1049395
+ taskDirs = import_fs48.default.readdirSync(TASKS_DIR2).filter((d) => {
1048966
1049396
  try {
1048967
- return import_fs47.default.statSync(import_path49.default.join(TASKS_DIR2, d)).isDirectory();
1049397
+ return import_fs48.default.statSync(import_path50.default.join(TASKS_DIR2, d)).isDirectory();
1048968
1049398
  } catch {
1048969
1049399
  return false;
1048970
1049400
  }
@@ -1048977,16 +1049407,16 @@ async function recoverTasks() {
1048977
1049407
  let cleaned = 0;
1048978
1049408
  let corrupted = 0;
1048979
1049409
  for (const taskId of taskDirs) {
1048980
- const statePath = import_path49.default.join(TASKS_DIR2, taskId, "state.json");
1048981
- if (!import_fs47.default.existsSync(statePath)) continue;
1049410
+ const statePath = import_path50.default.join(TASKS_DIR2, taskId, "state.json");
1049411
+ if (!import_fs48.default.existsSync(statePath)) continue;
1048982
1049412
  let state;
1048983
1049413
  try {
1048984
- state = JSON.parse(import_fs47.default.readFileSync(statePath, "utf-8"));
1049414
+ state = JSON.parse(import_fs48.default.readFileSync(statePath, "utf-8"));
1048985
1049415
  } catch {
1048986
1049416
  corrupted++;
1048987
1049417
  try {
1048988
1049418
  const tmp = statePath + ".tmp";
1048989
- import_fs47.default.writeFileSync(tmp, JSON.stringify({
1049419
+ import_fs48.default.writeFileSync(tmp, JSON.stringify({
1048990
1049420
  id: taskId,
1048991
1049421
  status: "failed",
1048992
1049422
  error: "Corrupt state file \u2014 overwritten on startup",
@@ -1048994,11 +1049424,11 @@ async function recoverTasks() {
1048994
1049424
  updatedAt: Date.now()
1048995
1049425
  }, null, 2));
1048996
1049426
  try {
1048997
- import_fs47.default.renameSync(tmp, statePath);
1049427
+ import_fs48.default.renameSync(tmp, statePath);
1048998
1049428
  } catch {
1048999
- import_fs47.default.writeFileSync(statePath, import_fs47.default.readFileSync(tmp, "utf-8"));
1049429
+ import_fs48.default.writeFileSync(statePath, import_fs48.default.readFileSync(tmp, "utf-8"));
1049000
1049430
  try {
1049001
- import_fs47.default.unlinkSync(tmp);
1049431
+ import_fs48.default.unlinkSync(tmp);
1049002
1049432
  } catch {
1049003
1049433
  }
1049004
1049434
  }
@@ -1049016,13 +1049446,13 @@ async function recoverTasks() {
1049016
1049446
  cleaned++;
1049017
1049447
  try {
1049018
1049448
  const tmp = statePath + ".tmp";
1049019
- import_fs47.default.writeFileSync(tmp, JSON.stringify(state, null, 2));
1049449
+ import_fs48.default.writeFileSync(tmp, JSON.stringify(state, null, 2));
1049020
1049450
  try {
1049021
- import_fs47.default.renameSync(tmp, statePath);
1049451
+ import_fs48.default.renameSync(tmp, statePath);
1049022
1049452
  } catch {
1049023
- import_fs47.default.writeFileSync(statePath, JSON.stringify(state, null, 2));
1049453
+ import_fs48.default.writeFileSync(statePath, JSON.stringify(state, null, 2));
1049024
1049454
  try {
1049025
- import_fs47.default.unlinkSync(tmp);
1049455
+ import_fs48.default.unlinkSync(tmp);
1049026
1049456
  } catch {
1049027
1049457
  }
1049028
1049458
  }
@@ -1049055,164 +1049485,10 @@ async function recoverTasks() {
1049055
1049485
 
1049056
1049486
  // api/server.ts
1049057
1049487
  init_skillLoader();
1049058
-
1049059
- // core/memoryIds.ts
1049060
- var fs53 = __toESM(require("fs"));
1049061
- var path55 = __toESM(require("path"));
1049062
- var MEM_DIR = path55.join(process.cwd(), "workspace", "memory");
1049063
- var SEQUENCE_FILE = path55.join(MEM_DIR, "sequence.json");
1049064
- var RECORDS_FILE = path55.join(MEM_DIR, "records.jsonl");
1049065
- function _ensureDir() {
1049066
- fs53.mkdirSync(MEM_DIR, { recursive: true });
1049067
- }
1049068
- function _readSeq() {
1049069
- try {
1049070
- if (!fs53.existsSync(SEQUENCE_FILE)) return 0;
1049071
- const d = JSON.parse(fs53.readFileSync(SEQUENCE_FILE, "utf-8"));
1049072
- return typeof d.next === "number" ? d.next : 0;
1049073
- } catch {
1049074
- return 0;
1049075
- }
1049076
- }
1049077
- function _writeSeq(n) {
1049078
- _ensureDir();
1049079
- fs53.writeFileSync(SEQUENCE_FILE, JSON.stringify({ next: n }), "utf-8");
1049080
- }
1049081
- function nextId() {
1049082
- const n = _readSeq();
1049083
- _writeSeq(n + 1);
1049084
- return `mem_${String(n + 1).padStart(6, "0")}`;
1049085
- }
1049086
- function appendRecord(record2) {
1049087
- _ensureDir();
1049088
- fs53.appendFileSync(RECORDS_FILE, JSON.stringify(record2) + "\n", "utf-8");
1049089
- }
1049090
- function loadAllRecords() {
1049091
- try {
1049092
- if (!fs53.existsSync(RECORDS_FILE)) return [];
1049093
- return fs53.readFileSync(RECORDS_FILE, "utf-8").split("\n").filter((l2) => l2.trim()).map((l2) => {
1049094
- try {
1049095
- return JSON.parse(l2);
1049096
- } catch {
1049097
- return null;
1049098
- }
1049099
- }).filter((r) => r !== null);
1049100
- } catch {
1049101
- return [];
1049102
- }
1049103
- }
1049104
- function loadRecordById(id) {
1049105
- const all3 = loadAllRecords();
1049106
- return all3.find((r) => r.id === id) ?? null;
1049107
- }
1049108
- function removeRecords(predicate) {
1049109
- const all3 = loadAllRecords();
1049110
- const kept = all3.filter((r) => !predicate(r));
1049111
- const removed = all3.length - kept.length;
1049112
- if (removed > 0) {
1049113
- _ensureDir();
1049114
- fs53.writeFileSync(
1049115
- RECORDS_FILE,
1049116
- kept.map((r) => JSON.stringify(r)).join("\n") + (kept.length ? "\n" : ""),
1049117
- "utf-8"
1049118
- );
1049119
- }
1049120
- return removed;
1049121
- }
1049122
- function assignId(partial2) {
1049123
- const record2 = {
1049124
- id: partial2.id ?? nextId(),
1049125
- timestamp: partial2.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
1049126
- type: partial2.type ?? "observation",
1049127
- content: partial2.content ?? "",
1049128
- summary: partial2.summary ?? _autoSummary(partial2.content ?? ""),
1049129
- sessionId: partial2.sessionId,
1049130
- tags: partial2.tags,
1049131
- entityRefs: partial2.entityRefs
1049132
- };
1049133
- appendRecord(record2);
1049134
- return record2;
1049135
- }
1049136
- function _autoSummary(content) {
1049137
- const first = content.split("\n").find((l2) => l2.trim()) ?? content;
1049138
- return first.slice(0, 100).trim();
1049139
- }
1049140
- function runMigrationIfNeeded() {
1049141
- if (fs53.existsSync(RECORDS_FILE)) return 0;
1049142
- _ensureDir();
1049143
- const records = [];
1049144
- try {
1049145
- const raw = fs53.readFileSync(path55.join(MEM_DIR, "memory.json"), "utf-8");
1049146
- const parsed = JSON.parse(raw);
1049147
- const items = Array.isArray(parsed) ? parsed : parsed.value ?? [];
1049148
- for (const item of items) {
1049149
- const v = item.value ?? {};
1049150
- const content = [
1049151
- v.goal ? `Goal: ${v.goal}` : "",
1049152
- v.result ? `Result: ${String(v.result).slice(0, 800)}` : "",
1049153
- v.role ? `Role: ${v.role}` : ""
1049154
- ].filter(Boolean).join("\n");
1049155
- if (!content) continue;
1049156
- records.push({
1049157
- timestamp: item.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1049158
- type: item.tags?.includes("task") ? "interaction" : "observation",
1049159
- content,
1049160
- summary: _autoSummary(v.goal ?? v.result ?? content),
1049161
- tags: item.tags ?? []
1049162
- });
1049163
- }
1049164
- } catch {
1049165
- }
1049166
- try {
1049167
- const raw = fs53.readFileSync(
1049168
- path55.join(process.cwd(), "workspace", "conversation-memory.json"),
1049169
- "utf-8"
1049170
- );
1049171
- const parsed = JSON.parse(raw);
1049172
- const msgs = parsed.messages ?? [];
1049173
- for (const msg of msgs) {
1049174
- if (msg.role !== "assistant") continue;
1049175
- const content = String(msg.content ?? "").trim();
1049176
- if (content.length < 20) continue;
1049177
- records.push({
1049178
- timestamp: msg.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
1049179
- type: "interaction",
1049180
- content: content.slice(0, 1e3),
1049181
- summary: _autoSummary(content),
1049182
- sessionId: msg.sessionId,
1049183
- tags: ["conversation"]
1049184
- });
1049185
- }
1049186
- } catch {
1049187
- }
1049188
- try {
1049189
- const raw = fs53.readFileSync(path55.join(MEM_DIR, "MEMORY_INDEX.md"), "utf-8");
1049190
- const lines = raw.split("\n").filter((l2) => l2.startsWith("- "));
1049191
- for (const line of lines) {
1049192
- const cleaned = line.replace(/^-\s*/, "").trim();
1049193
- if (cleaned.length < 10) continue;
1049194
- records.push({
1049195
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1049196
- type: "fact",
1049197
- content: cleaned,
1049198
- summary: cleaned.slice(0, 100),
1049199
- tags: ["index"]
1049200
- });
1049201
- }
1049202
- } catch {
1049203
- }
1049204
- records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
1049205
- let count = 0;
1049206
- for (const rec of records) {
1049207
- const id = nextId();
1049208
- const record2 = { id, ...rec };
1049209
- appendRecord(record2);
1049210
- count++;
1049211
- }
1049212
- return count;
1049213
- }
1049488
+ init_memoryIds();
1049214
1049489
 
1049215
1049490
  // core/memoryQuery.ts
1049491
+ init_memoryIds();
1049216
1049492
  var _sessionCitations = /* @__PURE__ */ new Map();
1049217
1049493
  function trackCitation(id, summary) {
1049218
1049494
  const c = _sessionCitations.get(id);
@@ -1049310,11 +1049586,11 @@ init_knowledgeBase();
1049310
1049586
  init_youtubeTranscript();
1049311
1049587
 
1049312
1049588
  // core/importers.ts
1049313
- var import_fs48 = __toESM(require("fs"));
1049314
- var import_path50 = __toESM(require("path"));
1049589
+ var import_fs49 = __toESM(require("fs"));
1049590
+ var import_path51 = __toESM(require("path"));
1049315
1049591
  init_knowledgeBase();
1049316
1049592
  var WORKSPACE_ROOT2 = process.env.AIDEN_USER_DATA || process.cwd();
1049317
- var MEMORY_DIR4 = import_path50.default.join(WORKSPACE_ROOT2, "workspace", "memory");
1049593
+ var MEMORY_DIR4 = import_path51.default.join(WORKSPACE_ROOT2, "workspace", "memory");
1049318
1049594
  async function importChatGPT(filePath) {
1049319
1049595
  const result = {
1049320
1049596
  source: "chatgpt",
@@ -1049323,7 +1049599,7 @@ async function importChatGPT(filePath) {
1049323
1049599
  errors: []
1049324
1049600
  };
1049325
1049601
  try {
1049326
- const raw = import_fs48.default.readFileSync(filePath, "utf8");
1049602
+ const raw = import_fs49.default.readFileSync(filePath, "utf8");
1049327
1049603
  const conversations = JSON.parse(raw);
1049328
1049604
  if (!Array.isArray(conversations)) {
1049329
1049605
  result.errors.push("Invalid format: expected array of conversations");
@@ -1049373,9 +1049649,9 @@ async function importChatGPT(filePath) {
1049373
1049649
  function findMdFiles(dir) {
1049374
1049650
  const files = [];
1049375
1049651
  try {
1049376
- const entries = import_fs48.default.readdirSync(dir, { withFileTypes: true });
1049652
+ const entries = import_fs49.default.readdirSync(dir, { withFileTypes: true });
1049377
1049653
  for (const entry of entries) {
1049378
- const fullPath = import_path50.default.join(dir, entry.name);
1049654
+ const fullPath = import_path51.default.join(dir, entry.name);
1049379
1049655
  if (entry.isDirectory() && !entry.name.startsWith(".")) {
1049380
1049656
  files.push(...findMdFiles(fullPath));
1049381
1049657
  } else if (entry.name.endsWith(".md")) {
@@ -1049393,16 +1049669,16 @@ async function importOpenClaw(directoryPath) {
1049393
1049669
  memoriesExtracted: 0,
1049394
1049670
  errors: []
1049395
1049671
  };
1049396
- if (!import_fs48.default.existsSync(directoryPath)) {
1049672
+ if (!import_fs49.default.existsSync(directoryPath)) {
1049397
1049673
  result.errors.push(`Directory not found: ${directoryPath}`);
1049398
1049674
  return result;
1049399
1049675
  }
1049400
1049676
  const mdFiles = findMdFiles(directoryPath);
1049401
1049677
  for (const file of mdFiles) {
1049402
1049678
  try {
1049403
- const content = import_fs48.default.readFileSync(file, "utf8");
1049679
+ const content = import_fs49.default.readFileSync(file, "utf8");
1049404
1049680
  if (content.trim().length < 50) continue;
1049405
- const basename5 = import_path50.default.basename(file, ".md");
1049681
+ const basename5 = import_path51.default.basename(file, ".md");
1049406
1049682
  const lower = file.toLowerCase();
1049407
1049683
  const isMemory = lower.includes("memory");
1049408
1049684
  const isLesson = lower.includes("lesson");
@@ -1049423,11 +1049699,11 @@ async function importOpenClaw(directoryPath) {
1049423
1049699
  }
1049424
1049700
  if (isMemory || isLesson) {
1049425
1049701
  try {
1049426
- import_fs48.default.mkdirSync(MEMORY_DIR4, { recursive: true });
1049702
+ import_fs49.default.mkdirSync(MEMORY_DIR4, { recursive: true });
1049427
1049703
  const destName = `imported_${basename5.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 60)}.md`;
1049428
- const destPath = import_path50.default.join(MEMORY_DIR4, destName);
1049429
- if (!import_fs48.default.existsSync(destPath)) {
1049430
- import_fs48.default.writeFileSync(
1049704
+ const destPath = import_path51.default.join(MEMORY_DIR4, destName);
1049705
+ if (!import_fs49.default.existsSync(destPath)) {
1049706
+ import_fs49.default.writeFileSync(
1049431
1049707
  destPath,
1049432
1049708
  `<!-- source: openclaw_import | confidence: 0.7 -->
1049433
1049709
  ${content}`,
@@ -1049440,7 +1049716,7 @@ ${content}`,
1049440
1049716
  }
1049441
1049717
  }
1049442
1049718
  } catch (err) {
1049443
- result.errors.push(`Failed: ${import_path50.default.basename(file)}`);
1049719
+ result.errors.push(`Failed: ${import_path51.default.basename(file)}`);
1049444
1049720
  }
1049445
1049721
  }
1049446
1049722
  console.log(
@@ -1049524,9 +1049800,9 @@ init_morningBriefing();
1049524
1049800
  init_memoryRecall();
1049525
1049801
 
1049526
1049802
  // core/lessonsBrowser.ts
1049527
- var import_fs49 = __toESM(require("fs"));
1049528
- var import_path51 = __toESM(require("path"));
1049529
- var LESSONS_PATH2 = import_path51.default.join(process.cwd(), "workspace", "LESSONS.md");
1049803
+ var import_fs50 = __toESM(require("fs"));
1049804
+ var import_path52 = __toESM(require("path"));
1049805
+ var LESSONS_PATH3 = import_path52.default.join(process.cwd(), "workspace", "LESSONS.md");
1049530
1049806
  var CATEGORY_RULES = [
1049531
1049807
  [/web_search|search|query|url/i, "web"],
1049532
1049808
  [/shell_exec|run_python|command|bash/i, "shell"],
@@ -1049546,7 +1049822,7 @@ function inferCategory(text) {
1049546
1049822
  function parseLessons() {
1049547
1049823
  let raw = "";
1049548
1049824
  try {
1049549
- raw = import_fs49.default.readFileSync(LESSONS_PATH2, "utf-8");
1049825
+ raw = import_fs50.default.readFileSync(LESSONS_PATH3, "utf-8");
1049550
1049826
  } catch {
1049551
1049827
  return [];
1049552
1049828
  }
@@ -1049585,12 +1049861,12 @@ function appendLesson2(text) {
1049585
1049861
  const entry = `${id}. [${date3}] ${text}
1049586
1049862
  `;
1049587
1049863
  try {
1049588
- if (!import_fs49.default.existsSync(LESSONS_PATH2)) {
1049864
+ if (!import_fs50.default.existsSync(LESSONS_PATH3)) {
1049589
1049865
  const header = "# LESSONS.md \u2014 Permanent Failure Rules\n# Auto-appended after task failures.\n\n## Rules\n\n";
1049590
- import_fs49.default.mkdirSync(import_path51.default.dirname(LESSONS_PATH2), { recursive: true });
1049591
- import_fs49.default.writeFileSync(LESSONS_PATH2, header + entry, "utf-8");
1049866
+ import_fs50.default.mkdirSync(import_path52.default.dirname(LESSONS_PATH3), { recursive: true });
1049867
+ import_fs50.default.writeFileSync(LESSONS_PATH3, header + entry, "utf-8");
1049592
1049868
  } else {
1049593
- import_fs49.default.appendFileSync(LESSONS_PATH2, entry, "utf-8");
1049869
+ import_fs50.default.appendFileSync(LESSONS_PATH3, entry, "utf-8");
1049594
1049870
  }
1049595
1049871
  } catch {
1049596
1049872
  }
@@ -1050148,13 +1050424,13 @@ function getCatalog() {
1050148
1050424
  init_permissionSystem();
1050149
1050425
 
1050150
1050426
  // core/aidenIdentity.ts
1050151
- var import_fs51 = __toESM(require("fs"));
1050152
- var import_path53 = __toESM(require("path"));
1050427
+ var import_fs52 = __toESM(require("fs"));
1050428
+ var import_path54 = __toESM(require("path"));
1050153
1050429
  init_skillTeacher();
1050154
1050430
  init_eventBus();
1050155
- var IDENTITY_PATH = import_path53.default.join(process.cwd(), "workspace", "identity.json");
1050156
- var AUDIT_PATH2 = import_path53.default.join(process.cwd(), "workspace", "audit", "audit.jsonl");
1050157
- var SESSIONS_DIR4 = import_path53.default.join(process.cwd(), "workspace", "sessions");
1050431
+ var IDENTITY_PATH = import_path54.default.join(process.cwd(), "workspace", "identity.json");
1050432
+ var AUDIT_PATH2 = import_path54.default.join(process.cwd(), "workspace", "audit", "audit.jsonl");
1050433
+ var SESSIONS_DIR4 = import_path54.default.join(process.cwd(), "workspace", "sessions");
1050158
1050434
  var LEVEL_THRESHOLDS = [0, 10, 50, 200, 500];
1050159
1050435
  var TITLES = ["Apprentice", "Assistant", "Specialist", "Expert", "Architect"];
1050160
1050436
  function computeLevel(xp) {
@@ -1050177,8 +1050453,8 @@ function computeProgress(xp, level) {
1050177
1050453
  }
1050178
1050454
  function computeXP() {
1050179
1050455
  try {
1050180
- if (!import_fs51.default.existsSync(AUDIT_PATH2)) return 0;
1050181
- return import_fs51.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean).map((l2) => {
1050456
+ if (!import_fs52.default.existsSync(AUDIT_PATH2)) return 0;
1050457
+ return import_fs52.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean).map((l2) => {
1050182
1050458
  try {
1050183
1050459
  return JSON.parse(l2);
1050184
1050460
  } catch {
@@ -1050191,8 +1050467,8 @@ function computeXP() {
1050191
1050467
  }
1050192
1050468
  function computeTopStrength() {
1050193
1050469
  try {
1050194
- if (!import_fs51.default.existsSync(AUDIT_PATH2)) return "Research";
1050195
- const entries = import_fs51.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean).map((l2) => {
1050470
+ if (!import_fs52.default.existsSync(AUDIT_PATH2)) return "Research";
1050471
+ const entries = import_fs52.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean).map((l2) => {
1050196
1050472
  try {
1050197
1050473
  return JSON.parse(l2);
1050198
1050474
  } catch {
@@ -1050219,20 +1050495,20 @@ function computeTopStrength() {
1050219
1050495
  }
1050220
1050496
  function computeStreakDays() {
1050221
1050497
  try {
1050222
- if (!import_fs51.default.existsSync(SESSIONS_DIR4)) return 0;
1050498
+ if (!import_fs52.default.existsSync(SESSIONS_DIR4)) return 0;
1050223
1050499
  const sessionDates = /* @__PURE__ */ new Set();
1050224
- for (const f of import_fs51.default.readdirSync(SESSIONS_DIR4)) {
1050500
+ for (const f of import_fs52.default.readdirSync(SESSIONS_DIR4)) {
1050225
1050501
  if (!f.endsWith(".md")) continue;
1050226
1050502
  try {
1050227
- const mtime = import_fs51.default.statSync(import_path53.default.join(SESSIONS_DIR4, f)).mtime;
1050503
+ const mtime = import_fs52.default.statSync(import_path54.default.join(SESSIONS_DIR4, f)).mtime;
1050228
1050504
  sessionDates.add(mtime.toISOString().slice(0, 10));
1050229
1050505
  } catch {
1050230
1050506
  }
1050231
1050507
  }
1050232
1050508
  if (sessionDates.size === 0) return 0;
1050233
1050509
  const auditDates = /* @__PURE__ */ new Set();
1050234
- if (import_fs51.default.existsSync(AUDIT_PATH2)) {
1050235
- for (const line of import_fs51.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean)) {
1050510
+ if (import_fs52.default.existsSync(AUDIT_PATH2)) {
1050511
+ for (const line of import_fs52.default.readFileSync(AUDIT_PATH2, "utf-8").trim().split("\n").filter(Boolean)) {
1050236
1050512
  try {
1050237
1050513
  const e = JSON.parse(line);
1050238
1050514
  if (e.ts) auditDates.add(new Date(e.ts).toISOString().slice(0, 10));
@@ -1050282,8 +1050558,8 @@ function computeIdentity() {
1050282
1050558
  function refreshIdentity() {
1050283
1050559
  const identity = computeIdentity();
1050284
1050560
  try {
1050285
- import_fs51.default.mkdirSync(import_path53.default.dirname(IDENTITY_PATH), { recursive: true });
1050286
- import_fs51.default.writeFileSync(IDENTITY_PATH, JSON.stringify(identity, null, 2));
1050561
+ import_fs52.default.mkdirSync(import_path54.default.dirname(IDENTITY_PATH), { recursive: true });
1050562
+ import_fs52.default.writeFileSync(IDENTITY_PATH, JSON.stringify(identity, null, 2));
1050287
1050563
  } catch (e) {
1050288
1050564
  console.error("[AidenIdentity] Write failed:", e.message);
1050289
1050565
  }
@@ -1050295,8 +1050571,8 @@ function refreshIdentity() {
1050295
1050571
  }
1050296
1050572
  function loadIdentity() {
1050297
1050573
  try {
1050298
- if (!import_fs51.default.existsSync(IDENTITY_PATH)) return null;
1050299
- return JSON.parse(import_fs51.default.readFileSync(IDENTITY_PATH, "utf-8"));
1050574
+ if (!import_fs52.default.existsSync(IDENTITY_PATH)) return null;
1050575
+ return JSON.parse(import_fs52.default.readFileSync(IDENTITY_PATH, "utf-8"));
1050300
1050576
  } catch {
1050301
1050577
  return null;
1050302
1050578
  }
@@ -1050305,7 +1050581,7 @@ function getIdentity() {
1050305
1050581
  return loadIdentity() ?? refreshIdentity();
1050306
1050582
  }
1050307
1050583
  try {
1050308
- import_fs51.default.mkdirSync(import_path53.default.dirname(IDENTITY_PATH), { recursive: true });
1050584
+ import_fs52.default.mkdirSync(import_path54.default.dirname(IDENTITY_PATH), { recursive: true });
1050309
1050585
  } catch {
1050310
1050586
  }
1050311
1050587
 
@@ -1050497,8 +1050773,8 @@ function registerTelegramCallbacks(bot) {
1050497
1050773
  }
1050498
1050774
 
1050499
1050775
  // core/memoryDistiller.ts
1050500
- var import_fs52 = __toESM(require("fs"));
1050501
- var import_path54 = __toESM(require("path"));
1050776
+ var import_fs53 = __toESM(require("fs"));
1050777
+ var import_path55 = __toESM(require("path"));
1050502
1050778
  init_conversationMemory();
1050503
1050779
  init_semanticMemory();
1050504
1050780
  init_agentLoop();
@@ -1050518,7 +1050794,7 @@ No headings, no explanations, no blank lines between facts.
1050518
1050794
  Facts must be self-contained (understandable without the conversation).
1050519
1050795
  Maximum 15 facts. Minimum 5 facts if the conversation has meaningful content.`;
1050520
1050796
  var MAX_TRANSCRIPT_CHARS = 32e3;
1050521
- var DISTILL_MARKER_PATH = import_path54.default.join(process.cwd(), "workspace", "distilled_sessions.json");
1050797
+ var DISTILL_MARKER_PATH = import_path55.default.join(process.cwd(), "workspace", "distilled_sessions.json");
1050522
1050798
  async function distillSession(sessionId, timeoutMs = 15e3) {
1050523
1050799
  try {
1050524
1050800
  conversationMemory.setSession(sessionId);
@@ -1050581,8 +1050857,8 @@ async function distillAllActiveSessions(timeoutMs = 8e3) {
1050581
1050857
  }
1050582
1050858
  function loadDistilledSet() {
1050583
1050859
  try {
1050584
- if (import_fs52.default.existsSync(DISTILL_MARKER_PATH)) {
1050585
- return new Set(JSON.parse(import_fs52.default.readFileSync(DISTILL_MARKER_PATH, "utf-8")));
1050860
+ if (import_fs53.default.existsSync(DISTILL_MARKER_PATH)) {
1050861
+ return new Set(JSON.parse(import_fs53.default.readFileSync(DISTILL_MARKER_PATH, "utf-8")));
1050586
1050862
  }
1050587
1050863
  } catch {
1050588
1050864
  }
@@ -1050595,15 +1050871,15 @@ function markDistilled(sessionId) {
1050595
1050871
  try {
1050596
1050872
  const set2 = loadDistilledSet();
1050597
1050873
  set2.add(sessionId);
1050598
- import_fs52.default.mkdirSync(import_path54.default.dirname(DISTILL_MARKER_PATH), { recursive: true });
1050599
- import_fs52.default.writeFileSync(DISTILL_MARKER_PATH, JSON.stringify([...set2], null, 2) + "\n", "utf-8");
1050874
+ import_fs53.default.mkdirSync(import_path55.default.dirname(DISTILL_MARKER_PATH), { recursive: true });
1050875
+ import_fs53.default.writeFileSync(DISTILL_MARKER_PATH, JSON.stringify([...set2], null, 2) + "\n", "utf-8");
1050600
1050876
  } catch {
1050601
1050877
  }
1050602
1050878
  }
1050603
1050879
 
1050604
1050880
  // core/failureAnalyzer.ts
1050605
- var import_fs53 = __toESM(require("fs"));
1050606
- var import_path55 = __toESM(require("path"));
1050881
+ var import_fs54 = __toESM(require("fs"));
1050882
+ var import_path56 = __toESM(require("path"));
1050607
1050883
  var FAILURE_KEYWORDS = [
1050608
1050884
  "that's wrong",
1050609
1050885
  "thats wrong",
@@ -1050686,10 +1050962,10 @@ function _degradeSkill(skillName, rootCause) {
1050686
1050962
  const cwd = process.cwd();
1050687
1050963
  const folders = ["learned", "approved", "installed"];
1050688
1050964
  for (const folder of folders) {
1050689
- const metaPath2 = import_path55.default.join(cwd, "workspace", "skills", folder, skillName, "meta.json");
1050690
- if (!import_fs53.default.existsSync(metaPath2)) continue;
1050965
+ const metaPath2 = import_path56.default.join(cwd, "workspace", "skills", folder, skillName, "meta.json");
1050966
+ if (!import_fs54.default.existsSync(metaPath2)) continue;
1050691
1050967
  try {
1050692
- const meta = JSON.parse(import_fs53.default.readFileSync(metaPath2, "utf-8"));
1050968
+ const meta = JSON.parse(import_fs54.default.readFileSync(metaPath2, "utf-8"));
1050693
1050969
  meta.failCount = (meta.failCount ?? 0) + 1;
1050694
1050970
  meta.lastFailureReason = rootCause;
1050695
1050971
  meta.confidence = Math.max(0.1, (meta.confidence ?? 1) - 0.15);
@@ -1050697,7 +1050973,7 @@ function _degradeSkill(skillName, rootCause) {
1050697
1050973
  meta.deprecated = true;
1050698
1050974
  console.warn(`[failureAnalyzer] skill "${skillName}" auto-deprecated after ${meta.failCount} failures`);
1050699
1050975
  }
1050700
- import_fs53.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
1050976
+ import_fs54.default.writeFileSync(metaPath2, JSON.stringify(meta, null, 2) + "\n", "utf-8");
1050701
1050977
  console.log(`[failureAnalyzer] degraded skill "${skillName}" \u2192 confidence ${meta.confidence.toFixed(2)}, failCount ${meta.failCount}`);
1050702
1050978
  } catch (e) {
1050703
1050979
  console.warn(`[failureAnalyzer] could not update meta for "${skillName}":`, e.message);
@@ -1050707,8 +1050983,8 @@ function _degradeSkill(skillName, rootCause) {
1050707
1050983
  }
1050708
1050984
 
1050709
1050985
  // core/sessionRouter.ts
1050710
- var import_fs54 = __toESM(require("fs"));
1050711
- var import_path56 = __toESM(require("path"));
1050986
+ var import_fs55 = __toESM(require("fs"));
1050987
+ var import_path57 = __toESM(require("path"));
1050712
1050988
  var SessionRouter = class {
1050713
1050989
  constructor() {
1050714
1050990
  this.sessions = /* @__PURE__ */ new Map();
@@ -1050749,15 +1051025,15 @@ var SessionRouter = class {
1050749
1051025
  getHistory(userId) {
1050750
1051026
  const sessionId = this.userToSession.get(userId);
1050751
1051027
  if (!sessionId) return [];
1050752
- const sessionFile = import_path56.default.join(
1051028
+ const sessionFile = import_path57.default.join(
1050753
1051029
  process.cwd(),
1050754
1051030
  "workspace",
1050755
1051031
  "sessions",
1050756
1051032
  `${sessionId}.json`
1050757
1051033
  );
1050758
- if (import_fs54.default.existsSync(sessionFile)) {
1051034
+ if (import_fs55.default.existsSync(sessionFile)) {
1050759
1051035
  try {
1050760
- const data = JSON.parse(import_fs54.default.readFileSync(sessionFile, "utf8"));
1051036
+ const data = JSON.parse(import_fs55.default.readFileSync(sessionFile, "utf8"));
1050761
1051037
  return data.messages || [];
1050762
1051038
  } catch {
1050763
1051039
  }
@@ -1050883,8 +1051159,8 @@ var Gateway = class {
1050883
1051159
  var gateway = new Gateway();
1050884
1051160
 
1050885
1051161
  // core/agentShield.ts
1050886
- var import_fs55 = __toESM(require("fs"));
1050887
- var import_path57 = __toESM(require("path"));
1051162
+ var import_fs56 = __toESM(require("fs"));
1051163
+ var import_path58 = __toESM(require("path"));
1050888
1051164
  var WORKSPACE_ROOT3 = process.env.AIDEN_USER_DATA || process.cwd();
1050889
1051165
  var INJECTION_PATTERNS2 = [
1050890
1051166
  { pattern: /ignore\s+(all\s+)?(previous|above|prior)/i, desc: "Prompt injection: ignore previous instructions" },
@@ -1050924,26 +1051200,26 @@ async function runSecurityScan() {
1050924
1051200
  let toolsScanned = 0;
1050925
1051201
  let configsScanned = 0;
1050926
1051202
  const skillDirs = [
1050927
- import_path57.default.join(WORKSPACE_ROOT3, "skills"),
1050928
- import_path57.default.join(WORKSPACE_ROOT3, "workspace", "skills"),
1050929
- import_path57.default.join(WORKSPACE_ROOT3, "workspace", "skills", "learned"),
1050930
- import_path57.default.join(WORKSPACE_ROOT3, "workspace", "skills", "approved")
1051203
+ import_path58.default.join(WORKSPACE_ROOT3, "skills"),
1051204
+ import_path58.default.join(WORKSPACE_ROOT3, "workspace", "skills"),
1051205
+ import_path58.default.join(WORKSPACE_ROOT3, "workspace", "skills", "learned"),
1051206
+ import_path58.default.join(WORKSPACE_ROOT3, "workspace", "skills", "approved")
1050931
1051207
  ];
1050932
1051208
  for (const dir of skillDirs) {
1050933
- if (!import_fs55.default.existsSync(dir)) continue;
1051209
+ if (!import_fs56.default.existsSync(dir)) continue;
1050934
1051210
  let entries;
1050935
1051211
  try {
1050936
- entries = import_fs55.default.readdirSync(dir, { withFileTypes: true });
1051212
+ entries = import_fs56.default.readdirSync(dir, { withFileTypes: true });
1050937
1051213
  } catch {
1050938
1051214
  continue;
1050939
1051215
  }
1050940
1051216
  for (const entry of entries) {
1050941
- const skillPath = entry.isDirectory() ? import_path57.default.join(dir, entry.name, "SKILL.md") : entry.name.endsWith(".md") ? import_path57.default.join(dir, entry.name) : "";
1050942
- if (!skillPath || !import_fs55.default.existsSync(skillPath)) continue;
1051217
+ const skillPath = entry.isDirectory() ? import_path58.default.join(dir, entry.name, "SKILL.md") : entry.name.endsWith(".md") ? import_path58.default.join(dir, entry.name) : "";
1051218
+ if (!skillPath || !import_fs56.default.existsSync(skillPath)) continue;
1050943
1051219
  const relPath = `skills/${entry.name}${entry.isDirectory() ? "/SKILL.md" : ""}`;
1050944
1051220
  let content;
1050945
1051221
  try {
1050946
- content = import_fs55.default.readFileSync(skillPath, "utf8");
1051222
+ content = import_fs56.default.readFileSync(skillPath, "utf8");
1050947
1051223
  } catch {
1050948
1051224
  continue;
1050949
1051225
  }
@@ -1050980,11 +1051256,11 @@ async function runSecurityScan() {
1050980
1051256
  }
1050981
1051257
  }
1050982
1051258
  configsScanned++;
1050983
- const configPath = import_path57.default.join(WORKSPACE_ROOT3, "config", "devos.config.json");
1050984
- if (import_fs55.default.existsSync(configPath)) {
1051259
+ const configPath = import_path58.default.join(WORKSPACE_ROOT3, "config", "devos.config.json");
1051260
+ if (import_fs56.default.existsSync(configPath)) {
1050985
1051261
  let config2 = "";
1050986
1051262
  try {
1050987
- config2 = import_fs55.default.readFileSync(configPath, "utf8");
1051263
+ config2 = import_fs56.default.readFileSync(configPath, "utf8");
1050988
1051264
  } catch {
1050989
1051265
  }
1050990
1051266
  if (config2 && RAW_KEY_PATTERN.test(config2)) {
@@ -1051004,11 +1051280,11 @@ async function runSecurityScan() {
1051004
1051280
  { name: "LESSONS.md", critical: false }
1051005
1051281
  ];
1051006
1051282
  for (const { name, critical } of sensitiveFiles) {
1051007
- const filePath = import_path57.default.join(WORKSPACE_ROOT3, "workspace", name);
1051008
- if (!import_fs55.default.existsSync(filePath)) continue;
1051283
+ const filePath = import_path58.default.join(WORKSPACE_ROOT3, "workspace", name);
1051284
+ if (!import_fs56.default.existsSync(filePath)) continue;
1051009
1051285
  let content = "";
1051010
1051286
  try {
1051011
- content = import_fs55.default.readFileSync(filePath, "utf8");
1051287
+ content = import_fs56.default.readFileSync(filePath, "utf8");
1051012
1051288
  } catch {
1051013
1051289
  continue;
1051014
1051290
  }
@@ -1051142,193 +1051418,8 @@ var AsyncTaskManager = class {
1051142
1051418
  };
1051143
1051419
  var asyncTasks = new AsyncTaskManager();
1051144
1051420
 
1051145
- // core/slashAsTool.ts
1051146
- var import_fs56 = __toESM(require("fs"));
1051147
- var import_path58 = __toESM(require("path"));
1051148
- var import_os5 = __toESM(require("os"));
1051149
- init_toolRegistry();
1051150
- init_conversationMemory();
1051151
- init_learningMemory();
1051152
- init_skillLoader();
1051153
- init_costTracker();
1051154
- init_goalTracker();
1051155
- init_providers();
1051156
- var LESSONS_PATH3 = import_path58.default.join(process.cwd(), "workspace", "LESSONS.md");
1051157
- function loadLessonsText() {
1051158
- try {
1051159
- if (import_fs56.default.existsSync(LESSONS_PATH3)) return import_fs56.default.readFileSync(LESSONS_PATH3, "utf-8").trim();
1051160
- } catch {
1051161
- }
1051162
- return "";
1051163
- }
1051164
- async function toolStatus(_2) {
1051165
- const uptimeSec = Math.floor(process.uptime());
1051166
- const ramMB = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
1051167
- const sessions = conversationMemory.getSessions().length;
1051168
- const lines = [
1051169
- "SYSTEM STATUS",
1051170
- `Uptime ${Math.floor(uptimeSec / 60)}m ${uptimeSec % 60}s`,
1051171
- `RAM ${ramMB} MB`,
1051172
- `Sessions ${sessions}`,
1051173
- `Platform ${import_os5.default.platform()} ${import_os5.default.arch()}`,
1051174
- `Node ${process.version}`
1051175
- ];
1051176
- return { success: true, output: lines.join("\n") };
1051177
- }
1051178
- async function toolAnalytics(_2) {
1051179
- const stats = learningMemory.getStats();
1051180
- const lines = [
1051181
- "LEARNING ANALYTICS",
1051182
- `Total tasks ${stats.total}`,
1051183
- `Success rate ${stats.successRate}%`,
1051184
- `Avg duration ${stats.avgDuration}ms`
1051185
- ];
1051186
- return { success: true, output: lines.join("\n") };
1051187
- }
1051188
- async function toolSpend(_2) {
1051189
- try {
1051190
- const summary = costTracker.getDailySummary();
1051191
- const byProvider = Object.entries(summary.byProvider || {}).map(([p, c]) => ` ${p}: $${c.toFixed(4)}`).join("\n");
1051192
- const lines = [
1051193
- `SPEND \u2014 ${summary.date}`,
1051194
- `Total $${summary.totalUSD.toFixed(4)}`,
1051195
- `User $${summary.userUSD.toFixed(4)}`,
1051196
- `System $${summary.systemUSD.toFixed(4)}`,
1051197
- byProvider ? `By provider:
1051198
- ${byProvider}` : ""
1051199
- ].filter(Boolean);
1051200
- return { success: true, output: lines.join("\n") };
1051201
- } catch {
1051202
- return { success: true, output: "Spend data unavailable." };
1051203
- }
1051204
- }
1051205
- async function toolMemoryShow(_2) {
1051206
- const facts = conversationMemory.getFacts();
1051207
- const history2 = conversationMemory.getRecentHistory();
1051208
- const lines = [
1051209
- "MEMORY FACTS",
1051210
- facts.lastFilesCreated.length ? `Files created : ${facts.lastFilesCreated.join(", ")}` : "",
1051211
- facts.lastSearchQueries.length ? `Last searches : ${facts.lastSearchQueries.join(", ")}` : "",
1051212
- facts.lastToolsUsed.length ? `Last tools : ${facts.lastToolsUsed.join(", ")}` : "",
1051213
- facts.mentionedEntities.length ? `Topics : ${facts.mentionedEntities.slice(-10).join(", ")}` : "",
1051214
- "",
1051215
- `Recent exchanges: ${history2.length}`,
1051216
- ...history2.slice(-3).map(
1051217
- (e) => e.userMessage ? ` User: ${e.userMessage.slice(0, 80)}` : ""
1051218
- ).filter(Boolean)
1051219
- ].filter((l2) => l2 !== void 0);
1051220
- return { success: true, output: lines.join("\n") };
1051221
- }
1051222
- async function toolLessons(_2) {
1051223
- const lessons = loadLessonsText();
1051224
- if (!lessons) return { success: true, output: "No lessons recorded yet." };
1051225
- return { success: true, output: `LESSONS (permanent failure rules):
1051226
- ${lessons}` };
1051227
- }
1051228
- async function toolSkillsList(_2) {
1051229
- const skills = skillLoader.loadAll();
1051230
- if (skills.length === 0) return { success: true, output: "No skills loaded." };
1051231
- const lines = [
1051232
- `SKILLS (${skills.length} loaded)`,
1051233
- ...skills.map((s) => ` ${s.name.padEnd(20)} ${s.description || ""}`)
1051234
- ];
1051235
- return { success: true, output: lines.join("\n") };
1051236
- }
1051237
- async function toolToolsList(_2) {
1051238
- const { TOOLS: TOOLS3 } = await Promise.resolve().then(() => (init_toolRegistry(), toolRegistry_exports));
1051239
- const names = Object.keys(TOOLS3).sort();
1051240
- return { success: true, output: `TOOLS (${names.length}):
1051241
- ${names.join(", ")}` };
1051242
- }
1051243
- async function toolWhoami(_2) {
1051244
- const cfg = loadConfig();
1051245
- const userName = cfg.userName || process.env.USERNAME || import_os5.default.userInfo().username || "User";
1051246
- const homeDir = import_os5.default.homedir();
1051247
- const lines = [
1051248
- "USER PROFILE",
1051249
- `Name ${userName}`,
1051250
- `Home ${homeDir}`,
1051251
- `Platform ${import_os5.default.platform()}`
1051252
- ];
1051253
- return { success: true, output: lines.join("\n") };
1051254
- }
1051255
- async function toolChannelsStatus(_2) {
1051256
- try {
1051257
- const cfg = loadConfig();
1051258
- const apis = cfg?.providers?.apis || [];
1051259
- const lines = [
1051260
- "PROVIDER CHANNELS",
1051261
- ...apis.map((api) => {
1051262
- const key2 = String(api.key || "");
1051263
- const hasKey = key2.startsWith("env:") ? !!(process.env[key2.replace("env:", "")] || "").trim() : key2.trim().length > 0;
1051264
- const status = !api.enabled ? "disabled" : api.rateLimited ? "rate-limited" : hasKey ? "active" : "no key";
1051265
- return ` ${(api.name || api.provider || "").padEnd(20)} ${api.model || ""} [${status}]`;
1051266
- })
1051267
- ];
1051268
- return { success: true, output: lines.join("\n") };
1051269
- } catch {
1051270
- return { success: true, output: "Provider status unavailable." };
1051271
- }
1051272
- }
1051273
- async function toolMemoryStore(input) {
1051274
- const fact = String(
1051275
- input?.fact || input?.content || input?.text || input?.preference || input?.value || input?.memory || input?.note || input?.data || input?.information || input?.detail || input?.message || input?.entry || input?.record || (input && typeof input === "object" ? Object.values(input).find((v) => typeof v === "string" && v.trim().length > 0) : "") || ""
1051276
- ).trim();
1051277
- if (!fact) return { success: false, output: 'No fact provided. Pass { fact: "the thing to remember" }' };
1051278
- const record2 = assignId({
1051279
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1051280
- type: input?.type ?? "fact",
1051281
- content: fact,
1051282
- summary: fact.slice(0, 100),
1051283
- tags: Array.isArray(input?.tags) ? input.tags : []
1051284
- });
1051285
- return { success: true, output: `Stored as ${record2.id}: ${record2.summary}` };
1051286
- }
1051287
- async function toolMemoryForget(input) {
1051288
- const keyword = String(
1051289
- input?.fact || input?.keyword || input?.content || input?.text || input?.query || input?.topic || input?.subject || (input && typeof input === "object" ? Object.values(input).find((v) => typeof v === "string" && v.trim().length > 0) : "") || ""
1051290
- ).trim().toLowerCase();
1051291
- if (!keyword)
1051292
- return { success: false, output: 'No keyword provided. Pass { fact: "thing to forget" }' };
1051293
- const removed = removeRecords(
1051294
- (r) => r.content.toLowerCase().includes(keyword) || r.summary.toLowerCase().includes(keyword)
1051295
- );
1051296
- if (removed === 0)
1051297
- return { success: true, output: `No memory entries matched "${keyword}".` };
1051298
- return { success: true, output: `Removed ${removed} memory entry(s) matching "${keyword}".` };
1051299
- }
1051300
- async function toolGoals(_2) {
1051301
- const summary = getActiveGoalsSummary();
1051302
- return { success: true, output: summary ? `ACTIVE GOALS:
1051303
- ${summary}` : "No active goals." };
1051304
- }
1051305
- var MIRROR_TOOLS = [
1051306
- { name: "status", description: "Show system status: uptime, RAM, session count", fn: toolStatus },
1051307
- { name: "analytics", description: "Show learning analytics: task count, success rate", fn: toolAnalytics },
1051308
- { name: "spend", description: "Show today's token cost and spend by provider", fn: toolSpend },
1051309
- { name: "memory_show", description: "Show conversation memory facts and recent history", fn: toolMemoryShow },
1051310
- { name: "memory_store", description: 'Persist a fact or preference to permanent memory (records.jsonl) right now. Pass { fact: "..." }', fn: toolMemoryStore },
1051311
- { name: "memory_forget", description: 'Remove a fact or preference from permanent memory (records.jsonl). Pass { fact: "thing to forget" }', fn: toolMemoryForget },
1051312
- { name: "lessons", description: "Show permanent failure rules learned from past tasks", fn: toolLessons },
1051313
- { name: "skills_list", description: "List all loaded skills with descriptions", fn: toolSkillsList },
1051314
- { name: "tools_list", description: "List all registered tool names", fn: toolToolsList },
1051315
- { name: "whoami", description: "Show current user profile: name, home dir, platform", fn: toolWhoami },
1051316
- { name: "channels_status", description: "Show provider channel status: active, disabled, no-key", fn: toolChannelsStatus },
1051317
- { name: "goals", description: "Show currently active goals", fn: toolGoals }
1051318
- ];
1051319
- var SLASH_MIRROR_TOOL_NAMES = MIRROR_TOOLS.map((t) => t.name);
1051320
- function registerSlashMirrorTools() {
1051321
- const isDebug = (process.env.AIDEN_LOG_LEVEL || "info") === "debug";
1051322
- for (const { name, description, fn } of MIRROR_TOOLS) {
1051323
- registerExternalTool(name, fn, "slash-mirror");
1051324
- if (isDebug) {
1051325
- console.log("[SlashAsTool] Registered mirror tool: " + name + " \u2014 " + description);
1051326
- }
1051327
- }
1051328
- if (!isDebug) {
1051329
- console.log("[SlashAsTool] Registered " + MIRROR_TOOLS.length + " mirror tools (AIDEN_LOG_LEVEL=debug for detail)");
1051330
- }
1051331
- }
1051421
+ // api/server.ts
1051422
+ init_slashAsTool();
1051332
1051423
 
1051333
1051424
  // core/memoryPreamble.ts
1051334
1051425
  var import_fs57 = __toESM(require("fs"));
@@ -1058877,7 +1058968,14 @@ ${cognitionHint}${memoryContext}${greetingPreamble}${sessionContext}${memoryInde
1058877
1058968
  }
1058878
1058969
  }
1058879
1058970
  console.error("[Router] All providers failed. Last error:", err?.message ?? "unknown");
1058880
- send({ token: buildDiagnostic({ tool: "respond", provider: "all", retries: 2, error: "All AI providers failed or are at capacity", suggestion: "Try again in a few minutes, or add more API keys in Settings \u2192 API Keys." }), done: false, provider: "error" });
1058971
+ const poolDiag = diagnoseProviderPool();
1058972
+ send({ token: buildDiagnostic({
1058973
+ tool: "respond",
1058974
+ provider: "all",
1058975
+ retries: 2,
1058976
+ error: poolDiag.state === "unconfigured" ? "No API keys configured" : "All AI providers failed or are at capacity",
1058977
+ suggestion: poolDiag.state === "unconfigured" ? "Add API keys in Settings > API Keys, or start Ollama for local inference." : "Try again in a few minutes, or add more API keys in Settings > API Keys."
1058978
+ }), done: false, provider: "error" });
1058881
1058979
  }
1058882
1058980
  streamEnded = true;
1058883
1058981
  clearTimeout(timeout);