chat-recall 0.7.1 → 0.7.3
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/cli.js +97 -65
- package/dist/code-index-cursor.d.ts +20 -3
- package/dist/code-index-cursor.d.ts.map +1 -1
- package/dist/code-index-cursor.js +53 -8
- package/dist/code-index-cursor.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +96 -65
- package/dist/scan-worker.js +78 -52
- package/dist/sync-client.js +3 -3
- package/dist/sync-client.js.map +1 -1
- package/dist/watch.js +167 -93
- package/package.json +1 -1
package/dist/watch.js
CHANGED
|
@@ -8199,12 +8199,12 @@ var init_claude2 = __esm({
|
|
|
8199
8199
|
const seen = /* @__PURE__ */ new Set();
|
|
8200
8200
|
const out = [];
|
|
8201
8201
|
for (const root of claudeProjectDirs()) {
|
|
8202
|
-
this.collectSessionsFromRoot(root, cutoff, filter, seen, out);
|
|
8202
|
+
this.collectSessionsFromRoot(root, cutoff, filter, seen, out, opts.previews !== false);
|
|
8203
8203
|
}
|
|
8204
8204
|
out.sort((a, b) => b.mtime - a.mtime);
|
|
8205
8205
|
return opts.limit ? out.slice(0, opts.limit) : out;
|
|
8206
8206
|
}
|
|
8207
|
-
collectSessionsFromRoot(root, cutoff, filter, seen, out) {
|
|
8207
|
+
collectSessionsFromRoot(root, cutoff, filter, seen, out, previews) {
|
|
8208
8208
|
if (!existsSync10(root))
|
|
8209
8209
|
return;
|
|
8210
8210
|
for (const proj of readdirSync7(root, { withFileTypes: true })) {
|
|
@@ -8263,7 +8263,7 @@ var init_claude2 = __esm({
|
|
|
8263
8263
|
}
|
|
8264
8264
|
if (stat3.mtimeMs < cutoff)
|
|
8265
8265
|
continue;
|
|
8266
|
-
const firstPrompt = extractFirstUserPromptSync(fullPath, { maxLength: 200 });
|
|
8266
|
+
const firstPrompt = previews ? extractFirstUserPromptSync(fullPath, { maxLength: 200 }) : "";
|
|
8267
8267
|
out.push({
|
|
8268
8268
|
toolId: "claude",
|
|
8269
8269
|
rawId: sessionId,
|
|
@@ -8861,23 +8861,8 @@ var init_opencode = __esm({
|
|
|
8861
8861
|
const projectPath = row.project_path || row.directory || "";
|
|
8862
8862
|
if (filter && !projectPath.toLowerCase().includes(filter))
|
|
8863
8863
|
continue;
|
|
8864
|
-
const
|
|
8865
|
-
|
|
8866
|
-
FROM part p JOIN message m ON m.id = p.message_id
|
|
8867
|
-
WHERE p.session_id = ?
|
|
8868
|
-
AND p.data LIKE '%"type":"text"%'
|
|
8869
|
-
AND m.data LIKE '%"role":"user"%'
|
|
8870
|
-
ORDER BY p.time_created ASC LIMIT 1
|
|
8871
|
-
`).get(row.id);
|
|
8872
|
-
let firstPrompt = "";
|
|
8873
|
-
if (firstUser) {
|
|
8874
|
-
try {
|
|
8875
|
-
const parsed = JSON.parse(firstUser.data);
|
|
8876
|
-
firstPrompt = flatString(String(parsed?.text || "").slice(0, 200));
|
|
8877
|
-
} catch {
|
|
8878
|
-
}
|
|
8879
|
-
}
|
|
8880
|
-
const messageCount = db.prepare("SELECT COUNT(*) as c FROM message WHERE session_id = ?").get(row.id)?.c ?? 0;
|
|
8864
|
+
const firstPrompt = opts.previews === false ? "" : this.firstUserPrompt(db, row.id);
|
|
8865
|
+
const messageCount = opts.previews === false ? 0 : db.prepare("SELECT COUNT(*) as c FROM message WHERE session_id = ?").get(row.id)?.c ?? 0;
|
|
8881
8866
|
const created = new Date(row.time_created || row.time_updated).toISOString();
|
|
8882
8867
|
const modified = new Date(row.time_updated).toISOString();
|
|
8883
8868
|
out.push({
|
|
@@ -8901,6 +8886,45 @@ var init_opencode = __esm({
|
|
|
8901
8886
|
db.close();
|
|
8902
8887
|
}
|
|
8903
8888
|
}
|
|
8889
|
+
/**
|
|
8890
|
+
* The first user text part of a session.
|
|
8891
|
+
*
|
|
8892
|
+
* Walks the session's user messages oldest first through the
|
|
8893
|
+
* (session_id, time_created, id) index and stops at the first one with a
|
|
8894
|
+
* text part. The role and the text are read by SQLite: a first message can
|
|
8895
|
+
* carry whole diffs in `summary` (107 MB on one row), and parsing that in JS
|
|
8896
|
+
* to read one field took the process to 510 MB. The earlier query filtered
|
|
8897
|
+
* every part and message with LIKE and then sorted, so it read all of a
|
|
8898
|
+
* session's data: 423 MB for a 236-session listing.
|
|
8899
|
+
*/
|
|
8900
|
+
firstUserPrompt(db, sessionId) {
|
|
8901
|
+
try {
|
|
8902
|
+
const has = (table, col) => !!db.prepare(`SELECT 1 FROM pragma_table_info(?) WHERE name = ?`).get(table, col);
|
|
8903
|
+
const msgOrder = has("message", "time_created") ? "time_created, id" : "rowid";
|
|
8904
|
+
const partOrder = has("part", "time_created") ? "time_created, id" : "rowid";
|
|
8905
|
+
const nextUser = db.prepare(`SELECT id, ${msgOrder === "rowid" ? "rowid AS k1, 0 AS k2" : "time_created AS k1, id AS k2"} FROM message
|
|
8906
|
+
WHERE session_id = ? AND (${msgOrder === "rowid" ? "rowid, 0" : "time_created, id"}) > (?, ?)
|
|
8907
|
+
AND json_extract(data, '$.role') = 'user'
|
|
8908
|
+
ORDER BY ${msgOrder} LIMIT 1`);
|
|
8909
|
+
const firstText = db.prepare(`SELECT substr(json_extract(data, '$.text'), 1, 400) AS text FROM part
|
|
8910
|
+
WHERE message_id = ? AND json_extract(data, '$.type') = 'text'
|
|
8911
|
+
AND length(trim(json_extract(data, '$.text'))) > 0
|
|
8912
|
+
ORDER BY ${partOrder} LIMIT 1`);
|
|
8913
|
+
let k1 = Number.MIN_SAFE_INTEGER, k2 = msgOrder === "rowid" ? 0 : "";
|
|
8914
|
+
for (; ; ) {
|
|
8915
|
+
const m = nextUser.get(sessionId, k1, k2);
|
|
8916
|
+
if (!m)
|
|
8917
|
+
return "";
|
|
8918
|
+
k1 = m.k1;
|
|
8919
|
+
k2 = m.k2;
|
|
8920
|
+
const t = firstText.get(m.id);
|
|
8921
|
+
if (t?.text)
|
|
8922
|
+
return flatString(t.text.slice(0, 200));
|
|
8923
|
+
}
|
|
8924
|
+
} catch {
|
|
8925
|
+
return "";
|
|
8926
|
+
}
|
|
8927
|
+
}
|
|
8904
8928
|
/** OpenCode auto-generates a session title (model-written, distinct from the
|
|
8905
8929
|
* first prompt — e.g. "Replacing Claude with Gemini CLI"). It's a plain
|
|
8906
8930
|
* column on the session row. */
|
|
@@ -9463,28 +9487,29 @@ var init_codex2 = __esm({
|
|
|
9463
9487
|
continue;
|
|
9464
9488
|
let firstPrompt = "";
|
|
9465
9489
|
let messageCount = 0;
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
|
|
9480
|
-
firstPrompt
|
|
9490
|
+
if (opts.previews !== false)
|
|
9491
|
+
try {
|
|
9492
|
+
const lines = readFileSync6(filePath, "utf-8").split("\n");
|
|
9493
|
+
for (const line of lines) {
|
|
9494
|
+
if (!line.trim())
|
|
9495
|
+
continue;
|
|
9496
|
+
let ev;
|
|
9497
|
+
try {
|
|
9498
|
+
ev = JSON.parse(line);
|
|
9499
|
+
} catch {
|
|
9500
|
+
continue;
|
|
9501
|
+
}
|
|
9502
|
+
if (ev.type === "event_msg" && ev.payload?.type === "user_message") {
|
|
9503
|
+
messageCount++;
|
|
9504
|
+
if (!firstPrompt && ev.payload.message) {
|
|
9505
|
+
firstPrompt = flatString(String(ev.payload.message).slice(0, 200));
|
|
9506
|
+
}
|
|
9507
|
+
} else if (ev.type === "response_item" && ev.payload?.type === "message") {
|
|
9508
|
+
messageCount++;
|
|
9481
9509
|
}
|
|
9482
|
-
} else if (ev.type === "response_item" && ev.payload?.type === "message") {
|
|
9483
|
-
messageCount++;
|
|
9484
9510
|
}
|
|
9511
|
+
} catch {
|
|
9485
9512
|
}
|
|
9486
|
-
} catch {
|
|
9487
|
-
}
|
|
9488
9513
|
const prior = seen.get(rawId);
|
|
9489
9514
|
if (prior) {
|
|
9490
9515
|
if (stat3.mtimeMs > prior.mtime) {
|
|
@@ -10174,21 +10199,22 @@ var init_agy = __esm({
|
|
|
10174
10199
|
const projectDir = projectPath ? basename10(projectPath) : "";
|
|
10175
10200
|
let firstPrompt = "";
|
|
10176
10201
|
let messageCount = 0;
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
const
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10202
|
+
if (opts.previews !== false)
|
|
10203
|
+
try {
|
|
10204
|
+
const lines = readFileSync7(filePath, "utf-8").split("\n").filter(Boolean);
|
|
10205
|
+
messageCount = lines.length;
|
|
10206
|
+
for (const line of lines) {
|
|
10207
|
+
const obj = JSON.parse(line);
|
|
10208
|
+
if (obj.source === "USER_EXPLICIT" && obj.type === "USER_INPUT" && typeof obj.content === "string") {
|
|
10209
|
+
const content = obj.content;
|
|
10210
|
+
const match = content.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
|
|
10211
|
+
const rawText = match ? match[1].trim() : content.trim();
|
|
10212
|
+
firstPrompt = flatString(rawText.slice(0, 200));
|
|
10213
|
+
break;
|
|
10214
|
+
}
|
|
10188
10215
|
}
|
|
10216
|
+
} catch {
|
|
10189
10217
|
}
|
|
10190
|
-
} catch {
|
|
10191
|
-
}
|
|
10192
10218
|
if (seenIds.has(rawId))
|
|
10193
10219
|
continue;
|
|
10194
10220
|
seenIds.add(rawId);
|
|
@@ -13256,12 +13282,13 @@ function resolveProjectId(inputPath) {
|
|
|
13256
13282
|
if (!isAbsolute(inputPath)) {
|
|
13257
13283
|
return { id: `path:${inputPath}`, displayName: inputPath, source: "path" };
|
|
13258
13284
|
}
|
|
13285
|
+
const known = inputCache.get(inputPath);
|
|
13286
|
+
if (known)
|
|
13287
|
+
return known;
|
|
13259
13288
|
const realPath = safeRealpath(inputPath);
|
|
13260
|
-
const
|
|
13261
|
-
if (cached)
|
|
13262
|
-
return cached;
|
|
13263
|
-
const result = doResolve(realPath);
|
|
13289
|
+
const result = resolveCache.get(realPath) ?? doResolve(realPath);
|
|
13264
13290
|
resolveCache.set(realPath, result);
|
|
13291
|
+
inputCache.set(inputPath, result);
|
|
13265
13292
|
return result;
|
|
13266
13293
|
}
|
|
13267
13294
|
function doResolve(realPath) {
|
|
@@ -13540,7 +13567,7 @@ function globToRegex(glob) {
|
|
|
13540
13567
|
function escapeRe(s) {
|
|
13541
13568
|
return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13542
13569
|
}
|
|
13543
|
-
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
|
|
13570
|
+
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, inputCache, gitCache, workspaceCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
|
|
13544
13571
|
var init_project_resolver = __esm({
|
|
13545
13572
|
"../engine/dist/core/project-resolver.js"() {
|
|
13546
13573
|
"use strict";
|
|
@@ -13548,6 +13575,7 @@ var init_project_resolver = __esm({
|
|
|
13548
13575
|
DEFAULT_AUTO_WORKSPACE_MIN_REPOS = 3;
|
|
13549
13576
|
BOT_WORKTREE_MARKERS = [".claude-pr-bot"];
|
|
13550
13577
|
resolveCache = /* @__PURE__ */ new Map();
|
|
13578
|
+
inputCache = /* @__PURE__ */ new Map();
|
|
13551
13579
|
gitCache = /* @__PURE__ */ new Map();
|
|
13552
13580
|
workspaceCache = /* @__PURE__ */ new Map();
|
|
13553
13581
|
cachedConfig = null;
|
|
@@ -18043,7 +18071,7 @@ var init_http = __esm({
|
|
|
18043
18071
|
CLI_VERSION = JSON.parse(readFileSync32(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18044
18072
|
} catch {
|
|
18045
18073
|
try {
|
|
18046
|
-
if (true) CLI_VERSION = "0.7.
|
|
18074
|
+
if (true) CLI_VERSION = "0.7.3";
|
|
18047
18075
|
} catch {
|
|
18048
18076
|
}
|
|
18049
18077
|
}
|
|
@@ -18515,16 +18543,16 @@ async function flush() {
|
|
|
18515
18543
|
}
|
|
18516
18544
|
function stableMark(value) {
|
|
18517
18545
|
try {
|
|
18518
|
-
const { createHash:
|
|
18519
|
-
return
|
|
18546
|
+
const { createHash: createHash14 } = __require("node:crypto");
|
|
18547
|
+
return createHash14("sha256").update(value).digest("hex").slice(0, 12);
|
|
18520
18548
|
} catch {
|
|
18521
18549
|
return "";
|
|
18522
18550
|
}
|
|
18523
18551
|
}
|
|
18524
18552
|
function hashHost() {
|
|
18525
18553
|
try {
|
|
18526
|
-
const { createHash:
|
|
18527
|
-
return
|
|
18554
|
+
const { createHash: createHash14 } = __require("node:crypto");
|
|
18555
|
+
return createHash14("sha256").update(hostname()).digest("hex").slice(0, 12);
|
|
18528
18556
|
} catch {
|
|
18529
18557
|
return "";
|
|
18530
18558
|
}
|
|
@@ -18538,7 +18566,7 @@ var init_telemetry = __esm({
|
|
|
18538
18566
|
init_sync_client();
|
|
18539
18567
|
cliVersion = () => {
|
|
18540
18568
|
try {
|
|
18541
|
-
return true ? "0.7.
|
|
18569
|
+
return true ? "0.7.3" : "dev";
|
|
18542
18570
|
} catch {
|
|
18543
18571
|
return "dev";
|
|
18544
18572
|
}
|
|
@@ -19511,7 +19539,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
19511
19539
|
const listSinceMs = changedWalk ? Math.max(0, (opts.sinceMs ?? 0) - CHANGED_WALK_OVERLAP_MS) : opts.useLedger ? void 0 : opts.sinceMs;
|
|
19512
19540
|
const refs = listAvailableBackends().flatMap((b) => {
|
|
19513
19541
|
try {
|
|
19514
|
-
return b.listSessions({ sinceMs: listSinceMs });
|
|
19542
|
+
return b.listSessions({ sinceMs: listSinceMs, previews: false });
|
|
19515
19543
|
} catch {
|
|
19516
19544
|
return [];
|
|
19517
19545
|
}
|
|
@@ -19826,7 +19854,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
19826
19854
|
cred,
|
|
19827
19855
|
() => listAvailableBackends().flatMap((b) => {
|
|
19828
19856
|
try {
|
|
19829
|
-
return b.listSessions({});
|
|
19857
|
+
return b.listSessions({ previews: false });
|
|
19830
19858
|
} catch {
|
|
19831
19859
|
return [];
|
|
19832
19860
|
}
|
|
@@ -20593,7 +20621,7 @@ var init_sync_client = __esm({
|
|
|
20593
20621
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
20594
20622
|
} catch {
|
|
20595
20623
|
try {
|
|
20596
|
-
if (true) ownVersion = "0.7.
|
|
20624
|
+
if (true) ownVersion = "0.7.3";
|
|
20597
20625
|
} catch {
|
|
20598
20626
|
}
|
|
20599
20627
|
}
|
|
@@ -21770,7 +21798,7 @@ __export(shadow_prune_exports, {
|
|
|
21770
21798
|
DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
|
|
21771
21799
|
pruneShadow: () => pruneShadow
|
|
21772
21800
|
});
|
|
21773
|
-
import { readdirSync as readdirSync33, statSync as
|
|
21801
|
+
import { readdirSync as readdirSync33, statSync as statSync43, unlinkSync as unlinkSync3 } from "fs";
|
|
21774
21802
|
import { join as join50 } from "path";
|
|
21775
21803
|
function listShadows(isFullyAcked) {
|
|
21776
21804
|
const out = [];
|
|
@@ -21795,7 +21823,7 @@ function listShadows(isFullyAcked) {
|
|
|
21795
21823
|
const path = join50(dir, name);
|
|
21796
21824
|
let st;
|
|
21797
21825
|
try {
|
|
21798
|
-
st =
|
|
21826
|
+
st = statSync43(path);
|
|
21799
21827
|
} catch {
|
|
21800
21828
|
continue;
|
|
21801
21829
|
}
|
|
@@ -21867,9 +21895,9 @@ var init_shadow_prune = __esm({
|
|
|
21867
21895
|
});
|
|
21868
21896
|
|
|
21869
21897
|
// ../engine/dist/types/code-intel.js
|
|
21870
|
-
import { createHash as
|
|
21898
|
+
import { createHash as createHash12 } from "crypto";
|
|
21871
21899
|
function shortHash(s) {
|
|
21872
|
-
return
|
|
21900
|
+
return createHash12("sha256").update(s).digest("hex").slice(0, 16);
|
|
21873
21901
|
}
|
|
21874
21902
|
function snippetKey(snippet) {
|
|
21875
21903
|
return (snippet ?? "").replace(/\s+/g, " ").trim().slice(0, 200);
|
|
@@ -21910,11 +21938,11 @@ var init_code_intel = __esm({
|
|
|
21910
21938
|
});
|
|
21911
21939
|
|
|
21912
21940
|
// ../engine/dist/core/companions.js
|
|
21913
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as
|
|
21941
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync44, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync42, writeFileSync as writeFileSync15 } from "node:fs";
|
|
21914
21942
|
import { homedir as homedir19 } from "node:os";
|
|
21915
21943
|
import { join as join51 } from "node:path";
|
|
21916
21944
|
import { execSync as execSync3 } from "node:child_process";
|
|
21917
|
-
import { createHash as
|
|
21945
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
21918
21946
|
function expectedCodeindexSha256(artifact) {
|
|
21919
21947
|
return CODEINDEX_SHA256[artifact.replace(/^codeindex-/, "").replace(/\.exe$/, "")] ?? null;
|
|
21920
21948
|
}
|
|
@@ -21961,7 +21989,7 @@ function checkCodeindexStatus() {
|
|
|
21961
21989
|
status.installed = true;
|
|
21962
21990
|
status.path = foundPath;
|
|
21963
21991
|
try {
|
|
21964
|
-
status.size =
|
|
21992
|
+
status.size = statSync44(foundPath).size;
|
|
21965
21993
|
} catch {
|
|
21966
21994
|
}
|
|
21967
21995
|
try {
|
|
@@ -22022,7 +22050,7 @@ async function installCodeindex(opts = {}) {
|
|
|
22022
22050
|
if (!expected) {
|
|
22023
22051
|
throw new Error(`No pinned checksum for ${status.artifactName} \u2014 refusing to install an unverified binary. Add its sha256 to CODEINDEX_SHA256 in companions.ts.`);
|
|
22024
22052
|
}
|
|
22025
|
-
const actual =
|
|
22053
|
+
const actual = createHash13("sha256").update(readFileSync42(tmpPath)).digest("hex");
|
|
22026
22054
|
if (actual !== expected) {
|
|
22027
22055
|
throw new Error(`Checksum mismatch for ${status.artifactName}.
|
|
22028
22056
|
expected ${expected}
|
|
@@ -22186,7 +22214,10 @@ async function resolveCodeindexBin(autoInstall = true) {
|
|
|
22186
22214
|
}
|
|
22187
22215
|
function runMcp(binPath, workspace, calls, timeoutMs = 18e4) {
|
|
22188
22216
|
return new Promise((resolve3, reject) => {
|
|
22189
|
-
const p = spawn2(binPath, ["--mcp", "--workspace", workspace], {
|
|
22217
|
+
const p = spawn2(binPath, ["--mcp", "--workspace", workspace], {
|
|
22218
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
22219
|
+
env: { ...process.env, CODEINDEX_NO_DAEMON: "1" }
|
|
22220
|
+
});
|
|
22190
22221
|
const res = /* @__PURE__ */ new Map();
|
|
22191
22222
|
let pending = "";
|
|
22192
22223
|
let failed = false;
|
|
@@ -23699,7 +23730,7 @@ try {
|
|
|
23699
23730
|
ownVersion2 = JSON.parse(readFileSync39(join48(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
23700
23731
|
} catch {
|
|
23701
23732
|
try {
|
|
23702
|
-
if (true) ownVersion2 = "0.7.
|
|
23733
|
+
if (true) ownVersion2 = "0.7.3";
|
|
23703
23734
|
} catch {
|
|
23704
23735
|
}
|
|
23705
23736
|
}
|
|
@@ -23764,7 +23795,9 @@ init_auto_update();
|
|
|
23764
23795
|
|
|
23765
23796
|
// src/code-index-cursor.ts
|
|
23766
23797
|
init_paths();
|
|
23767
|
-
import { readFileSync as readFileSync40, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15 } from "fs";
|
|
23798
|
+
import { readFileSync as readFileSync40, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, statSync as statSync41 } from "fs";
|
|
23799
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
23800
|
+
import { createHash as createHash10 } from "crypto";
|
|
23768
23801
|
import { join as join49, dirname as dirname24 } from "path";
|
|
23769
23802
|
var cursorPath = () => join49(getDataDir(), "code-index-cursor.json");
|
|
23770
23803
|
function readCursor() {
|
|
@@ -23773,7 +23806,11 @@ function readCursor() {
|
|
|
23773
23806
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
23774
23807
|
const out = {};
|
|
23775
23808
|
for (const [k, v] of Object.entries(raw)) {
|
|
23776
|
-
if (typeof v === "number" && Number.isFinite(v)) out[k] = v;
|
|
23809
|
+
if (typeof v === "number" && Number.isFinite(v)) out[k] = { at: v };
|
|
23810
|
+
else if (v && typeof v === "object" && typeof v.at === "number" && Number.isFinite(v.at)) {
|
|
23811
|
+
const fp = v.fp;
|
|
23812
|
+
out[k] = typeof fp === "string" ? { at: v.at, fp } : { at: v.at };
|
|
23813
|
+
}
|
|
23777
23814
|
}
|
|
23778
23815
|
return out;
|
|
23779
23816
|
}
|
|
@@ -23789,13 +23826,44 @@ function writeCursor(c) {
|
|
|
23789
23826
|
} catch {
|
|
23790
23827
|
}
|
|
23791
23828
|
}
|
|
23792
|
-
function noteIndexed(workspace, now = Date.now()) {
|
|
23829
|
+
function noteIndexed(workspace, now = Date.now(), fp) {
|
|
23793
23830
|
const c = readCursor();
|
|
23794
|
-
c[workspace] = now;
|
|
23831
|
+
c[workspace] = fp ? { at: now, fp } : { at: now };
|
|
23795
23832
|
writeCursor(c);
|
|
23796
23833
|
}
|
|
23834
|
+
function workspaceFingerprint(workspace, collectorVersion) {
|
|
23835
|
+
try {
|
|
23836
|
+
const git2 = (args) => execFileSync4(
|
|
23837
|
+
"git",
|
|
23838
|
+
["-C", workspace, ...args],
|
|
23839
|
+
{ encoding: "utf-8", timeout: 1e4, maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] }
|
|
23840
|
+
);
|
|
23841
|
+
const head = git2(["rev-parse", "HEAD"]).trim();
|
|
23842
|
+
const status = git2(["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
|
|
23843
|
+
const h = createHash10("sha256").update(`v${collectorVersion}\0${head}\0`);
|
|
23844
|
+
for (const entry of status.split("\0")) {
|
|
23845
|
+
if (entry.length < 4) continue;
|
|
23846
|
+
const rel = entry.slice(3);
|
|
23847
|
+
let stamp2 = "gone";
|
|
23848
|
+
try {
|
|
23849
|
+
const s = statSync41(join49(workspace, rel));
|
|
23850
|
+
stamp2 = `${s.size}:${Math.floor(s.mtimeMs)}`;
|
|
23851
|
+
} catch {
|
|
23852
|
+
}
|
|
23853
|
+
h.update(`${entry.slice(0, 2)}\0${rel}\0${stamp2}\0`);
|
|
23854
|
+
}
|
|
23855
|
+
return h.digest("hex");
|
|
23856
|
+
} catch {
|
|
23857
|
+
return null;
|
|
23858
|
+
}
|
|
23859
|
+
}
|
|
23860
|
+
var UNCHANGED_RESEND_MS = 7 * 24 * 3600 * 1e3;
|
|
23861
|
+
function isUnchangedSinceIndexed(workspace, fp, cursor, now = Date.now()) {
|
|
23862
|
+
const e = cursor[workspace];
|
|
23863
|
+
return !!fp && !!e && e.fp === fp && now - e.at < UNCHANGED_RESEND_MS;
|
|
23864
|
+
}
|
|
23797
23865
|
function orderByStaleness(workspaces, cursor = readCursor()) {
|
|
23798
|
-
return workspaces.map((w, i) => ({ w, i, at: cursor[w] ?? -1 })).sort((a, b) => a.at - b.at || a.i - b.i).map((e) => e.w);
|
|
23866
|
+
return workspaces.map((w, i) => ({ w, i, at: cursor[w]?.at ?? -1 })).sort((a, b) => a.at - b.at || a.i - b.i).map((e) => e.w);
|
|
23799
23867
|
}
|
|
23800
23868
|
function pruneCursor(known) {
|
|
23801
23869
|
const keep = new Set(known);
|
|
@@ -23915,7 +23983,7 @@ init_telemetry();
|
|
|
23915
23983
|
// src/self-restart.ts
|
|
23916
23984
|
import { spawn } from "child_process";
|
|
23917
23985
|
import { readFileSync as readFileSync41 } from "fs";
|
|
23918
|
-
import { createHash as
|
|
23986
|
+
import { createHash as createHash11 } from "crypto";
|
|
23919
23987
|
var EXIT_CODE_CODE_CHANGED = 75;
|
|
23920
23988
|
function codeFingerprint(entry = process.argv[1]) {
|
|
23921
23989
|
if (!entry) return null;
|
|
@@ -23924,7 +23992,7 @@ function codeFingerprint(entry = process.argv[1]) {
|
|
|
23924
23992
|
return {
|
|
23925
23993
|
path: entry,
|
|
23926
23994
|
size: buf.byteLength,
|
|
23927
|
-
hash:
|
|
23995
|
+
hash: createHash11("sha256").update(buf).digest("hex")
|
|
23928
23996
|
};
|
|
23929
23997
|
} catch {
|
|
23930
23998
|
return null;
|
|
@@ -23987,11 +24055,11 @@ function checkSelfRestart(opts) {
|
|
|
23987
24055
|
}
|
|
23988
24056
|
|
|
23989
24057
|
// src/log-rotate.ts
|
|
23990
|
-
import { statSync as
|
|
24058
|
+
import { statSync as statSync42, copyFileSync as copyFileSync3, truncateSync } from "fs";
|
|
23991
24059
|
var LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
23992
24060
|
function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
23993
24061
|
try {
|
|
23994
|
-
const size =
|
|
24062
|
+
const size = statSync42(logPath).size;
|
|
23995
24063
|
if (size < maxBytes) return { rotated: false, sizeBefore: 0 };
|
|
23996
24064
|
copyFileSync3(logPath, `${logPath}.1`);
|
|
23997
24065
|
truncateSync(logPath, 0);
|
|
@@ -24046,8 +24114,8 @@ async function runCollectorMigration(opts) {
|
|
|
24046
24114
|
// auto-indexer/indexer.ts
|
|
24047
24115
|
init_sync_ledger();
|
|
24048
24116
|
init_collector_health();
|
|
24049
|
-
import { existsSync as existsSync50, readFileSync as readFileSync45, statSync as
|
|
24050
|
-
var CLI_VERSION3 = true ? "0.7.
|
|
24117
|
+
import { existsSync as existsSync50, readFileSync as readFileSync45, statSync as statSync45 } from "fs";
|
|
24118
|
+
var CLI_VERSION3 = true ? "0.7.3" : "0.0.0";
|
|
24051
24119
|
var DEBOUNCE_MS = 5e3;
|
|
24052
24120
|
var CLAUDE_DIR = claudeBackend.projectsDir();
|
|
24053
24121
|
var PLANS_DIR = claudeBackend.plansDir();
|
|
@@ -24152,7 +24220,7 @@ var WATCH_WINDOW_MS = Math.max(1, Number(process.env.CHAT_RECALL_WATCH_WINDOW_DA
|
|
|
24152
24220
|
var sessionWatcher = watchWithFallback("sessions", `${CLAUDE_DIR}/**/*.jsonl`, {
|
|
24153
24221
|
ignored: (p, stats) => {
|
|
24154
24222
|
if (/agent-/.test(p) || /^\./.test(basename25(p))) return true;
|
|
24155
|
-
const st = stats ??
|
|
24223
|
+
const st = stats ?? statSync45(p, { throwIfNoEntry: false });
|
|
24156
24224
|
if (!st || st.isDirectory()) return false;
|
|
24157
24225
|
return st.mtimeMs < Date.now() - WATCH_WINDOW_MS;
|
|
24158
24226
|
},
|
|
@@ -24432,7 +24500,7 @@ function discoverWorkspaces() {
|
|
|
24432
24500
|
for (const b of listAvailableBackends()) {
|
|
24433
24501
|
let refs = [];
|
|
24434
24502
|
try {
|
|
24435
|
-
refs = b.listSessions({ sinceMs });
|
|
24503
|
+
refs = b.listSessions({ sinceMs, previews: false });
|
|
24436
24504
|
} catch {
|
|
24437
24505
|
}
|
|
24438
24506
|
for (const r of refs) {
|
|
@@ -24500,7 +24568,7 @@ async function codeIndexTick() {
|
|
|
24500
24568
|
if (discovered.length === 0) return;
|
|
24501
24569
|
pruneCursor(discovered);
|
|
24502
24570
|
const workspaces = orderByStaleness(discovered);
|
|
24503
|
-
const { collectCode: collectCode2, resolveCodeindexBin: resolveCodeindexBin2 } = await Promise.resolve().then(() => (init_collector(), collector_exports));
|
|
24571
|
+
const { collectCode: collectCode2, resolveCodeindexBin: resolveCodeindexBin2, COLLECTOR_VERSION: COLLECTOR_VERSION2 } = await Promise.resolve().then(() => (init_collector(), collector_exports));
|
|
24504
24572
|
let bin;
|
|
24505
24573
|
try {
|
|
24506
24574
|
bin = await resolveCodeindexBin2(true);
|
|
@@ -24508,8 +24576,14 @@ async function codeIndexTick() {
|
|
|
24508
24576
|
daemonLog.error(`code intelligence skipped \u2014 codeindex unavailable: ${e instanceof Error ? e.message : e}`);
|
|
24509
24577
|
return;
|
|
24510
24578
|
}
|
|
24511
|
-
let ok = 0;
|
|
24579
|
+
let ok = 0, unchanged = 0;
|
|
24580
|
+
const cursor = readCursor();
|
|
24512
24581
|
for (const ws of workspaces) {
|
|
24582
|
+
const fp = workspaceFingerprint(ws, COLLECTOR_VERSION2);
|
|
24583
|
+
if (isUnchangedSinceIndexed(ws, fp, cursor)) {
|
|
24584
|
+
unchanged++;
|
|
24585
|
+
continue;
|
|
24586
|
+
}
|
|
24513
24587
|
const t0 = Date.now();
|
|
24514
24588
|
daemonLog.info(`code intelligence: indexing ${ws} \u2026`);
|
|
24515
24589
|
let result;
|
|
@@ -24527,10 +24601,10 @@ async function codeIndexTick() {
|
|
|
24527
24601
|
} catch {
|
|
24528
24602
|
}
|
|
24529
24603
|
}
|
|
24530
|
-
noteIndexed(ws);
|
|
24604
|
+
noteIndexed(ws, Date.now(), fp);
|
|
24531
24605
|
ok++;
|
|
24532
24606
|
}
|
|
24533
|
-
if (ok > 0) daemonLog.info(`code intelligence: indexed ${ok}/${workspaces.length} workspace(s)`);
|
|
24607
|
+
if (ok > 0 || unchanged > 0) daemonLog.info(`code intelligence: indexed ${ok}/${workspaces.length} workspace(s), ${unchanged} unchanged`);
|
|
24534
24608
|
} finally {
|
|
24535
24609
|
codeIndexInFlight = false;
|
|
24536
24610
|
}
|