@loreai/core 0.19.0 → 0.20.0
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/bun/agents-file.d.ts.map +1 -1
- package/dist/bun/config.d.ts.map +1 -1
- package/dist/bun/db.d.ts +13 -1
- package/dist/bun/db.d.ts.map +1 -1
- package/dist/bun/embedding.d.ts.map +1 -1
- package/dist/bun/git.d.ts.map +1 -1
- package/dist/bun/gradient.d.ts +4 -1
- package/dist/bun/gradient.d.ts.map +1 -1
- package/dist/bun/hosted.d.ts +36 -0
- package/dist/bun/hosted.d.ts.map +1 -0
- package/dist/bun/index.d.ts +3 -2
- package/dist/bun/index.d.ts.map +1 -1
- package/dist/bun/index.js +236 -152
- package/dist/bun/index.js.map +4 -4
- package/dist/bun/lat-reader.d.ts.map +1 -1
- package/dist/node/agents-file.d.ts.map +1 -1
- package/dist/node/config.d.ts.map +1 -1
- package/dist/node/db.d.ts +13 -1
- package/dist/node/db.d.ts.map +1 -1
- package/dist/node/embedding.d.ts.map +1 -1
- package/dist/node/git.d.ts.map +1 -1
- package/dist/node/gradient.d.ts +4 -1
- package/dist/node/gradient.d.ts.map +1 -1
- package/dist/node/hosted.d.ts +36 -0
- package/dist/node/hosted.d.ts.map +1 -0
- package/dist/node/index.d.ts +3 -2
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +236 -152
- package/dist/node/index.js.map +4 -4
- package/dist/node/lat-reader.d.ts.map +1 -1
- package/dist/types/agents-file.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/db.d.ts +13 -1
- package/dist/types/db.d.ts.map +1 -1
- package/dist/types/embedding.d.ts.map +1 -1
- package/dist/types/git.d.ts.map +1 -1
- package/dist/types/gradient.d.ts +4 -1
- package/dist/types/gradient.d.ts.map +1 -1
- package/dist/types/hosted.d.ts +36 -0
- package/dist/types/hosted.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lat-reader.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/agents-file.ts +12 -0
- package/src/config.ts +10 -5
- package/src/db.ts +39 -6
- package/src/embedding.ts +43 -5
- package/src/git.ts +4 -0
- package/src/gradient.ts +44 -0
- package/src/hosted.ts +46 -0
- package/src/index.ts +4 -0
- package/src/lat-reader.ts +4 -0
package/dist/node/index.js
CHANGED
|
@@ -168,6 +168,17 @@ import { mkdirSync } from "fs";
|
|
|
168
168
|
|
|
169
169
|
// src/git.ts
|
|
170
170
|
import { execSync } from "child_process";
|
|
171
|
+
|
|
172
|
+
// src/hosted.ts
|
|
173
|
+
var _hostedMode = false;
|
|
174
|
+
function enableHostedMode() {
|
|
175
|
+
_hostedMode = true;
|
|
176
|
+
}
|
|
177
|
+
function isHostedMode() {
|
|
178
|
+
return _hostedMode;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/git.ts
|
|
171
182
|
function normalizeRemoteUrl(url2) {
|
|
172
183
|
let normalized = url2.trim();
|
|
173
184
|
const sshMatch = normalized.match(/^[\w.-]+@([\w.-]+):(.+)$/);
|
|
@@ -192,6 +203,7 @@ function clearGitRemoteCache() {
|
|
|
192
203
|
gitRemoteCache.clear();
|
|
193
204
|
}
|
|
194
205
|
function getGitRemote(path) {
|
|
206
|
+
if (isHostedMode()) return null;
|
|
195
207
|
const cached2 = gitRemoteCache.get(path);
|
|
196
208
|
if (cached2 !== void 0) return cached2;
|
|
197
209
|
try {
|
|
@@ -939,7 +951,7 @@ function close() {
|
|
|
939
951
|
instance = void 0;
|
|
940
952
|
}
|
|
941
953
|
}
|
|
942
|
-
function ensureProject(path, name) {
|
|
954
|
+
function ensureProject(path, name, suppliedGitRemote) {
|
|
943
955
|
if (!process.env.LORE_DB_PATH && /^\/test\//.test(path)) {
|
|
944
956
|
throw new Error(
|
|
945
957
|
`Refusing to create project with test path "${path}" in the production DB. Set LORE_DB_PATH to a temp path, or run tests via \`bun test\` from the repo root.`
|
|
@@ -948,22 +960,22 @@ function ensureProject(path, name) {
|
|
|
948
960
|
const existing = db().query("SELECT id, git_remote FROM projects WHERE path = ?").get(path);
|
|
949
961
|
if (existing) {
|
|
950
962
|
if (!existing.git_remote) {
|
|
951
|
-
const
|
|
952
|
-
if (
|
|
963
|
+
const resolvedRemote = suppliedGitRemote ?? getGitRemote(path);
|
|
964
|
+
if (resolvedRemote) {
|
|
953
965
|
const conflict = db().query(
|
|
954
966
|
"SELECT id FROM projects WHERE git_remote = ? AND id != ? LIMIT 1"
|
|
955
|
-
).get(
|
|
967
|
+
).get(resolvedRemote, existing.id);
|
|
956
968
|
if (conflict) {
|
|
957
969
|
mergeProjectInternal(conflict.id, existing.id);
|
|
958
970
|
}
|
|
959
|
-
db().query("UPDATE projects SET git_remote = ? WHERE id = ?").run(
|
|
971
|
+
db().query("UPDATE projects SET git_remote = ? WHERE id = ?").run(resolvedRemote, existing.id);
|
|
960
972
|
}
|
|
961
973
|
}
|
|
962
974
|
return existing.id;
|
|
963
975
|
}
|
|
964
976
|
const alias = db().query("SELECT project_id FROM project_path_aliases WHERE path = ?").get(path);
|
|
965
977
|
if (alias) return alias.project_id;
|
|
966
|
-
const gitRemote = getGitRemote(path);
|
|
978
|
+
const gitRemote = suppliedGitRemote ?? getGitRemote(path);
|
|
967
979
|
if (gitRemote) {
|
|
968
980
|
const byRemote = db().query("SELECT id FROM projects WHERE git_remote = ? LIMIT 1").get(gitRemote);
|
|
969
981
|
if (byRemote) {
|
|
@@ -991,6 +1003,20 @@ function projectId(path) {
|
|
|
991
1003
|
const alias = db().query("SELECT project_id FROM project_path_aliases WHERE path = ?").get(path);
|
|
992
1004
|
return alias?.project_id;
|
|
993
1005
|
}
|
|
1006
|
+
function resolveProjectByRemoteOrPath(gitRemote, path) {
|
|
1007
|
+
if (gitRemote) {
|
|
1008
|
+
const row = db().query("SELECT id FROM projects WHERE git_remote = ? LIMIT 1").get(gitRemote);
|
|
1009
|
+
if (row) return row.id;
|
|
1010
|
+
}
|
|
1011
|
+
if (path) {
|
|
1012
|
+
return projectId(path) ?? null;
|
|
1013
|
+
}
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
function projectPath(id) {
|
|
1017
|
+
const row = db().query("SELECT path FROM projects WHERE id = ?").get(id);
|
|
1018
|
+
return row?.path ?? null;
|
|
1019
|
+
}
|
|
994
1020
|
function projectName(id) {
|
|
995
1021
|
const row = db().query("SELECT name FROM projects WHERE id = ?").get(id);
|
|
996
1022
|
return row?.name ?? null;
|
|
@@ -999,13 +1025,13 @@ function isFirstRun() {
|
|
|
999
1025
|
const row = db().query("SELECT COUNT(*) as count FROM projects").get();
|
|
1000
1026
|
return row.count === 0;
|
|
1001
1027
|
}
|
|
1002
|
-
function getLastImportAt(
|
|
1003
|
-
const id = ensureProject(
|
|
1028
|
+
function getLastImportAt(projectPath2) {
|
|
1029
|
+
const id = ensureProject(projectPath2);
|
|
1004
1030
|
const row = db().query("SELECT last_import_at FROM projects WHERE id = ?").get(id);
|
|
1005
1031
|
return row?.last_import_at ?? null;
|
|
1006
1032
|
}
|
|
1007
|
-
function setLastImportAt(
|
|
1008
|
-
const id = ensureProject(
|
|
1033
|
+
function setLastImportAt(projectPath2, timestamp) {
|
|
1034
|
+
const id = ensureProject(projectPath2);
|
|
1009
1035
|
db().query("UPDATE projects SET last_import_at = ? WHERE id = ?").run(timestamp, id);
|
|
1010
1036
|
}
|
|
1011
1037
|
function loadForceMinLayer(sessionID) {
|
|
@@ -26791,11 +26817,13 @@ function config2() {
|
|
|
26791
26817
|
return current;
|
|
26792
26818
|
}
|
|
26793
26819
|
async function load(directory) {
|
|
26794
|
-
|
|
26795
|
-
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26820
|
+
if (!isHostedMode()) {
|
|
26821
|
+
const path = join5(directory, ".lore.json");
|
|
26822
|
+
if (existsSync2(path)) {
|
|
26823
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
26824
|
+
current = LoreConfig.parse(raw);
|
|
26825
|
+
return current;
|
|
26826
|
+
}
|
|
26799
26827
|
}
|
|
26800
26828
|
current = LoreConfig.parse({});
|
|
26801
26829
|
return current;
|
|
@@ -26835,6 +26863,14 @@ function vendorRegistration() {
|
|
|
26835
26863
|
|
|
26836
26864
|
// src/embedding.ts
|
|
26837
26865
|
var EMBED_TIMEOUT_MS = 1e4;
|
|
26866
|
+
var LOCAL_MAX_CHARS = 4096 * 4;
|
|
26867
|
+
function safeLocalTruncate(text4) {
|
|
26868
|
+
if (text4.length <= LOCAL_MAX_CHARS) return text4;
|
|
26869
|
+
let end = LOCAL_MAX_CHARS;
|
|
26870
|
+
const code2 = text4.charCodeAt(end - 1);
|
|
26871
|
+
if (code2 >= 55296 && code2 <= 56319) end--;
|
|
26872
|
+
return text4.slice(0, end);
|
|
26873
|
+
}
|
|
26838
26874
|
var VOYAGE_API_URL = "https://api.voyageai.com/v1/embeddings";
|
|
26839
26875
|
var VoyageProvider = class {
|
|
26840
26876
|
maxBatchSize = 128;
|
|
@@ -27017,8 +27053,9 @@ var LocalProvider = class {
|
|
|
27017
27053
|
localProviderKnownBroken = true;
|
|
27018
27054
|
if (!localProviderErrorLogged) {
|
|
27019
27055
|
localProviderErrorLogged = true;
|
|
27020
|
-
|
|
27021
|
-
`local embedding provider failed to init: ${msg.error}. Set VOYAGE_API_KEY/OPENAI_API_KEY for automatic remote fallback
|
|
27056
|
+
error(
|
|
27057
|
+
`local embedding provider failed to init: ${msg.error}. Set VOYAGE_API_KEY/OPENAI_API_KEY for automatic remote fallback.`,
|
|
27058
|
+
new Error(`embedding worker init failed: ${msg.error}`)
|
|
27022
27059
|
);
|
|
27023
27060
|
}
|
|
27024
27061
|
for (const [, p2] of this.pendingRequests) {
|
|
@@ -27033,6 +27070,7 @@ var LocalProvider = class {
|
|
|
27033
27070
|
this.worker.on("error", (err) => {
|
|
27034
27071
|
this.workerInitError = err.message;
|
|
27035
27072
|
this.workerReady = false;
|
|
27073
|
+
error("embedding worker crashed:", err);
|
|
27036
27074
|
for (const [, p2] of this.pendingRequests) {
|
|
27037
27075
|
p2.reject(new LocalProviderUnavailableError(err));
|
|
27038
27076
|
}
|
|
@@ -27042,6 +27080,10 @@ var LocalProvider = class {
|
|
|
27042
27080
|
this.worker.on("exit", (code2) => {
|
|
27043
27081
|
if (code2 !== 0 && !this.workerInitError) {
|
|
27044
27082
|
this.workerInitError = `embedding worker exited with code ${code2}`;
|
|
27083
|
+
error(
|
|
27084
|
+
this.workerInitError,
|
|
27085
|
+
new Error(this.workerInitError)
|
|
27086
|
+
);
|
|
27045
27087
|
}
|
|
27046
27088
|
this.workerReady = false;
|
|
27047
27089
|
for (const [, p2] of this.pendingRequests) {
|
|
@@ -27072,8 +27114,9 @@ var LocalProvider = class {
|
|
|
27072
27114
|
}
|
|
27073
27115
|
async embed(texts, inputType) {
|
|
27074
27116
|
await this.ensureWorker();
|
|
27117
|
+
const truncated = texts.map(safeLocalTruncate);
|
|
27075
27118
|
const prefix = inputType === "document" ? "search_document: " : "search_query: ";
|
|
27076
|
-
const prefixed =
|
|
27119
|
+
const prefixed = truncated.map((t2) => prefix + t2);
|
|
27077
27120
|
const id = this.nextRequestId++;
|
|
27078
27121
|
const priority = inputType === "query" && texts.length === 1 ? "high" : "normal";
|
|
27079
27122
|
return new Promise((resolve, reject) => {
|
|
@@ -27301,27 +27344,30 @@ function vectorSearchAllDistillations(queryEmbedding, projectId2, limit = 20) {
|
|
|
27301
27344
|
return scored.slice(0, limit);
|
|
27302
27345
|
}
|
|
27303
27346
|
function embedKnowledgeEntry(id, title, content3) {
|
|
27347
|
+
if (!isAvailable()) return;
|
|
27304
27348
|
const text4 = `${title}
|
|
27305
27349
|
${content3}`;
|
|
27306
27350
|
embed([text4], "document").then(([vec]) => {
|
|
27307
27351
|
db().query("UPDATE knowledge SET embedding = ? WHERE id = ?").run(toBlob(vec), id);
|
|
27308
27352
|
}).catch((err) => {
|
|
27309
|
-
|
|
27353
|
+
error("embedding failed for knowledge entry", id, ":", err);
|
|
27310
27354
|
});
|
|
27311
27355
|
}
|
|
27312
27356
|
function embedDistillation(id, observations) {
|
|
27357
|
+
if (!isAvailable()) return;
|
|
27313
27358
|
embed([observations], "document").then(([vec]) => {
|
|
27314
27359
|
db().query("UPDATE distillations SET embedding = ? WHERE id = ?").run(toBlob(vec), id);
|
|
27315
27360
|
}).catch((err) => {
|
|
27316
|
-
|
|
27361
|
+
error("embedding failed for distillation", id, ":", err);
|
|
27317
27362
|
});
|
|
27318
27363
|
}
|
|
27319
27364
|
function embedTemporalMessage(id, content3) {
|
|
27365
|
+
if (!isAvailable()) return;
|
|
27320
27366
|
if (content3.length < 50) return;
|
|
27321
27367
|
embed([content3], "document").then(([vec]) => {
|
|
27322
27368
|
db().query("UPDATE temporal_messages SET embedding = ? WHERE id = ?").run(toBlob(vec), id);
|
|
27323
27369
|
}).catch((err) => {
|
|
27324
|
-
|
|
27370
|
+
error("embedding failed for temporal message", id, ":", err);
|
|
27325
27371
|
});
|
|
27326
27372
|
}
|
|
27327
27373
|
function vectorSearchTemporal(queryEmbedding, projectId2, limit = 10, sessionId) {
|
|
@@ -27441,6 +27487,7 @@ ${r.content}` }));
|
|
|
27441
27487
|
}
|
|
27442
27488
|
} catch (err) {
|
|
27443
27489
|
error(`embedding backfill batch failed (${batch.length} items):`, err);
|
|
27490
|
+
if (err instanceof LocalProviderUnavailableError) break;
|
|
27444
27491
|
}
|
|
27445
27492
|
}
|
|
27446
27493
|
if (embedded > 0) {
|
|
@@ -27474,6 +27521,7 @@ async function backfillDistillationEmbeddings() {
|
|
|
27474
27521
|
}
|
|
27475
27522
|
} catch (err) {
|
|
27476
27523
|
error(`distillation embedding backfill batch failed (${batch.length} items):`, err);
|
|
27524
|
+
if (err instanceof LocalProviderUnavailableError) break;
|
|
27477
27525
|
}
|
|
27478
27526
|
if (embedded >= nextProgressAt) {
|
|
27479
27527
|
info(`embedding distillations: ${embedded}/${rows.length}\u2026`);
|
|
@@ -27563,14 +27611,14 @@ function store(input) {
|
|
|
27563
27611
|
embedTemporalMessage(input.info.id, content3);
|
|
27564
27612
|
}
|
|
27565
27613
|
}
|
|
27566
|
-
function undistilled(
|
|
27567
|
-
const pid = ensureProject(
|
|
27614
|
+
function undistilled(projectPath2, sessionID) {
|
|
27615
|
+
const pid = ensureProject(projectPath2);
|
|
27568
27616
|
const query = sessionID ? "SELECT * FROM temporal_messages WHERE project_id = ? AND session_id = ? AND distilled = 0 ORDER BY created_at ASC" : "SELECT * FROM temporal_messages WHERE project_id = ? AND distilled = 0 ORDER BY created_at ASC";
|
|
27569
27617
|
const params = sessionID ? [pid, sessionID] : [pid];
|
|
27570
27618
|
return db().query(query).all(...params);
|
|
27571
27619
|
}
|
|
27572
|
-
function bySession(
|
|
27573
|
-
const pid = ensureProject(
|
|
27620
|
+
function bySession(projectPath2, sessionID) {
|
|
27621
|
+
const pid = ensureProject(projectPath2);
|
|
27574
27622
|
return db().query(
|
|
27575
27623
|
"SELECT * FROM temporal_messages WHERE project_id = ? AND session_id = ? ORDER BY created_at ASC"
|
|
27576
27624
|
).all(pid, sessionID);
|
|
@@ -27646,26 +27694,26 @@ function temporalCnorm(timestamps, now = Date.now()) {
|
|
|
27646
27694
|
const maxVariance = (n - 1) / (n * n);
|
|
27647
27695
|
return maxVariance === 0 ? 0 : variance / maxVariance;
|
|
27648
27696
|
}
|
|
27649
|
-
function count(
|
|
27650
|
-
const pid = ensureProject(
|
|
27697
|
+
function count(projectPath2, sessionID) {
|
|
27698
|
+
const pid = ensureProject(projectPath2);
|
|
27651
27699
|
const query = sessionID ? "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ? AND session_id = ?" : "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ?";
|
|
27652
27700
|
const params = sessionID ? [pid, sessionID] : [pid];
|
|
27653
27701
|
return db().query(query).get(...params).count;
|
|
27654
27702
|
}
|
|
27655
|
-
function hasMessages(
|
|
27656
|
-
const pid = ensureProject(
|
|
27703
|
+
function hasMessages(projectPath2, sessionID) {
|
|
27704
|
+
const pid = ensureProject(projectPath2);
|
|
27657
27705
|
return !!db().query(
|
|
27658
27706
|
"SELECT 1 FROM temporal_messages WHERE project_id = ? AND session_id = ? LIMIT 1"
|
|
27659
27707
|
).get(pid, sessionID);
|
|
27660
27708
|
}
|
|
27661
|
-
function undistilledCount(
|
|
27662
|
-
const pid = ensureProject(
|
|
27709
|
+
function undistilledCount(projectPath2, sessionID) {
|
|
27710
|
+
const pid = ensureProject(projectPath2);
|
|
27663
27711
|
const query = sessionID ? "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ? AND session_id = ? AND distilled = 0" : "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ? AND distilled = 0";
|
|
27664
27712
|
const params = sessionID ? [pid, sessionID] : [pid];
|
|
27665
27713
|
return db().query(query).get(...params).count;
|
|
27666
27714
|
}
|
|
27667
|
-
function undistilledTokens(
|
|
27668
|
-
const pid = ensureProject(
|
|
27715
|
+
function undistilledTokens(projectPath2, sessionID) {
|
|
27716
|
+
const pid = ensureProject(projectPath2);
|
|
27669
27717
|
const query = sessionID ? "SELECT COALESCE(SUM(tokens), 0) as total FROM temporal_messages WHERE project_id = ? AND session_id = ? AND distilled = 0" : "SELECT COALESCE(SUM(tokens), 0) as total FROM temporal_messages WHERE project_id = ? AND distilled = 0";
|
|
27670
27718
|
const params = sessionID ? [pid, sessionID] : [pid];
|
|
27671
27719
|
return db().query(query).get(...params).total;
|
|
@@ -28186,14 +28234,16 @@ function listMarkdownFiles(dir) {
|
|
|
28186
28234
|
function contentHash(content3) {
|
|
28187
28235
|
return sha256(content3);
|
|
28188
28236
|
}
|
|
28189
|
-
function hasLatDir(
|
|
28190
|
-
|
|
28237
|
+
function hasLatDir(projectPath2) {
|
|
28238
|
+
if (isHostedMode()) return false;
|
|
28239
|
+
const latDir = join6(projectPath2, "lat.md");
|
|
28191
28240
|
return existsSync3(latDir) && statSync2(latDir).isDirectory();
|
|
28192
28241
|
}
|
|
28193
|
-
function refresh(
|
|
28194
|
-
|
|
28242
|
+
function refresh(projectPath2) {
|
|
28243
|
+
if (isHostedMode()) return 0;
|
|
28244
|
+
const latDir = join6(projectPath2, "lat.md");
|
|
28195
28245
|
if (!existsSync3(latDir) || !statSync2(latDir).isDirectory()) return 0;
|
|
28196
|
-
const pid = ensureProject(
|
|
28246
|
+
const pid = ensureProject(projectPath2);
|
|
28197
28247
|
const files = listMarkdownFiles(latDir);
|
|
28198
28248
|
let upserted = 0;
|
|
28199
28249
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
@@ -28208,7 +28258,7 @@ function refresh(projectPath) {
|
|
|
28208
28258
|
} catch {
|
|
28209
28259
|
continue;
|
|
28210
28260
|
}
|
|
28211
|
-
const fileRel = relative(
|
|
28261
|
+
const fileRel = relative(projectPath2, filePath);
|
|
28212
28262
|
seenFiles.add(fileRel);
|
|
28213
28263
|
const hash2 = contentHash(content3);
|
|
28214
28264
|
const existing = db().query("SELECT content_hash FROM lat_sections WHERE project_id = ? AND file = ? LIMIT 1").get(pid, fileRel.replace(/\.md$/, ""));
|
|
@@ -28216,7 +28266,7 @@ function refresh(projectPath) {
|
|
|
28216
28266
|
continue;
|
|
28217
28267
|
}
|
|
28218
28268
|
db().query("DELETE FROM lat_sections WHERE project_id = ? AND file = ?").run(pid, fileRel.replace(/\.md$/, ""));
|
|
28219
|
-
const sections = parseSections(filePath, content3,
|
|
28269
|
+
const sections = parseSections(filePath, content3, projectPath2);
|
|
28220
28270
|
const now = Date.now();
|
|
28221
28271
|
for (const section of sections) {
|
|
28222
28272
|
upsertStmt.run(
|
|
@@ -28266,9 +28316,9 @@ function searchScored2(input) {
|
|
|
28266
28316
|
return [];
|
|
28267
28317
|
}
|
|
28268
28318
|
}
|
|
28269
|
-
function scoreForSession(
|
|
28270
|
-
if (!hasLatDir(
|
|
28271
|
-
const pid = ensureProject(
|
|
28319
|
+
function scoreForSession(projectPath2, sessionContext, maxTokens) {
|
|
28320
|
+
if (!hasLatDir(projectPath2)) return [];
|
|
28321
|
+
const pid = ensureProject(projectPath2);
|
|
28272
28322
|
const terms = extractTopTerms(sessionContext);
|
|
28273
28323
|
if (!terms.length) return [];
|
|
28274
28324
|
const q = terms.map((t2) => `${t2}*`).join(" OR ");
|
|
@@ -28300,8 +28350,8 @@ function scoreForSession(projectPath, sessionContext, maxTokens) {
|
|
|
28300
28350
|
}
|
|
28301
28351
|
return packed;
|
|
28302
28352
|
}
|
|
28303
|
-
function count2(
|
|
28304
|
-
const pid = ensureProject(
|
|
28353
|
+
function count2(projectPath2) {
|
|
28354
|
+
const pid = ensureProject(projectPath2);
|
|
28305
28355
|
const row = db().query("SELECT COUNT(*) as cnt FROM lat_sections WHERE project_id = ?").get(pid);
|
|
28306
28356
|
return row.cnt;
|
|
28307
28357
|
}
|
|
@@ -28428,8 +28478,8 @@ function findFuzzyDuplicate(input) {
|
|
|
28428
28478
|
}
|
|
28429
28479
|
return null;
|
|
28430
28480
|
}
|
|
28431
|
-
function forProject(
|
|
28432
|
-
const pid = ensureProject(
|
|
28481
|
+
function forProject(projectPath2, includeCross = true) {
|
|
28482
|
+
const pid = ensureProject(projectPath2);
|
|
28433
28483
|
if (includeCross) {
|
|
28434
28484
|
return db().query(
|
|
28435
28485
|
`SELECT ${KNOWLEDGE_COLS} FROM knowledge
|
|
@@ -28477,8 +28527,8 @@ function scoreEntriesFTS(sessionContext) {
|
|
|
28477
28527
|
return /* @__PURE__ */ new Map();
|
|
28478
28528
|
}
|
|
28479
28529
|
}
|
|
28480
|
-
async function forSession(
|
|
28481
|
-
const pid = ensureProject(
|
|
28530
|
+
async function forSession(projectPath2, sessionID, maxTokens, options) {
|
|
28531
|
+
const pid = ensureProject(projectPath2);
|
|
28482
28532
|
const categoryFilter = options?.categories;
|
|
28483
28533
|
const excludeFilter = options?.excludeCategories;
|
|
28484
28534
|
let categoryClause = "";
|
|
@@ -28582,9 +28632,9 @@ async function forSession(projectPath, sessionID, maxTokens, options) {
|
|
|
28582
28632
|
result.push(entry);
|
|
28583
28633
|
used += cost;
|
|
28584
28634
|
}
|
|
28585
|
-
if (hasLatDir(
|
|
28635
|
+
if (hasLatDir(projectPath2) && used < maxTokens) {
|
|
28586
28636
|
const latSections = scoreForSession(
|
|
28587
|
-
|
|
28637
|
+
projectPath2,
|
|
28588
28638
|
sessionContext,
|
|
28589
28639
|
maxTokens - used
|
|
28590
28640
|
);
|
|
@@ -28807,8 +28857,8 @@ function cleanDeadRefs() {
|
|
|
28807
28857
|
}
|
|
28808
28858
|
return cleaned;
|
|
28809
28859
|
}
|
|
28810
|
-
function check2(
|
|
28811
|
-
const entries = forProject(
|
|
28860
|
+
function check2(projectPath2) {
|
|
28861
|
+
const entries = forProject(projectPath2, false);
|
|
28812
28862
|
const issues = [];
|
|
28813
28863
|
for (const entry of entries) {
|
|
28814
28864
|
if (entry.content.length > 1200) {
|
|
@@ -28963,10 +29013,10 @@ function _dedup(entries, dryRun, embeddingThreshold = EMBEDDING_DEDUP_THRESHOLD)
|
|
|
28963
29013
|
const entryTitles = new Map(entries.map((e) => [e.id, e.title]));
|
|
28964
29014
|
return { clusters: result, totalRemoved, pairSimilarities, entryTitles };
|
|
28965
29015
|
}
|
|
28966
|
-
async function deduplicate(
|
|
28967
|
-
const pid = ensureProject(
|
|
29016
|
+
async function deduplicate(projectPath2, opts) {
|
|
29017
|
+
const pid = ensureProject(projectPath2);
|
|
28968
29018
|
const threshold = loadCalibratedThreshold(pid) ?? EMBEDDING_DEDUP_THRESHOLD;
|
|
28969
|
-
const entries = forProject(
|
|
29019
|
+
const entries = forProject(projectPath2, false);
|
|
28970
29020
|
return _dedup(entries, opts?.dryRun ?? true, threshold);
|
|
28971
29021
|
}
|
|
28972
29022
|
async function deduplicateGlobal(opts) {
|
|
@@ -29191,8 +29241,8 @@ function setCache(fp, entry) {
|
|
|
29191
29241
|
"INSERT INTO kv_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = ?"
|
|
29192
29242
|
).run(key, value, value);
|
|
29193
29243
|
}
|
|
29194
|
-
function clearLoreFileCache(
|
|
29195
|
-
db().query("DELETE FROM kv_meta WHERE key = ?").run(CACHE_PREFIX + join7(
|
|
29244
|
+
function clearLoreFileCache(projectPath2) {
|
|
29245
|
+
db().query("DELETE FROM kv_meta WHERE key = ?").run(CACHE_PREFIX + join7(projectPath2, LORE_FILE));
|
|
29196
29246
|
}
|
|
29197
29247
|
function splitFile(fileContent) {
|
|
29198
29248
|
const spans = [];
|
|
@@ -29268,8 +29318,8 @@ function hashSection(section) {
|
|
|
29268
29318
|
}
|
|
29269
29319
|
return (h3 >>> 0).toString(16).padStart(8, "0");
|
|
29270
29320
|
}
|
|
29271
|
-
function buildSection(
|
|
29272
|
-
const entries = forProject(
|
|
29321
|
+
function buildSection(projectPath2) {
|
|
29322
|
+
const entries = forProject(projectPath2, false);
|
|
29273
29323
|
if (!entries.length) {
|
|
29274
29324
|
return "\n";
|
|
29275
29325
|
}
|
|
@@ -29301,6 +29351,7 @@ function buildSection(projectPath) {
|
|
|
29301
29351
|
return out.join("\n");
|
|
29302
29352
|
}
|
|
29303
29353
|
function exportToFile(input) {
|
|
29354
|
+
if (isHostedMode()) return;
|
|
29304
29355
|
exportLoreFile(input.projectPath);
|
|
29305
29356
|
const pointerBody = "\n## Long-term Knowledge\n\nFor long-term knowledge entries managed by [lore](https://github.com/BYK/loreai) (gotchas, patterns, decisions, architecture), see [`.lore.md`](.lore.md) in the project root.\n";
|
|
29306
29357
|
const newSection = LORE_SECTION_START + pointerBody + LORE_SECTION_END + "\n";
|
|
@@ -29318,6 +29369,7 @@ function exportToFile(input) {
|
|
|
29318
29369
|
writeFileSync(input.filePath, result, "utf8");
|
|
29319
29370
|
}
|
|
29320
29371
|
function shouldImport(input) {
|
|
29372
|
+
if (isHostedMode()) return false;
|
|
29321
29373
|
if (!existsSync4(input.filePath)) return false;
|
|
29322
29374
|
const fileContent = readFileSync3(input.filePath, "utf8");
|
|
29323
29375
|
const { section } = splitFile(fileContent);
|
|
@@ -29327,7 +29379,7 @@ function shouldImport(input) {
|
|
|
29327
29379
|
const expected = buildSection(input.projectPath);
|
|
29328
29380
|
return hashSection(section) !== hashSection(expected);
|
|
29329
29381
|
}
|
|
29330
|
-
function _importEntries(entries,
|
|
29382
|
+
function _importEntries(entries, projectPath2) {
|
|
29331
29383
|
const seenIds = /* @__PURE__ */ new Set();
|
|
29332
29384
|
for (const entry of entries) {
|
|
29333
29385
|
if (entry.id !== null) {
|
|
@@ -29339,7 +29391,7 @@ function _importEntries(entries, projectPath) {
|
|
|
29339
29391
|
update(entry.id, { content: entry.content });
|
|
29340
29392
|
}
|
|
29341
29393
|
} else {
|
|
29342
|
-
const pid = ensureProject(
|
|
29394
|
+
const pid = ensureProject(projectPath2);
|
|
29343
29395
|
const fuzzyMatch = findFuzzyDuplicate({ title: entry.title, projectId: pid });
|
|
29344
29396
|
if (fuzzyMatch) {
|
|
29345
29397
|
if (fuzzyMatch.title !== entry.title || get(fuzzyMatch.id)?.content !== entry.content) {
|
|
@@ -29347,7 +29399,7 @@ function _importEntries(entries, projectPath) {
|
|
|
29347
29399
|
}
|
|
29348
29400
|
} else {
|
|
29349
29401
|
create({
|
|
29350
|
-
projectPath,
|
|
29402
|
+
projectPath: projectPath2,
|
|
29351
29403
|
category: entry.category,
|
|
29352
29404
|
title: entry.title,
|
|
29353
29405
|
content: entry.content,
|
|
@@ -29358,13 +29410,13 @@ function _importEntries(entries, projectPath) {
|
|
|
29358
29410
|
}
|
|
29359
29411
|
}
|
|
29360
29412
|
} else {
|
|
29361
|
-
const existing = forProject(
|
|
29413
|
+
const existing = forProject(projectPath2, false);
|
|
29362
29414
|
const titleMatch = existing.find(
|
|
29363
29415
|
(e) => e.title.toLowerCase() === entry.title.toLowerCase()
|
|
29364
29416
|
);
|
|
29365
29417
|
if (!titleMatch) {
|
|
29366
29418
|
create({
|
|
29367
|
-
projectPath,
|
|
29419
|
+
projectPath: projectPath2,
|
|
29368
29420
|
category: entry.category,
|
|
29369
29421
|
title: entry.title,
|
|
29370
29422
|
content: entry.content,
|
|
@@ -29376,6 +29428,7 @@ function _importEntries(entries, projectPath) {
|
|
|
29376
29428
|
}
|
|
29377
29429
|
}
|
|
29378
29430
|
function importFromFile(input) {
|
|
29431
|
+
if (isHostedMode()) return;
|
|
29379
29432
|
if (!existsSync4(input.filePath)) return;
|
|
29380
29433
|
const fileContent = readFileSync3(input.filePath, "utf8");
|
|
29381
29434
|
const { section } = splitFile(fileContent);
|
|
@@ -29384,14 +29437,16 @@ function importFromFile(input) {
|
|
|
29384
29437
|
if (!fileEntries.length) return;
|
|
29385
29438
|
_importEntries(fileEntries, input.projectPath);
|
|
29386
29439
|
}
|
|
29387
|
-
function loreFileExists(
|
|
29388
|
-
|
|
29440
|
+
function loreFileExists(projectPath2) {
|
|
29441
|
+
if (isHostedMode()) return false;
|
|
29442
|
+
return existsSync4(join7(projectPath2, LORE_FILE));
|
|
29389
29443
|
}
|
|
29390
|
-
function exportLoreFile(
|
|
29391
|
-
|
|
29444
|
+
function exportLoreFile(projectPath2) {
|
|
29445
|
+
if (isHostedMode()) return;
|
|
29446
|
+
const sectionBody = buildSection(projectPath2);
|
|
29392
29447
|
const content3 = LORE_FILE_HEADER + "\n" + sectionBody;
|
|
29393
29448
|
const contentHash2 = hashSection(content3);
|
|
29394
|
-
const fp = join7(
|
|
29449
|
+
const fp = join7(projectPath2, LORE_FILE);
|
|
29395
29450
|
const cached2 = getCache(fp);
|
|
29396
29451
|
if (cached2 && cached2.hash === contentHash2) {
|
|
29397
29452
|
return;
|
|
@@ -29400,8 +29455,9 @@ function exportLoreFile(projectPath) {
|
|
|
29400
29455
|
const { mtimeMs } = statSync3(fp);
|
|
29401
29456
|
setCache(fp, { mtimeMs, hash: contentHash2 });
|
|
29402
29457
|
}
|
|
29403
|
-
function shouldImportLoreFile(
|
|
29404
|
-
|
|
29458
|
+
function shouldImportLoreFile(projectPath2) {
|
|
29459
|
+
if (isHostedMode()) return false;
|
|
29460
|
+
const fp = join7(projectPath2, LORE_FILE);
|
|
29405
29461
|
if (!existsSync4(fp)) return false;
|
|
29406
29462
|
const { mtimeMs } = statSync3(fp);
|
|
29407
29463
|
const cached2 = getCache(fp);
|
|
@@ -29410,7 +29466,7 @@ function shouldImportLoreFile(projectPath) {
|
|
|
29410
29466
|
}
|
|
29411
29467
|
const fileContent = readFileSync3(fp, "utf8");
|
|
29412
29468
|
const fileHash = hashSection(fileContent);
|
|
29413
|
-
const expected = LORE_FILE_HEADER + "\n" + buildSection(
|
|
29469
|
+
const expected = LORE_FILE_HEADER + "\n" + buildSection(projectPath2);
|
|
29414
29470
|
const expectedHash = hashSection(expected);
|
|
29415
29471
|
if (fileHash === expectedHash) {
|
|
29416
29472
|
setCache(fp, { mtimeMs, hash: fileHash });
|
|
@@ -29418,13 +29474,14 @@ function shouldImportLoreFile(projectPath) {
|
|
|
29418
29474
|
}
|
|
29419
29475
|
return true;
|
|
29420
29476
|
}
|
|
29421
|
-
function importLoreFile(
|
|
29422
|
-
|
|
29477
|
+
function importLoreFile(projectPath2) {
|
|
29478
|
+
if (isHostedMode()) return;
|
|
29479
|
+
const fp = join7(projectPath2, LORE_FILE);
|
|
29423
29480
|
if (!existsSync4(fp)) return;
|
|
29424
29481
|
const fileContent = readFileSync3(fp, "utf8");
|
|
29425
29482
|
const fileEntries = parseEntriesFromSection(fileContent);
|
|
29426
29483
|
if (!fileEntries.length) return;
|
|
29427
|
-
_importEntries(fileEntries,
|
|
29484
|
+
_importEntries(fileEntries, projectPath2);
|
|
29428
29485
|
try {
|
|
29429
29486
|
const { mtimeMs } = statSync3(fp);
|
|
29430
29487
|
setCache(fp, { mtimeMs, hash: hashSection(fileContent) });
|
|
@@ -29443,8 +29500,8 @@ function listProjects() {
|
|
|
29443
29500
|
FROM projects p ORDER BY p.created_at DESC`
|
|
29444
29501
|
).all();
|
|
29445
29502
|
}
|
|
29446
|
-
function listSessions(
|
|
29447
|
-
const pid = ensureProject(
|
|
29503
|
+
function listSessions(projectPath2, limit = 50) {
|
|
29504
|
+
const pid = ensureProject(projectPath2);
|
|
29448
29505
|
return db().query(
|
|
29449
29506
|
`SELECT
|
|
29450
29507
|
session_id,
|
|
@@ -29463,8 +29520,8 @@ function listSessions(projectPath, limit = 50) {
|
|
|
29463
29520
|
LIMIT ?`
|
|
29464
29521
|
).all(pid, limit);
|
|
29465
29522
|
}
|
|
29466
|
-
function listDistillations(
|
|
29467
|
-
const pid = ensureProject(
|
|
29523
|
+
function listDistillations(projectPath2, opts) {
|
|
29524
|
+
const pid = ensureProject(projectPath2);
|
|
29468
29525
|
const limit = opts?.limit ?? 50;
|
|
29469
29526
|
if (opts?.sessionId) {
|
|
29470
29527
|
return db().query(
|
|
@@ -29513,8 +29570,8 @@ function globalStats() {
|
|
|
29513
29570
|
}
|
|
29514
29571
|
return { ...row, db_size_bytes };
|
|
29515
29572
|
}
|
|
29516
|
-
function countForProject(
|
|
29517
|
-
const pid = projectId(
|
|
29573
|
+
function countForProject(projectPath2) {
|
|
29574
|
+
const pid = projectId(projectPath2);
|
|
29518
29575
|
if (!pid)
|
|
29519
29576
|
return { knowledge: 0, messages: 0, distillations: 0, sessions: 0 };
|
|
29520
29577
|
const row = db().query(
|
|
@@ -29526,8 +29583,8 @@ function countForProject(projectPath) {
|
|
|
29526
29583
|
).get(pid, pid, pid, pid);
|
|
29527
29584
|
return row;
|
|
29528
29585
|
}
|
|
29529
|
-
function clearProject(
|
|
29530
|
-
const pid = ensureProject(
|
|
29586
|
+
function clearProject(projectPath2) {
|
|
29587
|
+
const pid = ensureProject(projectPath2);
|
|
29531
29588
|
const database = db();
|
|
29532
29589
|
const counts = {
|
|
29533
29590
|
knowledge: database.query(
|
|
@@ -29558,9 +29615,9 @@ function clearProject(projectPath) {
|
|
|
29558
29615
|
database.exec("ROLLBACK");
|
|
29559
29616
|
throw e;
|
|
29560
29617
|
}
|
|
29561
|
-
if (existsSync5(
|
|
29618
|
+
if (existsSync5(projectPath2)) {
|
|
29562
29619
|
try {
|
|
29563
|
-
exportLoreFile(
|
|
29620
|
+
exportLoreFile(projectPath2);
|
|
29564
29621
|
} catch {
|
|
29565
29622
|
}
|
|
29566
29623
|
}
|
|
@@ -29623,30 +29680,30 @@ function renameProject(projectId2, newName) {
|
|
|
29623
29680
|
const result = db().query("UPDATE projects SET name = ? WHERE id = ?").run(newName.trim(), projectId2);
|
|
29624
29681
|
return result.changes > 0;
|
|
29625
29682
|
}
|
|
29626
|
-
function clearKnowledge(
|
|
29627
|
-
const pid = ensureProject(
|
|
29683
|
+
function clearKnowledge(projectPath2) {
|
|
29684
|
+
const pid = ensureProject(projectPath2);
|
|
29628
29685
|
const count3 = db().query(
|
|
29629
29686
|
"SELECT COUNT(*) as c FROM knowledge WHERE project_id = ?"
|
|
29630
29687
|
).get(pid).c;
|
|
29631
29688
|
db().query("DELETE FROM knowledge WHERE project_id = ?").run(pid);
|
|
29632
|
-
if (existsSync5(
|
|
29689
|
+
if (existsSync5(projectPath2)) {
|
|
29633
29690
|
try {
|
|
29634
|
-
exportLoreFile(
|
|
29691
|
+
exportLoreFile(projectPath2);
|
|
29635
29692
|
} catch {
|
|
29636
29693
|
}
|
|
29637
29694
|
}
|
|
29638
29695
|
return count3;
|
|
29639
29696
|
}
|
|
29640
|
-
function clearTemporal(
|
|
29641
|
-
const pid = ensureProject(
|
|
29697
|
+
function clearTemporal(projectPath2) {
|
|
29698
|
+
const pid = ensureProject(projectPath2);
|
|
29642
29699
|
const count3 = db().query(
|
|
29643
29700
|
"SELECT COUNT(*) as c FROM temporal_messages WHERE project_id = ?"
|
|
29644
29701
|
).get(pid).c;
|
|
29645
29702
|
db().query("DELETE FROM temporal_messages WHERE project_id = ?").run(pid);
|
|
29646
29703
|
return count3;
|
|
29647
29704
|
}
|
|
29648
|
-
function clearDistillations(
|
|
29649
|
-
const pid = ensureProject(
|
|
29705
|
+
function clearDistillations(projectPath2) {
|
|
29706
|
+
const pid = ensureProject(projectPath2);
|
|
29650
29707
|
const count3 = db().query(
|
|
29651
29708
|
"SELECT COUNT(*) as c FROM distillations WHERE project_id = ?"
|
|
29652
29709
|
).get(pid).c;
|
|
@@ -29665,8 +29722,8 @@ function deleteDistillation(id) {
|
|
|
29665
29722
|
db().query("DELETE FROM distillations WHERE id = ?").run(id);
|
|
29666
29723
|
return true;
|
|
29667
29724
|
}
|
|
29668
|
-
function deleteSession(
|
|
29669
|
-
const pid = ensureProject(
|
|
29725
|
+
function deleteSession(projectPath2, sessionId) {
|
|
29726
|
+
const pid = ensureProject(projectPath2);
|
|
29670
29727
|
const database = db();
|
|
29671
29728
|
const msgCount = database.query(
|
|
29672
29729
|
"SELECT COUNT(*) as c FROM temporal_messages WHERE project_id = ? AND session_id = ?"
|
|
@@ -29910,9 +29967,22 @@ function setMaxContextTokens(tokens) {
|
|
|
29910
29967
|
function getMaxContextTokens() {
|
|
29911
29968
|
return maxContextTokensCeiling;
|
|
29912
29969
|
}
|
|
29913
|
-
function updateBustRate(cacheWrite, cacheRead, sessionID) {
|
|
29970
|
+
function updateBustRate(cacheWrite, cacheRead, sessionID, lastLayer) {
|
|
29914
29971
|
if (!sessionID) return;
|
|
29915
29972
|
const state = getSessionState(sessionID);
|
|
29973
|
+
if (lastLayer === 4) {
|
|
29974
|
+
state.consecutiveLayer4++;
|
|
29975
|
+
if (state.consecutiveLayer4 >= 5 && state.dynamicContextCap > 0 && maxContextTokensCeiling > 0) {
|
|
29976
|
+
state.dynamicContextCap = Math.min(
|
|
29977
|
+
maxContextTokensCeiling,
|
|
29978
|
+
Math.floor(state.dynamicContextCap * 1.1)
|
|
29979
|
+
);
|
|
29980
|
+
}
|
|
29981
|
+
return;
|
|
29982
|
+
}
|
|
29983
|
+
if (lastLayer !== void 0) {
|
|
29984
|
+
state.consecutiveLayer4 = 0;
|
|
29985
|
+
}
|
|
29916
29986
|
const total = cacheWrite + cacheRead;
|
|
29917
29987
|
if (total === 0) return;
|
|
29918
29988
|
const bustRatio = cacheWrite / total;
|
|
@@ -29967,6 +30037,7 @@ function makeSessionState() {
|
|
|
29967
30037
|
cameOutOfIdle: false,
|
|
29968
30038
|
postIdleCompact: false,
|
|
29969
30039
|
consecutiveHighLayer: 0,
|
|
30040
|
+
consecutiveLayer4: 0,
|
|
29970
30041
|
bustRateEMA: -1,
|
|
29971
30042
|
interBustIntervalEMA: -1,
|
|
29972
30043
|
lastBustAt: 0,
|
|
@@ -30069,6 +30140,11 @@ function getLastTransformedCount(sessionID) {
|
|
|
30069
30140
|
function getLastTransformEstimate(sessionID) {
|
|
30070
30141
|
return sessionStates.get(sessionID)?.lastTransformEstimate ?? 0;
|
|
30071
30142
|
}
|
|
30143
|
+
function getLastLayer(sessionID) {
|
|
30144
|
+
if (sessionID) return sessionStates.get(sessionID)?.lastLayer ?? 0;
|
|
30145
|
+
const first = sessionStates.values().next().value;
|
|
30146
|
+
return first?.lastLayer ?? 0;
|
|
30147
|
+
}
|
|
30072
30148
|
function setForceMinLayer(layer, sessionID) {
|
|
30073
30149
|
if (sessionID) {
|
|
30074
30150
|
getSessionState(sessionID).forceMinLayer = layer;
|
|
@@ -30089,7 +30165,10 @@ function inspectSessionState(sessionID) {
|
|
|
30089
30165
|
cameOutOfIdle: state.cameOutOfIdle,
|
|
30090
30166
|
postIdleCompact: state.postIdleCompact,
|
|
30091
30167
|
lastTurnAt: state.lastTurnAt,
|
|
30092
|
-
distillationSnapshot: state.distillationSnapshot
|
|
30168
|
+
distillationSnapshot: state.distillationSnapshot,
|
|
30169
|
+
bustRateEMA: state.bustRateEMA,
|
|
30170
|
+
dynamicContextCap: state.dynamicContextCap,
|
|
30171
|
+
consecutiveLayer4: state.consecutiveLayer4
|
|
30093
30172
|
};
|
|
30094
30173
|
}
|
|
30095
30174
|
function setLastTurnAtForTest(sessionID, ms) {
|
|
@@ -30108,13 +30187,13 @@ function saveGradientState(sessionID) {
|
|
|
30108
30187
|
lastBustAt: state.lastBustAt
|
|
30109
30188
|
});
|
|
30110
30189
|
}
|
|
30111
|
-
function loadDistillations(
|
|
30112
|
-
const pid = ensureProject(
|
|
30190
|
+
function loadDistillations(projectPath2, sessionID) {
|
|
30191
|
+
const pid = ensureProject(projectPath2);
|
|
30113
30192
|
const query = sessionID ? "SELECT id, observations, generation, token_count, created_at, session_id FROM distillations WHERE project_id = ? AND session_id = ? AND archived = 0 ORDER BY created_at ASC" : "SELECT id, observations, generation, token_count, created_at, session_id FROM distillations WHERE project_id = ? AND archived = 0 ORDER BY created_at ASC";
|
|
30114
30193
|
const params = sessionID ? [pid, sessionID] : [pid];
|
|
30115
30194
|
return db().query(query).all(...params);
|
|
30116
30195
|
}
|
|
30117
|
-
function loadDistillationsCached(
|
|
30196
|
+
function loadDistillationsCached(projectPath2, sessionID, messages, sessState) {
|
|
30118
30197
|
let lastUserMsgId = null;
|
|
30119
30198
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
30120
30199
|
if (messages[i].info.role === "user") {
|
|
@@ -30126,7 +30205,7 @@ function loadDistillationsCached(projectPath, sessionID, messages, sessState) {
|
|
|
30126
30205
|
if (snapshot && snapshot.lastUserMsgId === lastUserMsgId) {
|
|
30127
30206
|
return snapshot.rows;
|
|
30128
30207
|
}
|
|
30129
|
-
const rows = loadDistillations(
|
|
30208
|
+
const rows = loadDistillations(projectPath2, sessionID);
|
|
30130
30209
|
sessState.distillationSnapshot = { rows, lastUserMsgId };
|
|
30131
30210
|
info(
|
|
30132
30211
|
`distillation refresh: ${rows.length} rows (user msg ${lastUserMsgId?.substring(0, 16) ?? "none"})`
|
|
@@ -31110,18 +31189,18 @@ function parseDistillationResult(text4) {
|
|
|
31110
31189
|
if (!observations) return null;
|
|
31111
31190
|
return { observations };
|
|
31112
31191
|
}
|
|
31113
|
-
function latestObservations(
|
|
31114
|
-
const pid = ensureProject(
|
|
31192
|
+
function latestObservations(projectPath2, sessionID) {
|
|
31193
|
+
const pid = ensureProject(projectPath2);
|
|
31115
31194
|
const row = db().query(
|
|
31116
31195
|
"SELECT observations FROM distillations WHERE project_id = ? AND session_id = ? ORDER BY created_at DESC LIMIT 1"
|
|
31117
31196
|
).get(pid, sessionID);
|
|
31118
31197
|
return row?.observations || void 0;
|
|
31119
31198
|
}
|
|
31120
|
-
function latestMetaObservations(
|
|
31121
|
-
return latestMeta(
|
|
31199
|
+
function latestMetaObservations(projectPath2, sessionID) {
|
|
31200
|
+
return latestMeta(projectPath2, sessionID)?.observations;
|
|
31122
31201
|
}
|
|
31123
|
-
function latestMeta(
|
|
31124
|
-
const pid = ensureProject(
|
|
31202
|
+
function latestMeta(projectPath2, sessionID) {
|
|
31203
|
+
const pid = ensureProject(projectPath2);
|
|
31125
31204
|
const row = db().query(
|
|
31126
31205
|
`SELECT observations, generation FROM distillations
|
|
31127
31206
|
WHERE project_id = ? AND session_id = ? AND generation > 0
|
|
@@ -31139,8 +31218,8 @@ function parseSourceIds(raw) {
|
|
|
31139
31218
|
return [];
|
|
31140
31219
|
}
|
|
31141
31220
|
}
|
|
31142
|
-
function loadForSession(
|
|
31143
|
-
const pid = ensureProject(
|
|
31221
|
+
function loadForSession(projectPath2, sessionID, includeArchived = false) {
|
|
31222
|
+
const pid = ensureProject(projectPath2);
|
|
31144
31223
|
const sql = includeArchived ? "SELECT id, project_id, session_id, observations, source_ids, generation, token_count, created_at, r_compression, c_norm FROM distillations WHERE project_id = ? AND session_id = ? ORDER BY created_at ASC" : "SELECT id, project_id, session_id, observations, source_ids, generation, token_count, created_at, r_compression, c_norm FROM distillations WHERE project_id = ? AND session_id = ? AND archived = 0 ORDER BY created_at ASC";
|
|
31145
31224
|
const rows = db().query(sql).all(pid, sessionID);
|
|
31146
31225
|
return rows.map((r) => ({
|
|
@@ -31175,14 +31254,14 @@ function storeDistillation(input) {
|
|
|
31175
31254
|
);
|
|
31176
31255
|
return id;
|
|
31177
31256
|
}
|
|
31178
|
-
function gen0Count(
|
|
31179
|
-
const pid = ensureProject(
|
|
31257
|
+
function gen0Count(projectPath2, sessionID) {
|
|
31258
|
+
const pid = ensureProject(projectPath2);
|
|
31180
31259
|
return db().query(
|
|
31181
31260
|
"SELECT COUNT(*) as count FROM distillations WHERE project_id = ? AND session_id = ? AND generation = 0 AND archived = 0"
|
|
31182
31261
|
).get(pid, sessionID).count;
|
|
31183
31262
|
}
|
|
31184
|
-
function loadGen0(
|
|
31185
|
-
const pid = ensureProject(
|
|
31263
|
+
function loadGen0(projectPath2, sessionID) {
|
|
31264
|
+
const pid = ensureProject(projectPath2);
|
|
31186
31265
|
const rows = db().query(
|
|
31187
31266
|
"SELECT id, project_id, session_id, observations, source_ids, generation, token_count, created_at, r_compression, c_norm FROM distillations WHERE project_id = ? AND session_id = ? AND generation = 0 AND archived = 0 ORDER BY created_at ASC"
|
|
31188
31267
|
).all(pid, sessionID);
|
|
@@ -31198,8 +31277,8 @@ function archiveDistillations(ids) {
|
|
|
31198
31277
|
`UPDATE distillations SET archived = 1 WHERE id IN (${placeholders})`
|
|
31199
31278
|
).run(...ids);
|
|
31200
31279
|
}
|
|
31201
|
-
function resetOrphans(
|
|
31202
|
-
const pid = ensureProject(
|
|
31280
|
+
function resetOrphans(projectPath2, sessionID) {
|
|
31281
|
+
const pid = ensureProject(projectPath2);
|
|
31203
31282
|
const rows = db().query(
|
|
31204
31283
|
"SELECT source_ids FROM distillations WHERE project_id = ? AND session_id = ?"
|
|
31205
31284
|
).all(pid, sessionID);
|
|
@@ -31831,11 +31910,11 @@ function clearProviders() {
|
|
|
31831
31910
|
}
|
|
31832
31911
|
|
|
31833
31912
|
// src/import/detect.ts
|
|
31834
|
-
function detectAll(
|
|
31913
|
+
function detectAll(projectPath2) {
|
|
31835
31914
|
const results = [];
|
|
31836
31915
|
for (const provider of getProviders()) {
|
|
31837
31916
|
try {
|
|
31838
|
-
const sessions = provider.detect(
|
|
31917
|
+
const sessions = provider.detect(projectPath2);
|
|
31839
31918
|
if (sessions.length > 0) {
|
|
31840
31919
|
results.push({
|
|
31841
31920
|
agentName: provider.name,
|
|
@@ -31924,8 +32003,8 @@ async function extractKnowledge(input) {
|
|
|
31924
32003
|
}
|
|
31925
32004
|
|
|
31926
32005
|
// src/import/history.ts
|
|
31927
|
-
function isImported(
|
|
31928
|
-
const projectId2 = ensureProject(
|
|
32006
|
+
function isImported(projectPath2, agentName, sourceId, sourceHash) {
|
|
32007
|
+
const projectId2 = ensureProject(projectPath2);
|
|
31929
32008
|
const row = db().query(
|
|
31930
32009
|
`SELECT * FROM import_history
|
|
31931
32010
|
WHERE project_id = ? AND agent_name = ? AND source_id = ?`
|
|
@@ -31934,8 +32013,8 @@ function isImported(projectPath, agentName, sourceId, sourceHash) {
|
|
|
31934
32013
|
if (row.source_hash !== sourceHash) return null;
|
|
31935
32014
|
return row;
|
|
31936
32015
|
}
|
|
31937
|
-
function recordImport(
|
|
31938
|
-
const projectId2 = ensureProject(
|
|
32016
|
+
function recordImport(projectPath2, agentName, sourceId, sourceHash, stats) {
|
|
32017
|
+
const projectId2 = ensureProject(projectPath2);
|
|
31939
32018
|
db().query(
|
|
31940
32019
|
`INSERT OR REPLACE INTO import_history
|
|
31941
32020
|
(id, project_id, agent_name, source_id, source_hash, entries_created, entries_updated, imported_at)
|
|
@@ -31951,8 +32030,8 @@ function recordImport(projectPath, agentName, sourceId, sourceHash, stats) {
|
|
|
31951
32030
|
Date.now()
|
|
31952
32031
|
);
|
|
31953
32032
|
}
|
|
31954
|
-
function listImports(
|
|
31955
|
-
const projectId2 = ensureProject(
|
|
32033
|
+
function listImports(projectPath2) {
|
|
32034
|
+
const projectId2 = ensureProject(projectPath2);
|
|
31956
32035
|
return db().query(
|
|
31957
32036
|
`SELECT * FROM import_history
|
|
31958
32037
|
WHERE project_id = ? AND source_id != '__declined__'
|
|
@@ -31970,8 +32049,8 @@ import { homedir as homedir2 } from "os";
|
|
|
31970
32049
|
var CLAUDE_DIR = join8(homedir2(), ".claude", "projects");
|
|
31971
32050
|
var MAX_TOOL_OUTPUT_CHARS = 500;
|
|
31972
32051
|
var DEFAULT_MAX_TOKENS = 12288;
|
|
31973
|
-
function manglePath(
|
|
31974
|
-
return
|
|
32052
|
+
function manglePath(projectPath2) {
|
|
32053
|
+
return projectPath2.replace(/\//g, "-");
|
|
31975
32054
|
}
|
|
31976
32055
|
function estimateTokens4(text4) {
|
|
31977
32056
|
return Math.ceil(text4.length / 3);
|
|
@@ -32085,8 +32164,8 @@ function getSessionMetadata(filePath) {
|
|
|
32085
32164
|
var claudeCodeProvider = {
|
|
32086
32165
|
name: "claude-code",
|
|
32087
32166
|
displayName: "Claude Code",
|
|
32088
|
-
detect(
|
|
32089
|
-
const mangled = manglePath(
|
|
32167
|
+
detect(projectPath2) {
|
|
32168
|
+
const mangled = manglePath(projectPath2);
|
|
32090
32169
|
const dir = join8(CLAUDE_DIR, mangled);
|
|
32091
32170
|
let entries;
|
|
32092
32171
|
try {
|
|
@@ -32284,7 +32363,7 @@ function getSessionMeta(filePath) {
|
|
|
32284
32363
|
var codexProvider = {
|
|
32285
32364
|
name: "codex",
|
|
32286
32365
|
displayName: "Codex",
|
|
32287
|
-
detect(
|
|
32366
|
+
detect(projectPath2) {
|
|
32288
32367
|
const sessions = [];
|
|
32289
32368
|
const allFiles = [
|
|
32290
32369
|
...findJsonlFiles(SESSIONS_DIR),
|
|
@@ -32293,7 +32372,7 @@ var codexProvider = {
|
|
|
32293
32372
|
for (const filePath of allFiles) {
|
|
32294
32373
|
const meta3 = getSessionMeta(filePath);
|
|
32295
32374
|
if (!meta3) continue;
|
|
32296
|
-
if (meta3.cwd !==
|
|
32375
|
+
if (meta3.cwd !== projectPath2) continue;
|
|
32297
32376
|
if (meta3.messageCount < 3) continue;
|
|
32298
32377
|
const ts = new Date(meta3.timestamp).getTime();
|
|
32299
32378
|
const estimatedTokens = Math.ceil(meta3.fileSize / 5);
|
|
@@ -32425,14 +32504,14 @@ function partsToConversationText(parts) {
|
|
|
32425
32504
|
var opencodeProvider = {
|
|
32426
32505
|
name: "opencode",
|
|
32427
32506
|
displayName: "OpenCode",
|
|
32428
|
-
detect(
|
|
32507
|
+
detect(projectPath2) {
|
|
32429
32508
|
const database = openDB();
|
|
32430
32509
|
if (!database) return [];
|
|
32431
32510
|
try {
|
|
32432
32511
|
if (!tableExists(database, "project") || !tableExists(database, "session") || !tableExists(database, "message")) {
|
|
32433
32512
|
return [];
|
|
32434
32513
|
}
|
|
32435
|
-
const project = database.query("SELECT id FROM project WHERE worktree = ?").get(
|
|
32514
|
+
const project = database.query("SELECT id FROM project WHERE worktree = ?").get(projectPath2);
|
|
32436
32515
|
if (!project) return [];
|
|
32437
32516
|
const sessions = database.query(
|
|
32438
32517
|
`SELECT s.id, s.title, s.time_created, s.time_updated,
|
|
@@ -32597,7 +32676,7 @@ function findGlobalStorageDirs() {
|
|
|
32597
32676
|
}
|
|
32598
32677
|
return dirs;
|
|
32599
32678
|
}
|
|
32600
|
-
function loadTaskHistory(storageDir,
|
|
32679
|
+
function loadTaskHistory(storageDir, projectPath2) {
|
|
32601
32680
|
const paths = [
|
|
32602
32681
|
join11(storageDir, "state", "taskHistory.json"),
|
|
32603
32682
|
join11(storageDir, "taskHistory.json")
|
|
@@ -32609,7 +32688,7 @@ function loadTaskHistory(storageDir, projectPath) {
|
|
|
32609
32688
|
const items = JSON.parse(raw);
|
|
32610
32689
|
if (!Array.isArray(items)) continue;
|
|
32611
32690
|
return items.filter(
|
|
32612
|
-
(item) => item.cwdOnTaskInitialization ===
|
|
32691
|
+
(item) => item.cwdOnTaskInitialization === projectPath2
|
|
32613
32692
|
);
|
|
32614
32693
|
} catch {
|
|
32615
32694
|
continue;
|
|
@@ -32662,11 +32741,11 @@ function messageToText(msg) {
|
|
|
32662
32741
|
var clineProvider = {
|
|
32663
32742
|
name: "cline",
|
|
32664
32743
|
displayName: "Cline",
|
|
32665
|
-
detect(
|
|
32744
|
+
detect(projectPath2) {
|
|
32666
32745
|
const sessions = [];
|
|
32667
32746
|
const storageDirs = findGlobalStorageDirs();
|
|
32668
32747
|
for (const storageDir of storageDirs) {
|
|
32669
|
-
const tasks = loadTaskHistory(storageDir,
|
|
32748
|
+
const tasks = loadTaskHistory(storageDir, projectPath2);
|
|
32670
32749
|
for (const task of tasks) {
|
|
32671
32750
|
const taskDir = join11(storageDir, "tasks", task.id);
|
|
32672
32751
|
if (!existsSync8(taskDir)) continue;
|
|
@@ -32814,11 +32893,11 @@ function historyItemToText(item) {
|
|
|
32814
32893
|
var continueProvider = {
|
|
32815
32894
|
name: "continue",
|
|
32816
32895
|
displayName: "Continue",
|
|
32817
|
-
detect(
|
|
32896
|
+
detect(projectPath2) {
|
|
32818
32897
|
const sessions = [];
|
|
32819
32898
|
const index2 = loadSessionIndex();
|
|
32820
32899
|
for (const meta3 of index2) {
|
|
32821
|
-
if (meta3.workspaceDirectory !==
|
|
32900
|
+
if (meta3.workspaceDirectory !== projectPath2) continue;
|
|
32822
32901
|
const session = loadSession(meta3.sessionId);
|
|
32823
32902
|
if (!session || !session.history || session.history.length < 3) continue;
|
|
32824
32903
|
const ts = new Date(meta3.dateCreated).getTime();
|
|
@@ -32850,7 +32929,7 @@ var continueProvider = {
|
|
|
32850
32929
|
if (existingIds.has(sessionId)) continue;
|
|
32851
32930
|
const session = loadSession(sessionId);
|
|
32852
32931
|
if (!session) continue;
|
|
32853
|
-
if (session.workspaceDirectory !==
|
|
32932
|
+
if (session.workspaceDirectory !== projectPath2) continue;
|
|
32854
32933
|
if (!session.history || session.history.length < 3) continue;
|
|
32855
32934
|
const dateStr = session.title ? truncate5(session.title, 60) : sessionId.slice(0, 8);
|
|
32856
32935
|
sessions.push({
|
|
@@ -32999,8 +33078,8 @@ function getSessionMeta2(filePath) {
|
|
|
32999
33078
|
var piProvider = {
|
|
33000
33079
|
name: "pi",
|
|
33001
33080
|
displayName: "Pi",
|
|
33002
|
-
detect(
|
|
33003
|
-
const encoded = encodeCwd(
|
|
33081
|
+
detect(projectPath2) {
|
|
33082
|
+
const encoded = encodeCwd(projectPath2);
|
|
33004
33083
|
const dir = join13(PI_DIR, encoded);
|
|
33005
33084
|
let entries;
|
|
33006
33085
|
try {
|
|
@@ -33138,8 +33217,8 @@ function parseAiderHistory(content3) {
|
|
|
33138
33217
|
var aiderProvider = {
|
|
33139
33218
|
name: "aider",
|
|
33140
33219
|
displayName: "Aider",
|
|
33141
|
-
detect(
|
|
33142
|
-
const filePath = join14(
|
|
33220
|
+
detect(projectPath2) {
|
|
33221
|
+
const filePath = join14(projectPath2, HISTORY_FILE);
|
|
33143
33222
|
if (!existsSync11(filePath)) return [];
|
|
33144
33223
|
let stat;
|
|
33145
33224
|
try {
|
|
@@ -33168,7 +33247,7 @@ var aiderProvider = {
|
|
|
33168
33247
|
}
|
|
33169
33248
|
];
|
|
33170
33249
|
},
|
|
33171
|
-
readChunks(
|
|
33250
|
+
readChunks(projectPath2, sessionIds, maxTokens = DEFAULT_MAX_TOKENS7) {
|
|
33172
33251
|
const chunks = [];
|
|
33173
33252
|
for (const filePath of sessionIds) {
|
|
33174
33253
|
let content3;
|
|
@@ -33463,7 +33542,7 @@ async function searchRecall(input) {
|
|
|
33463
33542
|
const {
|
|
33464
33543
|
query,
|
|
33465
33544
|
scope = "all",
|
|
33466
|
-
projectPath,
|
|
33545
|
+
projectPath: projectPath2,
|
|
33467
33546
|
sessionID,
|
|
33468
33547
|
knowledgeEnabled = true,
|
|
33469
33548
|
llm,
|
|
@@ -33490,7 +33569,7 @@ async function searchRecall(input) {
|
|
|
33490
33569
|
if (knowledgeEnabled && scope !== "session") {
|
|
33491
33570
|
try {
|
|
33492
33571
|
knowledgeResults.push(
|
|
33493
|
-
...searchScored3({ query: q, projectPath, limit })
|
|
33572
|
+
...searchScored3({ query: q, projectPath: projectPath2, limit })
|
|
33494
33573
|
);
|
|
33495
33574
|
} catch (err) {
|
|
33496
33575
|
error("recall: knowledge search failed:", err);
|
|
@@ -33501,7 +33580,7 @@ async function searchRecall(input) {
|
|
|
33501
33580
|
try {
|
|
33502
33581
|
distillationResults.push(
|
|
33503
33582
|
...searchDistillationsScored({
|
|
33504
|
-
projectPath,
|
|
33583
|
+
projectPath: projectPath2,
|
|
33505
33584
|
query: q,
|
|
33506
33585
|
sessionID: scope === "session" ? sessionID : void 0,
|
|
33507
33586
|
limit
|
|
@@ -33516,7 +33595,7 @@ async function searchRecall(input) {
|
|
|
33516
33595
|
try {
|
|
33517
33596
|
temporalResults.push(
|
|
33518
33597
|
...searchScored({
|
|
33519
|
-
projectPath,
|
|
33598
|
+
projectPath: projectPath2,
|
|
33520
33599
|
query: q,
|
|
33521
33600
|
sessionID: scope === "session" ? sessionID : void 0,
|
|
33522
33601
|
limit
|
|
@@ -33610,7 +33689,7 @@ async function searchRecall(input) {
|
|
|
33610
33689
|
}
|
|
33611
33690
|
}
|
|
33612
33691
|
if (scope !== "knowledge") {
|
|
33613
|
-
const pid = ensureProject(
|
|
33692
|
+
const pid = ensureProject(projectPath2);
|
|
33614
33693
|
const temporalVectorHits = vectorSearchTemporal(
|
|
33615
33694
|
queryVec,
|
|
33616
33695
|
pid,
|
|
@@ -33638,11 +33717,11 @@ async function searchRecall(input) {
|
|
|
33638
33717
|
info("recall: vector search failed:", err);
|
|
33639
33718
|
}
|
|
33640
33719
|
}
|
|
33641
|
-
if (scope !== "session" && hasLatDir(
|
|
33720
|
+
if (scope !== "session" && hasLatDir(projectPath2)) {
|
|
33642
33721
|
try {
|
|
33643
33722
|
const latResults = searchScored2({
|
|
33644
33723
|
query,
|
|
33645
|
-
projectPath,
|
|
33724
|
+
projectPath: projectPath2,
|
|
33646
33725
|
limit
|
|
33647
33726
|
});
|
|
33648
33727
|
if (latResults.length) {
|
|
@@ -33662,7 +33741,7 @@ async function searchRecall(input) {
|
|
|
33662
33741
|
try {
|
|
33663
33742
|
const crossProjectResults = searchScoredOtherProjects({
|
|
33664
33743
|
query,
|
|
33665
|
-
excludeProjectPath:
|
|
33744
|
+
excludeProjectPath: projectPath2,
|
|
33666
33745
|
limit
|
|
33667
33746
|
});
|
|
33668
33747
|
if (crossProjectResults.length) {
|
|
@@ -33868,6 +33947,7 @@ export {
|
|
|
33868
33947
|
distillationUser,
|
|
33869
33948
|
embedding_exports as embedding,
|
|
33870
33949
|
embedding_vendor_exports as embeddingVendor,
|
|
33950
|
+
enableHostedMode,
|
|
33871
33951
|
ensureProject,
|
|
33872
33952
|
exactTermMatchRank,
|
|
33873
33953
|
expandQuery,
|
|
@@ -33883,6 +33963,7 @@ export {
|
|
|
33883
33963
|
getInstanceId,
|
|
33884
33964
|
getKV,
|
|
33885
33965
|
getLastImportAt,
|
|
33966
|
+
getLastLayer,
|
|
33886
33967
|
getLastTransformEstimate,
|
|
33887
33968
|
getLastTransformedCount,
|
|
33888
33969
|
getLastTurnAt,
|
|
@@ -33897,6 +33978,7 @@ export {
|
|
|
33897
33978
|
inspectSessionState,
|
|
33898
33979
|
instruction_detect_exports as instructionDetect,
|
|
33899
33980
|
isFirstRun,
|
|
33981
|
+
isHostedMode,
|
|
33900
33982
|
isReasoningPart,
|
|
33901
33983
|
isTextPart,
|
|
33902
33984
|
isToolPart,
|
|
@@ -33922,10 +34004,12 @@ export {
|
|
|
33922
34004
|
pattern_extract_exports as patternExtract,
|
|
33923
34005
|
projectId,
|
|
33924
34006
|
projectName,
|
|
34007
|
+
projectPath,
|
|
33925
34008
|
recallById,
|
|
33926
34009
|
reciprocalRankFusion,
|
|
33927
34010
|
recursiveUser,
|
|
33928
34011
|
renderMarkdown,
|
|
34012
|
+
resolveProjectByRemoteOrPath,
|
|
33929
34013
|
root2 as root,
|
|
33930
34014
|
runRecall,
|
|
33931
34015
|
sanitizeSurrogates,
|