chat-recall 0.5.27 → 0.5.29

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.
@@ -0,0 +1,52 @@
1
+ export interface WalkSnapshot {
2
+ done: number;
3
+ total: number;
4
+ complete: boolean;
5
+ }
6
+ /** A fixed-width bar. Pure, so the rendering is pinned by tests. */
7
+ export declare function renderBar(done: number, total: number, width?: number): string;
8
+ /** `1,240/15,748` — grouped, because five- and six-digit counts are unreadable raw. */
9
+ export declare function renderCount(done: number, total: number): string;
10
+ /**
11
+ * The one line shown while a walk is in flight, or the one line shown when it
12
+ * is handed off / finished. Kept pure and separate from the polling so the exact
13
+ * wording is testable — the whole point of this change is the wording.
14
+ */
15
+ export declare function progressLine(snap: WalkSnapshot | null): string;
16
+ export declare function handOffLine(snap: WalkSnapshot | null): string;
17
+ export interface FirstSyncDeps {
18
+ /** Current walk state, or null when none has been reported yet. */
19
+ readProgress: () => WalkSnapshot | null;
20
+ /** Draw the single line, in place. */
21
+ draw: (text: string) => void;
22
+ /** Start the detached worker. Returns a stop handle for tests. */
23
+ startWorker: () => void;
24
+ now: () => number;
25
+ sleep: (ms: number) => Promise<void>;
26
+ /** How long to watch before handing off. */
27
+ handOffAfterMs?: number;
28
+ pollMs?: number;
29
+ }
30
+ export interface FirstSyncOutcome {
31
+ /** True when the walk reported `complete` before the hand-off deadline. */
32
+ finished: boolean;
33
+ snapshot: WalkSnapshot | null;
34
+ }
35
+ /**
36
+ * Start the sync, watch it on ONE line, and stop watching at the deadline.
37
+ *
38
+ * Never kills the worker — handing off means letting it run, not cancelling it.
39
+ * The caller prints the final line, because only it knows the surrounding
40
+ * layout.
41
+ */
42
+ export declare function watchFirstSync(deps: FirstSyncDeps): Promise<FirstSyncOutcome>;
43
+ /**
44
+ * Spawn `<this cli> sync` fully detached, stdio discarded.
45
+ *
46
+ * `stdio: 'ignore'` is the half that silences the daemon log; `detached` +
47
+ * `unref` is the half that lets a long walk outlive `init`. `argv[1]` rather
48
+ * than a resolved package path, so a dev checkout, a global install and a
49
+ * user-prefix install all re-invoke the binary that is actually running.
50
+ */
51
+ export declare function spawnDetachedSync(extraArgs?: string[]): void;
52
+ //# sourceMappingURL=init-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-progress.d.ts","sourceRoot":"","sources":["../src/init-progress.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAKzE;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAI9D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAK7D;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,YAAY,EAAE,MAAM,YAAY,GAAG,IAAI,CAAC;IACxC,sCAAsC;IACtC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,kEAAkE;IAClE,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAcnF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,MAAM,EAAO,GAAG,IAAI,CAShE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * ONE LINE for the first sync, and a hand-off when it is long.
3
+ *
4
+ * ── What this replaces ────────────────────────────────────────────────────
5
+ * `init` step 5 was `await syncSessions()`. Two problems, both reported by a
6
+ * user on a 15,748-session machine:
7
+ *
8
+ * 1. It BLOCKED for minutes, while step 6 went on to explain that background
9
+ * sync runs via the MCP anyway — so the wait bought nothing but a wait.
10
+ * 2. It printed the daemon's log to the terminal. `sync-client.ts` has 18
11
+ * `[sync] …` console.error calls written for a log file nobody tails, and
12
+ * onboarding inherited every one of them, including
13
+ * "01758d3f… is 115MB (over the 64MB ceiling)" — true, and none of a new
14
+ * user's business.
15
+ *
16
+ * Running the sync as a DETACHED CHILD fixes both at once: its stdio is
17
+ * discarded, so the log cannot reach the terminal by construction, and it
18
+ * survives `init` exiting, so a long walk continues without holding anyone up.
19
+ *
20
+ * Progress needs no new plumbing. `sync-client.ts` already calls
21
+ * `reportWalkProgress()` into the collector-health file on every walk; this
22
+ * polls that file. So the bar reflects the real walk, not an estimate.
23
+ */
24
+ import { spawn } from 'node:child_process';
25
+ /** A fixed-width bar. Pure, so the rendering is pinned by tests. */
26
+ export function renderBar(done, total, width = 12) {
27
+ if (total <= 0)
28
+ return '░'.repeat(width);
29
+ const ratio = Math.max(0, Math.min(1, done / total));
30
+ const filled = Math.round(ratio * width);
31
+ return '█'.repeat(filled) + '░'.repeat(width - filled);
32
+ }
33
+ /** `1,240/15,748` — grouped, because five- and six-digit counts are unreadable raw. */
34
+ export function renderCount(done, total) {
35
+ const n = (x) => x.toLocaleString('en-US');
36
+ return `${n(done)}/${n(total)}`;
37
+ }
38
+ /**
39
+ * The one line shown while a walk is in flight, or the one line shown when it
40
+ * is handed off / finished. Kept pure and separate from the polling so the exact
41
+ * wording is testable — the whole point of this change is the wording.
42
+ */
43
+ export function progressLine(snap) {
44
+ if (!snap || snap.total <= 0)
45
+ return 'starting…';
46
+ if (snap.complete)
47
+ return `${renderCount(snap.done, snap.total)} indexed`;
48
+ return `${renderBar(snap.done, snap.total)} ${renderCount(snap.done, snap.total)}`;
49
+ }
50
+ export function handOffLine(snap) {
51
+ const where = snap && snap.total > 0
52
+ ? `${renderCount(snap.done, snap.total)} so far`
53
+ : 'started';
54
+ return `${where} — continuing in the background`;
55
+ }
56
+ /**
57
+ * Start the sync, watch it on ONE line, and stop watching at the deadline.
58
+ *
59
+ * Never kills the worker — handing off means letting it run, not cancelling it.
60
+ * The caller prints the final line, because only it knows the surrounding
61
+ * layout.
62
+ */
63
+ export async function watchFirstSync(deps) {
64
+ const handOffAfterMs = deps.handOffAfterMs ?? 20_000;
65
+ const pollMs = deps.pollMs ?? 400;
66
+ const started = deps.now();
67
+ deps.startWorker();
68
+ let snap = null;
69
+ for (;;) {
70
+ snap = deps.readProgress();
71
+ if (snap?.complete)
72
+ return { finished: true, snapshot: snap };
73
+ if (deps.now() - started >= handOffAfterMs)
74
+ return { finished: false, snapshot: snap };
75
+ deps.draw(progressLine(snap));
76
+ await deps.sleep(pollMs);
77
+ }
78
+ }
79
+ /**
80
+ * Spawn `<this cli> sync` fully detached, stdio discarded.
81
+ *
82
+ * `stdio: 'ignore'` is the half that silences the daemon log; `detached` +
83
+ * `unref` is the half that lets a long walk outlive `init`. `argv[1]` rather
84
+ * than a resolved package path, so a dev checkout, a global install and a
85
+ * user-prefix install all re-invoke the binary that is actually running.
86
+ */
87
+ export function spawnDetachedSync(extraArgs = []) {
88
+ const entry = process.argv[1];
89
+ if (!entry)
90
+ return;
91
+ const child = spawn(process.execPath, [entry, 'sync', ...extraArgs], {
92
+ detached: true,
93
+ stdio: 'ignore',
94
+ windowsHide: true,
95
+ });
96
+ child.unref();
97
+ }
98
+ //# sourceMappingURL=init-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-progress.js","sourceRoot":"","sources":["../src/init-progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `init` says two things: installing, then done.
3
+ *
4
+ * ── What it used to say ───────────────────────────────────────────────────
5
+ * Forty lines. A numbered heading per step, then a line per ITEM inside each
6
+ * step — one per AI tool found AND per tool not found, one per MCP client
7
+ * configured, one per skills directory, a four-line advert for an optional
8
+ * companion, a sixty-name list of MCP tools, and the sync daemon's own log,
9
+ * including "01758d3f… is 115MB (over the 64MB ceiling)".
10
+ *
11
+ * ── What it says now ──────────────────────────────────────────────────────
12
+ * chat-recall init v0.5.27
13
+ * Installing…
14
+ * ✓ Done
15
+ *
16
+ * That is the whole contract. No step numbers, no counts, no per-item audit.
17
+ *
18
+ * The ONE exception is a thing the user must act on — a config file that would
19
+ * not parse, an env var to set, a server that cannot be reached. Those print on
20
+ * their own line, always. A quiet install that hides a failure is not quiet, it
21
+ * is broken; every bug found on 2026-08-27 was one the output failed to name.
22
+ */
23
+ export interface InitReporter {
24
+ /** Show the single "Installing…" line. Idempotent — call it freely. */
25
+ start: () => void;
26
+ /** Something the user must act on. ALWAYS printed, on its own line. */
27
+ warn: (text: string) => void;
28
+ /** Clear the status line and print the closing line. */
29
+ done: (text: string) => void;
30
+ }
31
+ export interface ReporterOpts {
32
+ /** A TTY gets an in-place line it can overwrite; a pipe gets a plain one. */
33
+ tty: boolean;
34
+ write: (s: string) => void;
35
+ line: (s: string) => void;
36
+ }
37
+ export declare function createInitReporter(opts: ReporterOpts): InitReporter;
38
+ //# sourceMappingURL=init-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-report.d.ts","sourceRoot":"","sources":["../src/init-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,uEAAuE;IACvE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,wDAAwD;IACxD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3B;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAwBnE"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `init` says two things: installing, then done.
3
+ *
4
+ * ── What it used to say ───────────────────────────────────────────────────
5
+ * Forty lines. A numbered heading per step, then a line per ITEM inside each
6
+ * step — one per AI tool found AND per tool not found, one per MCP client
7
+ * configured, one per skills directory, a four-line advert for an optional
8
+ * companion, a sixty-name list of MCP tools, and the sync daemon's own log,
9
+ * including "01758d3f… is 115MB (over the 64MB ceiling)".
10
+ *
11
+ * ── What it says now ──────────────────────────────────────────────────────
12
+ * chat-recall init v0.5.27
13
+ * Installing…
14
+ * ✓ Done
15
+ *
16
+ * That is the whole contract. No step numbers, no counts, no per-item audit.
17
+ *
18
+ * The ONE exception is a thing the user must act on — a config file that would
19
+ * not parse, an env var to set, a server that cannot be reached. Those print on
20
+ * their own line, always. A quiet install that hides a failure is not quiet, it
21
+ * is broken; every bug found on 2026-08-27 was one the output failed to name.
22
+ */
23
+ const INSTALLING = 'Installing…';
24
+ export function createInitReporter(opts) {
25
+ let painted = false;
26
+ const clear = () => {
27
+ if (painted && opts.tty)
28
+ opts.write(`\r${' '.repeat(INSTALLING.length)}\r`);
29
+ painted = false;
30
+ };
31
+ return {
32
+ start() {
33
+ if (painted)
34
+ return;
35
+ if (opts.tty) {
36
+ opts.write(INSTALLING);
37
+ painted = true;
38
+ }
39
+ else
40
+ opts.line(INSTALLING);
41
+ },
42
+ warn(text) {
43
+ // Clear first, or the warning lands on top of the status line.
44
+ clear();
45
+ opts.line(text);
46
+ },
47
+ done(text) {
48
+ clear();
49
+ opts.line(text);
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=init-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-report.js","sourceRoot":"","sources":["../src/init-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAkBH,MAAM,UAAU,GAAG,aAAa,CAAC;AAEjC,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5E,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;YACH,IAAI,OAAO;gBAAE,OAAO;YACpB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAAC,OAAO,GAAG,IAAI,CAAC;YAAC,CAAC;;gBACpD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,IAAI;YACP,+DAA+D;YAC/D,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,IAAI;YACP,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}