@lydia-agent/core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +129 -118
- package/dist/index.js +129 -118
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -713,17 +713,20 @@ var StrategyRegistry = class {
|
|
|
713
713
|
|
|
714
714
|
// src/strategy/approval-service.ts
|
|
715
715
|
var os2 = __toESM(require("os"), 1);
|
|
716
|
-
var
|
|
716
|
+
var path3 = __toESM(require("path"), 1);
|
|
717
717
|
|
|
718
718
|
// src/memory/manager.ts
|
|
719
719
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
720
720
|
var import_node_events = require("events");
|
|
721
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
722
|
+
var path2 = __toESM(require("path"), 1);
|
|
721
723
|
var MemoryManager = class extends import_node_events.EventEmitter {
|
|
722
724
|
db;
|
|
723
725
|
checkpointTtlMs;
|
|
724
726
|
observationFrameTtlMs;
|
|
725
727
|
constructor(dbPath, options = {}) {
|
|
726
728
|
super();
|
|
729
|
+
fs2.mkdirSync(path2.dirname(dbPath), { recursive: true });
|
|
727
730
|
this.db = new import_better_sqlite3.default(dbPath);
|
|
728
731
|
this.checkpointTtlMs = options.checkpointTtlMs ?? 24 * 60 * 60 * 1e3;
|
|
729
732
|
this.observationFrameTtlMs = options.observationFrameTtlMs ?? 24 * 7 * 60 * 60 * 1e3;
|
|
@@ -1607,7 +1610,7 @@ var StrategyApprovalService = class {
|
|
|
1607
1610
|
if (memoryManager) {
|
|
1608
1611
|
this.memory = memoryManager;
|
|
1609
1612
|
} else {
|
|
1610
|
-
const dbPath =
|
|
1613
|
+
const dbPath = path3.join(os2.homedir(), ".lydia", "memory.db");
|
|
1611
1614
|
this.memory = new MemoryManager(dbPath);
|
|
1612
1615
|
}
|
|
1613
1616
|
this.configLoader = configLoader || new ConfigLoader();
|
|
@@ -1668,7 +1671,7 @@ var StrategyApprovalService = class {
|
|
|
1668
1671
|
};
|
|
1669
1672
|
|
|
1670
1673
|
// src/strategy/shadow-router.ts
|
|
1671
|
-
var
|
|
1674
|
+
var path4 = __toESM(require("path"), 1);
|
|
1672
1675
|
var os3 = __toESM(require("os"), 1);
|
|
1673
1676
|
var ShadowRouter = class {
|
|
1674
1677
|
memory;
|
|
@@ -1678,7 +1681,7 @@ var ShadowRouter = class {
|
|
|
1678
1681
|
if (memoryManager) {
|
|
1679
1682
|
this.memory = memoryManager;
|
|
1680
1683
|
} else {
|
|
1681
|
-
const dbPath =
|
|
1684
|
+
const dbPath = path4.join(os3.homedir(), ".lydia", "memory.db");
|
|
1682
1685
|
this.memory = new MemoryManager(dbPath);
|
|
1683
1686
|
}
|
|
1684
1687
|
this.registry = strategyRegistry || new StrategyRegistry();
|
|
@@ -1949,39 +1952,39 @@ var StrategyReviewer = class {
|
|
|
1949
1952
|
};
|
|
1950
1953
|
|
|
1951
1954
|
// src/strategy/branch-manager.ts
|
|
1952
|
-
var
|
|
1953
|
-
var
|
|
1955
|
+
var fs3 = __toESM(require("fs/promises"), 1);
|
|
1956
|
+
var path5 = __toESM(require("path"), 1);
|
|
1954
1957
|
var os4 = __toESM(require("os"), 1);
|
|
1955
1958
|
var import_yaml2 = require("yaml");
|
|
1956
1959
|
var StrategyBranchManager = class {
|
|
1957
1960
|
baseDir;
|
|
1958
1961
|
constructor(baseDir) {
|
|
1959
|
-
this.baseDir = baseDir ||
|
|
1962
|
+
this.baseDir = baseDir || path5.join(os4.homedir(), ".lydia", "strategies");
|
|
1960
1963
|
}
|
|
1961
1964
|
async init() {
|
|
1962
|
-
await
|
|
1963
|
-
await
|
|
1964
|
-
await
|
|
1965
|
+
await fs3.mkdir(this.baseDir, { recursive: true });
|
|
1966
|
+
await fs3.mkdir(path5.join(this.baseDir, "branches"), { recursive: true });
|
|
1967
|
+
await fs3.mkdir(path5.join(this.baseDir, "archive"), { recursive: true });
|
|
1965
1968
|
}
|
|
1966
1969
|
async listBranches() {
|
|
1967
|
-
const branchesDir =
|
|
1970
|
+
const branchesDir = path5.join(this.baseDir, "branches");
|
|
1968
1971
|
try {
|
|
1969
|
-
const entries = await
|
|
1972
|
+
const entries = await fs3.readdir(branchesDir, { withFileTypes: true });
|
|
1970
1973
|
const branches = [];
|
|
1971
1974
|
for (const entry of entries) {
|
|
1972
1975
|
if (!entry.isDirectory()) continue;
|
|
1973
1976
|
}
|
|
1974
|
-
const files = await
|
|
1977
|
+
const files = await fs3.readdir(branchesDir);
|
|
1975
1978
|
for (const file of files) {
|
|
1976
1979
|
if (!file.endsWith(".yml")) continue;
|
|
1977
|
-
const content = await
|
|
1980
|
+
const content = await fs3.readFile(path5.join(branchesDir, file), "utf-8");
|
|
1978
1981
|
try {
|
|
1979
1982
|
const strategy = StrategySchema.parse((0, import_yaml2.parse)(content));
|
|
1980
1983
|
branches.push({
|
|
1981
1984
|
name: strategy.metadata.id,
|
|
1982
1985
|
// ID is used as branch name effectively
|
|
1983
1986
|
version: strategy.metadata.version,
|
|
1984
|
-
path:
|
|
1987
|
+
path: path5.join(branchesDir, file),
|
|
1985
1988
|
parent: strategy.metadata.inheritFrom,
|
|
1986
1989
|
createdAt: Date.now()
|
|
1987
1990
|
// We might want to store this in metadata later
|
|
@@ -1997,8 +2000,8 @@ var StrategyBranchManager = class {
|
|
|
1997
2000
|
}
|
|
1998
2001
|
}
|
|
1999
2002
|
async createBranch(sourceStrategy, newBranchName, modifications) {
|
|
2000
|
-
const targetDir =
|
|
2001
|
-
await
|
|
2003
|
+
const targetDir = path5.join(this.baseDir, "branches");
|
|
2004
|
+
await fs3.mkdir(targetDir, { recursive: true });
|
|
2002
2005
|
const newStrategy = {
|
|
2003
2006
|
...sourceStrategy,
|
|
2004
2007
|
...modifications,
|
|
@@ -2012,14 +2015,14 @@ var StrategyBranchManager = class {
|
|
|
2012
2015
|
...modifications.metadata
|
|
2013
2016
|
}
|
|
2014
2017
|
};
|
|
2015
|
-
const filePath =
|
|
2016
|
-
await
|
|
2018
|
+
const filePath = path5.join(targetDir, `${newBranchName}.yml`);
|
|
2019
|
+
await fs3.writeFile(filePath, (0, import_yaml2.stringify)(newStrategy), "utf-8");
|
|
2017
2020
|
return newStrategy;
|
|
2018
2021
|
}
|
|
2019
2022
|
async getBranch(branchName) {
|
|
2020
|
-
const filePath =
|
|
2023
|
+
const filePath = path5.join(this.baseDir, "branches", `${branchName}.yml`);
|
|
2021
2024
|
try {
|
|
2022
|
-
const content = await
|
|
2025
|
+
const content = await fs3.readFile(filePath, "utf-8");
|
|
2023
2026
|
return StrategySchema.parse((0, import_yaml2.parse)(content));
|
|
2024
2027
|
} catch {
|
|
2025
2028
|
return null;
|
|
@@ -2030,12 +2033,12 @@ var StrategyBranchManager = class {
|
|
|
2030
2033
|
if (!branch) throw new Error(`Branch ${branchName} not found`);
|
|
2031
2034
|
const parentId = branch.metadata.inheritFrom;
|
|
2032
2035
|
if (!parentId) throw new Error("Branch has no parent to merge into");
|
|
2033
|
-
const files = await
|
|
2036
|
+
const files = await fs3.readdir(this.baseDir);
|
|
2034
2037
|
let parentFile = null;
|
|
2035
2038
|
for (const file of files) {
|
|
2036
2039
|
if (file === "branches" || file === "archive") continue;
|
|
2037
2040
|
try {
|
|
2038
|
-
const content = await
|
|
2041
|
+
const content = await fs3.readFile(path5.join(this.baseDir, file), "utf-8");
|
|
2039
2042
|
const data = (0, import_yaml2.parse)(content);
|
|
2040
2043
|
if (data.metadata?.id === parentId) {
|
|
2041
2044
|
parentFile = file;
|
|
@@ -2047,18 +2050,18 @@ var StrategyBranchManager = class {
|
|
|
2047
2050
|
if (!parentFile) {
|
|
2048
2051
|
throw new Error(`Parent strategy ${parentId} not found in ${this.baseDir}`);
|
|
2049
2052
|
}
|
|
2050
|
-
const parentPath =
|
|
2051
|
-
await
|
|
2053
|
+
const parentPath = path5.join(this.baseDir, parentFile);
|
|
2054
|
+
await fs3.copyFile(parentPath, path5.join(this.baseDir, "archive", `${parentId}-${Date.now()}.bak.yml`));
|
|
2052
2055
|
const start = Date.now();
|
|
2053
|
-
const branchContent = await
|
|
2054
|
-
await
|
|
2056
|
+
const branchContent = await fs3.readFile(path5.join(this.baseDir, "branches", `${branchName}.yml`), "utf-8");
|
|
2057
|
+
await fs3.writeFile(parentPath, branchContent, "utf-8");
|
|
2055
2058
|
await this.archiveBranch(branchName);
|
|
2056
2059
|
}
|
|
2057
2060
|
async archiveBranch(branchName) {
|
|
2058
|
-
const srcPath =
|
|
2059
|
-
const destPath =
|
|
2061
|
+
const srcPath = path5.join(this.baseDir, "branches", `${branchName}.yml`);
|
|
2062
|
+
const destPath = path5.join(this.baseDir, "archive", `${branchName}-${Date.now()}.yml`);
|
|
2060
2063
|
try {
|
|
2061
|
-
await
|
|
2064
|
+
await fs3.rename(srcPath, destPath);
|
|
2062
2065
|
} catch (e) {
|
|
2063
2066
|
console.error(`Failed to archive branch ${branchName}:`, e);
|
|
2064
2067
|
throw e;
|
|
@@ -2321,11 +2324,11 @@ var SkillRegistry = class {
|
|
|
2321
2324
|
};
|
|
2322
2325
|
|
|
2323
2326
|
// src/skills/loader.ts
|
|
2324
|
-
var
|
|
2325
|
-
var
|
|
2327
|
+
var fs4 = __toESM(require("fs/promises"), 1);
|
|
2328
|
+
var path6 = __toESM(require("path"), 1);
|
|
2326
2329
|
var os5 = __toESM(require("os"), 1);
|
|
2327
2330
|
var import_node_url2 = require("url");
|
|
2328
|
-
var __dirname2 =
|
|
2331
|
+
var __dirname2 = path6.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
2329
2332
|
var SkillLoader = class {
|
|
2330
2333
|
registry;
|
|
2331
2334
|
/** Ordered list of directories to scan for skills */
|
|
@@ -2340,13 +2343,13 @@ var SkillLoader = class {
|
|
|
2340
2343
|
getDirectories(extraDirs = []) {
|
|
2341
2344
|
return [
|
|
2342
2345
|
// 1. Built-in skills (relative to this file in dist/skills)
|
|
2343
|
-
|
|
2346
|
+
path6.resolve(__dirname2, "../../skills"),
|
|
2344
2347
|
// 1.5 Built-in skills in source tree (dev mode)
|
|
2345
|
-
|
|
2348
|
+
path6.resolve(__dirname2, "../skills"),
|
|
2346
2349
|
// 2. User global skills
|
|
2347
|
-
|
|
2350
|
+
path6.join(os5.homedir(), ".lydia", "skills"),
|
|
2348
2351
|
// 3. Project local skills
|
|
2349
|
-
|
|
2352
|
+
path6.join(process.cwd(), ".lydia", "skills"),
|
|
2350
2353
|
// 4. Extra directories from config
|
|
2351
2354
|
...extraDirs
|
|
2352
2355
|
];
|
|
@@ -2367,11 +2370,11 @@ var SkillLoader = class {
|
|
|
2367
2370
|
*/
|
|
2368
2371
|
async loadMetadataFromDirectory(dirPath) {
|
|
2369
2372
|
try {
|
|
2370
|
-
const stats = await
|
|
2373
|
+
const stats = await fs4.stat(dirPath);
|
|
2371
2374
|
if (!stats.isDirectory()) return;
|
|
2372
|
-
const entries = await
|
|
2375
|
+
const entries = await fs4.readdir(dirPath, { withFileTypes: true });
|
|
2373
2376
|
for (const entry of entries) {
|
|
2374
|
-
const fullPath =
|
|
2377
|
+
const fullPath = path6.join(dirPath, entry.name);
|
|
2375
2378
|
if (entry.isDirectory()) {
|
|
2376
2379
|
await this.loadMetadataFromDirectory(fullPath);
|
|
2377
2380
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -2387,7 +2390,7 @@ var SkillLoader = class {
|
|
|
2387
2390
|
*/
|
|
2388
2391
|
async loadSkillMeta(filePath) {
|
|
2389
2392
|
try {
|
|
2390
|
-
const content = await
|
|
2393
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
2391
2394
|
if (content.startsWith("---")) {
|
|
2392
2395
|
const meta = SkillParser.parseMeta(content, filePath);
|
|
2393
2396
|
this.registry.register(meta);
|
|
@@ -2408,7 +2411,7 @@ var SkillLoader = class {
|
|
|
2408
2411
|
const meta = this.registry.get(name);
|
|
2409
2412
|
if (!meta?.path) return null;
|
|
2410
2413
|
try {
|
|
2411
|
-
const fileContent = await
|
|
2414
|
+
const fileContent = await fs4.readFile(meta.path, "utf-8");
|
|
2412
2415
|
const skill = SkillParser.parse(fileContent, meta.path);
|
|
2413
2416
|
return skill.content;
|
|
2414
2417
|
} catch (error) {
|
|
@@ -2424,7 +2427,7 @@ var SkillLoader = class {
|
|
|
2424
2427
|
const meta = this.registry.get(name);
|
|
2425
2428
|
if (!meta?.path) return null;
|
|
2426
2429
|
try {
|
|
2427
|
-
const fileContent = await
|
|
2430
|
+
const fileContent = await fs4.readFile(meta.path, "utf-8");
|
|
2428
2431
|
return SkillParser.parse(fileContent, meta.path);
|
|
2429
2432
|
} catch (error) {
|
|
2430
2433
|
console.warn(`Failed to load full skill "${name}":`, error);
|
|
@@ -2437,7 +2440,7 @@ var SkillLoader = class {
|
|
|
2437
2440
|
*/
|
|
2438
2441
|
async reloadSkillMeta(filePath) {
|
|
2439
2442
|
try {
|
|
2440
|
-
const content = await
|
|
2443
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
2441
2444
|
if (content.startsWith("---")) {
|
|
2442
2445
|
const meta = SkillParser.parseMeta(content, filePath);
|
|
2443
2446
|
this.registry.register(meta);
|
|
@@ -2452,9 +2455,9 @@ var SkillLoader = class {
|
|
|
2452
2455
|
|
|
2453
2456
|
// src/skills/watcher.ts
|
|
2454
2457
|
var import_node_events2 = require("events");
|
|
2455
|
-
var
|
|
2458
|
+
var fs5 = __toESM(require("fs"), 1);
|
|
2456
2459
|
var fsPromises = __toESM(require("fs/promises"), 1);
|
|
2457
|
-
var
|
|
2460
|
+
var path7 = __toESM(require("path"), 1);
|
|
2458
2461
|
var SkillWatcher = class extends import_node_events2.EventEmitter {
|
|
2459
2462
|
constructor(directories, registry, loader, options) {
|
|
2460
2463
|
super();
|
|
@@ -2464,7 +2467,7 @@ var SkillWatcher = class extends import_node_events2.EventEmitter {
|
|
|
2464
2467
|
this.debounceMs = options?.debounceMs ?? 300;
|
|
2465
2468
|
for (const skill of this.registry.list()) {
|
|
2466
2469
|
if (skill.path) {
|
|
2467
|
-
this.pathToName.set(
|
|
2470
|
+
this.pathToName.set(path7.resolve(skill.path), skill.name);
|
|
2468
2471
|
}
|
|
2469
2472
|
}
|
|
2470
2473
|
}
|
|
@@ -2503,12 +2506,12 @@ var SkillWatcher = class extends import_node_events2.EventEmitter {
|
|
|
2503
2506
|
}
|
|
2504
2507
|
watchDirectory(dirPath) {
|
|
2505
2508
|
try {
|
|
2506
|
-
if (!
|
|
2509
|
+
if (!fs5.existsSync(dirPath) || !fs5.statSync(dirPath).isDirectory()) {
|
|
2507
2510
|
return;
|
|
2508
2511
|
}
|
|
2509
|
-
const watcher =
|
|
2512
|
+
const watcher = fs5.watch(dirPath, { recursive: true }, (eventType, filename) => {
|
|
2510
2513
|
if (!filename) return;
|
|
2511
|
-
const fullPath =
|
|
2514
|
+
const fullPath = path7.resolve(dirPath, filename);
|
|
2512
2515
|
if (!filename.endsWith(".md")) return;
|
|
2513
2516
|
this.handleFileChange(fullPath, eventType);
|
|
2514
2517
|
});
|
|
@@ -2520,7 +2523,7 @@ var SkillWatcher = class extends import_node_events2.EventEmitter {
|
|
|
2520
2523
|
}
|
|
2521
2524
|
}
|
|
2522
2525
|
handleFileChange(filePath, _eventType) {
|
|
2523
|
-
const resolvedPath =
|
|
2526
|
+
const resolvedPath = path7.resolve(filePath);
|
|
2524
2527
|
const existingTimer = this.debounceTimers.get(resolvedPath);
|
|
2525
2528
|
if (existingTimer) {
|
|
2526
2529
|
clearTimeout(existingTimer);
|
|
@@ -2577,7 +2580,7 @@ var ShellServer = class {
|
|
|
2577
2580
|
this.server = new import_server.Server(
|
|
2578
2581
|
{
|
|
2579
2582
|
name: "internal-shell",
|
|
2580
|
-
version: "0.1.
|
|
2583
|
+
version: "0.1.1"
|
|
2581
2584
|
},
|
|
2582
2585
|
{
|
|
2583
2586
|
capabilities: {
|
|
@@ -2644,18 +2647,18 @@ ${error.stderr || ""}`
|
|
|
2644
2647
|
// src/mcp/servers/filesystem.ts
|
|
2645
2648
|
var import_server2 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
2646
2649
|
var import_types4 = require("@modelcontextprotocol/sdk/types.js");
|
|
2647
|
-
var
|
|
2648
|
-
var
|
|
2650
|
+
var fs6 = __toESM(require("fs/promises"), 1);
|
|
2651
|
+
var path8 = __toESM(require("path"), 1);
|
|
2649
2652
|
var import_node_zlib = require("zlib");
|
|
2650
2653
|
var FileSystemServer = class {
|
|
2651
2654
|
server;
|
|
2652
2655
|
allowedRootDir;
|
|
2653
2656
|
constructor(allowedRootDir = process.cwd()) {
|
|
2654
|
-
this.allowedRootDir =
|
|
2657
|
+
this.allowedRootDir = path8.resolve(allowedRootDir);
|
|
2655
2658
|
this.server = new import_server2.Server(
|
|
2656
2659
|
{
|
|
2657
2660
|
name: "internal-fs",
|
|
2658
|
-
version: "0.1.
|
|
2661
|
+
version: "0.1.1"
|
|
2659
2662
|
},
|
|
2660
2663
|
{
|
|
2661
2664
|
capabilities: {
|
|
@@ -2666,7 +2669,7 @@ var FileSystemServer = class {
|
|
|
2666
2669
|
this.setupHandlers();
|
|
2667
2670
|
}
|
|
2668
2671
|
validatePath(requestedPath) {
|
|
2669
|
-
const resolvedPath =
|
|
2672
|
+
const resolvedPath = path8.resolve(this.allowedRootDir, requestedPath);
|
|
2670
2673
|
const root = process.platform === "win32" ? this.allowedRootDir.toLowerCase() : this.allowedRootDir;
|
|
2671
2674
|
const target = process.platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
|
|
2672
2675
|
if (!target.startsWith(root)) {
|
|
@@ -2788,22 +2791,22 @@ var FileSystemServer = class {
|
|
|
2788
2791
|
switch (request.params.name) {
|
|
2789
2792
|
case "fs_read_file": {
|
|
2790
2793
|
const filePath = this.validatePath(args.path);
|
|
2791
|
-
const content = await
|
|
2794
|
+
const content = await fs6.readFile(filePath, "utf-8");
|
|
2792
2795
|
return {
|
|
2793
2796
|
content: [{ type: "text", text: content }]
|
|
2794
2797
|
};
|
|
2795
2798
|
}
|
|
2796
2799
|
case "fs_write_file": {
|
|
2797
2800
|
const filePath = this.validatePath(args.path);
|
|
2798
|
-
await
|
|
2799
|
-
await
|
|
2801
|
+
await fs6.mkdir(path8.dirname(filePath), { recursive: true });
|
|
2802
|
+
await fs6.writeFile(filePath, args.content, "utf-8");
|
|
2800
2803
|
return {
|
|
2801
2804
|
content: [{ type: "text", text: `Successfully wrote to ${filePath}` }]
|
|
2802
2805
|
};
|
|
2803
2806
|
}
|
|
2804
2807
|
case "fs_list_directory": {
|
|
2805
2808
|
const dirPath = this.validatePath(args.path);
|
|
2806
|
-
const entries = await
|
|
2809
|
+
const entries = await fs6.readdir(dirPath, { withFileTypes: true });
|
|
2807
2810
|
const list = entries.map((e) => `${e.isDirectory() ? "[DIR]" : "[FILE]"} ${e.name}`).join("\n");
|
|
2808
2811
|
return {
|
|
2809
2812
|
content: [{ type: "text", text: list }]
|
|
@@ -2814,8 +2817,8 @@ var FileSystemServer = class {
|
|
|
2814
2817
|
const toPath = this.validatePath(args.to);
|
|
2815
2818
|
const overwrite = Boolean(args.overwrite);
|
|
2816
2819
|
await this.ensureDestWritable(toPath, overwrite);
|
|
2817
|
-
await
|
|
2818
|
-
await
|
|
2820
|
+
await fs6.mkdir(path8.dirname(toPath), { recursive: true });
|
|
2821
|
+
await fs6.copyFile(fromPath, toPath);
|
|
2819
2822
|
return {
|
|
2820
2823
|
content: [{ type: "text", text: `Successfully copied ${fromPath} -> ${toPath}` }]
|
|
2821
2824
|
};
|
|
@@ -2825,7 +2828,7 @@ var FileSystemServer = class {
|
|
|
2825
2828
|
const toPath = this.validatePath(args.to);
|
|
2826
2829
|
const overwrite = Boolean(args.overwrite);
|
|
2827
2830
|
await this.ensureDestWritable(toPath, overwrite);
|
|
2828
|
-
await
|
|
2831
|
+
await fs6.mkdir(path8.dirname(toPath), { recursive: true });
|
|
2829
2832
|
await this.moveFile(fromPath, toPath);
|
|
2830
2833
|
return {
|
|
2831
2834
|
content: [{ type: "text", text: `Successfully moved ${fromPath} -> ${toPath}` }]
|
|
@@ -2847,9 +2850,9 @@ var FileSystemServer = class {
|
|
|
2847
2850
|
const overwrite = Boolean(args.overwrite);
|
|
2848
2851
|
const maxBytes = Math.max(1024, Number(args.maxBytes) || 20 * 1024 * 1024);
|
|
2849
2852
|
await this.ensureDestWritable(outputPath, overwrite);
|
|
2850
|
-
await
|
|
2853
|
+
await fs6.mkdir(path8.dirname(outputPath), { recursive: true });
|
|
2851
2854
|
const bundle = await this.createArchiveBundle(sourcePath, maxBytes);
|
|
2852
|
-
await
|
|
2855
|
+
await fs6.writeFile(outputPath, bundle.buffer);
|
|
2853
2856
|
return {
|
|
2854
2857
|
content: [{ type: "text", text: `Successfully archived ${bundle.fileCount} file(s) to ${outputPath}` }]
|
|
2855
2858
|
};
|
|
@@ -2859,7 +2862,7 @@ var FileSystemServer = class {
|
|
|
2859
2862
|
const outputDir = this.validatePath(args.outputDir);
|
|
2860
2863
|
const overwrite = Boolean(args.overwrite);
|
|
2861
2864
|
const maxBytes = Math.max(1024, Number(args.maxBytes) || 20 * 1024 * 1024);
|
|
2862
|
-
const archiveBuffer = await
|
|
2865
|
+
const archiveBuffer = await fs6.readFile(archivePath);
|
|
2863
2866
|
const bundle = this.parseArchiveBundle(archiveBuffer);
|
|
2864
2867
|
const written = await this.extractArchiveBundle(bundle, outputDir, overwrite, maxBytes);
|
|
2865
2868
|
return {
|
|
@@ -2879,11 +2882,11 @@ var FileSystemServer = class {
|
|
|
2879
2882
|
}
|
|
2880
2883
|
async ensureDestWritable(destPath, overwrite) {
|
|
2881
2884
|
try {
|
|
2882
|
-
await
|
|
2885
|
+
await fs6.access(destPath);
|
|
2883
2886
|
if (!overwrite) {
|
|
2884
2887
|
throw new Error(`Destination already exists: ${destPath}. Pass overwrite=true to replace.`);
|
|
2885
2888
|
}
|
|
2886
|
-
await
|
|
2889
|
+
await fs6.rm(destPath, { recursive: true, force: true });
|
|
2887
2890
|
} catch (error) {
|
|
2888
2891
|
if (error?.code === "ENOENT") return;
|
|
2889
2892
|
throw error;
|
|
@@ -2891,11 +2894,11 @@ var FileSystemServer = class {
|
|
|
2891
2894
|
}
|
|
2892
2895
|
async moveFile(fromPath, toPath) {
|
|
2893
2896
|
try {
|
|
2894
|
-
await
|
|
2897
|
+
await fs6.rename(fromPath, toPath);
|
|
2895
2898
|
} catch (error) {
|
|
2896
2899
|
if (error?.code !== "EXDEV") throw error;
|
|
2897
|
-
await
|
|
2898
|
-
await
|
|
2900
|
+
await fs6.copyFile(fromPath, toPath);
|
|
2901
|
+
await fs6.unlink(fromPath);
|
|
2899
2902
|
}
|
|
2900
2903
|
}
|
|
2901
2904
|
async searchByName(basePath, pattern, maxResults) {
|
|
@@ -2905,10 +2908,10 @@ var FileSystemServer = class {
|
|
|
2905
2908
|
while (queue.length > 0 && results.length < maxResults) {
|
|
2906
2909
|
const current = queue.shift();
|
|
2907
2910
|
if (!current) break;
|
|
2908
|
-
const entries = await
|
|
2911
|
+
const entries = await fs6.readdir(current, { withFileTypes: true });
|
|
2909
2912
|
for (const entry of entries) {
|
|
2910
|
-
const fullPath =
|
|
2911
|
-
const relative3 =
|
|
2913
|
+
const fullPath = path8.join(current, entry.name);
|
|
2914
|
+
const relative3 = path8.relative(this.allowedRootDir, fullPath) || ".";
|
|
2912
2915
|
if (matcher(entry.name)) {
|
|
2913
2916
|
results.push(`${entry.isDirectory() ? "[DIR]" : "[FILE]"} ${relative3}`);
|
|
2914
2917
|
if (results.length >= maxResults) break;
|
|
@@ -2932,11 +2935,11 @@ var FileSystemServer = class {
|
|
|
2932
2935
|
return (name) => name.toLowerCase().includes(lowered);
|
|
2933
2936
|
}
|
|
2934
2937
|
async createArchiveBundle(sourcePath, maxBytes) {
|
|
2935
|
-
const stat3 = await
|
|
2938
|
+
const stat3 = await fs6.stat(sourcePath);
|
|
2936
2939
|
const files = [];
|
|
2937
2940
|
let totalBytes = 0;
|
|
2938
2941
|
const readAndAppend = async (absolutePath, relativePath) => {
|
|
2939
|
-
const data = await
|
|
2942
|
+
const data = await fs6.readFile(absolutePath);
|
|
2940
2943
|
totalBytes += data.length;
|
|
2941
2944
|
if (totalBytes > maxBytes) {
|
|
2942
2945
|
throw new Error(`Archive exceeds maxBytes limit (${maxBytes}).`);
|
|
@@ -2949,28 +2952,28 @@ var FileSystemServer = class {
|
|
|
2949
2952
|
});
|
|
2950
2953
|
};
|
|
2951
2954
|
if (stat3.isFile()) {
|
|
2952
|
-
await readAndAppend(sourcePath,
|
|
2955
|
+
await readAndAppend(sourcePath, path8.basename(sourcePath));
|
|
2953
2956
|
} else if (stat3.isDirectory()) {
|
|
2954
2957
|
const queue = [sourcePath];
|
|
2955
2958
|
while (queue.length > 0) {
|
|
2956
2959
|
const current = queue.shift();
|
|
2957
2960
|
if (!current) break;
|
|
2958
|
-
const entries = await
|
|
2961
|
+
const entries = await fs6.readdir(current, { withFileTypes: true });
|
|
2959
2962
|
for (const entry of entries) {
|
|
2960
|
-
const fullPath =
|
|
2963
|
+
const fullPath = path8.join(current, entry.name);
|
|
2961
2964
|
if (entry.isDirectory()) {
|
|
2962
2965
|
queue.push(fullPath);
|
|
2963
2966
|
continue;
|
|
2964
2967
|
}
|
|
2965
2968
|
if (!entry.isFile()) continue;
|
|
2966
|
-
const relativePath =
|
|
2969
|
+
const relativePath = path8.relative(sourcePath, fullPath) || entry.name;
|
|
2967
2970
|
await readAndAppend(fullPath, relativePath.replace(/\\/g, "/"));
|
|
2968
2971
|
}
|
|
2969
2972
|
}
|
|
2970
2973
|
} else {
|
|
2971
2974
|
throw new Error("Only files and directories can be archived.");
|
|
2972
2975
|
}
|
|
2973
|
-
const sourceRelative =
|
|
2976
|
+
const sourceRelative = path8.relative(this.allowedRootDir, sourcePath).replace(/\\/g, "/");
|
|
2974
2977
|
const bundle = {
|
|
2975
2978
|
format: "lydia-archive-v1",
|
|
2976
2979
|
source: sourceRelative || ".",
|
|
@@ -3003,13 +3006,13 @@ var FileSystemServer = class {
|
|
|
3003
3006
|
let count = 0;
|
|
3004
3007
|
for (const file of bundle.files) {
|
|
3005
3008
|
const relPath = String(file.path || "").replace(/\\/g, "/");
|
|
3006
|
-
if (!relPath ||
|
|
3009
|
+
if (!relPath || path8.isAbsolute(relPath) || relPath.includes("..")) {
|
|
3007
3010
|
throw new Error(`Unsafe archive entry path: ${relPath || "<empty>"}`);
|
|
3008
3011
|
}
|
|
3009
|
-
const targetPath =
|
|
3012
|
+
const targetPath = path8.resolve(outputDir, relPath);
|
|
3010
3013
|
const safeOutputDir = process.platform === "win32" ? outputDir.toLowerCase() : outputDir;
|
|
3011
3014
|
const safeTarget = process.platform === "win32" ? targetPath.toLowerCase() : targetPath;
|
|
3012
|
-
if (!safeTarget.startsWith(safeOutputDir +
|
|
3015
|
+
if (!safeTarget.startsWith(safeOutputDir + path8.sep) && safeTarget !== safeOutputDir) {
|
|
3013
3016
|
throw new Error(`Archive entry escapes destination: ${relPath}`);
|
|
3014
3017
|
}
|
|
3015
3018
|
const data = this.decodeArchiveEntry(file);
|
|
@@ -3017,8 +3020,8 @@ var FileSystemServer = class {
|
|
|
3017
3020
|
if (totalBytes > maxBytes) {
|
|
3018
3021
|
throw new Error(`Unarchive exceeds maxBytes limit (${maxBytes}).`);
|
|
3019
3022
|
}
|
|
3020
|
-
await
|
|
3021
|
-
await
|
|
3023
|
+
await fs6.mkdir(path8.dirname(targetPath), { recursive: true });
|
|
3024
|
+
await fs6.writeFile(targetPath, data);
|
|
3022
3025
|
count += 1;
|
|
3023
3026
|
}
|
|
3024
3027
|
return count;
|
|
@@ -3038,22 +3041,22 @@ var FileSystemServer = class {
|
|
|
3038
3041
|
}
|
|
3039
3042
|
async prepareOutputDirectory(outputDir, overwrite) {
|
|
3040
3043
|
try {
|
|
3041
|
-
const stat3 = await
|
|
3044
|
+
const stat3 = await fs6.stat(outputDir);
|
|
3042
3045
|
if (!stat3.isDirectory()) {
|
|
3043
3046
|
throw new Error(`Output path is not a directory: ${outputDir}`);
|
|
3044
3047
|
}
|
|
3045
3048
|
if (!overwrite) {
|
|
3046
|
-
const entries = await
|
|
3049
|
+
const entries = await fs6.readdir(outputDir);
|
|
3047
3050
|
if (entries.length > 0) {
|
|
3048
3051
|
throw new Error(`Output directory is not empty: ${outputDir}. Pass overwrite=true to replace.`);
|
|
3049
3052
|
}
|
|
3050
3053
|
} else {
|
|
3051
|
-
await
|
|
3052
|
-
await
|
|
3054
|
+
await fs6.rm(outputDir, { recursive: true, force: true });
|
|
3055
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
3053
3056
|
}
|
|
3054
3057
|
} catch (error) {
|
|
3055
3058
|
if (error?.code === "ENOENT") {
|
|
3056
|
-
await
|
|
3059
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
3057
3060
|
return;
|
|
3058
3061
|
}
|
|
3059
3062
|
throw error;
|
|
@@ -3073,7 +3076,7 @@ var GitServer = class {
|
|
|
3073
3076
|
this.server = new import_server3.Server(
|
|
3074
3077
|
{
|
|
3075
3078
|
name: "internal-git",
|
|
3076
|
-
version: "0.1.
|
|
3079
|
+
version: "0.1.1"
|
|
3077
3080
|
},
|
|
3078
3081
|
{
|
|
3079
3082
|
capabilities: {
|
|
@@ -3250,7 +3253,7 @@ var MemoryServer = class {
|
|
|
3250
3253
|
this.server = new import_server4.Server(
|
|
3251
3254
|
{
|
|
3252
3255
|
name: "internal-memory",
|
|
3253
|
-
version: "0.1.
|
|
3256
|
+
version: "0.1.1"
|
|
3254
3257
|
},
|
|
3255
3258
|
{
|
|
3256
3259
|
capabilities: {
|
|
@@ -3376,7 +3379,7 @@ var InteractionServer = class extends import_node_events3.EventEmitter {
|
|
|
3376
3379
|
constructor() {
|
|
3377
3380
|
super();
|
|
3378
3381
|
this.server = new import_server5.Server(
|
|
3379
|
-
{ name: "internal-interaction", version: "0.1.
|
|
3382
|
+
{ name: "internal-interaction", version: "0.1.1" },
|
|
3380
3383
|
{ capabilities: { tools: {} } }
|
|
3381
3384
|
);
|
|
3382
3385
|
this.setupHandlers();
|
|
@@ -3757,7 +3760,7 @@ var McpClientManager = class {
|
|
|
3757
3760
|
const client = new import_client.Client(
|
|
3758
3761
|
{
|
|
3759
3762
|
name: "lydia-client",
|
|
3760
|
-
version: "0.1.
|
|
3763
|
+
version: "0.1.1"
|
|
3761
3764
|
},
|
|
3762
3765
|
{
|
|
3763
3766
|
capabilities: {
|
|
@@ -3865,7 +3868,7 @@ var McpClientManager = class {
|
|
|
3865
3868
|
};
|
|
3866
3869
|
|
|
3867
3870
|
// src/gate/risk.ts
|
|
3868
|
-
var
|
|
3871
|
+
var path9 = __toESM(require("path"), 1);
|
|
3869
3872
|
var os6 = __toESM(require("os"), 1);
|
|
3870
3873
|
var DEFAULT_USER_DATA_DIRS = [
|
|
3871
3874
|
"~/.lydia",
|
|
@@ -3895,13 +3898,13 @@ var COMPUTER_USE_HIGH_RISK_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
3895
3898
|
]);
|
|
3896
3899
|
function expandHome(p) {
|
|
3897
3900
|
if (p.startsWith("~/") || p === "~") {
|
|
3898
|
-
return
|
|
3901
|
+
return path9.join(os6.homedir(), p.slice(2));
|
|
3899
3902
|
}
|
|
3900
3903
|
return p;
|
|
3901
3904
|
}
|
|
3902
3905
|
function normalizePath(p) {
|
|
3903
3906
|
const expanded = expandHome(p);
|
|
3904
|
-
const normalized =
|
|
3907
|
+
const normalized = path9.resolve(expanded);
|
|
3905
3908
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
3906
3909
|
}
|
|
3907
3910
|
function buildProtectedDirs(config) {
|
|
@@ -3914,7 +3917,7 @@ function buildProtectedDirs(config) {
|
|
|
3914
3917
|
}
|
|
3915
3918
|
function isInProtectedDir(targetPath, protectedDirs) {
|
|
3916
3919
|
const normalizedTarget = normalizePath(targetPath);
|
|
3917
|
-
return protectedDirs.some((dir) => normalizedTarget === dir || normalizedTarget.startsWith(dir +
|
|
3920
|
+
return protectedDirs.some((dir) => normalizedTarget === dir || normalizedTarget.startsWith(dir + path9.sep));
|
|
3918
3921
|
}
|
|
3919
3922
|
function extractPathsFromCommand(command) {
|
|
3920
3923
|
const paths = [];
|
|
@@ -3936,7 +3939,7 @@ function hasRelativePathTraversal(input) {
|
|
|
3936
3939
|
return /(^|[\\\/])\.\.([\\\/]|$)/.test(input);
|
|
3937
3940
|
}
|
|
3938
3941
|
function isRelativePath(input) {
|
|
3939
|
-
return !
|
|
3942
|
+
return !path9.isAbsolute(input);
|
|
3940
3943
|
}
|
|
3941
3944
|
function resolveCanonicalComputerUseAction(toolName) {
|
|
3942
3945
|
const direct = resolveCanonicalComputerUseToolName(toolName);
|
|
@@ -4001,7 +4004,7 @@ function assessRisk(toolName, args, mcp, config) {
|
|
|
4001
4004
|
return {
|
|
4002
4005
|
level: "high",
|
|
4003
4006
|
reason: `${opLabel} with relative path traversal`,
|
|
4004
|
-
signature: `fs_write_rel:${normalizePath(
|
|
4007
|
+
signature: `fs_write_rel:${normalizePath(path9.resolve(targetPath))}`,
|
|
4005
4008
|
details: targetPath
|
|
4006
4009
|
};
|
|
4007
4010
|
}
|
|
@@ -4032,6 +4035,14 @@ function assessRisk(toolName, args, mcp, config) {
|
|
|
4032
4035
|
if (toolName === "shell_execute") {
|
|
4033
4036
|
const command = typeof args?.command === "string" ? args.command : "";
|
|
4034
4037
|
if (command && (isDestructiveShellCommand(command) || isPermissionChangeCommand(command))) {
|
|
4038
|
+
if (isPermissionChangeCommand(command)) {
|
|
4039
|
+
return {
|
|
4040
|
+
level: "high",
|
|
4041
|
+
reason: "Permission change shell command",
|
|
4042
|
+
signature: `shell_permission:${command.toLowerCase().slice(0, 80)}`,
|
|
4043
|
+
details: command
|
|
4044
|
+
};
|
|
4045
|
+
}
|
|
4035
4046
|
const targets = extractPathsFromCommand(command);
|
|
4036
4047
|
const hasTraversal = hasRelativePathTraversal(command);
|
|
4037
4048
|
if (targets.length === 0 || hasTraversal) {
|
|
@@ -4270,7 +4281,7 @@ var StrategyUpdateGate = class {
|
|
|
4270
4281
|
};
|
|
4271
4282
|
|
|
4272
4283
|
// src/gate/review-manager.ts
|
|
4273
|
-
var
|
|
4284
|
+
var path10 = __toESM(require("path"), 1);
|
|
4274
4285
|
var os7 = __toESM(require("os"), 1);
|
|
4275
4286
|
var ReviewManager = class {
|
|
4276
4287
|
memory;
|
|
@@ -4279,7 +4290,7 @@ var ReviewManager = class {
|
|
|
4279
4290
|
this.memory = memoryManager;
|
|
4280
4291
|
return;
|
|
4281
4292
|
}
|
|
4282
|
-
const dbPath =
|
|
4293
|
+
const dbPath = path10.join(os7.homedir(), ".lydia", "memory.db");
|
|
4283
4294
|
this.memory = new MemoryManager(dbPath);
|
|
4284
4295
|
}
|
|
4285
4296
|
async init() {
|
|
@@ -4458,7 +4469,7 @@ ${this.originalPlan}
|
|
|
4458
4469
|
};
|
|
4459
4470
|
|
|
4460
4471
|
// src/replay/mcp.ts
|
|
4461
|
-
var
|
|
4472
|
+
var path11 = __toESM(require("path"), 1);
|
|
4462
4473
|
var ReplayMcpClientManager = class extends McpClientManager {
|
|
4463
4474
|
traces;
|
|
4464
4475
|
callIndex = 0;
|
|
@@ -4613,12 +4624,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4613
4624
|
const loweredPattern = rawPattern.toLowerCase();
|
|
4614
4625
|
const names = /* @__PURE__ */ new Set();
|
|
4615
4626
|
for (const storedPath of this.virtualFiles.keys()) {
|
|
4616
|
-
const rel =
|
|
4627
|
+
const rel = path11.relative(normalized, storedPath);
|
|
4617
4628
|
if (rel.startsWith("..")) continue;
|
|
4618
4629
|
const parts = rel.split("/").filter(Boolean);
|
|
4619
4630
|
for (const part of parts) {
|
|
4620
4631
|
if (part.toLowerCase().includes(loweredPattern)) {
|
|
4621
|
-
names.add(`[FILE] ${
|
|
4632
|
+
names.add(`[FILE] ${path11.posix.join(path11.posix.relative(this.virtualRoot, normalized), rel)}`);
|
|
4622
4633
|
break;
|
|
4623
4634
|
}
|
|
4624
4635
|
}
|
|
@@ -4646,12 +4657,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4646
4657
|
createdAt: 0,
|
|
4647
4658
|
totalBytes: sourceFile ? sourceFile.length : sourceEntries.reduce((acc, [, text]) => acc + text.length, 0),
|
|
4648
4659
|
files: sourceFile ? [{
|
|
4649
|
-
path:
|
|
4660
|
+
path: path11.posix.basename(source),
|
|
4650
4661
|
size: sourceFile.length,
|
|
4651
4662
|
encoding: "base64",
|
|
4652
4663
|
data: Buffer.from(sourceFile, "utf-8").toString("base64")
|
|
4653
4664
|
}] : sourceEntries.map(([filePath, text]) => ({
|
|
4654
|
-
path:
|
|
4665
|
+
path: path11.posix.relative(source, filePath),
|
|
4655
4666
|
size: text.length,
|
|
4656
4667
|
encoding: "base64",
|
|
4657
4668
|
data: Buffer.from(text, "utf-8").toString("base64")
|
|
@@ -4706,7 +4717,7 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4706
4717
|
for (const item of parsed.files) {
|
|
4707
4718
|
const rel = typeof item?.path === "string" ? item.path.replace(/\\/g, "/") : "";
|
|
4708
4719
|
if (!rel || rel.includes("..") || rel.startsWith("/")) continue;
|
|
4709
|
-
const target = this.normalizeFsPath(
|
|
4720
|
+
const target = this.normalizeFsPath(path11.posix.join(outputDir, rel));
|
|
4710
4721
|
const base64 = typeof item?.data === "string" ? item.data : "";
|
|
4711
4722
|
const text = base64 ? Buffer.from(base64, "base64").toString("utf-8") : "";
|
|
4712
4723
|
this.virtualFiles.set(target, text);
|
|
@@ -4999,12 +5010,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4999
5010
|
if (driveMatch) {
|
|
5000
5011
|
const drive = driveMatch[1].toLowerCase();
|
|
5001
5012
|
const rest = driveMatch[2] || "/";
|
|
5002
|
-
return
|
|
5013
|
+
return path11.posix.normalize(`/${drive}${rest}`);
|
|
5003
5014
|
}
|
|
5004
5015
|
if (source.startsWith("/")) {
|
|
5005
|
-
return
|
|
5016
|
+
return path11.posix.normalize(source);
|
|
5006
5017
|
}
|
|
5007
|
-
return
|
|
5018
|
+
return path11.posix.normalize(path11.posix.join(this.virtualRoot, source));
|
|
5008
5019
|
}
|
|
5009
5020
|
listDirectoryEntries(directory) {
|
|
5010
5021
|
const normalizedDir = this.normalizeFsPath(directory);
|
|
@@ -5195,7 +5206,7 @@ var StrategyEvaluator = class {
|
|
|
5195
5206
|
};
|
|
5196
5207
|
|
|
5197
5208
|
// src/replay/manager.ts
|
|
5198
|
-
var
|
|
5209
|
+
var path12 = __toESM(require("path"), 1);
|
|
5199
5210
|
var os8 = __toESM(require("os"), 1);
|
|
5200
5211
|
var ReplayManager = class {
|
|
5201
5212
|
memoryManager;
|
|
@@ -5204,7 +5215,7 @@ var ReplayManager = class {
|
|
|
5204
5215
|
if (memoryManager) {
|
|
5205
5216
|
this.memoryManager = memoryManager;
|
|
5206
5217
|
} else {
|
|
5207
|
-
const dbPath =
|
|
5218
|
+
const dbPath = path12.join(os8.homedir(), ".lydia", "memory.db");
|
|
5208
5219
|
this.memoryManager = new MemoryManager(dbPath);
|
|
5209
5220
|
}
|
|
5210
5221
|
this.evaluator = new StrategyEvaluator();
|
|
@@ -5224,7 +5235,7 @@ var ReplayManager = class {
|
|
|
5224
5235
|
const agent = new Agent(mockLLM);
|
|
5225
5236
|
agent.mcpClientManager = mockMcp;
|
|
5226
5237
|
agent.isInitialized = true;
|
|
5227
|
-
const tempDb =
|
|
5238
|
+
const tempDb = path12.join(os8.tmpdir(), `lydia-replay-${Date.now()}-${episodeId}.db`);
|
|
5228
5239
|
agent.memoryManager = new MemoryManager(tempDb);
|
|
5229
5240
|
try {
|
|
5230
5241
|
const config = await agent.configLoader.load();
|
|
@@ -5544,7 +5555,7 @@ var FeedbackCollector = class {
|
|
|
5544
5555
|
};
|
|
5545
5556
|
|
|
5546
5557
|
// src/execution/agent.ts
|
|
5547
|
-
var
|
|
5558
|
+
var path13 = __toESM(require("path"), 1);
|
|
5548
5559
|
var os9 = __toESM(require("os"), 1);
|
|
5549
5560
|
var Agent = class extends import_node_events5.EventEmitter {
|
|
5550
5561
|
llm;
|
|
@@ -5641,7 +5652,7 @@ var Agent = class extends import_node_events5.EventEmitter {
|
|
|
5641
5652
|
await this.reviewManager.init();
|
|
5642
5653
|
const config = await this.configLoader.load();
|
|
5643
5654
|
this.config = config;
|
|
5644
|
-
const dbPath =
|
|
5655
|
+
const dbPath = path13.join(os9.homedir(), ".lydia", "memory.db");
|
|
5645
5656
|
this.memoryManager = new MemoryManager(dbPath, {
|
|
5646
5657
|
checkpointTtlMs: Math.max(1, config.memory?.checkpointTtlHours ?? 24) * 60 * 60 * 1e3,
|
|
5647
5658
|
observationFrameTtlMs: Math.max(1, config.memory?.observationFrameTtlHours ?? 24 * 7) * 60 * 60 * 1e3
|