@clauderecallhq/cli 0.12.5 → 0.61.3
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 +37 -17
- package/README.md +110 -22
- package/dist/cli.js +1641 -353
- package/dist/daemon/entrypoint.js +1872 -54
- package/dist/mcp-server.js +930 -0
- package/dist/share/fonts/Inter-Bold.woff +0 -0
- package/dist/share/fonts/Inter-Regular.woff +0 -0
- package/dist/share/fonts/JetBrainsMono-Regular.woff +0 -0
- package/dist/web/assets/_brand-Bw9uSB4O.js +1 -0
- package/dist/web/assets/captureNode-9CVj9vYC.js +2 -0
- package/dist/web/assets/card-a-minimal-ujNERzX7.js +1 -0
- package/dist/web/assets/card-b-terminal-DpJ_tVpg.js +1 -0
- package/dist/web/assets/card-c-gradient-CZXVGuNd.js +1 -0
- package/dist/web/assets/card-d-dashboard-CHKD-PnB.js +1 -0
- package/dist/web/assets/dist-CWaokT35.js +56 -0
- package/dist/web/assets/index-B-HrjaDy.css +1 -0
- package/dist/web/assets/index-BZYcD76T.js +633 -0
- package/dist/web/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/dist/web/assets/patterns-BPeZb9N0.js +1 -0
- package/dist/web/assets/stats-BSwqSiFU.js +1 -0
- package/dist/web/assets/thread-D2AXyhOx.js +1 -0
- package/dist/web/index.html +8 -2
- package/package.json +58 -18
- package/scripts/postinstall.mjs +38 -0
- package/dist/cli.js.map +0 -1
- package/dist/commands/activate.js +0 -69
- package/dist/commands/activate.js.map +0 -1
- package/dist/commands/audit-secrets.js +0 -103
- package/dist/commands/audit-secrets.js.map +0 -1
- package/dist/commands/blame.js +0 -35
- package/dist/commands/blame.js.map +0 -1
- package/dist/commands/config-verification.js +0 -18
- package/dist/commands/config-verification.js.map +0 -1
- package/dist/commands/context.js +0 -144
- package/dist/commands/context.js.map +0 -1
- package/dist/commands/correlate.js +0 -70
- package/dist/commands/correlate.js.map +0 -1
- package/dist/commands/digest.js +0 -78
- package/dist/commands/digest.js.map +0 -1
- package/dist/commands/health.js +0 -62
- package/dist/commands/health.js.map +0 -1
- package/dist/commands/index.js +0 -247
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/install-extension.js +0 -138
- package/dist/commands/install-extension.js.map +0 -1
- package/dist/commands/license.js +0 -39
- package/dist/commands/license.js.map +0 -1
- package/dist/commands/list.js +0 -47
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/mcp.js +0 -29
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/open.js +0 -28
- package/dist/commands/open.js.map +0 -1
- package/dist/commands/paste.js +0 -154
- package/dist/commands/paste.js.map +0 -1
- package/dist/commands/projects.js +0 -36
- package/dist/commands/projects.js.map +0 -1
- package/dist/commands/search.js +0 -67
- package/dist/commands/search.js.map +0 -1
- package/dist/commands/semantic.js +0 -173
- package/dist/commands/semantic.js.map +0 -1
- package/dist/commands/show.js +0 -121
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/start.js +0 -47
- package/dist/commands/start.js.map +0 -1
- package/dist/commands/stats.js +0 -133
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/status.js +0 -45
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/stop.js +0 -29
- package/dist/commands/stop.js.map +0 -1
- package/dist/commands/thread.js +0 -396
- package/dist/commands/thread.js.map +0 -1
- package/dist/context/formatter.js +0 -103
- package/dist/context/formatter.js.map +0 -1
- package/dist/daemon/auto-tag-config.js +0 -103
- package/dist/daemon/auto-tag-config.js.map +0 -1
- package/dist/daemon/auto-tag-config.test.js +0 -72
- package/dist/daemon/auto-tag-config.test.js.map +0 -1
- package/dist/daemon/auto-title-config.js +0 -70
- package/dist/daemon/auto-title-config.js.map +0 -1
- package/dist/daemon/bulk-title-jobs.js +0 -170
- package/dist/daemon/bulk-title-jobs.js.map +0 -1
- package/dist/daemon/correlator.js +0 -320
- package/dist/daemon/correlator.js.map +0 -1
- package/dist/daemon/discover.js +0 -316
- package/dist/daemon/discover.js.map +0 -1
- package/dist/daemon/editor-detection.js +0 -186
- package/dist/daemon/editor-detection.js.map +0 -1
- package/dist/daemon/entrypoint.js.map +0 -1
- package/dist/daemon/git-correlator.js +0 -256
- package/dist/daemon/git-correlator.js.map +0 -1
- package/dist/daemon/mcp-installer.js +0 -108
- package/dist/daemon/mcp-installer.js.map +0 -1
- package/dist/daemon/onboarding-state.js +0 -140
- package/dist/daemon/onboarding-state.js.map +0 -1
- package/dist/daemon/pidfile.js +0 -57
- package/dist/daemon/pidfile.js.map +0 -1
- package/dist/daemon/ports.js +0 -48
- package/dist/daemon/ports.js.map +0 -1
- package/dist/daemon/scanProgressRegistry.js +0 -62
- package/dist/daemon/scanProgressRegistry.js.map +0 -1
- package/dist/daemon/server.js +0 -2010
- package/dist/daemon/server.js.map +0 -1
- package/dist/daemon/tag-scanner/anthropic-client.js +0 -40
- package/dist/daemon/tag-scanner/anthropic-client.js.map +0 -1
- package/dist/daemon/tag-scanner/autopilot.js +0 -131
- package/dist/daemon/tag-scanner/autopilot.js.map +0 -1
- package/dist/daemon/tag-scanner/claude-cli-driver.js +0 -250
- package/dist/daemon/tag-scanner/claude-cli-driver.js.map +0 -1
- package/dist/daemon/tag-scanner/orchestrator.js +0 -88
- package/dist/daemon/tag-scanner/orchestrator.js.map +0 -1
- package/dist/daemon/tag-scanner/prompt.js +0 -46
- package/dist/daemon/tag-scanner/prompt.js.map +0 -1
- package/dist/daemon/tag-scanner/prompt.test.js +0 -48
- package/dist/daemon/tag-scanner/prompt.test.js.map +0 -1
- package/dist/daemon/tag-scanner/scan-state.js +0 -49
- package/dist/daemon/tag-scanner/scan-state.js.map +0 -1
- package/dist/daemon/tag-scanner/session-fetcher.js +0 -82
- package/dist/daemon/tag-scanner/session-fetcher.js.map +0 -1
- package/dist/daemon/tag-scanner/session-fetcher.test.js +0 -34
- package/dist/daemon/tag-scanner/session-fetcher.test.js.map +0 -1
- package/dist/daemon/tag-scanner/validator.js +0 -50
- package/dist/daemon/tag-scanner/validator.js.map +0 -1
- package/dist/daemon/tag-scanner/validator.test.js +0 -41
- package/dist/daemon/tag-scanner/validator.test.js.map +0 -1
- package/dist/daemon/terminal-registry.js +0 -443
- package/dist/daemon/terminal-registry.js.map +0 -1
- package/dist/daemon/ui.js +0 -64
- package/dist/daemon/ui.js.map +0 -1
- package/dist/daemon/watcher.js +0 -256
- package/dist/daemon/watcher.js.map +0 -1
- package/dist/db/client.js +0 -22
- package/dist/db/client.js.map +0 -1
- package/dist/db/schema.js +0 -496
- package/dist/db/schema.js.map +0 -1
- package/dist/license/api-base.js +0 -13
- package/dist/license/api-base.js.map +0 -1
- package/dist/license/manager.js +0 -43
- package/dist/license/manager.js.map +0 -1
- package/dist/license/public-key.js +0 -19
- package/dist/license/public-key.js.map +0 -1
- package/dist/license/storage.js +0 -27
- package/dist/license/storage.js.map +0 -1
- package/dist/license/verify.js +0 -23
- package/dist/license/verify.js.map +0 -1
- package/dist/mcp/audit.js +0 -126
- package/dist/mcp/audit.js.map +0 -1
- package/dist/mcp/prompts.js +0 -180
- package/dist/mcp/prompts.js.map +0 -1
- package/dist/mcp/server.js +0 -502
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/thread-tools.js +0 -363
- package/dist/mcp/thread-tools.js.map +0 -1
- package/dist/mcp/write-tools.js +0 -239
- package/dist/mcp/write-tools.js.map +0 -1
- package/dist/parser/jsonl.js +0 -150
- package/dist/parser/jsonl.js.map +0 -1
- package/dist/semantic/chunker.js +0 -47
- package/dist/semantic/chunker.js.map +0 -1
- package/dist/semantic/config.js +0 -74
- package/dist/semantic/config.js.map +0 -1
- package/dist/semantic/embedder.js +0 -54
- package/dist/semantic/embedder.js.map +0 -1
- package/dist/semantic/fusion.js +0 -38
- package/dist/semantic/fusion.js.map +0 -1
- package/dist/semantic/model-download.js +0 -69
- package/dist/semantic/model-download.js.map +0 -1
- package/dist/semantic/pipeline.js +0 -375
- package/dist/semantic/pipeline.js.map +0 -1
- package/dist/semantic/query.js +0 -42
- package/dist/semantic/query.js.map +0 -1
- package/dist/semantic/worker.js +0 -78
- package/dist/semantic/worker.js.map +0 -1
- package/dist/stats/backfill.js +0 -151
- package/dist/stats/backfill.js.map +0 -1
- package/dist/stats/health.js +0 -102
- package/dist/stats/health.js.map +0 -1
- package/dist/stats/query.js +0 -385
- package/dist/stats/query.js.map +0 -1
- package/dist/utils/aliases.js +0 -107
- package/dist/utils/aliases.js.map +0 -1
- package/dist/utils/autoCollections.js +0 -635
- package/dist/utils/autoCollections.js.map +0 -1
- package/dist/utils/autoTitle.js +0 -348
- package/dist/utils/autoTitle.js.map +0 -1
- package/dist/utils/collections.js +0 -446
- package/dist/utils/collections.js.map +0 -1
- package/dist/utils/format.js +0 -46
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/notes.js +0 -270
- package/dist/utils/notes.js.map +0 -1
- package/dist/utils/paths.js +0 -50
- package/dist/utils/paths.js.map +0 -1
- package/dist/utils/pricing.js +0 -257
- package/dist/utils/pricing.js.map +0 -1
- package/dist/utils/secret-scanner.js +0 -166
- package/dist/utils/secret-scanner.js.map +0 -1
- package/dist/utils/sessionLabel.js +0 -64
- package/dist/utils/sessionLabel.js.map +0 -1
- package/dist/utils/tags.js +0 -97
- package/dist/utils/tags.js.map +0 -1
- package/dist/utils/thread-context.js +0 -129
- package/dist/utils/thread-context.js.map +0 -1
- package/dist/utils/threadFilter.js +0 -18
- package/dist/utils/threadFilter.js.map +0 -1
- package/dist/utils/threads-titler.js +0 -298
- package/dist/utils/threads-titler.js.map +0 -1
- package/dist/utils/threads.js +0 -383
- package/dist/utils/threads.js.map +0 -1
- package/dist/utils/usage.js +0 -76
- package/dist/utils/usage.js.map +0 -1
- package/dist/verification/compute.js +0 -88
- package/dist/verification/compute.js.map +0 -1
- package/dist/verification/config.js +0 -34
- package/dist/verification/config.js.map +0 -1
- package/dist/web/assets/index-CIr6J4Fw.js +0 -1201
- package/dist/web/assets/index-Ctc8g9Jw.css +0 -1
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { getDb } from '../db/client.js';
|
|
5
|
-
import { spawnClaudePrompt, isClaudeCliAvailable } from '../daemon/tag-scanner/claude-cli-driver.js';
|
|
6
|
-
import { readSemanticConfig, writeSemanticConfig } from './config.js';
|
|
7
|
-
/**
|
|
8
|
-
* v0.11 — Semantic-search pipeline. Same Tier-0 strategy as auto-tagging:
|
|
9
|
-
* shell out to the user's local `claude` CLI to summarize a session into
|
|
10
|
-
* 3 sentences + ~15 keywords, then store the result in `session_semantic`
|
|
11
|
-
* (which feeds the `sessions_fts` virtual table for conceptual search).
|
|
12
|
-
*
|
|
13
|
-
* Three-layer durability matches every other write feature:
|
|
14
|
-
* 1. SQLite row in `session_semantic`
|
|
15
|
-
* 2. Plain-text mirror at $RECALL_HOME/semantic/<session_id>.json
|
|
16
|
-
* 3. Source JSONLs at ~/.claude/projects/ are never touched
|
|
17
|
-
*
|
|
18
|
-
* Rate limiting: a global token bucket gated by `ratePerMinute` from
|
|
19
|
-
* config. The bucket refills continuously — `acquireToken()` waits
|
|
20
|
-
* (does NOT drop) so every queued session eventually gets processed.
|
|
21
|
-
*/
|
|
22
|
-
const PROMPT_VERSION = 1;
|
|
23
|
-
const MAX_CONTEXT_CHARS = 12_000;
|
|
24
|
-
const MIN_MESSAGES = 3;
|
|
25
|
-
const ALLOWED_TOOLS = []; // pure summarization, no MCP tools needed
|
|
26
|
-
function recallHome() {
|
|
27
|
-
return process.env.RECALL_HOME ?? join(homedir(), '.recall');
|
|
28
|
-
}
|
|
29
|
-
function semanticDir() {
|
|
30
|
-
return join(recallHome(), 'semantic');
|
|
31
|
-
}
|
|
32
|
-
function ensureSemanticDir() {
|
|
33
|
-
const dir = semanticDir();
|
|
34
|
-
if (!existsSync(dir))
|
|
35
|
-
mkdirSync(dir, { recursive: true });
|
|
36
|
-
}
|
|
37
|
-
function fetchSnippet(sessionId) {
|
|
38
|
-
const db = getDb();
|
|
39
|
-
const meta = db
|
|
40
|
-
.prepare(`SELECT s.id, s.message_count, s.first_user_message,
|
|
41
|
-
p.name AS project,
|
|
42
|
-
NULLIF(sa.alias, '') AS alias
|
|
43
|
-
FROM sessions s
|
|
44
|
-
JOIN projects p ON p.id = s.project_id
|
|
45
|
-
LEFT JOIN session_aliases sa ON sa.session_id = s.id
|
|
46
|
-
WHERE s.id = ?`)
|
|
47
|
-
.get(sessionId);
|
|
48
|
-
if (!meta)
|
|
49
|
-
return null;
|
|
50
|
-
const rows = db
|
|
51
|
-
.prepare(`SELECT role, content_text
|
|
52
|
-
FROM messages
|
|
53
|
-
WHERE session_id = ? AND is_sidechain = 0
|
|
54
|
-
ORDER BY COALESCE(timestamp, ''), rowid`)
|
|
55
|
-
.all(sessionId);
|
|
56
|
-
const lines = [];
|
|
57
|
-
let used = 0;
|
|
58
|
-
for (const r of rows) {
|
|
59
|
-
if (!r.content_text)
|
|
60
|
-
continue;
|
|
61
|
-
const role = r.role ?? 'system';
|
|
62
|
-
// Strip code blocks heavily — semantic summary doesn't need them and they
|
|
63
|
-
// dominate the context budget. Replace with a placeholder so the summary
|
|
64
|
-
// model still knows code happened.
|
|
65
|
-
const trimmed = r.content_text
|
|
66
|
-
.replace(/```[\s\S]*?```/g, '[code]')
|
|
67
|
-
.replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, '')
|
|
68
|
-
.trim();
|
|
69
|
-
if (!trimmed)
|
|
70
|
-
continue;
|
|
71
|
-
const slice = trimmed.length > 1500 ? trimmed.slice(0, 1500) + '…' : trimmed;
|
|
72
|
-
const line = `${role}: ${slice}`;
|
|
73
|
-
if (used + line.length > MAX_CONTEXT_CHARS)
|
|
74
|
-
break;
|
|
75
|
-
lines.push(line);
|
|
76
|
-
used += line.length;
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
id: meta.id,
|
|
80
|
-
alias: meta.alias,
|
|
81
|
-
project: meta.project,
|
|
82
|
-
firstUserMessage: meta.first_user_message,
|
|
83
|
-
excerpt: lines.join('\n\n'),
|
|
84
|
-
messageCount: meta.message_count,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
function buildPrompt(snippet) {
|
|
88
|
-
return [
|
|
89
|
-
'You are summarizing a Claude Code session for a local semantic-search index. The summary will be stored as plain text and matched against future natural-language queries.',
|
|
90
|
-
'',
|
|
91
|
-
`Session: ${snippet.alias ?? snippet.id}`,
|
|
92
|
-
`Project: ${snippet.project}`,
|
|
93
|
-
snippet.firstUserMessage ? `Opening prompt: ${snippet.firstUserMessage}` : '',
|
|
94
|
-
'',
|
|
95
|
-
'Transcript excerpt (truncated):',
|
|
96
|
-
'---',
|
|
97
|
-
snippet.excerpt,
|
|
98
|
-
'---',
|
|
99
|
-
'',
|
|
100
|
-
'Output a single JSON object on one line, with no Markdown fences and no commentary:',
|
|
101
|
-
'{"summary": "<3 sentences describing what the user was trying to do, what was built or debugged, and the outcome>", "keywords": ["<concept>", "<technology>", "<problem>", ...]}',
|
|
102
|
-
'',
|
|
103
|
-
'Constraints:',
|
|
104
|
-
'- summary: 3 sentences, plain prose, no bullet points',
|
|
105
|
-
'- keywords: 10–15 lowercase tokens, multi-word entries hyphenated (e.g. "memory-leak"); no duplicates; no generic words like "code" or "session"',
|
|
106
|
-
'- Output JSON only. Do not echo this prompt.',
|
|
107
|
-
]
|
|
108
|
-
.filter(Boolean)
|
|
109
|
-
.join('\n');
|
|
110
|
-
}
|
|
111
|
-
function extractJson(stdout) {
|
|
112
|
-
// claude --print --output-format json wraps output in `{type: "result", result: "..."}`.
|
|
113
|
-
// Try the wrapper first, then fall back to raw JSON in case the format changes.
|
|
114
|
-
let candidate = stdout.trim();
|
|
115
|
-
try {
|
|
116
|
-
const wrapper = JSON.parse(candidate);
|
|
117
|
-
if (typeof wrapper.result === 'string') {
|
|
118
|
-
candidate = wrapper.result.trim();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// not the wrapper — proceed with raw stdout
|
|
123
|
-
}
|
|
124
|
-
// Strip leading/trailing markdown fences if the model emitted them anyway.
|
|
125
|
-
candidate = candidate.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
|
|
126
|
-
// Find the first {...} JSON object.
|
|
127
|
-
const start = candidate.indexOf('{');
|
|
128
|
-
const end = candidate.lastIndexOf('}');
|
|
129
|
-
if (start === -1 || end === -1 || end <= start)
|
|
130
|
-
return null;
|
|
131
|
-
const slice = candidate.slice(start, end + 1);
|
|
132
|
-
try {
|
|
133
|
-
const parsed = JSON.parse(slice);
|
|
134
|
-
const summary = typeof parsed.summary === 'string' ? parsed.summary.trim() : '';
|
|
135
|
-
const keywordsArr = Array.isArray(parsed.keywords) ? parsed.keywords : [];
|
|
136
|
-
const keywords = keywordsArr
|
|
137
|
-
.filter((k) => typeof k === 'string')
|
|
138
|
-
.map((k) => k.trim().toLowerCase())
|
|
139
|
-
.filter((k) => k.length > 0 && k.length < 64);
|
|
140
|
-
if (!summary || keywords.length === 0)
|
|
141
|
-
return null;
|
|
142
|
-
return { summary, keywords: Array.from(new Set(keywords)).slice(0, 20) };
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function persist(row) {
|
|
149
|
-
const db = getDb();
|
|
150
|
-
const keywordsCsv = row.keywords.join(',');
|
|
151
|
-
db.prepare(`INSERT INTO session_semantic
|
|
152
|
-
(session_id, summary, keywords, model, source_message_count, generated_at)
|
|
153
|
-
VALUES (@session_id, @summary, @keywords, @model, @source_message_count, @generated_at)
|
|
154
|
-
ON CONFLICT(session_id) DO UPDATE SET
|
|
155
|
-
summary = excluded.summary,
|
|
156
|
-
keywords = excluded.keywords,
|
|
157
|
-
model = excluded.model,
|
|
158
|
-
source_message_count = excluded.source_message_count,
|
|
159
|
-
generated_at = excluded.generated_at`).run({
|
|
160
|
-
session_id: row.sessionId,
|
|
161
|
-
summary: row.summary,
|
|
162
|
-
keywords: keywordsCsv,
|
|
163
|
-
model: row.model,
|
|
164
|
-
source_message_count: row.sourceMessageCount,
|
|
165
|
-
generated_at: row.generatedAt,
|
|
166
|
-
});
|
|
167
|
-
ensureSemanticDir();
|
|
168
|
-
const mirrorPath = join(semanticDir(), `${row.sessionId}.json`);
|
|
169
|
-
writeFileSync(mirrorPath, JSON.stringify({
|
|
170
|
-
version: PROMPT_VERSION,
|
|
171
|
-
session_id: row.sessionId,
|
|
172
|
-
summary: row.summary,
|
|
173
|
-
keywords: row.keywords,
|
|
174
|
-
model: row.model,
|
|
175
|
-
source_message_count: row.sourceMessageCount,
|
|
176
|
-
generated_at: row.generatedAt,
|
|
177
|
-
}, null, 2));
|
|
178
|
-
}
|
|
179
|
-
let bucket = null;
|
|
180
|
-
function getBucket() {
|
|
181
|
-
const cfg = readSemanticConfig();
|
|
182
|
-
const capacity = cfg.ratePerMinute;
|
|
183
|
-
const refillPerMs = capacity / 60_000;
|
|
184
|
-
if (!bucket || bucket.capacity !== capacity) {
|
|
185
|
-
bucket = { tokens: capacity, capacity, refillPerMs, lastRefill: Date.now() };
|
|
186
|
-
}
|
|
187
|
-
return bucket;
|
|
188
|
-
}
|
|
189
|
-
function refill(b) {
|
|
190
|
-
const now = Date.now();
|
|
191
|
-
const elapsed = now - b.lastRefill;
|
|
192
|
-
if (elapsed > 0) {
|
|
193
|
-
b.tokens = Math.min(b.capacity, b.tokens + elapsed * b.refillPerMs);
|
|
194
|
-
b.lastRefill = now;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
async function acquireToken(signal) {
|
|
198
|
-
while (true) {
|
|
199
|
-
if (signal?.aborted)
|
|
200
|
-
throw new Error('aborted');
|
|
201
|
-
const b = getBucket();
|
|
202
|
-
refill(b);
|
|
203
|
-
if (b.tokens >= 1) {
|
|
204
|
-
b.tokens -= 1;
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const needed = 1 - b.tokens;
|
|
208
|
-
const waitMs = Math.max(50, Math.ceil(needed / b.refillPerMs));
|
|
209
|
-
await new Promise((r) => setTimeout(r, Math.min(waitMs, 5_000)));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Process a single session: build context, call claude, parse, persist.
|
|
214
|
-
* Returns a structured result instead of throwing — callers (watcher,
|
|
215
|
-
* backfill loop) need to keep going on individual failures.
|
|
216
|
-
*/
|
|
217
|
-
export async function processSession(sessionId, opts = {}) {
|
|
218
|
-
const cfg = readSemanticConfig();
|
|
219
|
-
if (!cfg.enabled)
|
|
220
|
-
return { sessionId, ok: false, reason: 'disabled' };
|
|
221
|
-
if (!isClaudeCliAvailable())
|
|
222
|
-
return { sessionId, ok: false, reason: 'claude-cli-missing' };
|
|
223
|
-
const snippet = fetchSnippet(sessionId);
|
|
224
|
-
if (!snippet)
|
|
225
|
-
return { sessionId, ok: false, reason: 'session-not-found' };
|
|
226
|
-
if (snippet.messageCount < MIN_MESSAGES) {
|
|
227
|
-
return { sessionId, ok: false, reason: 'too-short' };
|
|
228
|
-
}
|
|
229
|
-
if (!snippet.excerpt.trim()) {
|
|
230
|
-
return { sessionId, ok: false, reason: 'empty-excerpt' };
|
|
231
|
-
}
|
|
232
|
-
await acquireToken(opts.signal);
|
|
233
|
-
const prompt = buildPrompt(snippet);
|
|
234
|
-
const result = await spawnClaudePrompt(prompt, ALLOWED_TOOLS, { model: cfg.model });
|
|
235
|
-
if (!result.success) {
|
|
236
|
-
return {
|
|
237
|
-
sessionId,
|
|
238
|
-
ok: false,
|
|
239
|
-
reason: `claude-cli-exit-${result.exitCode ?? 'null'}`,
|
|
240
|
-
model: cfg.model ?? null,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
const parsed = extractJson(result.stdout);
|
|
244
|
-
if (!parsed) {
|
|
245
|
-
return { sessionId, ok: false, reason: 'parse-failed', model: cfg.model ?? null };
|
|
246
|
-
}
|
|
247
|
-
persist({
|
|
248
|
-
sessionId: snippet.id,
|
|
249
|
-
summary: parsed.summary,
|
|
250
|
-
keywords: parsed.keywords,
|
|
251
|
-
model: cfg.model ?? null,
|
|
252
|
-
sourceMessageCount: snippet.messageCount,
|
|
253
|
-
generatedAt: new Date().toISOString(),
|
|
254
|
-
});
|
|
255
|
-
return { sessionId, ok: true, model: cfg.model ?? null };
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Iterate over every session with no semantic row (or every session when
|
|
259
|
-
* `force`), in oldest→newest order so the backfill cursor advances
|
|
260
|
-
* monotonically. Resumable: writes `lastProcessedSessionId` to config after
|
|
261
|
-
* each successful row.
|
|
262
|
-
*/
|
|
263
|
-
export async function backfill(opts = {}) {
|
|
264
|
-
const cfg = readSemanticConfig();
|
|
265
|
-
if (!cfg.enabled) {
|
|
266
|
-
return { total: 0, processed: 0, ok: 0, failed: 0, currentSessionId: null };
|
|
267
|
-
}
|
|
268
|
-
const db = getDb();
|
|
269
|
-
const limit = opts.limit ?? 1000;
|
|
270
|
-
const params = { limit };
|
|
271
|
-
let where = 's.message_count >= 3';
|
|
272
|
-
if (!opts.force) {
|
|
273
|
-
where += ' AND ss.session_id IS NULL';
|
|
274
|
-
}
|
|
275
|
-
if (cfg.lastProcessedSessionId && !opts.force) {
|
|
276
|
-
// Resume from cursor: skip already-processed (covered by the IS NULL
|
|
277
|
-
// join above) but we keep the cursor for callers/CLI to display.
|
|
278
|
-
}
|
|
279
|
-
const rows = db
|
|
280
|
-
.prepare(`SELECT s.id
|
|
281
|
-
FROM sessions s
|
|
282
|
-
LEFT JOIN session_semantic ss ON ss.session_id = s.id
|
|
283
|
-
WHERE ${where}
|
|
284
|
-
ORDER BY COALESCE(s.started_at, '') ASC, s.id ASC
|
|
285
|
-
LIMIT @limit`)
|
|
286
|
-
.all(params);
|
|
287
|
-
const snapshot = {
|
|
288
|
-
total: rows.length,
|
|
289
|
-
processed: 0,
|
|
290
|
-
ok: 0,
|
|
291
|
-
failed: 0,
|
|
292
|
-
currentSessionId: null,
|
|
293
|
-
};
|
|
294
|
-
opts.onProgress?.(snapshot);
|
|
295
|
-
for (const { id } of rows) {
|
|
296
|
-
if (opts.signal?.aborted)
|
|
297
|
-
break;
|
|
298
|
-
const fresh = readSemanticConfig();
|
|
299
|
-
if (fresh.backfillPaused)
|
|
300
|
-
break;
|
|
301
|
-
snapshot.currentSessionId = id;
|
|
302
|
-
opts.onProgress?.({ ...snapshot });
|
|
303
|
-
try {
|
|
304
|
-
const r = await processSession(id, { signal: opts.signal });
|
|
305
|
-
if (r.ok)
|
|
306
|
-
snapshot.ok += 1;
|
|
307
|
-
else
|
|
308
|
-
snapshot.failed += 1;
|
|
309
|
-
}
|
|
310
|
-
catch (err) {
|
|
311
|
-
snapshot.failed += 1;
|
|
312
|
-
console.error('[semantic.backfill] failed for', id, err);
|
|
313
|
-
}
|
|
314
|
-
snapshot.processed += 1;
|
|
315
|
-
writeSemanticConfig({ lastProcessedSessionId: id });
|
|
316
|
-
opts.onProgress?.({ ...snapshot });
|
|
317
|
-
}
|
|
318
|
-
snapshot.currentSessionId = null;
|
|
319
|
-
opts.onProgress?.({ ...snapshot });
|
|
320
|
-
return snapshot;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Watcher hook — fire-and-forget after a session has been (re-)indexed.
|
|
324
|
-
* Silent no-op when semantic mode is disabled or when the session already
|
|
325
|
-
* has a row whose generation timestamp is newer than the session's last
|
|
326
|
-
* activity (no new messages since we summarized).
|
|
327
|
-
*/
|
|
328
|
-
export async function maybeProcessOnSessionClose(sessionId) {
|
|
329
|
-
const cfg = readSemanticConfig();
|
|
330
|
-
if (!cfg.enabled)
|
|
331
|
-
return;
|
|
332
|
-
const db = getDb();
|
|
333
|
-
const row = db
|
|
334
|
-
.prepare(`SELECT s.message_count, s.ended_at,
|
|
335
|
-
ss.generated_at, ss.source_message_count
|
|
336
|
-
FROM sessions s
|
|
337
|
-
LEFT JOIN session_semantic ss ON ss.session_id = s.id
|
|
338
|
-
WHERE s.id = ?`)
|
|
339
|
-
.get(sessionId);
|
|
340
|
-
if (!row)
|
|
341
|
-
return;
|
|
342
|
-
if (row.message_count < MIN_MESSAGES)
|
|
343
|
-
return;
|
|
344
|
-
if (row.generated_at &&
|
|
345
|
-
row.source_message_count != null &&
|
|
346
|
-
row.source_message_count >= row.message_count) {
|
|
347
|
-
return; // up to date
|
|
348
|
-
}
|
|
349
|
-
try {
|
|
350
|
-
await processSession(sessionId);
|
|
351
|
-
}
|
|
352
|
-
catch (err) {
|
|
353
|
-
console.error('[semantic] processSession error for', sessionId, err);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
export function getSemanticStatus() {
|
|
357
|
-
const cfg = readSemanticConfig();
|
|
358
|
-
const db = getDb();
|
|
359
|
-
const total = db.prepare("SELECT COUNT(*) AS n FROM sessions WHERE message_count >= 3").get().n;
|
|
360
|
-
const processed = db.prepare('SELECT COUNT(*) AS n FROM session_semantic').get().n;
|
|
361
|
-
return {
|
|
362
|
-
enabled: cfg.enabled,
|
|
363
|
-
claudeCliAvailable: isClaudeCliAvailable(),
|
|
364
|
-
ratePerMinute: cfg.ratePerMinute,
|
|
365
|
-
model: cfg.model ?? null,
|
|
366
|
-
totalSessions: total,
|
|
367
|
-
processedSessions: processed,
|
|
368
|
-
pendingSessions: Math.max(0, total - processed),
|
|
369
|
-
lastProcessedSessionId: cfg.lastProcessedSessionId,
|
|
370
|
-
backfillPaused: cfg.backfillPaused,
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
// Test/exported for unit coverage.
|
|
374
|
-
export const __test__ = { extractJson, buildPrompt };
|
|
375
|
-
//# sourceMappingURL=pipeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/semantic/pipeline.ts"],"names":[],"mappings":"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"}
|
package/dist/semantic/query.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { getDb } from '../db/client.js';
|
|
2
|
-
import { embedQuery } from './embedder.js';
|
|
3
|
-
export async function vectorSearch(query, limit = 50) {
|
|
4
|
-
const vector = await embedQuery(query);
|
|
5
|
-
const db = getDb();
|
|
6
|
-
const buf = Buffer.from(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
7
|
-
const rows = db.prepare(`SELECT v.rowid, v.distance, cm.session_id, cm.text, cm.message_uuids
|
|
8
|
-
FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
|
|
9
|
-
WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(buf, limit);
|
|
10
|
-
return rows.map((r) => ({
|
|
11
|
-
sessionId: r.session_id, chunkRowid: r.rowid, distance: r.distance,
|
|
12
|
-
text: r.text, messageUuids: JSON.parse(r.message_uuids),
|
|
13
|
-
}));
|
|
14
|
-
}
|
|
15
|
-
export async function findSimilarSessions(sessionId, limit = 10, minCosine = 0.65) {
|
|
16
|
-
const db = getDb();
|
|
17
|
-
const firstChunk = db.prepare('SELECT rowid FROM chunk_meta WHERE session_id = ? ORDER BY rowid LIMIT 1').get(sessionId);
|
|
18
|
-
if (!firstChunk)
|
|
19
|
-
return [];
|
|
20
|
-
const vecRow = db.prepare('SELECT embedding FROM vec_chunks WHERE rowid = ?').get(firstChunk.rowid);
|
|
21
|
-
if (!vecRow)
|
|
22
|
-
return [];
|
|
23
|
-
const rows = db.prepare(`SELECT v.rowid, v.distance, cm.session_id FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
|
|
24
|
-
WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(vecRow.embedding, limit * 5);
|
|
25
|
-
const sessionBest = new Map();
|
|
26
|
-
for (const row of rows) {
|
|
27
|
-
if (row.session_id === sessionId)
|
|
28
|
-
continue;
|
|
29
|
-
const existing = sessionBest.get(row.session_id);
|
|
30
|
-
if (existing === undefined || row.distance < existing)
|
|
31
|
-
sessionBest.set(row.session_id, row.distance);
|
|
32
|
-
}
|
|
33
|
-
const results = [];
|
|
34
|
-
for (const [sid, distance] of sessionBest) {
|
|
35
|
-
const similarity = 1 - distance;
|
|
36
|
-
if (similarity >= minCosine)
|
|
37
|
-
results.push({ sessionId: sid, similarity });
|
|
38
|
-
}
|
|
39
|
-
results.sort((a, b) => b.similarity - a.similarity);
|
|
40
|
-
return results.slice(0, limit);
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=query.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/semantic/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAU3C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,QAAgB,EAAE;IAClE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB;;6DAEyD,CAC1D,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAwG,CAAC;IACzH,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtB,SAAS,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ;QAClE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAa;KACpE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EAAE,QAAgB,EAAE,EAAE,YAAoB,IAAI;IAE/D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,0EAA0E,CAAC,CAAC,GAAG,CAAC,SAAS,CAAkC,CAAC;IAC1J,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAsC,CAAC;IACzI,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB;6DACyD,CAC1D,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,GAAG,CAAC,CAAmE,CAAC;IACrG,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS;YAAE,SAAS;QAC3C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,GAAG,QAAQ;YAAE,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,OAAO,GAAqD,EAAE,CAAC;IACrE,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,WAAW,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,CAAC,GAAG,QAAQ,CAAC;QAChC,IAAI,UAAU,IAAI,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/semantic/worker.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { getDb } from '../db/client.js';
|
|
2
|
-
import { getEmbedderStatus, embed } from './embedder.js';
|
|
3
|
-
import { chunkSession } from './chunker.js';
|
|
4
|
-
const POLL_ACTIVE_MS = 2000;
|
|
5
|
-
const POLL_IDLE_MS = 10000;
|
|
6
|
-
let intervalId = null;
|
|
7
|
-
let running = false;
|
|
8
|
-
let lastProcessedAt = null;
|
|
9
|
-
function getQueueDepth() {
|
|
10
|
-
const db = getDb();
|
|
11
|
-
const row = db.prepare('SELECT COUNT(*) AS n FROM chunk_queue').get();
|
|
12
|
-
return row.n;
|
|
13
|
-
}
|
|
14
|
-
async function processNextSession() {
|
|
15
|
-
const db = getDb();
|
|
16
|
-
const next = db.prepare('SELECT DISTINCT session_id FROM chunk_queue ORDER BY id LIMIT 1').get();
|
|
17
|
-
if (!next)
|
|
18
|
-
return false;
|
|
19
|
-
const sessionId = next.session_id;
|
|
20
|
-
try {
|
|
21
|
-
db.prepare('DELETE FROM vec_chunks WHERE rowid IN (SELECT rowid FROM chunk_meta WHERE session_id = ?)').run(sessionId);
|
|
22
|
-
db.prepare('DELETE FROM chunk_meta WHERE session_id = ?').run(sessionId);
|
|
23
|
-
const chunks = chunkSession(sessionId);
|
|
24
|
-
if (chunks.length === 0) {
|
|
25
|
-
db.prepare('DELETE FROM chunk_queue WHERE session_id = ?').run(sessionId);
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
const texts = chunks.map((c) => c.text);
|
|
29
|
-
const embeddings = await embed(texts);
|
|
30
|
-
const insertMeta = db.prepare(`INSERT INTO chunk_meta(session_id, message_uuids, text, embedding_model_id, embedding_dim, stale, generated_at) VALUES (?, ?, ?, 'bge-base-en-v1.5', 768, 0, datetime('now'))`);
|
|
31
|
-
const insertVec = db.prepare('INSERT INTO vec_chunks(rowid, embedding) VALUES (?, ?)');
|
|
32
|
-
const writeTx = db.transaction(() => {
|
|
33
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
34
|
-
const info = insertMeta.run(sessionId, JSON.stringify(chunks[i].messageUuids), chunks[i].text);
|
|
35
|
-
const buf = Buffer.from(embeddings[i].buffer, embeddings[i].byteOffset, embeddings[i].byteLength);
|
|
36
|
-
insertVec.run(info.lastInsertRowid, buf);
|
|
37
|
-
}
|
|
38
|
-
db.prepare('DELETE FROM chunk_queue WHERE session_id = ?').run(sessionId);
|
|
39
|
-
});
|
|
40
|
-
writeTx();
|
|
41
|
-
lastProcessedAt = new Date().toISOString();
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
console.error('[vector-worker] failed for session', sessionId, err);
|
|
45
|
-
db.prepare('DELETE FROM chunk_queue WHERE session_id = ?').run(sessionId);
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
async function tick() {
|
|
50
|
-
if (!getEmbedderStatus().loaded)
|
|
51
|
-
return;
|
|
52
|
-
const hadWork = await processNextSession();
|
|
53
|
-
if (intervalId !== null)
|
|
54
|
-
clearTimeout(intervalId);
|
|
55
|
-
const delay = hadWork ? POLL_ACTIVE_MS : POLL_IDLE_MS;
|
|
56
|
-
intervalId = setTimeout(() => void tick(), delay);
|
|
57
|
-
}
|
|
58
|
-
export function startWorker() {
|
|
59
|
-
if (running)
|
|
60
|
-
return;
|
|
61
|
-
if (!getEmbedderStatus().loaded) {
|
|
62
|
-
console.error('[vector-worker] cannot start: embedder not loaded');
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
running = true;
|
|
66
|
-
intervalId = setTimeout(() => void tick(), POLL_ACTIVE_MS);
|
|
67
|
-
}
|
|
68
|
-
export function stopWorker() {
|
|
69
|
-
running = false;
|
|
70
|
-
if (intervalId !== null) {
|
|
71
|
-
clearTimeout(intervalId);
|
|
72
|
-
intervalId = null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
export function getWorkerStatus() {
|
|
76
|
-
return { running, queueDepth: getQueueDepth(), lastProcessedAt };
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=worker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/semantic/worker.ts"],"names":[],"mappings":"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"}
|