chat-recall 0.7.11 → 0.7.12
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 +184 -13
- package/dist/cli.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +178 -11
- package/dist/scan-worker.d.ts.map +1 -1
- package/dist/scan-worker.js +199 -100
- package/dist/scan-worker.js.map +1 -1
- package/dist/sync-client.js +2 -2
- package/dist/sync-client.js.map +1 -1
- package/dist/watch.js +183 -12
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4628,8 +4628,15 @@ var init_claude_prompt_origin = __esm({
|
|
|
4628
4628
|
INJECTED_PREFIXES = [
|
|
4629
4629
|
["<task-notification", "task-notification"],
|
|
4630
4630
|
["<agent-message", "peer"],
|
|
4631
|
+
["<cross-session-message", "peer"],
|
|
4632
|
+
["[Cross-session delivery notice]", "peer"],
|
|
4631
4633
|
["Another Claude session sent a message:", "peer"],
|
|
4632
|
-
["Stop hook feedback:", "hook"]
|
|
4634
|
+
["Stop hook feedback:", "hook"],
|
|
4635
|
+
["<bash-stdout>", "command-output"],
|
|
4636
|
+
["<bash-stderr>", "command-output"],
|
|
4637
|
+
["<local-command-stdout>", "command-output"],
|
|
4638
|
+
["<local-command-stderr>", "command-output"],
|
|
4639
|
+
["<<autonomous-loop", "meta"]
|
|
4633
4640
|
];
|
|
4634
4641
|
}
|
|
4635
4642
|
});
|
|
@@ -6618,7 +6625,11 @@ __export(raw_exports, {
|
|
|
6618
6625
|
gzipContainer: () => gzipContainer,
|
|
6619
6626
|
mapContainerText: () => mapContainerText,
|
|
6620
6627
|
parseOpenCodeDumpText: () => parseOpenCodeDumpText,
|
|
6621
|
-
parseTranscriptFromContainer: () => parseTranscriptFromContainer
|
|
6628
|
+
parseTranscriptFromContainer: () => parseTranscriptFromContainer,
|
|
6629
|
+
redactContainer: () => redactContainer,
|
|
6630
|
+
redactJsonLine: () => redactJsonLine,
|
|
6631
|
+
repairContainer: () => repairContainer,
|
|
6632
|
+
repairRedactedJsonl: () => repairRedactedJsonl
|
|
6622
6633
|
});
|
|
6623
6634
|
import { gzipSync, gunzipSync } from "zlib";
|
|
6624
6635
|
import { createHash } from "crypto";
|
|
@@ -6659,6 +6670,134 @@ function gunzipContainer(gz) {
|
|
|
6659
6670
|
function mapContainerText(c, fn) {
|
|
6660
6671
|
return { ...c, files: c.files.map((f) => ({ name: f.name, text: fn(f.text) })) };
|
|
6661
6672
|
}
|
|
6673
|
+
function repairRedactedJsonl(text) {
|
|
6674
|
+
let repaired = 0;
|
|
6675
|
+
const parts = [];
|
|
6676
|
+
let copied = 0;
|
|
6677
|
+
let at = text.indexOf("[REDACTED:");
|
|
6678
|
+
while (at >= 0) {
|
|
6679
|
+
const start = text.lastIndexOf("\n", at) + 1;
|
|
6680
|
+
let end = text.indexOf("\n", at);
|
|
6681
|
+
if (end < 0)
|
|
6682
|
+
end = text.length;
|
|
6683
|
+
const fixed = repairLine(text.slice(start, end));
|
|
6684
|
+
if (fixed !== null) {
|
|
6685
|
+
parts.push(text.slice(copied, start), fixed);
|
|
6686
|
+
copied = end;
|
|
6687
|
+
repaired++;
|
|
6688
|
+
}
|
|
6689
|
+
at = text.indexOf("[REDACTED:", end);
|
|
6690
|
+
}
|
|
6691
|
+
if (repaired === 0)
|
|
6692
|
+
return { text, repaired: 0 };
|
|
6693
|
+
parts.push(text.slice(copied));
|
|
6694
|
+
return { text: parts.join(""), repaired };
|
|
6695
|
+
}
|
|
6696
|
+
function parseError(line) {
|
|
6697
|
+
try {
|
|
6698
|
+
JSON.parse(line);
|
|
6699
|
+
return null;
|
|
6700
|
+
} catch (e) {
|
|
6701
|
+
const m = /position (\d+)/.exec(e instanceof Error ? e.message : "");
|
|
6702
|
+
return m ? Number(m[1]) : line.length;
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
function repairLine(line) {
|
|
6706
|
+
if (!line.includes("[REDACTED:") || parseError(line) === null)
|
|
6707
|
+
return null;
|
|
6708
|
+
let out = line.replace(/(?<!\\)((?:\\\\)*)\\(\[REDACTED:)/g, "$1$2");
|
|
6709
|
+
for (let attempt = 0; attempt < 64; attempt++) {
|
|
6710
|
+
const at = parseError(out);
|
|
6711
|
+
if (at === null)
|
|
6712
|
+
return out;
|
|
6713
|
+
let site = -1;
|
|
6714
|
+
for (const m of out.matchAll(MARKER_QUOTE)) {
|
|
6715
|
+
const q = m.index + m[0].length - 1;
|
|
6716
|
+
if (q < at)
|
|
6717
|
+
site = q;
|
|
6718
|
+
}
|
|
6719
|
+
if (site < 0)
|
|
6720
|
+
return null;
|
|
6721
|
+
out = out.slice(0, site) + "\\" + out.slice(site);
|
|
6722
|
+
}
|
|
6723
|
+
return null;
|
|
6724
|
+
}
|
|
6725
|
+
function redactJsonLine(line, redact) {
|
|
6726
|
+
if (!line.includes('"'))
|
|
6727
|
+
return redact(line);
|
|
6728
|
+
try {
|
|
6729
|
+
JSON.parse(line);
|
|
6730
|
+
} catch {
|
|
6731
|
+
return redact(line);
|
|
6732
|
+
}
|
|
6733
|
+
const decoded = mapJsonStrings(line, redact, true);
|
|
6734
|
+
const out = redact(decoded);
|
|
6735
|
+
try {
|
|
6736
|
+
JSON.parse(out);
|
|
6737
|
+
return out;
|
|
6738
|
+
} catch {
|
|
6739
|
+
return mapJsonStrings(decoded, redact, false);
|
|
6740
|
+
}
|
|
6741
|
+
}
|
|
6742
|
+
function mapJsonStrings(line, fn, escapedOnly) {
|
|
6743
|
+
let out = "";
|
|
6744
|
+
let i = 0;
|
|
6745
|
+
for (; ; ) {
|
|
6746
|
+
const q = line.indexOf('"', i);
|
|
6747
|
+
if (q < 0)
|
|
6748
|
+
return out + line.slice(i);
|
|
6749
|
+
let j = q + 1;
|
|
6750
|
+
while (j < line.length) {
|
|
6751
|
+
const c = line.charCodeAt(j);
|
|
6752
|
+
if (c === 92)
|
|
6753
|
+
j += 2;
|
|
6754
|
+
else if (c === 34)
|
|
6755
|
+
break;
|
|
6756
|
+
else
|
|
6757
|
+
j++;
|
|
6758
|
+
}
|
|
6759
|
+
const token = line.slice(q, j + 1);
|
|
6760
|
+
out += line.slice(i, q);
|
|
6761
|
+
i = j + 1;
|
|
6762
|
+
const body2 = token.slice(1, -1);
|
|
6763
|
+
const escaped = body2.includes("\\");
|
|
6764
|
+
if (escapedOnly && !escaped) {
|
|
6765
|
+
out += token;
|
|
6766
|
+
continue;
|
|
6767
|
+
}
|
|
6768
|
+
let value = body2;
|
|
6769
|
+
if (escaped) {
|
|
6770
|
+
try {
|
|
6771
|
+
value = JSON.parse(token);
|
|
6772
|
+
} catch {
|
|
6773
|
+
out += token;
|
|
6774
|
+
continue;
|
|
6775
|
+
}
|
|
6776
|
+
}
|
|
6777
|
+
const next = fn(value);
|
|
6778
|
+
out += next === value ? token : JSON.stringify(next);
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
function redactContainer(c, redact) {
|
|
6782
|
+
return {
|
|
6783
|
+
...c,
|
|
6784
|
+
files: c.files.map((f) => ({
|
|
6785
|
+
name: f.name,
|
|
6786
|
+
text: f.name.endsWith(".jsonl") ? f.text.split("\n").map((l) => l ? redactJsonLine(l, redact) : l).join("\n") : redact(f.text)
|
|
6787
|
+
}))
|
|
6788
|
+
};
|
|
6789
|
+
}
|
|
6790
|
+
function repairContainer(c) {
|
|
6791
|
+
let repaired = 0;
|
|
6792
|
+
const files = c.files.map((f) => {
|
|
6793
|
+
if (!f.name.endsWith(".jsonl"))
|
|
6794
|
+
return f;
|
|
6795
|
+
const r = repairRedactedJsonl(f.text);
|
|
6796
|
+
repaired += r.repaired;
|
|
6797
|
+
return r.repaired > 0 ? { name: f.name, text: r.text } : f;
|
|
6798
|
+
});
|
|
6799
|
+
return repaired > 0 ? { container: { ...c, files }, repaired } : { container: c, repaired: 0 };
|
|
6800
|
+
}
|
|
6662
6801
|
function subagentKind(id) {
|
|
6663
6802
|
return id.includes("acompact") ? "compact" : id.includes("aside_question") ? "aside" : id.includes("explore") || /^agent-a[0-9a-f]{16,}$/i.test(id) ? "explore" : "other";
|
|
6664
6803
|
}
|
|
@@ -6829,6 +6968,7 @@ function requireFs() {
|
|
|
6829
6968
|
function requirePath() {
|
|
6830
6969
|
return pathMod;
|
|
6831
6970
|
}
|
|
6971
|
+
var MARKER_QUOTE;
|
|
6832
6972
|
var init_raw = __esm({
|
|
6833
6973
|
"../engine/dist/transcript/raw.js"() {
|
|
6834
6974
|
"use strict";
|
|
@@ -6836,6 +6976,7 @@ var init_raw = __esm({
|
|
|
6836
6976
|
init_claude();
|
|
6837
6977
|
init_codex();
|
|
6838
6978
|
init_from_events();
|
|
6979
|
+
MARKER_QUOTE = /\[REDACTED:[A-Za-z0-9_-]+\]"/g;
|
|
6839
6980
|
}
|
|
6840
6981
|
});
|
|
6841
6982
|
|
|
@@ -6990,7 +7131,7 @@ var init_session_sentiment = __esm({
|
|
|
6990
7131
|
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;
|
|
6991
7132
|
CLARIFY_PHRASES = /\b(?:wdym|what do you mean|explain|clarify|what is|what's|huh\??|i don'?t understand)\b/i;
|
|
6992
7133
|
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 =
|
|
7134
|
+
MARKERS_VERSION = 3;
|
|
6994
7135
|
}
|
|
6995
7136
|
});
|
|
6996
7137
|
|
|
@@ -12662,7 +12803,13 @@ function redactSecrets(text, opts = {}) {
|
|
|
12662
12803
|
return whole;
|
|
12663
12804
|
if (opts.count)
|
|
12664
12805
|
opts.count.redactions++;
|
|
12665
|
-
|
|
12806
|
+
let last = args.length - 1;
|
|
12807
|
+
if (typeof args[last] === "object")
|
|
12808
|
+
last--;
|
|
12809
|
+
const source = args[last];
|
|
12810
|
+
const secretStart = args[last - 1] + whole.length - secret.length;
|
|
12811
|
+
const head = escapeHead(source, secretStart, secret.length);
|
|
12812
|
+
return whole.slice(0, whole.length - secret.length + head) + `[REDACTED:${r.label}]` + escapeKept(whole, whole.length);
|
|
12666
12813
|
});
|
|
12667
12814
|
}
|
|
12668
12815
|
const ctx = findContextualSecrets(out);
|
|
@@ -12670,10 +12817,25 @@ function redactSecrets(text, opts = {}) {
|
|
|
12670
12817
|
const { start, end } = ctx[i];
|
|
12671
12818
|
if (opts.count)
|
|
12672
12819
|
opts.count.redactions++;
|
|
12673
|
-
|
|
12820
|
+
const head = escapeHead(out, start, end - start);
|
|
12821
|
+
out = out.slice(0, start + head) + "[REDACTED:secret-context]" + escapeKept(out, end) + out.slice(end);
|
|
12674
12822
|
}
|
|
12675
12823
|
return out;
|
|
12676
12824
|
}
|
|
12825
|
+
function escapeKept(text, end) {
|
|
12826
|
+
let run = 0;
|
|
12827
|
+
while (run < end && text.charCodeAt(end - 1 - run) === 92)
|
|
12828
|
+
run++;
|
|
12829
|
+
return run % 2 === 1 ? "\\" : "";
|
|
12830
|
+
}
|
|
12831
|
+
function escapeHead(text, start, length) {
|
|
12832
|
+
let run = 0;
|
|
12833
|
+
while (run < start && text.charCodeAt(start - 1 - run) === 92)
|
|
12834
|
+
run++;
|
|
12835
|
+
if (run % 2 === 0)
|
|
12836
|
+
return 0;
|
|
12837
|
+
return Math.min(text[start] === "u" ? 5 : 1, length);
|
|
12838
|
+
}
|
|
12677
12839
|
function maskSecret(s) {
|
|
12678
12840
|
if (!s)
|
|
12679
12841
|
return "";
|
|
@@ -12828,7 +12990,12 @@ var init_secret_redactor = __esm({
|
|
|
12828
12990
|
// userinfo URL walked through in cleartext — and a `jdbc:postgresql://…`
|
|
12829
12991
|
// prefix broke the \b anchor for the one family it did cover. Any scheme
|
|
12830
12992
|
// followed by userinfo is a credential, so match the shape, not a list.
|
|
12831
|
-
|
|
12993
|
+
//
|
|
12994
|
+
// A quote in userinfo is percent-encoded, so neither part takes a `"`. The
|
|
12995
|
+
// sync redacts JSONL text, and a match that ran on through `","is_error":`
|
|
12996
|
+
// to a later `@` replaced JSON structure: 4 lines on one machine stopped
|
|
12997
|
+
// parsing, and their records were dropped.
|
|
12998
|
+
{ label: "url-password", secret: 1, pattern: /\b[a-zA-Z][a-zA-Z0-9+.-]{1,31}:\/\/[^:@\s/"]{1,64}:([^@\s/"]{1,256})(?=@)/g },
|
|
12832
12999
|
// Bare AWS secret-access-key VALUE: EXACTLY 40 base64 chars, word-bounded,
|
|
12833
13000
|
// containing upper+lower+digit. This is the gitleaks heuristic — the mixed-case
|
|
12834
13001
|
// requirement excludes 40-char lowercase-hex git SHAs, and the exact-40 bound
|
|
@@ -14150,6 +14317,10 @@ __export(transcript_exports, {
|
|
|
14150
14317
|
parseTranscript: () => parseTranscript,
|
|
14151
14318
|
parseTranscriptFromContainer: () => parseTranscriptFromContainer,
|
|
14152
14319
|
readShadowContainer: () => readShadowContainer,
|
|
14320
|
+
redactContainer: () => redactContainer,
|
|
14321
|
+
redactJsonLine: () => redactJsonLine,
|
|
14322
|
+
repairContainer: () => repairContainer,
|
|
14323
|
+
repairRedactedJsonl: () => repairRedactedJsonl,
|
|
14153
14324
|
seedShadow: () => seedShadow,
|
|
14154
14325
|
shadowFileFor: () => shadowFileFor,
|
|
14155
14326
|
shadowRoot: () => shadowRoot,
|
|
@@ -18765,7 +18936,7 @@ var init_http = __esm({
|
|
|
18765
18936
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18766
18937
|
} catch {
|
|
18767
18938
|
try {
|
|
18768
|
-
if (true) CLI_VERSION = "0.7.
|
|
18939
|
+
if (true) CLI_VERSION = "0.7.12";
|
|
18769
18940
|
} catch {
|
|
18770
18941
|
}
|
|
18771
18942
|
}
|
|
@@ -19263,7 +19434,7 @@ var init_telemetry = __esm({
|
|
|
19263
19434
|
init_sync_client();
|
|
19264
19435
|
cliVersion2 = () => {
|
|
19265
19436
|
try {
|
|
19266
|
-
return true ? "0.7.
|
|
19437
|
+
return true ? "0.7.12" : "dev";
|
|
19267
19438
|
} catch {
|
|
19268
19439
|
return "dev";
|
|
19269
19440
|
}
|
|
@@ -21444,7 +21615,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21444
21615
|
} else {
|
|
21445
21616
|
try {
|
|
21446
21617
|
const count2 = { redactions: 0 };
|
|
21447
|
-
const redacted =
|
|
21618
|
+
const redacted = redactContainer(container, (t) => redactSecrets(t, { force: true, count: count2 }));
|
|
21448
21619
|
count.redactions += count2.redactions;
|
|
21449
21620
|
const { gz, size } = gzipContainer(redacted);
|
|
21450
21621
|
if (gz.length <= 8 * 1024 * 1024) {
|
|
@@ -21644,7 +21815,7 @@ var init_sync_client = __esm({
|
|
|
21644
21815
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21645
21816
|
} catch {
|
|
21646
21817
|
try {
|
|
21647
|
-
if (true) ownVersion = "0.7.
|
|
21818
|
+
if (true) ownVersion = "0.7.12";
|
|
21648
21819
|
} catch {
|
|
21649
21820
|
}
|
|
21650
21821
|
}
|
|
@@ -25806,7 +25977,7 @@ var init_intent_drain = __esm({
|
|
|
25806
25977
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25807
25978
|
} catch {
|
|
25808
25979
|
try {
|
|
25809
|
-
if (true) ownVersion2 = "0.7.
|
|
25980
|
+
if (true) ownVersion2 = "0.7.12";
|
|
25810
25981
|
} catch {
|
|
25811
25982
|
}
|
|
25812
25983
|
}
|
|
@@ -29368,7 +29539,7 @@ program.command("verify").description("Check that the server holds everything th
|
|
|
29368
29539
|
}
|
|
29369
29540
|
const { verifyAgainstServer: verifyAgainstServer2, verifyTargets: verifyTargets2 } = await Promise.resolve().then(() => (init_verify_deep(), verify_deep_exports));
|
|
29370
29541
|
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_tool_backend(), tool_backend_exports));
|
|
29371
|
-
const { gzipContainer: gzipContainer2,
|
|
29542
|
+
const { gzipContainer: gzipContainer2, redactContainer: redactContainer2 } = await Promise.resolve().then(() => (init_transcript(), transcript_exports));
|
|
29372
29543
|
const { redactSecrets: redactSecrets2 } = await Promise.resolve().then(() => (init_secret_redactor(), secret_redactor_exports));
|
|
29373
29544
|
const { fetchWithTimeout: fetchWithTimeout2 } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
29374
29545
|
const { forceFullResync: forceFullResync2 } = await Promise.resolve().then(() => (init_verify_repair(), verify_repair_exports));
|
|
@@ -29417,7 +29588,7 @@ program.command("verify").description("Check that the server holds everything th
|
|
|
29417
29588
|
mtime: exp.mtime,
|
|
29418
29589
|
files: exp.files.map((f) => ({ name: f.name, text: f.bytes.toString("utf-8") }))
|
|
29419
29590
|
};
|
|
29420
|
-
const redacted =
|
|
29591
|
+
const redacted = redactContainer2(container, (t) => redactSecrets2(t, { force: true }));
|
|
29421
29592
|
return gzipContainer2(redacted).size;
|
|
29422
29593
|
} catch {
|
|
29423
29594
|
return null;
|