chat-recall 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-update.d.ts +34 -0
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +51 -8
- package/dist/auto-update.js.map +1 -1
- package/dist/cli.js +463 -244
- package/dist/cli.js.map +1 -1
- 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 +76 -13
- package/dist/mcp-relay.js.map +1 -1
- package/dist/mcp.js +777 -471
- package/dist/mcp.js.map +1 -1
- package/dist/relay-lifecycle.d.ts +69 -0
- package/dist/relay-lifecycle.d.ts.map +1 -0
- package/dist/relay-lifecycle.js +117 -0
- package/dist/relay-lifecycle.js.map +1 -0
- package/dist/repair.d.ts +2 -0
- package/dist/repair.d.ts.map +1 -1
- package/dist/repair.js +23 -3
- package/dist/repair.js.map +1 -1
- package/dist/scan-worker.js +122 -65
- package/dist/service-installer.d.ts.map +1 -1
- package/dist/service-installer.js +7 -2
- package/dist/service-installer.js.map +1 -1
- package/dist/sync-client.d.ts +38 -5
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +194 -61
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-supervisor.d.ts +43 -0
- package/dist/sync-supervisor.d.ts.map +1 -0
- package/dist/sync-supervisor.js +84 -0
- package/dist/sync-supervisor.js.map +1 -0
- package/dist/watch.js +470 -213
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7736,23 +7736,8 @@ var init_opencode = __esm({
|
|
|
7736
7736
|
const projectPath = row.project_path || row.directory || "";
|
|
7737
7737
|
if (filter && !projectPath.toLowerCase().includes(filter))
|
|
7738
7738
|
continue;
|
|
7739
|
-
const
|
|
7740
|
-
|
|
7741
|
-
FROM part p JOIN message m ON m.id = p.message_id
|
|
7742
|
-
WHERE p.session_id = ?
|
|
7743
|
-
AND p.data LIKE '%"type":"text"%'
|
|
7744
|
-
AND m.data LIKE '%"role":"user"%'
|
|
7745
|
-
ORDER BY p.time_created ASC LIMIT 1
|
|
7746
|
-
`).get(row.id);
|
|
7747
|
-
let firstPrompt = "";
|
|
7748
|
-
if (firstUser) {
|
|
7749
|
-
try {
|
|
7750
|
-
const parsed = JSON.parse(firstUser.data);
|
|
7751
|
-
firstPrompt = flatString(String(parsed?.text || "").slice(0, 200));
|
|
7752
|
-
} catch {
|
|
7753
|
-
}
|
|
7754
|
-
}
|
|
7755
|
-
const messageCount = db.prepare("SELECT COUNT(*) as c FROM message WHERE session_id = ?").get(row.id)?.c ?? 0;
|
|
7739
|
+
const firstPrompt = opts.previews === false ? "" : this.firstUserPrompt(db, row.id);
|
|
7740
|
+
const messageCount = opts.previews === false ? 0 : db.prepare("SELECT COUNT(*) as c FROM message WHERE session_id = ?").get(row.id)?.c ?? 0;
|
|
7756
7741
|
const created = new Date(row.time_created || row.time_updated).toISOString();
|
|
7757
7742
|
const modified = new Date(row.time_updated).toISOString();
|
|
7758
7743
|
out.push({
|
|
@@ -7776,6 +7761,45 @@ var init_opencode = __esm({
|
|
|
7776
7761
|
db.close();
|
|
7777
7762
|
}
|
|
7778
7763
|
}
|
|
7764
|
+
/**
|
|
7765
|
+
* The first user text part of a session.
|
|
7766
|
+
*
|
|
7767
|
+
* Walks the session's user messages oldest first through the
|
|
7768
|
+
* (session_id, time_created, id) index and stops at the first one with a
|
|
7769
|
+
* text part. The role and the text are read by SQLite: a first message can
|
|
7770
|
+
* carry whole diffs in `summary` (107 MB on one row), and parsing that in JS
|
|
7771
|
+
* to read one field took the process to 510 MB. The earlier query filtered
|
|
7772
|
+
* every part and message with LIKE and then sorted, so it read all of a
|
|
7773
|
+
* session's data: 423 MB for a 236-session listing.
|
|
7774
|
+
*/
|
|
7775
|
+
firstUserPrompt(db, sessionId) {
|
|
7776
|
+
try {
|
|
7777
|
+
const has = (table, col) => !!db.prepare(`SELECT 1 FROM pragma_table_info(?) WHERE name = ?`).get(table, col);
|
|
7778
|
+
const msgOrder = has("message", "time_created") ? "time_created, id" : "rowid";
|
|
7779
|
+
const partOrder = has("part", "time_created") ? "time_created, id" : "rowid";
|
|
7780
|
+
const nextUser = db.prepare(`SELECT id, ${msgOrder === "rowid" ? "rowid AS k1, 0 AS k2" : "time_created AS k1, id AS k2"} FROM message
|
|
7781
|
+
WHERE session_id = ? AND (${msgOrder === "rowid" ? "rowid, 0" : "time_created, id"}) > (?, ?)
|
|
7782
|
+
AND json_extract(data, '$.role') = 'user'
|
|
7783
|
+
ORDER BY ${msgOrder} LIMIT 1`);
|
|
7784
|
+
const firstText = db.prepare(`SELECT substr(json_extract(data, '$.text'), 1, 400) AS text FROM part
|
|
7785
|
+
WHERE message_id = ? AND json_extract(data, '$.type') = 'text'
|
|
7786
|
+
AND length(trim(json_extract(data, '$.text'))) > 0
|
|
7787
|
+
ORDER BY ${partOrder} LIMIT 1`);
|
|
7788
|
+
let k1 = Number.MIN_SAFE_INTEGER, k2 = msgOrder === "rowid" ? 0 : "";
|
|
7789
|
+
for (; ; ) {
|
|
7790
|
+
const m = nextUser.get(sessionId, k1, k2);
|
|
7791
|
+
if (!m)
|
|
7792
|
+
return "";
|
|
7793
|
+
k1 = m.k1;
|
|
7794
|
+
k2 = m.k2;
|
|
7795
|
+
const t = firstText.get(m.id);
|
|
7796
|
+
if (t?.text)
|
|
7797
|
+
return flatString(t.text.slice(0, 200));
|
|
7798
|
+
}
|
|
7799
|
+
} catch {
|
|
7800
|
+
return "";
|
|
7801
|
+
}
|
|
7802
|
+
}
|
|
7779
7803
|
/** OpenCode auto-generates a session title (model-written, distinct from the
|
|
7780
7804
|
* first prompt — e.g. "Replacing Claude with Gemini CLI"). It's a plain
|
|
7781
7805
|
* column on the session row. */
|
|
@@ -8093,7 +8117,7 @@ var init_opencode = __esm({
|
|
|
8093
8117
|
|
|
8094
8118
|
// ../engine/dist/core/backends/tail-read.js
|
|
8095
8119
|
import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2, statSync as statSync4 } from "node:fs";
|
|
8096
|
-
function readTailFromOffset(path, offset) {
|
|
8120
|
+
function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
8097
8121
|
let size = 0;
|
|
8098
8122
|
try {
|
|
8099
8123
|
size = statSync4(path).size;
|
|
@@ -8102,7 +8126,7 @@ function readTailFromOffset(path, offset) {
|
|
|
8102
8126
|
}
|
|
8103
8127
|
if (size <= offset)
|
|
8104
8128
|
return { text: "", newOffset: offset };
|
|
8105
|
-
const len = Math.min(size - offset,
|
|
8129
|
+
const len = Math.min(size - offset, Math.max(1, maxBytes));
|
|
8106
8130
|
const buf = Buffer.allocUnsafe(len);
|
|
8107
8131
|
let fd = null;
|
|
8108
8132
|
try {
|
|
@@ -8118,11 +8142,16 @@ function readTailFromOffset(path, offset) {
|
|
|
8118
8142
|
return { text: "", newOffset: offset };
|
|
8119
8143
|
const slice = got < len ? buf.subarray(0, got) : buf;
|
|
8120
8144
|
const lastNl = slice.lastIndexOf(10);
|
|
8121
|
-
if (lastNl
|
|
8122
|
-
|
|
8145
|
+
if (lastNl >= 0) {
|
|
8146
|
+
const text = slice.subarray(0, lastNl + 1).toString("utf-8");
|
|
8147
|
+
return { text, newOffset: offset + lastNl + 1 };
|
|
8123
8148
|
}
|
|
8124
|
-
|
|
8125
|
-
|
|
8149
|
+
if (offset + got >= size)
|
|
8150
|
+
return { text: "", newOffset: offset };
|
|
8151
|
+
const end = findNewline(fd, offset + got, size);
|
|
8152
|
+
if (end < 0)
|
|
8153
|
+
return { text: "", newOffset: offset };
|
|
8154
|
+
return { text: "", newOffset: end + 1, skippedBytes: end + 1 - offset };
|
|
8126
8155
|
} catch {
|
|
8127
8156
|
return { text: "", newOffset: offset };
|
|
8128
8157
|
} finally {
|
|
@@ -8134,9 +8163,26 @@ function readTailFromOffset(path, offset) {
|
|
|
8134
8163
|
}
|
|
8135
8164
|
}
|
|
8136
8165
|
}
|
|
8166
|
+
function findNewline(fd, from, size) {
|
|
8167
|
+
const block = Buffer.allocUnsafe(SKIP_SCAN_BYTES);
|
|
8168
|
+
let pos = from;
|
|
8169
|
+
while (pos < size) {
|
|
8170
|
+
const n = readSync2(fd, block, 0, Math.min(SKIP_SCAN_BYTES, size - pos), pos);
|
|
8171
|
+
if (n <= 0)
|
|
8172
|
+
return -1;
|
|
8173
|
+
const i = block.subarray(0, n).indexOf(10);
|
|
8174
|
+
if (i >= 0)
|
|
8175
|
+
return pos + i;
|
|
8176
|
+
pos += n;
|
|
8177
|
+
}
|
|
8178
|
+
return -1;
|
|
8179
|
+
}
|
|
8180
|
+
var TAIL_READ_MAX_BYTES, SKIP_SCAN_BYTES;
|
|
8137
8181
|
var init_tail_read = __esm({
|
|
8138
8182
|
"../engine/dist/core/backends/tail-read.js"() {
|
|
8139
8183
|
"use strict";
|
|
8184
|
+
TAIL_READ_MAX_BYTES = 16 * 1024 * 1024;
|
|
8185
|
+
SKIP_SCAN_BYTES = 1024 * 1024;
|
|
8140
8186
|
}
|
|
8141
8187
|
});
|
|
8142
8188
|
|
|
@@ -8387,28 +8433,29 @@ var init_codex2 = __esm({
|
|
|
8387
8433
|
continue;
|
|
8388
8434
|
let firstPrompt = "";
|
|
8389
8435
|
let messageCount = 0;
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
firstPrompt
|
|
8436
|
+
if (opts.previews !== false)
|
|
8437
|
+
try {
|
|
8438
|
+
const lines = readFileSync3(filePath, "utf-8").split("\n");
|
|
8439
|
+
for (const line of lines) {
|
|
8440
|
+
if (!line.trim())
|
|
8441
|
+
continue;
|
|
8442
|
+
let ev;
|
|
8443
|
+
try {
|
|
8444
|
+
ev = JSON.parse(line);
|
|
8445
|
+
} catch {
|
|
8446
|
+
continue;
|
|
8447
|
+
}
|
|
8448
|
+
if (ev.type === "event_msg" && ev.payload?.type === "user_message") {
|
|
8449
|
+
messageCount++;
|
|
8450
|
+
if (!firstPrompt && ev.payload.message) {
|
|
8451
|
+
firstPrompt = flatString(String(ev.payload.message).slice(0, 200));
|
|
8452
|
+
}
|
|
8453
|
+
} else if (ev.type === "response_item" && ev.payload?.type === "message") {
|
|
8454
|
+
messageCount++;
|
|
8405
8455
|
}
|
|
8406
|
-
} else if (ev.type === "response_item" && ev.payload?.type === "message") {
|
|
8407
|
-
messageCount++;
|
|
8408
8456
|
}
|
|
8457
|
+
} catch {
|
|
8409
8458
|
}
|
|
8410
|
-
} catch {
|
|
8411
|
-
}
|
|
8412
8459
|
const prior = seen.get(rawId);
|
|
8413
8460
|
if (prior) {
|
|
8414
8461
|
if (stat3.mtimeMs > prior.mtime) {
|
|
@@ -8843,11 +8890,11 @@ var init_codex2 = __esm({
|
|
|
8843
8890
|
return 0;
|
|
8844
8891
|
}
|
|
8845
8892
|
}
|
|
8846
|
-
async readFromOffset(prefixedId, offset) {
|
|
8893
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
8847
8894
|
const loc = this.findSession(prefixedId);
|
|
8848
8895
|
if (!loc)
|
|
8849
8896
|
return { text: "", newOffset: offset };
|
|
8850
|
-
return readTailFromOffset(loc.path, offset);
|
|
8897
|
+
return readTailFromOffset(loc.path, offset, maxBytes);
|
|
8851
8898
|
}
|
|
8852
8899
|
};
|
|
8853
8900
|
codexBackend = new CodexBackend();
|
|
@@ -9098,21 +9145,22 @@ var init_agy = __esm({
|
|
|
9098
9145
|
const projectDir = projectPath ? basename8(projectPath) : "";
|
|
9099
9146
|
let firstPrompt = "";
|
|
9100
9147
|
let messageCount = 0;
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
const
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9148
|
+
if (opts.previews !== false)
|
|
9149
|
+
try {
|
|
9150
|
+
const lines = readFileSync4(filePath, "utf-8").split("\n").filter(Boolean);
|
|
9151
|
+
messageCount = lines.length;
|
|
9152
|
+
for (const line of lines) {
|
|
9153
|
+
const obj = JSON.parse(line);
|
|
9154
|
+
if (obj.source === "USER_EXPLICIT" && obj.type === "USER_INPUT" && typeof obj.content === "string") {
|
|
9155
|
+
const content = obj.content;
|
|
9156
|
+
const match = content.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
|
|
9157
|
+
const rawText = match ? match[1].trim() : content.trim();
|
|
9158
|
+
firstPrompt = flatString(rawText.slice(0, 200));
|
|
9159
|
+
break;
|
|
9160
|
+
}
|
|
9112
9161
|
}
|
|
9162
|
+
} catch {
|
|
9113
9163
|
}
|
|
9114
|
-
} catch {
|
|
9115
|
-
}
|
|
9116
9164
|
if (seenIds.has(rawId))
|
|
9117
9165
|
continue;
|
|
9118
9166
|
seenIds.add(rawId);
|
|
@@ -9408,11 +9456,11 @@ var init_agy = __esm({
|
|
|
9408
9456
|
return 0;
|
|
9409
9457
|
}
|
|
9410
9458
|
}
|
|
9411
|
-
async readFromOffset(prefixedId, offset) {
|
|
9459
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
9412
9460
|
const loc = this.findSession(prefixedId);
|
|
9413
9461
|
if (!loc)
|
|
9414
9462
|
return { text: "", newOffset: offset };
|
|
9415
|
-
return readTailFromOffset(loc.path, offset);
|
|
9463
|
+
return readTailFromOffset(loc.path, offset, maxBytes);
|
|
9416
9464
|
}
|
|
9417
9465
|
};
|
|
9418
9466
|
agyBackend = new AgyBackend();
|
|
@@ -10608,7 +10656,7 @@ var init_backends = __esm({
|
|
|
10608
10656
|
// ../engine/dist/transcript/shadow.js
|
|
10609
10657
|
import { gzipSync as gzipSync2, gunzipSync as gunzipSync2 } from "zlib";
|
|
10610
10658
|
import { createHash as createHash2 } from "crypto";
|
|
10611
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2, renameSync as renameSync2, statSync as statSync10 } from "fs";
|
|
10659
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2, renameSync as renameSync2, statSync as statSync10, openSync as openSync4, readSync as readSync4, closeSync as closeSync4 } from "fs";
|
|
10612
10660
|
import { dirname as dirname12, join as join14 } from "path";
|
|
10613
10661
|
function shadowRoot() {
|
|
10614
10662
|
return join14(getDataDir(), "shadow");
|
|
@@ -10832,6 +10880,29 @@ function seedShadow(sessionId, container) {
|
|
|
10832
10880
|
}
|
|
10833
10881
|
return fullest;
|
|
10834
10882
|
}
|
|
10883
|
+
function shadowUncompressedBytes(tool, rawId) {
|
|
10884
|
+
const path = shadowFileFor(tool, rawId);
|
|
10885
|
+
let fd = null;
|
|
10886
|
+
try {
|
|
10887
|
+
const size = statSync10(path).size;
|
|
10888
|
+
if (size < 18)
|
|
10889
|
+
return 0;
|
|
10890
|
+
fd = openSync4(path, "r");
|
|
10891
|
+
const tail = Buffer.alloc(4);
|
|
10892
|
+
if (readSync4(fd, tail, 0, 4, size - 4) !== 4)
|
|
10893
|
+
return 0;
|
|
10894
|
+
return tail.readUInt32LE(0);
|
|
10895
|
+
} catch {
|
|
10896
|
+
return 0;
|
|
10897
|
+
} finally {
|
|
10898
|
+
if (fd !== null) {
|
|
10899
|
+
try {
|
|
10900
|
+
closeSync4(fd);
|
|
10901
|
+
} catch {
|
|
10902
|
+
}
|
|
10903
|
+
}
|
|
10904
|
+
}
|
|
10905
|
+
}
|
|
10835
10906
|
function shadowSizeOnDisk(tool, rawId) {
|
|
10836
10907
|
try {
|
|
10837
10908
|
return statSync10(shadowFileFor(tool, rawId)).size;
|
|
@@ -10852,7 +10923,7 @@ var init_shadow = __esm({
|
|
|
10852
10923
|
});
|
|
10853
10924
|
|
|
10854
10925
|
// ../engine/dist/core/live-session-scan.js
|
|
10855
|
-
import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as
|
|
10926
|
+
import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
|
|
10856
10927
|
import { join as join15, basename as basename9 } from "path";
|
|
10857
10928
|
function detectTool(sessionId) {
|
|
10858
10929
|
return getBackendForId(sessionId)?.id ?? "claude";
|
|
@@ -10879,6 +10950,15 @@ function sessionFileIndex() {
|
|
|
10879
10950
|
return indexCache;
|
|
10880
10951
|
const byId = /* @__PURE__ */ new Map();
|
|
10881
10952
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
10953
|
+
const projectPaths = /* @__PURE__ */ new Map();
|
|
10954
|
+
const projectPathOf = (dirName) => {
|
|
10955
|
+
let p = projectPaths.get(dirName);
|
|
10956
|
+
if (p === void 0) {
|
|
10957
|
+
p = resolveProjectDirName(dirName);
|
|
10958
|
+
projectPaths.set(dirName, p);
|
|
10959
|
+
}
|
|
10960
|
+
return p;
|
|
10961
|
+
};
|
|
10882
10962
|
for (const root of claudeProjectDirs()) {
|
|
10883
10963
|
if (seenRoots.has(root) || !existsSync13(root))
|
|
10884
10964
|
continue;
|
|
@@ -10906,7 +10986,7 @@ function sessionFileIndex() {
|
|
|
10906
10986
|
const located = {
|
|
10907
10987
|
path: join15(dir, name),
|
|
10908
10988
|
projectDir: entry.name,
|
|
10909
|
-
projectPath:
|
|
10989
|
+
projectPath: projectPathOf(entry.name)
|
|
10910
10990
|
};
|
|
10911
10991
|
const prior = byId.get(id);
|
|
10912
10992
|
if (prior)
|
|
@@ -11096,7 +11176,7 @@ var init_live_session_scan = __esm({
|
|
|
11096
11176
|
});
|
|
11097
11177
|
|
|
11098
11178
|
// ../engine/dist/core/first-prompt.js
|
|
11099
|
-
import { createReadStream as createReadStream2, existsSync as existsSync14, openSync as
|
|
11179
|
+
import { createReadStream as createReadStream2, existsSync as existsSync14, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
|
|
11100
11180
|
import { StringDecoder } from "string_decoder";
|
|
11101
11181
|
function stripBanners2(s) {
|
|
11102
11182
|
let out = s;
|
|
@@ -11150,7 +11230,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11150
11230
|
const maxBytes = options.maxBytes ?? 4 * 1024 * 1024;
|
|
11151
11231
|
let fd;
|
|
11152
11232
|
try {
|
|
11153
|
-
fd =
|
|
11233
|
+
fd = openSync6(filePath, "r");
|
|
11154
11234
|
} catch {
|
|
11155
11235
|
return "";
|
|
11156
11236
|
}
|
|
@@ -11162,7 +11242,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11162
11242
|
let pos = 0;
|
|
11163
11243
|
let lineNo = 0;
|
|
11164
11244
|
for (; ; ) {
|
|
11165
|
-
const n =
|
|
11245
|
+
const n = readSync6(fd, buf, 0, CHUNK, pos);
|
|
11166
11246
|
if (n <= 0)
|
|
11167
11247
|
break;
|
|
11168
11248
|
pos += n;
|
|
@@ -11188,7 +11268,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11188
11268
|
return "";
|
|
11189
11269
|
} finally {
|
|
11190
11270
|
try {
|
|
11191
|
-
|
|
11271
|
+
closeSync6(fd);
|
|
11192
11272
|
} catch {
|
|
11193
11273
|
}
|
|
11194
11274
|
}
|
|
@@ -11207,7 +11287,7 @@ var init_first_prompt = __esm({
|
|
|
11207
11287
|
});
|
|
11208
11288
|
|
|
11209
11289
|
// ../engine/dist/core/backends/claude.js
|
|
11210
|
-
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as readFileSync10, statSync as statSync12, openSync as
|
|
11290
|
+
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as readFileSync10, statSync as statSync12, openSync as openSync7, readSync as readSync7, closeSync as closeSync7 } from "fs";
|
|
11211
11291
|
import { join as join16, basename as basename10 } from "path";
|
|
11212
11292
|
function stripReminders(text) {
|
|
11213
11293
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
|
|
@@ -11304,13 +11384,13 @@ var init_claude2 = __esm({
|
|
|
11304
11384
|
return null;
|
|
11305
11385
|
let head;
|
|
11306
11386
|
try {
|
|
11307
|
-
const fd =
|
|
11387
|
+
const fd = openSync7(located.path, "r");
|
|
11308
11388
|
try {
|
|
11309
11389
|
const buf = Buffer.alloc(65536);
|
|
11310
|
-
const n =
|
|
11390
|
+
const n = readSync7(fd, buf, 0, buf.length, 0);
|
|
11311
11391
|
head = buf.toString("utf-8", 0, n);
|
|
11312
11392
|
} finally {
|
|
11313
|
-
|
|
11393
|
+
closeSync7(fd);
|
|
11314
11394
|
}
|
|
11315
11395
|
} catch {
|
|
11316
11396
|
return null;
|
|
@@ -11355,12 +11435,12 @@ var init_claude2 = __esm({
|
|
|
11355
11435
|
const seen = /* @__PURE__ */ new Set();
|
|
11356
11436
|
const out = [];
|
|
11357
11437
|
for (const root of claudeProjectDirs()) {
|
|
11358
|
-
this.collectSessionsFromRoot(root, cutoff, filter, seen, out);
|
|
11438
|
+
this.collectSessionsFromRoot(root, cutoff, filter, seen, out, opts.previews !== false);
|
|
11359
11439
|
}
|
|
11360
11440
|
out.sort((a, b) => b.mtime - a.mtime);
|
|
11361
11441
|
return opts.limit ? out.slice(0, opts.limit) : out;
|
|
11362
11442
|
}
|
|
11363
|
-
collectSessionsFromRoot(root, cutoff, filter, seen, out) {
|
|
11443
|
+
collectSessionsFromRoot(root, cutoff, filter, seen, out, previews) {
|
|
11364
11444
|
if (!existsSync15(root))
|
|
11365
11445
|
return;
|
|
11366
11446
|
for (const proj of readdirSync11(root, { withFileTypes: true })) {
|
|
@@ -11419,7 +11499,7 @@ var init_claude2 = __esm({
|
|
|
11419
11499
|
}
|
|
11420
11500
|
if (stat3.mtimeMs < cutoff)
|
|
11421
11501
|
continue;
|
|
11422
|
-
const firstPrompt = extractFirstUserPromptSync(fullPath, { maxLength: 200 });
|
|
11502
|
+
const firstPrompt = previews ? extractFirstUserPromptSync(fullPath, { maxLength: 200 }) : "";
|
|
11423
11503
|
out.push({
|
|
11424
11504
|
toolId: "claude",
|
|
11425
11505
|
rawId: sessionId,
|
|
@@ -11782,14 +11862,14 @@ var init_claude2 = __esm({
|
|
|
11782
11862
|
spansMultipleSources(prefixedId) {
|
|
11783
11863
|
return findSessionFiles(this.toRawId(prefixedId)).length > 1;
|
|
11784
11864
|
}
|
|
11785
|
-
async readFromOffset(prefixedId, offset) {
|
|
11865
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
11786
11866
|
const rawId = this.toRawId(prefixedId);
|
|
11787
11867
|
const copies = findSessionFiles(rawId);
|
|
11788
11868
|
if (copies.length === 0)
|
|
11789
11869
|
return { text: "", newOffset: offset };
|
|
11790
11870
|
if (copies.length > 1)
|
|
11791
11871
|
return { text: "", newOffset: offset };
|
|
11792
|
-
return readTailFromOffset(copies[0].path, offset);
|
|
11872
|
+
return readTailFromOffset(copies[0].path, offset, maxBytes);
|
|
11793
11873
|
}
|
|
11794
11874
|
};
|
|
11795
11875
|
claudeBackend = new ClaudeBackend();
|
|
@@ -11839,6 +11919,7 @@ function loadProjectsConfig() {
|
|
|
11839
11919
|
}
|
|
11840
11920
|
function resetProjectResolverCache() {
|
|
11841
11921
|
resolveCache.clear();
|
|
11922
|
+
inputCache.clear();
|
|
11842
11923
|
gitCache.clear();
|
|
11843
11924
|
workspaceCache.clear();
|
|
11844
11925
|
wsIdCache.clear();
|
|
@@ -11855,12 +11936,13 @@ function resolveProjectId(inputPath) {
|
|
|
11855
11936
|
if (!isAbsolute(inputPath)) {
|
|
11856
11937
|
return { id: `path:${inputPath}`, displayName: inputPath, source: "path" };
|
|
11857
11938
|
}
|
|
11939
|
+
const known = inputCache.get(inputPath);
|
|
11940
|
+
if (known)
|
|
11941
|
+
return known;
|
|
11858
11942
|
const realPath = safeRealpath(inputPath);
|
|
11859
|
-
const
|
|
11860
|
-
if (cached)
|
|
11861
|
-
return cached;
|
|
11862
|
-
const result = doResolve(realPath);
|
|
11943
|
+
const result = resolveCache.get(realPath) ?? doResolve(realPath);
|
|
11863
11944
|
resolveCache.set(realPath, result);
|
|
11945
|
+
inputCache.set(inputPath, result);
|
|
11864
11946
|
return result;
|
|
11865
11947
|
}
|
|
11866
11948
|
function resolveWorkspaceId(inputPath) {
|
|
@@ -12161,7 +12243,7 @@ function globToRegex(glob) {
|
|
|
12161
12243
|
function escapeRe(s) {
|
|
12162
12244
|
return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
12163
12245
|
}
|
|
12164
|
-
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, wsIdCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
|
|
12246
|
+
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, inputCache, gitCache, workspaceCache, wsIdCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
|
|
12165
12247
|
var init_project_resolver = __esm({
|
|
12166
12248
|
"../engine/dist/core/project-resolver.js"() {
|
|
12167
12249
|
"use strict";
|
|
@@ -12169,6 +12251,7 @@ var init_project_resolver = __esm({
|
|
|
12169
12251
|
DEFAULT_AUTO_WORKSPACE_MIN_REPOS = 3;
|
|
12170
12252
|
BOT_WORKTREE_MARKERS = [".claude-pr-bot"];
|
|
12171
12253
|
resolveCache = /* @__PURE__ */ new Map();
|
|
12254
|
+
inputCache = /* @__PURE__ */ new Map();
|
|
12172
12255
|
gitCache = /* @__PURE__ */ new Map();
|
|
12173
12256
|
workspaceCache = /* @__PURE__ */ new Map();
|
|
12174
12257
|
wsIdCache = /* @__PURE__ */ new Map();
|
|
@@ -13742,10 +13825,10 @@ var init_types = __esm({
|
|
|
13742
13825
|
|
|
13743
13826
|
// ../engine/dist/transcript/opencode.js
|
|
13744
13827
|
async function parseOpenCodeSubagents(parentSessionId) {
|
|
13745
|
-
const { existsSync:
|
|
13828
|
+
const { existsSync: existsSync58 } = await import("fs");
|
|
13746
13829
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13747
13830
|
const dbPath = opencodeBackend2.dbPath();
|
|
13748
|
-
if (!
|
|
13831
|
+
if (!existsSync58(dbPath))
|
|
13749
13832
|
return [];
|
|
13750
13833
|
const realParent = parentSessionId.replace("opencode_", "");
|
|
13751
13834
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13786,10 +13869,10 @@ async function parseOpenCodeSubagents(parentSessionId) {
|
|
|
13786
13869
|
}
|
|
13787
13870
|
}
|
|
13788
13871
|
async function parseOpenCodeTranscript(sessionId) {
|
|
13789
|
-
const { existsSync:
|
|
13872
|
+
const { existsSync: existsSync58 } = await import("fs");
|
|
13790
13873
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13791
13874
|
const dbPath = opencodeBackend2.dbPath();
|
|
13792
|
-
if (!
|
|
13875
|
+
if (!existsSync58(dbPath))
|
|
13793
13876
|
return [];
|
|
13794
13877
|
const realId = sessionId.replace("opencode_", "");
|
|
13795
13878
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13866,6 +13949,7 @@ __export(transcript_exports, {
|
|
|
13866
13949
|
shadowFileFor: () => shadowFileFor,
|
|
13867
13950
|
shadowRoot: () => shadowRoot,
|
|
13868
13951
|
shadowSizeOnDisk: () => shadowSizeOnDisk,
|
|
13952
|
+
shadowUncompressedBytes: () => shadowUncompressedBytes,
|
|
13869
13953
|
snapshotShadow: () => snapshotShadow,
|
|
13870
13954
|
trimTranscriptForSync: () => trimTranscriptForSync,
|
|
13871
13955
|
updateShadow: () => updateShadow,
|
|
@@ -18335,7 +18419,7 @@ var init_sync_fields = __esm({
|
|
|
18335
18419
|
});
|
|
18336
18420
|
|
|
18337
18421
|
// ../engine/dist/core/index-lock.js
|
|
18338
|
-
import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as
|
|
18422
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as openSync8, writeFileSync as writeFileSync6, readFileSync as readFileSync30, rmSync as rmSync4, statSync as statSync35, closeSync as closeSync8 } from "fs";
|
|
18339
18423
|
import { dirname as dirname16, join as join39 } from "path";
|
|
18340
18424
|
function acquireIndexLock(opts) {
|
|
18341
18425
|
const lockPath = lockFilePath();
|
|
@@ -18347,7 +18431,7 @@ function acquireIndexLock(opts) {
|
|
|
18347
18431
|
}
|
|
18348
18432
|
let fd;
|
|
18349
18433
|
try {
|
|
18350
|
-
fd =
|
|
18434
|
+
fd = openSync8(lockPath, "wx", 384);
|
|
18351
18435
|
} catch (err) {
|
|
18352
18436
|
if (err.code === "EEXIST")
|
|
18353
18437
|
return null;
|
|
@@ -18357,7 +18441,7 @@ function acquireIndexLock(opts) {
|
|
|
18357
18441
|
try {
|
|
18358
18442
|
writeFileSync6(fd, JSON.stringify(holder));
|
|
18359
18443
|
} finally {
|
|
18360
|
-
|
|
18444
|
+
closeSync8(fd);
|
|
18361
18445
|
}
|
|
18362
18446
|
let released = false;
|
|
18363
18447
|
return {
|
|
@@ -18457,7 +18541,7 @@ var init_http = __esm({
|
|
|
18457
18541
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18458
18542
|
} catch {
|
|
18459
18543
|
try {
|
|
18460
|
-
if (true) CLI_VERSION = "0.7.
|
|
18544
|
+
if (true) CLI_VERSION = "0.7.2";
|
|
18461
18545
|
} catch {
|
|
18462
18546
|
}
|
|
18463
18547
|
}
|
|
@@ -18956,7 +19040,7 @@ var init_telemetry = __esm({
|
|
|
18956
19040
|
init_sync_client();
|
|
18957
19041
|
cliVersion2 = () => {
|
|
18958
19042
|
try {
|
|
18959
|
-
return true ? "0.7.
|
|
19043
|
+
return true ? "0.7.2" : "dev";
|
|
18960
19044
|
} catch {
|
|
18961
19045
|
return "dev";
|
|
18962
19046
|
}
|
|
@@ -19312,16 +19396,17 @@ __export(auto_update_exports, {
|
|
|
19312
19396
|
noteUpdateFailure: () => noteUpdateFailure,
|
|
19313
19397
|
planAutoUpdate: () => planAutoUpdate,
|
|
19314
19398
|
readUpdateState: () => readUpdateState,
|
|
19399
|
+
resolveNpm: () => resolveNpm,
|
|
19315
19400
|
runAutoUpdate: () => runAutoUpdate,
|
|
19316
19401
|
runningPrefix: () => runningPrefix,
|
|
19317
19402
|
sweepStaleStaging: () => sweepStaleStaging,
|
|
19318
19403
|
tarballUrl: () => tarballUrl
|
|
19319
19404
|
});
|
|
19320
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
19321
|
-
import { readFileSync as readFileSync34 } from "node:fs";
|
|
19405
|
+
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19406
|
+
import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
|
|
19322
19407
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19323
19408
|
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync31, statSync as statSync36, mkdirSync as mkdirSync9 } from "node:fs";
|
|
19324
|
-
import { join as join41, dirname as dirname18, sep as sep2 } from "node:path";
|
|
19409
|
+
import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
19325
19410
|
import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
|
|
19326
19411
|
import { createHash as createHash8 } from "node:crypto";
|
|
19327
19412
|
function compareVersions(a, b) {
|
|
@@ -19436,25 +19521,46 @@ function runningPrefix(moduleUrl = import.meta.url) {
|
|
|
19436
19521
|
const beforeNodeModules = here.slice(0, at);
|
|
19437
19522
|
return beforeNodeModules.endsWith(`${sep2}lib`) ? beforeNodeModules.slice(0, -4) : beforeNodeModules;
|
|
19438
19523
|
}
|
|
19439
|
-
function npmInstall(
|
|
19524
|
+
function npmInstall(npm, args) {
|
|
19440
19525
|
try {
|
|
19441
|
-
|
|
19526
|
+
const opts = { stdio: ["ignore", "ignore", "pipe"], env: npm.env };
|
|
19527
|
+
if (npm.shell) execSync2([npm.file, ...npm.args, ...args].map((a) => `"${a}"`).join(" "), opts);
|
|
19528
|
+
else execFileSync3(npm.file, [...npm.args, ...args], opts);
|
|
19442
19529
|
} catch (e) {
|
|
19443
19530
|
const err = e;
|
|
19444
19531
|
const detail = String(err.stderr ?? "").trim().split("\n").filter((l) => l.trim() && !/^npm (notice|warn)\b/i.test(l)).slice(-4).join(" | ").slice(0, 400);
|
|
19445
19532
|
throw new Error(detail ? `${err.message ?? "install failed"} \u2014 ${detail}` : err.message ?? "install failed");
|
|
19446
19533
|
}
|
|
19447
19534
|
}
|
|
19535
|
+
function resolveNpm(loc) {
|
|
19536
|
+
const win = loc.platform === "win32";
|
|
19537
|
+
const p = win ? pathWin32 : pathPosix;
|
|
19538
|
+
const nodeDir = p.dirname(loc.execPath);
|
|
19539
|
+
const cliUnder = (root) => win ? p.join(root, "node_modules", "npm", "bin", "npm-cli.js") : p.join(root, "lib", "node_modules", "npm", "bin", "npm-cli.js");
|
|
19540
|
+
const candidates2 = [
|
|
19541
|
+
cliUnder(win ? nodeDir : p.join(nodeDir, "..")),
|
|
19542
|
+
...loc.prefix ? [cliUnder(loc.prefix)] : []
|
|
19543
|
+
];
|
|
19544
|
+
const pathKey = Object.keys(loc.env).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
19545
|
+
const binDirs = [nodeDir, ...loc.prefix ? [win ? loc.prefix : p.join(loc.prefix, "bin")] : []];
|
|
19546
|
+
const delimiter3 = win ? ";" : ":";
|
|
19547
|
+
const current = loc.env[pathKey] ?? "";
|
|
19548
|
+
const env = { ...loc.env, [pathKey]: [...binDirs, ...current ? [current] : []].join(delimiter3) };
|
|
19549
|
+
const cli = candidates2.find((c) => loc.exists(c));
|
|
19550
|
+
if (cli) return { file: loc.execPath, args: [cli], env, shell: false };
|
|
19551
|
+
return { file: "npm", args: [], env, shell: true };
|
|
19552
|
+
}
|
|
19448
19553
|
function realInstall(tgz) {
|
|
19449
19554
|
const prefix = runningPrefix();
|
|
19555
|
+
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists: existsSync41 });
|
|
19450
19556
|
if (prefix) {
|
|
19451
|
-
npmInstall(
|
|
19557
|
+
npmInstall(npm, ["install", "-g", "--prefix", prefix, tgz]);
|
|
19452
19558
|
return;
|
|
19453
19559
|
}
|
|
19454
19560
|
try {
|
|
19455
|
-
npmInstall(
|
|
19561
|
+
npmInstall(npm, ["install", "-g", tgz]);
|
|
19456
19562
|
} catch {
|
|
19457
|
-
npmInstall(
|
|
19563
|
+
npmInstall(npm, ["install", "-g", "--prefix", join41(homedir15(), ".local"), tgz]);
|
|
19458
19564
|
}
|
|
19459
19565
|
}
|
|
19460
19566
|
function realRestart(platform2) {
|
|
@@ -19555,7 +19661,9 @@ var init_auto_update = __esm({
|
|
|
19555
19661
|
var sync_client_exports = {};
|
|
19556
19662
|
__export(sync_client_exports, {
|
|
19557
19663
|
BATCH_SCAN_MAX_BYTES: () => BATCH_SCAN_MAX_BYTES,
|
|
19664
|
+
DERIVED_MAX_BYTES: () => DERIVED_MAX_BYTES,
|
|
19558
19665
|
FULL_BUILD_MAX_BYTES: () => FULL_BUILD_MAX_BYTES,
|
|
19666
|
+
SYNC_CHUNK_BYTES: () => SYNC_CHUNK_BYTES,
|
|
19559
19667
|
_acceptedUploads: () => _acceptedUploads,
|
|
19560
19668
|
_fetchTenantSyncConfigForTests: () => _fetchTenantSyncConfigForTests,
|
|
19561
19669
|
_resetCapsCacheForTests: () => _resetCapsCacheForTests,
|
|
@@ -19574,8 +19682,10 @@ __export(sync_client_exports, {
|
|
|
19574
19682
|
reconcileFields: () => reconcileFields,
|
|
19575
19683
|
removeCredentials: () => removeCredentials,
|
|
19576
19684
|
saveCredentials: () => saveCredentials,
|
|
19685
|
+
scanTranscriptFindingsChunked: () => scanTranscriptFindingsChunked,
|
|
19577
19686
|
serverAcceptsGzipBody: () => serverAcceptsGzipBody,
|
|
19578
19687
|
serverIngestConcurrency: () => serverIngestConcurrency,
|
|
19688
|
+
sessionBuildBytes: () => sessionBuildBytes,
|
|
19579
19689
|
sessionFileBytes: () => sessionFileBytes,
|
|
19580
19690
|
setServerIngestConcurrency: () => setServerIngestConcurrency,
|
|
19581
19691
|
syncIncremental: () => syncIncremental,
|
|
@@ -19965,7 +20075,7 @@ async function reconcileFields(opts = {}) {
|
|
|
19965
20075
|
let cached = null;
|
|
19966
20076
|
const fullRefs = () => cached ??= listAvailableBackends().flatMap((b) => {
|
|
19967
20077
|
try {
|
|
19968
|
-
return b.listSessions({});
|
|
20078
|
+
return b.listSessions({ previews: false });
|
|
19969
20079
|
} catch {
|
|
19970
20080
|
return [];
|
|
19971
20081
|
}
|
|
@@ -20128,7 +20238,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20128
20238
|
const listSinceMs = changedWalk ? Math.max(0, (opts.sinceMs ?? 0) - CHANGED_WALK_OVERLAP_MS) : opts.useLedger ? void 0 : opts.sinceMs;
|
|
20129
20239
|
const refs = listAvailableBackends().flatMap((b) => {
|
|
20130
20240
|
try {
|
|
20131
|
-
return b.listSessions({ sinceMs: listSinceMs });
|
|
20241
|
+
return b.listSessions({ sinceMs: listSinceMs, previews: false });
|
|
20132
20242
|
} catch {
|
|
20133
20243
|
return [];
|
|
20134
20244
|
}
|
|
@@ -20347,16 +20457,53 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20347
20457
|
clearTimeout(timer);
|
|
20348
20458
|
}
|
|
20349
20459
|
};
|
|
20460
|
+
const postChunkedHead = async (conv, fileSize) => {
|
|
20461
|
+
const headers = { "content-type": "application/json" };
|
|
20462
|
+
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
20463
|
+
const ac = new AbortController();
|
|
20464
|
+
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20465
|
+
try {
|
|
20466
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20467
|
+
method: "POST",
|
|
20468
|
+
headers,
|
|
20469
|
+
body: JSON.stringify({ conversations: [conv] }),
|
|
20470
|
+
signal: ac.signal
|
|
20471
|
+
});
|
|
20472
|
+
if (!res.ok) throw new Error(`chunked head sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
20473
|
+
const body = await res.json().catch(() => ({}));
|
|
20474
|
+
const id = conv.session_id;
|
|
20475
|
+
const guarded = (body.shrink_guarded ?? []).find((g) => g.session_id === id);
|
|
20476
|
+
const mtime = conv.mtime;
|
|
20477
|
+
try {
|
|
20478
|
+
if (!guarded) {
|
|
20479
|
+
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
20480
|
+
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
20481
|
+
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
20482
|
+
} else {
|
|
20483
|
+
markSynced(base3, [{ id, mtime }]);
|
|
20484
|
+
}
|
|
20485
|
+
} catch {
|
|
20486
|
+
}
|
|
20487
|
+
appendResults.uploaded++;
|
|
20488
|
+
} finally {
|
|
20489
|
+
clearTimeout(timer);
|
|
20490
|
+
}
|
|
20491
|
+
};
|
|
20350
20492
|
let appendBatch = [];
|
|
20493
|
+
let appendBatchBytes = 0;
|
|
20351
20494
|
const APPEND_BATCH_SIZE = 50;
|
|
20495
|
+
const APPEND_BATCH_MAX_BYTES = SYNC_CHUNK_BYTES;
|
|
20352
20496
|
const appendFlush = async () => {
|
|
20353
20497
|
if (appendBatch.length === 0) return;
|
|
20354
20498
|
const batch = appendBatch;
|
|
20355
20499
|
appendBatch = [];
|
|
20500
|
+
appendBatchBytes = 0;
|
|
20356
20501
|
await postAppend(batch);
|
|
20357
20502
|
};
|
|
20358
|
-
const appendAdd = async (conv) => {
|
|
20503
|
+
const appendAdd = async (conv, bytes = 0) => {
|
|
20504
|
+
if (appendBatch.length > 0 && appendBatchBytes + bytes > APPEND_BATCH_MAX_BYTES) await appendFlush();
|
|
20359
20505
|
appendBatch.push(conv);
|
|
20506
|
+
appendBatchBytes += bytes;
|
|
20360
20507
|
if (appendBatch.length >= APPEND_BATCH_SIZE) await appendFlush();
|
|
20361
20508
|
};
|
|
20362
20509
|
const itemsBatch = makeBatcher("items", 100);
|
|
@@ -20406,7 +20553,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20406
20553
|
cred,
|
|
20407
20554
|
() => listAvailableBackends().flatMap((b) => {
|
|
20408
20555
|
try {
|
|
20409
|
-
return b.listSessions({});
|
|
20556
|
+
return b.listSessions({ previews: false });
|
|
20410
20557
|
} catch {
|
|
20411
20558
|
return [];
|
|
20412
20559
|
}
|
|
@@ -20435,7 +20582,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20435
20582
|
let externalFindings = null;
|
|
20436
20583
|
if (scanSecrets) {
|
|
20437
20584
|
externalFindings = /* @__PURE__ */ new Map();
|
|
20438
|
-
const toScan = slice.filter((ref) => modeOf(ref) === "full" &&
|
|
20585
|
+
const toScan = slice.filter((ref) => modeOf(ref) === "full" && sessionBuildBytes(ref) <= FULL_BUILD_MAX_BYTES);
|
|
20439
20586
|
trace?.(`batch secret scan start: ${toScan.length} session(s), \u2264${(BATCH_SCAN_MAX_BYTES / 1048576).toFixed(0)}MB per slice`);
|
|
20440
20587
|
const batch = batchScanExternal(
|
|
20441
20588
|
toScan.map((ref) => ({
|
|
@@ -20479,11 +20626,17 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20479
20626
|
const ack = ledger.get(ref.prefixedId);
|
|
20480
20627
|
try {
|
|
20481
20628
|
const tail = await buildConversationTail(ref, ack.o ?? 0, { mapPath, tenantRules });
|
|
20482
|
-
|
|
20629
|
+
const chunked = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
20630
|
+
if (tail && tail.findings.length > 0 && !chunked) {
|
|
20483
20631
|
promotedForFindings = true;
|
|
20484
20632
|
} else if (tail) {
|
|
20485
20633
|
redactions += tail.redactions;
|
|
20486
|
-
await appendAdd(tail.conv);
|
|
20634
|
+
await appendAdd(tail.conv, tail.bytes);
|
|
20635
|
+
if (tail.findings.length > 0) {
|
|
20636
|
+
await appendFlush();
|
|
20637
|
+
const all = await scanTranscriptFindingsChunked(ref, tenantRules);
|
|
20638
|
+
if (all.length > 0) await findingsBatch.add(all);
|
|
20639
|
+
}
|
|
20487
20640
|
walked++;
|
|
20488
20641
|
if (walked % 250 === 0) console.error(`[sync] ${walked}/${slice.length} sessions\u2026`);
|
|
20489
20642
|
continue;
|
|
@@ -20531,12 +20684,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20531
20684
|
}
|
|
20532
20685
|
redactions += built.redactions;
|
|
20533
20686
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
20534
|
-
await
|
|
20687
|
+
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
20688
|
+
else await convBatch.add(built.conv);
|
|
20535
20689
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
20536
20690
|
if (upload.sessionMeta) {
|
|
20537
20691
|
await accumulateKg(extractEntities(built.kgText, { projectPath: built.projectPath, sourceType: "session", sessionId: ref.prefixedId, validFrom: ref.mtime ? new Date(ref.mtime).toISOString().slice(0, 10) : void 0 }), ref.prefixedId);
|
|
20538
20692
|
}
|
|
20539
|
-
if (upload.sessionMeta && sessionFileBytes(ref) <=
|
|
20693
|
+
if (upload.sessionMeta && sessionFileBytes(ref) <= DERIVED_MAX_BYTES) {
|
|
20540
20694
|
try {
|
|
20541
20695
|
const count = { redactions: 0 };
|
|
20542
20696
|
const offloaded = await scanPool().runDerived({
|
|
@@ -20716,35 +20870,70 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20716
20870
|
scanMs: Math.round(scanMs)
|
|
20717
20871
|
};
|
|
20718
20872
|
}
|
|
20873
|
+
async function scanTranscriptFindingsChunked(ref, tenantRules) {
|
|
20874
|
+
const backend = getBackendForId(ref.prefixedId);
|
|
20875
|
+
const findings = [];
|
|
20876
|
+
if (!backend?.readFromOffset) return findings;
|
|
20877
|
+
let offset = 0;
|
|
20878
|
+
let lineBase = 0;
|
|
20879
|
+
for (; ; ) {
|
|
20880
|
+
const chunk = await backend.readFromOffset(ref.prefixedId, offset, SYNC_CHUNK_BYTES);
|
|
20881
|
+
if (chunk.newOffset <= offset) break;
|
|
20882
|
+
offset = chunk.newOffset;
|
|
20883
|
+
if (chunk.skippedBytes) {
|
|
20884
|
+
lineBase += 1;
|
|
20885
|
+
continue;
|
|
20886
|
+
}
|
|
20887
|
+
try {
|
|
20888
|
+
for (const f of scanTextForFindings(chunk.text)) {
|
|
20889
|
+
findings.push({ session_id: ref.prefixedId, detector: "builtin", rule: f.rule, line: lineBase + f.line, preview: f.preview });
|
|
20890
|
+
}
|
|
20891
|
+
if (tenantRules && tenantRules.length > 0) {
|
|
20892
|
+
for (const f of scanTenantRules(chunk.text, tenantRules)) {
|
|
20893
|
+
findings.push({ session_id: ref.prefixedId, detector: f.detector, rule: f.rule, line: lineBase + f.line, preview: f.preview });
|
|
20894
|
+
}
|
|
20895
|
+
}
|
|
20896
|
+
} catch {
|
|
20897
|
+
}
|
|
20898
|
+
for (let i = chunk.text.indexOf("\n"); i >= 0; i = chunk.text.indexOf("\n", i + 1)) lineBase++;
|
|
20899
|
+
}
|
|
20900
|
+
return dropFuzzyFindings(findings, (f) => ({ detector: f.detector, rule: f.rule }));
|
|
20901
|
+
}
|
|
20719
20902
|
function sessionFileBytes(ref) {
|
|
20720
20903
|
const backend = getBackendForId(ref.prefixedId);
|
|
20721
20904
|
if (!backend?.isAppendOnly?.()) return 0;
|
|
20722
20905
|
return backend.fileSize?.(ref.prefixedId) ?? 0;
|
|
20723
20906
|
}
|
|
20907
|
+
function sessionBuildBytes(ref) {
|
|
20908
|
+
const main = sessionFileBytes(ref);
|
|
20909
|
+
if (main === 0) return 0;
|
|
20910
|
+
return Math.max(main, shadowUncompressedBytes(ref.toolId, ref.rawId));
|
|
20911
|
+
}
|
|
20724
20912
|
async function buildConversationSync(ref, mtime, opts = {}) {
|
|
20725
20913
|
const mapPath = opts.mapPath ?? ((p) => p);
|
|
20726
20914
|
let includeRaw = opts.includeRaw !== false;
|
|
20727
20915
|
let includeMeta = opts.includeMeta !== false;
|
|
20728
20916
|
let srcHash;
|
|
20729
|
-
const
|
|
20730
|
-
|
|
20731
|
-
let
|
|
20732
|
-
let tailOffsetEnd = 0;
|
|
20917
|
+
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
20918
|
+
let headOffsetEnd = 0;
|
|
20919
|
+
let oversizedFindings = null;
|
|
20733
20920
|
let transcript = null;
|
|
20734
20921
|
let fullestContainer = null;
|
|
20735
20922
|
if (oversized) {
|
|
20736
20923
|
const backend = getBackendForId(ref.prefixedId);
|
|
20737
20924
|
if (!backend?.readFromOffset) return null;
|
|
20738
20925
|
try {
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20926
|
+
let head = await backend.readFromOffset(ref.prefixedId, 0, SYNC_CHUNK_BYTES);
|
|
20927
|
+
for (let hops = 0; head.skippedBytes && hops < 8; hops++) {
|
|
20928
|
+
head = await backend.readFromOffset(ref.prefixedId, head.newOffset, SYNC_CHUNK_BYTES);
|
|
20929
|
+
}
|
|
20930
|
+
headOffsetEnd = head.newOffset;
|
|
20931
|
+
const messages = parseTailMessages(ref.toolId, head.text);
|
|
20743
20932
|
if (messages.length > 0) transcript = { messages, subagents: [] };
|
|
20744
20933
|
} catch {
|
|
20745
20934
|
}
|
|
20746
20935
|
includeRaw = false;
|
|
20747
|
-
|
|
20936
|
+
oversizedFindings = await scanTranscriptFindingsChunked(ref, opts.tenantRules);
|
|
20748
20937
|
} else {
|
|
20749
20938
|
try {
|
|
20750
20939
|
const backend = getBackendForId(ref.prefixedId) ?? getBackend("claude");
|
|
@@ -20805,7 +20994,6 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20805
20994
|
);
|
|
20806
20995
|
let projectPath = ref.projectPath;
|
|
20807
20996
|
const meta = { messageCount: textMessages.length };
|
|
20808
|
-
if (oversized) meta.truncated = true;
|
|
20809
20997
|
if (textMessages.filter((m) => m.role === "user").length <= 1) meta.oneShot = true;
|
|
20810
20998
|
try {
|
|
20811
20999
|
const cwd = ref.fullPath ? readCwdFromJsonl(ref.fullPath) : "";
|
|
@@ -20919,21 +21107,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20919
21107
|
}
|
|
20920
21108
|
scanMs = performance.now() - t0;
|
|
20921
21109
|
}
|
|
20922
|
-
if (
|
|
20923
|
-
const t0 = performance.now();
|
|
20924
|
-
try {
|
|
20925
|
-
for (const f of scanTextForFindings(tailText)) {
|
|
20926
|
-
findings.push({ session_id: ref.prefixedId, detector: "builtin", rule: f.rule, line: f.line, preview: f.preview });
|
|
20927
|
-
}
|
|
20928
|
-
if (opts.tenantRules && opts.tenantRules.length > 0) {
|
|
20929
|
-
for (const f of scanTenantRules(tailText, opts.tenantRules)) {
|
|
20930
|
-
findings.push({ session_id: ref.prefixedId, detector: f.detector, rule: f.rule, line: f.line, preview: f.preview });
|
|
20931
|
-
}
|
|
20932
|
-
}
|
|
20933
|
-
} catch {
|
|
20934
|
-
}
|
|
20935
|
-
scanMs = performance.now() - t0;
|
|
20936
|
-
}
|
|
21110
|
+
if (oversizedFindings) findings.push(...oversizedFindings);
|
|
20937
21111
|
const keptFindings = dropFuzzyFindings(findings, (f) => ({ detector: f.detector, rule: f.rule }));
|
|
20938
21112
|
findings.length = 0;
|
|
20939
21113
|
findings.push(...keptFindings);
|
|
@@ -20979,7 +21153,10 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20979
21153
|
// (convBatch onFlush uses this, not a recomputed size) so the next
|
|
20980
21154
|
// append's base_offset matches exactly — no spurious continuity misses on
|
|
20981
21155
|
// an actively-growing session. undefined for non-append-only backends.
|
|
20982
|
-
from_offset: oversized ?
|
|
21156
|
+
from_offset: oversized ? headOffsetEnd : getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId),
|
|
21157
|
+
// The head of a chunked session. The server reports back when its shrink
|
|
21158
|
+
// guard keeps a fuller stored copy, so the client appends from there.
|
|
21159
|
+
...oversized ? { chunked: true } : {},
|
|
20983
21160
|
meta,
|
|
20984
21161
|
mtime
|
|
20985
21162
|
},
|
|
@@ -21001,12 +21178,30 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
|
|
|
21001
21178
|
const backend = getBackendForId(ref.prefixedId);
|
|
21002
21179
|
if (!backend?.readFromOffset) return null;
|
|
21003
21180
|
const mapPath = opts.mapPath ?? ((p) => p);
|
|
21004
|
-
const { text: tailText, newOffset } = await backend.readFromOffset(ref.prefixedId, fromOffset);
|
|
21005
|
-
if (
|
|
21006
|
-
const messages = parseTailMessages(ref.toolId, tailText);
|
|
21007
|
-
if (messages.length === 0) return null;
|
|
21181
|
+
const { text: tailText, newOffset, skippedBytes } = await backend.readFromOffset(ref.prefixedId, fromOffset, SYNC_CHUNK_BYTES);
|
|
21182
|
+
if (newOffset <= fromOffset) return null;
|
|
21183
|
+
const messages = skippedBytes ? [] : parseTailMessages(ref.toolId, tailText);
|
|
21008
21184
|
const textMessages = messages.filter((m) => m.role !== "summary" && m.content?.trim());
|
|
21009
|
-
|
|
21185
|
+
const hasContent = textMessages.length > 0 || messages.some((m) => m.toolCalls?.length);
|
|
21186
|
+
if (!hasContent) {
|
|
21187
|
+
return {
|
|
21188
|
+
conv: {
|
|
21189
|
+
session_id: ref.prefixedId,
|
|
21190
|
+
tool: ref.toolId,
|
|
21191
|
+
project_path: mapPath(ref.projectPath),
|
|
21192
|
+
append: true,
|
|
21193
|
+
base_offset: fromOffset,
|
|
21194
|
+
from_offset: newOffset,
|
|
21195
|
+
redacted_text: "",
|
|
21196
|
+
envelope: { v: TRANSCRIPT_VERSION, messages: [], subagents: [] },
|
|
21197
|
+
mtime: Math.floor(ref.mtime) || 0
|
|
21198
|
+
},
|
|
21199
|
+
redactions: 0,
|
|
21200
|
+
newOffset,
|
|
21201
|
+
findings: [],
|
|
21202
|
+
bytes: 0
|
|
21203
|
+
};
|
|
21204
|
+
}
|
|
21010
21205
|
const firstUser = textMessages.find((m) => m.role === "user");
|
|
21011
21206
|
if (isInternalToolPrompt(firstUser?.content)) return null;
|
|
21012
21207
|
const count = { redactions: 0 };
|
|
@@ -21049,7 +21244,8 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
|
|
|
21049
21244
|
},
|
|
21050
21245
|
redactions: count.redactions,
|
|
21051
21246
|
newOffset,
|
|
21052
|
-
findings
|
|
21247
|
+
findings,
|
|
21248
|
+
bytes: Buffer.byteLength(tailText)
|
|
21053
21249
|
};
|
|
21054
21250
|
}
|
|
21055
21251
|
function isSyncSkip(r) {
|
|
@@ -21079,7 +21275,7 @@ async function syncIncremental(opts = {}) {
|
|
|
21079
21275
|
lock.release();
|
|
21080
21276
|
}
|
|
21081
21277
|
}
|
|
21082
|
-
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES,
|
|
21278
|
+
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, DERIVED_MAX_BYTES, SYNC_CHUNK_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
21083
21279
|
var init_sync_client = __esm({
|
|
21084
21280
|
"src/sync-client.ts"() {
|
|
21085
21281
|
"use strict";
|
|
@@ -21124,7 +21320,7 @@ var init_sync_client = __esm({
|
|
|
21124
21320
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21125
21321
|
} catch {
|
|
21126
21322
|
try {
|
|
21127
|
-
if (true) ownVersion = "0.7.
|
|
21323
|
+
if (true) ownVersion = "0.7.2";
|
|
21128
21324
|
} catch {
|
|
21129
21325
|
}
|
|
21130
21326
|
}
|
|
@@ -21151,8 +21347,9 @@ var init_sync_client = __esm({
|
|
|
21151
21347
|
capsOk = /* @__PURE__ */ new Map();
|
|
21152
21348
|
advertisedIngestConc = /* @__PURE__ */ new Map();
|
|
21153
21349
|
advertisedGzipBody = /* @__PURE__ */ new Set();
|
|
21154
|
-
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "
|
|
21155
|
-
|
|
21350
|
+
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "24", 10)) * 1024 * 1024;
|
|
21351
|
+
DERIVED_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_DERIVED_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21352
|
+
SYNC_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
21156
21353
|
BATCH_SCAN_MAX_BYTES = Math.max(1, parseInt(process.env.CHAT_RECALL_BATCHSCAN_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21157
21354
|
}
|
|
21158
21355
|
});
|
|
@@ -21273,7 +21470,7 @@ var init_update_notice = __esm({
|
|
|
21273
21470
|
});
|
|
21274
21471
|
|
|
21275
21472
|
// ../engine/dist/core/which.js
|
|
21276
|
-
import { existsSync as
|
|
21473
|
+
import { existsSync as existsSync42, statSync as statSync38, accessSync, constants } from "node:fs";
|
|
21277
21474
|
import { join as join44, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
21278
21475
|
function executable(p) {
|
|
21279
21476
|
try {
|
|
@@ -21314,7 +21511,7 @@ function resolveOnPath(name) {
|
|
|
21314
21511
|
continue;
|
|
21315
21512
|
for (const c of candidates(name)) {
|
|
21316
21513
|
const full = join44(dir, c);
|
|
21317
|
-
if (
|
|
21514
|
+
if (existsSync42(full) && executable(full))
|
|
21318
21515
|
return full;
|
|
21319
21516
|
}
|
|
21320
21517
|
}
|
|
@@ -21377,7 +21574,7 @@ __export(mcp_clients_exports, {
|
|
|
21377
21574
|
inspectMcpClients: () => inspectMcpClients,
|
|
21378
21575
|
registerMcpEverywhere: () => registerMcpEverywhere
|
|
21379
21576
|
});
|
|
21380
|
-
import { existsSync as
|
|
21577
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync12, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "fs";
|
|
21381
21578
|
import { homedir as homedir16 } from "os";
|
|
21382
21579
|
import { dirname as dirname21, join as join46 } from "path";
|
|
21383
21580
|
function envHome(varName, fallback) {
|
|
@@ -21396,7 +21593,7 @@ function readJsonObject(path) {
|
|
|
21396
21593
|
}
|
|
21397
21594
|
function registerMcpServersJson(target, path, spec) {
|
|
21398
21595
|
let cfg = {};
|
|
21399
|
-
if (
|
|
21596
|
+
if (existsSync44(path)) {
|
|
21400
21597
|
try {
|
|
21401
21598
|
cfg = readJsonObject(path);
|
|
21402
21599
|
} catch (err) {
|
|
@@ -21425,7 +21622,7 @@ function registerOpencodeJson(path, spec) {
|
|
|
21425
21622
|
const id = "opencode";
|
|
21426
21623
|
const label = "OpenCode";
|
|
21427
21624
|
let cfg = {};
|
|
21428
|
-
if (
|
|
21625
|
+
if (existsSync44(path)) {
|
|
21429
21626
|
try {
|
|
21430
21627
|
cfg = readJsonObject(path);
|
|
21431
21628
|
} catch (err) {
|
|
@@ -21464,7 +21661,7 @@ function registerCodexToml(path, spec) {
|
|
|
21464
21661
|
const id = "codex";
|
|
21465
21662
|
const label = "Codex";
|
|
21466
21663
|
const block = codexBlock(spec);
|
|
21467
|
-
const prev =
|
|
21664
|
+
const prev = existsSync44(path) ? readFileSync37(path, "utf-8") : "";
|
|
21468
21665
|
const lines = prev.length ? prev.split("\n") : [];
|
|
21469
21666
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
21470
21667
|
if (start === -1) {
|
|
@@ -21505,7 +21702,7 @@ function inspectMcpClients(opts = {}) {
|
|
|
21505
21702
|
return MCP_CLIENTS.map((c) => {
|
|
21506
21703
|
const path = c.configPath(home);
|
|
21507
21704
|
let registered = false;
|
|
21508
|
-
if (
|
|
21705
|
+
if (existsSync44(path)) {
|
|
21509
21706
|
try {
|
|
21510
21707
|
const raw = readFileSync37(path, "utf-8");
|
|
21511
21708
|
registered = c.id === "codex" ? raw.includes(CODEX_HEADER) : !!(JSON.parse(raw).mcpServers?.[MCP_SERVER_NAME] ?? JSON.parse(raw).mcp?.[MCP_SERVER_NAME]);
|
|
@@ -21542,7 +21739,7 @@ var init_mcp_clients = __esm({
|
|
|
21542
21739
|
configPath: (home) => join46(envHome("CHAT_RECALL_CODEX_HOME", join46(home, ".codex")), "config.toml"),
|
|
21543
21740
|
isPresent(home) {
|
|
21544
21741
|
const p = this.configPath(home);
|
|
21545
|
-
return
|
|
21742
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21546
21743
|
},
|
|
21547
21744
|
register(spec, home) {
|
|
21548
21745
|
return registerCodexToml(this.configPath(home), spec);
|
|
@@ -21555,7 +21752,7 @@ var init_mcp_clients = __esm({
|
|
|
21555
21752
|
configPath: (home) => join46(envHome("XDG_CONFIG_HOME", join46(home, ".config")), "opencode", "opencode.json"),
|
|
21556
21753
|
isPresent(home) {
|
|
21557
21754
|
const p = this.configPath(home);
|
|
21558
|
-
return
|
|
21755
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21559
21756
|
},
|
|
21560
21757
|
register(spec, home) {
|
|
21561
21758
|
return registerOpencodeJson(this.configPath(home), spec);
|
|
@@ -21569,7 +21766,7 @@ var init_mcp_clients = __esm({
|
|
|
21569
21766
|
bin: "agy",
|
|
21570
21767
|
configPath: (home) => join46(home, ".gemini", "config", "mcp_config.json"),
|
|
21571
21768
|
isPresent(home) {
|
|
21572
|
-
return
|
|
21769
|
+
return existsSync44(join46(home, ".gemini", "antigravity-cli")) || existsSync44(this.configPath(home));
|
|
21573
21770
|
},
|
|
21574
21771
|
register(spec, home) {
|
|
21575
21772
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -21582,7 +21779,7 @@ var init_mcp_clients = __esm({
|
|
|
21582
21779
|
configPath: (home) => join46(home, ".cursor", "mcp.json"),
|
|
21583
21780
|
isPresent(home) {
|
|
21584
21781
|
const p = this.configPath(home);
|
|
21585
|
-
return
|
|
21782
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21586
21783
|
},
|
|
21587
21784
|
register(spec, home) {
|
|
21588
21785
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -21606,7 +21803,7 @@ __export(companions_exports, {
|
|
|
21606
21803
|
uninstallCodeindex: () => uninstallCodeindex,
|
|
21607
21804
|
unregisterCodeindexMcp: () => unregisterCodeindexMcp
|
|
21608
21805
|
});
|
|
21609
|
-
import { existsSync as
|
|
21806
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync39, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync38, writeFileSync as writeFileSync13 } from "node:fs";
|
|
21610
21807
|
import { homedir as homedir17 } from "node:os";
|
|
21611
21808
|
import { join as join47 } from "node:path";
|
|
21612
21809
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -21729,7 +21926,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
21729
21926
|
renameSync5(tmpPath, CODEINDEX_BIN_PATH);
|
|
21730
21927
|
} catch (err) {
|
|
21731
21928
|
try {
|
|
21732
|
-
if (
|
|
21929
|
+
if (existsSync45(tmpPath))
|
|
21733
21930
|
unlinkSync3(tmpPath);
|
|
21734
21931
|
} catch {
|
|
21735
21932
|
}
|
|
@@ -21738,7 +21935,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
21738
21935
|
return checkCodeindexStatus();
|
|
21739
21936
|
}
|
|
21740
21937
|
function uninstallCodeindex() {
|
|
21741
|
-
if (
|
|
21938
|
+
if (existsSync45(CODEINDEX_BIN_PATH)) {
|
|
21742
21939
|
unlinkSync3(CODEINDEX_BIN_PATH);
|
|
21743
21940
|
return { removed: true, path: CODEINDEX_BIN_PATH };
|
|
21744
21941
|
}
|
|
@@ -21746,7 +21943,7 @@ function uninstallCodeindex() {
|
|
|
21746
21943
|
}
|
|
21747
21944
|
function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
21748
21945
|
let cfg = {};
|
|
21749
|
-
if (
|
|
21946
|
+
if (existsSync45(mcpJsonPath)) {
|
|
21750
21947
|
try {
|
|
21751
21948
|
cfg = JSON.parse(readFileSync38(mcpJsonPath, "utf-8"));
|
|
21752
21949
|
} catch {
|
|
@@ -21761,7 +21958,7 @@ function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
|
21761
21958
|
return { added: true };
|
|
21762
21959
|
}
|
|
21763
21960
|
function unregisterCodeindexMcp(mcpJsonPath) {
|
|
21764
|
-
if (!
|
|
21961
|
+
if (!existsSync45(mcpJsonPath))
|
|
21765
21962
|
return { removed: false };
|
|
21766
21963
|
let cfg;
|
|
21767
21964
|
try {
|
|
@@ -21807,7 +22004,7 @@ __export(install_skills_exports, {
|
|
|
21807
22004
|
skillsSourceDir: () => skillsSourceDir,
|
|
21808
22005
|
uninstallSkills: () => uninstallSkills
|
|
21809
22006
|
});
|
|
21810
|
-
import { readdirSync as readdirSync33, existsSync as
|
|
22007
|
+
import { readdirSync as readdirSync33, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync7, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync39, statSync as statSync40, realpathSync as realpathSync4 } from "fs";
|
|
21811
22008
|
import { createHash as createHash11 } from "crypto";
|
|
21812
22009
|
import { join as join48, basename as basename21 } from "path";
|
|
21813
22010
|
function skillsSourceDir() {
|
|
@@ -21846,8 +22043,8 @@ function skillStamp() {
|
|
|
21846
22043
|
}
|
|
21847
22044
|
function bundledSkillNames() {
|
|
21848
22045
|
const src = skillsSourceDir();
|
|
21849
|
-
if (!
|
|
21850
|
-
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() &&
|
|
22046
|
+
if (!existsSync46(src)) return [];
|
|
22047
|
+
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync46(join48(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
21851
22048
|
}
|
|
21852
22049
|
function realPathOrSelf(p) {
|
|
21853
22050
|
try {
|
|
@@ -21871,7 +22068,7 @@ function claudeSkillTargets() {
|
|
|
21871
22068
|
dir,
|
|
21872
22069
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
21873
22070
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
21874
|
-
available:
|
|
22071
|
+
available: existsSync46(join48(home, "projects"))
|
|
21875
22072
|
});
|
|
21876
22073
|
}
|
|
21877
22074
|
if (targets.length === 0) {
|
|
@@ -21895,7 +22092,7 @@ function skillTargets() {
|
|
|
21895
22092
|
];
|
|
21896
22093
|
}
|
|
21897
22094
|
function isManaged(dir) {
|
|
21898
|
-
return
|
|
22095
|
+
return existsSync46(join48(dir, MARKER));
|
|
21899
22096
|
}
|
|
21900
22097
|
function installSkills(opts = {}) {
|
|
21901
22098
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -21913,7 +22110,7 @@ function installSkills(opts = {}) {
|
|
|
21913
22110
|
}
|
|
21914
22111
|
for (const name of names) {
|
|
21915
22112
|
const dest = join48(t.dir, name);
|
|
21916
|
-
if (
|
|
22113
|
+
if (existsSync46(dest) && !isManaged(dest)) {
|
|
21917
22114
|
skippedUserOwned.push(name);
|
|
21918
22115
|
continue;
|
|
21919
22116
|
}
|
|
@@ -21933,7 +22130,7 @@ function uninstallSkills() {
|
|
|
21933
22130
|
const perTarget = [];
|
|
21934
22131
|
for (const t of skillTargets()) {
|
|
21935
22132
|
const removed = [];
|
|
21936
|
-
if (!
|
|
22133
|
+
if (!existsSync46(t.dir)) {
|
|
21937
22134
|
perTarget.push({ id: t.id, label: t.label, removed });
|
|
21938
22135
|
continue;
|
|
21939
22136
|
}
|
|
@@ -21957,7 +22154,7 @@ function skillsNeedRefresh() {
|
|
|
21957
22154
|
if (!t.available) continue;
|
|
21958
22155
|
for (const name of names) {
|
|
21959
22156
|
const marker = join48(t.dir, name, MARKER);
|
|
21960
|
-
if (!
|
|
22157
|
+
if (!existsSync46(marker)) return true;
|
|
21961
22158
|
try {
|
|
21962
22159
|
if (readFileSync39(marker, "utf-8").trim() !== cur) return true;
|
|
21963
22160
|
} catch {
|
|
@@ -21975,7 +22172,7 @@ function skillStatus() {
|
|
|
21975
22172
|
let ver = null;
|
|
21976
22173
|
for (const name of names) {
|
|
21977
22174
|
const marker = join48(t.dir, name, MARKER);
|
|
21978
|
-
if (
|
|
22175
|
+
if (existsSync46(marker)) {
|
|
21979
22176
|
installed++;
|
|
21980
22177
|
try {
|
|
21981
22178
|
ver = readFileSync39(marker, "utf-8").trim();
|
|
@@ -22163,7 +22360,7 @@ __export(toolkit_sync_exports, {
|
|
|
22163
22360
|
supportedTargetsFor: () => supportedTargetsFor,
|
|
22164
22361
|
writeMcpEntry: () => writeMcpEntry
|
|
22165
22362
|
});
|
|
22166
|
-
import { existsSync as
|
|
22363
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync15, readFileSync as readFileSync41, writeFileSync as writeFileSync15, cpSync as cpSync2 } from "fs";
|
|
22167
22364
|
import { dirname as dirname22, join as join50, basename as basename23 } from "path";
|
|
22168
22365
|
import { homedir as homedir19 } from "os";
|
|
22169
22366
|
function supportedTargetsFor(type) {
|
|
@@ -22218,11 +22415,11 @@ function skillsDirFor(tool) {
|
|
|
22218
22415
|
}
|
|
22219
22416
|
function copySkill(row, toTool) {
|
|
22220
22417
|
const skillDir = row.extra.skillDir || dirname22(row.filePath);
|
|
22221
|
-
if (!
|
|
22418
|
+
if (!existsSync47(skillDir))
|
|
22222
22419
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
22223
22420
|
const name = row.extra.skillName || basename23(skillDir);
|
|
22224
22421
|
const targetDir = join50(skillsDirFor(toTool), name);
|
|
22225
|
-
if (
|
|
22422
|
+
if (existsSync47(targetDir))
|
|
22226
22423
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
22227
22424
|
try {
|
|
22228
22425
|
mkdirSync15(dirname22(targetDir), { recursive: true });
|
|
@@ -22254,7 +22451,7 @@ function readMcpEntry(tool, name) {
|
|
|
22254
22451
|
return entry;
|
|
22255
22452
|
}
|
|
22256
22453
|
for (const t of tries) {
|
|
22257
|
-
if (!
|
|
22454
|
+
if (!existsSync47(t.path))
|
|
22258
22455
|
continue;
|
|
22259
22456
|
try {
|
|
22260
22457
|
const cfg = JSON.parse(readFileSync41(t.path, "utf-8"));
|
|
@@ -22267,7 +22464,7 @@ function readMcpEntry(tool, name) {
|
|
|
22267
22464
|
return null;
|
|
22268
22465
|
}
|
|
22269
22466
|
function readCodexMcpEntry(path, target) {
|
|
22270
|
-
if (!
|
|
22467
|
+
if (!existsSync47(path))
|
|
22271
22468
|
return null;
|
|
22272
22469
|
let content;
|
|
22273
22470
|
try {
|
|
@@ -22321,7 +22518,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
22321
22518
|
}
|
|
22322
22519
|
function writeCodexMcpEntry(path, name, entry) {
|
|
22323
22520
|
let content = "";
|
|
22324
|
-
if (
|
|
22521
|
+
if (existsSync47(path))
|
|
22325
22522
|
content = readFileSync41(path, "utf-8");
|
|
22326
22523
|
const header = `[mcp_servers.${name}]`;
|
|
22327
22524
|
if (content.includes(header))
|
|
@@ -22379,7 +22576,7 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
22379
22576
|
key2 = "mcp";
|
|
22380
22577
|
}
|
|
22381
22578
|
let cfg = {};
|
|
22382
|
-
if (
|
|
22579
|
+
if (existsSync47(path)) {
|
|
22383
22580
|
try {
|
|
22384
22581
|
cfg = JSON.parse(readFileSync41(path, "utf-8"));
|
|
22385
22582
|
} catch {
|
|
@@ -22443,7 +22640,7 @@ function copyCommandOrAgent(type, row, toTool) {
|
|
|
22443
22640
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
22444
22641
|
}
|
|
22445
22642
|
const out = emit(type, art, toTool);
|
|
22446
|
-
if (
|
|
22643
|
+
if (existsSync47(out.path))
|
|
22447
22644
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
22448
22645
|
try {
|
|
22449
22646
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -22463,7 +22660,7 @@ function copyInstructions(row, toTool) {
|
|
|
22463
22660
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
22464
22661
|
}
|
|
22465
22662
|
const out = emit("instructions", art, toTool, row.projectPath || void 0);
|
|
22466
|
-
if (
|
|
22663
|
+
if (existsSync47(out.path))
|
|
22467
22664
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
22468
22665
|
try {
|
|
22469
22666
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -22613,7 +22810,7 @@ __export(toolkit_pull_exports, {
|
|
|
22613
22810
|
planPull: () => planPull,
|
|
22614
22811
|
portableCommand: () => portableCommand
|
|
22615
22812
|
});
|
|
22616
|
-
import { existsSync as
|
|
22813
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync41, writeFileSync as writeFileSync16 } from "node:fs";
|
|
22617
22814
|
import { dirname as dirname23, join as join51, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
|
|
22618
22815
|
function isExecutableFile(p) {
|
|
22619
22816
|
try {
|
|
@@ -22766,7 +22963,7 @@ function executePull(rows, opts = {}) {
|
|
|
22766
22963
|
for (const tool of tools) {
|
|
22767
22964
|
const dir = join51(skillsDirFor(tool), name);
|
|
22768
22965
|
const file = join51(dir, "SKILL.md");
|
|
22769
|
-
if (
|
|
22966
|
+
if (existsSync48(file)) {
|
|
22770
22967
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
22771
22968
|
continue;
|
|
22772
22969
|
}
|
|
@@ -22811,7 +23008,7 @@ function executePull(rows, opts = {}) {
|
|
|
22811
23008
|
outcomes.push({ type, name, tool, status: "failed", reason: e instanceof Error ? e.message : "emit failed" });
|
|
22812
23009
|
continue;
|
|
22813
23010
|
}
|
|
22814
|
-
if (
|
|
23011
|
+
if (existsSync48(out.path)) {
|
|
22815
23012
|
outcomes.push({ type, name, tool, status: "present" });
|
|
22816
23013
|
continue;
|
|
22817
23014
|
}
|
|
@@ -22969,7 +23166,7 @@ __export(board_hooks_exports, {
|
|
|
22969
23166
|
removeBoardHooks: () => removeBoardHooks,
|
|
22970
23167
|
resolveCliEntry: () => resolveCliEntry
|
|
22971
23168
|
});
|
|
22972
|
-
import { existsSync as
|
|
23169
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync17, readFileSync as readFileSync42, writeFileSync as writeFileSync17 } from "node:fs";
|
|
22973
23170
|
import { dirname as dirname24, join as join52 } from "node:path";
|
|
22974
23171
|
function boardHookCommand(execPath, cliEntry, mode) {
|
|
22975
23172
|
return `"${execPath}" "${cliEntry}" task-hook --${mode}`;
|
|
@@ -23009,7 +23206,7 @@ function removeBoardHooks(config2) {
|
|
|
23009
23206
|
return removed;
|
|
23010
23207
|
}
|
|
23011
23208
|
function readConfig(file) {
|
|
23012
|
-
if (!
|
|
23209
|
+
if (!existsSync49(file)) return { hooks: {} };
|
|
23013
23210
|
try {
|
|
23014
23211
|
const parsed = JSON.parse(readFileSync42(file, "utf-8"));
|
|
23015
23212
|
if (!parsed.hooks || typeof parsed.hooks !== "object") parsed.hooks = {};
|
|
@@ -23021,7 +23218,7 @@ function readConfig(file) {
|
|
|
23021
23218
|
function registerBoardHooks(files, execPath, cliEntry) {
|
|
23022
23219
|
const written = [];
|
|
23023
23220
|
for (const file of files) {
|
|
23024
|
-
if (
|
|
23221
|
+
if (existsSync49(file)) {
|
|
23025
23222
|
try {
|
|
23026
23223
|
JSON.parse(readFileSync42(file, "utf-8"));
|
|
23027
23224
|
} catch {
|
|
@@ -23041,7 +23238,7 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23041
23238
|
}
|
|
23042
23239
|
function resolveCliEntry(distDir) {
|
|
23043
23240
|
const bundled = join52(distDir, "cli.js");
|
|
23044
|
-
return
|
|
23241
|
+
return existsSync49(bundled) ? bundled : join52(distDir, "cli.ts");
|
|
23045
23242
|
}
|
|
23046
23243
|
var BOARD_HOOKS;
|
|
23047
23244
|
var init_board_hooks = __esm({
|
|
@@ -23144,6 +23341,9 @@ async function repairSession(id, opts = {}) {
|
|
|
23144
23341
|
note: "archive count is a lower bound; the rebuild also unions the on-disk tail"
|
|
23145
23342
|
};
|
|
23146
23343
|
}
|
|
23344
|
+
if (!opts.force && endpoints.every((ep) => (currentOnServer.get(ep.url) ?? 0) >= fullest.messages)) {
|
|
23345
|
+
return { sessionId: id, status: "already-full", fullestMessages: fullest.messages, fullestSource: fullest.source, pushed: [] };
|
|
23346
|
+
}
|
|
23147
23347
|
seedShadow(rawId, fullest.container);
|
|
23148
23348
|
const located = backend.findSession(rawId);
|
|
23149
23349
|
const projectPath = located?.projectPath || cwdFromContainer(fullest.container);
|
|
@@ -23186,7 +23386,7 @@ async function repairSession(id, opts = {}) {
|
|
|
23186
23386
|
try {
|
|
23187
23387
|
const res = await fetchWithTimeout(`${ep.url}/api/sync`, { method: "POST", headers, body: JSON.stringify({ conversations: [built.conv] }) }, 6e4);
|
|
23188
23388
|
if (!res.ok) {
|
|
23189
|
-
pushed.push({ server: ep.url, before, after: before });
|
|
23389
|
+
pushed.push({ server: ep.url, before, after: before, error: `HTTP ${res.status}` });
|
|
23190
23390
|
log6(`push to ${ep.url} FAILED: HTTP ${res.status}`);
|
|
23191
23391
|
continue;
|
|
23192
23392
|
}
|
|
@@ -23195,10 +23395,21 @@ async function repairSession(id, opts = {}) {
|
|
|
23195
23395
|
pushed.push({ server: ep.url, before, after: afterN });
|
|
23196
23396
|
log6(`pushed to ${ep.url}: ${before} \u2192 ${afterN} msg(s)`);
|
|
23197
23397
|
} catch (e) {
|
|
23198
|
-
|
|
23199
|
-
|
|
23398
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
23399
|
+
pushed.push({ server: ep.url, before, after: before, error });
|
|
23400
|
+
log6(`push to ${ep.url} errored: ${error}`);
|
|
23200
23401
|
}
|
|
23201
23402
|
}
|
|
23403
|
+
if (pushed.every((p) => p.error)) {
|
|
23404
|
+
return {
|
|
23405
|
+
sessionId: id,
|
|
23406
|
+
status: "error",
|
|
23407
|
+
fullestMessages: builtCount,
|
|
23408
|
+
fullestSource: fullest.source,
|
|
23409
|
+
pushed,
|
|
23410
|
+
note: `every push failed: ${pushed.map((p) => `${p.server}: ${p.error}`).join("; ")}`
|
|
23411
|
+
};
|
|
23412
|
+
}
|
|
23202
23413
|
return { sessionId: id, status: "repaired", fullestMessages: builtCount, fullestSource: fullest.source, pushed };
|
|
23203
23414
|
}
|
|
23204
23415
|
async function repairSessions(ids, opts = {}) {
|
|
@@ -23693,11 +23904,11 @@ var verify_repair_exports = {};
|
|
|
23693
23904
|
__export(verify_repair_exports, {
|
|
23694
23905
|
forceFullResync: () => forceFullResync
|
|
23695
23906
|
});
|
|
23696
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
23907
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync50 } from "fs";
|
|
23697
23908
|
function forceFullResync(server, sessionIds) {
|
|
23698
23909
|
if (sessionIds.length === 0) return 0;
|
|
23699
23910
|
const path = ledgerFilePath();
|
|
23700
|
-
if (
|
|
23911
|
+
if (existsSync50(path)) {
|
|
23701
23912
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/-/g, "");
|
|
23702
23913
|
try {
|
|
23703
23914
|
copyFileSync3(path, `${path}.bak-${stamp}`);
|
|
@@ -23900,7 +24111,10 @@ async function resolveCodeindexBin(autoInstall = true) {
|
|
|
23900
24111
|
}
|
|
23901
24112
|
function runMcp(binPath, workspace, calls, timeoutMs = 18e4) {
|
|
23902
24113
|
return new Promise((resolve3, reject) => {
|
|
23903
|
-
const p = spawn3(binPath, ["--mcp", "--workspace", workspace], {
|
|
24114
|
+
const p = spawn3(binPath, ["--mcp", "--workspace", workspace], {
|
|
24115
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
24116
|
+
env: { ...process.env, CODEINDEX_NO_DAEMON: "1" }
|
|
24117
|
+
});
|
|
23904
24118
|
const res = /* @__PURE__ */ new Map();
|
|
23905
24119
|
let pending = "";
|
|
23906
24120
|
let failed = false;
|
|
@@ -24851,7 +25065,7 @@ __export(project_tasks_exports, {
|
|
|
24851
25065
|
pushProjectTaskStatuses: () => pushProjectTaskStatuses,
|
|
24852
25066
|
renderTeamTasksMd: () => renderTeamTasksMd
|
|
24853
25067
|
});
|
|
24854
|
-
import { existsSync as
|
|
25068
|
+
import { existsSync as existsSync51, readFileSync as readFileSync44, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync42 } from "node:fs";
|
|
24855
25069
|
import { join as join55, dirname as dirname25 } from "node:path";
|
|
24856
25070
|
import { homedir as homedir21 } from "node:os";
|
|
24857
25071
|
function isTeamTaskStatus(v) {
|
|
@@ -24937,7 +25151,7 @@ async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
|
|
|
24937
25151
|
}
|
|
24938
25152
|
for (const project of projects) {
|
|
24939
25153
|
const file = join55(project, fk.filename);
|
|
24940
|
-
if (!
|
|
25154
|
+
if (!existsSync51(file)) continue;
|
|
24941
25155
|
let mtime;
|
|
24942
25156
|
try {
|
|
24943
25157
|
mtime = statSync42(file).mtimeMs;
|
|
@@ -25019,7 +25233,7 @@ __export(intent_drain_exports, {
|
|
|
25019
25233
|
drainSyncIntents: () => drainSyncIntents,
|
|
25020
25234
|
instructionTargets: () => instructionTargets
|
|
25021
25235
|
});
|
|
25022
|
-
import { existsSync as
|
|
25236
|
+
import { existsSync as existsSync52, readFileSync as readFileSync45, writeFileSync as writeFileSync19, appendFileSync, mkdirSync as mkdirSync19 } from "node:fs";
|
|
25023
25237
|
import { join as join56 } from "node:path";
|
|
25024
25238
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
25025
25239
|
import { dirname as dirname26 } from "node:path";
|
|
@@ -25034,7 +25248,7 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
25034
25248
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
25035
25249
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
25036
25250
|
if (!rootPath) return [];
|
|
25037
|
-
const present = INSTRUCTION_FILENAMES.map((f) => join56(rootPath, f)).filter((p) =>
|
|
25251
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join56(rootPath, f)).filter((p) => existsSync52(p));
|
|
25038
25252
|
if (present.length) return present;
|
|
25039
25253
|
return [...new Set(tools.map((t) => join56(rootPath, instructionsFilename(t.id))))];
|
|
25040
25254
|
}
|
|
@@ -25062,7 +25276,7 @@ function applyCodeRecommendation(intent) {
|
|
|
25062
25276
|
mkdirSync19(dir, { recursive: true });
|
|
25063
25277
|
} catch {
|
|
25064
25278
|
}
|
|
25065
|
-
const existing =
|
|
25279
|
+
const existing = existsSync52(file) ? readFileSync45(file, "utf8") : "";
|
|
25066
25280
|
if (existing.includes(text)) {
|
|
25067
25281
|
skipped.push(file);
|
|
25068
25282
|
continue;
|
|
@@ -25240,7 +25454,7 @@ var init_intent_drain = __esm({
|
|
|
25240
25454
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25241
25455
|
} catch {
|
|
25242
25456
|
try {
|
|
25243
|
-
if (true) ownVersion2 = "0.7.
|
|
25457
|
+
if (true) ownVersion2 = "0.7.2";
|
|
25244
25458
|
} catch {
|
|
25245
25459
|
}
|
|
25246
25460
|
}
|
|
@@ -25441,7 +25655,7 @@ var team_merge_exports = {};
|
|
|
25441
25655
|
__export(team_merge_exports, {
|
|
25442
25656
|
mergePullResult: () => mergePullResult
|
|
25443
25657
|
});
|
|
25444
|
-
import { existsSync as
|
|
25658
|
+
import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as readFileSync46, rmSync as rmSync8, writeFileSync as writeFileSync20, statSync as statSync43 } from "fs";
|
|
25445
25659
|
import { dirname as dirname27, join as join57 } from "path";
|
|
25446
25660
|
import { createHash as createHash14 } from "crypto";
|
|
25447
25661
|
function installPathFor(art, tool) {
|
|
@@ -25558,7 +25772,7 @@ async function mergePullResult(opts) {
|
|
|
25558
25772
|
if (!path)
|
|
25559
25773
|
continue;
|
|
25560
25774
|
try {
|
|
25561
|
-
if (
|
|
25775
|
+
if (existsSync53(path))
|
|
25562
25776
|
rmSync8(path, { force: true });
|
|
25563
25777
|
await teamInstallsForget(id, row.tool);
|
|
25564
25778
|
report.removed.push({ artifactId: id, path });
|
|
@@ -25576,7 +25790,7 @@ async function mergePullResult(opts) {
|
|
|
25576
25790
|
}
|
|
25577
25791
|
function readFileIfExists(path) {
|
|
25578
25792
|
try {
|
|
25579
|
-
if (!
|
|
25793
|
+
if (!existsSync53(path))
|
|
25580
25794
|
return null;
|
|
25581
25795
|
const s = statSync43(path);
|
|
25582
25796
|
if (!s.isFile())
|
|
@@ -25662,7 +25876,7 @@ var init_vault_crypto = __esm({
|
|
|
25662
25876
|
});
|
|
25663
25877
|
|
|
25664
25878
|
// ../engine/dist/core/vault-source.js
|
|
25665
|
-
import { existsSync as
|
|
25879
|
+
import { existsSync as existsSync54, readdirSync as readdirSync34, statSync as statSync44 } from "fs";
|
|
25666
25880
|
import { extname, join as join58 } from "path";
|
|
25667
25881
|
function* walkVaultSources() {
|
|
25668
25882
|
const t = loadSettings().team.vault;
|
|
@@ -25688,7 +25902,7 @@ function safeStat(path) {
|
|
|
25688
25902
|
}
|
|
25689
25903
|
function* walkClaude() {
|
|
25690
25904
|
const root = claudeBackend.projectsDir();
|
|
25691
|
-
if (!
|
|
25905
|
+
if (!existsSync54(root))
|
|
25692
25906
|
return;
|
|
25693
25907
|
let projectDirs = [];
|
|
25694
25908
|
try {
|
|
@@ -25741,7 +25955,7 @@ function* walkCursor() {
|
|
|
25741
25955
|
}
|
|
25742
25956
|
function* walkCodex() {
|
|
25743
25957
|
const sessionsRoot = join58(codexBackend.homeDir(), "sessions");
|
|
25744
|
-
if (!
|
|
25958
|
+
if (!existsSync54(sessionsRoot))
|
|
25745
25959
|
return;
|
|
25746
25960
|
const stack = [sessionsRoot];
|
|
25747
25961
|
while (stack.length) {
|
|
@@ -25770,7 +25984,7 @@ function* walkCodex() {
|
|
|
25770
25984
|
}
|
|
25771
25985
|
function* walkAgy() {
|
|
25772
25986
|
const brainDir = join58(agyBackend.homeDir(), "brain");
|
|
25773
|
-
if (!
|
|
25987
|
+
if (!existsSync54(brainDir))
|
|
25774
25988
|
return;
|
|
25775
25989
|
let sessionDirs = [];
|
|
25776
25990
|
try {
|
|
@@ -25787,10 +26001,10 @@ function* walkAgy() {
|
|
|
25787
26001
|
continue;
|
|
25788
26002
|
}
|
|
25789
26003
|
let filePath = join58(sessionPath, ".system_generated", "logs", "transcript.jsonl");
|
|
25790
|
-
if (!
|
|
26004
|
+
if (!existsSync54(filePath)) {
|
|
25791
26005
|
filePath = join58(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
|
|
25792
26006
|
}
|
|
25793
|
-
if (!
|
|
26007
|
+
if (!existsSync54(filePath))
|
|
25794
26008
|
continue;
|
|
25795
26009
|
const s = safeStat(filePath);
|
|
25796
26010
|
if (!s)
|
|
@@ -25826,7 +26040,7 @@ __export(vault_client_exports, {
|
|
|
25826
26040
|
vaultStatus: () => vaultStatus,
|
|
25827
26041
|
vaultSync: () => vaultSync
|
|
25828
26042
|
});
|
|
25829
|
-
import { mkdirSync as mkdirSync21, readFileSync as readFileSync47, writeFileSync as writeFileSync21, existsSync as
|
|
26043
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync47, writeFileSync as writeFileSync21, existsSync as existsSync55 } from "fs";
|
|
25830
26044
|
import { dirname as dirname28, join as join59 } from "path";
|
|
25831
26045
|
function context2() {
|
|
25832
26046
|
const s = loadSettings().team;
|
|
@@ -26039,7 +26253,7 @@ async function vaultRestore(passphrase, opts = {}) {
|
|
|
26039
26253
|
}
|
|
26040
26254
|
try {
|
|
26041
26255
|
const path = importedPathFor(blob.tool, blob.sessionId);
|
|
26042
|
-
if (
|
|
26256
|
+
if (existsSync55(path)) {
|
|
26043
26257
|
const localStat = await import("fs").then((m) => m.statSync(path));
|
|
26044
26258
|
if (Math.abs(localStat.mtimeMs - blob.mtimeSourceMs) < 1) {
|
|
26045
26259
|
report.skipped.push({ sessionId: blob.sessionId, tool: blob.tool, reason: "unchanged" });
|
|
@@ -26122,7 +26336,7 @@ __export(keyring_exports, {
|
|
|
26122
26336
|
psQuote: () => psQuote,
|
|
26123
26337
|
shQuote: () => shQuote
|
|
26124
26338
|
});
|
|
26125
|
-
import { execFileSync as
|
|
26339
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
26126
26340
|
function probeKeyring(r = realRunner) {
|
|
26127
26341
|
if (r.platform === "darwin") {
|
|
26128
26342
|
try {
|
|
@@ -26234,7 +26448,7 @@ var init_keyring = __esm({
|
|
|
26234
26448
|
ACCOUNT = "vault-passphrase";
|
|
26235
26449
|
realRunner = {
|
|
26236
26450
|
run(file, args, input) {
|
|
26237
|
-
return
|
|
26451
|
+
return execFileSync4(file, args, {
|
|
26238
26452
|
input,
|
|
26239
26453
|
encoding: "utf-8",
|
|
26240
26454
|
stdio: input === void 0 ? ["ignore", "pipe", "pipe"] : ["pipe", "pipe", "pipe"]
|
|
@@ -26669,7 +26883,7 @@ __export(service_installer_exports, {
|
|
|
26669
26883
|
uninstallService: () => uninstallService
|
|
26670
26884
|
});
|
|
26671
26885
|
import { execSync as execSync5 } from "child_process";
|
|
26672
|
-
import { existsSync as
|
|
26886
|
+
import { existsSync as existsSync56, mkdirSync as mkdirSync22, readFileSync as readFileSync48, rmSync as rmSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
26673
26887
|
import { homedir as homedir22 } from "os";
|
|
26674
26888
|
import { join as join60 } from "path";
|
|
26675
26889
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -26696,7 +26910,7 @@ function isServiceRunning() {
|
|
|
26696
26910
|
return /com\.chat-recall\.watch/.test(tryCmd("launchctl list 2>/dev/null"));
|
|
26697
26911
|
}
|
|
26698
26912
|
if (process.platform === "linux") {
|
|
26699
|
-
return
|
|
26913
|
+
return /^active$/m.test(tryCmd("systemctl --user is-active chat-recall-watch.service 2>/dev/null"));
|
|
26700
26914
|
}
|
|
26701
26915
|
return false;
|
|
26702
26916
|
}
|
|
@@ -26705,7 +26919,7 @@ function refreshServiceDefinition() {
|
|
|
26705
26919
|
try {
|
|
26706
26920
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
26707
26921
|
const unitPath = join60(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
26708
|
-
if (!
|
|
26922
|
+
if (!existsSync56(unitPath)) return false;
|
|
26709
26923
|
const current = readFileSync48(unitPath, "utf8");
|
|
26710
26924
|
if (!current.includes(watchJs)) return false;
|
|
26711
26925
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
@@ -26772,7 +26986,12 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
26772
26986
|
// sawtooth. 1536MB keeps GC honest (768 OOMed on the largest subagent-fanout session) with plenty of headroom for the
|
|
26773
26987
|
// largest transcripts.
|
|
26774
26988
|
`ExecStart=${node} --max-old-space-size=1536 ${watchJs}`,
|
|
26775
|
-
|
|
26989
|
+
// ALWAYS: the collector never ends its own work, so any exit systemd did
|
|
26990
|
+
// not ask for is a fault. Under on-failure a clean exit left it dead: on
|
|
26991
|
+
// 2026-09-16 the unit went "inactive (dead) … status=0/SUCCESS" and stayed
|
|
26992
|
+
// down for 8 days, so nothing synced and the auto-update tick, which runs
|
|
26993
|
+
// inside the daemon, never ran. `systemctl stop` still stops it.
|
|
26994
|
+
"Restart=always",
|
|
26776
26995
|
"RestartSec=10",
|
|
26777
26996
|
"Nice=10",
|
|
26778
26997
|
// NEVER STOP RETRYING. systemd's default start limiter gives up after a
|
|
@@ -26868,7 +27087,7 @@ function uninstallService() {
|
|
|
26868
27087
|
} catch {
|
|
26869
27088
|
}
|
|
26870
27089
|
const unitPath = join60(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
26871
|
-
if (
|
|
27090
|
+
if (existsSync56(unitPath)) {
|
|
26872
27091
|
rmSync9(unitPath, { force: true });
|
|
26873
27092
|
removed = true;
|
|
26874
27093
|
}
|
|
@@ -26885,7 +27104,7 @@ function uninstallService() {
|
|
|
26885
27104
|
} catch {
|
|
26886
27105
|
}
|
|
26887
27106
|
let removed = false;
|
|
26888
|
-
if (
|
|
27107
|
+
if (existsSync56(plistPath)) {
|
|
26889
27108
|
rmSync9(plistPath, { force: true });
|
|
26890
27109
|
removed = true;
|
|
26891
27110
|
}
|
|
@@ -27298,7 +27517,7 @@ init_project_resolver();
|
|
|
27298
27517
|
import { config } from "dotenv";
|
|
27299
27518
|
import { Command } from "commander";
|
|
27300
27519
|
import chalk2 from "chalk";
|
|
27301
|
-
import { existsSync as
|
|
27520
|
+
import { existsSync as existsSync57, readFileSync as readFileSync49, writeFileSync as writeFileSync23, realpathSync as realpathSync5 } from "fs";
|
|
27302
27521
|
import { homedir as homedir23 } from "os";
|
|
27303
27522
|
import { join as join61, resolve as resolve2, dirname as dirname29, basename as basename27 } from "path";
|
|
27304
27523
|
|
|
@@ -27407,7 +27626,7 @@ function renderEnvNeeds(needs, installedCount) {
|
|
|
27407
27626
|
|
|
27408
27627
|
// src/star-nudge.ts
|
|
27409
27628
|
init_paths();
|
|
27410
|
-
import { existsSync as
|
|
27629
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
27411
27630
|
import { dirname as dirname20, join as join45 } from "node:path";
|
|
27412
27631
|
var REPO = "https://github.com/munhq/chat-recall";
|
|
27413
27632
|
function markerPath() {
|
|
@@ -27423,7 +27642,7 @@ function shouldAskForStar(resultCount) {
|
|
|
27423
27642
|
if (suppressed()) return false;
|
|
27424
27643
|
if (!process.stderr.isTTY) return false;
|
|
27425
27644
|
try {
|
|
27426
|
-
return !
|
|
27645
|
+
return !existsSync43(markerPath());
|
|
27427
27646
|
} catch {
|
|
27428
27647
|
return false;
|
|
27429
27648
|
}
|
|
@@ -27464,7 +27683,7 @@ function claudeHookConfigFiles() {
|
|
|
27464
27683
|
const out = [];
|
|
27465
27684
|
const seen = /* @__PURE__ */ new Set();
|
|
27466
27685
|
for (const home of claudeHomeDirs()) {
|
|
27467
|
-
if (!
|
|
27686
|
+
if (!existsSync57(join61(home, "projects"))) continue;
|
|
27468
27687
|
const file = join61(home, "hooks.json");
|
|
27469
27688
|
let key2;
|
|
27470
27689
|
try {
|
|
@@ -28250,7 +28469,7 @@ memory.command("wake-up").description("Generate wake-up context (high-importance
|
|
|
28250
28469
|
try {
|
|
28251
28470
|
const identityFile = getIdentityFilePath();
|
|
28252
28471
|
let identity = "AI coding assistant";
|
|
28253
|
-
if (
|
|
28472
|
+
if (existsSync57(identityFile)) {
|
|
28254
28473
|
identity = readFileSync49(identityFile, "utf-8").trim();
|
|
28255
28474
|
}
|
|
28256
28475
|
const lines = [
|
|
@@ -28351,7 +28570,7 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
28351
28570
|
}
|
|
28352
28571
|
});
|
|
28353
28572
|
program.command("doctor").description("Quick health check across login, server, credentials, hooks, MCP server, and codeindex").option("--purge-local", "Remove the legacy local index (cache.db + vector/KG files) left by pre-thin-collector versions \u2014 storage is server-side now. Requires login; keeps credentials, sync ledger, identity, and the audit log.").action(async (opts) => {
|
|
28354
|
-
const { existsSync:
|
|
28573
|
+
const { existsSync: existsSync58, readFileSync: readFileSync50, statSync: statSync45 } = await import("fs");
|
|
28355
28574
|
const { execSync: execSync6 } = await import("child_process");
|
|
28356
28575
|
const rows = [];
|
|
28357
28576
|
const note = (ok, label, detail) => rows.push({ ok, label, detail });
|
|
@@ -28415,7 +28634,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28415
28634
|
}
|
|
28416
28635
|
}
|
|
28417
28636
|
const credFile = join61(getDataDir(), "credentials.json");
|
|
28418
|
-
if (!
|
|
28637
|
+
if (!existsSync58(credFile)) {
|
|
28419
28638
|
note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
|
|
28420
28639
|
} else {
|
|
28421
28640
|
try {
|
|
@@ -28430,13 +28649,13 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28430
28649
|
for (const hooksJson of claudeHookConfigFiles()) {
|
|
28431
28650
|
const profile = basename27(dirname29(hooksJson));
|
|
28432
28651
|
const label = `Claude hooks (${profile})`;
|
|
28433
|
-
if (!
|
|
28652
|
+
if (!existsSync58(hooksJson)) {
|
|
28434
28653
|
note(false, label, `no ${hooksJson} \u2014 run \`chat-recall install-hooks\``);
|
|
28435
28654
|
continue;
|
|
28436
28655
|
}
|
|
28437
28656
|
try {
|
|
28438
28657
|
const readHooks = (file) => {
|
|
28439
|
-
if (!
|
|
28658
|
+
if (!existsSync58(file)) return {};
|
|
28440
28659
|
try {
|
|
28441
28660
|
return JSON.parse(readFileSync50(file, "utf-8")).hooks || {};
|
|
28442
28661
|
} catch {
|
|
@@ -28479,9 +28698,9 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28479
28698
|
try {
|
|
28480
28699
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
28481
28700
|
for (const target2 of reg.guardTargets()) {
|
|
28482
|
-
if (!
|
|
28701
|
+
if (!existsSync58(target2.homeDir)) continue;
|
|
28483
28702
|
const label = `Decision guard \u2014 ${target2.label}`;
|
|
28484
|
-
if (!
|
|
28703
|
+
if (!existsSync58(target2.configPath)) {
|
|
28485
28704
|
note(false, label, `not registered \u2014 run \`chat-recall install-hooks\``);
|
|
28486
28705
|
continue;
|
|
28487
28706
|
}
|
|
@@ -28506,7 +28725,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28506
28725
|
const want = bundledSkillNames2().length;
|
|
28507
28726
|
for (const t of skillTargets2()) {
|
|
28508
28727
|
if (!t.available) continue;
|
|
28509
|
-
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) =>
|
|
28728
|
+
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync58(join61(t.dir, n, ".chat-recall-managed"))).length;
|
|
28510
28729
|
note(
|
|
28511
28730
|
have === want,
|
|
28512
28731
|
`Skills \u2014 ${t.label}`,
|
|
@@ -28576,7 +28795,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28576
28795
|
} else if (process.platform === "darwin") {
|
|
28577
28796
|
watchRunning = /com\.chat-recall\.watch/.test(tryCmd2("launchctl list 2>/dev/null"));
|
|
28578
28797
|
} else {
|
|
28579
|
-
watchRunning =
|
|
28798
|
+
watchRunning = /^active$/m.test(tryCmd2("systemctl --user is-active chat-recall-watch.service 2>/dev/null"));
|
|
28580
28799
|
}
|
|
28581
28800
|
note(watchRunning, "Watch daemon", watchRunning ? "running" : "not running (run `chat-recall watch --install-service` to keep collection running)");
|
|
28582
28801
|
const dataDir = getDataDir();
|
|
@@ -28588,7 +28807,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28588
28807
|
join61(dataDir, "index", "knowledge_graph.db"),
|
|
28589
28808
|
join61(dataDir, "index", "metadata.db")
|
|
28590
28809
|
];
|
|
28591
|
-
const legacyPresent = legacyPaths.filter((p) =>
|
|
28810
|
+
const legacyPresent = legacyPaths.filter((p) => existsSync58(p));
|
|
28592
28811
|
if (opts.purgeLocal) {
|
|
28593
28812
|
if (!target) {
|
|
28594
28813
|
note(false, "Purge legacy index", "refused \u2014 log in and `chat-recall sync` first, so your history is on the server before removing local copies");
|
|
@@ -29232,10 +29451,10 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
|
|
|
29232
29451
|
try {
|
|
29233
29452
|
const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
|
|
29234
29453
|
const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
29235
|
-
const { writeFileSync: writeFileSync24, readFileSync: readFileSync50, existsSync:
|
|
29454
|
+
const { writeFileSync: writeFileSync24, readFileSync: readFileSync50, existsSync: existsSync58 } = await import("node:fs");
|
|
29236
29455
|
const { join: join62 } = await import("node:path");
|
|
29237
29456
|
const file = join62(cwd, "TEAM_TASKS.md");
|
|
29238
|
-
if (!opts.force &&
|
|
29457
|
+
if (!opts.force && existsSync58(file) && parseTeamTasksFile2(readFileSync50(file, "utf8")).length > 0) {
|
|
29239
29458
|
console.error(chalk2.red("TEAM_TASKS.md has unpushed edits."), "Run", chalk2.bold("chat-recall tasks push"), "first, or", chalk2.bold("tasks pull --force"), "to discard.");
|
|
29240
29459
|
process.exit(1);
|
|
29241
29460
|
}
|
|
@@ -29254,10 +29473,10 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
|
|
|
29254
29473
|
const cwd = dir || process.cwd();
|
|
29255
29474
|
try {
|
|
29256
29475
|
const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
29257
|
-
const { readFileSync: readFileSync50, existsSync:
|
|
29476
|
+
const { readFileSync: readFileSync50, existsSync: existsSync58 } = await import("node:fs");
|
|
29258
29477
|
const { join: join62 } = await import("node:path");
|
|
29259
29478
|
const file = join62(cwd, "TEAM_TASKS.md");
|
|
29260
|
-
if (!
|
|
29479
|
+
if (!existsSync58(file)) {
|
|
29261
29480
|
console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
|
|
29262
29481
|
process.exit(1);
|
|
29263
29482
|
}
|
|
@@ -29699,10 +29918,10 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
29699
29918
|
return;
|
|
29700
29919
|
}
|
|
29701
29920
|
if (!opts.close) return;
|
|
29702
|
-
const { execFileSync:
|
|
29921
|
+
const { execFileSync: execFileSync5 } = await import("node:child_process");
|
|
29703
29922
|
const git2 = (args) => {
|
|
29704
29923
|
try {
|
|
29705
|
-
return
|
|
29924
|
+
return execFileSync5("git", args, {
|
|
29706
29925
|
cwd,
|
|
29707
29926
|
encoding: "utf8",
|
|
29708
29927
|
timeout: 5e3,
|
|
@@ -29744,7 +29963,7 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
29744
29963
|
}
|
|
29745
29964
|
});
|
|
29746
29965
|
program.command("install-hooks").description("Install Claude Code hooks (Stop + PreCompact + UserPromptSubmit + SessionEnd + SessionStart) into every Claude profile").option("--uninstall", "Remove hooks instead of installing them").option("--no-resume-hint", "Don't install the UserPromptSubmit resume-hint hook").option("--no-escalate", "Don't install the SessionEnd learnings-escalation hook").option("--no-wakeup", "Don't install the SessionStart wake-up hook").option("--no-guard", "Don't install the PreToolUse decision guard").option("--no-task-board", "Don't install the hooks that claim and close board cards").action(async (opts) => {
|
|
29747
|
-
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync:
|
|
29966
|
+
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync: readFileSync50, writeFileSync: writeFileSync24, statSync: statSync45, unlinkSync: unlinkSync4 } = await import("fs");
|
|
29748
29967
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
29749
29968
|
const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
|
|
29750
29969
|
const here = fileURLToPath6(new URL(".", import.meta.url));
|
|
@@ -29757,7 +29976,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29757
29976
|
// freshly added script is only at the root until that build runs.
|
|
29758
29977
|
join61(here, "..", "..", "..", "hooks", name)
|
|
29759
29978
|
];
|
|
29760
|
-
return candidates2.find((p) =>
|
|
29979
|
+
return candidates2.find((p) => existsSync58(p));
|
|
29761
29980
|
};
|
|
29762
29981
|
const sourceSaveHook = findHook("chat_recall_save_hook.sh");
|
|
29763
29982
|
const sourceGuardHook = findHook("chat_recall_guard_hook.sh");
|
|
@@ -29776,7 +29995,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29776
29995
|
const installedWakeupHook = join61(hooksDir, "chat_recall_wakeup_hook.sh");
|
|
29777
29996
|
const wakeupWiredInSettings = (home) => {
|
|
29778
29997
|
const settings2 = join61(home, "settings.json");
|
|
29779
|
-
if (!
|
|
29998
|
+
if (!existsSync58(settings2)) return false;
|
|
29780
29999
|
try {
|
|
29781
30000
|
const cfg = JSON.parse(readFileSync50(settings2, "utf-8"));
|
|
29782
30001
|
const arr = Array.isArray(cfg.hooks?.SessionStart) ? cfg.hooks.SessionStart : [];
|
|
@@ -29787,7 +30006,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29787
30006
|
};
|
|
29788
30007
|
const hookConfigFiles = claudeHookConfigFiles();
|
|
29789
30008
|
const readHookConfig = (file) => {
|
|
29790
|
-
if (!
|
|
30009
|
+
if (!existsSync58(file)) return { hooks: {} };
|
|
29791
30010
|
try {
|
|
29792
30011
|
const c = JSON.parse(readFileSync50(file, "utf-8"));
|
|
29793
30012
|
if (!c.hooks || typeof c.hooks !== "object") c.hooks = {};
|
|
@@ -29804,7 +30023,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29804
30023
|
};
|
|
29805
30024
|
const HOOK_EVENTS = ["Stop", "PreCompact", "UserPromptSubmit", "SessionEnd", "SessionStart", "PreToolUse"];
|
|
29806
30025
|
const readJson4 = (file) => {
|
|
29807
|
-
if (!
|
|
30026
|
+
if (!existsSync58(file)) return {};
|
|
29808
30027
|
try {
|
|
29809
30028
|
return JSON.parse(readFileSync50(file, "utf-8"));
|
|
29810
30029
|
} catch {
|
|
@@ -29815,7 +30034,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29815
30034
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
29816
30035
|
const notes = [];
|
|
29817
30036
|
for (const target of reg.guardTargets()) {
|
|
29818
|
-
if (!
|
|
30037
|
+
if (!existsSync58(target.homeDir)) continue;
|
|
29819
30038
|
const wrapper = join61(hooksDir, reg.guardWrapperName(target.tool));
|
|
29820
30039
|
writeFileSync24(wrapper, reg.guardWrapperSource(target.tool, hookPath));
|
|
29821
30040
|
chmodSync5(wrapper, 493);
|
|
@@ -29836,7 +30055,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29836
30055
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
29837
30056
|
let removed = 0;
|
|
29838
30057
|
for (const target of reg.guardTargets()) {
|
|
29839
|
-
if (!
|
|
30058
|
+
if (!existsSync58(target.configPath)) continue;
|
|
29840
30059
|
if (target.tool === "opencode") {
|
|
29841
30060
|
const body = readFileSync50(target.configPath, "utf-8");
|
|
29842
30061
|
if (!body.includes("chat-recall install-hooks")) continue;
|
|
@@ -29864,7 +30083,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29864
30083
|
if (filtered.length) config2.hooks[event] = filtered;
|
|
29865
30084
|
else delete config2.hooks[event];
|
|
29866
30085
|
}
|
|
29867
|
-
if (removed === 0 && !
|
|
30086
|
+
if (removed === 0 && !existsSync58(hooksJson)) continue;
|
|
29868
30087
|
writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
|
|
29869
30088
|
total += removed;
|
|
29870
30089
|
console.log(chalk2.green(`\u2713 Removed ${removed} chat-recall hook entr${removed === 1 ? "y" : "ies"} from ${hooksJson}`));
|
|
@@ -30737,8 +30956,8 @@ npm has ${version2}; the server you sync to still serves ${check.serverVersion}.
|
|
|
30737
30956
|
console.log(chalk2.dim(`
|
|
30738
30957
|
Installing ${version2} from npm\u2026`));
|
|
30739
30958
|
try {
|
|
30740
|
-
const { execFileSync:
|
|
30741
|
-
|
|
30959
|
+
const { execFileSync: execFileSync5 } = await import("node:child_process");
|
|
30960
|
+
execFileSync5("npm", ["install", "-g", `chat-recall@${version2}`], { stdio: "inherit" });
|
|
30742
30961
|
const { installedVersion: installedVersion2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
30743
30962
|
const landed = installedVersion2();
|
|
30744
30963
|
if (landed && compareVersions2(landed, version2) >= 0) {
|