@strvmarv/total-recall 0.6.8-beta.5 → 0.6.8-beta.7
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/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -0
- package/dist/eval/ci-smoke.js +3 -2
- package/dist/index.js +221 -139
- package/package.json +3 -2
- package/scripts/mcp-smoke-test.mjs +388 -0
- package/scripts/postinstall.js +25 -0
package/dist/index.js
CHANGED
|
@@ -6803,7 +6803,8 @@ import { randomUUID as randomUUID8 } from "crypto";
|
|
|
6803
6803
|
|
|
6804
6804
|
// src/config.ts
|
|
6805
6805
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
6806
|
-
import { join } from "path";
|
|
6806
|
+
import { join, isAbsolute } from "path";
|
|
6807
|
+
import { homedir } from "os";
|
|
6807
6808
|
import { createHash, randomUUID } from "crypto";
|
|
6808
6809
|
|
|
6809
6810
|
// node_modules/smol-toml/dist/error.js
|
|
@@ -7640,7 +7641,40 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
|
7640
7641
|
// src/config.ts
|
|
7641
7642
|
var DEFAULTS_PATH = new URL("./defaults.toml", import.meta.url);
|
|
7642
7643
|
function getDataDir() {
|
|
7643
|
-
return process.env.TOTAL_RECALL_HOME ?? join(
|
|
7644
|
+
return process.env.TOTAL_RECALL_HOME ?? join(homedir(), ".total-recall");
|
|
7645
|
+
}
|
|
7646
|
+
var SqliteDbPathError = class extends Error {
|
|
7647
|
+
constructor(message) {
|
|
7648
|
+
super(message);
|
|
7649
|
+
this.name = "SqliteDbPathError";
|
|
7650
|
+
}
|
|
7651
|
+
};
|
|
7652
|
+
function getDbPath() {
|
|
7653
|
+
const raw = process.env.TOTAL_RECALL_DB_PATH;
|
|
7654
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
7655
|
+
return join(getDataDir(), "total-recall.db");
|
|
7656
|
+
}
|
|
7657
|
+
const trimmed = raw.trim();
|
|
7658
|
+
if (trimmed.endsWith("/") || trimmed.endsWith("\\")) {
|
|
7659
|
+
throw new SqliteDbPathError(
|
|
7660
|
+
`TOTAL_RECALL_DB_PATH must be a file path, not a directory. Got: "${trimmed}"`
|
|
7661
|
+
);
|
|
7662
|
+
}
|
|
7663
|
+
if (trimmed === "~") {
|
|
7664
|
+
throw new SqliteDbPathError(
|
|
7665
|
+
`TOTAL_RECALL_DB_PATH must be a file path, not a directory. Got: "~"`
|
|
7666
|
+
);
|
|
7667
|
+
}
|
|
7668
|
+
let expanded = trimmed;
|
|
7669
|
+
if (trimmed.startsWith("~/")) {
|
|
7670
|
+
expanded = join(homedir(), trimmed.slice(2));
|
|
7671
|
+
}
|
|
7672
|
+
if (!isAbsolute(expanded)) {
|
|
7673
|
+
throw new SqliteDbPathError(
|
|
7674
|
+
`TOTAL_RECALL_DB_PATH must be absolute or start with ~/. Got: "${trimmed}"`
|
|
7675
|
+
);
|
|
7676
|
+
}
|
|
7677
|
+
return expanded;
|
|
7644
7678
|
}
|
|
7645
7679
|
function loadConfig() {
|
|
7646
7680
|
const defaultsText = readFileSync(DEFAULTS_PATH, "utf-8");
|
|
@@ -7734,9 +7768,9 @@ function deepMerge(target, source) {
|
|
|
7734
7768
|
}
|
|
7735
7769
|
|
|
7736
7770
|
// src/db/connection.ts
|
|
7737
|
-
import { Database } from "bun:sqlite";
|
|
7738
|
-
import { mkdirSync as mkdirSync2
|
|
7739
|
-
import {
|
|
7771
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
7772
|
+
import { mkdirSync as mkdirSync2 } from "fs";
|
|
7773
|
+
import { dirname } from "path";
|
|
7740
7774
|
|
|
7741
7775
|
// node_modules/sqlite-vec/index.mjs
|
|
7742
7776
|
import { fileURLToPath } from "url";
|
|
@@ -7988,16 +8022,55 @@ function initSchema(db) {
|
|
|
7988
8022
|
migrate();
|
|
7989
8023
|
}
|
|
7990
8024
|
|
|
8025
|
+
// src/db/sqlite-bootstrap.ts
|
|
8026
|
+
import { Database } from "bun:sqlite";
|
|
8027
|
+
import { existsSync as existsSync2 } from "fs";
|
|
8028
|
+
var DARWIN_SQLITE_CANDIDATES = [
|
|
8029
|
+
"/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib",
|
|
8030
|
+
// Apple Silicon brew
|
|
8031
|
+
"/usr/local/opt/sqlite/lib/libsqlite3.dylib"
|
|
8032
|
+
// Intel brew
|
|
8033
|
+
];
|
|
8034
|
+
var SqliteExtensionError = class extends Error {
|
|
8035
|
+
constructor(message) {
|
|
8036
|
+
super(message);
|
|
8037
|
+
this.name = "SqliteExtensionError";
|
|
8038
|
+
}
|
|
8039
|
+
};
|
|
8040
|
+
var _bootstrapped = false;
|
|
8041
|
+
function bootstrapSqlite() {
|
|
8042
|
+
if (_bootstrapped) return;
|
|
8043
|
+
_bootstrapped = true;
|
|
8044
|
+
if (process.platform !== "darwin") return;
|
|
8045
|
+
for (const candidate of DARWIN_SQLITE_CANDIDATES) {
|
|
8046
|
+
if (existsSync2(candidate)) {
|
|
8047
|
+
Database.setCustomSQLite(candidate);
|
|
8048
|
+
return;
|
|
8049
|
+
}
|
|
8050
|
+
}
|
|
8051
|
+
throw new SqliteExtensionError(
|
|
8052
|
+
[
|
|
8053
|
+
"total-recall: no extension-capable libsqlite3 found on this Mac.",
|
|
8054
|
+
"",
|
|
8055
|
+
"macOS ships /usr/lib/libsqlite3.dylib without SQLITE_ENABLE_LOAD_EXTENSION,",
|
|
8056
|
+
"so sqlite-vec cannot be loaded. Install Homebrew sqlite to fix:",
|
|
8057
|
+
"",
|
|
8058
|
+
" brew install sqlite",
|
|
8059
|
+
"",
|
|
8060
|
+
"total-recall will automatically pick it up from:",
|
|
8061
|
+
...DARWIN_SQLITE_CANDIDATES.map((p) => ` - ${p}`)
|
|
8062
|
+
].join("\n")
|
|
8063
|
+
);
|
|
8064
|
+
}
|
|
8065
|
+
|
|
7991
8066
|
// src/db/connection.ts
|
|
7992
8067
|
var _db = null;
|
|
7993
8068
|
function getDb() {
|
|
7994
8069
|
if (_db) return _db;
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
const dbPath = join2(dataDir, "total-recall.db");
|
|
8000
|
-
_db = new Database(dbPath);
|
|
8070
|
+
bootstrapSqlite();
|
|
8071
|
+
const dbPath = getDbPath();
|
|
8072
|
+
mkdirSync2(dirname(dbPath), { recursive: true });
|
|
8073
|
+
_db = new Database2(dbPath);
|
|
8001
8074
|
load(_db);
|
|
8002
8075
|
initSchema(_db);
|
|
8003
8076
|
return _db;
|
|
@@ -8011,30 +8084,30 @@ function closeDb() {
|
|
|
8011
8084
|
|
|
8012
8085
|
// src/embedding/embedder.ts
|
|
8013
8086
|
import { readFile as readFile2 } from "fs/promises";
|
|
8014
|
-
import { join as
|
|
8087
|
+
import { join as join5 } from "path";
|
|
8015
8088
|
import * as ort from "onnxruntime-node";
|
|
8016
8089
|
|
|
8017
8090
|
// src/embedding/bootstrap.ts
|
|
8018
8091
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
8019
|
-
import { join as
|
|
8092
|
+
import { join as join4 } from "path";
|
|
8020
8093
|
|
|
8021
8094
|
// src/embedding/registry.ts
|
|
8022
8095
|
import { readFileSync as readFileSync2 } from "fs";
|
|
8023
8096
|
|
|
8024
8097
|
// src/pkg-root.ts
|
|
8025
8098
|
import { existsSync as existsSync3 } from "fs";
|
|
8026
|
-
import { dirname, join as
|
|
8099
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
8027
8100
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8028
8101
|
var cached = null;
|
|
8029
8102
|
function getPackageRoot() {
|
|
8030
8103
|
if (cached) return cached;
|
|
8031
|
-
let dir =
|
|
8104
|
+
let dir = dirname2(fileURLToPath2(import.meta.url));
|
|
8032
8105
|
for (let i = 0; i < 10; i++) {
|
|
8033
|
-
if (existsSync3(
|
|
8106
|
+
if (existsSync3(join2(dir, "package.json"))) {
|
|
8034
8107
|
cached = dir;
|
|
8035
8108
|
return dir;
|
|
8036
8109
|
}
|
|
8037
|
-
const parent =
|
|
8110
|
+
const parent = dirname2(dir);
|
|
8038
8111
|
if (parent === dir) break;
|
|
8039
8112
|
dir = parent;
|
|
8040
8113
|
}
|
|
@@ -8043,7 +8116,7 @@ function getPackageRoot() {
|
|
|
8043
8116
|
);
|
|
8044
8117
|
}
|
|
8045
8118
|
function pkgPath(...segments) {
|
|
8046
|
-
return
|
|
8119
|
+
return join2(getPackageRoot(), ...segments);
|
|
8047
8120
|
}
|
|
8048
8121
|
|
|
8049
8122
|
// src/embedding/registry.ts
|
|
@@ -8096,14 +8169,14 @@ import { Readable } from "stream";
|
|
|
8096
8169
|
import { pipeline } from "stream/promises";
|
|
8097
8170
|
import { createWriteStream } from "fs";
|
|
8098
8171
|
import { createHash as createHash2 } from "crypto";
|
|
8099
|
-
import { join as
|
|
8172
|
+
import { join as join3, dirname as dirname3 } from "path";
|
|
8100
8173
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8101
8174
|
function getBundledModelPath(modelName) {
|
|
8102
|
-
const distDir =
|
|
8103
|
-
return
|
|
8175
|
+
const distDir = dirname3(fileURLToPath3(import.meta.url));
|
|
8176
|
+
return join3(distDir, "..", "models", modelName);
|
|
8104
8177
|
}
|
|
8105
8178
|
function getUserModelPath(modelName) {
|
|
8106
|
-
return
|
|
8179
|
+
return join3(getDataDir(), "models", modelName);
|
|
8107
8180
|
}
|
|
8108
8181
|
function getModelPath(modelName) {
|
|
8109
8182
|
const bundled = getBundledModelPath(modelName);
|
|
@@ -8206,10 +8279,10 @@ async function downloadModel(modelName, options = {}) {
|
|
|
8206
8279
|
const fileCount = fileEntries.length;
|
|
8207
8280
|
for (let i = 0; i < fileEntries.length; i++) {
|
|
8208
8281
|
const { file: file2, url: url2 } = fileEntries[i];
|
|
8209
|
-
const finalPath =
|
|
8282
|
+
const finalPath = join3(target, file2);
|
|
8210
8283
|
await downloadFile(url2, finalPath, file2, i, fileCount, options, maxRetries);
|
|
8211
8284
|
}
|
|
8212
|
-
const onnxPath =
|
|
8285
|
+
const onnxPath = join3(target, "model.onnx");
|
|
8213
8286
|
const actualHash = await sha256File(onnxPath);
|
|
8214
8287
|
if (actualHash !== spec.sha256) {
|
|
8215
8288
|
try {
|
|
@@ -8220,7 +8293,7 @@ async function downloadModel(modelName, options = {}) {
|
|
|
8220
8293
|
`sha256 mismatch for model.onnx: expected ${spec.sha256}, actual ${actualHash}`
|
|
8221
8294
|
);
|
|
8222
8295
|
}
|
|
8223
|
-
const sidecarPath =
|
|
8296
|
+
const sidecarPath = join3(target, ".verified");
|
|
8224
8297
|
await writeFileAtomic(sidecarPath, spec.sha256);
|
|
8225
8298
|
return target;
|
|
8226
8299
|
}
|
|
@@ -8255,11 +8328,11 @@ async function writeFileAtomic(dest, data) {
|
|
|
8255
8328
|
function isModelStructurallyValid(modelPath, spec) {
|
|
8256
8329
|
if (!existsSync4(modelPath)) return false;
|
|
8257
8330
|
for (const file2 of Object.keys(spec.files)) {
|
|
8258
|
-
const p =
|
|
8331
|
+
const p = join3(modelPath, file2);
|
|
8259
8332
|
if (!existsSync4(p)) return false;
|
|
8260
8333
|
}
|
|
8261
8334
|
try {
|
|
8262
|
-
const onnx =
|
|
8335
|
+
const onnx = join3(modelPath, "model.onnx");
|
|
8263
8336
|
const size = statSync(onnx).size;
|
|
8264
8337
|
return size === spec.sizeBytes;
|
|
8265
8338
|
} catch {
|
|
@@ -8267,7 +8340,7 @@ function isModelStructurallyValid(modelPath, spec) {
|
|
|
8267
8340
|
}
|
|
8268
8341
|
}
|
|
8269
8342
|
async function isModelChecksumValid(modelPath, spec) {
|
|
8270
|
-
const sidecarPath =
|
|
8343
|
+
const sidecarPath = join3(modelPath, ".verified");
|
|
8271
8344
|
if (existsSync4(sidecarPath)) {
|
|
8272
8345
|
try {
|
|
8273
8346
|
const cached4 = (await readFile(sidecarPath, "utf8")).trim();
|
|
@@ -8275,7 +8348,7 @@ async function isModelChecksumValid(modelPath, spec) {
|
|
|
8275
8348
|
} catch {
|
|
8276
8349
|
}
|
|
8277
8350
|
}
|
|
8278
|
-
const onnxPath =
|
|
8351
|
+
const onnxPath = join3(modelPath, "model.onnx");
|
|
8279
8352
|
if (!existsSync4(onnxPath)) return false;
|
|
8280
8353
|
let computed;
|
|
8281
8354
|
try {
|
|
@@ -8316,7 +8389,7 @@ import * as lockfile from "proper-lockfile";
|
|
|
8316
8389
|
var defaultAcquireLock = async (targetDir) => {
|
|
8317
8390
|
mkdirSync4(targetDir, { recursive: true });
|
|
8318
8391
|
const release = await lockfile.lock(targetDir, {
|
|
8319
|
-
lockfilePath:
|
|
8392
|
+
lockfilePath: join4(targetDir, ".bootstrap.lock"),
|
|
8320
8393
|
retries: { retries: 60, minTimeout: 1e3, maxTimeout: 1e3 }
|
|
8321
8394
|
});
|
|
8322
8395
|
return { release: async () => {
|
|
@@ -8579,9 +8652,9 @@ var Embedder = class {
|
|
|
8579
8652
|
}
|
|
8580
8653
|
}
|
|
8581
8654
|
const modelPath = await this.bootstrap.ensureReady();
|
|
8582
|
-
const onnxPath =
|
|
8655
|
+
const onnxPath = join5(modelPath, "model.onnx");
|
|
8583
8656
|
this.session = await ort.InferenceSession.create(onnxPath);
|
|
8584
|
-
const tokenizerPath =
|
|
8657
|
+
const tokenizerPath = join5(modelPath, "tokenizer.json");
|
|
8585
8658
|
const tokenizerText = await readFile2(tokenizerPath, "utf-8");
|
|
8586
8659
|
const tokenizerJson = JSON.parse(tokenizerText);
|
|
8587
8660
|
this.tokenizer = new WordPieceTokenizer(tokenizerJson.model.vocab);
|
|
@@ -23515,7 +23588,6 @@ async function handleMemoryTool(name, args, ctx) {
|
|
|
23515
23588
|
|
|
23516
23589
|
// src/tools/system-tools.ts
|
|
23517
23590
|
import { statSync as statSync2 } from "fs";
|
|
23518
|
-
import { join as join7 } from "path";
|
|
23519
23591
|
|
|
23520
23592
|
// src/ingestion/hierarchical-index.ts
|
|
23521
23593
|
function rowToEntry2(row) {
|
|
@@ -23644,8 +23716,7 @@ function handleSystemTool(name, args, ctx) {
|
|
|
23644
23716
|
const key = `${tier}_${type === "memory" ? "memories" : "knowledge"}`;
|
|
23645
23717
|
tierSizes[key] = countEntries(ctx.db, tier, type);
|
|
23646
23718
|
}
|
|
23647
|
-
const
|
|
23648
|
-
const dbPath = join7(dataDir, "total-recall.db");
|
|
23719
|
+
const dbPath = getDbPath();
|
|
23649
23720
|
let dbSizeBytes = null;
|
|
23650
23721
|
try {
|
|
23651
23722
|
dbSizeBytes = statSync2(dbPath).size;
|
|
@@ -23742,7 +23813,7 @@ import { statSync as statSync4 } from "fs";
|
|
|
23742
23813
|
|
|
23743
23814
|
// src/ingestion/ingest.ts
|
|
23744
23815
|
import { readFileSync as readFileSync3, readdirSync, statSync as statSync3 } from "fs";
|
|
23745
|
-
import { join as
|
|
23816
|
+
import { join as join6, dirname as dirname4, basename, extname } from "path";
|
|
23746
23817
|
|
|
23747
23818
|
// src/ingestion/markdown-parser.ts
|
|
23748
23819
|
function estimateTokens(text) {
|
|
@@ -24215,7 +24286,7 @@ async function ingestFile(db, embed, filePath, collectionId) {
|
|
|
24215
24286
|
const chunks = chunkFile(content, filePath, { maxTokens: 512, overlapTokens: 50 });
|
|
24216
24287
|
let resolvedCollectionId = collectionId;
|
|
24217
24288
|
if (!resolvedCollectionId) {
|
|
24218
|
-
const dirPath =
|
|
24289
|
+
const dirPath = dirname4(filePath);
|
|
24219
24290
|
const dirName = basename(dirPath);
|
|
24220
24291
|
resolvedCollectionId = await createCollection(db, embed, {
|
|
24221
24292
|
name: dirName,
|
|
@@ -24262,7 +24333,7 @@ function walkDirectory(dirPath) {
|
|
|
24262
24333
|
}
|
|
24263
24334
|
for (const entry of entries) {
|
|
24264
24335
|
if (entry.startsWith(".") || entry === "node_modules") continue;
|
|
24265
|
-
const fullPath =
|
|
24336
|
+
const fullPath = join6(dirPath, entry);
|
|
24266
24337
|
let stat;
|
|
24267
24338
|
try {
|
|
24268
24339
|
stat = statSync3(fullPath);
|
|
@@ -24581,7 +24652,7 @@ function registerKbTools() {
|
|
|
24581
24652
|
}
|
|
24582
24653
|
|
|
24583
24654
|
// src/tools/eval-tools.ts
|
|
24584
|
-
import { resolve as resolve3, dirname as
|
|
24655
|
+
import { resolve as resolve3, dirname as dirname6, basename as basename3 } from "path";
|
|
24585
24656
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
24586
24657
|
|
|
24587
24658
|
// src/eval/benchmark-runner.ts
|
|
@@ -24662,9 +24733,9 @@ async function runBenchmark(db, embed, opts) {
|
|
|
24662
24733
|
// src/eval/benchmark-candidates.ts
|
|
24663
24734
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
24664
24735
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
24665
|
-
import { resolve as resolve2, dirname as
|
|
24736
|
+
import { resolve as resolve2, dirname as dirname5, basename as basename2 } from "path";
|
|
24666
24737
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
24667
|
-
var __dirname =
|
|
24738
|
+
var __dirname = dirname5(fileURLToPath4(import.meta.url));
|
|
24668
24739
|
var PACKAGE_ROOT = basename2(__dirname) === "dist" ? resolve2(__dirname, "..") : resolve2(__dirname, "..", "..");
|
|
24669
24740
|
function writeCandidates(db, misses, contexts) {
|
|
24670
24741
|
const contextMap = new Map(contexts.map((c) => [c.query, c]));
|
|
@@ -24911,7 +24982,7 @@ function computeCompactionHealth(rows) {
|
|
|
24911
24982
|
}
|
|
24912
24983
|
|
|
24913
24984
|
// src/tools/eval-tools.ts
|
|
24914
|
-
var __dirname2 =
|
|
24985
|
+
var __dirname2 = dirname6(fileURLToPath5(import.meta.url));
|
|
24915
24986
|
var PACKAGE_ROOT2 = basename3(__dirname2) === "dist" ? resolve3(__dirname2, "..") : resolve3(__dirname2, "..", "..");
|
|
24916
24987
|
var EVAL_TOOLS = [
|
|
24917
24988
|
{
|
|
@@ -25099,8 +25170,8 @@ function registerEvalTools() {
|
|
|
25099
25170
|
|
|
25100
25171
|
// src/importers/claude-code.ts
|
|
25101
25172
|
import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
|
|
25102
|
-
import { join as
|
|
25103
|
-
import { homedir } from "os";
|
|
25173
|
+
import { join as join7 } from "path";
|
|
25174
|
+
import { homedir as homedir2 } from "os";
|
|
25104
25175
|
|
|
25105
25176
|
// src/importers/import-utils.ts
|
|
25106
25177
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -25142,29 +25213,29 @@ var ClaudeCodeImporter = class {
|
|
|
25142
25213
|
name = "claude-code";
|
|
25143
25214
|
basePath;
|
|
25144
25215
|
constructor(basePath) {
|
|
25145
|
-
this.basePath = basePath ??
|
|
25216
|
+
this.basePath = basePath ?? join7(homedir2(), ".claude");
|
|
25146
25217
|
}
|
|
25147
25218
|
detect() {
|
|
25148
|
-
return existsSync5(this.basePath) && existsSync5(
|
|
25219
|
+
return existsSync5(this.basePath) && existsSync5(join7(this.basePath, "projects"));
|
|
25149
25220
|
}
|
|
25150
25221
|
scan() {
|
|
25151
25222
|
let memoryFiles = 0;
|
|
25152
25223
|
let knowledgeFiles = 0;
|
|
25153
25224
|
let sessionFiles = 0;
|
|
25154
|
-
const projectsDir =
|
|
25225
|
+
const projectsDir = join7(this.basePath, "projects");
|
|
25155
25226
|
if (!existsSync5(projectsDir)) {
|
|
25156
25227
|
return { memoryFiles, knowledgeFiles, sessionFiles };
|
|
25157
25228
|
}
|
|
25158
25229
|
for (const projectEntry of readdirSync2(projectsDir, { withFileTypes: true })) {
|
|
25159
25230
|
if (!projectEntry.isDirectory()) continue;
|
|
25160
|
-
const projectDir =
|
|
25161
|
-
const memoryDir =
|
|
25231
|
+
const projectDir = join7(projectsDir, projectEntry.name);
|
|
25232
|
+
const memoryDir = join7(projectDir, "memory");
|
|
25162
25233
|
if (existsSync5(memoryDir)) {
|
|
25163
25234
|
for (const f of readdirSync2(memoryDir)) {
|
|
25164
25235
|
if (f.endsWith(".md") && f !== "MEMORY.md") memoryFiles++;
|
|
25165
25236
|
}
|
|
25166
25237
|
}
|
|
25167
|
-
if (existsSync5(
|
|
25238
|
+
if (existsSync5(join7(projectDir, "CLAUDE.md"))) knowledgeFiles++;
|
|
25168
25239
|
for (const f of readdirSync2(projectDir)) {
|
|
25169
25240
|
if (f.endsWith(".jsonl")) sessionFiles++;
|
|
25170
25241
|
}
|
|
@@ -25173,16 +25244,16 @@ var ClaudeCodeImporter = class {
|
|
|
25173
25244
|
}
|
|
25174
25245
|
async importMemories(db, embed, project) {
|
|
25175
25246
|
const result = { imported: 0, skipped: 0, errors: [] };
|
|
25176
|
-
const projectsDir =
|
|
25247
|
+
const projectsDir = join7(this.basePath, "projects");
|
|
25177
25248
|
if (!existsSync5(projectsDir)) return result;
|
|
25178
25249
|
for (const projectEntry of readdirSync2(projectsDir, { withFileTypes: true })) {
|
|
25179
25250
|
if (!projectEntry.isDirectory()) continue;
|
|
25180
|
-
const projectDir =
|
|
25181
|
-
const memoryDir =
|
|
25251
|
+
const projectDir = join7(projectsDir, projectEntry.name);
|
|
25252
|
+
const memoryDir = join7(projectDir, "memory");
|
|
25182
25253
|
if (!existsSync5(memoryDir)) continue;
|
|
25183
25254
|
for (const filename of readdirSync2(memoryDir)) {
|
|
25184
25255
|
if (!filename.endsWith(".md") || filename === "MEMORY.md") continue;
|
|
25185
|
-
const filePath =
|
|
25256
|
+
const filePath = join7(memoryDir, filename);
|
|
25186
25257
|
try {
|
|
25187
25258
|
const raw = readFileSync6(filePath, "utf8");
|
|
25188
25259
|
const hash2 = contentHash(raw);
|
|
@@ -25217,7 +25288,7 @@ var ClaudeCodeImporter = class {
|
|
|
25217
25288
|
}
|
|
25218
25289
|
async importKnowledge(db, embed) {
|
|
25219
25290
|
const result = { imported: 0, skipped: 0, errors: [] };
|
|
25220
|
-
const claudeMdPath =
|
|
25291
|
+
const claudeMdPath = join7(this.basePath, "CLAUDE.md");
|
|
25221
25292
|
if (!existsSync5(claudeMdPath)) return result;
|
|
25222
25293
|
try {
|
|
25223
25294
|
const raw = readFileSync6(claudeMdPath, "utf8");
|
|
@@ -25247,28 +25318,28 @@ var ClaudeCodeImporter = class {
|
|
|
25247
25318
|
|
|
25248
25319
|
// src/importers/copilot-cli.ts
|
|
25249
25320
|
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync7 } from "fs";
|
|
25250
|
-
import { join as
|
|
25251
|
-
import { homedir as
|
|
25321
|
+
import { join as join8 } from "path";
|
|
25322
|
+
import { homedir as homedir3 } from "os";
|
|
25252
25323
|
var CopilotCliImporter = class {
|
|
25253
25324
|
name = "copilot-cli";
|
|
25254
25325
|
basePath;
|
|
25255
25326
|
constructor(basePath) {
|
|
25256
|
-
this.basePath = basePath ??
|
|
25327
|
+
this.basePath = basePath ?? join8(homedir3(), ".copilot");
|
|
25257
25328
|
}
|
|
25258
25329
|
detect() {
|
|
25259
|
-
return existsSync6(this.basePath) && existsSync6(
|
|
25330
|
+
return existsSync6(this.basePath) && existsSync6(join8(this.basePath, "session-state"));
|
|
25260
25331
|
}
|
|
25261
25332
|
scan() {
|
|
25262
25333
|
let knowledgeFiles = 0;
|
|
25263
25334
|
let sessionFiles = 0;
|
|
25264
|
-
const sessionStateDir =
|
|
25335
|
+
const sessionStateDir = join8(this.basePath, "session-state");
|
|
25265
25336
|
if (!existsSync6(sessionStateDir)) {
|
|
25266
25337
|
return { memoryFiles: 0, knowledgeFiles, sessionFiles };
|
|
25267
25338
|
}
|
|
25268
25339
|
for (const entry of readdirSync3(sessionStateDir, { withFileTypes: true })) {
|
|
25269
25340
|
if (!entry.isDirectory()) continue;
|
|
25270
|
-
const sessionDir =
|
|
25271
|
-
if (existsSync6(
|
|
25341
|
+
const sessionDir = join8(sessionStateDir, entry.name);
|
|
25342
|
+
if (existsSync6(join8(sessionDir, "plan.md"))) knowledgeFiles++;
|
|
25272
25343
|
for (const f of readdirSync3(sessionDir)) {
|
|
25273
25344
|
if (f.endsWith(".jsonl")) sessionFiles++;
|
|
25274
25345
|
}
|
|
@@ -25280,11 +25351,11 @@ var CopilotCliImporter = class {
|
|
|
25280
25351
|
}
|
|
25281
25352
|
async importKnowledge(db, embed) {
|
|
25282
25353
|
const result = { imported: 0, skipped: 0, errors: [] };
|
|
25283
|
-
const sessionStateDir =
|
|
25354
|
+
const sessionStateDir = join8(this.basePath, "session-state");
|
|
25284
25355
|
if (!existsSync6(sessionStateDir)) return result;
|
|
25285
25356
|
for (const entry of readdirSync3(sessionStateDir, { withFileTypes: true })) {
|
|
25286
25357
|
if (!entry.isDirectory()) continue;
|
|
25287
|
-
const planPath =
|
|
25358
|
+
const planPath = join8(sessionStateDir, entry.name, "plan.md");
|
|
25288
25359
|
if (!existsSync6(planPath)) continue;
|
|
25289
25360
|
try {
|
|
25290
25361
|
const raw = readFileSync7(planPath, "utf8");
|
|
@@ -25311,10 +25382,10 @@ var CopilotCliImporter = class {
|
|
|
25311
25382
|
|
|
25312
25383
|
// src/importers/cursor.ts
|
|
25313
25384
|
import { existsSync as existsSync7, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "fs";
|
|
25314
|
-
import { join as
|
|
25315
|
-
import { homedir as
|
|
25385
|
+
import { join as join9 } from "path";
|
|
25386
|
+
import { homedir as homedir4 } from "os";
|
|
25316
25387
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
25317
|
-
import { Database as
|
|
25388
|
+
import { Database as Database3 } from "bun:sqlite";
|
|
25318
25389
|
function safeFileURLToPath(url2) {
|
|
25319
25390
|
try {
|
|
25320
25391
|
return fileURLToPath6(url2);
|
|
@@ -25327,28 +25398,28 @@ var CursorImporter = class {
|
|
|
25327
25398
|
configPath;
|
|
25328
25399
|
extensionPath;
|
|
25329
25400
|
constructor(configPath, extensionPath) {
|
|
25330
|
-
this.configPath = configPath ??
|
|
25331
|
-
this.extensionPath = extensionPath ??
|
|
25401
|
+
this.configPath = configPath ?? join9(homedir4(), ".config", "Cursor");
|
|
25402
|
+
this.extensionPath = extensionPath ?? join9(homedir4(), ".cursor");
|
|
25332
25403
|
}
|
|
25333
25404
|
detect() {
|
|
25334
25405
|
return existsSync7(this.configPath) || existsSync7(this.extensionPath);
|
|
25335
25406
|
}
|
|
25336
25407
|
scan() {
|
|
25337
25408
|
let knowledgeFiles = 0;
|
|
25338
|
-
const globalDb =
|
|
25409
|
+
const globalDb = join9(this.configPath, "User", "globalStorage", "state.vscdb");
|
|
25339
25410
|
if (existsSync7(globalDb)) knowledgeFiles++;
|
|
25340
|
-
const workspaceDir =
|
|
25411
|
+
const workspaceDir = join9(this.configPath, "User", "workspaceStorage");
|
|
25341
25412
|
if (existsSync7(workspaceDir)) {
|
|
25342
25413
|
for (const entry of readdirSync4(workspaceDir, { withFileTypes: true })) {
|
|
25343
25414
|
if (!entry.isDirectory()) continue;
|
|
25344
|
-
const wsJson =
|
|
25415
|
+
const wsJson = join9(workspaceDir, entry.name, "workspace.json");
|
|
25345
25416
|
if (!existsSync7(wsJson)) continue;
|
|
25346
25417
|
try {
|
|
25347
25418
|
const ws = JSON.parse(readFileSync8(wsJson, "utf8"));
|
|
25348
25419
|
const projectPath = ws.folder ? safeFileURLToPath(ws.folder) : ws.workspace ? safeFileURLToPath(ws.workspace) : null;
|
|
25349
25420
|
if (!projectPath) continue;
|
|
25350
|
-
if (existsSync7(
|
|
25351
|
-
const rulesDir =
|
|
25421
|
+
if (existsSync7(join9(projectPath, ".cursorrules"))) knowledgeFiles++;
|
|
25422
|
+
const rulesDir = join9(projectPath, ".cursor", "rules");
|
|
25352
25423
|
if (existsSync7(rulesDir)) {
|
|
25353
25424
|
for (const f of readdirSync4(rulesDir)) {
|
|
25354
25425
|
if (f.endsWith(".mdc")) knowledgeFiles++;
|
|
@@ -25370,11 +25441,11 @@ var CursorImporter = class {
|
|
|
25370
25441
|
return result;
|
|
25371
25442
|
}
|
|
25372
25443
|
async importGlobalRules(db, embed, result) {
|
|
25373
|
-
const dbPath =
|
|
25444
|
+
const dbPath = join9(this.configPath, "User", "globalStorage", "state.vscdb");
|
|
25374
25445
|
if (!existsSync7(dbPath)) return;
|
|
25375
25446
|
let cursorDb = null;
|
|
25376
25447
|
try {
|
|
25377
|
-
cursorDb = new
|
|
25448
|
+
cursorDb = new Database3(dbPath, { readonly: true });
|
|
25378
25449
|
const row = cursorDb.query("SELECT value FROM ItemTable WHERE key = 'aicontext.personalContext'").get();
|
|
25379
25450
|
if (!row?.value) return;
|
|
25380
25451
|
const content = row.value;
|
|
@@ -25399,12 +25470,12 @@ var CursorImporter = class {
|
|
|
25399
25470
|
}
|
|
25400
25471
|
}
|
|
25401
25472
|
async importProjectRules(db, embed, result) {
|
|
25402
|
-
const workspaceDir =
|
|
25473
|
+
const workspaceDir = join9(this.configPath, "User", "workspaceStorage");
|
|
25403
25474
|
if (!existsSync7(workspaceDir)) return;
|
|
25404
25475
|
const projectPaths = /* @__PURE__ */ new Set();
|
|
25405
25476
|
for (const entry of readdirSync4(workspaceDir, { withFileTypes: true })) {
|
|
25406
25477
|
if (!entry.isDirectory()) continue;
|
|
25407
|
-
const wsJson =
|
|
25478
|
+
const wsJson = join9(workspaceDir, entry.name, "workspace.json");
|
|
25408
25479
|
if (!existsSync7(wsJson)) continue;
|
|
25409
25480
|
try {
|
|
25410
25481
|
const ws = JSON.parse(readFileSync8(wsJson, "utf8"));
|
|
@@ -25414,15 +25485,15 @@ var CursorImporter = class {
|
|
|
25414
25485
|
}
|
|
25415
25486
|
}
|
|
25416
25487
|
for (const projectPath of projectPaths) {
|
|
25417
|
-
const legacyPath =
|
|
25488
|
+
const legacyPath = join9(projectPath, ".cursorrules");
|
|
25418
25489
|
if (existsSync7(legacyPath)) {
|
|
25419
25490
|
await this.importRuleFile(db, embed, result, legacyPath, ["cursorrules", "legacy"]);
|
|
25420
25491
|
}
|
|
25421
|
-
const rulesDir =
|
|
25492
|
+
const rulesDir = join9(projectPath, ".cursor", "rules");
|
|
25422
25493
|
if (existsSync7(rulesDir)) {
|
|
25423
25494
|
for (const filename of readdirSync4(rulesDir)) {
|
|
25424
25495
|
if (!filename.endsWith(".mdc")) continue;
|
|
25425
|
-
await this.importRuleFile(db, embed, result,
|
|
25496
|
+
await this.importRuleFile(db, embed, result, join9(rulesDir, filename), ["cursor-rule"]);
|
|
25426
25497
|
}
|
|
25427
25498
|
}
|
|
25428
25499
|
}
|
|
@@ -25454,24 +25525,24 @@ var CursorImporter = class {
|
|
|
25454
25525
|
|
|
25455
25526
|
// src/importers/cline.ts
|
|
25456
25527
|
import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "fs";
|
|
25457
|
-
import { join as
|
|
25458
|
-
import { homedir as
|
|
25528
|
+
import { join as join10 } from "path";
|
|
25529
|
+
import { homedir as homedir5 } from "os";
|
|
25459
25530
|
var ClineImporter = class {
|
|
25460
25531
|
name = "cline";
|
|
25461
25532
|
dataPath;
|
|
25462
25533
|
legacyPath;
|
|
25463
25534
|
globalRulesPath;
|
|
25464
25535
|
constructor(dataPath, legacyPath) {
|
|
25465
|
-
this.dataPath = dataPath ??
|
|
25466
|
-
this.legacyPath = legacyPath ??
|
|
25467
|
-
|
|
25536
|
+
this.dataPath = dataPath ?? join10(homedir5(), ".cline", "data");
|
|
25537
|
+
this.legacyPath = legacyPath ?? join10(
|
|
25538
|
+
homedir5(),
|
|
25468
25539
|
".config",
|
|
25469
25540
|
"Code",
|
|
25470
25541
|
"User",
|
|
25471
25542
|
"globalStorage",
|
|
25472
25543
|
"saoudrizwan.claude-dev"
|
|
25473
25544
|
);
|
|
25474
|
-
this.globalRulesPath =
|
|
25545
|
+
this.globalRulesPath = join10(homedir5(), "Documents", "Cline", "Rules");
|
|
25475
25546
|
}
|
|
25476
25547
|
detect() {
|
|
25477
25548
|
return existsSync8(this.dataPath) || existsSync8(this.legacyPath);
|
|
@@ -25479,13 +25550,13 @@ var ClineImporter = class {
|
|
|
25479
25550
|
scan() {
|
|
25480
25551
|
let knowledgeFiles = 0;
|
|
25481
25552
|
let sessionFiles = 0;
|
|
25482
|
-
const ruleDirs = [this.globalRulesPath,
|
|
25553
|
+
const ruleDirs = [this.globalRulesPath, join10(homedir5(), "Cline", "Rules")];
|
|
25483
25554
|
for (const dir of ruleDirs) {
|
|
25484
25555
|
if (existsSync8(dir)) knowledgeFiles += countFiles(dir, [".md", ".txt"]);
|
|
25485
25556
|
}
|
|
25486
25557
|
const stateDir = this.resolveStateDir();
|
|
25487
25558
|
if (stateDir) {
|
|
25488
|
-
const historyPath =
|
|
25559
|
+
const historyPath = join10(stateDir, "taskHistory.json");
|
|
25489
25560
|
if (existsSync8(historyPath)) {
|
|
25490
25561
|
try {
|
|
25491
25562
|
const items = JSON.parse(readFileSync9(historyPath, "utf8"));
|
|
@@ -25494,7 +25565,7 @@ var ClineImporter = class {
|
|
|
25494
25565
|
}
|
|
25495
25566
|
}
|
|
25496
25567
|
}
|
|
25497
|
-
const mcpSettings =
|
|
25568
|
+
const mcpSettings = join10(this.resolveDataDir() ?? "", "settings", "cline_mcp_settings.json");
|
|
25498
25569
|
if (existsSync8(mcpSettings)) knowledgeFiles++;
|
|
25499
25570
|
return { memoryFiles: 0, knowledgeFiles, sessionFiles };
|
|
25500
25571
|
}
|
|
@@ -25515,20 +25586,20 @@ var ClineImporter = class {
|
|
|
25515
25586
|
resolveStateDir() {
|
|
25516
25587
|
const dataDir = this.resolveDataDir();
|
|
25517
25588
|
if (!dataDir) return null;
|
|
25518
|
-
const newState =
|
|
25589
|
+
const newState = join10(dataDir, "state");
|
|
25519
25590
|
if (existsSync8(newState)) return newState;
|
|
25520
25591
|
return dataDir;
|
|
25521
25592
|
}
|
|
25522
25593
|
async importGlobalRules(db, embed, result) {
|
|
25523
25594
|
const ruleDirs = [
|
|
25524
25595
|
this.globalRulesPath,
|
|
25525
|
-
|
|
25596
|
+
join10(homedir5(), "Cline", "Rules")
|
|
25526
25597
|
];
|
|
25527
25598
|
for (const dir of ruleDirs) {
|
|
25528
25599
|
if (!existsSync8(dir)) continue;
|
|
25529
25600
|
for (const filename of readdirSync5(dir)) {
|
|
25530
25601
|
if (!filename.endsWith(".md") && !filename.endsWith(".txt")) continue;
|
|
25531
|
-
const filePath =
|
|
25602
|
+
const filePath = join10(dir, filename);
|
|
25532
25603
|
try {
|
|
25533
25604
|
const raw = readFileSync9(filePath, "utf8");
|
|
25534
25605
|
const hash2 = contentHash(raw);
|
|
@@ -25554,7 +25625,7 @@ var ClineImporter = class {
|
|
|
25554
25625
|
async importTaskSummaries(db, embed, result) {
|
|
25555
25626
|
const stateDir = this.resolveStateDir();
|
|
25556
25627
|
if (!stateDir) return;
|
|
25557
|
-
const historyPath =
|
|
25628
|
+
const historyPath = join10(stateDir, "taskHistory.json");
|
|
25558
25629
|
if (!existsSync8(historyPath)) return;
|
|
25559
25630
|
let items;
|
|
25560
25631
|
try {
|
|
@@ -25603,20 +25674,20 @@ function countFiles(dir, extensions) {
|
|
|
25603
25674
|
|
|
25604
25675
|
// src/importers/opencode.ts
|
|
25605
25676
|
import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as readFileSync10 } from "fs";
|
|
25606
|
-
import { join as
|
|
25607
|
-
import { homedir as
|
|
25608
|
-
import { Database as
|
|
25677
|
+
import { join as join11 } from "path";
|
|
25678
|
+
import { homedir as homedir6 } from "os";
|
|
25679
|
+
import { Database as Database4 } from "bun:sqlite";
|
|
25609
25680
|
var OpenCodeImporter = class {
|
|
25610
25681
|
name = "opencode";
|
|
25611
25682
|
dataPath;
|
|
25612
25683
|
configPath;
|
|
25613
25684
|
constructor(dataPath, configPath) {
|
|
25614
|
-
this.dataPath = dataPath ??
|
|
25615
|
-
process.env["XDG_DATA_HOME"] ??
|
|
25685
|
+
this.dataPath = dataPath ?? join11(
|
|
25686
|
+
process.env["XDG_DATA_HOME"] ?? join11(homedir6(), ".local", "share"),
|
|
25616
25687
|
"opencode"
|
|
25617
25688
|
);
|
|
25618
|
-
this.configPath = configPath ??
|
|
25619
|
-
process.env["XDG_CONFIG_HOME"] ??
|
|
25689
|
+
this.configPath = configPath ?? join11(
|
|
25690
|
+
process.env["XDG_CONFIG_HOME"] ?? join11(homedir6(), ".config"),
|
|
25620
25691
|
"opencode"
|
|
25621
25692
|
);
|
|
25622
25693
|
}
|
|
@@ -25626,8 +25697,8 @@ var OpenCodeImporter = class {
|
|
|
25626
25697
|
scan() {
|
|
25627
25698
|
let knowledgeFiles = 0;
|
|
25628
25699
|
let sessionFiles = 0;
|
|
25629
|
-
if (existsSync9(
|
|
25630
|
-
const dbPath =
|
|
25700
|
+
if (existsSync9(join11(this.configPath, "AGENTS.md"))) knowledgeFiles++;
|
|
25701
|
+
const dbPath = join11(this.dataPath, "opencode.db");
|
|
25631
25702
|
if (existsSync9(dbPath)) sessionFiles = 1;
|
|
25632
25703
|
return { memoryFiles: 0, knowledgeFiles, sessionFiles };
|
|
25633
25704
|
}
|
|
@@ -25641,7 +25712,7 @@ var OpenCodeImporter = class {
|
|
|
25641
25712
|
return result;
|
|
25642
25713
|
}
|
|
25643
25714
|
async importAgentsMd(db, embed, result) {
|
|
25644
|
-
const agentsMdPath =
|
|
25715
|
+
const agentsMdPath = join11(this.configPath, "AGENTS.md");
|
|
25645
25716
|
if (!existsSync9(agentsMdPath)) return;
|
|
25646
25717
|
try {
|
|
25647
25718
|
const raw = readFileSync10(agentsMdPath, "utf8");
|
|
@@ -25667,28 +25738,28 @@ var OpenCodeImporter = class {
|
|
|
25667
25738
|
async importProjectContent(db, embed, result) {
|
|
25668
25739
|
const projectPaths = await this.discoverProjects();
|
|
25669
25740
|
for (const projectPath of projectPaths) {
|
|
25670
|
-
const openCodeDir =
|
|
25741
|
+
const openCodeDir = join11(projectPath, ".opencode");
|
|
25671
25742
|
if (!existsSync9(openCodeDir)) continue;
|
|
25672
|
-
const agentDir =
|
|
25743
|
+
const agentDir = join11(openCodeDir, "agent");
|
|
25673
25744
|
if (existsSync9(agentDir)) {
|
|
25674
25745
|
await this.importMdDir(db, embed, result, agentDir, ["opencode-agent"]);
|
|
25675
25746
|
}
|
|
25676
|
-
const commandDir =
|
|
25747
|
+
const commandDir = join11(openCodeDir, "command");
|
|
25677
25748
|
if (existsSync9(commandDir)) {
|
|
25678
25749
|
await this.importMdDir(db, embed, result, commandDir, ["opencode-command"]);
|
|
25679
25750
|
}
|
|
25680
|
-
const projectAgentsMd =
|
|
25751
|
+
const projectAgentsMd = join11(projectPath, "AGENTS.md");
|
|
25681
25752
|
if (existsSync9(projectAgentsMd)) {
|
|
25682
25753
|
await this.importSingleFile(db, embed, result, projectAgentsMd, ["agents-md", "project"]);
|
|
25683
25754
|
}
|
|
25684
25755
|
}
|
|
25685
25756
|
}
|
|
25686
25757
|
async discoverProjects() {
|
|
25687
|
-
const dbPath =
|
|
25758
|
+
const dbPath = join11(this.dataPath, "opencode.db");
|
|
25688
25759
|
if (!existsSync9(dbPath)) return [];
|
|
25689
25760
|
let ocDb = null;
|
|
25690
25761
|
try {
|
|
25691
|
-
ocDb = new
|
|
25762
|
+
ocDb = new Database4(dbPath, { readonly: true });
|
|
25692
25763
|
const rows = ocDb.query("SELECT worktree FROM project").all();
|
|
25693
25764
|
return rows.map((r) => r.worktree).filter((p) => existsSync9(p));
|
|
25694
25765
|
} catch {
|
|
@@ -25700,7 +25771,7 @@ var OpenCodeImporter = class {
|
|
|
25700
25771
|
async importMdDir(db, embed, result, dir, tags) {
|
|
25701
25772
|
for (const filename of readdirSync6(dir)) {
|
|
25702
25773
|
if (!filename.endsWith(".md")) continue;
|
|
25703
|
-
await this.importSingleFile(db, embed, result,
|
|
25774
|
+
await this.importSingleFile(db, embed, result, join11(dir, filename), tags);
|
|
25704
25775
|
}
|
|
25705
25776
|
}
|
|
25706
25777
|
async importSingleFile(db, embed, result, filePath, tags) {
|
|
@@ -25730,36 +25801,36 @@ var OpenCodeImporter = class {
|
|
|
25730
25801
|
|
|
25731
25802
|
// src/importers/hermes.ts
|
|
25732
25803
|
import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync11 } from "fs";
|
|
25733
|
-
import { join as
|
|
25734
|
-
import { homedir as
|
|
25804
|
+
import { join as join12 } from "path";
|
|
25805
|
+
import { homedir as homedir7 } from "os";
|
|
25735
25806
|
var HermesImporter = class {
|
|
25736
25807
|
name = "hermes";
|
|
25737
25808
|
basePath;
|
|
25738
25809
|
constructor(basePath) {
|
|
25739
|
-
this.basePath = basePath ?? (process.env["HERMES_HOME"] ||
|
|
25810
|
+
this.basePath = basePath ?? (process.env["HERMES_HOME"] || join12(homedir7(), ".hermes"));
|
|
25740
25811
|
}
|
|
25741
25812
|
detect() {
|
|
25742
|
-
return existsSync10(this.basePath) && (existsSync10(
|
|
25813
|
+
return existsSync10(this.basePath) && (existsSync10(join12(this.basePath, "state.db")) || existsSync10(join12(this.basePath, "memories")) || existsSync10(join12(this.basePath, "config.yaml")));
|
|
25743
25814
|
}
|
|
25744
25815
|
scan() {
|
|
25745
25816
|
let memoryFiles = 0;
|
|
25746
25817
|
let knowledgeFiles = 0;
|
|
25747
25818
|
let sessionFiles = 0;
|
|
25748
|
-
const memoriesDir =
|
|
25819
|
+
const memoriesDir = join12(this.basePath, "memories");
|
|
25749
25820
|
if (existsSync10(memoriesDir)) {
|
|
25750
|
-
if (existsSync10(
|
|
25751
|
-
if (existsSync10(
|
|
25821
|
+
if (existsSync10(join12(memoriesDir, "MEMORY.md"))) memoryFiles++;
|
|
25822
|
+
if (existsSync10(join12(memoriesDir, "USER.md"))) memoryFiles++;
|
|
25752
25823
|
}
|
|
25753
|
-
const skillsDir =
|
|
25824
|
+
const skillsDir = join12(this.basePath, "skills");
|
|
25754
25825
|
if (existsSync10(skillsDir)) {
|
|
25755
25826
|
for (const entry of readdirSync7(skillsDir, { withFileTypes: true })) {
|
|
25756
|
-
if (entry.isDirectory() && existsSync10(
|
|
25827
|
+
if (entry.isDirectory() && existsSync10(join12(skillsDir, entry.name, "SKILL.md"))) {
|
|
25757
25828
|
knowledgeFiles++;
|
|
25758
25829
|
}
|
|
25759
25830
|
}
|
|
25760
25831
|
}
|
|
25761
|
-
if (existsSync10(
|
|
25762
|
-
if (existsSync10(
|
|
25832
|
+
if (existsSync10(join12(this.basePath, "SOUL.md"))) knowledgeFiles++;
|
|
25833
|
+
if (existsSync10(join12(this.basePath, "state.db"))) sessionFiles = 1;
|
|
25763
25834
|
return { memoryFiles, knowledgeFiles, sessionFiles };
|
|
25764
25835
|
}
|
|
25765
25836
|
async importMemories(db, embed, _project) {
|
|
@@ -25768,21 +25839,21 @@ var HermesImporter = class {
|
|
|
25768
25839
|
db,
|
|
25769
25840
|
embed,
|
|
25770
25841
|
result,
|
|
25771
|
-
|
|
25842
|
+
join12(this.basePath, "memories", "MEMORY.md"),
|
|
25772
25843
|
["hermes-memory"]
|
|
25773
25844
|
);
|
|
25774
25845
|
await this.importMemoryFile(
|
|
25775
25846
|
db,
|
|
25776
25847
|
embed,
|
|
25777
25848
|
result,
|
|
25778
|
-
|
|
25849
|
+
join12(this.basePath, "memories", "USER.md"),
|
|
25779
25850
|
["hermes-user", "user-profile"]
|
|
25780
25851
|
);
|
|
25781
25852
|
return result;
|
|
25782
25853
|
}
|
|
25783
25854
|
async importKnowledge(db, embed) {
|
|
25784
25855
|
const result = { imported: 0, skipped: 0, errors: [] };
|
|
25785
|
-
const soulPath =
|
|
25856
|
+
const soulPath = join12(this.basePath, "SOUL.md");
|
|
25786
25857
|
if (existsSync10(soulPath)) {
|
|
25787
25858
|
await this.importSingleFile(db, embed, result, soulPath, "warm", ["hermes-soul"]);
|
|
25788
25859
|
}
|
|
@@ -25816,11 +25887,11 @@ var HermesImporter = class {
|
|
|
25816
25887
|
}
|
|
25817
25888
|
}
|
|
25818
25889
|
async importSkills(db, embed, result) {
|
|
25819
|
-
const skillsDir =
|
|
25890
|
+
const skillsDir = join12(this.basePath, "skills");
|
|
25820
25891
|
if (!existsSync10(skillsDir)) return;
|
|
25821
25892
|
for (const entry of readdirSync7(skillsDir, { withFileTypes: true })) {
|
|
25822
25893
|
if (!entry.isDirectory()) continue;
|
|
25823
|
-
const skillPath =
|
|
25894
|
+
const skillPath = join12(skillsDir, entry.name, "SKILL.md");
|
|
25824
25895
|
if (!existsSync10(skillPath)) continue;
|
|
25825
25896
|
await this.importSingleFile(db, embed, result, skillPath, "cold", ["hermes-skill", entry.name]);
|
|
25826
25897
|
}
|
|
@@ -26048,7 +26119,7 @@ async function sweepWarmTier(db, embed, config2, sessionId) {
|
|
|
26048
26119
|
|
|
26049
26120
|
// src/importers/project-docs.ts
|
|
26050
26121
|
import { existsSync as existsSync11, readFileSync as readFileSync12, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
|
|
26051
|
-
import { join as
|
|
26122
|
+
import { join as join13, basename as basename4 } from "path";
|
|
26052
26123
|
import { createHash as createHash4 } from "crypto";
|
|
26053
26124
|
var DOC_FILES = ["README.md", "CONTRIBUTING.md", "CLAUDE.md", "AGENTS.md"];
|
|
26054
26125
|
var DOC_DIRS = ["docs", "doc"];
|
|
@@ -26073,11 +26144,11 @@ async function ingestProjectDocs(db, embed, cwd) {
|
|
|
26073
26144
|
let collectionId = null;
|
|
26074
26145
|
const filesToIngest = [];
|
|
26075
26146
|
for (const file2 of DOC_FILES) {
|
|
26076
|
-
const path =
|
|
26147
|
+
const path = join13(cwd, file2);
|
|
26077
26148
|
if (existsSync11(path)) filesToIngest.push(path);
|
|
26078
26149
|
}
|
|
26079
26150
|
for (const dir of DOC_DIRS) {
|
|
26080
|
-
const dirPath =
|
|
26151
|
+
const dirPath = join13(cwd, dir);
|
|
26081
26152
|
if (existsSync11(dirPath) && statSync5(dirPath).isDirectory()) {
|
|
26082
26153
|
collectMarkdownFiles(dirPath, filesToIngest);
|
|
26083
26154
|
}
|
|
@@ -26105,7 +26176,7 @@ async function ingestProjectDocs(db, embed, cwd) {
|
|
|
26105
26176
|
}
|
|
26106
26177
|
function collectMarkdownFiles(dirPath, files) {
|
|
26107
26178
|
for (const entry of readdirSync8(dirPath, { withFileTypes: true })) {
|
|
26108
|
-
const full =
|
|
26179
|
+
const full = join13(dirPath, entry.name);
|
|
26109
26180
|
if (entry.isDirectory()) {
|
|
26110
26181
|
collectMarkdownFiles(full, files);
|
|
26111
26182
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -26117,9 +26188,9 @@ function collectMarkdownFiles(dirPath, files) {
|
|
|
26117
26188
|
// src/utils/project-detect.ts
|
|
26118
26189
|
import { execFileSync } from "child_process";
|
|
26119
26190
|
import { basename as basename5, parse as parsePath } from "path";
|
|
26120
|
-
import { homedir as
|
|
26191
|
+
import { homedir as homedir8 } from "os";
|
|
26121
26192
|
function detectProject(cwd) {
|
|
26122
|
-
if (cwd ===
|
|
26193
|
+
if (cwd === homedir8()) return null;
|
|
26123
26194
|
if (cwd === parsePath(cwd).root) return null;
|
|
26124
26195
|
try {
|
|
26125
26196
|
const remote = execFileSync("git", ["remote", "get-url", "origin"], {
|
|
@@ -26137,10 +26208,10 @@ function detectProject(cwd) {
|
|
|
26137
26208
|
}
|
|
26138
26209
|
|
|
26139
26210
|
// src/eval/smoke-test.ts
|
|
26140
|
-
import { resolve as resolve4, dirname as
|
|
26211
|
+
import { resolve as resolve4, dirname as dirname7, basename as basename6 } from "path";
|
|
26141
26212
|
import { readFileSync as readFileSync13 } from "fs";
|
|
26142
26213
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
26143
|
-
var __dirname3 =
|
|
26214
|
+
var __dirname3 = dirname7(fileURLToPath7(import.meta.url));
|
|
26144
26215
|
var PACKAGE_ROOT3 = basename6(__dirname3) === "dist" ? resolve4(__dirname3, "..") : resolve4(__dirname3, "..", "..");
|
|
26145
26216
|
var SMOKE_PASS_THRESHOLD = 0.8;
|
|
26146
26217
|
function getMetaValue(db, key) {
|
|
@@ -26538,7 +26609,7 @@ function registerSessionTools() {
|
|
|
26538
26609
|
|
|
26539
26610
|
// src/tools/extra-tools.ts
|
|
26540
26611
|
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, readFileSync as readFileSync14 } from "fs";
|
|
26541
|
-
import { join as
|
|
26612
|
+
import { join as join14 } from "path";
|
|
26542
26613
|
function registerExtraTools() {
|
|
26543
26614
|
return [
|
|
26544
26615
|
{
|
|
@@ -26771,10 +26842,10 @@ async function handleExtraTool(name, args, ctx) {
|
|
|
26771
26842
|
});
|
|
26772
26843
|
}
|
|
26773
26844
|
}
|
|
26774
|
-
const exportsDir =
|
|
26845
|
+
const exportsDir = join14(getDataDir(), "exports");
|
|
26775
26846
|
mkdirSync5(exportsDir, { recursive: true });
|
|
26776
26847
|
const timestamp = Date.now();
|
|
26777
|
-
const exportPath =
|
|
26848
|
+
const exportPath = join14(exportsDir, `${timestamp}.json`);
|
|
26778
26849
|
const exportData = { version: 1, exported_at: timestamp, entries: allEntries };
|
|
26779
26850
|
const jsonStr = JSON.stringify(exportData, null, 2);
|
|
26780
26851
|
writeFileSync3(exportPath, jsonStr, "utf-8");
|
|
@@ -26963,6 +27034,17 @@ async function startServer(ctx) {
|
|
|
26963
27034
|
|
|
26964
27035
|
// src/index.ts
|
|
26965
27036
|
async function main() {
|
|
27037
|
+
let dbPath;
|
|
27038
|
+
try {
|
|
27039
|
+
dbPath = getDbPath();
|
|
27040
|
+
} catch (e) {
|
|
27041
|
+
if (e instanceof SqliteDbPathError) {
|
|
27042
|
+
process.stderr.write(`total-recall: ${e.message}
|
|
27043
|
+
`);
|
|
27044
|
+
process.exit(1);
|
|
27045
|
+
}
|
|
27046
|
+
throw e;
|
|
27047
|
+
}
|
|
26966
27048
|
const config2 = loadConfig();
|
|
26967
27049
|
const db = getDb();
|
|
26968
27050
|
const embedder = new Embedder({
|
|
@@ -26970,7 +27052,7 @@ async function main() {
|
|
|
26970
27052
|
dimensions: config2.embedding.dimensions
|
|
26971
27053
|
});
|
|
26972
27054
|
const sessionId = randomUUID8();
|
|
26973
|
-
process.stderr.write(`total-recall: MCP server starting (db: ${
|
|
27055
|
+
process.stderr.write(`total-recall: MCP server starting (db: ${dbPath})
|
|
26974
27056
|
`);
|
|
26975
27057
|
await startServer({ db, config: config2, embedder, sessionId, configSnapshotId: "default", sessionInitialized: false, sessionInitResult: null, sessionInitPromise: null });
|
|
26976
27058
|
const cleanup = () => {
|