chat-recall 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +362 -211
- package/dist/cli.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +303 -174
- package/dist/scan-worker.js +70 -16
- package/dist/watch.js +80 -26
- package/package.json +1 -1
- package/skills/chat-recall-find/SKILL.md +3 -1
- package/skills/chat-recall-resume/SKILL.md +4 -2
package/dist/cli.js
CHANGED
|
@@ -4892,8 +4892,8 @@ function writeSecrets(secrets) {
|
|
|
4892
4892
|
_secretsCache = null;
|
|
4893
4893
|
const p = secretsPath();
|
|
4894
4894
|
mkdirSync2(dirname2(p), { recursive: true });
|
|
4895
|
-
const
|
|
4896
|
-
writeFileSync(p,
|
|
4895
|
+
const body2 = "# chat-recall secrets \u2014 NOT committed/synced. Mode 0600.\n" + Object.entries(secrets).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
|
|
4896
|
+
writeFileSync(p, body2);
|
|
4897
4897
|
try {
|
|
4898
4898
|
chmodSync(p, 384);
|
|
4899
4899
|
} catch {
|
|
@@ -5979,11 +5979,11 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
|
|
|
5979
5979
|
}
|
|
5980
5980
|
const toolResult = obj.toolUseResult;
|
|
5981
5981
|
if (toolResult && typeof toolResult === "object" && toolCount < maxMessages) {
|
|
5982
|
-
const
|
|
5982
|
+
const resultText2 = toolResult.result;
|
|
5983
5983
|
const query = toolResult.query;
|
|
5984
|
-
if (
|
|
5984
|
+
if (resultText2 && typeof resultText2 === "string" && isValuableToolResult(resultText2, "WebSearch")) {
|
|
5985
5985
|
const searchText = query ? `Search: ${query}
|
|
5986
|
-
${
|
|
5986
|
+
${resultText2}` : resultText2;
|
|
5987
5987
|
content.toolResults.push({
|
|
5988
5988
|
text: searchText.slice(0, 2e3),
|
|
5989
5989
|
lineNumber: lineNum,
|
|
@@ -7002,7 +7002,7 @@ function gitLogRepo(repo, startIso, endIso) {
|
|
|
7002
7002
|
const authorIso = seg.slice(fieldPositions[1] + 1, fieldPositions[2]);
|
|
7003
7003
|
const authorName = seg.slice(fieldPositions[2] + 1, fieldPositions[3]);
|
|
7004
7004
|
const subject = seg.slice(fieldPositions[3] + 1, fieldPositions[4]);
|
|
7005
|
-
let
|
|
7005
|
+
let body2 = seg.slice(fieldPositions[4] + 1);
|
|
7006
7006
|
current = {
|
|
7007
7007
|
sha,
|
|
7008
7008
|
shortSha,
|
|
@@ -7016,11 +7016,11 @@ function gitLogRepo(repo, startIso, endIso) {
|
|
|
7016
7016
|
};
|
|
7017
7017
|
const recovered = [];
|
|
7018
7018
|
let m;
|
|
7019
|
-
while (m = TRAILING_NUMSTAT.exec(
|
|
7019
|
+
while (m = TRAILING_NUMSTAT.exec(body2)) {
|
|
7020
7020
|
recovered.unshift(m[1]);
|
|
7021
|
-
|
|
7021
|
+
body2 = body2.slice(0, body2.length - m[0].length);
|
|
7022
7022
|
}
|
|
7023
|
-
current.body =
|
|
7023
|
+
current.body = body2.trim();
|
|
7024
7024
|
for (const line of recovered)
|
|
7025
7025
|
recordNumstat(line);
|
|
7026
7026
|
} else if (NUMSTAT.test(seg)) {
|
|
@@ -7914,7 +7914,7 @@ var init_opencode = __esm({
|
|
|
7914
7914
|
});
|
|
7915
7915
|
const out = d?.state?.output;
|
|
7916
7916
|
if (out !== void 0 && out !== null) {
|
|
7917
|
-
const
|
|
7917
|
+
const body2 = typeof out === "string" ? out : JSON.stringify(out);
|
|
7918
7918
|
events.push({
|
|
7919
7919
|
kind: "tool_result",
|
|
7920
7920
|
ts,
|
|
@@ -7922,9 +7922,9 @@ var init_opencode = __esm({
|
|
|
7922
7922
|
line: lineNum,
|
|
7923
7923
|
toolUseId: callId,
|
|
7924
7924
|
toolName,
|
|
7925
|
-
resultBody:
|
|
7925
|
+
resultBody: body2,
|
|
7926
7926
|
resultIsError: d?.state?.status === "error",
|
|
7927
|
-
resultBytes:
|
|
7927
|
+
resultBytes: body2.length
|
|
7928
7928
|
});
|
|
7929
7929
|
}
|
|
7930
7930
|
}
|
|
@@ -8699,13 +8699,13 @@ var init_codex2 = __esm({
|
|
|
8699
8699
|
} else if (obj.type === "response_item" && payload.type === "function_call_output") {
|
|
8700
8700
|
const callId = String(payload.call_id || "");
|
|
8701
8701
|
const out = payload.output;
|
|
8702
|
-
let
|
|
8702
|
+
let body2 = "";
|
|
8703
8703
|
let isError = false;
|
|
8704
8704
|
let exitCode;
|
|
8705
8705
|
if (typeof out === "string")
|
|
8706
|
-
|
|
8706
|
+
body2 = out;
|
|
8707
8707
|
else if (out && typeof out === "object") {
|
|
8708
|
-
|
|
8708
|
+
body2 = String(out.content ?? out.output ?? out.stdout ?? out.text ?? "");
|
|
8709
8709
|
if (typeof out.exit_code === "number") {
|
|
8710
8710
|
exitCode = out.exit_code;
|
|
8711
8711
|
isError = exitCode !== 0;
|
|
@@ -8717,10 +8717,10 @@ var init_codex2 = __esm({
|
|
|
8717
8717
|
tsIso,
|
|
8718
8718
|
line: lineNum,
|
|
8719
8719
|
toolUseId: callId,
|
|
8720
|
-
resultBody:
|
|
8720
|
+
resultBody: body2,
|
|
8721
8721
|
resultIsError: isError,
|
|
8722
8722
|
resultExitCode: exitCode,
|
|
8723
|
-
resultBytes:
|
|
8723
|
+
resultBytes: body2.length
|
|
8724
8724
|
});
|
|
8725
8725
|
}
|
|
8726
8726
|
}
|
|
@@ -9742,15 +9742,15 @@ function messagesToEvents(messages, createdAtMs, updatedAtMs) {
|
|
|
9742
9742
|
const p = part;
|
|
9743
9743
|
if (p.type !== "tool-result")
|
|
9744
9744
|
continue;
|
|
9745
|
-
const
|
|
9745
|
+
const body2 = resultBodyOf(p);
|
|
9746
9746
|
events.push({
|
|
9747
9747
|
kind: "tool_result",
|
|
9748
9748
|
ts: clock,
|
|
9749
9749
|
line: 0,
|
|
9750
9750
|
toolUseId: typeof p.toolCallId === "string" ? p.toolCallId : void 0,
|
|
9751
|
-
resultBody:
|
|
9751
|
+
resultBody: body2,
|
|
9752
9752
|
resultIsError: isError,
|
|
9753
|
-
resultBytes: Buffer.byteLength(
|
|
9753
|
+
resultBytes: Buffer.byteLength(body2, "utf8")
|
|
9754
9754
|
});
|
|
9755
9755
|
}
|
|
9756
9756
|
}
|
|
@@ -10613,11 +10613,11 @@ var init_cursor = __esm({
|
|
|
10613
10613
|
const events = readComposerEvents(r.composer);
|
|
10614
10614
|
if (events.length === 0)
|
|
10615
10615
|
return null;
|
|
10616
|
-
const
|
|
10616
|
+
const body2 = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
10617
10617
|
return {
|
|
10618
10618
|
tool: "cursor",
|
|
10619
10619
|
mtime: statSync9(r.composer.globalDbPath).mtimeMs,
|
|
10620
|
-
files: [{ name: `${r.composer.composerId}.jsonl`, bytes: Buffer.from(
|
|
10620
|
+
files: [{ name: `${r.composer.composerId}.jsonl`, bytes: Buffer.from(body2, "utf8") }]
|
|
10621
10621
|
};
|
|
10622
10622
|
} catch {
|
|
10623
10623
|
return null;
|
|
@@ -10972,9 +10972,29 @@ function findSessionFile(sessionId) {
|
|
|
10972
10972
|
function invalidateSessionFileIndex() {
|
|
10973
10973
|
indexCache = null;
|
|
10974
10974
|
}
|
|
10975
|
+
function indexStillValid(cache4) {
|
|
10976
|
+
const roots = claudeProjectDirs();
|
|
10977
|
+
if (roots.length !== cache4.roots.length || roots.some((r, i) => r !== cache4.roots[i]))
|
|
10978
|
+
return false;
|
|
10979
|
+
for (const [dir, mtime] of cache4.dirs) {
|
|
10980
|
+
if (dirMtime(dir) !== mtime)
|
|
10981
|
+
return false;
|
|
10982
|
+
}
|
|
10983
|
+
return true;
|
|
10984
|
+
}
|
|
10975
10985
|
function sessionFileIndex() {
|
|
10976
|
-
if (indexCache)
|
|
10977
|
-
|
|
10986
|
+
if (indexCache) {
|
|
10987
|
+
const now = Date.now();
|
|
10988
|
+
if (now - indexCache.checkedAt < INDEX_RECHECK_MS)
|
|
10989
|
+
return indexCache.byId;
|
|
10990
|
+
if (indexStillValid(indexCache)) {
|
|
10991
|
+
indexCache.checkedAt = now;
|
|
10992
|
+
return indexCache.byId;
|
|
10993
|
+
}
|
|
10994
|
+
indexCache = null;
|
|
10995
|
+
}
|
|
10996
|
+
const dirs = /* @__PURE__ */ new Map();
|
|
10997
|
+
const roots = claudeProjectDirs();
|
|
10978
10998
|
const byId = /* @__PURE__ */ new Map();
|
|
10979
10999
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
10980
11000
|
const projectPaths = /* @__PURE__ */ new Map();
|
|
@@ -10986,10 +11006,11 @@ function sessionFileIndex() {
|
|
|
10986
11006
|
}
|
|
10987
11007
|
return p;
|
|
10988
11008
|
};
|
|
10989
|
-
for (const root of
|
|
11009
|
+
for (const root of roots) {
|
|
10990
11010
|
if (seenRoots.has(root) || !existsSync13(root))
|
|
10991
11011
|
continue;
|
|
10992
11012
|
seenRoots.add(root);
|
|
11013
|
+
dirs.set(root, dirMtime(root));
|
|
10993
11014
|
let entries;
|
|
10994
11015
|
try {
|
|
10995
11016
|
entries = readdirSync10(root, { withFileTypes: true });
|
|
@@ -11000,6 +11021,7 @@ function sessionFileIndex() {
|
|
|
11000
11021
|
if (!entry.isDirectory())
|
|
11001
11022
|
continue;
|
|
11002
11023
|
const dir = join15(root, entry.name);
|
|
11024
|
+
dirs.set(dir, dirMtime(dir));
|
|
11003
11025
|
let names;
|
|
11004
11026
|
try {
|
|
11005
11027
|
names = readdirSync10(dir);
|
|
@@ -11024,7 +11046,7 @@ function sessionFileIndex() {
|
|
|
11024
11046
|
}
|
|
11025
11047
|
}
|
|
11026
11048
|
if (scanScopeDepth > 0)
|
|
11027
|
-
indexCache = byId;
|
|
11049
|
+
indexCache = { byId, dirs, roots, checkedAt: Date.now() };
|
|
11028
11050
|
return byId;
|
|
11029
11051
|
}
|
|
11030
11052
|
function findSessionFiles(sessionId) {
|
|
@@ -11182,7 +11204,7 @@ function findCodexSessionFileIn(root, sessionId) {
|
|
|
11182
11204
|
}
|
|
11183
11205
|
return scanDir(root);
|
|
11184
11206
|
}
|
|
11185
|
-
var scanScopeDepth, indexCache, readScope, readScopeDepth, derivedScope, geminiCache, MAX_EVENT_LINE_BYTES;
|
|
11207
|
+
var scanScopeDepth, indexCache, INDEX_RECHECK_MS, dirMtime, readScope, readScopeDepth, derivedScope, geminiCache, MAX_EVENT_LINE_BYTES;
|
|
11186
11208
|
var init_live_session_scan = __esm({
|
|
11187
11209
|
"../engine/dist/core/live-session-scan.js"() {
|
|
11188
11210
|
"use strict";
|
|
@@ -11194,6 +11216,14 @@ var init_live_session_scan = __esm({
|
|
|
11194
11216
|
init_project_dir_name();
|
|
11195
11217
|
scanScopeDepth = 0;
|
|
11196
11218
|
indexCache = null;
|
|
11219
|
+
INDEX_RECHECK_MS = 1e3;
|
|
11220
|
+
dirMtime = (p) => {
|
|
11221
|
+
try {
|
|
11222
|
+
return statSync11(p).mtimeMs;
|
|
11223
|
+
} catch {
|
|
11224
|
+
return -1;
|
|
11225
|
+
}
|
|
11226
|
+
};
|
|
11197
11227
|
readScope = null;
|
|
11198
11228
|
readScopeDepth = 0;
|
|
11199
11229
|
derivedScope = null;
|
|
@@ -11459,15 +11489,36 @@ var init_claude2 = __esm({
|
|
|
11459
11489
|
listSessions(opts = {}) {
|
|
11460
11490
|
const cutoff = opts.sinceMs ?? 0;
|
|
11461
11491
|
const filter = opts.projectFilter?.toLowerCase();
|
|
11462
|
-
const
|
|
11463
|
-
const out = [];
|
|
11492
|
+
const byId = /* @__PURE__ */ new Map();
|
|
11464
11493
|
for (const root of claudeProjectDirs()) {
|
|
11465
|
-
this.collectSessionsFromRoot(root,
|
|
11494
|
+
this.collectSessionsFromRoot(root, filter, byId, opts.previews !== false);
|
|
11466
11495
|
}
|
|
11496
|
+
const out = [...byId.values()].filter((r) => r.mtime >= cutoff);
|
|
11467
11497
|
out.sort((a, b) => b.mtime - a.mtime);
|
|
11468
11498
|
return opts.limit ? out.slice(0, opts.limit) : out;
|
|
11469
11499
|
}
|
|
11470
|
-
|
|
11500
|
+
/**
|
|
11501
|
+
* Add this root's sessions to `byId`. A session resumed under a second
|
|
11502
|
+
* profile has one file in each home under the same id. It is ONE session: the
|
|
11503
|
+
* first home keeps its path, and its mtime is the newest of all copies.
|
|
11504
|
+
*
|
|
11505
|
+
* Each copy was listed as its own ref before. Session 8da8d72b had a primary
|
|
11506
|
+
* copy frozen at 05:55 and a second-home copy growing until 12:00; the walk
|
|
11507
|
+
* handled both refs under one ledger row with two different mtimes, and the
|
|
11508
|
+
* row that shipped nothing stamped the other copy's mtime.
|
|
11509
|
+
*/
|
|
11510
|
+
collectSessionsFromRoot(root, filter, byId, previews) {
|
|
11511
|
+
const add = (ref) => {
|
|
11512
|
+
const prior = byId.get(ref.rawId);
|
|
11513
|
+
if (!prior) {
|
|
11514
|
+
byId.set(ref.rawId, ref);
|
|
11515
|
+
return;
|
|
11516
|
+
}
|
|
11517
|
+
if (ref.mtime > prior.mtime) {
|
|
11518
|
+
prior.mtime = ref.mtime;
|
|
11519
|
+
prior.modified = ref.modified;
|
|
11520
|
+
}
|
|
11521
|
+
};
|
|
11471
11522
|
if (!existsSync15(root))
|
|
11472
11523
|
return;
|
|
11473
11524
|
for (const proj of readdirSync11(root, { withFileTypes: true })) {
|
|
@@ -11478,6 +11529,7 @@ var init_claude2 = __esm({
|
|
|
11478
11529
|
const projPath = join16(root, proj.name);
|
|
11479
11530
|
const projectPath = resolveProjectDirName(proj.name);
|
|
11480
11531
|
const indexPath = join16(projPath, "sessions-index.json");
|
|
11532
|
+
const indexed = /* @__PURE__ */ new Set();
|
|
11481
11533
|
if (existsSync15(indexPath)) {
|
|
11482
11534
|
try {
|
|
11483
11535
|
const indexData = JSON.parse(readFileSync10(indexPath, "utf-8"));
|
|
@@ -11485,10 +11537,8 @@ var init_claude2 = __esm({
|
|
|
11485
11537
|
for (const entry of entries) {
|
|
11486
11538
|
if (!entry.fullPath || !existsSync15(entry.fullPath))
|
|
11487
11539
|
continue;
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
seen.add(entry.sessionId);
|
|
11491
|
-
out.push({
|
|
11540
|
+
indexed.add(entry.sessionId);
|
|
11541
|
+
add({
|
|
11492
11542
|
toolId: "claude",
|
|
11493
11543
|
rawId: entry.sessionId,
|
|
11494
11544
|
prefixedId: entry.sessionId,
|
|
@@ -11515,7 +11565,7 @@ var init_claude2 = __esm({
|
|
|
11515
11565
|
if (!f.endsWith(".jsonl") || f === "sessions-index.json")
|
|
11516
11566
|
continue;
|
|
11517
11567
|
const sessionId = basename10(f, ".jsonl");
|
|
11518
|
-
if (
|
|
11568
|
+
if (indexed.has(sessionId))
|
|
11519
11569
|
continue;
|
|
11520
11570
|
const fullPath = join16(projPath, f);
|
|
11521
11571
|
let stat3;
|
|
@@ -11524,10 +11574,13 @@ var init_claude2 = __esm({
|
|
|
11524
11574
|
} catch {
|
|
11525
11575
|
continue;
|
|
11526
11576
|
}
|
|
11527
|
-
|
|
11577
|
+
const prior = byId.get(sessionId);
|
|
11578
|
+
if (prior) {
|
|
11579
|
+
add({ ...prior, mtime: stat3.mtimeMs, modified: stat3.mtime.toISOString() });
|
|
11528
11580
|
continue;
|
|
11581
|
+
}
|
|
11529
11582
|
const firstPrompt = previews ? extractFirstUserPromptSync(fullPath, { maxLength: 200 }) : "";
|
|
11530
|
-
|
|
11583
|
+
add({
|
|
11531
11584
|
toolId: "claude",
|
|
11532
11585
|
rawId: sessionId,
|
|
11533
11586
|
prefixedId: sessionId,
|
|
@@ -11657,20 +11710,20 @@ var init_claude2 = __esm({
|
|
|
11657
11710
|
text += (text ? "\n" : "") + it.text;
|
|
11658
11711
|
} else if (it.type === "tool_result") {
|
|
11659
11712
|
const id = typeof it.tool_use_id === "string" ? it.tool_use_id : "";
|
|
11660
|
-
let
|
|
11713
|
+
let body2 = "";
|
|
11661
11714
|
const c = it.content;
|
|
11662
11715
|
if (typeof c === "string")
|
|
11663
|
-
|
|
11716
|
+
body2 = c;
|
|
11664
11717
|
else if (Array.isArray(c)) {
|
|
11665
11718
|
for (const sub of c) {
|
|
11666
11719
|
if (sub && typeof sub === "object" && sub.type === "text") {
|
|
11667
11720
|
const t = sub.text;
|
|
11668
11721
|
if (typeof t === "string")
|
|
11669
|
-
|
|
11722
|
+
body2 += t;
|
|
11670
11723
|
}
|
|
11671
11724
|
}
|
|
11672
11725
|
}
|
|
11673
|
-
toolResults.push({ id, body, isError: it.is_error === true });
|
|
11726
|
+
toolResults.push({ id, body: body2, isError: it.is_error === true });
|
|
11674
11727
|
}
|
|
11675
11728
|
}
|
|
11676
11729
|
}
|
|
@@ -12606,10 +12659,10 @@ function applyChunkPrivacy(text) {
|
|
|
12606
12659
|
out = redactFilePaths(out);
|
|
12607
12660
|
return out;
|
|
12608
12661
|
}
|
|
12609
|
-
function redactToolResultBody(toolName,
|
|
12610
|
-
if (!
|
|
12611
|
-
return
|
|
12612
|
-
return `[redacted: ${toolName} output, ${
|
|
12662
|
+
function redactToolResultBody(toolName, body2) {
|
|
12663
|
+
if (!body2)
|
|
12664
|
+
return body2;
|
|
12665
|
+
return `[redacted: ${toolName} output, ${body2.length} chars]`;
|
|
12613
12666
|
}
|
|
12614
12667
|
var DEFAULT_REDACTION_RULES, SECRET_CONTEXT_RE, HIGH_ENTROPY_TOKEN_RE, cache, CANARY, MAX_PACK_RULES, MAX_PATTERN_LEN, serverPack, globalRegexCache, privacyCache, PATH_REGEX;
|
|
12615
12668
|
var init_secret_redactor = __esm({
|
|
@@ -14839,8 +14892,8 @@ function parseFrontmatter(content) {
|
|
|
14839
14892
|
return { body: content };
|
|
14840
14893
|
const header = content.slice(3, close);
|
|
14841
14894
|
const afterFence = content.indexOf("\n", close + 1);
|
|
14842
|
-
const
|
|
14843
|
-
const out = { body };
|
|
14895
|
+
const body2 = afterFence === -1 ? "" : content.slice(afterFence + 1);
|
|
14896
|
+
const out = { body: body2 };
|
|
14844
14897
|
for (const line of header.split("\n")) {
|
|
14845
14898
|
const m = line.match(/^\s*([A-Za-z_]+)\s*:\s*(.+?)\s*$/);
|
|
14846
14899
|
if (!m)
|
|
@@ -14932,9 +14985,9 @@ var init_plan_source = __esm({
|
|
|
14932
14985
|
const isAgentPlan = planName.includes("-agent-");
|
|
14933
14986
|
const content = readFileSync15(filePath, "utf-8");
|
|
14934
14987
|
const fm = parseFrontmatter(content);
|
|
14935
|
-
const
|
|
14936
|
-
const firstLine =
|
|
14937
|
-
const projectPath = fm.cwd || this.extractProjectPath(
|
|
14988
|
+
const body2 = fm.body;
|
|
14989
|
+
const firstLine = body2.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || planName;
|
|
14990
|
+
const projectPath = fm.cwd || this.extractProjectPath(body2);
|
|
14938
14991
|
const baseName = planName.replace(/-agent-[a-z0-9]+$/i, "");
|
|
14939
14992
|
const claudeSessionId = fm.sessionId || (UUID_RE3.test(baseName) ? baseName : void 0);
|
|
14940
14993
|
yield {
|
|
@@ -14944,7 +14997,7 @@ var init_plan_source = __esm({
|
|
|
14944
14997
|
projectPath,
|
|
14945
14998
|
filePath,
|
|
14946
14999
|
mtime: stat3.mtimeMs,
|
|
14947
|
-
contentPreview:
|
|
15000
|
+
contentPreview: body2.slice(0, 300),
|
|
14948
15001
|
extra: {
|
|
14949
15002
|
tool: "claude",
|
|
14950
15003
|
isAgentPlan,
|
|
@@ -15051,8 +15104,8 @@ var init_plan_source = __esm({
|
|
|
15051
15104
|
return [];
|
|
15052
15105
|
const content = readFileSync15(item.filePath, "utf-8");
|
|
15053
15106
|
const chunks = [];
|
|
15054
|
-
const { body } = parseFrontmatter(content);
|
|
15055
|
-
const sections = splitByHeaders(
|
|
15107
|
+
const { body: body2 } = parseFrontmatter(content);
|
|
15108
|
+
const sections = splitByHeaders(body2);
|
|
15056
15109
|
for (let i = 0; i < sections.length; i++) {
|
|
15057
15110
|
const section = sections[i];
|
|
15058
15111
|
if (!section.text.trim() || section.text.trim().length < 20)
|
|
@@ -15685,10 +15738,10 @@ import { homedir as homedir9 } from "os";
|
|
|
15685
15738
|
import { join as join26, basename as basename14 } from "path";
|
|
15686
15739
|
function parseFrontmatter2(content) {
|
|
15687
15740
|
const fm = {};
|
|
15688
|
-
let
|
|
15741
|
+
let body2 = content;
|
|
15689
15742
|
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
15690
15743
|
if (m) {
|
|
15691
|
-
|
|
15744
|
+
body2 = m[2];
|
|
15692
15745
|
for (const line of m[1].split(/\r?\n/)) {
|
|
15693
15746
|
const t = line.trim();
|
|
15694
15747
|
if (!t || t.startsWith("#"))
|
|
@@ -15705,7 +15758,7 @@ function parseFrontmatter2(content) {
|
|
|
15705
15758
|
fm[k] = v;
|
|
15706
15759
|
}
|
|
15707
15760
|
}
|
|
15708
|
-
return { fm, body };
|
|
15761
|
+
return { fm, body: body2 };
|
|
15709
15762
|
}
|
|
15710
15763
|
function projectHashToPath(hashDir) {
|
|
15711
15764
|
return resolveProjectDirName(hashDir);
|
|
@@ -15782,9 +15835,9 @@ var init_agent_memory_source = __esm({
|
|
|
15782
15835
|
if (!existsSync25(item.filePath))
|
|
15783
15836
|
return [];
|
|
15784
15837
|
const content = readFileSync18(item.filePath, "utf-8");
|
|
15785
|
-
const { body } = parseFrontmatter2(content);
|
|
15838
|
+
const { body: body2 } = parseFrontmatter2(content);
|
|
15786
15839
|
const chunks = [];
|
|
15787
|
-
const sections = splitByHeaders(
|
|
15840
|
+
const sections = splitByHeaders(body2);
|
|
15788
15841
|
for (let i = 0; i < sections.length; i++) {
|
|
15789
15842
|
const section = sections[i];
|
|
15790
15843
|
if (!section.text.trim() || section.text.trim().length < 20)
|
|
@@ -17428,13 +17481,13 @@ function parseFrontmatter4(text) {
|
|
|
17428
17481
|
}
|
|
17429
17482
|
return { fm, body: m[2] ?? "" };
|
|
17430
17483
|
}
|
|
17431
|
-
function stringifyFrontmatter(fm,
|
|
17484
|
+
function stringifyFrontmatter(fm, body2) {
|
|
17432
17485
|
const lines = Object.entries(fm).filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => `${k}: ${needsQuote(v) ? JSON.stringify(v) : v}`);
|
|
17433
17486
|
return `---
|
|
17434
17487
|
${lines.join("\n")}
|
|
17435
17488
|
---
|
|
17436
17489
|
|
|
17437
|
-
${
|
|
17490
|
+
${body2.replace(/^\n+/, "")}`;
|
|
17438
17491
|
}
|
|
17439
17492
|
function needsQuote(v) {
|
|
17440
17493
|
return /[:#]/.test(v) || /^\s|\s$/.test(v);
|
|
@@ -17521,11 +17574,11 @@ function parseCommand(content, fallbackName, format) {
|
|
|
17521
17574
|
body: t.prompt || ""
|
|
17522
17575
|
};
|
|
17523
17576
|
}
|
|
17524
|
-
const { fm, body } = parseFrontmatter4(content);
|
|
17577
|
+
const { fm, body: body2 } = parseFrontmatter4(content);
|
|
17525
17578
|
return {
|
|
17526
17579
|
name: fm.name || fallbackName,
|
|
17527
17580
|
description: fm.description || "",
|
|
17528
|
-
body:
|
|
17581
|
+
body: body2.trim()
|
|
17529
17582
|
};
|
|
17530
17583
|
}
|
|
17531
17584
|
var MAX_CHUNK_CHARS12, MAX_BODY_CHARS2, SlashCommandsSource;
|
|
@@ -17669,12 +17722,12 @@ function parseAgent(content, fallbackName, format) {
|
|
|
17669
17722
|
body: t.developer_instructions || t.instructions || ""
|
|
17670
17723
|
};
|
|
17671
17724
|
}
|
|
17672
|
-
const { fm, body } = parseFrontmatter4(content);
|
|
17725
|
+
const { fm, body: body2 } = parseFrontmatter4(content);
|
|
17673
17726
|
return {
|
|
17674
17727
|
name: fm.name || fallbackName,
|
|
17675
17728
|
description: fm.description || "",
|
|
17676
17729
|
tools: fm.tools || "",
|
|
17677
|
-
body:
|
|
17730
|
+
body: body2.trim()
|
|
17678
17731
|
};
|
|
17679
17732
|
}
|
|
17680
17733
|
var MAX_CHUNK_CHARS13, MAX_BODY_CHARS3, SubagentsSource;
|
|
@@ -18587,7 +18640,7 @@ var init_http = __esm({
|
|
|
18587
18640
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18588
18641
|
} catch {
|
|
18589
18642
|
try {
|
|
18590
|
-
if (true) CLI_VERSION = "0.7.
|
|
18643
|
+
if (true) CLI_VERSION = "0.7.8";
|
|
18591
18644
|
} catch {
|
|
18592
18645
|
}
|
|
18593
18646
|
}
|
|
@@ -19086,7 +19139,7 @@ var init_telemetry = __esm({
|
|
|
19086
19139
|
init_sync_client();
|
|
19087
19140
|
cliVersion2 = () => {
|
|
19088
19141
|
try {
|
|
19089
|
-
return true ? "0.7.
|
|
19142
|
+
return true ? "0.7.8" : "dev";
|
|
19090
19143
|
} catch {
|
|
19091
19144
|
return "dev";
|
|
19092
19145
|
}
|
|
@@ -19258,20 +19311,20 @@ async function probeServer(base3, opts = {}) {
|
|
|
19258
19311
|
if (res.status === 404 || res.status === 410) return { kind: "moved", status: res.status };
|
|
19259
19312
|
if (res.status >= 500) return { kind: "server_error", status: res.status };
|
|
19260
19313
|
if (!res.ok) return { kind: "moved", status: res.status };
|
|
19261
|
-
let
|
|
19314
|
+
let body2;
|
|
19262
19315
|
try {
|
|
19263
|
-
|
|
19316
|
+
body2 = await res.text();
|
|
19264
19317
|
} catch (err) {
|
|
19265
19318
|
return { kind: "unreachable", error: describeCause(err), reason: classifyUnreachable(err) };
|
|
19266
19319
|
}
|
|
19267
19320
|
let parsed;
|
|
19268
19321
|
try {
|
|
19269
|
-
parsed = JSON.parse(
|
|
19322
|
+
parsed = JSON.parse(body2);
|
|
19270
19323
|
} catch {
|
|
19271
|
-
return { kind: "not_api", status: res.status, snippet:
|
|
19324
|
+
return { kind: "not_api", status: res.status, snippet: body2.trim().slice(0, 60) };
|
|
19272
19325
|
}
|
|
19273
19326
|
if (typeof parsed?.apiVersion !== "number") {
|
|
19274
|
-
return { kind: "not_api", status: res.status, snippet:
|
|
19327
|
+
return { kind: "not_api", status: res.status, snippet: body2.trim().slice(0, 60) };
|
|
19275
19328
|
}
|
|
19276
19329
|
return {
|
|
19277
19330
|
kind: "ok",
|
|
@@ -19390,7 +19443,7 @@ function reportClientEvent(kind, opts = {}) {
|
|
|
19390
19443
|
try {
|
|
19391
19444
|
const targets = loadAllCredentials();
|
|
19392
19445
|
if (!targets.length) return;
|
|
19393
|
-
const
|
|
19446
|
+
const body2 = JSON.stringify({
|
|
19394
19447
|
events: [{
|
|
19395
19448
|
ts: Date.now(),
|
|
19396
19449
|
kind: String(kind).slice(0, 64),
|
|
@@ -19407,7 +19460,7 @@ function reportClientEvent(kind, opts = {}) {
|
|
|
19407
19460
|
void fetch(`${t.serverUrl.replace(/\/+$/, "")}/api/client-events`, {
|
|
19408
19461
|
method: "POST",
|
|
19409
19462
|
headers,
|
|
19410
|
-
body,
|
|
19463
|
+
body: body2,
|
|
19411
19464
|
signal: AbortSignal.timeout(3e3)
|
|
19412
19465
|
}).catch(() => {
|
|
19413
19466
|
});
|
|
@@ -19821,10 +19874,10 @@ async function fetchTenantSecurityConfig(cred) {
|
|
|
19821
19874
|
let tenantRules = [];
|
|
19822
19875
|
let rulePackVersion = null;
|
|
19823
19876
|
if (rulesRes.ok) {
|
|
19824
|
-
const
|
|
19825
|
-
const enabled = (
|
|
19877
|
+
const body2 = await rulesRes.json().catch(() => ({}));
|
|
19878
|
+
const enabled = (body2.rules || []).filter((r) => r.enabled !== false);
|
|
19826
19879
|
tenantRules = enabled;
|
|
19827
|
-
const packSpec =
|
|
19880
|
+
const packSpec = body2.pack?.rules ? { version: body2.pack.version, rules: body2.pack.rules.map((r) => ({ name: r.name, regex: r.regex, flags: r.flags, redact: true, source: r.source })) } : { version: body2.version, rules: enabled.filter((r) => r.redact === true).map((r) => ({ name: r.name, regex: r.regex, redact: true, source: "tenant" })) };
|
|
19828
19881
|
lastServerPackSpec = { version: packSpec.version || "", rules: packSpec.rules };
|
|
19829
19882
|
const pack = installServerRulePack(packSpec);
|
|
19830
19883
|
rulePackVersion = serverRulePackVersion();
|
|
@@ -19832,20 +19885,20 @@ async function fetchTenantSecurityConfig(cred) {
|
|
|
19832
19885
|
console.error(`[sync] server redaction rule "${r.name}" ignored: ${r.reason}`);
|
|
19833
19886
|
}
|
|
19834
19887
|
if (pack.accepted > 0) {
|
|
19835
|
-
const rev =
|
|
19888
|
+
const rev = body2.pack?.revision ? `, rev ${body2.pack.revision}` : "";
|
|
19836
19889
|
console.error(`[sync] ${pack.accepted} server redaction rule(s) active (pack ${rulePackVersion}${rev})`);
|
|
19837
19890
|
}
|
|
19838
19891
|
}
|
|
19839
19892
|
let verifySecrets = true;
|
|
19840
19893
|
if (settingsRes?.ok) {
|
|
19841
|
-
const
|
|
19842
|
-
if (typeof
|
|
19843
|
-
if (typeof
|
|
19844
|
-
setTelemetryEligible(base3,
|
|
19894
|
+
const body2 = await settingsRes.json().catch(() => ({}));
|
|
19895
|
+
if (typeof body2.verifySecrets === "boolean") verifySecrets = body2.verifySecrets;
|
|
19896
|
+
if (typeof body2.telemetry === "boolean") {
|
|
19897
|
+
setTelemetryEligible(base3, body2.telemetry);
|
|
19845
19898
|
try {
|
|
19846
19899
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
19847
19900
|
updateCollectorHealth({
|
|
19848
|
-
telemetryEligible: { ...prior, [base3]: { allowed:
|
|
19901
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
|
|
19849
19902
|
});
|
|
19850
19903
|
} catch {
|
|
19851
19904
|
}
|
|
@@ -19904,14 +19957,14 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19904
19957
|
return EMPTY_SYNC_CONFIG;
|
|
19905
19958
|
}
|
|
19906
19959
|
if (!res.ok) return lastKnownSyncConfig(base3, `HTTP ${res.status}`);
|
|
19907
|
-
const
|
|
19960
|
+
const body2 = await res.json().catch(() => ({}));
|
|
19908
19961
|
const config2 = {
|
|
19909
|
-
excludeTools: Array.isArray(
|
|
19910
|
-
excludeProjects: Array.isArray(
|
|
19962
|
+
excludeTools: Array.isArray(body2.excludeTools) ? body2.excludeTools.filter((t) => typeof t === "string") : [],
|
|
19963
|
+
excludeProjects: Array.isArray(body2.excludeProjects) ? body2.excludeProjects.filter((p) => typeof p === "string") : [],
|
|
19911
19964
|
// Ids only — installSourceExclusions drops anything else, so a server
|
|
19912
19965
|
// sending a path cannot make this collector read it.
|
|
19913
|
-
excludeSources: Array.isArray(
|
|
19914
|
-
approveSources: Array.isArray(
|
|
19966
|
+
excludeSources: Array.isArray(body2.excludeSources) ? body2.excludeSources.filter((x) => typeof x === "string") : [],
|
|
19967
|
+
approveSources: Array.isArray(body2.approveSources) ? body2.approveSources.filter((x) => typeof x === "string") : []
|
|
19915
19968
|
};
|
|
19916
19969
|
const applied = installSourceExclusions(config2.excludeSources);
|
|
19917
19970
|
if (applied.excluded > 0) {
|
|
@@ -20306,9 +20359,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20306
20359
|
const maxInflight = explicitThrottle ? 1 : isLocalHost(cred.serverUrl) ? Math.max(LOCAL_INFLIGHT, advertised ?? 0) : advertised ?? REMOTE_INFLIGHT_FALLBACK;
|
|
20307
20360
|
const UPLOAD_TIMEOUT_MS = Number(process.env.CHAT_RECALL_UPLOAD_TIMEOUT_MS) || 9e4;
|
|
20308
20361
|
const gzipBody = serverAcceptsGzipBody(cred.serverUrl);
|
|
20309
|
-
const post = async (
|
|
20362
|
+
const post = async (body2) => {
|
|
20310
20363
|
const payload = (() => {
|
|
20311
|
-
const withProgress = walkProgressForUpload ? { ...
|
|
20364
|
+
const withProgress = walkProgressForUpload ? { ...body2, progress: walkProgressForUpload } : body2;
|
|
20312
20365
|
const json = JSON.stringify(withProgress);
|
|
20313
20366
|
const raw = Buffer.from(json, "utf8");
|
|
20314
20367
|
return gzipBody ? gzipSync3(raw, { level: 6 }) : raw;
|
|
@@ -20332,25 +20385,25 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20332
20385
|
});
|
|
20333
20386
|
if (res.ok) {
|
|
20334
20387
|
acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
|
|
20335
|
-
const
|
|
20336
|
-
if (typeof
|
|
20337
|
-
setTelemetryEligible(base3,
|
|
20388
|
+
const body3 = await res.json().catch(() => ({}));
|
|
20389
|
+
if (typeof body3.telemetry === "boolean") {
|
|
20390
|
+
setTelemetryEligible(base3, body3.telemetry);
|
|
20338
20391
|
try {
|
|
20339
20392
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
20340
20393
|
updateCollectorHealth({
|
|
20341
|
-
telemetryEligible: { ...prior, [base3]: { allowed:
|
|
20394
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body3.telemetry, at: Date.now() } }
|
|
20342
20395
|
});
|
|
20343
20396
|
} catch {
|
|
20344
20397
|
}
|
|
20345
20398
|
}
|
|
20346
|
-
const adv =
|
|
20399
|
+
const adv = body3.limits?.ingestConcurrencyPerTenant;
|
|
20347
20400
|
if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
|
|
20348
20401
|
setServerIngestConcurrency(base3, Math.floor(adv));
|
|
20349
20402
|
}
|
|
20350
|
-
if (
|
|
20403
|
+
if (body3.cli && body3.cli.version) {
|
|
20351
20404
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20352
20405
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20353
|
-
const plan = planAutoUpdate2(base3, { cli:
|
|
20406
|
+
const plan = planAutoUpdate2(base3, { cli: body3.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20354
20407
|
sweepStaleStaging2();
|
|
20355
20408
|
if (plan.update) {
|
|
20356
20409
|
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
@@ -20367,13 +20420,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20367
20420
|
if (res.status === 402) {
|
|
20368
20421
|
let detail = text;
|
|
20369
20422
|
try {
|
|
20370
|
-
const
|
|
20371
|
-
detail =
|
|
20372
|
-
if (
|
|
20373
|
-
${
|
|
20374
|
-
if (
|
|
20375
|
-
if (
|
|
20376
|
-
${
|
|
20423
|
+
const body3 = JSON.parse(text);
|
|
20424
|
+
detail = body3.error ?? text;
|
|
20425
|
+
if (body3.detail) detail += `
|
|
20426
|
+
${body3.detail}`;
|
|
20427
|
+
if (body3.resetsAt) detail += ` (resets ${new Date(body3.resetsAt).toISOString().slice(0, 10)})`;
|
|
20428
|
+
if (body3.upgradeUrl) detail += `
|
|
20429
|
+
${body3.upgradeUrl}`;
|
|
20377
20430
|
} catch {
|
|
20378
20431
|
}
|
|
20379
20432
|
throw classedError("payment_required", `sync paused by the server: ${detail}`);
|
|
@@ -20402,7 +20455,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20402
20455
|
let poolError = null;
|
|
20403
20456
|
const MAX_INFLIGHT_BYTES = (Number(process.env.CHAT_RECALL_MAX_INFLIGHT_MB) || 32) * 1024 * 1024;
|
|
20404
20457
|
let inflightBytes = 0;
|
|
20405
|
-
const submit = async (
|
|
20458
|
+
const submit = async (body2, after, bytesHint = 0) => {
|
|
20406
20459
|
while (inflight.size > 0 && (inflight.size >= maxInflight || inflightBytes + bytesHint > MAX_INFLIGHT_BYTES)) {
|
|
20407
20460
|
await Promise.race(inflight);
|
|
20408
20461
|
}
|
|
@@ -20410,7 +20463,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20410
20463
|
inflightBytes += bytesHint;
|
|
20411
20464
|
let task;
|
|
20412
20465
|
task = (async () => {
|
|
20413
|
-
await post(
|
|
20466
|
+
await post(body2);
|
|
20414
20467
|
after();
|
|
20415
20468
|
})().catch((e) => {
|
|
20416
20469
|
poolError = poolError ?? e;
|
|
@@ -20477,18 +20530,18 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20477
20530
|
signal: ac.signal
|
|
20478
20531
|
});
|
|
20479
20532
|
if (!res.ok) throw new Error(`append sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
20480
|
-
const
|
|
20481
|
-
if (
|
|
20533
|
+
const body2 = await res.json().catch(() => ({}));
|
|
20534
|
+
if (body2.cli && body2.cli.version) {
|
|
20482
20535
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20483
20536
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20484
|
-
const plan = planAutoUpdate2(base3, { cli:
|
|
20537
|
+
const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20485
20538
|
sweepStaleStaging2();
|
|
20486
20539
|
if (plan.update) {
|
|
20487
20540
|
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
20488
20541
|
});
|
|
20489
20542
|
}
|
|
20490
20543
|
}
|
|
20491
|
-
const fullNeeded = new Set(
|
|
20544
|
+
const fullNeeded = new Set(body2.full_resync_needed ?? []);
|
|
20492
20545
|
const acked = convs.filter((c) => !fullNeeded.has(c.session_id));
|
|
20493
20546
|
if (acked.length > 0) {
|
|
20494
20547
|
try {
|
|
@@ -20523,9 +20576,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20523
20576
|
signal: ac.signal
|
|
20524
20577
|
});
|
|
20525
20578
|
if (!res.ok) throw new Error(`chunked head sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
20526
|
-
const
|
|
20579
|
+
const body2 = await res.json().catch(() => ({}));
|
|
20527
20580
|
const id = conv.session_id;
|
|
20528
|
-
const guarded = (
|
|
20581
|
+
const guarded = (body2.shrink_guarded ?? []).find((g) => g.session_id === id);
|
|
20529
20582
|
const mtime = conv.mtime;
|
|
20530
20583
|
try {
|
|
20531
20584
|
if (!guarded) {
|
|
@@ -21402,7 +21455,7 @@ var init_sync_client = __esm({
|
|
|
21402
21455
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21403
21456
|
} catch {
|
|
21404
21457
|
try {
|
|
21405
|
-
if (true) ownVersion = "0.7.
|
|
21458
|
+
if (true) ownVersion = "0.7.8";
|
|
21406
21459
|
} catch {
|
|
21407
21460
|
}
|
|
21408
21461
|
}
|
|
@@ -21481,8 +21534,8 @@ async function fetchNpmLatest() {
|
|
|
21481
21534
|
headers: { accept: "application/vnd.npm.install-v1+json" }
|
|
21482
21535
|
}, 5e3);
|
|
21483
21536
|
if (!res.ok) return null;
|
|
21484
|
-
const
|
|
21485
|
-
const v =
|
|
21537
|
+
const body2 = await res.json();
|
|
21538
|
+
const v = body2["dist-tags"]?.latest;
|
|
21486
21539
|
return typeof v === "string" && v ? v : null;
|
|
21487
21540
|
} catch {
|
|
21488
21541
|
return null;
|
|
@@ -21664,9 +21717,9 @@ function envHome(varName, fallback) {
|
|
|
21664
21717
|
const v = process.env[varName];
|
|
21665
21718
|
return v && v.trim() ? v.trim() : fallback;
|
|
21666
21719
|
}
|
|
21667
|
-
function writeFileMkdir(path,
|
|
21720
|
+
function writeFileMkdir(path, body2) {
|
|
21668
21721
|
mkdirSync12(dirname21(path), { recursive: true });
|
|
21669
|
-
writeFileSync12(path,
|
|
21722
|
+
writeFileSync12(path, body2);
|
|
21670
21723
|
}
|
|
21671
21724
|
function readJsonObject(path) {
|
|
21672
21725
|
const raw = readFileSync37(path, "utf-8");
|
|
@@ -21748,8 +21801,8 @@ function registerCodexToml(path, spec) {
|
|
|
21748
21801
|
const lines = prev.length ? prev.split("\n") : [];
|
|
21749
21802
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
21750
21803
|
if (start === -1) {
|
|
21751
|
-
const
|
|
21752
|
-
writeFileMkdir(path,
|
|
21804
|
+
const body2 = prev.length ? prev.replace(/\n*$/, "\n") + "\n" + block : block;
|
|
21805
|
+
writeFileMkdir(path, body2);
|
|
21753
21806
|
return { id, label, path, state: "created" };
|
|
21754
21807
|
}
|
|
21755
21808
|
let end = lines.length;
|
|
@@ -22290,8 +22343,8 @@ function parseCommandText(content, format, fallbackName) {
|
|
|
22290
22343
|
const t = parseScalarToml(content);
|
|
22291
22344
|
return { name: t.name || fallbackName, description: t.description || "", body: t.prompt || "" };
|
|
22292
22345
|
}
|
|
22293
|
-
const { fm, body } = parseFrontmatter4(content);
|
|
22294
|
-
return { name: fm.name || fallbackName, description: fm.description || "", body:
|
|
22346
|
+
const { fm, body: body2 } = parseFrontmatter4(content);
|
|
22347
|
+
return { name: fm.name || fallbackName, description: fm.description || "", body: body2.trim() };
|
|
22295
22348
|
}
|
|
22296
22349
|
function parseAgentText(content, format, fallbackName) {
|
|
22297
22350
|
if (format === "toml") {
|
|
@@ -22302,8 +22355,8 @@ function parseAgentText(content, format, fallbackName) {
|
|
|
22302
22355
|
body: t.developer_instructions || t.instructions || ""
|
|
22303
22356
|
};
|
|
22304
22357
|
}
|
|
22305
|
-
const { fm, body } = parseFrontmatter4(content);
|
|
22306
|
-
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body:
|
|
22358
|
+
const { fm, body: body2 } = parseFrontmatter4(content);
|
|
22359
|
+
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body2.trim() };
|
|
22307
22360
|
}
|
|
22308
22361
|
function readCommand(filePath, format) {
|
|
22309
22362
|
return parseCommandText(readFileSync40(filePath, "utf-8"), format, base(filePath));
|
|
@@ -22960,8 +23013,8 @@ function planPull(rows, opts = {}) {
|
|
|
22960
23013
|
continue;
|
|
22961
23014
|
const extra2 = parseExtra(row);
|
|
22962
23015
|
const name2 = extra2.skillName || row.title;
|
|
22963
|
-
const
|
|
22964
|
-
if (!name2 || typeof
|
|
23016
|
+
const body2 = extra2.body;
|
|
23017
|
+
if (!name2 || typeof body2 !== "string" || !body2.trim()) {
|
|
22965
23018
|
seenUnsupported.set("skill", (seenUnsupported.get("skill") || 0) + 1);
|
|
22966
23019
|
continue;
|
|
22967
23020
|
}
|
|
@@ -22970,7 +23023,7 @@ function planPull(rows, opts = {}) {
|
|
|
22970
23023
|
const prev2 = skillsByName.get(name2);
|
|
22971
23024
|
if (!prev2 || rank >= 0 && (prev2.rank < 0 || rank < prev2.rank)) {
|
|
22972
23025
|
skillsByName.set(name2, {
|
|
22973
|
-
body,
|
|
23026
|
+
body: body2,
|
|
22974
23027
|
rank,
|
|
22975
23028
|
truncated: extra2.bodyTruncated === true,
|
|
22976
23029
|
redacted: extra2.bodySecretsRedacted === true
|
|
@@ -22983,8 +23036,8 @@ function planPull(rows, opts = {}) {
|
|
|
22983
23036
|
continue;
|
|
22984
23037
|
const extra2 = parseExtra(row);
|
|
22985
23038
|
const name2 = extra2[type === "agent" ? "agentName" : "commandName"] || row.title;
|
|
22986
|
-
const
|
|
22987
|
-
if (!name2 || typeof
|
|
23039
|
+
const body2 = extra2.body;
|
|
23040
|
+
if (!name2 || typeof body2 !== "string" || !body2.trim() || extra2.bodyTruncated === true) {
|
|
22988
23041
|
seenUnsupported.set(type, (seenUnsupported.get(type) || 0) + 1);
|
|
22989
23042
|
continue;
|
|
22990
23043
|
}
|
|
@@ -22994,7 +23047,7 @@ function planPull(rows, opts = {}) {
|
|
|
22994
23047
|
const prev2 = bucket.get(name2);
|
|
22995
23048
|
if (!prev2 || rank >= 0 && (prev2.rank < 0 || rank < prev2.rank)) {
|
|
22996
23049
|
bucket.set(name2, {
|
|
22997
|
-
body,
|
|
23050
|
+
body: body2,
|
|
22998
23051
|
rank,
|
|
22999
23052
|
format: extra2.format === "toml" ? "toml" : "md",
|
|
23000
23053
|
redacted: extra2.bodySecretsRedacted === true
|
|
@@ -23063,7 +23116,7 @@ function executePull(rows, opts = {}) {
|
|
|
23063
23116
|
const explicit = new Set(opts.explicit ?? []);
|
|
23064
23117
|
const { mcps, skills, codecs, unsupported } = planPull(rows, opts);
|
|
23065
23118
|
const outcomes = [];
|
|
23066
|
-
for (const { name, body, truncated, redacted, tools } of skills) {
|
|
23119
|
+
for (const { name, body: body2, truncated, redacted, tools } of skills) {
|
|
23067
23120
|
for (const tool of tools) {
|
|
23068
23121
|
const dir = join51(skillsDirFor(tool), name);
|
|
23069
23122
|
const file = join51(dir, "SKILL.md");
|
|
@@ -23081,17 +23134,17 @@ function executePull(rows, opts = {}) {
|
|
|
23081
23134
|
}
|
|
23082
23135
|
try {
|
|
23083
23136
|
mkdirSync16(dir, { recursive: true });
|
|
23084
|
-
writeFileSync16(file,
|
|
23137
|
+
writeFileSync16(file, body2);
|
|
23085
23138
|
outcomes.push({ type: "skill", name, tool, status: "written", path: file, redactedContent: redacted });
|
|
23086
23139
|
} catch (e) {
|
|
23087
23140
|
outcomes.push({ type: "skill", name, tool, status: "failed", reason: e instanceof Error ? e.message : "write failed" });
|
|
23088
23141
|
}
|
|
23089
23142
|
}
|
|
23090
23143
|
}
|
|
23091
|
-
for (const { type, name, body, format, redacted, tools } of codecs) {
|
|
23144
|
+
for (const { type, name, body: body2, format, redacted, tools } of codecs) {
|
|
23092
23145
|
let art;
|
|
23093
23146
|
try {
|
|
23094
|
-
art = type === "agent" ? parseAgentText(
|
|
23147
|
+
art = type === "agent" ? parseAgentText(body2, format, name) : parseCommandText(body2, format, name);
|
|
23095
23148
|
} catch (e) {
|
|
23096
23149
|
for (const tool of tools) {
|
|
23097
23150
|
outcomes.push({ type, name, tool, status: "failed", reason: `could not parse the stored body: ${e instanceof Error ? e.message : "failed"}` });
|
|
@@ -24370,11 +24423,11 @@ async function collectCode(opts) {
|
|
|
24370
24423
|
for (const block of log22.split("\0END\0")) {
|
|
24371
24424
|
if (!block.includes("\0"))
|
|
24372
24425
|
continue;
|
|
24373
|
-
const [h,
|
|
24426
|
+
const [h, body2] = [block.slice(0, block.indexOf("\0")).trim(), block.slice(block.indexOf("\0") + 1)];
|
|
24374
24427
|
if (!h)
|
|
24375
24428
|
continue;
|
|
24376
24429
|
totalCommits++;
|
|
24377
|
-
if (AI_RE.test(
|
|
24430
|
+
if (AI_RE.test(body2)) {
|
|
24378
24431
|
aiCommits++;
|
|
24379
24432
|
try {
|
|
24380
24433
|
const files2 = execSync4(`git -C "${ws}" show --format= --name-only ${h}`, { encoding: "utf8", timeout: 2e4, maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] });
|
|
@@ -25417,8 +25470,8 @@ async function runPull(base3, opts) {
|
|
|
25417
25470
|
try {
|
|
25418
25471
|
const res = await fetchWithTimeout(`${base3}/api/toolkit/browse/${type}?limit=1000`, { headers });
|
|
25419
25472
|
if (!res.ok) continue;
|
|
25420
|
-
const
|
|
25421
|
-
for (const it of
|
|
25473
|
+
const body2 = await res.json();
|
|
25474
|
+
for (const it of body2.items || []) rows.push(it);
|
|
25422
25475
|
} catch {
|
|
25423
25476
|
}
|
|
25424
25477
|
}
|
|
@@ -25563,7 +25616,7 @@ var init_intent_drain = __esm({
|
|
|
25563
25616
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25564
25617
|
} catch {
|
|
25565
25618
|
try {
|
|
25566
|
-
if (true) ownVersion2 = "0.7.
|
|
25619
|
+
if (true) ownVersion2 = "0.7.8";
|
|
25567
25620
|
} catch {
|
|
25568
25621
|
}
|
|
25569
25622
|
}
|
|
@@ -25604,7 +25657,7 @@ function context(opts = {}) {
|
|
|
25604
25657
|
throw new TeamConfigError("Not joined to a team. Run `chat-recall team join <invite-token>`.");
|
|
25605
25658
|
return { serverUrl: t.serverUrl, token, handle: t.memberHandle ?? "", teamId: t.teamId };
|
|
25606
25659
|
}
|
|
25607
|
-
async function http(ctx, method, path,
|
|
25660
|
+
async function http(ctx, method, path, body2) {
|
|
25608
25661
|
const url = ctx.serverUrl.replace(/\/+$/, "") + path;
|
|
25609
25662
|
const r = await fetch(url, {
|
|
25610
25663
|
method,
|
|
@@ -25613,7 +25666,7 @@ async function http(ctx, method, path, body) {
|
|
|
25613
25666
|
"Content-Type": "application/json",
|
|
25614
25667
|
"Accept": "application/json"
|
|
25615
25668
|
},
|
|
25616
|
-
body:
|
|
25669
|
+
body: body2 == null ? void 0 : JSON.stringify(body2)
|
|
25617
25670
|
});
|
|
25618
25671
|
const text = await r.text();
|
|
25619
25672
|
let parsed = void 0;
|
|
@@ -25750,10 +25803,10 @@ var init_team_client = __esm({
|
|
|
25750
25803
|
TeamHttpError = class extends Error {
|
|
25751
25804
|
status;
|
|
25752
25805
|
body;
|
|
25753
|
-
constructor(msg, status,
|
|
25806
|
+
constructor(msg, status, body2) {
|
|
25754
25807
|
super(msg);
|
|
25755
25808
|
this.status = status;
|
|
25756
|
-
this.body =
|
|
25809
|
+
this.body = body2;
|
|
25757
25810
|
}
|
|
25758
25811
|
};
|
|
25759
25812
|
}
|
|
@@ -25846,8 +25899,8 @@ async function mergePullResult(opts) {
|
|
|
25846
25899
|
report.skipped.push({ artifactId: a.id, path: "(no installed target tool)", reason: "no-target-tool" });
|
|
25847
25900
|
continue;
|
|
25848
25901
|
}
|
|
25849
|
-
const
|
|
25850
|
-
const sha = createHash14("sha256").update(
|
|
25902
|
+
const body2 = Buffer.from(a.bodyB64, "base64");
|
|
25903
|
+
const sha = createHash14("sha256").update(body2).digest("hex");
|
|
25851
25904
|
for (const tool of targets) {
|
|
25852
25905
|
const path = installPathFor(a, tool);
|
|
25853
25906
|
if (!path)
|
|
@@ -25860,7 +25913,7 @@ async function mergePullResult(opts) {
|
|
|
25860
25913
|
continue;
|
|
25861
25914
|
}
|
|
25862
25915
|
mkdirSync20(dirname27(path), { recursive: true });
|
|
25863
|
-
writeFileSync20(path,
|
|
25916
|
+
writeFileSync20(path, body2);
|
|
25864
25917
|
pending.push({ artifactId: a.id, tool, artifactType: a.type, artifactName: a.name, sha256: sha, installedAt: Date.now() });
|
|
25865
25918
|
report.written.push({ artifactId: a.id, path });
|
|
25866
25919
|
} catch (err) {
|
|
@@ -26166,7 +26219,7 @@ function context2() {
|
|
|
26166
26219
|
throw new VaultConfigError(`Env var ${s.tokenRef} is not set.`);
|
|
26167
26220
|
return { serverUrl: s.serverUrl, teamId: s.teamId, token };
|
|
26168
26221
|
}
|
|
26169
|
-
async function api(ctx, method, path,
|
|
26222
|
+
async function api(ctx, method, path, body2) {
|
|
26170
26223
|
const doFetch = () => fetch(ctx.serverUrl.replace(/\/+$/, "") + path, {
|
|
26171
26224
|
method,
|
|
26172
26225
|
headers: {
|
|
@@ -26174,7 +26227,7 @@ async function api(ctx, method, path, body) {
|
|
|
26174
26227
|
"Content-Type": "application/json",
|
|
26175
26228
|
"Accept": "application/json"
|
|
26176
26229
|
},
|
|
26177
|
-
body:
|
|
26230
|
+
body: body2 == null ? void 0 : JSON.stringify(body2)
|
|
26178
26231
|
});
|
|
26179
26232
|
let r;
|
|
26180
26233
|
try {
|
|
@@ -26253,13 +26306,13 @@ async function vaultEnableWithRemote(passphrase, remote, opts = {}) {
|
|
|
26253
26306
|
body: JSON.stringify({ saltHex: result.saltHex, keyId: result.keyId })
|
|
26254
26307
|
});
|
|
26255
26308
|
if (r.status === 409) {
|
|
26256
|
-
const
|
|
26257
|
-
if (
|
|
26258
|
-
const redone = vaultEnable(passphrase, { existingSaltHex:
|
|
26259
|
-
if (
|
|
26309
|
+
const body2 = await r.json();
|
|
26310
|
+
if (body2.saltHex && body2.saltHex !== result.saltHex) {
|
|
26311
|
+
const redone = vaultEnable(passphrase, { existingSaltHex: body2.saltHex });
|
|
26312
|
+
if (body2.keyId && body2.keyId !== redone.keyId) {
|
|
26260
26313
|
throw new VaultPassphraseMismatchError("Another device published a vault with a different passphrase. Nothing was changed here.");
|
|
26261
26314
|
}
|
|
26262
|
-
return { ...redone, saltSource: "server", keyIdMatches:
|
|
26315
|
+
return { ...redone, saltSource: "server", keyIdMatches: body2.keyId ? true : void 0 };
|
|
26263
26316
|
}
|
|
26264
26317
|
}
|
|
26265
26318
|
} catch (err) {
|
|
@@ -26421,10 +26474,10 @@ var init_vault_client = __esm({
|
|
|
26421
26474
|
VaultHttpError = class extends Error {
|
|
26422
26475
|
status;
|
|
26423
26476
|
body;
|
|
26424
|
-
constructor(msg, status,
|
|
26477
|
+
constructor(msg, status, body2) {
|
|
26425
26478
|
super(msg);
|
|
26426
26479
|
this.status = status;
|
|
26427
|
-
this.body =
|
|
26480
|
+
this.body = body2;
|
|
26428
26481
|
}
|
|
26429
26482
|
};
|
|
26430
26483
|
uploadKey = (sessionId, tool) => `${sessionId}\0${tool}`;
|
|
@@ -27321,15 +27374,15 @@ async function deviceLogin(opts, onPrompt) {
|
|
|
27321
27374
|
code_verifier: codeVerifier
|
|
27322
27375
|
})
|
|
27323
27376
|
});
|
|
27324
|
-
const
|
|
27325
|
-
if (res.ok && typeof
|
|
27377
|
+
const body2 = await res.json().catch(() => ({}));
|
|
27378
|
+
if (res.ok && typeof body2.access_token === "string") {
|
|
27326
27379
|
return {
|
|
27327
|
-
accessToken:
|
|
27328
|
-
refreshToken: typeof
|
|
27329
|
-
expiresIn: typeof
|
|
27380
|
+
accessToken: body2.access_token,
|
|
27381
|
+
refreshToken: typeof body2.refresh_token === "string" ? body2.refresh_token : void 0,
|
|
27382
|
+
expiresIn: typeof body2.expires_in === "number" ? body2.expires_in : 0
|
|
27330
27383
|
};
|
|
27331
27384
|
}
|
|
27332
|
-
const err =
|
|
27385
|
+
const err = body2.error;
|
|
27333
27386
|
if (err === "authorization_pending") continue;
|
|
27334
27387
|
if (err === "slow_down") {
|
|
27335
27388
|
interval += 5e3;
|
|
@@ -27369,14 +27422,14 @@ async function betterAuthDeviceLogin(serverUrl, onPrompt) {
|
|
|
27369
27422
|
client_id: BETTER_AUTH_CLI_CLIENT_ID
|
|
27370
27423
|
})
|
|
27371
27424
|
});
|
|
27372
|
-
const
|
|
27373
|
-
if (res.ok && typeof
|
|
27425
|
+
const body2 = await res.json().catch(() => ({}));
|
|
27426
|
+
if (res.ok && typeof body2.access_token === "string") {
|
|
27374
27427
|
return {
|
|
27375
|
-
accessToken:
|
|
27376
|
-
expiresIn: typeof
|
|
27428
|
+
accessToken: body2.access_token,
|
|
27429
|
+
expiresIn: typeof body2.expires_in === "number" ? body2.expires_in : 0
|
|
27377
27430
|
};
|
|
27378
27431
|
}
|
|
27379
|
-
const err =
|
|
27432
|
+
const err = body2.error;
|
|
27380
27433
|
if (err === "authorization_pending") continue;
|
|
27381
27434
|
if (err === "slow_down") {
|
|
27382
27435
|
interval += 5e3;
|
|
@@ -27466,8 +27519,8 @@ async function selectSessions(target, opts, fetchImpl = fetch) {
|
|
|
27466
27519
|
headers: { authorization: `Bearer ${target.token}` }
|
|
27467
27520
|
});
|
|
27468
27521
|
if (!res.ok) throw new Error(`list failed: HTTP ${res.status}`);
|
|
27469
|
-
const
|
|
27470
|
-
const page =
|
|
27522
|
+
const body2 = await res.json();
|
|
27523
|
+
const page = body2.sessions ?? [];
|
|
27471
27524
|
if (page.length === 0) break;
|
|
27472
27525
|
for (const row of page) {
|
|
27473
27526
|
if (!row.sessionId) continue;
|
|
@@ -27550,9 +27603,9 @@ async function restoreSessions(ids, opts = {}) {
|
|
|
27550
27603
|
body: JSON.stringify({ session_ids: unique.slice(i, i + BATCH) })
|
|
27551
27604
|
});
|
|
27552
27605
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
27553
|
-
const
|
|
27554
|
-
restored +=
|
|
27555
|
-
notDeleted += (
|
|
27606
|
+
const body2 = await res.json();
|
|
27607
|
+
restored += body2.restored ?? 0;
|
|
27608
|
+
notDeleted += (body2.notDeleted ?? []).length;
|
|
27556
27609
|
}
|
|
27557
27610
|
out.perTarget[t.serverUrl] = { restored, notDeleted };
|
|
27558
27611
|
best = Math.max(best, restored);
|
|
@@ -27618,6 +27671,104 @@ function resumeCommandFor(sessionId, tool) {
|
|
|
27618
27671
|
}
|
|
27619
27672
|
}
|
|
27620
27673
|
|
|
27674
|
+
// ../engine/dist/mcp/show-render.js
|
|
27675
|
+
var BODY_LIMIT = 2e3;
|
|
27676
|
+
var EDGE = 100;
|
|
27677
|
+
var INDENT = " ";
|
|
27678
|
+
var oneLine = (v) => String(v).replace(/\s*\n\s*/g, " \u23CE ");
|
|
27679
|
+
var indent = (text) => text.split("\n").map((l) => INDENT + l).join("\n");
|
|
27680
|
+
function safeSlice(s, start, end) {
|
|
27681
|
+
const lo = start > 0 && /[\uDC00-\uDFFF]/.test(s[start] ?? "") ? start - 1 : start;
|
|
27682
|
+
const hi = end < s.length && /[\uD800-\uDBFF]/.test(s[end - 1] ?? "") ? end + 1 : end;
|
|
27683
|
+
return s.slice(lo, hi);
|
|
27684
|
+
}
|
|
27685
|
+
function body(text, line, opts) {
|
|
27686
|
+
if (opts.full || text.length <= BODY_LIMIT)
|
|
27687
|
+
return indent(text);
|
|
27688
|
+
const lines = text.split("\n").length;
|
|
27689
|
+
const cut = text.length - 2 * EDGE;
|
|
27690
|
+
const how = opts.expandHint ? ` ${opts.expandHint(line)}` : "";
|
|
27691
|
+
return [
|
|
27692
|
+
indent(safeSlice(text, 0, EDGE)),
|
|
27693
|
+
`${INDENT}\u2026 ${cut} characters cut (${text.length} in all, ${lines} lines).${how} \u2026`,
|
|
27694
|
+
indent(safeSlice(text, text.length - EDGE, text.length))
|
|
27695
|
+
].join("\n");
|
|
27696
|
+
}
|
|
27697
|
+
function resultText(result) {
|
|
27698
|
+
if (typeof result === "string")
|
|
27699
|
+
return result;
|
|
27700
|
+
if (Array.isArray(result)) {
|
|
27701
|
+
return result.map((b) => {
|
|
27702
|
+
if (b?.type === "text")
|
|
27703
|
+
return String(b.text ?? "");
|
|
27704
|
+
if (b?.type === "image")
|
|
27705
|
+
return "[image]";
|
|
27706
|
+
if (b?.type === "tool_reference")
|
|
27707
|
+
return `[tool_reference: ${b.tool_name ?? ""}]`;
|
|
27708
|
+
return JSON.stringify(b);
|
|
27709
|
+
}).join("\n");
|
|
27710
|
+
}
|
|
27711
|
+
return JSON.stringify(result);
|
|
27712
|
+
}
|
|
27713
|
+
function renderToolCall(tc, line, opts) {
|
|
27714
|
+
const inp = tc.input && typeof tc.input === "object" ? tc.input : {};
|
|
27715
|
+
const out = [];
|
|
27716
|
+
if (tc.name === "Bash" && inp.command !== void 0) {
|
|
27717
|
+
const desc = inp.description ? ` # ${oneLine(inp.description)}` : "";
|
|
27718
|
+
out.push(`[Bash]${desc}
|
|
27719
|
+
$ ${oneLine(inp.command)}`);
|
|
27720
|
+
} else if (inp.file_path !== void 0) {
|
|
27721
|
+
const inline = {};
|
|
27722
|
+
const blocks = [];
|
|
27723
|
+
for (const [k, v] of Object.entries(inp)) {
|
|
27724
|
+
if (k === "file_path")
|
|
27725
|
+
continue;
|
|
27726
|
+
if (typeof v === "string" && (v.includes("\n") || v.length > 120))
|
|
27727
|
+
blocks.push([k, v]);
|
|
27728
|
+
else
|
|
27729
|
+
inline[k] = v;
|
|
27730
|
+
}
|
|
27731
|
+
const opts_ = Object.keys(inline).length ? ` ${JSON.stringify(inline)}` : "";
|
|
27732
|
+
out.push(`[${tc.name}] ${inp.file_path}${opts_}`);
|
|
27733
|
+
for (const [k, v] of blocks)
|
|
27734
|
+
out.push(` ${k}:`, body(v, line, opts));
|
|
27735
|
+
} else if (typeof tc.input === "string") {
|
|
27736
|
+
out.push(`[${tc.name}]`, body(tc.input, line, opts));
|
|
27737
|
+
} else {
|
|
27738
|
+
const json = JSON.stringify(tc.input ?? {});
|
|
27739
|
+
if (opts.full || json.length <= BODY_LIMIT)
|
|
27740
|
+
out.push(`[${tc.name}] ${oneLine(json)}`);
|
|
27741
|
+
else
|
|
27742
|
+
out.push(`[${tc.name}]`, body(json, line, opts));
|
|
27743
|
+
}
|
|
27744
|
+
if (tc.result !== void 0) {
|
|
27745
|
+
out.push(tc.isError ? " \u2192 error:" : " \u2192 result:", body(resultText(tc.result), line, opts));
|
|
27746
|
+
}
|
|
27747
|
+
return out.join("\n");
|
|
27748
|
+
}
|
|
27749
|
+
function renderShowMessages(messages, opts = {}) {
|
|
27750
|
+
const out = [];
|
|
27751
|
+
for (const msg of messages) {
|
|
27752
|
+
const text = msg.content ?? "";
|
|
27753
|
+
const thinking = msg.thinking ?? "";
|
|
27754
|
+
const calls = msg.toolCalls ?? [];
|
|
27755
|
+
if (!text.trim() && !thinking.trim() && !calls.length && msg.thinking !== void 0)
|
|
27756
|
+
continue;
|
|
27757
|
+
out.push(`**${msg.role}** (line ${msg.line})`);
|
|
27758
|
+
if (thinking.trim())
|
|
27759
|
+
out.push(`_(thinking)_
|
|
27760
|
+
${thinking}`);
|
|
27761
|
+
if (text.trim())
|
|
27762
|
+
out.push(text);
|
|
27763
|
+
for (const tc of calls)
|
|
27764
|
+
out.push(renderToolCall(tc, msg.line, opts));
|
|
27765
|
+
if (!text.trim() && !thinking.trim() && !calls.length)
|
|
27766
|
+
out.push("_(empty)_");
|
|
27767
|
+
out.push("");
|
|
27768
|
+
}
|
|
27769
|
+
return out;
|
|
27770
|
+
}
|
|
27771
|
+
|
|
27621
27772
|
// src/cli.ts
|
|
27622
27773
|
init_paths();
|
|
27623
27774
|
init_claude2();
|
|
@@ -27850,38 +28001,38 @@ async function serverGetSoft(path) {
|
|
|
27850
28001
|
const t = requireTarget();
|
|
27851
28002
|
const res = await fetch(t.base + path, { headers: t.token ? { authorization: `Bearer ${t.token}` } : {} });
|
|
27852
28003
|
if (res.status === 202 || res.status === 404) {
|
|
27853
|
-
const
|
|
27854
|
-
return { status: res.status, data: null, message:
|
|
28004
|
+
const body2 = await res.json().catch(() => ({}));
|
|
28005
|
+
return { status: res.status, data: null, message: body2.message };
|
|
27855
28006
|
}
|
|
27856
28007
|
if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
27857
28008
|
return { status: res.status, data: await readJsonBody(res, t.base, `GET ${path}`) };
|
|
27858
28009
|
}
|
|
27859
|
-
async function serverPost(path,
|
|
28010
|
+
async function serverPost(path, body2) {
|
|
27860
28011
|
const t = requireTarget();
|
|
27861
28012
|
const res = await fetch(t.base + path, {
|
|
27862
28013
|
method: "POST",
|
|
27863
28014
|
headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
|
|
27864
|
-
body: JSON.stringify(
|
|
28015
|
+
body: JSON.stringify(body2)
|
|
27865
28016
|
});
|
|
27866
28017
|
if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
27867
28018
|
return readJsonBody(res, t.base, `POST ${path}`);
|
|
27868
28019
|
}
|
|
27869
|
-
async function serverPatch(path,
|
|
28020
|
+
async function serverPatch(path, body2) {
|
|
27870
28021
|
const t = requireTarget();
|
|
27871
28022
|
const res = await fetch(t.base + path, {
|
|
27872
28023
|
method: "PATCH",
|
|
27873
28024
|
headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
|
|
27874
|
-
body: JSON.stringify(
|
|
28025
|
+
body: JSON.stringify(body2)
|
|
27875
28026
|
});
|
|
27876
28027
|
if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
27877
28028
|
return readJsonBody(res, t.base, `PATCH ${path}`);
|
|
27878
28029
|
}
|
|
27879
|
-
async function serverDelete(path,
|
|
28030
|
+
async function serverDelete(path, body2) {
|
|
27880
28031
|
const t = requireTarget();
|
|
27881
28032
|
const res = await fetch(t.base + path, {
|
|
27882
28033
|
method: "DELETE",
|
|
27883
28034
|
headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
|
|
27884
|
-
body: JSON.stringify(
|
|
28035
|
+
body: JSON.stringify(body2)
|
|
27885
28036
|
});
|
|
27886
28037
|
if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
27887
28038
|
return readJsonBody(res, t.base, `DELETE ${path}`);
|
|
@@ -28168,15 +28319,15 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28168
28319
|
continue;
|
|
28169
28320
|
}
|
|
28170
28321
|
const text = await res.text();
|
|
28171
|
-
let
|
|
28322
|
+
let body2;
|
|
28172
28323
|
try {
|
|
28173
|
-
|
|
28324
|
+
body2 = JSON.parse(text);
|
|
28174
28325
|
} catch {
|
|
28175
28326
|
askFailed.push(`${t.serverUrl} (not JSON: ${JSON.stringify(text.trim().slice(0, 40))})`);
|
|
28176
28327
|
continue;
|
|
28177
28328
|
}
|
|
28178
28329
|
answered++;
|
|
28179
|
-
for (const it of
|
|
28330
|
+
for (const it of body2.items || []) rows.push(it);
|
|
28180
28331
|
} catch (e) {
|
|
28181
28332
|
askFailed.push(`${t.serverUrl} (${describeProbeError(e)})`);
|
|
28182
28333
|
}
|
|
@@ -28425,7 +28576,7 @@ program.command("optimize").description("Deprecated: storage is server-side now,
|
|
|
28425
28576
|
console.log(chalk2.dim("Run `chat-recall sync` to ship sessions; the server manages its own storage."));
|
|
28426
28577
|
process.exit(0);
|
|
28427
28578
|
});
|
|
28428
|
-
program.command("show <session_id>").description("Show conversation content from a session (requires login)").option("-m, --messages <number>", "Number of messages to show", "10").option("-f, --full", "Show full conversation (all messages)", false).action(async (sessionId, options) => {
|
|
28579
|
+
program.command("show <session_id>").description("Show conversation content from a session (requires login)").option("-m, --messages <number>", "Number of messages to show", "10").option("-f, --full", "Show full conversation (all messages)", false).option("-l, --line <number>", "Show only the message at this line, with every tool input and result whole").action(async (sessionId, options) => {
|
|
28429
28580
|
try {
|
|
28430
28581
|
const soft = await serverGetSoft(`/api/conversations/${encodeURIComponent(sessionId)}?limit=0`);
|
|
28431
28582
|
if (!soft.data || soft.data.messages.length === 0) {
|
|
@@ -28435,21 +28586,21 @@ program.command("show <session_id>").description("Show conversation content from
|
|
|
28435
28586
|
const messagesList = soft.data.messages;
|
|
28436
28587
|
console.log(chalk2.bold("Session:"), sessionId);
|
|
28437
28588
|
console.log();
|
|
28438
|
-
|
|
28439
|
-
|
|
28440
|
-
|
|
28441
|
-
|
|
28442
|
-
|
|
28443
|
-
|
|
28444
|
-
|
|
28445
|
-
} else if (msg.role === "assistant") {
|
|
28446
|
-
console.log(`${chalk2.bold.green("Assistant")} ${chalk2.dim(`(line ${msg.line})`)}`);
|
|
28447
|
-
} else {
|
|
28448
|
-
console.log(chalk2.bold.yellow(msg.role));
|
|
28589
|
+
if (options.line !== void 0) {
|
|
28590
|
+
const line = parseInt(options.line, 10);
|
|
28591
|
+
const hit = messagesList.find((m) => m.line === line);
|
|
28592
|
+
if (!hit) {
|
|
28593
|
+
const lines = messagesList.map((m) => m.line);
|
|
28594
|
+
console.log(chalk2.yellow(`No message at line ${options.line}. Its lines run from ${Math.min(...lines)} to ${Math.max(...lines)}.`));
|
|
28595
|
+
process.exit(1);
|
|
28449
28596
|
}
|
|
28450
|
-
console.log(
|
|
28451
|
-
|
|
28597
|
+
console.log(renderShowMessages([hit], { full: true }).join("\n"));
|
|
28598
|
+
return;
|
|
28452
28599
|
}
|
|
28600
|
+
const maxMessages = parseInt(options.messages, 10);
|
|
28601
|
+
const displayMessages = options.full ? messagesList : messagesList.slice(0, maxMessages);
|
|
28602
|
+
const expandHint = (line) => `Run chat-recall show ${sessionId} --line ${line} for the whole text.`;
|
|
28603
|
+
console.log(renderShowMessages(displayMessages, { expandHint }).join("\n"));
|
|
28453
28604
|
console.log(chalk2.dim(`Showing ${displayMessages.length} of ${messagesList.length} messages. Use --full for the complete conversation.`));
|
|
28454
28605
|
{
|
|
28455
28606
|
const rc = resumeCommandFor(sessionId);
|
|
@@ -28662,8 +28813,8 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
28662
28813
|
signal: AbortSignal.timeout(1e4)
|
|
28663
28814
|
});
|
|
28664
28815
|
if (!res.ok) {
|
|
28665
|
-
const
|
|
28666
|
-
console.error(chalk2.red(`Could not send: ${
|
|
28816
|
+
const body2 = await res.json().catch(() => ({}));
|
|
28817
|
+
console.error(chalk2.red(`Could not send: ${body2.error || res.status}`));
|
|
28667
28818
|
process.exitCode = 1;
|
|
28668
28819
|
return;
|
|
28669
28820
|
}
|
|
@@ -29080,8 +29231,8 @@ program.command("verify").description("Check that the server holds everything th
|
|
|
29080
29231
|
if (token) headers.authorization = `Bearer ${token}`;
|
|
29081
29232
|
const res = await fetchWithTimeout2(`${server}/api/status/archives`, { headers }, 12e4);
|
|
29082
29233
|
if (!res.ok) throw new Error(`${server}: HTTP ${res.status} from /api/status/archives`);
|
|
29083
|
-
const
|
|
29084
|
-
return new Map((
|
|
29234
|
+
const body2 = await res.json();
|
|
29235
|
+
return new Map((body2.archives || []).map((a) => [a.id, Number(a.size) || 0]));
|
|
29085
29236
|
}
|
|
29086
29237
|
};
|
|
29087
29238
|
let exitCode = 0;
|
|
@@ -29133,8 +29284,8 @@ ${t.serverUrl}`));
|
|
|
29133
29284
|
console.log(` ${f.sessionId.slice(0, 8)} server records unavailable (HTTP ${res.status})`);
|
|
29134
29285
|
continue;
|
|
29135
29286
|
}
|
|
29136
|
-
const
|
|
29137
|
-
serverIds = new Set(
|
|
29287
|
+
const body2 = await res.json();
|
|
29288
|
+
serverIds = new Set(body2.records || []);
|
|
29138
29289
|
} catch (e) {
|
|
29139
29290
|
console.log(` ${f.sessionId.slice(0, 8)} record fetch failed: ${e instanceof Error ? e.message : e}`);
|
|
29140
29291
|
continue;
|
|
@@ -29454,8 +29605,8 @@ toolkit.command("pull").description("Install artifacts this device is missing, f
|
|
|
29454
29605
|
headers: t.token ? { authorization: `Bearer ${t.token}` } : {}
|
|
29455
29606
|
});
|
|
29456
29607
|
if (!res.ok) continue;
|
|
29457
|
-
const
|
|
29458
|
-
for (const it of
|
|
29608
|
+
const body2 = await res.json();
|
|
29609
|
+
for (const it of body2.items || []) rows.push(it);
|
|
29459
29610
|
} catch (err) {
|
|
29460
29611
|
console.log(chalk2.dim(` (${t.serverUrl} ${type}: ${err instanceof Error ? err.message : err})`));
|
|
29461
29612
|
}
|
|
@@ -29697,13 +29848,13 @@ team.command("publish <type> <name> <file>").description("Publish a local file a
|
|
|
29697
29848
|
process.exit(1);
|
|
29698
29849
|
}
|
|
29699
29850
|
const { readFileSync: readFileSync50 } = await import("fs");
|
|
29700
|
-
const
|
|
29851
|
+
const body2 = readFileSync50(file);
|
|
29701
29852
|
const { teamPublish: teamPublish2 } = await Promise.resolve().then(() => (init_team_client(), team_client_exports));
|
|
29702
29853
|
const a = await teamPublish2({
|
|
29703
29854
|
type,
|
|
29704
29855
|
tool: opts.tool,
|
|
29705
29856
|
name,
|
|
29706
|
-
body,
|
|
29857
|
+
body: body2,
|
|
29707
29858
|
pinnedTo: opts.pinnedTo
|
|
29708
29859
|
});
|
|
29709
29860
|
console.log(chalk2.green(`\u2713 Published ${chalk2.bold(type + "/" + name)} v${a.version}`));
|
|
@@ -29996,13 +30147,13 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
29996
30147
|
4e3
|
|
29997
30148
|
);
|
|
29998
30149
|
if (!res.ok) return null;
|
|
29999
|
-
const
|
|
30000
|
-
return
|
|
30150
|
+
const body2 = await res.json().catch(() => ({}));
|
|
30151
|
+
return body2.task ?? null;
|
|
30001
30152
|
};
|
|
30002
|
-
const patchCard = async (id,
|
|
30153
|
+
const patchCard = async (id, body2) => {
|
|
30003
30154
|
const res = await fetchWithTimeout2(
|
|
30004
30155
|
`${target.base}/api/tasks/${encodeURIComponent(id)}`,
|
|
30005
|
-
{ method: "PATCH", headers, body: JSON.stringify(
|
|
30156
|
+
{ method: "PATCH", headers, body: JSON.stringify(body2) },
|
|
30006
30157
|
6e3
|
|
30007
30158
|
);
|
|
30008
30159
|
return res.ok;
|
|
@@ -30167,8 +30318,8 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30167
30318
|
for (const target of reg.guardTargets()) {
|
|
30168
30319
|
if (!existsSync58(target.configPath)) continue;
|
|
30169
30320
|
if (target.tool === "opencode") {
|
|
30170
|
-
const
|
|
30171
|
-
if (!
|
|
30321
|
+
const body2 = readFileSync50(target.configPath, "utf-8");
|
|
30322
|
+
if (!body2.includes("chat-recall install-hooks")) continue;
|
|
30172
30323
|
unlinkSync4(target.configPath);
|
|
30173
30324
|
removed += 1;
|
|
30174
30325
|
} else {
|