@lydia-agent/core 0.1.0 → 0.1.2
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 +131 -118
- package/dist/index.js +131 -118
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -529,6 +529,8 @@ var StrategyRegistry = class {
|
|
|
529
529
|
// User Home
|
|
530
530
|
path.join(os.homedir(), ".lydia", "strategies", "default.yml"),
|
|
531
531
|
// Package Built-in
|
|
532
|
+
path.resolve(__dirname2, "../strategies/base-v1.yml"),
|
|
533
|
+
// Package Built-in (older path assumption)
|
|
532
534
|
path.resolve(__dirname2, "../../strategies/base-v1.yml"),
|
|
533
535
|
// Package Built-in (dev/src)
|
|
534
536
|
path.resolve(__dirname2, "../../../strategies/base-v1.yml")
|
|
@@ -590,17 +592,20 @@ var StrategyRegistry = class {
|
|
|
590
592
|
|
|
591
593
|
// src/strategy/approval-service.ts
|
|
592
594
|
import * as os2 from "os";
|
|
593
|
-
import * as
|
|
595
|
+
import * as path3 from "path";
|
|
594
596
|
|
|
595
597
|
// src/memory/manager.ts
|
|
596
598
|
import Database from "better-sqlite3";
|
|
597
599
|
import { EventEmitter } from "events";
|
|
600
|
+
import * as fs2 from "fs";
|
|
601
|
+
import * as path2 from "path";
|
|
598
602
|
var MemoryManager = class extends EventEmitter {
|
|
599
603
|
db;
|
|
600
604
|
checkpointTtlMs;
|
|
601
605
|
observationFrameTtlMs;
|
|
602
606
|
constructor(dbPath, options = {}) {
|
|
603
607
|
super();
|
|
608
|
+
fs2.mkdirSync(path2.dirname(dbPath), { recursive: true });
|
|
604
609
|
this.db = new Database(dbPath);
|
|
605
610
|
this.checkpointTtlMs = options.checkpointTtlMs ?? 24 * 60 * 60 * 1e3;
|
|
606
611
|
this.observationFrameTtlMs = options.observationFrameTtlMs ?? 24 * 7 * 60 * 60 * 1e3;
|
|
@@ -1484,7 +1489,7 @@ var StrategyApprovalService = class {
|
|
|
1484
1489
|
if (memoryManager) {
|
|
1485
1490
|
this.memory = memoryManager;
|
|
1486
1491
|
} else {
|
|
1487
|
-
const dbPath =
|
|
1492
|
+
const dbPath = path3.join(os2.homedir(), ".lydia", "memory.db");
|
|
1488
1493
|
this.memory = new MemoryManager(dbPath);
|
|
1489
1494
|
}
|
|
1490
1495
|
this.configLoader = configLoader || new ConfigLoader();
|
|
@@ -1545,7 +1550,7 @@ var StrategyApprovalService = class {
|
|
|
1545
1550
|
};
|
|
1546
1551
|
|
|
1547
1552
|
// src/strategy/shadow-router.ts
|
|
1548
|
-
import * as
|
|
1553
|
+
import * as path4 from "path";
|
|
1549
1554
|
import * as os3 from "os";
|
|
1550
1555
|
var ShadowRouter = class {
|
|
1551
1556
|
memory;
|
|
@@ -1555,7 +1560,7 @@ var ShadowRouter = class {
|
|
|
1555
1560
|
if (memoryManager) {
|
|
1556
1561
|
this.memory = memoryManager;
|
|
1557
1562
|
} else {
|
|
1558
|
-
const dbPath =
|
|
1563
|
+
const dbPath = path4.join(os3.homedir(), ".lydia", "memory.db");
|
|
1559
1564
|
this.memory = new MemoryManager(dbPath);
|
|
1560
1565
|
}
|
|
1561
1566
|
this.registry = strategyRegistry || new StrategyRegistry();
|
|
@@ -1826,39 +1831,39 @@ var StrategyReviewer = class {
|
|
|
1826
1831
|
};
|
|
1827
1832
|
|
|
1828
1833
|
// src/strategy/branch-manager.ts
|
|
1829
|
-
import * as
|
|
1830
|
-
import * as
|
|
1834
|
+
import * as fs3 from "fs/promises";
|
|
1835
|
+
import * as path5 from "path";
|
|
1831
1836
|
import * as os4 from "os";
|
|
1832
1837
|
import { parse as parseYaml2, stringify as stringifyYaml2 } from "yaml";
|
|
1833
1838
|
var StrategyBranchManager = class {
|
|
1834
1839
|
baseDir;
|
|
1835
1840
|
constructor(baseDir) {
|
|
1836
|
-
this.baseDir = baseDir ||
|
|
1841
|
+
this.baseDir = baseDir || path5.join(os4.homedir(), ".lydia", "strategies");
|
|
1837
1842
|
}
|
|
1838
1843
|
async init() {
|
|
1839
|
-
await
|
|
1840
|
-
await
|
|
1841
|
-
await
|
|
1844
|
+
await fs3.mkdir(this.baseDir, { recursive: true });
|
|
1845
|
+
await fs3.mkdir(path5.join(this.baseDir, "branches"), { recursive: true });
|
|
1846
|
+
await fs3.mkdir(path5.join(this.baseDir, "archive"), { recursive: true });
|
|
1842
1847
|
}
|
|
1843
1848
|
async listBranches() {
|
|
1844
|
-
const branchesDir =
|
|
1849
|
+
const branchesDir = path5.join(this.baseDir, "branches");
|
|
1845
1850
|
try {
|
|
1846
|
-
const entries = await
|
|
1851
|
+
const entries = await fs3.readdir(branchesDir, { withFileTypes: true });
|
|
1847
1852
|
const branches = [];
|
|
1848
1853
|
for (const entry of entries) {
|
|
1849
1854
|
if (!entry.isDirectory()) continue;
|
|
1850
1855
|
}
|
|
1851
|
-
const files = await
|
|
1856
|
+
const files = await fs3.readdir(branchesDir);
|
|
1852
1857
|
for (const file of files) {
|
|
1853
1858
|
if (!file.endsWith(".yml")) continue;
|
|
1854
|
-
const content = await
|
|
1859
|
+
const content = await fs3.readFile(path5.join(branchesDir, file), "utf-8");
|
|
1855
1860
|
try {
|
|
1856
1861
|
const strategy = StrategySchema.parse(parseYaml2(content));
|
|
1857
1862
|
branches.push({
|
|
1858
1863
|
name: strategy.metadata.id,
|
|
1859
1864
|
// ID is used as branch name effectively
|
|
1860
1865
|
version: strategy.metadata.version,
|
|
1861
|
-
path:
|
|
1866
|
+
path: path5.join(branchesDir, file),
|
|
1862
1867
|
parent: strategy.metadata.inheritFrom,
|
|
1863
1868
|
createdAt: Date.now()
|
|
1864
1869
|
// We might want to store this in metadata later
|
|
@@ -1874,8 +1879,8 @@ var StrategyBranchManager = class {
|
|
|
1874
1879
|
}
|
|
1875
1880
|
}
|
|
1876
1881
|
async createBranch(sourceStrategy, newBranchName, modifications) {
|
|
1877
|
-
const targetDir =
|
|
1878
|
-
await
|
|
1882
|
+
const targetDir = path5.join(this.baseDir, "branches");
|
|
1883
|
+
await fs3.mkdir(targetDir, { recursive: true });
|
|
1879
1884
|
const newStrategy = {
|
|
1880
1885
|
...sourceStrategy,
|
|
1881
1886
|
...modifications,
|
|
@@ -1889,14 +1894,14 @@ var StrategyBranchManager = class {
|
|
|
1889
1894
|
...modifications.metadata
|
|
1890
1895
|
}
|
|
1891
1896
|
};
|
|
1892
|
-
const filePath =
|
|
1893
|
-
await
|
|
1897
|
+
const filePath = path5.join(targetDir, `${newBranchName}.yml`);
|
|
1898
|
+
await fs3.writeFile(filePath, stringifyYaml2(newStrategy), "utf-8");
|
|
1894
1899
|
return newStrategy;
|
|
1895
1900
|
}
|
|
1896
1901
|
async getBranch(branchName) {
|
|
1897
|
-
const filePath =
|
|
1902
|
+
const filePath = path5.join(this.baseDir, "branches", `${branchName}.yml`);
|
|
1898
1903
|
try {
|
|
1899
|
-
const content = await
|
|
1904
|
+
const content = await fs3.readFile(filePath, "utf-8");
|
|
1900
1905
|
return StrategySchema.parse(parseYaml2(content));
|
|
1901
1906
|
} catch {
|
|
1902
1907
|
return null;
|
|
@@ -1907,12 +1912,12 @@ var StrategyBranchManager = class {
|
|
|
1907
1912
|
if (!branch) throw new Error(`Branch ${branchName} not found`);
|
|
1908
1913
|
const parentId = branch.metadata.inheritFrom;
|
|
1909
1914
|
if (!parentId) throw new Error("Branch has no parent to merge into");
|
|
1910
|
-
const files = await
|
|
1915
|
+
const files = await fs3.readdir(this.baseDir);
|
|
1911
1916
|
let parentFile = null;
|
|
1912
1917
|
for (const file of files) {
|
|
1913
1918
|
if (file === "branches" || file === "archive") continue;
|
|
1914
1919
|
try {
|
|
1915
|
-
const content = await
|
|
1920
|
+
const content = await fs3.readFile(path5.join(this.baseDir, file), "utf-8");
|
|
1916
1921
|
const data = parseYaml2(content);
|
|
1917
1922
|
if (data.metadata?.id === parentId) {
|
|
1918
1923
|
parentFile = file;
|
|
@@ -1924,18 +1929,18 @@ var StrategyBranchManager = class {
|
|
|
1924
1929
|
if (!parentFile) {
|
|
1925
1930
|
throw new Error(`Parent strategy ${parentId} not found in ${this.baseDir}`);
|
|
1926
1931
|
}
|
|
1927
|
-
const parentPath =
|
|
1928
|
-
await
|
|
1932
|
+
const parentPath = path5.join(this.baseDir, parentFile);
|
|
1933
|
+
await fs3.copyFile(parentPath, path5.join(this.baseDir, "archive", `${parentId}-${Date.now()}.bak.yml`));
|
|
1929
1934
|
const start = Date.now();
|
|
1930
|
-
const branchContent = await
|
|
1931
|
-
await
|
|
1935
|
+
const branchContent = await fs3.readFile(path5.join(this.baseDir, "branches", `${branchName}.yml`), "utf-8");
|
|
1936
|
+
await fs3.writeFile(parentPath, branchContent, "utf-8");
|
|
1932
1937
|
await this.archiveBranch(branchName);
|
|
1933
1938
|
}
|
|
1934
1939
|
async archiveBranch(branchName) {
|
|
1935
|
-
const srcPath =
|
|
1936
|
-
const destPath =
|
|
1940
|
+
const srcPath = path5.join(this.baseDir, "branches", `${branchName}.yml`);
|
|
1941
|
+
const destPath = path5.join(this.baseDir, "archive", `${branchName}-${Date.now()}.yml`);
|
|
1937
1942
|
try {
|
|
1938
|
-
await
|
|
1943
|
+
await fs3.rename(srcPath, destPath);
|
|
1939
1944
|
} catch (e) {
|
|
1940
1945
|
console.error(`Failed to archive branch ${branchName}:`, e);
|
|
1941
1946
|
throw e;
|
|
@@ -2198,11 +2203,11 @@ var SkillRegistry = class {
|
|
|
2198
2203
|
};
|
|
2199
2204
|
|
|
2200
2205
|
// src/skills/loader.ts
|
|
2201
|
-
import * as
|
|
2202
|
-
import * as
|
|
2206
|
+
import * as fs4 from "fs/promises";
|
|
2207
|
+
import * as path6 from "path";
|
|
2203
2208
|
import * as os5 from "os";
|
|
2204
2209
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2205
|
-
var __dirname3 =
|
|
2210
|
+
var __dirname3 = path6.dirname(fileURLToPath2(import.meta.url));
|
|
2206
2211
|
var SkillLoader = class {
|
|
2207
2212
|
registry;
|
|
2208
2213
|
/** Ordered list of directories to scan for skills */
|
|
@@ -2217,13 +2222,13 @@ var SkillLoader = class {
|
|
|
2217
2222
|
getDirectories(extraDirs = []) {
|
|
2218
2223
|
return [
|
|
2219
2224
|
// 1. Built-in skills (relative to this file in dist/skills)
|
|
2220
|
-
|
|
2225
|
+
path6.resolve(__dirname3, "../../skills"),
|
|
2221
2226
|
// 1.5 Built-in skills in source tree (dev mode)
|
|
2222
|
-
|
|
2227
|
+
path6.resolve(__dirname3, "../skills"),
|
|
2223
2228
|
// 2. User global skills
|
|
2224
|
-
|
|
2229
|
+
path6.join(os5.homedir(), ".lydia", "skills"),
|
|
2225
2230
|
// 3. Project local skills
|
|
2226
|
-
|
|
2231
|
+
path6.join(process.cwd(), ".lydia", "skills"),
|
|
2227
2232
|
// 4. Extra directories from config
|
|
2228
2233
|
...extraDirs
|
|
2229
2234
|
];
|
|
@@ -2244,11 +2249,11 @@ var SkillLoader = class {
|
|
|
2244
2249
|
*/
|
|
2245
2250
|
async loadMetadataFromDirectory(dirPath) {
|
|
2246
2251
|
try {
|
|
2247
|
-
const stats = await
|
|
2252
|
+
const stats = await fs4.stat(dirPath);
|
|
2248
2253
|
if (!stats.isDirectory()) return;
|
|
2249
|
-
const entries = await
|
|
2254
|
+
const entries = await fs4.readdir(dirPath, { withFileTypes: true });
|
|
2250
2255
|
for (const entry of entries) {
|
|
2251
|
-
const fullPath =
|
|
2256
|
+
const fullPath = path6.join(dirPath, entry.name);
|
|
2252
2257
|
if (entry.isDirectory()) {
|
|
2253
2258
|
await this.loadMetadataFromDirectory(fullPath);
|
|
2254
2259
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -2264,7 +2269,7 @@ var SkillLoader = class {
|
|
|
2264
2269
|
*/
|
|
2265
2270
|
async loadSkillMeta(filePath) {
|
|
2266
2271
|
try {
|
|
2267
|
-
const content = await
|
|
2272
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
2268
2273
|
if (content.startsWith("---")) {
|
|
2269
2274
|
const meta = SkillParser.parseMeta(content, filePath);
|
|
2270
2275
|
this.registry.register(meta);
|
|
@@ -2285,7 +2290,7 @@ var SkillLoader = class {
|
|
|
2285
2290
|
const meta = this.registry.get(name);
|
|
2286
2291
|
if (!meta?.path) return null;
|
|
2287
2292
|
try {
|
|
2288
|
-
const fileContent = await
|
|
2293
|
+
const fileContent = await fs4.readFile(meta.path, "utf-8");
|
|
2289
2294
|
const skill = SkillParser.parse(fileContent, meta.path);
|
|
2290
2295
|
return skill.content;
|
|
2291
2296
|
} catch (error) {
|
|
@@ -2301,7 +2306,7 @@ var SkillLoader = class {
|
|
|
2301
2306
|
const meta = this.registry.get(name);
|
|
2302
2307
|
if (!meta?.path) return null;
|
|
2303
2308
|
try {
|
|
2304
|
-
const fileContent = await
|
|
2309
|
+
const fileContent = await fs4.readFile(meta.path, "utf-8");
|
|
2305
2310
|
return SkillParser.parse(fileContent, meta.path);
|
|
2306
2311
|
} catch (error) {
|
|
2307
2312
|
console.warn(`Failed to load full skill "${name}":`, error);
|
|
@@ -2314,7 +2319,7 @@ var SkillLoader = class {
|
|
|
2314
2319
|
*/
|
|
2315
2320
|
async reloadSkillMeta(filePath) {
|
|
2316
2321
|
try {
|
|
2317
|
-
const content = await
|
|
2322
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
2318
2323
|
if (content.startsWith("---")) {
|
|
2319
2324
|
const meta = SkillParser.parseMeta(content, filePath);
|
|
2320
2325
|
this.registry.register(meta);
|
|
@@ -2329,9 +2334,9 @@ var SkillLoader = class {
|
|
|
2329
2334
|
|
|
2330
2335
|
// src/skills/watcher.ts
|
|
2331
2336
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
2332
|
-
import * as
|
|
2337
|
+
import * as fs5 from "fs";
|
|
2333
2338
|
import * as fsPromises from "fs/promises";
|
|
2334
|
-
import * as
|
|
2339
|
+
import * as path7 from "path";
|
|
2335
2340
|
var SkillWatcher = class extends EventEmitter2 {
|
|
2336
2341
|
constructor(directories, registry, loader, options) {
|
|
2337
2342
|
super();
|
|
@@ -2341,7 +2346,7 @@ var SkillWatcher = class extends EventEmitter2 {
|
|
|
2341
2346
|
this.debounceMs = options?.debounceMs ?? 300;
|
|
2342
2347
|
for (const skill of this.registry.list()) {
|
|
2343
2348
|
if (skill.path) {
|
|
2344
|
-
this.pathToName.set(
|
|
2349
|
+
this.pathToName.set(path7.resolve(skill.path), skill.name);
|
|
2345
2350
|
}
|
|
2346
2351
|
}
|
|
2347
2352
|
}
|
|
@@ -2380,12 +2385,12 @@ var SkillWatcher = class extends EventEmitter2 {
|
|
|
2380
2385
|
}
|
|
2381
2386
|
watchDirectory(dirPath) {
|
|
2382
2387
|
try {
|
|
2383
|
-
if (!
|
|
2388
|
+
if (!fs5.existsSync(dirPath) || !fs5.statSync(dirPath).isDirectory()) {
|
|
2384
2389
|
return;
|
|
2385
2390
|
}
|
|
2386
|
-
const watcher =
|
|
2391
|
+
const watcher = fs5.watch(dirPath, { recursive: true }, (eventType, filename) => {
|
|
2387
2392
|
if (!filename) return;
|
|
2388
|
-
const fullPath =
|
|
2393
|
+
const fullPath = path7.resolve(dirPath, filename);
|
|
2389
2394
|
if (!filename.endsWith(".md")) return;
|
|
2390
2395
|
this.handleFileChange(fullPath, eventType);
|
|
2391
2396
|
});
|
|
@@ -2397,7 +2402,7 @@ var SkillWatcher = class extends EventEmitter2 {
|
|
|
2397
2402
|
}
|
|
2398
2403
|
}
|
|
2399
2404
|
handleFileChange(filePath, _eventType) {
|
|
2400
|
-
const resolvedPath =
|
|
2405
|
+
const resolvedPath = path7.resolve(filePath);
|
|
2401
2406
|
const existingTimer = this.debounceTimers.get(resolvedPath);
|
|
2402
2407
|
if (existingTimer) {
|
|
2403
2408
|
clearTimeout(existingTimer);
|
|
@@ -2454,7 +2459,7 @@ var ShellServer = class {
|
|
|
2454
2459
|
this.server = new Server(
|
|
2455
2460
|
{
|
|
2456
2461
|
name: "internal-shell",
|
|
2457
|
-
version: "0.1.
|
|
2462
|
+
version: "0.1.2"
|
|
2458
2463
|
},
|
|
2459
2464
|
{
|
|
2460
2465
|
capabilities: {
|
|
@@ -2521,18 +2526,18 @@ ${error.stderr || ""}`
|
|
|
2521
2526
|
// src/mcp/servers/filesystem.ts
|
|
2522
2527
|
import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2523
2528
|
import { CallToolRequestSchema as CallToolRequestSchema2, ListToolsRequestSchema as ListToolsRequestSchema2 } from "@modelcontextprotocol/sdk/types.js";
|
|
2524
|
-
import * as
|
|
2525
|
-
import * as
|
|
2529
|
+
import * as fs6 from "fs/promises";
|
|
2530
|
+
import * as path8 from "path";
|
|
2526
2531
|
import { gunzipSync, gzipSync } from "zlib";
|
|
2527
2532
|
var FileSystemServer = class {
|
|
2528
2533
|
server;
|
|
2529
2534
|
allowedRootDir;
|
|
2530
2535
|
constructor(allowedRootDir = process.cwd()) {
|
|
2531
|
-
this.allowedRootDir =
|
|
2536
|
+
this.allowedRootDir = path8.resolve(allowedRootDir);
|
|
2532
2537
|
this.server = new Server2(
|
|
2533
2538
|
{
|
|
2534
2539
|
name: "internal-fs",
|
|
2535
|
-
version: "0.1.
|
|
2540
|
+
version: "0.1.2"
|
|
2536
2541
|
},
|
|
2537
2542
|
{
|
|
2538
2543
|
capabilities: {
|
|
@@ -2543,7 +2548,7 @@ var FileSystemServer = class {
|
|
|
2543
2548
|
this.setupHandlers();
|
|
2544
2549
|
}
|
|
2545
2550
|
validatePath(requestedPath) {
|
|
2546
|
-
const resolvedPath =
|
|
2551
|
+
const resolvedPath = path8.resolve(this.allowedRootDir, requestedPath);
|
|
2547
2552
|
const root = process.platform === "win32" ? this.allowedRootDir.toLowerCase() : this.allowedRootDir;
|
|
2548
2553
|
const target = process.platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
|
|
2549
2554
|
if (!target.startsWith(root)) {
|
|
@@ -2665,22 +2670,22 @@ var FileSystemServer = class {
|
|
|
2665
2670
|
switch (request.params.name) {
|
|
2666
2671
|
case "fs_read_file": {
|
|
2667
2672
|
const filePath = this.validatePath(args.path);
|
|
2668
|
-
const content = await
|
|
2673
|
+
const content = await fs6.readFile(filePath, "utf-8");
|
|
2669
2674
|
return {
|
|
2670
2675
|
content: [{ type: "text", text: content }]
|
|
2671
2676
|
};
|
|
2672
2677
|
}
|
|
2673
2678
|
case "fs_write_file": {
|
|
2674
2679
|
const filePath = this.validatePath(args.path);
|
|
2675
|
-
await
|
|
2676
|
-
await
|
|
2680
|
+
await fs6.mkdir(path8.dirname(filePath), { recursive: true });
|
|
2681
|
+
await fs6.writeFile(filePath, args.content, "utf-8");
|
|
2677
2682
|
return {
|
|
2678
2683
|
content: [{ type: "text", text: `Successfully wrote to ${filePath}` }]
|
|
2679
2684
|
};
|
|
2680
2685
|
}
|
|
2681
2686
|
case "fs_list_directory": {
|
|
2682
2687
|
const dirPath = this.validatePath(args.path);
|
|
2683
|
-
const entries = await
|
|
2688
|
+
const entries = await fs6.readdir(dirPath, { withFileTypes: true });
|
|
2684
2689
|
const list = entries.map((e) => `${e.isDirectory() ? "[DIR]" : "[FILE]"} ${e.name}`).join("\n");
|
|
2685
2690
|
return {
|
|
2686
2691
|
content: [{ type: "text", text: list }]
|
|
@@ -2691,8 +2696,8 @@ var FileSystemServer = class {
|
|
|
2691
2696
|
const toPath = this.validatePath(args.to);
|
|
2692
2697
|
const overwrite = Boolean(args.overwrite);
|
|
2693
2698
|
await this.ensureDestWritable(toPath, overwrite);
|
|
2694
|
-
await
|
|
2695
|
-
await
|
|
2699
|
+
await fs6.mkdir(path8.dirname(toPath), { recursive: true });
|
|
2700
|
+
await fs6.copyFile(fromPath, toPath);
|
|
2696
2701
|
return {
|
|
2697
2702
|
content: [{ type: "text", text: `Successfully copied ${fromPath} -> ${toPath}` }]
|
|
2698
2703
|
};
|
|
@@ -2702,7 +2707,7 @@ var FileSystemServer = class {
|
|
|
2702
2707
|
const toPath = this.validatePath(args.to);
|
|
2703
2708
|
const overwrite = Boolean(args.overwrite);
|
|
2704
2709
|
await this.ensureDestWritable(toPath, overwrite);
|
|
2705
|
-
await
|
|
2710
|
+
await fs6.mkdir(path8.dirname(toPath), { recursive: true });
|
|
2706
2711
|
await this.moveFile(fromPath, toPath);
|
|
2707
2712
|
return {
|
|
2708
2713
|
content: [{ type: "text", text: `Successfully moved ${fromPath} -> ${toPath}` }]
|
|
@@ -2724,9 +2729,9 @@ var FileSystemServer = class {
|
|
|
2724
2729
|
const overwrite = Boolean(args.overwrite);
|
|
2725
2730
|
const maxBytes = Math.max(1024, Number(args.maxBytes) || 20 * 1024 * 1024);
|
|
2726
2731
|
await this.ensureDestWritable(outputPath, overwrite);
|
|
2727
|
-
await
|
|
2732
|
+
await fs6.mkdir(path8.dirname(outputPath), { recursive: true });
|
|
2728
2733
|
const bundle = await this.createArchiveBundle(sourcePath, maxBytes);
|
|
2729
|
-
await
|
|
2734
|
+
await fs6.writeFile(outputPath, bundle.buffer);
|
|
2730
2735
|
return {
|
|
2731
2736
|
content: [{ type: "text", text: `Successfully archived ${bundle.fileCount} file(s) to ${outputPath}` }]
|
|
2732
2737
|
};
|
|
@@ -2736,7 +2741,7 @@ var FileSystemServer = class {
|
|
|
2736
2741
|
const outputDir = this.validatePath(args.outputDir);
|
|
2737
2742
|
const overwrite = Boolean(args.overwrite);
|
|
2738
2743
|
const maxBytes = Math.max(1024, Number(args.maxBytes) || 20 * 1024 * 1024);
|
|
2739
|
-
const archiveBuffer = await
|
|
2744
|
+
const archiveBuffer = await fs6.readFile(archivePath);
|
|
2740
2745
|
const bundle = this.parseArchiveBundle(archiveBuffer);
|
|
2741
2746
|
const written = await this.extractArchiveBundle(bundle, outputDir, overwrite, maxBytes);
|
|
2742
2747
|
return {
|
|
@@ -2756,11 +2761,11 @@ var FileSystemServer = class {
|
|
|
2756
2761
|
}
|
|
2757
2762
|
async ensureDestWritable(destPath, overwrite) {
|
|
2758
2763
|
try {
|
|
2759
|
-
await
|
|
2764
|
+
await fs6.access(destPath);
|
|
2760
2765
|
if (!overwrite) {
|
|
2761
2766
|
throw new Error(`Destination already exists: ${destPath}. Pass overwrite=true to replace.`);
|
|
2762
2767
|
}
|
|
2763
|
-
await
|
|
2768
|
+
await fs6.rm(destPath, { recursive: true, force: true });
|
|
2764
2769
|
} catch (error) {
|
|
2765
2770
|
if (error?.code === "ENOENT") return;
|
|
2766
2771
|
throw error;
|
|
@@ -2768,11 +2773,11 @@ var FileSystemServer = class {
|
|
|
2768
2773
|
}
|
|
2769
2774
|
async moveFile(fromPath, toPath) {
|
|
2770
2775
|
try {
|
|
2771
|
-
await
|
|
2776
|
+
await fs6.rename(fromPath, toPath);
|
|
2772
2777
|
} catch (error) {
|
|
2773
2778
|
if (error?.code !== "EXDEV") throw error;
|
|
2774
|
-
await
|
|
2775
|
-
await
|
|
2779
|
+
await fs6.copyFile(fromPath, toPath);
|
|
2780
|
+
await fs6.unlink(fromPath);
|
|
2776
2781
|
}
|
|
2777
2782
|
}
|
|
2778
2783
|
async searchByName(basePath, pattern, maxResults) {
|
|
@@ -2782,10 +2787,10 @@ var FileSystemServer = class {
|
|
|
2782
2787
|
while (queue.length > 0 && results.length < maxResults) {
|
|
2783
2788
|
const current = queue.shift();
|
|
2784
2789
|
if (!current) break;
|
|
2785
|
-
const entries = await
|
|
2790
|
+
const entries = await fs6.readdir(current, { withFileTypes: true });
|
|
2786
2791
|
for (const entry of entries) {
|
|
2787
|
-
const fullPath =
|
|
2788
|
-
const relative3 =
|
|
2792
|
+
const fullPath = path8.join(current, entry.name);
|
|
2793
|
+
const relative3 = path8.relative(this.allowedRootDir, fullPath) || ".";
|
|
2789
2794
|
if (matcher(entry.name)) {
|
|
2790
2795
|
results.push(`${entry.isDirectory() ? "[DIR]" : "[FILE]"} ${relative3}`);
|
|
2791
2796
|
if (results.length >= maxResults) break;
|
|
@@ -2809,11 +2814,11 @@ var FileSystemServer = class {
|
|
|
2809
2814
|
return (name) => name.toLowerCase().includes(lowered);
|
|
2810
2815
|
}
|
|
2811
2816
|
async createArchiveBundle(sourcePath, maxBytes) {
|
|
2812
|
-
const stat3 = await
|
|
2817
|
+
const stat3 = await fs6.stat(sourcePath);
|
|
2813
2818
|
const files = [];
|
|
2814
2819
|
let totalBytes = 0;
|
|
2815
2820
|
const readAndAppend = async (absolutePath, relativePath) => {
|
|
2816
|
-
const data = await
|
|
2821
|
+
const data = await fs6.readFile(absolutePath);
|
|
2817
2822
|
totalBytes += data.length;
|
|
2818
2823
|
if (totalBytes > maxBytes) {
|
|
2819
2824
|
throw new Error(`Archive exceeds maxBytes limit (${maxBytes}).`);
|
|
@@ -2826,28 +2831,28 @@ var FileSystemServer = class {
|
|
|
2826
2831
|
});
|
|
2827
2832
|
};
|
|
2828
2833
|
if (stat3.isFile()) {
|
|
2829
|
-
await readAndAppend(sourcePath,
|
|
2834
|
+
await readAndAppend(sourcePath, path8.basename(sourcePath));
|
|
2830
2835
|
} else if (stat3.isDirectory()) {
|
|
2831
2836
|
const queue = [sourcePath];
|
|
2832
2837
|
while (queue.length > 0) {
|
|
2833
2838
|
const current = queue.shift();
|
|
2834
2839
|
if (!current) break;
|
|
2835
|
-
const entries = await
|
|
2840
|
+
const entries = await fs6.readdir(current, { withFileTypes: true });
|
|
2836
2841
|
for (const entry of entries) {
|
|
2837
|
-
const fullPath =
|
|
2842
|
+
const fullPath = path8.join(current, entry.name);
|
|
2838
2843
|
if (entry.isDirectory()) {
|
|
2839
2844
|
queue.push(fullPath);
|
|
2840
2845
|
continue;
|
|
2841
2846
|
}
|
|
2842
2847
|
if (!entry.isFile()) continue;
|
|
2843
|
-
const relativePath =
|
|
2848
|
+
const relativePath = path8.relative(sourcePath, fullPath) || entry.name;
|
|
2844
2849
|
await readAndAppend(fullPath, relativePath.replace(/\\/g, "/"));
|
|
2845
2850
|
}
|
|
2846
2851
|
}
|
|
2847
2852
|
} else {
|
|
2848
2853
|
throw new Error("Only files and directories can be archived.");
|
|
2849
2854
|
}
|
|
2850
|
-
const sourceRelative =
|
|
2855
|
+
const sourceRelative = path8.relative(this.allowedRootDir, sourcePath).replace(/\\/g, "/");
|
|
2851
2856
|
const bundle = {
|
|
2852
2857
|
format: "lydia-archive-v1",
|
|
2853
2858
|
source: sourceRelative || ".",
|
|
@@ -2880,13 +2885,13 @@ var FileSystemServer = class {
|
|
|
2880
2885
|
let count = 0;
|
|
2881
2886
|
for (const file of bundle.files) {
|
|
2882
2887
|
const relPath = String(file.path || "").replace(/\\/g, "/");
|
|
2883
|
-
if (!relPath ||
|
|
2888
|
+
if (!relPath || path8.isAbsolute(relPath) || relPath.includes("..")) {
|
|
2884
2889
|
throw new Error(`Unsafe archive entry path: ${relPath || "<empty>"}`);
|
|
2885
2890
|
}
|
|
2886
|
-
const targetPath =
|
|
2891
|
+
const targetPath = path8.resolve(outputDir, relPath);
|
|
2887
2892
|
const safeOutputDir = process.platform === "win32" ? outputDir.toLowerCase() : outputDir;
|
|
2888
2893
|
const safeTarget = process.platform === "win32" ? targetPath.toLowerCase() : targetPath;
|
|
2889
|
-
if (!safeTarget.startsWith(safeOutputDir +
|
|
2894
|
+
if (!safeTarget.startsWith(safeOutputDir + path8.sep) && safeTarget !== safeOutputDir) {
|
|
2890
2895
|
throw new Error(`Archive entry escapes destination: ${relPath}`);
|
|
2891
2896
|
}
|
|
2892
2897
|
const data = this.decodeArchiveEntry(file);
|
|
@@ -2894,8 +2899,8 @@ var FileSystemServer = class {
|
|
|
2894
2899
|
if (totalBytes > maxBytes) {
|
|
2895
2900
|
throw new Error(`Unarchive exceeds maxBytes limit (${maxBytes}).`);
|
|
2896
2901
|
}
|
|
2897
|
-
await
|
|
2898
|
-
await
|
|
2902
|
+
await fs6.mkdir(path8.dirname(targetPath), { recursive: true });
|
|
2903
|
+
await fs6.writeFile(targetPath, data);
|
|
2899
2904
|
count += 1;
|
|
2900
2905
|
}
|
|
2901
2906
|
return count;
|
|
@@ -2915,22 +2920,22 @@ var FileSystemServer = class {
|
|
|
2915
2920
|
}
|
|
2916
2921
|
async prepareOutputDirectory(outputDir, overwrite) {
|
|
2917
2922
|
try {
|
|
2918
|
-
const stat3 = await
|
|
2923
|
+
const stat3 = await fs6.stat(outputDir);
|
|
2919
2924
|
if (!stat3.isDirectory()) {
|
|
2920
2925
|
throw new Error(`Output path is not a directory: ${outputDir}`);
|
|
2921
2926
|
}
|
|
2922
2927
|
if (!overwrite) {
|
|
2923
|
-
const entries = await
|
|
2928
|
+
const entries = await fs6.readdir(outputDir);
|
|
2924
2929
|
if (entries.length > 0) {
|
|
2925
2930
|
throw new Error(`Output directory is not empty: ${outputDir}. Pass overwrite=true to replace.`);
|
|
2926
2931
|
}
|
|
2927
2932
|
} else {
|
|
2928
|
-
await
|
|
2929
|
-
await
|
|
2933
|
+
await fs6.rm(outputDir, { recursive: true, force: true });
|
|
2934
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
2930
2935
|
}
|
|
2931
2936
|
} catch (error) {
|
|
2932
2937
|
if (error?.code === "ENOENT") {
|
|
2933
|
-
await
|
|
2938
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
2934
2939
|
return;
|
|
2935
2940
|
}
|
|
2936
2941
|
throw error;
|
|
@@ -2950,7 +2955,7 @@ var GitServer = class {
|
|
|
2950
2955
|
this.server = new Server3(
|
|
2951
2956
|
{
|
|
2952
2957
|
name: "internal-git",
|
|
2953
|
-
version: "0.1.
|
|
2958
|
+
version: "0.1.2"
|
|
2954
2959
|
},
|
|
2955
2960
|
{
|
|
2956
2961
|
capabilities: {
|
|
@@ -3127,7 +3132,7 @@ var MemoryServer = class {
|
|
|
3127
3132
|
this.server = new Server4(
|
|
3128
3133
|
{
|
|
3129
3134
|
name: "internal-memory",
|
|
3130
|
-
version: "0.1.
|
|
3135
|
+
version: "0.1.2"
|
|
3131
3136
|
},
|
|
3132
3137
|
{
|
|
3133
3138
|
capabilities: {
|
|
@@ -3253,7 +3258,7 @@ var InteractionServer = class extends EventEmitter3 {
|
|
|
3253
3258
|
constructor() {
|
|
3254
3259
|
super();
|
|
3255
3260
|
this.server = new Server5(
|
|
3256
|
-
{ name: "internal-interaction", version: "0.1.
|
|
3261
|
+
{ name: "internal-interaction", version: "0.1.2" },
|
|
3257
3262
|
{ capabilities: { tools: {} } }
|
|
3258
3263
|
);
|
|
3259
3264
|
this.setupHandlers();
|
|
@@ -3634,7 +3639,7 @@ var McpClientManager = class {
|
|
|
3634
3639
|
const client = new Client(
|
|
3635
3640
|
{
|
|
3636
3641
|
name: "lydia-client",
|
|
3637
|
-
version: "0.1.
|
|
3642
|
+
version: "0.1.2"
|
|
3638
3643
|
},
|
|
3639
3644
|
{
|
|
3640
3645
|
capabilities: {
|
|
@@ -3742,7 +3747,7 @@ var McpClientManager = class {
|
|
|
3742
3747
|
};
|
|
3743
3748
|
|
|
3744
3749
|
// src/gate/risk.ts
|
|
3745
|
-
import * as
|
|
3750
|
+
import * as path9 from "path";
|
|
3746
3751
|
import * as os6 from "os";
|
|
3747
3752
|
var DEFAULT_USER_DATA_DIRS = [
|
|
3748
3753
|
"~/.lydia",
|
|
@@ -3772,13 +3777,13 @@ var COMPUTER_USE_HIGH_RISK_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
3772
3777
|
]);
|
|
3773
3778
|
function expandHome(p) {
|
|
3774
3779
|
if (p.startsWith("~/") || p === "~") {
|
|
3775
|
-
return
|
|
3780
|
+
return path9.join(os6.homedir(), p.slice(2));
|
|
3776
3781
|
}
|
|
3777
3782
|
return p;
|
|
3778
3783
|
}
|
|
3779
3784
|
function normalizePath(p) {
|
|
3780
3785
|
const expanded = expandHome(p);
|
|
3781
|
-
const normalized =
|
|
3786
|
+
const normalized = path9.resolve(expanded);
|
|
3782
3787
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
3783
3788
|
}
|
|
3784
3789
|
function buildProtectedDirs(config) {
|
|
@@ -3791,7 +3796,7 @@ function buildProtectedDirs(config) {
|
|
|
3791
3796
|
}
|
|
3792
3797
|
function isInProtectedDir(targetPath, protectedDirs) {
|
|
3793
3798
|
const normalizedTarget = normalizePath(targetPath);
|
|
3794
|
-
return protectedDirs.some((dir) => normalizedTarget === dir || normalizedTarget.startsWith(dir +
|
|
3799
|
+
return protectedDirs.some((dir) => normalizedTarget === dir || normalizedTarget.startsWith(dir + path9.sep));
|
|
3795
3800
|
}
|
|
3796
3801
|
function extractPathsFromCommand(command) {
|
|
3797
3802
|
const paths = [];
|
|
@@ -3813,7 +3818,7 @@ function hasRelativePathTraversal(input) {
|
|
|
3813
3818
|
return /(^|[\\\/])\.\.([\\\/]|$)/.test(input);
|
|
3814
3819
|
}
|
|
3815
3820
|
function isRelativePath(input) {
|
|
3816
|
-
return !
|
|
3821
|
+
return !path9.isAbsolute(input);
|
|
3817
3822
|
}
|
|
3818
3823
|
function resolveCanonicalComputerUseAction(toolName) {
|
|
3819
3824
|
const direct = resolveCanonicalComputerUseToolName(toolName);
|
|
@@ -3878,7 +3883,7 @@ function assessRisk(toolName, args, mcp, config) {
|
|
|
3878
3883
|
return {
|
|
3879
3884
|
level: "high",
|
|
3880
3885
|
reason: `${opLabel} with relative path traversal`,
|
|
3881
|
-
signature: `fs_write_rel:${normalizePath(
|
|
3886
|
+
signature: `fs_write_rel:${normalizePath(path9.resolve(targetPath))}`,
|
|
3882
3887
|
details: targetPath
|
|
3883
3888
|
};
|
|
3884
3889
|
}
|
|
@@ -3909,6 +3914,14 @@ function assessRisk(toolName, args, mcp, config) {
|
|
|
3909
3914
|
if (toolName === "shell_execute") {
|
|
3910
3915
|
const command = typeof args?.command === "string" ? args.command : "";
|
|
3911
3916
|
if (command && (isDestructiveShellCommand(command) || isPermissionChangeCommand(command))) {
|
|
3917
|
+
if (isPermissionChangeCommand(command)) {
|
|
3918
|
+
return {
|
|
3919
|
+
level: "high",
|
|
3920
|
+
reason: "Permission change shell command",
|
|
3921
|
+
signature: `shell_permission:${command.toLowerCase().slice(0, 80)}`,
|
|
3922
|
+
details: command
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3912
3925
|
const targets = extractPathsFromCommand(command);
|
|
3913
3926
|
const hasTraversal = hasRelativePathTraversal(command);
|
|
3914
3927
|
if (targets.length === 0 || hasTraversal) {
|
|
@@ -4147,7 +4160,7 @@ var StrategyUpdateGate = class {
|
|
|
4147
4160
|
};
|
|
4148
4161
|
|
|
4149
4162
|
// src/gate/review-manager.ts
|
|
4150
|
-
import * as
|
|
4163
|
+
import * as path10 from "path";
|
|
4151
4164
|
import * as os7 from "os";
|
|
4152
4165
|
var ReviewManager = class {
|
|
4153
4166
|
memory;
|
|
@@ -4156,7 +4169,7 @@ var ReviewManager = class {
|
|
|
4156
4169
|
this.memory = memoryManager;
|
|
4157
4170
|
return;
|
|
4158
4171
|
}
|
|
4159
|
-
const dbPath =
|
|
4172
|
+
const dbPath = path10.join(os7.homedir(), ".lydia", "memory.db");
|
|
4160
4173
|
this.memory = new MemoryManager(dbPath);
|
|
4161
4174
|
}
|
|
4162
4175
|
async init() {
|
|
@@ -4335,7 +4348,7 @@ ${this.originalPlan}
|
|
|
4335
4348
|
};
|
|
4336
4349
|
|
|
4337
4350
|
// src/replay/mcp.ts
|
|
4338
|
-
import * as
|
|
4351
|
+
import * as path11 from "path";
|
|
4339
4352
|
var ReplayMcpClientManager = class extends McpClientManager {
|
|
4340
4353
|
traces;
|
|
4341
4354
|
callIndex = 0;
|
|
@@ -4490,12 +4503,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4490
4503
|
const loweredPattern = rawPattern.toLowerCase();
|
|
4491
4504
|
const names = /* @__PURE__ */ new Set();
|
|
4492
4505
|
for (const storedPath of this.virtualFiles.keys()) {
|
|
4493
|
-
const rel =
|
|
4506
|
+
const rel = path11.relative(normalized, storedPath);
|
|
4494
4507
|
if (rel.startsWith("..")) continue;
|
|
4495
4508
|
const parts = rel.split("/").filter(Boolean);
|
|
4496
4509
|
for (const part of parts) {
|
|
4497
4510
|
if (part.toLowerCase().includes(loweredPattern)) {
|
|
4498
|
-
names.add(`[FILE] ${
|
|
4511
|
+
names.add(`[FILE] ${path11.posix.join(path11.posix.relative(this.virtualRoot, normalized), rel)}`);
|
|
4499
4512
|
break;
|
|
4500
4513
|
}
|
|
4501
4514
|
}
|
|
@@ -4523,12 +4536,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4523
4536
|
createdAt: 0,
|
|
4524
4537
|
totalBytes: sourceFile ? sourceFile.length : sourceEntries.reduce((acc, [, text]) => acc + text.length, 0),
|
|
4525
4538
|
files: sourceFile ? [{
|
|
4526
|
-
path:
|
|
4539
|
+
path: path11.posix.basename(source),
|
|
4527
4540
|
size: sourceFile.length,
|
|
4528
4541
|
encoding: "base64",
|
|
4529
4542
|
data: Buffer.from(sourceFile, "utf-8").toString("base64")
|
|
4530
4543
|
}] : sourceEntries.map(([filePath, text]) => ({
|
|
4531
|
-
path:
|
|
4544
|
+
path: path11.posix.relative(source, filePath),
|
|
4532
4545
|
size: text.length,
|
|
4533
4546
|
encoding: "base64",
|
|
4534
4547
|
data: Buffer.from(text, "utf-8").toString("base64")
|
|
@@ -4583,7 +4596,7 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4583
4596
|
for (const item of parsed.files) {
|
|
4584
4597
|
const rel = typeof item?.path === "string" ? item.path.replace(/\\/g, "/") : "";
|
|
4585
4598
|
if (!rel || rel.includes("..") || rel.startsWith("/")) continue;
|
|
4586
|
-
const target = this.normalizeFsPath(
|
|
4599
|
+
const target = this.normalizeFsPath(path11.posix.join(outputDir, rel));
|
|
4587
4600
|
const base64 = typeof item?.data === "string" ? item.data : "";
|
|
4588
4601
|
const text = base64 ? Buffer.from(base64, "base64").toString("utf-8") : "";
|
|
4589
4602
|
this.virtualFiles.set(target, text);
|
|
@@ -4876,12 +4889,12 @@ var ReplayMcpClientManager = class extends McpClientManager {
|
|
|
4876
4889
|
if (driveMatch) {
|
|
4877
4890
|
const drive = driveMatch[1].toLowerCase();
|
|
4878
4891
|
const rest = driveMatch[2] || "/";
|
|
4879
|
-
return
|
|
4892
|
+
return path11.posix.normalize(`/${drive}${rest}`);
|
|
4880
4893
|
}
|
|
4881
4894
|
if (source.startsWith("/")) {
|
|
4882
|
-
return
|
|
4895
|
+
return path11.posix.normalize(source);
|
|
4883
4896
|
}
|
|
4884
|
-
return
|
|
4897
|
+
return path11.posix.normalize(path11.posix.join(this.virtualRoot, source));
|
|
4885
4898
|
}
|
|
4886
4899
|
listDirectoryEntries(directory) {
|
|
4887
4900
|
const normalizedDir = this.normalizeFsPath(directory);
|
|
@@ -5072,7 +5085,7 @@ var StrategyEvaluator = class {
|
|
|
5072
5085
|
};
|
|
5073
5086
|
|
|
5074
5087
|
// src/replay/manager.ts
|
|
5075
|
-
import * as
|
|
5088
|
+
import * as path12 from "path";
|
|
5076
5089
|
import * as os8 from "os";
|
|
5077
5090
|
var ReplayManager = class {
|
|
5078
5091
|
memoryManager;
|
|
@@ -5081,7 +5094,7 @@ var ReplayManager = class {
|
|
|
5081
5094
|
if (memoryManager) {
|
|
5082
5095
|
this.memoryManager = memoryManager;
|
|
5083
5096
|
} else {
|
|
5084
|
-
const dbPath =
|
|
5097
|
+
const dbPath = path12.join(os8.homedir(), ".lydia", "memory.db");
|
|
5085
5098
|
this.memoryManager = new MemoryManager(dbPath);
|
|
5086
5099
|
}
|
|
5087
5100
|
this.evaluator = new StrategyEvaluator();
|
|
@@ -5101,7 +5114,7 @@ var ReplayManager = class {
|
|
|
5101
5114
|
const agent = new Agent(mockLLM);
|
|
5102
5115
|
agent.mcpClientManager = mockMcp;
|
|
5103
5116
|
agent.isInitialized = true;
|
|
5104
|
-
const tempDb =
|
|
5117
|
+
const tempDb = path12.join(os8.tmpdir(), `lydia-replay-${Date.now()}-${episodeId}.db`);
|
|
5105
5118
|
agent.memoryManager = new MemoryManager(tempDb);
|
|
5106
5119
|
try {
|
|
5107
5120
|
const config = await agent.configLoader.load();
|
|
@@ -5421,7 +5434,7 @@ var FeedbackCollector = class {
|
|
|
5421
5434
|
};
|
|
5422
5435
|
|
|
5423
5436
|
// src/execution/agent.ts
|
|
5424
|
-
import * as
|
|
5437
|
+
import * as path13 from "path";
|
|
5425
5438
|
import * as os9 from "os";
|
|
5426
5439
|
var Agent = class extends EventEmitter5 {
|
|
5427
5440
|
llm;
|
|
@@ -5518,7 +5531,7 @@ var Agent = class extends EventEmitter5 {
|
|
|
5518
5531
|
await this.reviewManager.init();
|
|
5519
5532
|
const config = await this.configLoader.load();
|
|
5520
5533
|
this.config = config;
|
|
5521
|
-
const dbPath =
|
|
5534
|
+
const dbPath = path13.join(os9.homedir(), ".lydia", "memory.db");
|
|
5522
5535
|
this.memoryManager = new MemoryManager(dbPath, {
|
|
5523
5536
|
checkpointTtlMs: Math.max(1, config.memory?.checkpointTtlHours ?? 24) * 60 * 60 * 1e3,
|
|
5524
5537
|
observationFrameTtlMs: Math.max(1, config.memory?.observationFrameTtlHours ?? 24 * 7) * 60 * 60 * 1e3
|