chat-recall 0.5.4 → 0.5.6
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 +1506 -733
- package/dist/cli.js.map +1 -1
- package/dist/mcp-diagnostics.d.ts +45 -0
- package/dist/mcp-diagnostics.d.ts.map +1 -0
- package/dist/mcp-diagnostics.js +98 -0
- package/dist/mcp-diagnostics.js.map +1 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +2096 -1151
- package/dist/mcp.js.map +1 -1
- package/dist/project-tasks.d.ts.map +1 -1
- package/dist/project-tasks.js +12 -7
- package/dist/project-tasks.js.map +1 -1
- package/dist/service-installer.d.ts +1 -1
- package/dist/service-installer.d.ts.map +1 -1
- package/dist/service-installer.js +20 -6
- package/dist/service-installer.js.map +1 -1
- package/dist/sync-client.d.ts +1 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +179 -92
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +22 -0
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +108 -1
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +1104 -481
- package/hooks/chat_recall_escalate_hook.sh +28 -2
- package/hooks/chat_recall_save_hook.sh +17 -11
- package/hooks/chat_recall_wakeup_hook.sh +27 -1
- package/package.json +7 -3
- package/skills/chat-recall/SKILL.md +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tasks.d.ts","sourceRoot":"","sources":["../src/project-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAClD,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CAAE;AAItF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAwC;
|
|
1
|
+
{"version":3,"file":"project-tasks.d.ts","sourceRoot":"","sources":["../src/project-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAClD,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CAAE;AAItF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAwC;AAoCxG,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAa7D;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAUzD;AAmBD,MAAM,WAAW,UAAU;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;CAAE;AAEnE;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,UAAU,CAAC,CA8CrB;AASD,MAAM,WAAW,YAAY;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAAE;AAE7H,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAe/D;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAE9D"}
|
package/dist/project-tasks.js
CHANGED
|
@@ -23,7 +23,7 @@ import { fetchWithTimeout } from './http.js';
|
|
|
23
23
|
import { isSecretTaskStatus } from '@chat-recall/engine/core/secret-task-status.js';
|
|
24
24
|
import { isCodeTaskStatus } from '@chat-recall/engine/core/code-task-status.js';
|
|
25
25
|
/** Collaborative-task statuses (mirrors the team_tasks CHECK constraint). */
|
|
26
|
-
const TEAM_STATUSES = new Set(['todo', 'in_progress', '
|
|
26
|
+
const TEAM_STATUSES = new Set(['todo', 'in_progress', 'done', 'rejected']);
|
|
27
27
|
export function isTeamTaskStatus(v) { return !!v && TEAM_STATUSES.has(v); }
|
|
28
28
|
// Matches both `cr-secret id=…` (kind implied secret) and `cr-task kind=… id=…`.
|
|
29
29
|
// Status tokens can contain underscores (`in_progress`, `false_positive`), so
|
|
@@ -42,11 +42,15 @@ function reconcile(kind, was, token, checked) {
|
|
|
42
42
|
if (token && token !== was)
|
|
43
43
|
return token; // explicit status edit wins (all kinds)
|
|
44
44
|
if (kind === 'team') {
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
// A TICK CANNOT MEAN DONE ANY MORE. Done is earned by the work: the route
|
|
46
|
+
// refuses it without a linked session, so a tick here would send a 409 the
|
|
47
|
+
// user cannot act on from a markdown file. The honest mapping is to claim
|
|
48
|
+
// the card — that is what a person ticking a box in their repo means, and
|
|
49
|
+
// the agent that finishes it closes it with its session attached.
|
|
50
|
+
//
|
|
51
|
+
// An untick still resets a done card, because undoing a claim is safe.
|
|
52
|
+
if (checked && was === 'todo')
|
|
53
|
+
return 'in_progress';
|
|
50
54
|
if (!checked && was === 'done')
|
|
51
55
|
return 'todo';
|
|
52
56
|
return token ?? was;
|
|
@@ -186,7 +190,8 @@ export function renderTeamTasksMd(tasks) {
|
|
|
186
190
|
'# Team tasks',
|
|
187
191
|
'',
|
|
188
192
|
'<!-- Managed by chat-recall. Tick a box or edit the `status:` token, then run',
|
|
189
|
-
' `chat-recall tasks push`. Statuses: todo · in_progress ·
|
|
193
|
+
' `chat-recall tasks push`. Statuses: todo · in_progress · done · rejected.',
|
|
194
|
+
' A tick claims a task; only the session that does the work can close it. -->',
|
|
190
195
|
'',
|
|
191
196
|
];
|
|
192
197
|
if (tasks.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tasks.js","sourceRoot":"","sources":["../src/project-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAKhF,6EAA6E;AAC7E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"project-tasks.js","sourceRoot":"","sources":["../src/project-tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ export declare function renderSystemdUnit(watchJs: string, node: string, logFile
|
|
|
17
17
|
/** Render the launchd plist body (pure — no FS, no exec). */
|
|
18
18
|
export declare function renderLaunchdPlist(watchJs: string, node: string, logFile: string, label?: string): string;
|
|
19
19
|
/** Render the schtasks /create command (pure — no exec). */
|
|
20
|
-
export declare function renderWindowsTaskCommand(watchJs: string, node: string, taskName?: string): string;
|
|
20
|
+
export declare function renderWindowsTaskCommand(watchJs: string, node: string, taskName?: string, logFile?: string): string;
|
|
21
21
|
/**
|
|
22
22
|
* Stop + remove the per-user background service. Idempotent — no error if
|
|
23
23
|
* the service isn't installed. Returns true if something was removed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-installer.d.ts","sourceRoot":"","sources":["../src/service-installer.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;CACjB;AAiBD,0EAA0E;AAC1E,wBAAgB,gBAAgB,IAAI,OAAO,CAe1C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,YAAY,CAiB7C;AAsBD,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"service-installer.d.ts","sourceRoot":"","sources":["../src/service-installer.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;CACjB;AAiBD,0EAA0E;AAC1E,wBAAgB,gBAAgB,IAAI,OAAO,CAe1C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,YAAY,CAiB7C;AAsBD,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAoBxF;AAmBD,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAA0B,GAAG,MAAM,CAa1H;AAuBD,4DAA4D;AAC5D,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAsB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhI;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAoB1C;AAED,kDAAkD;AAClD,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAI3C"}
|
|
@@ -102,9 +102,13 @@ export function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
102
102
|
// largest transcripts.
|
|
103
103
|
`ExecStart=${node} --max-old-space-size=1536 ${watchJs}`,
|
|
104
104
|
'Restart=on-failure', 'RestartSec=10', 'Nice=10',
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
105
|
+
// JOURNAL, not append:. The file version had no rotation and nothing to
|
|
106
|
+
// give it any: systemd holds the fd open, so the daemon cannot rename or
|
|
107
|
+
// truncate its own log without leaving systemd writing into a hole. It
|
|
108
|
+
// reached 45 MB on this developer's machine and would have grown forever.
|
|
109
|
+
// journald already rotates and applies disk limits. Read it with
|
|
110
|
+
// journalctl --user -u chat-recall-watch -f
|
|
111
|
+
'StandardOutput=journal', 'StandardError=journal', '',
|
|
108
112
|
'[Install]', 'WantedBy=default.target', '',
|
|
109
113
|
].join('\n');
|
|
110
114
|
}
|
|
@@ -145,7 +149,15 @@ export function renderLaunchdPlist(watchJs, node, logFile, label = 'com.chat-rec
|
|
|
145
149
|
}
|
|
146
150
|
function installWindowsTask(watchJs, node, logFile) {
|
|
147
151
|
const taskName = 'chat-recall-watch';
|
|
148
|
-
|
|
152
|
+
// REDIRECT THE LOG. systemd gets StandardOutput=append: and launchd gets
|
|
153
|
+
// StandardOutPath, but the Scheduled Task had no redirection at all — so
|
|
154
|
+
// every diagnostic the daemon printed was discarded, while the CLI went on
|
|
155
|
+
// telling the user to read ~/.chat-recall/watch.log, a file that was never
|
|
156
|
+
// created. A crash-looping collector with no log is undiagnosable.
|
|
157
|
+
//
|
|
158
|
+
// schtasks /tr cannot express redirection itself, so wrap in cmd /c. The
|
|
159
|
+
// whole thing is one /tr argument, hence the escaped quotes.
|
|
160
|
+
const tr = `cmd /c \\"\\"${node}\\" --max-old-space-size=1536 \\"${watchJs}\\" >> \\"${logFile}\\" 2>&1\\"`;
|
|
149
161
|
try {
|
|
150
162
|
execSync(`schtasks /create /tn "${taskName}" /tr "${tr}" /sc onlogon /rl LIMITED /f`, { stdio: 'inherit' });
|
|
151
163
|
// Start now too (best-effort — starts next logon if /run unsupported).
|
|
@@ -160,8 +172,10 @@ function installWindowsTask(watchJs, node, logFile) {
|
|
|
160
172
|
return { definitionPath: null, logFile };
|
|
161
173
|
}
|
|
162
174
|
/** Render the schtasks /create command (pure — no exec). */
|
|
163
|
-
export function renderWindowsTaskCommand(watchJs, node, taskName = 'chat-recall-watch') {
|
|
164
|
-
const tr =
|
|
175
|
+
export function renderWindowsTaskCommand(watchJs, node, taskName = 'chat-recall-watch', logFile) {
|
|
176
|
+
const tr = logFile
|
|
177
|
+
? `cmd /c \\"\\"${node}\\" --max-old-space-size=1536 \\"${watchJs}\\" >> \\"${logFile}\\" 2>&1\\"`
|
|
178
|
+
: `\\"${node}\\" --max-old-space-size=1536 \\"${watchJs}\\"`;
|
|
165
179
|
return `schtasks /create /tn "${taskName}" /tr "${tr}" /sc onlogon /rl LIMITED /f`;
|
|
166
180
|
}
|
|
167
181
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-installer.js","sourceRoot":"","sources":["../src/service-installer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service-installer.js","sourceRoot":"","sources":["../src/service-installer.ts"],"names":[],"mappings":"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"}
|
package/dist/sync-client.d.ts
CHANGED
|
@@ -108,6 +108,7 @@ export declare function batchScanExternal(items: Array<{
|
|
|
108
108
|
slices: number;
|
|
109
109
|
scanMs: number;
|
|
110
110
|
};
|
|
111
|
+
export declare function _resetCapsCacheForTests(): void;
|
|
111
112
|
/**
|
|
112
113
|
* Build the live per-session conversation payload — the THIN-COLLECTOR core.
|
|
113
114
|
* Reads ONLY the raw transcript (via `parseTranscript` + `parseSessionFile`),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../src/sync-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../src/sync-client.ts"],"names":[],"mappings":"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"}
|
package/dist/sync-client.js
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
* server owns them.
|
|
32
32
|
*/
|
|
33
33
|
import { join, dirname, basename } from 'node:path';
|
|
34
|
+
import { envCredentials } from '@chat-recall/engine/core/credentials-env.js';
|
|
34
35
|
import { readFileSync, writeFileSync, mkdirSync, mkdtempSync, rmSync, chmodSync, unlinkSync, readdirSync, statSync } from 'node:fs';
|
|
35
36
|
import { tmpdir, hostname } from 'node:os';
|
|
36
37
|
import { createHash } from 'node:crypto';
|
|
@@ -70,11 +71,12 @@ import { parseSessionFile, readCwdFromJsonl } from '@chat-recall/engine/parsers/
|
|
|
70
71
|
import { resolveProjectId } from '@chat-recall/engine/core/project-resolver.js';
|
|
71
72
|
import { extractEntities } from '@chat-recall/engine/core/entity-extractor.js';
|
|
72
73
|
import { buildSourceRegistry } from '@chat-recall/engine/parsers/all-sources.js';
|
|
73
|
-
import { getSyncedRows, markSynced, getLedgerData, persistLedgerData, fieldNeedsScan, markFieldCoverage, fieldNeedsFullPass, markFieldFullPassDone, syncMode, markFullResync, loadItemVersions, saveItemVersions } from './sync-ledger.js';
|
|
74
|
+
import { getSyncedRows, markSynced, getLedgerData, persistLedgerData, fieldNeedsScan, markFieldCoverage, fieldNeedsFullPass, markFieldFullPassDone, syncMode, markFullResync, loadItemVersions, saveItemVersions, flushLedger, pruneLedgerTargets } from './sync-ledger.js';
|
|
74
75
|
import { extractorVersionForTool, extractorVersionForId, toolOfId, EXTRACTOR_VERSION } from '@chat-recall/engine/core/extractor-version.js';
|
|
75
76
|
import { SYNC_FIELDS } from '@chat-recall/engine/core/sync-fields.js';
|
|
76
77
|
import { acquireIndexLock } from '@chat-recall/engine/core/index-lock.js';
|
|
77
78
|
import { fetchWithTimeout } from './http.js';
|
|
79
|
+
import { withSessionReadCache } from '@chat-recall/engine/core/live-session-scan.js';
|
|
78
80
|
import '@chat-recall/engine/core/backends/index.js'; // register the tool backends
|
|
79
81
|
// Lives under the data dir so CHAT_RECALL_DATA_DIR isolates credentials the
|
|
80
82
|
// same way it isolates the index (tests, multi-profile setups).
|
|
@@ -107,6 +109,12 @@ export function saveCredentials(c) {
|
|
|
107
109
|
catch { /* settings unwritable — manual `chat-recall sync` still works */ }
|
|
108
110
|
}
|
|
109
111
|
export function loadAllCredentials() {
|
|
112
|
+
// A container, a CI job or a headless daemon has no credentials.json. When
|
|
113
|
+
// the environment carries an explicit token it IS the login — see
|
|
114
|
+
// credentials-env.ts for why the file is not consulted in that case.
|
|
115
|
+
const fromEnv = envCredentials();
|
|
116
|
+
if (fromEnv)
|
|
117
|
+
return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
110
118
|
try {
|
|
111
119
|
const parsed = JSON.parse(readFileSync(credPath(), 'utf-8'));
|
|
112
120
|
// token may be '' for a no-auth local self-host server (AUTH_PROVIDER=none) —
|
|
@@ -340,6 +348,12 @@ export async function syncSessions(opts = {}) {
|
|
|
340
348
|
const targets = loadAllCredentials();
|
|
341
349
|
if (targets.length === 0)
|
|
342
350
|
throw new Error('Not logged in — run `chat-recall login <server-url> --token <token>`');
|
|
351
|
+
// Once per walk: forget servers we no longer sync to, so their rows stop
|
|
352
|
+
// riding along in every write of this single-file ledger.
|
|
353
|
+
try {
|
|
354
|
+
pruneLedgerTargets(targets.map((t) => t.serverUrl));
|
|
355
|
+
}
|
|
356
|
+
catch { /* never block a sync on housekeeping */ }
|
|
343
357
|
let agg = null;
|
|
344
358
|
const errors = [];
|
|
345
359
|
for (const cred of targets) {
|
|
@@ -356,6 +370,11 @@ export async function syncSessions(opts = {}) {
|
|
|
356
370
|
errors.push(`${cred.serverUrl}: ${e instanceof Error ? e.message : e}`);
|
|
357
371
|
}
|
|
358
372
|
}
|
|
373
|
+
// Ledger writes are coalesced during the walk (see persist() in sync-ledger).
|
|
374
|
+
// This is the durability point: everything acked above reaches disk before we
|
|
375
|
+
// report success, so a crash after this cannot re-ship what the server has.
|
|
376
|
+
// In the finally, because a partial walk's acks are still worth keeping.
|
|
377
|
+
flushLedger();
|
|
359
378
|
if (!agg)
|
|
360
379
|
throw new Error(`sync failed for all targets:\n ${errors.join('\n ')}`);
|
|
361
380
|
if (errors.length > 0)
|
|
@@ -582,6 +601,28 @@ export function batchScanExternal(items, opts = {}) {
|
|
|
582
601
|
}
|
|
583
602
|
return { findings, scanned, slices, scanMs };
|
|
584
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Server API version check, cached per target for an hour.
|
|
606
|
+
*
|
|
607
|
+
* Only SUCCESS is cached. A server that is down, or too old, is re-checked on
|
|
608
|
+
* the next tick — caching a failure would turn a thirty-second outage into an
|
|
609
|
+
* hour of refusing to sync.
|
|
610
|
+
*/
|
|
611
|
+
const CAPS_TTL_MS = 60 * 60_000;
|
|
612
|
+
const capsOk = new Map(); // serverUrl -> epoch ms verified
|
|
613
|
+
export function _resetCapsCacheForTests() { capsOk.clear(); }
|
|
614
|
+
async function verifyServerApi(serverUrl, minApi) {
|
|
615
|
+
const base = serverUrl.replace(/\/$/, '');
|
|
616
|
+
const seen = capsOk.get(base);
|
|
617
|
+
if (seen !== undefined && Date.now() - seen < CAPS_TTL_MS)
|
|
618
|
+
return true;
|
|
619
|
+
const caps = await fetchWithTimeout(`${base}/api/capabilities`).then((r) => r.json());
|
|
620
|
+
if ((caps.apiVersion ?? 0) < minApi) {
|
|
621
|
+
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? 'none'} < required ${minApi} — update the server image before syncing`);
|
|
622
|
+
}
|
|
623
|
+
capsOk.set(base, Date.now());
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
585
626
|
async function syncToTarget(cred, opts = {}) {
|
|
586
627
|
const sync = loadSettings().sync;
|
|
587
628
|
// Exclusions = local settings ∪ server-side tenant config (dashboard-edited).
|
|
@@ -618,16 +659,18 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
618
659
|
// server ignores payload fields it doesn't know — which looks like
|
|
619
660
|
// success and produces gutted data (lived experience, June 2026).
|
|
620
661
|
const MIN_SERVER_API = 2;
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
662
|
+
{
|
|
663
|
+
// Cached for an hour per target. This ran on EVERY sync — every file-change
|
|
664
|
+
// debounce, every heartbeat, per target — to re-learn a number that changes
|
|
665
|
+
// only when the server is redeployed. The check itself stays: refusing to
|
|
666
|
+
// sync blind is the point, and an old server silently ignoring payload fields
|
|
667
|
+
// is how gutted data shipped in June 2026. Only the frequency changes.
|
|
668
|
+
//
|
|
669
|
+
// A FAILURE IS NEVER CACHED. An unreachable server must be retried on the
|
|
670
|
+
// next tick, not written off for an hour.
|
|
671
|
+
const ok = await verifyServerApi(cred.serverUrl, MIN_SERVER_API);
|
|
672
|
+
if (!ok)
|
|
673
|
+
throw new Error(`cannot verify server version — refusing to sync blind`);
|
|
631
674
|
}
|
|
632
675
|
// Fetch tenant-specific secret-scan configuration from the server. Rules are
|
|
633
676
|
// configured in the dashboard and must be applied to raw session text on the
|
|
@@ -723,6 +766,28 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
723
766
|
if (res.status === 401 || res.status === 403) {
|
|
724
767
|
throw new Error(`server rejected this machine's device token (HTTP ${res.status} — revoked?). Reconnect with: chat-recall login ${base}`);
|
|
725
768
|
}
|
|
769
|
+
// 402 is a standing plan condition, not a glitch: a meter (monthly
|
|
770
|
+
// quota / storage cap) or a missing email confirmation. The server's
|
|
771
|
+
// payload carries the one actionable sentence — print IT, not the raw
|
|
772
|
+
// HTTP line, and never retry: the answer is the same until the meter
|
|
773
|
+
// resets or the human acts.
|
|
774
|
+
if (res.status === 402) {
|
|
775
|
+
let detail = text;
|
|
776
|
+
try {
|
|
777
|
+
const body = JSON.parse(text);
|
|
778
|
+
detail = body.error ?? text;
|
|
779
|
+
// `detail` carries the part that stops this reading as breakage —
|
|
780
|
+
// what still works, and the one command that restores the rest.
|
|
781
|
+
if (body.detail)
|
|
782
|
+
detail += `\n ${body.detail}`;
|
|
783
|
+
if (body.resetsAt)
|
|
784
|
+
detail += ` (resets ${new Date(body.resetsAt).toISOString().slice(0, 10)})`;
|
|
785
|
+
if (body.upgradeUrl)
|
|
786
|
+
detail += `\n ${body.upgradeUrl}`;
|
|
787
|
+
}
|
|
788
|
+
catch { /* non-JSON 402 — print as-is */ }
|
|
789
|
+
throw new Error(`sync paused by the server: ${detail}`);
|
|
790
|
+
}
|
|
726
791
|
if (!retryable)
|
|
727
792
|
throw new Error(`sync failed: HTTP ${res.status} ${text}`);
|
|
728
793
|
if (attempt >= RETRY_DELAYS_MS.length)
|
|
@@ -936,29 +1001,50 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
936
1001
|
// and redaction of everything shipped is unconditional.
|
|
937
1002
|
const scanSecrets = isSecretScannerAvailable() && upload.findings && process.env.CHAT_RECALL_SCAN_SECRETS !== '0';
|
|
938
1003
|
const verifySecretsScan = verifySecrets;
|
|
939
|
-
|
|
940
|
-
//
|
|
1004
|
+
let skipped = 0, redactions = 0, walked = 0;
|
|
1005
|
+
// ── Live KG accumulator. Triples are extracted on the spot from each item's
|
|
1006
|
+
// redacted text (no local knowledge-graph DB is read). Dedupe by
|
|
941
1007
|
// subject|predicate|object|valid_from; entity types come from `is_a`
|
|
942
1008
|
// triples seen in the same pass, defaulting to 'unknown' otherwise.
|
|
1009
|
+
//
|
|
1010
|
+
// TRIPLES SHIP IMMEDIATELY. They used to pile into an array that was drained
|
|
1011
|
+
// only after the ENTIRE walk — on this developer's box that is 15,700
|
|
1012
|
+
// sessions, so the array grew for the whole run and every row stayed live and
|
|
1013
|
+
// reachable. A full Mark-Compact freed 0 MB at 1602 MB before the daemon
|
|
1014
|
+
// aborted, which is the signature of retention, not of transient copies:
|
|
1015
|
+
// nothing transient survives a mark-compact. Handing each triple to the
|
|
1016
|
+
// batcher as it is produced bounds the resident set to one 4 MB window.
|
|
1017
|
+
//
|
|
1018
|
+
// Two small structures still span the walk, and both are bounded by DISTINCT
|
|
1019
|
+
// entity count rather than by session count:
|
|
1020
|
+
// kgSeen — dedup. Stores a 16-hex digest, because the old key
|
|
1021
|
+
// repeated all three long strings in a fourth string.
|
|
1022
|
+
// kgEntityNames — the names to emit entities for at the end. This is the
|
|
1023
|
+
// only reason the row array was ever kept; a Set of names
|
|
1024
|
+
// it already references costs a pointer, not a row.
|
|
943
1025
|
const kgSeen = new Set();
|
|
944
1026
|
const kgEntityType = new Map();
|
|
945
|
-
const
|
|
946
|
-
const
|
|
1027
|
+
const kgEntityNames = new Set();
|
|
1028
|
+
const kgKey = (subject, predicate, object, validFrom) => createHash('sha1').update(`${subject}|${predicate}|${object}|${validFrom}`).digest('hex').slice(0, 16);
|
|
1029
|
+
const accumulateKg = async (triples, sourceSession) => {
|
|
947
1030
|
for (const t of triples) {
|
|
948
|
-
const key =
|
|
1031
|
+
const key = kgKey(t.subject, t.predicate, t.object, t.validFrom ?? '');
|
|
949
1032
|
if (kgSeen.has(key))
|
|
950
1033
|
continue;
|
|
951
1034
|
kgSeen.add(key);
|
|
952
1035
|
if (t.predicate === 'is_a' && !kgEntityType.has(t.subject))
|
|
953
1036
|
kgEntityType.set(t.subject, t.object);
|
|
954
|
-
|
|
1037
|
+
kgEntityNames.add(t.subject);
|
|
1038
|
+
kgEntityNames.add(t.object);
|
|
1039
|
+
const count = { redactions: 0 };
|
|
1040
|
+
await kgTripleBatch.add(redactDeep({
|
|
955
1041
|
subject: t.subject, predicate: t.predicate, object: t.object,
|
|
956
1042
|
valid_from: t.validFrom ?? null, valid_to: null,
|
|
957
1043
|
confidence: t.confidence ?? 1.0, source_session: sourceSession,
|
|
958
|
-
});
|
|
1044
|
+
}, count));
|
|
1045
|
+
redactions += count.redactions;
|
|
959
1046
|
}
|
|
960
1047
|
};
|
|
961
|
-
let skipped = 0, redactions = 0, walked = 0;
|
|
962
1048
|
let scanMs = 0, scanned = 0; // secret-scan metrics
|
|
963
1049
|
const slice = refs.slice(0, opts.limit ?? refs.length);
|
|
964
1050
|
// CHAT_RECALL_SYNC_TRACE=1: phase + progress markers with heap usage, to
|
|
@@ -1196,7 +1282,7 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
1196
1282
|
// Knowledge graph: extract triples live from the redacted conversation
|
|
1197
1283
|
// text (no local KG DB is read). Accumulated + deduped, flushed at the end.
|
|
1198
1284
|
if (upload.sessionMeta) {
|
|
1199
|
-
accumulateKg(extractEntities(built.kgText, { projectPath: built.projectPath, sourceType: 'session', sessionId: ref.prefixedId, validFrom: ref.mtime ? new Date(ref.mtime).toISOString().slice(0, 10) : undefined }), ref.prefixedId);
|
|
1285
|
+
await accumulateKg(extractEntities(built.kgText, { projectPath: built.projectPath, sourceType: 'session', sessionId: ref.prefixedId, validFrom: ref.mtime ? new Date(ref.mtime).toISOString().slice(0, 10) : undefined }), ref.prefixedId);
|
|
1200
1286
|
}
|
|
1201
1287
|
// Derived data — the CLI has the FS/git/transcript, the server doesn't.
|
|
1202
1288
|
// Always computed live (diff/outcome/commits/markers + badge row); no
|
|
@@ -1308,7 +1394,7 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
1308
1394
|
});
|
|
1309
1395
|
// KG: extract triples live from this item's redacted chunk text.
|
|
1310
1396
|
if (upload.sessionMeta && redactedChunks.length > 0) {
|
|
1311
|
-
accumulateKg(extractEntities(redactedChunks.map((c) => c.text).join('\n'), { projectPath: item.projectPath || '', sourceType: item.sourceType, validFrom: item.mtime ? new Date(Number(item.mtime)).toISOString().slice(0, 10) : undefined }), null);
|
|
1397
|
+
await accumulateKg(extractEntities(redactedChunks.map((c) => c.text).join('\n'), { projectPath: item.projectPath || '', sourceType: item.sourceType, validFrom: item.mtime ? new Date(Number(item.mtime)).toISOString().slice(0, 10) : undefined }), null);
|
|
1312
1398
|
}
|
|
1313
1399
|
try {
|
|
1314
1400
|
for (const l of await source.extractLinks(item)) {
|
|
@@ -1337,16 +1423,12 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
1337
1423
|
// also the incremental-correct set: no manual-fact replay, no local KG
|
|
1338
1424
|
// DB). Entities are derived from the triple subjects/objects, typed from
|
|
1339
1425
|
// any `is_a` triple seen in the same pass.
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
entityNames.add(t.subject);
|
|
1347
|
-
entityNames.add(t.object);
|
|
1348
|
-
}
|
|
1349
|
-
for (const name of entityNames) {
|
|
1426
|
+
// Triples already shipped inside accumulateKg (see above). Entities cannot:
|
|
1427
|
+
// a name's type comes from an `is_a` triple that may appear in any later
|
|
1428
|
+
// session, so the type is only known once the walk is over. The names are
|
|
1429
|
+
// held as a Set, bounded by distinct entities rather than by session count.
|
|
1430
|
+
if (upload.sessionMeta && kgEntityNames.size > 0) {
|
|
1431
|
+
for (const name of kgEntityNames) {
|
|
1350
1432
|
const count = { redactions: 0 };
|
|
1351
1433
|
await kgEntityBatch.add(redactDeep({ name, type: kgEntityType.get(name) ?? 'unknown', properties: {} }, count));
|
|
1352
1434
|
redactions += count.redactions;
|
|
@@ -1862,73 +1944,78 @@ function collectDerived(ref, mtime, count) {
|
|
|
1862
1944
|
const id = ref.prefixedId;
|
|
1863
1945
|
const compute = [];
|
|
1864
1946
|
let fullOutcome = null;
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
else if (kind === 'commits') {
|
|
1879
|
-
// computeOutcome already ran git for the session window — reuse.
|
|
1880
|
-
if (!fullOutcome)
|
|
1947
|
+
// One read of this transcript instead of four. replay, computeOutcome (twice
|
|
1948
|
+
// internally) and extractTurns each re-read the whole file; the scope holds
|
|
1949
|
+
// exactly one session's text and drops it on the way out.
|
|
1950
|
+
return withSessionReadCache(() => {
|
|
1951
|
+
for (const kind of COMPUTE_KINDS) {
|
|
1952
|
+
let data = null;
|
|
1953
|
+
try {
|
|
1954
|
+
if (kind === 'diff') {
|
|
1955
|
+
const replay = replaySessionAny(id);
|
|
1956
|
+
if (replay.found)
|
|
1957
|
+
data = replay;
|
|
1958
|
+
}
|
|
1959
|
+
else if (kind === 'outcome') {
|
|
1881
1960
|
fullOutcome = computeOutcome(id);
|
|
1882
|
-
|
|
1883
|
-
|
|
1961
|
+
if (fullOutcome.found)
|
|
1962
|
+
data = fullOutcome;
|
|
1963
|
+
}
|
|
1964
|
+
else if (kind === 'commits') {
|
|
1965
|
+
// computeOutcome already ran git for the session window — reuse.
|
|
1966
|
+
if (!fullOutcome)
|
|
1967
|
+
fullOutcome = computeOutcome(id);
|
|
1968
|
+
if (fullOutcome.found)
|
|
1969
|
+
data = fullOutcome.commits;
|
|
1970
|
+
}
|
|
1971
|
+
else if (kind === 'markers') {
|
|
1972
|
+
// Analysis-only use of the turns extractor (R4) — markers need
|
|
1973
|
+
// per-prompt line/ts, not render fidelity.
|
|
1974
|
+
const turns = extractTurnsAny(id, { maxTurns: 50_000 });
|
|
1975
|
+
const prompts = turns.turns
|
|
1976
|
+
.filter((t) => t.kind === 'user' && t.text)
|
|
1977
|
+
.map((t) => ({ line: t.line, ts: t.ts, tsIso: t.tsIso, ...markPrompt(t.text) }));
|
|
1978
|
+
data = { sessionId: id, prompts, summary: summarizeMarkers(prompts) };
|
|
1979
|
+
}
|
|
1884
1980
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
// per-prompt line/ts, not render fidelity.
|
|
1888
|
-
const turns = extractTurnsAny(id, { maxTurns: 50_000 });
|
|
1889
|
-
const prompts = turns.turns
|
|
1890
|
-
.filter((t) => t.kind === 'user' && t.text)
|
|
1891
|
-
.map((t) => ({ line: t.line, ts: t.ts, tsIso: t.tsIso, ...markPrompt(t.text) }));
|
|
1892
|
-
data = { sessionId: id, prompts, summary: summarizeMarkers(prompts) };
|
|
1981
|
+
catch {
|
|
1982
|
+
data = null;
|
|
1893
1983
|
}
|
|
1984
|
+
if (data === null)
|
|
1985
|
+
continue;
|
|
1986
|
+
const redacted = redactDeep(data, count);
|
|
1987
|
+
if (JSON.stringify(redacted).length > MAX_DERIVED_ROW_BYTES)
|
|
1988
|
+
continue;
|
|
1989
|
+
compute.push({ kind, mtime, data: redacted });
|
|
1894
1990
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1991
|
+
// Outcome-badge row (session_outcome_cache) — what the list badges read.
|
|
1992
|
+
// Computed live from the outcome we already ran above.
|
|
1993
|
+
let outcomeRow = null;
|
|
1994
|
+
if (fullOutcome?.found) {
|
|
1995
|
+
outcomeRow = {
|
|
1996
|
+
sessionId: id,
|
|
1997
|
+
tool: ref.toolId,
|
|
1998
|
+
status: fullOutcome.status,
|
|
1999
|
+
reason: fullOutcome.reason,
|
|
2000
|
+
fileMtime: mtime,
|
|
2001
|
+
fileSize: 0,
|
|
2002
|
+
contentHash: '',
|
|
2003
|
+
fileCount: fullOutcome.fileCount,
|
|
2004
|
+
linesAdded: fullOutcome.totalLinesAdded,
|
|
2005
|
+
linesRemoved: fullOutcome.totalLinesRemoved,
|
|
2006
|
+
commits: fullOutcome.commits?.totalCommits ?? 0,
|
|
2007
|
+
isFull: true,
|
|
2008
|
+
classifiedAt: Date.now(),
|
|
2009
|
+
lastScannedOffset: 0,
|
|
2010
|
+
};
|
|
1897
2011
|
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
compute.push({ kind, mtime, data: redacted });
|
|
1904
|
-
}
|
|
1905
|
-
// Outcome-badge row (session_outcome_cache) — what the list badges read.
|
|
1906
|
-
// Computed live from the outcome we already ran above.
|
|
1907
|
-
let outcomeRow = null;
|
|
1908
|
-
if (fullOutcome?.found) {
|
|
1909
|
-
outcomeRow = {
|
|
1910
|
-
sessionId: id,
|
|
1911
|
-
tool: ref.toolId,
|
|
1912
|
-
status: fullOutcome.status,
|
|
1913
|
-
reason: fullOutcome.reason,
|
|
1914
|
-
fileMtime: mtime,
|
|
1915
|
-
fileSize: 0,
|
|
1916
|
-
contentHash: '',
|
|
1917
|
-
fileCount: fullOutcome.fileCount,
|
|
1918
|
-
linesAdded: fullOutcome.totalLinesAdded,
|
|
1919
|
-
linesRemoved: fullOutcome.totalLinesRemoved,
|
|
1920
|
-
commits: fullOutcome.commits?.totalCommits ?? 0,
|
|
1921
|
-
isFull: true,
|
|
1922
|
-
classifiedAt: Date.now(),
|
|
1923
|
-
lastScannedOffset: 0,
|
|
2012
|
+
return {
|
|
2013
|
+
session_id: id,
|
|
2014
|
+
mtime,
|
|
2015
|
+
compute,
|
|
2016
|
+
outcome_row: outcomeRow ? redactDeep({ ...outcomeRow, sessionId: undefined }, count) : null,
|
|
1924
2017
|
};
|
|
1925
|
-
}
|
|
1926
|
-
return {
|
|
1927
|
-
session_id: id,
|
|
1928
|
-
mtime,
|
|
1929
|
-
compute,
|
|
1930
|
-
outcome_row: outcomeRow ? redactDeep({ ...outcomeRow, sessionId: undefined }, count) : null,
|
|
1931
|
-
};
|
|
2018
|
+
});
|
|
1932
2019
|
}
|
|
1933
2020
|
export function isSyncSkip(r) {
|
|
1934
2021
|
return typeof r.skipped === 'string';
|