chat-recall 0.0.1 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +93 -0
- package/dist/auto-update.d.ts +52 -0
- package/dist/auto-update.d.ts.map +1 -0
- package/dist/auto-update.js +157 -0
- package/dist/auto-update.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +26102 -0
- package/dist/cli.js.map +1 -0
- package/dist/client-events.d.ts +11 -0
- package/dist/client-events.d.ts.map +1 -0
- package/dist/client-events.js +77 -0
- package/dist/client-events.js.map +1 -0
- package/dist/collector-migrate.d.ts +27 -0
- package/dist/collector-migrate.d.ts.map +1 -0
- package/dist/collector-migrate.js +60 -0
- package/dist/collector-migrate.js.map +1 -0
- package/dist/device-auth.d.ts +37 -0
- package/dist/device-auth.d.ts.map +1 -0
- package/dist/device-auth.js +161 -0
- package/dist/device-auth.js.map +1 -0
- package/dist/escalate.d.ts +99 -0
- package/dist/escalate.d.ts.map +1 -0
- package/dist/escalate.js +219 -0
- package/dist/escalate.js.map +1 -0
- package/dist/http.d.ts +14 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +49 -0
- package/dist/http.js.map +1 -0
- package/dist/install-skills.d.ts +51 -0
- package/dist/install-skills.d.ts.map +1 -0
- package/dist/install-skills.js +223 -0
- package/dist/install-skills.js.map +1 -0
- package/dist/intent-drain.d.ts +25 -0
- package/dist/intent-drain.d.ts.map +1 -0
- package/dist/intent-drain.js +189 -0
- package/dist/intent-drain.js.map +1 -0
- package/dist/keyring.d.ts +28 -0
- package/dist/keyring.d.ts.map +1 -0
- package/dist/keyring.js +163 -0
- package/dist/keyring.js.map +1 -0
- package/dist/mcp.d.ts +8 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +23665 -0
- package/dist/mcp.js.map +1 -0
- package/dist/project-tasks.d.ts +54 -0
- package/dist/project-tasks.d.ts.map +1 -0
- package/dist/project-tasks.js +204 -0
- package/dist/project-tasks.js.map +1 -0
- package/dist/repair.d.ts +73 -0
- package/dist/repair.d.ts.map +1 -0
- package/dist/repair.js +267 -0
- package/dist/repair.js.map +1 -0
- package/dist/self-restart.d.ts +91 -0
- package/dist/self-restart.d.ts.map +1 -0
- package/dist/self-restart.js +137 -0
- package/dist/self-restart.js.map +1 -0
- package/dist/service-installer.d.ts +32 -0
- package/dist/service-installer.d.ts.map +1 -0
- package/dist/service-installer.js +231 -0
- package/dist/service-installer.js.map +1 -0
- package/dist/sync-client.d.ts +234 -0
- package/dist/sync-client.d.ts.map +1 -0
- package/dist/sync-client.js +1985 -0
- package/dist/sync-client.js.map +1 -0
- package/dist/sync-ledger.d.ts +131 -0
- package/dist/sync-ledger.d.ts.map +1 -0
- package/dist/sync-ledger.js +366 -0
- package/dist/sync-ledger.js.map +1 -0
- package/dist/update-notice.d.ts +16 -0
- package/dist/update-notice.d.ts.map +1 -0
- package/dist/update-notice.js +107 -0
- package/dist/update-notice.js.map +1 -0
- package/dist/verify-deep.d.ts +79 -0
- package/dist/verify-deep.d.ts.map +1 -0
- package/dist/verify-deep.js +97 -0
- package/dist/verify-deep.js.map +1 -0
- package/dist/verify-repair.d.ts +21 -0
- package/dist/verify-repair.d.ts.map +1 -0
- package/dist/verify-repair.js +58 -0
- package/dist/verify-repair.js.map +1 -0
- package/dist/watch.js +21550 -0
- package/hooks/chat_recall_escalate_hook.sh +51 -0
- package/hooks/chat_recall_resume_hook.sh +69 -0
- package/hooks/chat_recall_save_hook.sh +254 -0
- package/hooks/chat_recall_wakeup_hook.sh +39 -0
- package/package.json +38 -4
- package/skills/chat-recall/SKILL.md +76 -0
- package/skills/chat-recall-changes/SKILL.md +50 -0
- package/skills/chat-recall-find/SKILL.md +64 -0
- package/skills/chat-recall-memory/SKILL.md +55 -0
- package/skills/chat-recall-project/SKILL.md +75 -0
- package/skills/chat-recall-resume/SKILL.md +62 -0
- package/README.md +0 -7
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type Platform = 'linux' | 'darwin' | 'win32' | 'other';
|
|
2
|
+
export interface ServicePaths {
|
|
3
|
+
/** Absolute path to the unit/plist/task definition (or null on Windows). */
|
|
4
|
+
definitionPath: string | null;
|
|
5
|
+
/** Absolute path to the log file the service writes stdout+stderr to. */
|
|
6
|
+
logFile: string;
|
|
7
|
+
}
|
|
8
|
+
/** Detect whether the per-user service is currently installed+running. */
|
|
9
|
+
export declare function isServiceRunning(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Install + start the per-user background service. Returns the paths written
|
|
12
|
+
* (for status messaging) or throws on platform/manager failure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function installService(): ServicePaths;
|
|
15
|
+
/** Render the systemd --user unit file body (pure — no FS, no exec). */
|
|
16
|
+
export declare function renderSystemdUnit(watchJs: string, node: string, logFile: string): string;
|
|
17
|
+
/** Render the launchd plist body (pure — no FS, no exec). */
|
|
18
|
+
export declare function renderLaunchdPlist(watchJs: string, node: string, logFile: string, label?: string): string;
|
|
19
|
+
/** Render the schtasks /create command (pure — no exec). */
|
|
20
|
+
export declare function renderWindowsTaskCommand(watchJs: string, node: string, taskName?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Stop + remove the per-user background service. Idempotent — no error if
|
|
23
|
+
* the service isn't installed. Returns true if something was removed.
|
|
24
|
+
*/
|
|
25
|
+
export declare function uninstallService(): boolean;
|
|
26
|
+
/** Human-readable platform name for messaging. */
|
|
27
|
+
export declare function platformName(): string;
|
|
28
|
+
export declare class ServiceInstallError extends Error {
|
|
29
|
+
hint?: string;
|
|
30
|
+
constructor(message: string, hint?: string);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=service-installer.d.ts.map
|
|
@@ -0,0 +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,CAgBxF;AAmBD,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAA0B,GAAG,MAAM,CAa1H;AAeD,4DAA4D;AAC5D,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAsB,GAAG,MAAM,CAG9G;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"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-native background-service installer for the watch daemon.
|
|
3
|
+
*
|
|
4
|
+
* `chat-recall init` and `chat-recall watch --install-service` both route
|
|
5
|
+
* through here so there is ONE place that knows how to install, uninstall,
|
|
6
|
+
* and detect the per-user service across Linux (systemd --user), macOS
|
|
7
|
+
* (launchd), and Windows (Scheduled Task). No admin rights needed.
|
|
8
|
+
*
|
|
9
|
+
* The daemon entry is resolved next to this file (dist/watch.js) so the
|
|
10
|
+
* service survives `npm prefix` moves better than relying on PATH at boot.
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
|
|
14
|
+
import { homedir } from 'os';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
/** Resolve the watch.js entry next to this file and the log file path. */
|
|
18
|
+
function resolveDaemonPaths() {
|
|
19
|
+
const watchJs = fileURLToPath(new URL('./watch.js', import.meta.url));
|
|
20
|
+
const node = process.execPath;
|
|
21
|
+
const dataDir = join(homedir(), '.chat-recall');
|
|
22
|
+
const logFile = join(dataDir, 'watch.log');
|
|
23
|
+
return { watchJs, node, logFile, dataDir };
|
|
24
|
+
}
|
|
25
|
+
/** Best-effort command runner — swallows errors, returns stdout string. */
|
|
26
|
+
function tryCmd(cmd) {
|
|
27
|
+
try {
|
|
28
|
+
return execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Detect whether the per-user service is currently installed+running. */
|
|
35
|
+
export function isServiceRunning() {
|
|
36
|
+
if (process.platform === 'win32') {
|
|
37
|
+
if (/Running/i.test(tryCmd('schtasks /query /tn chat-recall-watch /fo LIST /v 2>nul')))
|
|
38
|
+
return true;
|
|
39
|
+
return /watch\.js/i.test(tryCmd('wmic process where "name=\'node.exe\'" get commandline 2>nul'));
|
|
40
|
+
}
|
|
41
|
+
if (process.platform === 'darwin') {
|
|
42
|
+
// launchctl list shows the label when the agent is loaded.
|
|
43
|
+
return /com\.chat-recall\.watch/.test(tryCmd('launchctl list 2>/dev/null'));
|
|
44
|
+
}
|
|
45
|
+
if (process.platform === 'linux') {
|
|
46
|
+
// systemd is-active is authoritative; skip the pgrep fallback (it
|
|
47
|
+
// self-matches the bash -c that runs the check, causing false positives).
|
|
48
|
+
return /active/.test(tryCmd('systemctl --user is-active chat-recall-watch.service 2>/dev/null'));
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Install + start the per-user background service. Returns the paths written
|
|
54
|
+
* (for status messaging) or throws on platform/manager failure.
|
|
55
|
+
*/
|
|
56
|
+
export function installService() {
|
|
57
|
+
const { watchJs, node, logFile, dataDir } = resolveDaemonPaths();
|
|
58
|
+
mkdirSync(dataDir, { recursive: true });
|
|
59
|
+
if (process.platform === 'linux') {
|
|
60
|
+
return installSystemd(watchJs, node, logFile);
|
|
61
|
+
}
|
|
62
|
+
if (process.platform === 'darwin') {
|
|
63
|
+
return installLaunchd(watchJs, node, logFile);
|
|
64
|
+
}
|
|
65
|
+
if (process.platform === 'win32') {
|
|
66
|
+
return installWindowsTask(watchJs, node, logFile);
|
|
67
|
+
}
|
|
68
|
+
throw new ServiceInstallError(`--install-service: unsupported platform '${process.platform}'.`, 'Run `chat-recall watch` in the foreground, or point your OS scheduler at `chat-recall-watch`.');
|
|
69
|
+
}
|
|
70
|
+
function installSystemd(watchJs, node, logFile) {
|
|
71
|
+
const unitDir = join(homedir(), '.config', 'systemd', 'user');
|
|
72
|
+
const unitPath = join(unitDir, 'chat-recall-watch.service');
|
|
73
|
+
const unit = renderSystemdUnit(watchJs, node, logFile);
|
|
74
|
+
mkdirSync(unitDir, { recursive: true });
|
|
75
|
+
writeFileSync(unitPath, unit);
|
|
76
|
+
try {
|
|
77
|
+
// `restart` (not `enable --now`) so an upgrade reload actually replaces a
|
|
78
|
+
// running daemon — `--now` no-ops on an already-running unit, leaving the
|
|
79
|
+
// old binary in memory. restart starts it if stopped, restarts if running.
|
|
80
|
+
execSync('systemctl --user daemon-reload && systemctl --user enable chat-recall-watch.service && systemctl --user restart chat-recall-watch.service', { stdio: 'inherit' });
|
|
81
|
+
// Survive logout/reboot when no session is open (best-effort; needs the
|
|
82
|
+
// user's password once on some distros).
|
|
83
|
+
try {
|
|
84
|
+
execSync('loginctl enable-linger "$USER" 2>/dev/null', { stdio: 'ignore' });
|
|
85
|
+
}
|
|
86
|
+
catch { /* optional */ }
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
throw new ServiceInstallError('Unit written but systemctl failed.', `Unit: ${unitPath}`);
|
|
90
|
+
}
|
|
91
|
+
return { definitionPath: unitPath, logFile };
|
|
92
|
+
}
|
|
93
|
+
/** Render the systemd --user unit file body (pure — no FS, no exec). */
|
|
94
|
+
export function renderSystemdUnit(watchJs, node, logFile) {
|
|
95
|
+
return [
|
|
96
|
+
'[Unit]', 'Description=chat-recall live indexer (sessions → local index, optional server sync)', 'After=default.target', '',
|
|
97
|
+
'[Service]',
|
|
98
|
+
// Bounded heap: the daemon does bursty batch work (transcript parse,
|
|
99
|
+
// base64 payloads); V8's default old-space on a big-RAM box is ~4GB and
|
|
100
|
+
// GC only gets aggressive near the ceiling — observed as a multi-GB RSS
|
|
101
|
+
// sawtooth. 1536MB keeps GC honest (768 OOMed on the largest subagent-fanout session) with plenty of headroom for the
|
|
102
|
+
// largest transcripts.
|
|
103
|
+
`ExecStart=${node} --max-old-space-size=1536 ${watchJs}`,
|
|
104
|
+
'Restart=on-failure', 'RestartSec=10', 'Nice=10',
|
|
105
|
+
// Keep the service's own stdout/stderr out of the journal noise but
|
|
106
|
+
// available for `chat-recall service status` without paging journald.
|
|
107
|
+
`StandardOutput=append:${logFile}`, `StandardError=append:${logFile}`, '',
|
|
108
|
+
'[Install]', 'WantedBy=default.target', '',
|
|
109
|
+
].join('\n');
|
|
110
|
+
}
|
|
111
|
+
function installLaunchd(watchJs, node, logFile) {
|
|
112
|
+
const label = 'com.chat-recall.watch';
|
|
113
|
+
const plistDir = join(homedir(), 'Library', 'LaunchAgents');
|
|
114
|
+
const plistPath = join(plistDir, `${label}.plist`);
|
|
115
|
+
const plist = renderLaunchdPlist(watchJs, node, logFile, label);
|
|
116
|
+
mkdirSync(plistDir, { recursive: true });
|
|
117
|
+
writeFileSync(plistPath, plist);
|
|
118
|
+
try {
|
|
119
|
+
// Reload idempotently: unload an old copy first, ignore "not loaded".
|
|
120
|
+
try {
|
|
121
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: 'ignore' });
|
|
122
|
+
}
|
|
123
|
+
catch { /* not loaded yet */ }
|
|
124
|
+
execSync(`launchctl load "${plistPath}"`, { stdio: 'inherit' });
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
throw new ServiceInstallError('Plist written but launchctl failed.', `Plist: ${plistPath}`);
|
|
128
|
+
}
|
|
129
|
+
return { definitionPath: plistPath, logFile };
|
|
130
|
+
}
|
|
131
|
+
/** Render the launchd plist body (pure — no FS, no exec). */
|
|
132
|
+
export function renderLaunchdPlist(watchJs, node, logFile, label = 'com.chat-recall.watch') {
|
|
133
|
+
return [
|
|
134
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
135
|
+
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
136
|
+
'<plist version="1.0"><dict>',
|
|
137
|
+
` <key>Label</key><string>${label}</string>`,
|
|
138
|
+
` <key>ProgramArguments</key><array><string>${node}</string><string>--max-old-space-size=1536</string><string>${watchJs}</string></array>`,
|
|
139
|
+
' <key>RunAtLoad</key><true/>',
|
|
140
|
+
' <key>KeepAlive</key><true/>',
|
|
141
|
+
` <key>StandardOutPath</key><string>${logFile}</string>`,
|
|
142
|
+
` <key>StandardErrorPath</key><string>${logFile}</string>`,
|
|
143
|
+
'</dict></plist>', '',
|
|
144
|
+
].join('\n');
|
|
145
|
+
}
|
|
146
|
+
function installWindowsTask(watchJs, node, logFile) {
|
|
147
|
+
const taskName = 'chat-recall-watch';
|
|
148
|
+
const tr = `\\"${node}\\" --max-old-space-size=1536 \\"${watchJs}\\"`;
|
|
149
|
+
try {
|
|
150
|
+
execSync(`schtasks /create /tn "${taskName}" /tr "${tr}" /sc onlogon /rl LIMITED /f`, { stdio: 'inherit' });
|
|
151
|
+
// Start now too (best-effort — starts next logon if /run unsupported).
|
|
152
|
+
try {
|
|
153
|
+
execSync(`schtasks /run /tn "${taskName}"`, { stdio: 'inherit' });
|
|
154
|
+
}
|
|
155
|
+
catch { /* starts next logon */ }
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
throw new ServiceInstallError('Scheduled Task creation failed (schtasks).', '');
|
|
159
|
+
}
|
|
160
|
+
return { definitionPath: null, logFile };
|
|
161
|
+
}
|
|
162
|
+
/** Render the schtasks /create command (pure — no exec). */
|
|
163
|
+
export function renderWindowsTaskCommand(watchJs, node, taskName = 'chat-recall-watch') {
|
|
164
|
+
const tr = `\\"${node}\\" --max-old-space-size=1536 \\"${watchJs}\\"`;
|
|
165
|
+
return `schtasks /create /tn "${taskName}" /tr "${tr}" /sc onlogon /rl LIMITED /f`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Stop + remove the per-user background service. Idempotent — no error if
|
|
169
|
+
* the service isn't installed. Returns true if something was removed.
|
|
170
|
+
*/
|
|
171
|
+
export function uninstallService() {
|
|
172
|
+
if (process.platform === 'linux') {
|
|
173
|
+
let removed = false;
|
|
174
|
+
try {
|
|
175
|
+
execSync('systemctl --user disable --now chat-recall-watch.service 2>/dev/null', { stdio: 'ignore' });
|
|
176
|
+
removed = true;
|
|
177
|
+
}
|
|
178
|
+
catch { /* not installed */ }
|
|
179
|
+
const unitPath = join(homedir(), '.config', 'systemd', 'user', 'chat-recall-watch.service');
|
|
180
|
+
if (existsSync(unitPath)) {
|
|
181
|
+
rmSync(unitPath, { force: true });
|
|
182
|
+
removed = true;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
execSync('systemctl --user daemon-reload 2>/dev/null', { stdio: 'ignore' });
|
|
186
|
+
}
|
|
187
|
+
catch { /* tolerate */ }
|
|
188
|
+
return removed;
|
|
189
|
+
}
|
|
190
|
+
if (process.platform === 'darwin') {
|
|
191
|
+
const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.chat-recall.watch.plist');
|
|
192
|
+
try {
|
|
193
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: 'ignore' });
|
|
194
|
+
}
|
|
195
|
+
catch { /* not loaded */ }
|
|
196
|
+
let removed = false;
|
|
197
|
+
if (existsSync(plistPath)) {
|
|
198
|
+
rmSync(plistPath, { force: true });
|
|
199
|
+
removed = true;
|
|
200
|
+
}
|
|
201
|
+
return removed;
|
|
202
|
+
}
|
|
203
|
+
if (process.platform === 'win32') {
|
|
204
|
+
try {
|
|
205
|
+
execSync('schtasks /delete /tn chat-recall-watch /f 2>nul', { stdio: 'ignore' });
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
/** Human-readable platform name for messaging. */
|
|
215
|
+
export function platformName() {
|
|
216
|
+
if (process.platform === 'linux')
|
|
217
|
+
return 'systemd --user';
|
|
218
|
+
if (process.platform === 'darwin')
|
|
219
|
+
return 'launchd';
|
|
220
|
+
if (process.platform === 'win32')
|
|
221
|
+
return 'Scheduled Task';
|
|
222
|
+
return process.platform;
|
|
223
|
+
}
|
|
224
|
+
export class ServiceInstallError extends Error {
|
|
225
|
+
hint;
|
|
226
|
+
constructor(message, hint) {
|
|
227
|
+
super(message);
|
|
228
|
+
this.hint = hint;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=service-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-installer.js","sourceRoot":"","sources":["../src/service-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { type ScanFinding, type DirScanFinding } from '@chat-recall/engine/core/secret-scanner.js';
|
|
2
|
+
import { type SessionRef } from '@chat-recall/engine/core/tool-backend.js';
|
|
3
|
+
import '@chat-recall/engine/core/backends/index.js';
|
|
4
|
+
export interface Credentials {
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
token: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Multi-target: logging in ADDS a server (or updates its token). Every
|
|
10
|
+
* sync pushes to ALL targets; the per-server ledger keeps coverage
|
|
11
|
+
* independent. File shape is {targets:[...]} with the legacy single-object
|
|
12
|
+
* form still readable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function saveCredentials(c: Credentials): void;
|
|
15
|
+
export declare function loadAllCredentials(): Credentials[];
|
|
16
|
+
export declare function _resetTenantSecurityConfigCache(): void;
|
|
17
|
+
export declare function _resetTenantSyncConfigCache(): void;
|
|
18
|
+
/** Legacy single-target accessor — first target. */
|
|
19
|
+
/** The ACTIVE target = most recent login (saveCredentials unshifts). */
|
|
20
|
+
export declare function loadCredentials(): Credentials | null;
|
|
21
|
+
export declare function removeCredentials(serverUrl: string): boolean;
|
|
22
|
+
export interface SyncResult {
|
|
23
|
+
uploaded: number;
|
|
24
|
+
skipped: number;
|
|
25
|
+
redactions: number;
|
|
26
|
+
items: number;
|
|
27
|
+
links: number;
|
|
28
|
+
findings: number;
|
|
29
|
+
derived: number;
|
|
30
|
+
kgEntities: number;
|
|
31
|
+
kgTriples: number;
|
|
32
|
+
/** Sessions secret-scanned this run. */
|
|
33
|
+
scanned: number;
|
|
34
|
+
/** Total wall-clock ms spent scanning this run. */
|
|
35
|
+
scanMs: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function syncSessions(opts?: {
|
|
38
|
+
sinceMs?: number;
|
|
39
|
+
cleartextPaths?: boolean;
|
|
40
|
+
limit?: number;
|
|
41
|
+
throttleMs?: number;
|
|
42
|
+
prune?: boolean;
|
|
43
|
+
useLedger?: boolean;
|
|
44
|
+
walk?: 'full' | 'changed';
|
|
45
|
+
}): Promise<SyncResult>;
|
|
46
|
+
export interface ReconcileResult {
|
|
47
|
+
sessions: number;
|
|
48
|
+
scanned: number;
|
|
49
|
+
pushed: number;
|
|
50
|
+
absent: number;
|
|
51
|
+
perTarget: Record<string, {
|
|
52
|
+
pushed: number;
|
|
53
|
+
absent: number;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Manual entrypoint (CLI `reconcile`): reconcile derived fields for ALL targets.
|
|
58
|
+
* Normal `sync` already runs reconciliation each pass; this is the explicit
|
|
59
|
+
* on-demand backfill / forced re-scan (also what a UI "re-scan this field"
|
|
60
|
+
* action drives, via forceFieldRescan + a sync).
|
|
61
|
+
*/
|
|
62
|
+
export declare function reconcileFields(opts?: {
|
|
63
|
+
force?: boolean;
|
|
64
|
+
}): Promise<ReconcileResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Reap batch-scan temp dirs leaked by a previous run.
|
|
67
|
+
*
|
|
68
|
+
* The scan below deletes its dir in a `finally` — which a SIGKILL or the OOM
|
|
69
|
+
* killer skips entirely, and this loop is exactly the one that has OOM-killed
|
|
70
|
+
* the daemon before. Each leaked dir holds one file per session: one of them
|
|
71
|
+
* was found at 3.4GB / 309k files, and together with other cruft it filled a
|
|
72
|
+
* 31GB tmpfs, at which point *everything* on the box that needed /tmp broke.
|
|
73
|
+
*
|
|
74
|
+
* So: before starting a scan, delete our own stale dirs. 6h is far longer than
|
|
75
|
+
* any real scan, so an in-flight dir from a concurrent process is never at risk.
|
|
76
|
+
*/
|
|
77
|
+
export declare function reapStaleScanDirs(dir?: string, maxAgeMs?: number, now?: number): number;
|
|
78
|
+
/**
|
|
79
|
+
* Run the optional external detectors (gitleaks/trufflehog) over many sessions
|
|
80
|
+
* with a BOUNDED amount of pre-redaction text on disk at any one time.
|
|
81
|
+
*
|
|
82
|
+
* The detectors take a path, so their input has to be materialized — and that
|
|
83
|
+
* input is raw session text, i.e. real credentials in cleartext. Writing all of
|
|
84
|
+
* it at once is what left 3.4GB / 309k such files in /tmp when the daemon was
|
|
85
|
+
* OOM-killed mid-scan (the `finally` never ran). So we fill a temp dir up to
|
|
86
|
+
* `maxBytes`, scan it, delete it, and repeat: worst-case exposure — and
|
|
87
|
+
* worst-case leak if this process is killed — is one slice, not the whole walk.
|
|
88
|
+
*
|
|
89
|
+
* Cost of slicing is 2 detector spawns per extra slice, still far below the
|
|
90
|
+
* 2·N of per-session scanning.
|
|
91
|
+
*
|
|
92
|
+
* `text()` returning null (unexportable session) is skipped silently: it just
|
|
93
|
+
* gets no external findings, the builtin scan still covers it.
|
|
94
|
+
* `scan` is injectable so tests don't need the binaries installed.
|
|
95
|
+
*/
|
|
96
|
+
export declare function batchScanExternal(items: Array<{
|
|
97
|
+
id: string;
|
|
98
|
+
text: () => string | null;
|
|
99
|
+
}>, opts?: {
|
|
100
|
+
verifyOnly?: boolean;
|
|
101
|
+
maxBytes?: number;
|
|
102
|
+
scan?: (dir: string, o: {
|
|
103
|
+
verifyOnly?: boolean;
|
|
104
|
+
}) => DirScanFinding[];
|
|
105
|
+
}): {
|
|
106
|
+
findings: Map<string, ScanFinding[]>;
|
|
107
|
+
scanned: number;
|
|
108
|
+
slices: number;
|
|
109
|
+
scanMs: number;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Build the live per-session conversation payload — the THIN-COLLECTOR core.
|
|
113
|
+
* Reads ONLY the raw transcript (via `parseTranscript` + `parseSessionFile`),
|
|
114
|
+
* never the local store. Returns the conversation row exactly as the server
|
|
115
|
+
* ingest expects it, plus the redacted plain text (for live KG extraction)
|
|
116
|
+
* and the redaction count. Returns null when there's nothing worth shipping.
|
|
117
|
+
*
|
|
118
|
+
* Exported so the payload can be exercised in tests with no server and no
|
|
119
|
+
* pre-populated index (see sync-client.test.ts).
|
|
120
|
+
*/
|
|
121
|
+
export interface BuiltConversation {
|
|
122
|
+
conv: Record<string, unknown>;
|
|
123
|
+
/** Redacted conversation text — feed to `extractEntities` for the KG. */
|
|
124
|
+
kgText: string;
|
|
125
|
+
/** Real project path resolved from the transcript cwd (for KG context). */
|
|
126
|
+
projectPath: string;
|
|
127
|
+
redactions: number;
|
|
128
|
+
/** Masked secret findings from the raw session (built-in regex always, plus
|
|
129
|
+
* gitleaks/trufflehog/tenant rules when installed), shipped to the server's secret_findings. */
|
|
130
|
+
findings: Array<{
|
|
131
|
+
session_id: string;
|
|
132
|
+
detector: string;
|
|
133
|
+
rule: string;
|
|
134
|
+
line: number;
|
|
135
|
+
preview: string;
|
|
136
|
+
verified_at?: string | null;
|
|
137
|
+
}>;
|
|
138
|
+
/** Wall-clock ms spent scanning this session (0 if nothing to scan). */
|
|
139
|
+
scanMs: number;
|
|
140
|
+
/** Content fingerprint of the transcript this payload was built from
|
|
141
|
+
* (containerSrcHash of the raw export). The walk stamps it into the ledger so
|
|
142
|
+
* a later mtime-only bump with identical content can skip the whole rebuild.
|
|
143
|
+
* Undefined for the oversized-tail path (no full container is materialized). */
|
|
144
|
+
srcHash?: string;
|
|
145
|
+
}
|
|
146
|
+
/** buildConversationSync's early-out when the caller passed a priorContentHash
|
|
147
|
+
* that matches the freshly-exported content: nothing changed since the last
|
|
148
|
+
* FULL sync, so the caller just re-stamps the ledger mtime and skips. */
|
|
149
|
+
export interface UnchangedConversation {
|
|
150
|
+
unchanged: true;
|
|
151
|
+
srcHash: string;
|
|
152
|
+
}
|
|
153
|
+
/** Transcript bytes beyond which a FULL sync must not materialize the whole
|
|
154
|
+
* file. The FULL pipeline copies the transcript ~5× (parse, trim+redact,
|
|
155
|
+
* raw export, raw-text join, redacted container) — a 350MB session transiently
|
|
156
|
+
* needs >1.5GB of heap, which OOM-killed the watch daemon in a restart loop
|
|
157
|
+
* (ledger never acked → same file retried on every startup tick, forever). */
|
|
158
|
+
export declare const FULL_BUILD_MAX_BYTES: number;
|
|
159
|
+
/** Ceiling on PRE-REDACTION session text materialized on disk at any one moment
|
|
160
|
+
* by the optional external-detector batch scan. The batch dir is flushed and
|
|
161
|
+
* deleted every time it crosses this, so a SIGKILL/OOM mid-scan can strand at
|
|
162
|
+
* most this many bytes of cleartext (the incident stranded 3.4GB), and the
|
|
163
|
+
* window in which they exist is proportionally short. Raising it buys fewer
|
|
164
|
+
* detector spawns; lowering it buys a smaller blast radius. */
|
|
165
|
+
export declare const BATCH_SCAN_MAX_BYTES: number;
|
|
166
|
+
/** Bytes an append-only session occupies on disk (0 for non-AO backends). */
|
|
167
|
+
export declare function sessionFileBytes(ref: SessionRef): number;
|
|
168
|
+
export declare function buildConversationSync(ref: SessionRef, mtime: number, opts?: {
|
|
169
|
+
mapPath?: (p: string) => string;
|
|
170
|
+
includeRaw?: boolean;
|
|
171
|
+
includeMeta?: boolean;
|
|
172
|
+
scanSecrets?: boolean;
|
|
173
|
+
verifySecrets?: boolean;
|
|
174
|
+
tenantRules?: Array<{
|
|
175
|
+
name: string;
|
|
176
|
+
regex: string;
|
|
177
|
+
}>;
|
|
178
|
+
/** Batch-scan results for THIS session (gitleaks/trufflehog already run
|
|
179
|
+
* over a directory). When provided, skip the per-session subprocess scan
|
|
180
|
+
* and use these instead — built-in regex + tenant rules still run inline. */
|
|
181
|
+
precomputedExternal?: ScanFinding[];
|
|
182
|
+
/** The content hash this target last FULL-synced (ledger `h`). When the
|
|
183
|
+
* freshly-exported transcript hashes equal to it, the whole build is
|
|
184
|
+
* redundant — we bail immediately with { unchanged, srcHash } so the caller
|
|
185
|
+
* just advances the ledger mtime. Only pass it when the ledger row is at the
|
|
186
|
+
* current extractor version (else a re-derive is genuinely owed). */
|
|
187
|
+
priorContentHash?: string;
|
|
188
|
+
}): Promise<BuiltConversation | UnchangedConversation | null>;
|
|
189
|
+
/**
|
|
190
|
+
* Build the tail-only conversation payload for an APPEND sync (see
|
|
191
|
+
* docs/SYNC-INCREMENTAL.md). Reads ONLY the new bytes from `fromOffset` via
|
|
192
|
+
* the backend's `readFromOffset`, parses them into messages, and ships a
|
|
193
|
+
* minimal append envelope — no raw_b64, no telemetry meta, no title/
|
|
194
|
+
* first_prompt (all head-derived; the server keeps its prior values), no
|
|
195
|
+
* derived (deferred to the FULL re-sync when the session goes quiet).
|
|
196
|
+
*
|
|
197
|
+
* Returns null when the tail is empty / unparseable / all-internal — the
|
|
198
|
+
* caller treats that as "nothing to ship this tick" and leaves the ledger
|
|
199
|
+
* cursor unchanged.
|
|
200
|
+
*/
|
|
201
|
+
export declare function buildConversationTail(ref: SessionRef, fromOffset: number, opts?: {
|
|
202
|
+
mapPath?: (p: string) => string;
|
|
203
|
+
tenantRules?: Array<{
|
|
204
|
+
name: string;
|
|
205
|
+
regex: string;
|
|
206
|
+
}>;
|
|
207
|
+
}): Promise<{
|
|
208
|
+
conv: Record<string, unknown>;
|
|
209
|
+
redactions: number;
|
|
210
|
+
newOffset: number;
|
|
211
|
+
findings: BuiltConversation['findings'];
|
|
212
|
+
} | null>;
|
|
213
|
+
/**
|
|
214
|
+
* Incremental sync for the watch daemon and parameterless `chat-recall sync`:
|
|
215
|
+
* push only sessions modified after `settings.sync.lastSyncAt`, then advance
|
|
216
|
+
* the watermark. The watermark is captured BEFORE the walk so sessions that
|
|
217
|
+
* change mid-sync are re-pushed next time instead of being skipped forever.
|
|
218
|
+
*
|
|
219
|
+
* Returns null when sync isn't configured (no credentials) — callers treat
|
|
220
|
+
* that as "feature off", not an error.
|
|
221
|
+
*/
|
|
222
|
+
/** Why an incremental sync tick did no work. Distinct outcomes because the
|
|
223
|
+
* right reaction differs: 'lock-held' is routine writer election (be quiet),
|
|
224
|
+
* 'no-credentials'/'paused' are user-actionable. Historically all three were
|
|
225
|
+
* a bare `null` and every skip logged as "not logged in" — thousands of
|
|
226
|
+
* misleading lines in the watch log. */
|
|
227
|
+
export interface SyncSkip {
|
|
228
|
+
skipped: 'no-credentials' | 'paused' | 'lock-held';
|
|
229
|
+
}
|
|
230
|
+
export declare function isSyncSkip(r: SyncResult | SyncSkip): r is SyncSkip;
|
|
231
|
+
export declare function syncIncremental(opts?: {
|
|
232
|
+
scope?: 'full' | 'changed';
|
|
233
|
+
}): Promise<SyncResult | SyncSkip>;
|
|
234
|
+
//# sourceMappingURL=sync-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../src/sync-client.ts"],"names":[],"mappings":"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"}
|