chat-recall 0.7.9 → 0.7.11
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 +31 -0
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +81 -15
- package/dist/auto-update.js.map +1 -1
- package/dist/cli.js +237 -57
- package/dist/cli.js.map +1 -1
- package/dist/derived.d.ts.map +1 -1
- package/dist/derived.js +2 -5
- package/dist/derived.js.map +1 -1
- package/dist/escalate.d.ts +2 -0
- package/dist/escalate.d.ts.map +1 -1
- package/dist/escalate.js +2 -1
- package/dist/escalate.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +6533 -6236
- package/dist/scan-worker.js +109 -8
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +9 -7
- package/dist/sync-client.js.map +1 -1
- package/dist/watch.js +210 -42
- package/package.json +1 -1
- package/skills/chat-recall/SKILL.md +1 -1
- package/skills/chat-recall-find/SKILL.md +4 -2
- package/skills/chat-recall-resume/SKILL.md +3 -1
package/dist/cli.js
CHANGED
|
@@ -4568,6 +4568,72 @@ var init_banners = __esm({
|
|
|
4568
4568
|
}
|
|
4569
4569
|
});
|
|
4570
4570
|
|
|
4571
|
+
// ../engine/dist/core/claude-prompt-origin.js
|
|
4572
|
+
function originFromText(text) {
|
|
4573
|
+
const head = text.trimStart();
|
|
4574
|
+
for (const [prefix, origin] of INJECTED_PREFIXES) {
|
|
4575
|
+
if (head.startsWith(prefix))
|
|
4576
|
+
return origin;
|
|
4577
|
+
}
|
|
4578
|
+
return "human";
|
|
4579
|
+
}
|
|
4580
|
+
function declaredOrigin(value) {
|
|
4581
|
+
if (!value || typeof value !== "object")
|
|
4582
|
+
return void 0;
|
|
4583
|
+
const kind = value.kind;
|
|
4584
|
+
return typeof kind === "string" && kind ? kind : void 0;
|
|
4585
|
+
}
|
|
4586
|
+
function userRecordOrigin(obj, text) {
|
|
4587
|
+
if (obj.isSidechain === true)
|
|
4588
|
+
return "subagent";
|
|
4589
|
+
const declared = declaredOrigin(obj.origin);
|
|
4590
|
+
if (declared && declared !== "human")
|
|
4591
|
+
return declared;
|
|
4592
|
+
if (obj.isMeta === true)
|
|
4593
|
+
return "meta";
|
|
4594
|
+
if (declared === "human")
|
|
4595
|
+
return "human";
|
|
4596
|
+
return originFromText(text);
|
|
4597
|
+
}
|
|
4598
|
+
function queuedCommandPrompt(obj) {
|
|
4599
|
+
if (obj.type !== "attachment")
|
|
4600
|
+
return null;
|
|
4601
|
+
const att = obj.attachment;
|
|
4602
|
+
if (!att || att.type !== "queued_command")
|
|
4603
|
+
return null;
|
|
4604
|
+
const text = promptText(att.prompt);
|
|
4605
|
+
if (!text)
|
|
4606
|
+
return null;
|
|
4607
|
+
if (obj.isSidechain === true)
|
|
4608
|
+
return { text, origin: "subagent" };
|
|
4609
|
+
const declared = declaredOrigin(att.origin);
|
|
4610
|
+
if (declared)
|
|
4611
|
+
return { text, origin: declared };
|
|
4612
|
+
return { text, origin: att.humanTurn === true ? "human" : originFromText(text) };
|
|
4613
|
+
}
|
|
4614
|
+
function promptText(prompt) {
|
|
4615
|
+
if (typeof prompt === "string")
|
|
4616
|
+
return prompt;
|
|
4617
|
+
if (!Array.isArray(prompt))
|
|
4618
|
+
return "";
|
|
4619
|
+
return prompt.filter((b) => !!b && typeof b === "object" && b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
|
|
4620
|
+
}
|
|
4621
|
+
function isPersonMessage(m) {
|
|
4622
|
+
return m.role === "user" && !m.origin;
|
|
4623
|
+
}
|
|
4624
|
+
var INJECTED_PREFIXES;
|
|
4625
|
+
var init_claude_prompt_origin = __esm({
|
|
4626
|
+
"../engine/dist/core/claude-prompt-origin.js"() {
|
|
4627
|
+
"use strict";
|
|
4628
|
+
INJECTED_PREFIXES = [
|
|
4629
|
+
["<task-notification", "task-notification"],
|
|
4630
|
+
["<agent-message", "peer"],
|
|
4631
|
+
["Another Claude session sent a message:", "peer"],
|
|
4632
|
+
["Stop hook feedback:", "hook"]
|
|
4633
|
+
];
|
|
4634
|
+
}
|
|
4635
|
+
});
|
|
4636
|
+
|
|
4571
4637
|
// ../engine/dist/core/project-path-match.js
|
|
4572
4638
|
function canonicalProjectPath(p) {
|
|
4573
4639
|
return (p || "").trim().replace(/\\/g, "/").replace(/[-_]/g, "/").replace(/\/{2,}/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
@@ -5809,7 +5875,8 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
|
|
|
5809
5875
|
const filesToParse = hasSubagentsDir(sessionPath) ? [sessionPath, ...getSubagentPaths(sessionPath)] : [sessionPath];
|
|
5810
5876
|
let userCount = 0;
|
|
5811
5877
|
const seenPrompts = /* @__PURE__ */ new Set();
|
|
5812
|
-
const
|
|
5878
|
+
const pendingQueued = /* @__PURE__ */ new Set();
|
|
5879
|
+
const recordPrompt = (raw, line, via = "record") => {
|
|
5813
5880
|
if (userCount >= maxMessages)
|
|
5814
5881
|
return;
|
|
5815
5882
|
const withoutReminders = raw.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "");
|
|
@@ -5818,8 +5885,14 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
|
|
|
5818
5885
|
const cleanedText = stripInjectedBanners(withoutReminders).trim();
|
|
5819
5886
|
if (cleanedText.length < 10)
|
|
5820
5887
|
return;
|
|
5821
|
-
if (
|
|
5888
|
+
if (via === "enqueue") {
|
|
5889
|
+
if (seenPrompts.has(cleanedText))
|
|
5890
|
+
return;
|
|
5891
|
+
pendingQueued.add(cleanedText);
|
|
5892
|
+
} else if (pendingQueued.has(cleanedText)) {
|
|
5893
|
+
pendingQueued.delete(cleanedText);
|
|
5822
5894
|
return;
|
|
5895
|
+
}
|
|
5823
5896
|
seenPrompts.add(cleanedText);
|
|
5824
5897
|
content.userMessages.push({ text: cleanedText, lineNumber: line, contentType: "user" });
|
|
5825
5898
|
userCount++;
|
|
@@ -5904,12 +5977,16 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
|
|
|
5904
5977
|
text = textParts.join("\n");
|
|
5905
5978
|
}
|
|
5906
5979
|
}
|
|
5907
|
-
if (text)
|
|
5980
|
+
if (text && userRecordOrigin(obj, text) === "human")
|
|
5908
5981
|
recordPrompt(text, lineNum);
|
|
5909
5982
|
} else if (msgType === "queue-operation") {
|
|
5910
|
-
if (obj.operation === "enqueue" && typeof obj.content === "string") {
|
|
5911
|
-
recordPrompt(obj.content, lineNum,
|
|
5983
|
+
if (obj.operation === "enqueue" && typeof obj.content === "string" && originFromText(obj.content) === "human") {
|
|
5984
|
+
recordPrompt(obj.content, lineNum, "enqueue");
|
|
5912
5985
|
}
|
|
5986
|
+
} else if (msgType === "attachment") {
|
|
5987
|
+
const queued = queuedCommandPrompt(obj);
|
|
5988
|
+
if (queued?.origin === "human")
|
|
5989
|
+
recordPrompt(queued.text, lineNum, "delivery");
|
|
5913
5990
|
} else if (msgType === "assistant") {
|
|
5914
5991
|
const msg = obj.message;
|
|
5915
5992
|
if (!msg || typeof msg !== "object")
|
|
@@ -6013,6 +6090,7 @@ var init_session = __esm({
|
|
|
6013
6090
|
"../engine/dist/parsers/session.js"() {
|
|
6014
6091
|
"use strict";
|
|
6015
6092
|
init_banners();
|
|
6093
|
+
init_claude_prompt_origin();
|
|
6016
6094
|
init_claude2();
|
|
6017
6095
|
init_tool_paths();
|
|
6018
6096
|
init_project_dir_name();
|
|
@@ -6177,7 +6255,16 @@ function messagesFromRawLines(raw) {
|
|
|
6177
6255
|
const cleaned = stripBanners(text);
|
|
6178
6256
|
if (!cleaned)
|
|
6179
6257
|
continue;
|
|
6180
|
-
|
|
6258
|
+
const origin = userRecordOrigin(obj, cleaned);
|
|
6259
|
+
messages.push({ line, role: "user", content: cleaned, timestamp, ...origin === "human" ? {} : { origin } });
|
|
6260
|
+
} else if (obj.type === "attachment") {
|
|
6261
|
+
const queued = queuedCommandPrompt(obj);
|
|
6262
|
+
if (!queued)
|
|
6263
|
+
continue;
|
|
6264
|
+
const cleaned = stripBanners(queued.text);
|
|
6265
|
+
if (!cleaned)
|
|
6266
|
+
continue;
|
|
6267
|
+
messages.push({ line, role: "user", content: cleaned, timestamp, ...queued.origin === "human" ? {} : { origin: queued.origin } });
|
|
6181
6268
|
} else if (obj.type === "assistant") {
|
|
6182
6269
|
const blocks = Array.isArray(obj.message?.content) ? obj.message.content : [];
|
|
6183
6270
|
const thinkingBlock = blocks.find((c) => c?.type === "thinking");
|
|
@@ -6273,6 +6360,7 @@ var init_claude = __esm({
|
|
|
6273
6360
|
"../engine/dist/transcript/claude.js"() {
|
|
6274
6361
|
"use strict";
|
|
6275
6362
|
init_logger();
|
|
6363
|
+
init_claude_prompt_origin();
|
|
6276
6364
|
log2 = createLogger("transcript-claude");
|
|
6277
6365
|
INJECTED_BANNERS2 = [
|
|
6278
6366
|
/MCP issues detected\. ?Run \/mcp list for status\.?/g,
|
|
@@ -6885,10 +6973,15 @@ function summarizeMarkers(marked) {
|
|
|
6885
6973
|
}
|
|
6886
6974
|
return counts;
|
|
6887
6975
|
}
|
|
6888
|
-
|
|
6976
|
+
function markersFromTurns(sessionId, turns) {
|
|
6977
|
+
const prompts = turns.filter((t) => t.kind === "user" && t.text).map((t) => ({ line: t.line, ts: t.ts, tsIso: t.tsIso, ...markPrompt(t.text) }));
|
|
6978
|
+
return { v: MARKERS_VERSION, sessionId, prompts, summary: summarizeMarkers(prompts) };
|
|
6979
|
+
}
|
|
6980
|
+
var PROFANITY, PROFANITY_LOOSE, APPROVAL_HEAD, NEG_HEAD, QUESTION_HEAD, DIRECTIVE_HEAD, CLARIFY_PHRASES, FRUSTRATED_PHRASES, MARKERS_VERSION;
|
|
6889
6981
|
var init_session_sentiment = __esm({
|
|
6890
6982
|
"../engine/dist/core/session-sentiment.js"() {
|
|
6891
6983
|
"use strict";
|
|
6984
|
+
init_claude_prompt_origin();
|
|
6892
6985
|
PROFANITY = /\b(fuck(?:ing|er|ed)?|shit|ffs|wtf|bullshit|crap|damn(?:it)?|hell)\b/i;
|
|
6893
6986
|
PROFANITY_LOOSE = /\b(fu[ckj]+(?:ing|er|ed|c?k)?|fukc|fucj|sht|fk|wt[ft])\b/i;
|
|
6894
6987
|
APPROVAL_HEAD = /^(?:yes|y|ok(?:ay)?|sure|alright|fine|i\s*approve|approved|go\s*(?:on|ahead)|do\s*it|continue|please\s*do|sounds?\s*good|let'?s\s*go|ship\s*it|👍|✓+)\b/i;
|
|
@@ -6897,6 +6990,7 @@ var init_session_sentiment = __esm({
|
|
|
6897
6990
|
DIRECTIVE_HEAD = /^(?:please\s+)?(?:use|implement|build|make|add|create|fix|remove|delete|update|refactor|run|deploy|push|merge|test|check|investigate|find|search|show|list|generate|set\s+up|ensure)\b/i;
|
|
6898
6991
|
CLARIFY_PHRASES = /\b(?:wdym|what do you mean|explain|clarify|what is|what's|huh\??|i don'?t understand)\b/i;
|
|
6899
6992
|
FRUSTRATED_PHRASES = /\b(?:why (?:the )?(?:fuck|hell)|wtf|are you (?:kidding|serious)|stop slacking|stop making|why did you|why didn'?t you|i (?:fucking )?(?:asked|told you)|are you (?:listening|even)|come\s*on|just\s+do)\b/i;
|
|
6993
|
+
MARKERS_VERSION = 2;
|
|
6900
6994
|
}
|
|
6901
6995
|
});
|
|
6902
6996
|
|
|
@@ -11365,6 +11459,7 @@ var init_claude2 = __esm({
|
|
|
11365
11459
|
init_first_prompt();
|
|
11366
11460
|
init_tail_read();
|
|
11367
11461
|
init_project_dir_name();
|
|
11462
|
+
init_claude_prompt_origin();
|
|
11368
11463
|
init_generic_engine();
|
|
11369
11464
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11370
11465
|
ClaudeBackend = class {
|
|
@@ -11672,6 +11767,15 @@ var init_claude2 = __esm({
|
|
|
11672
11767
|
}
|
|
11673
11768
|
appendEventsFromText(events, raw, mtime, startLine) {
|
|
11674
11769
|
let lineNum = startLine;
|
|
11770
|
+
const queued = /* @__PURE__ */ new Map();
|
|
11771
|
+
const superseded = /* @__PURE__ */ new Set();
|
|
11772
|
+
const pushPrompt = (e) => {
|
|
11773
|
+
const pending = queued.get(e.text);
|
|
11774
|
+
const earlier = pending?.shift();
|
|
11775
|
+
if (earlier)
|
|
11776
|
+
superseded.add(earlier);
|
|
11777
|
+
events.push(e);
|
|
11778
|
+
};
|
|
11675
11779
|
{
|
|
11676
11780
|
for (const line of raw.split("\n")) {
|
|
11677
11781
|
lineNum++;
|
|
@@ -11687,13 +11791,26 @@ var init_claude2 = __esm({
|
|
|
11687
11791
|
const ts = tsIso ? Date.parse(tsIso) || mtime : mtime;
|
|
11688
11792
|
if (obj.type === "queue-operation") {
|
|
11689
11793
|
if (obj.operation === "enqueue" && typeof obj.content === "string") {
|
|
11690
|
-
const
|
|
11691
|
-
if (
|
|
11692
|
-
|
|
11794
|
+
const text = stripReminders(obj.content);
|
|
11795
|
+
if (text && originFromText(text) === "human") {
|
|
11796
|
+
const e = { kind: "user", ts, tsIso, line: lineNum, text };
|
|
11797
|
+
events.push(e);
|
|
11798
|
+
const list = queued.get(text);
|
|
11799
|
+
if (list)
|
|
11800
|
+
list.push(e);
|
|
11801
|
+
else
|
|
11802
|
+
queued.set(text, [e]);
|
|
11693
11803
|
}
|
|
11694
11804
|
}
|
|
11695
11805
|
continue;
|
|
11696
11806
|
}
|
|
11807
|
+
const delivered = queuedCommandPrompt(obj);
|
|
11808
|
+
if (delivered) {
|
|
11809
|
+
const text = stripReminders(delivered.text);
|
|
11810
|
+
if (text && delivered.origin === "human")
|
|
11811
|
+
pushPrompt({ kind: "user", ts, tsIso, line: lineNum, text });
|
|
11812
|
+
continue;
|
|
11813
|
+
}
|
|
11697
11814
|
if (obj.type === "user") {
|
|
11698
11815
|
const msg = obj.message;
|
|
11699
11816
|
const content = msg?.content;
|
|
@@ -11728,8 +11845,9 @@ var init_claude2 = __esm({
|
|
|
11728
11845
|
}
|
|
11729
11846
|
}
|
|
11730
11847
|
const spoken = stripReminders(text);
|
|
11731
|
-
if (spoken)
|
|
11732
|
-
|
|
11848
|
+
if (spoken && userRecordOrigin(obj, spoken) === "human") {
|
|
11849
|
+
pushPrompt({ kind: "user", ts, tsIso, line: lineNum, text: spoken });
|
|
11850
|
+
}
|
|
11733
11851
|
for (const tr of toolResults) {
|
|
11734
11852
|
events.push({
|
|
11735
11853
|
kind: "tool_result",
|
|
@@ -11778,6 +11896,13 @@ var init_claude2 = __esm({
|
|
|
11778
11896
|
}
|
|
11779
11897
|
}
|
|
11780
11898
|
}
|
|
11899
|
+
if (superseded.size > 0) {
|
|
11900
|
+
let w = 0;
|
|
11901
|
+
for (const e of events)
|
|
11902
|
+
if (!superseded.has(e))
|
|
11903
|
+
events[w++] = e;
|
|
11904
|
+
events.length = w;
|
|
11905
|
+
}
|
|
11781
11906
|
return lineNum;
|
|
11782
11907
|
}
|
|
11783
11908
|
// ── Per-session operations — all delegate to the generic engine ─
|
|
@@ -18521,7 +18646,7 @@ var init_sync_fields = __esm({
|
|
|
18521
18646
|
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";
|
|
18522
18647
|
import { dirname as dirname16, join as join39 } from "path";
|
|
18523
18648
|
function acquireIndexLock(opts) {
|
|
18524
|
-
const lockPath = lockFilePath();
|
|
18649
|
+
const lockPath = lockFilePath(opts.file);
|
|
18525
18650
|
mkdirSync7(dirname16(lockPath), { recursive: true });
|
|
18526
18651
|
if (existsSync39(lockPath)) {
|
|
18527
18652
|
if (!stealStaleLock(lockPath, opts.staleAfterMs ?? 10 * 6e4)) {
|
|
@@ -18563,8 +18688,8 @@ function acquireIndexLock(opts) {
|
|
|
18563
18688
|
}
|
|
18564
18689
|
};
|
|
18565
18690
|
}
|
|
18566
|
-
function lockFilePath() {
|
|
18567
|
-
return join39(getIndexDir(),
|
|
18691
|
+
function lockFilePath(file = ".compact.lock") {
|
|
18692
|
+
return join39(getIndexDir(), file);
|
|
18568
18693
|
}
|
|
18569
18694
|
function stealStaleLock(lockPath, staleAfterMs) {
|
|
18570
18695
|
try {
|
|
@@ -18640,7 +18765,7 @@ var init_http = __esm({
|
|
|
18640
18765
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18641
18766
|
} catch {
|
|
18642
18767
|
try {
|
|
18643
|
-
if (true) CLI_VERSION = "0.7.
|
|
18768
|
+
if (true) CLI_VERSION = "0.7.11";
|
|
18644
18769
|
} catch {
|
|
18645
18770
|
}
|
|
18646
18771
|
}
|
|
@@ -18685,8 +18810,7 @@ function collectDerivedRows(ref, mtime, count, maxRowBytes) {
|
|
|
18685
18810
|
if (fullOutcome.found) data = fullOutcome.commits;
|
|
18686
18811
|
} else if (kind === "markers") {
|
|
18687
18812
|
const turns = extractTurnsAny(id, { maxTurns: 5e4 });
|
|
18688
|
-
|
|
18689
|
-
data = { sessionId: id, prompts, summary: summarizeMarkers(prompts) };
|
|
18813
|
+
data = markersFromTurns(id, turns.turns);
|
|
18690
18814
|
}
|
|
18691
18815
|
} catch {
|
|
18692
18816
|
data = null;
|
|
@@ -19139,7 +19263,7 @@ var init_telemetry = __esm({
|
|
|
19139
19263
|
init_sync_client();
|
|
19140
19264
|
cliVersion2 = () => {
|
|
19141
19265
|
try {
|
|
19142
|
-
return true ? "0.7.
|
|
19266
|
+
return true ? "0.7.11" : "dev";
|
|
19143
19267
|
} catch {
|
|
19144
19268
|
return "dev";
|
|
19145
19269
|
}
|
|
@@ -19157,6 +19281,7 @@ __export(collector_health_exports, {
|
|
|
19157
19281
|
applySyncOutcome: () => applySyncOutcome,
|
|
19158
19282
|
collectorHealthPath: () => collectorHealthPath,
|
|
19159
19283
|
crashesAtBoot: () => crashesAtBoot,
|
|
19284
|
+
firstSyncInProgress: () => firstSyncInProgress,
|
|
19160
19285
|
judgeHealth: () => judgeHealth,
|
|
19161
19286
|
markCleanExit: () => markCleanExit,
|
|
19162
19287
|
progressLine: () => progressLine,
|
|
@@ -19189,7 +19314,11 @@ function progressLine(h) {
|
|
|
19189
19314
|
if (!p || p.complete || p.total <= 0)
|
|
19190
19315
|
return null;
|
|
19191
19316
|
const pct = Math.min(99, Math.floor(100 * p.done / p.total));
|
|
19192
|
-
return
|
|
19317
|
+
return `${p.first ? "first sync" : "sync"} in progress \u2014 ${p.done.toLocaleString()} of ${p.total.toLocaleString()} sessions (${pct}%)`;
|
|
19318
|
+
}
|
|
19319
|
+
function firstSyncInProgress(h) {
|
|
19320
|
+
const p = h?.progress;
|
|
19321
|
+
return !!p && p.first === true && !p.complete && p.total > 0;
|
|
19193
19322
|
}
|
|
19194
19323
|
function collectorHealthPath() {
|
|
19195
19324
|
return healthPath();
|
|
@@ -19502,6 +19631,8 @@ var init_client_events = __esm({
|
|
|
19502
19631
|
// src/auto-update.ts
|
|
19503
19632
|
var auto_update_exports = {};
|
|
19504
19633
|
__export(auto_update_exports, {
|
|
19634
|
+
LOCKED_REASON: () => LOCKED_REASON,
|
|
19635
|
+
STOPPING_REASON: () => STOPPING_REASON,
|
|
19505
19636
|
clearUpdateFailures: () => clearUpdateFailures,
|
|
19506
19637
|
compareVersions: () => compareVersions,
|
|
19507
19638
|
executeAutoUpdate: () => executeAutoUpdate,
|
|
@@ -19513,8 +19644,10 @@ __export(auto_update_exports, {
|
|
|
19513
19644
|
planAutoUpdate: () => planAutoUpdate,
|
|
19514
19645
|
readUpdateState: () => readUpdateState,
|
|
19515
19646
|
resolveNpm: () => resolveNpm,
|
|
19647
|
+
restartCommand: () => restartCommand,
|
|
19516
19648
|
runAutoUpdate: () => runAutoUpdate,
|
|
19517
19649
|
runningPrefix: () => runningPrefix,
|
|
19650
|
+
stopAutoUpdates: () => stopAutoUpdates,
|
|
19518
19651
|
sweepStaleStaging: () => sweepStaleStaging,
|
|
19519
19652
|
tarballUrl: () => tarballUrl
|
|
19520
19653
|
});
|
|
@@ -19610,6 +19743,10 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
19610
19743
|
};
|
|
19611
19744
|
const tgz = join41(dir, "chat-recall.tgz");
|
|
19612
19745
|
writeFileSync8(tgz, buf);
|
|
19746
|
+
if (deps.stopping?.()) {
|
|
19747
|
+
discardStaging();
|
|
19748
|
+
return { updated: false, reason: STOPPING_REASON };
|
|
19749
|
+
}
|
|
19613
19750
|
try {
|
|
19614
19751
|
deps.install(tgz);
|
|
19615
19752
|
} catch (e) {
|
|
@@ -19624,9 +19761,11 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
19624
19761
|
reason: `install reported success but ${landed} is still on disk (wanted ${plan.to}) \u2014 the package that runs is not the one npm wrote. Reinstall by hand: npm install -g ${plan.url}`
|
|
19625
19762
|
};
|
|
19626
19763
|
}
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19764
|
+
if (!deps.stopping?.()) {
|
|
19765
|
+
try {
|
|
19766
|
+
deps.restart(deps.platform ?? process.platform);
|
|
19767
|
+
} catch {
|
|
19768
|
+
}
|
|
19630
19769
|
}
|
|
19631
19770
|
return { updated: true, reason: `updated ${plan.from} \u2192 ${plan.to}`, from: plan.from, to: plan.to };
|
|
19632
19771
|
}
|
|
@@ -19685,10 +19824,18 @@ function realInstall(tgz) {
|
|
|
19685
19824
|
npmInstall(npm, ["install", "-g", "--prefix", join41(homedir15(), ".local"), tgz]);
|
|
19686
19825
|
}
|
|
19687
19826
|
}
|
|
19827
|
+
function acquireUpdateLock() {
|
|
19828
|
+
return acquireIndexLock({ kind: "auto-update", file: ".update.lock", staleAfterMs: 10 * 6e4 });
|
|
19829
|
+
}
|
|
19830
|
+
function restartCommand(platform2) {
|
|
19831
|
+
if (platform2 === "linux") return { cmd: "systemctl --user --no-block restart chat-recall-watch.service" };
|
|
19832
|
+
if (platform2 === "darwin") return { cmd: "launchctl kickstart -k gui/$(id -u)/com.chat-recall.watch", shell: "/bin/bash" };
|
|
19833
|
+
if (platform2 === "win32") return { cmd: "schtasks /End /TN chat-recall-watch & schtasks /Run /TN chat-recall-watch" };
|
|
19834
|
+
return null;
|
|
19835
|
+
}
|
|
19688
19836
|
function realRestart(platform2) {
|
|
19689
|
-
|
|
19690
|
-
|
|
19691
|
-
else if (platform2 === "win32") execSync2("schtasks /End /TN chat-recall-watch & schtasks /Run /TN chat-recall-watch", { stdio: "ignore" });
|
|
19837
|
+
const c = restartCommand(platform2);
|
|
19838
|
+
if (c) execSync2(c.cmd, { stdio: "ignore", ...c.shell ? { shell: c.shell } : {} });
|
|
19692
19839
|
}
|
|
19693
19840
|
function updateStatePath() {
|
|
19694
19841
|
const dir = process.env.CHAT_RECALL_DATA_DIR || join41(homedir15(), ".chat-recall");
|
|
@@ -19721,6 +19868,9 @@ function noteUpdateFailure(target) {
|
|
|
19721
19868
|
function clearUpdateFailures() {
|
|
19722
19869
|
writeUpdateState({});
|
|
19723
19870
|
}
|
|
19871
|
+
function stopAutoUpdates() {
|
|
19872
|
+
stopRequested = true;
|
|
19873
|
+
}
|
|
19724
19874
|
async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
|
|
19725
19875
|
let caps;
|
|
19726
19876
|
try {
|
|
@@ -19747,12 +19897,28 @@ async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
|
|
|
19747
19897
|
if (target && hasGivenUpOn(target)) {
|
|
19748
19898
|
return { updated: false, reason: `gave up installing ${plan.to} after ${GIVE_UP_AFTER} failed attempts \u2014 run \`npm install -g chat-recall\` by hand` };
|
|
19749
19899
|
}
|
|
19750
|
-
const
|
|
19751
|
-
|
|
19752
|
-
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
|
|
19900
|
+
const stopping = deps?.stopping ?? (() => stopRequested);
|
|
19901
|
+
if (stopping()) return { updated: false, reason: STOPPING_REASON };
|
|
19902
|
+
const lock = (deps?.acquireLock ?? acquireUpdateLock)();
|
|
19903
|
+
if (!lock) return { updated: false, reason: LOCKED_REASON };
|
|
19904
|
+
let result;
|
|
19905
|
+
try {
|
|
19906
|
+
const onDisk = (deps?.onDisk ?? installedVersion)();
|
|
19907
|
+
if (onDisk && plan.to && compareVersions(onDisk, plan.to) >= 0) {
|
|
19908
|
+
return { updated: false, reason: `already current: ${onDisk} is on disk` };
|
|
19909
|
+
}
|
|
19910
|
+
result = await executeAutoUpdate(plan, {
|
|
19911
|
+
download: deps?.download ?? realDownload,
|
|
19912
|
+
install: deps?.install ?? realInstall,
|
|
19913
|
+
restart: deps?.restart ?? realRestart,
|
|
19914
|
+
platform: deps?.platform,
|
|
19915
|
+
verify: deps?.verify,
|
|
19916
|
+
stopping
|
|
19917
|
+
});
|
|
19918
|
+
} finally {
|
|
19919
|
+
lock.release();
|
|
19920
|
+
}
|
|
19921
|
+
if (result.reason === STOPPING_REASON) return result;
|
|
19756
19922
|
if (!result.updated) {
|
|
19757
19923
|
const failures = target ? noteUpdateFailure(target) : 1;
|
|
19758
19924
|
if (failures <= GIVE_UP_AFTER) {
|
|
@@ -19768,14 +19934,18 @@ async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
|
|
|
19768
19934
|
}
|
|
19769
19935
|
return result;
|
|
19770
19936
|
}
|
|
19771
|
-
var tarballUrl, GIVE_UP_AFTER, reportedStandingSkip;
|
|
19937
|
+
var tarballUrl, GIVE_UP_AFTER, reportedStandingSkip, STOPPING_REASON, LOCKED_REASON, stopRequested;
|
|
19772
19938
|
var init_auto_update = __esm({
|
|
19773
19939
|
"src/auto-update.ts"() {
|
|
19774
19940
|
"use strict";
|
|
19775
19941
|
init_http();
|
|
19942
|
+
init_index_lock();
|
|
19776
19943
|
tarballUrl = (base3, version2) => `${base3.replace(/\/+$/, "")}/install/${version2 ? `chat-recall-${version2}.tgz` : "chat-recall.tgz"}`;
|
|
19777
19944
|
GIVE_UP_AFTER = 3;
|
|
19778
19945
|
reportedStandingSkip = /* @__PURE__ */ new Set();
|
|
19946
|
+
STOPPING_REASON = "not installed: this process is shutting down";
|
|
19947
|
+
LOCKED_REASON = "another process is installing an update";
|
|
19948
|
+
stopRequested = false;
|
|
19779
19949
|
}
|
|
19780
19950
|
});
|
|
19781
19951
|
|
|
@@ -20726,7 +20896,8 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20726
20896
|
}
|
|
20727
20897
|
trace?.("conversation walk start");
|
|
20728
20898
|
const walkStartedAt = Date.now();
|
|
20729
|
-
|
|
20899
|
+
const firstWalk = (ledger ?? getSyncedRows(base3)).size === 0;
|
|
20900
|
+
reportWalkProgress({ done: 0, total: slice.length, startedAt: walkStartedAt, complete: false, first: firstWalk });
|
|
20730
20901
|
walkProgressForUpload = { done: 0, total: slice.length, complete: false };
|
|
20731
20902
|
let traceN = 0;
|
|
20732
20903
|
let considered = 0;
|
|
@@ -20734,7 +20905,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20734
20905
|
await new Promise((resolve3) => setImmediate(resolve3));
|
|
20735
20906
|
considered++;
|
|
20736
20907
|
const walkDone = considered >= slice.length;
|
|
20737
|
-
reportWalkProgress({ done: considered, total: slice.length, startedAt: walkStartedAt, complete: walkDone });
|
|
20908
|
+
reportWalkProgress({ done: considered, total: slice.length, startedAt: walkStartedAt, complete: walkDone, first: firstWalk });
|
|
20738
20909
|
walkProgressForUpload = { done: considered, total: slice.length, complete: walkDone };
|
|
20739
20910
|
if (trace && ++traceN % 500 === 0) trace(`walk ${traceN}/${slice.length} \xB7 at ${ref.prefixedId}`);
|
|
20740
20911
|
localSessionIds.add(ref.prefixedId);
|
|
@@ -21006,7 +21177,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21006
21177
|
}
|
|
21007
21178
|
}
|
|
21008
21179
|
if (opts.prune) await post({ prune_empty_sessions: true });
|
|
21009
|
-
reportWalkProgress({ done: slice.length, total: slice.length, startedAt: walkStartedAt, complete: true });
|
|
21180
|
+
reportWalkProgress({ done: slice.length, total: slice.length, startedAt: walkStartedAt, complete: true, first: firstWalk });
|
|
21010
21181
|
walkProgressForUpload = { done: slice.length, total: slice.length, complete: true };
|
|
21011
21182
|
return {
|
|
21012
21183
|
uploaded: convBatch.sent + appendResults.uploaded,
|
|
@@ -21137,7 +21308,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21137
21308
|
if (!transcript) return null;
|
|
21138
21309
|
const textMessages = transcript.messages.filter((m) => m.role !== "summary" && m.content?.trim());
|
|
21139
21310
|
if (textMessages.length === 0 && !transcript.messages.some((m) => m.toolCalls?.length)) return null;
|
|
21140
|
-
const firstUser = textMessages.find(
|
|
21311
|
+
const firstUser = textMessages.find(isPersonMessage);
|
|
21141
21312
|
if (isInternalToolPrompt(firstUser?.content)) return null;
|
|
21142
21313
|
const count = { redactions: 0 };
|
|
21143
21314
|
const envelope = redactDeep(
|
|
@@ -21146,7 +21317,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21146
21317
|
);
|
|
21147
21318
|
let projectPath = ref.projectPath;
|
|
21148
21319
|
const meta = { messageCount: textMessages.length };
|
|
21149
|
-
if (textMessages.filter(
|
|
21320
|
+
if (textMessages.filter(isPersonMessage).length <= 1) meta.oneShot = true;
|
|
21150
21321
|
try {
|
|
21151
21322
|
const cwd = ref.fullPath ? readCwdFromJsonl(ref.fullPath) : "";
|
|
21152
21323
|
if (cwd) projectPath = cwd;
|
|
@@ -21298,7 +21469,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21298
21469
|
envelope,
|
|
21299
21470
|
raw_b64,
|
|
21300
21471
|
raw_size,
|
|
21301
|
-
first_prompt: envTexts.find(
|
|
21472
|
+
first_prompt: envTexts.find(isPersonMessage)?.content?.slice(0, 200),
|
|
21302
21473
|
// Byte offset this FULL sync is synced THROUGH (file size at build time,
|
|
21303
21474
|
// or the end of the bounded tail for an oversized session). The server
|
|
21304
21475
|
// stores it as the envelope's `o`; the ledger records the SAME value
|
|
@@ -21354,7 +21525,7 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
|
|
|
21354
21525
|
bytes: 0
|
|
21355
21526
|
};
|
|
21356
21527
|
}
|
|
21357
|
-
const firstUser = textMessages.find(
|
|
21528
|
+
const firstUser = textMessages.find(isPersonMessage);
|
|
21358
21529
|
if (isInternalToolPrompt(firstUser?.content)) return null;
|
|
21359
21530
|
const count = { redactions: 0 };
|
|
21360
21531
|
const envelope = redactDeep(
|
|
@@ -21431,6 +21602,7 @@ var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServer
|
|
|
21431
21602
|
var init_sync_client = __esm({
|
|
21432
21603
|
"src/sync-client.ts"() {
|
|
21433
21604
|
"use strict";
|
|
21605
|
+
init_claude_prompt_origin();
|
|
21434
21606
|
init_credentials_env();
|
|
21435
21607
|
init_secret_redactor();
|
|
21436
21608
|
init_source_discovery();
|
|
@@ -21472,7 +21644,7 @@ var init_sync_client = __esm({
|
|
|
21472
21644
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21473
21645
|
} catch {
|
|
21474
21646
|
try {
|
|
21475
|
-
if (true) ownVersion = "0.7.
|
|
21647
|
+
if (true) ownVersion = "0.7.11";
|
|
21476
21648
|
} catch {
|
|
21477
21649
|
}
|
|
21478
21650
|
}
|
|
@@ -23676,7 +23848,7 @@ function extractCorrections(messages, cap = 5) {
|
|
|
23676
23848
|
const seen = /* @__PURE__ */ new Set();
|
|
23677
23849
|
let userTurns = 0;
|
|
23678
23850
|
for (const msg of messages) {
|
|
23679
|
-
if (msg
|
|
23851
|
+
if (!isPersonMessage(msg)) continue;
|
|
23680
23852
|
userTurns++;
|
|
23681
23853
|
if (userTurns === 1) continue;
|
|
23682
23854
|
if (isNoiseUserMessage(msg.content)) continue;
|
|
@@ -23782,6 +23954,7 @@ var CORRECTION_STARTS, CORRECTION_CONTAINS, TERMINAL_STATUSES;
|
|
|
23782
23954
|
var init_escalate = __esm({
|
|
23783
23955
|
"src/escalate.ts"() {
|
|
23784
23956
|
"use strict";
|
|
23957
|
+
init_claude_prompt_origin();
|
|
23785
23958
|
CORRECTION_STARTS = [
|
|
23786
23959
|
/^no+\b[,.! ]/i,
|
|
23787
23960
|
/^(nope|wrong|incorrect|not quite|not right)\b/i,
|
|
@@ -25633,7 +25806,7 @@ var init_intent_drain = __esm({
|
|
|
25633
25806
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25634
25807
|
} catch {
|
|
25635
25808
|
try {
|
|
25636
|
-
if (true) ownVersion2 = "0.7.
|
|
25809
|
+
if (true) ownVersion2 = "0.7.11";
|
|
25637
25810
|
} catch {
|
|
25638
25811
|
}
|
|
25639
25812
|
}
|
|
@@ -27650,17 +27823,18 @@ var init_bulk_delete = __esm({
|
|
|
27650
27823
|
});
|
|
27651
27824
|
|
|
27652
27825
|
// ../engine/dist/core/resume-command.js
|
|
27826
|
+
var SESSION_ID_PREFIXES = {
|
|
27827
|
+
codex: "codex_",
|
|
27828
|
+
opencode: "opencode_",
|
|
27829
|
+
agy: "agy_",
|
|
27830
|
+
cursor: "cursor_",
|
|
27831
|
+
gemini: "gemini_"
|
|
27832
|
+
};
|
|
27653
27833
|
function toolOfSessionId(sessionId) {
|
|
27654
|
-
|
|
27655
|
-
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
if (sessionId.startsWith("agy_"))
|
|
27659
|
-
return "agy";
|
|
27660
|
-
if (sessionId.startsWith("cursor_"))
|
|
27661
|
-
return "cursor";
|
|
27662
|
-
if (sessionId.startsWith("gemini_"))
|
|
27663
|
-
return "gemini";
|
|
27834
|
+
for (const [tool, prefix] of Object.entries(SESSION_ID_PREFIXES)) {
|
|
27835
|
+
if (sessionId.startsWith(prefix))
|
|
27836
|
+
return tool;
|
|
27837
|
+
}
|
|
27664
27838
|
return "claude";
|
|
27665
27839
|
}
|
|
27666
27840
|
function resumeCommandFor(sessionId, tool) {
|
|
@@ -27771,7 +27945,7 @@ function renderShowMessages(messages, opts = {}) {
|
|
|
27771
27945
|
const calls = msg.toolCalls ?? [];
|
|
27772
27946
|
if (!text.trim() && !thinking.trim() && !calls.length && msg.thinking !== void 0)
|
|
27773
27947
|
continue;
|
|
27774
|
-
out.push(`**${msg.role}** (line ${msg.line})`);
|
|
27948
|
+
out.push(msg.origin ? `**${msg.role}** (line ${msg.line}, written by the harness: ${msg.origin})` : `**${msg.role}** (line ${msg.line})`);
|
|
27775
27949
|
if (thinking.trim())
|
|
27776
27950
|
out.push(`_(thinking)_
|
|
27777
27951
|
${thinking}`);
|
|
@@ -27785,6 +27959,13 @@ ${thinking}`);
|
|
|
27785
27959
|
}
|
|
27786
27960
|
return out;
|
|
27787
27961
|
}
|
|
27962
|
+
function nearestMessageLines(messages, line, count = 4) {
|
|
27963
|
+
return [...new Set(messages.map((m) => m.line))].sort((a, b) => Math.abs(a - line) - Math.abs(b - line) || a - b).slice(0, count).sort((a, b) => a - b);
|
|
27964
|
+
}
|
|
27965
|
+
function noMessageAtLine(messages, line, sessionId) {
|
|
27966
|
+
const near = nearestMessageLines(messages, line);
|
|
27967
|
+
return `No message at line ${line} in ${sessionId}. The nearest messages are at lines ${near.join(", ")}.`;
|
|
27968
|
+
}
|
|
27788
27969
|
|
|
27789
27970
|
// src/cli.ts
|
|
27790
27971
|
init_paths();
|
|
@@ -28541,7 +28722,7 @@ program.command("search <query>").description("Search your server for relevant s
|
|
|
28541
28722
|
(c) => c.chunkType !== "summary" && c.chunkType !== "first_prompt"
|
|
28542
28723
|
);
|
|
28543
28724
|
if (chunk) {
|
|
28544
|
-
const label = chunk.chunkType === "assistant" ? "Discussed" : chunk.chunkType === "user_context" ? "Asked about" : chunk.chunkType === "tool_result" ? "Tool result" : "Context";
|
|
28725
|
+
const label = chunk.chunkType === "assistant" ? "Discussed" : chunk.chunkType === "user_context" ? "Asked about" : chunk.chunkType === "tool_result" ? "Tool result" : chunk.chunkType === "harness" ? "Harness message" : "Context";
|
|
28545
28726
|
let text = chunk.text.replace(/\n/g, " ").trim();
|
|
28546
28727
|
if (text.length > 150) text = text.slice(0, 150) + "...";
|
|
28547
28728
|
console.log(` ${chalk2.magenta(label + ":")} ${text}`);
|
|
@@ -28607,8 +28788,7 @@ program.command("show <session_id>").description("Show conversation content from
|
|
|
28607
28788
|
const line = parseInt(options.line, 10);
|
|
28608
28789
|
const hit = messagesList.find((m) => m.line === line);
|
|
28609
28790
|
if (!hit) {
|
|
28610
|
-
|
|
28611
|
-
console.log(chalk2.yellow(`No message at line ${options.line}. Its lines run from ${Math.min(...lines)} to ${Math.max(...lines)}.`));
|
|
28791
|
+
console.log(chalk2.yellow(noMessageAtLine(messagesList, line, sessionId)));
|
|
28612
28792
|
process.exit(1);
|
|
28613
28793
|
}
|
|
28614
28794
|
console.log(renderShowMessages([hit], { full: true }).join("\n"));
|