@clauderecallhq/cli 0.0.1 → 0.11.0
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 +33 -0
- package/README.md +543 -3
- package/README.public.md +523 -0
- package/dist/cli.js +354 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/activate.js +69 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/audit-secrets.js +103 -0
- package/dist/commands/audit-secrets.js.map +1 -0
- package/dist/commands/blame.js +35 -0
- package/dist/commands/blame.js.map +1 -0
- package/dist/commands/config-verification.js +18 -0
- package/dist/commands/config-verification.js.map +1 -0
- package/dist/commands/context.js +144 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/correlate.js +70 -0
- package/dist/commands/correlate.js.map +1 -0
- package/dist/commands/digest.js +78 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/health.js +62 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/index.js +247 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/install-extension.js +138 -0
- package/dist/commands/install-extension.js.map +1 -0
- package/dist/commands/license.js +39 -0
- package/dist/commands/license.js.map +1 -0
- package/dist/commands/list.js +47 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/mcp.js +29 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/open.js +28 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/paste.js +154 -0
- package/dist/commands/paste.js.map +1 -0
- package/dist/commands/projects.js +36 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/search.js +67 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/semantic.js +173 -0
- package/dist/commands/semantic.js.map +1 -0
- package/dist/commands/show.js +121 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/start.js +47 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/stats.js +133 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/status.js +45 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.js +29 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/thread.js +396 -0
- package/dist/commands/thread.js.map +1 -0
- package/dist/context/formatter.js +103 -0
- package/dist/context/formatter.js.map +1 -0
- package/dist/daemon/auto-tag-config.js +103 -0
- package/dist/daemon/auto-tag-config.js.map +1 -0
- package/dist/daemon/auto-tag-config.test.js +72 -0
- package/dist/daemon/auto-tag-config.test.js.map +1 -0
- package/dist/daemon/auto-title-config.js +70 -0
- package/dist/daemon/auto-title-config.js.map +1 -0
- package/dist/daemon/bulk-title-jobs.js +170 -0
- package/dist/daemon/bulk-title-jobs.js.map +1 -0
- package/dist/daemon/correlator.js +320 -0
- package/dist/daemon/correlator.js.map +1 -0
- package/dist/daemon/discover.js +316 -0
- package/dist/daemon/discover.js.map +1 -0
- package/dist/daemon/editor-detection.js +186 -0
- package/dist/daemon/editor-detection.js.map +1 -0
- package/dist/daemon/entrypoint.js +55 -0
- package/dist/daemon/entrypoint.js.map +1 -0
- package/dist/daemon/git-correlator.js +256 -0
- package/dist/daemon/git-correlator.js.map +1 -0
- package/dist/daemon/mcp-installer.js +108 -0
- package/dist/daemon/mcp-installer.js.map +1 -0
- package/dist/daemon/onboarding-state.js +140 -0
- package/dist/daemon/onboarding-state.js.map +1 -0
- package/dist/daemon/pidfile.js +57 -0
- package/dist/daemon/pidfile.js.map +1 -0
- package/dist/daemon/ports.js +48 -0
- package/dist/daemon/ports.js.map +1 -0
- package/dist/daemon/scanProgressRegistry.js +62 -0
- package/dist/daemon/scanProgressRegistry.js.map +1 -0
- package/dist/daemon/server.js +2010 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/tag-scanner/anthropic-client.js +40 -0
- package/dist/daemon/tag-scanner/anthropic-client.js.map +1 -0
- package/dist/daemon/tag-scanner/autopilot.js +131 -0
- package/dist/daemon/tag-scanner/autopilot.js.map +1 -0
- package/dist/daemon/tag-scanner/claude-cli-driver.js +250 -0
- package/dist/daemon/tag-scanner/claude-cli-driver.js.map +1 -0
- package/dist/daemon/tag-scanner/orchestrator.js +88 -0
- package/dist/daemon/tag-scanner/orchestrator.js.map +1 -0
- package/dist/daemon/tag-scanner/prompt.js +46 -0
- package/dist/daemon/tag-scanner/prompt.js.map +1 -0
- package/dist/daemon/tag-scanner/prompt.test.js +48 -0
- package/dist/daemon/tag-scanner/prompt.test.js.map +1 -0
- package/dist/daemon/tag-scanner/scan-state.js +49 -0
- package/dist/daemon/tag-scanner/scan-state.js.map +1 -0
- package/dist/daemon/tag-scanner/session-fetcher.js +82 -0
- package/dist/daemon/tag-scanner/session-fetcher.js.map +1 -0
- package/dist/daemon/tag-scanner/session-fetcher.test.js +34 -0
- package/dist/daemon/tag-scanner/session-fetcher.test.js.map +1 -0
- package/dist/daemon/tag-scanner/validator.js +50 -0
- package/dist/daemon/tag-scanner/validator.js.map +1 -0
- package/dist/daemon/tag-scanner/validator.test.js +41 -0
- package/dist/daemon/tag-scanner/validator.test.js.map +1 -0
- package/dist/daemon/terminal-registry.js +443 -0
- package/dist/daemon/terminal-registry.js.map +1 -0
- package/dist/daemon/ui.js +64 -0
- package/dist/daemon/ui.js.map +1 -0
- package/dist/daemon/watcher.js +256 -0
- package/dist/daemon/watcher.js.map +1 -0
- package/dist/db/client.js +22 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/schema.js +496 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/license/api-base.js +13 -0
- package/dist/license/api-base.js.map +1 -0
- package/dist/license/manager.js +43 -0
- package/dist/license/manager.js.map +1 -0
- package/dist/license/public-key.js +19 -0
- package/dist/license/public-key.js.map +1 -0
- package/dist/license/storage.js +27 -0
- package/dist/license/storage.js.map +1 -0
- package/dist/license/verify.js +23 -0
- package/dist/license/verify.js.map +1 -0
- package/dist/mcp/audit.js +126 -0
- package/dist/mcp/audit.js.map +1 -0
- package/dist/mcp/prompts.js +180 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/server.js +502 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/thread-tools.js +363 -0
- package/dist/mcp/thread-tools.js.map +1 -0
- package/dist/mcp/write-tools.js +239 -0
- package/dist/mcp/write-tools.js.map +1 -0
- package/dist/parser/jsonl.js +150 -0
- package/dist/parser/jsonl.js.map +1 -0
- package/dist/semantic/chunker.js +47 -0
- package/dist/semantic/chunker.js.map +1 -0
- package/dist/semantic/config.js +74 -0
- package/dist/semantic/config.js.map +1 -0
- package/dist/semantic/embedder.js +54 -0
- package/dist/semantic/embedder.js.map +1 -0
- package/dist/semantic/fusion.js +38 -0
- package/dist/semantic/fusion.js.map +1 -0
- package/dist/semantic/model-download.js +69 -0
- package/dist/semantic/model-download.js.map +1 -0
- package/dist/semantic/pipeline.js +375 -0
- package/dist/semantic/pipeline.js.map +1 -0
- package/dist/semantic/query.js +42 -0
- package/dist/semantic/query.js.map +1 -0
- package/dist/semantic/worker.js +78 -0
- package/dist/semantic/worker.js.map +1 -0
- package/dist/stats/backfill.js +151 -0
- package/dist/stats/backfill.js.map +1 -0
- package/dist/stats/health.js +102 -0
- package/dist/stats/health.js.map +1 -0
- package/dist/stats/query.js +385 -0
- package/dist/stats/query.js.map +1 -0
- package/dist/utils/aliases.js +107 -0
- package/dist/utils/aliases.js.map +1 -0
- package/dist/utils/autoCollections.js +635 -0
- package/dist/utils/autoCollections.js.map +1 -0
- package/dist/utils/autoTitle.js +348 -0
- package/dist/utils/autoTitle.js.map +1 -0
- package/dist/utils/collections.js +446 -0
- package/dist/utils/collections.js.map +1 -0
- package/dist/utils/format.js +46 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/notes.js +270 -0
- package/dist/utils/notes.js.map +1 -0
- package/dist/utils/paths.js +50 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/pricing.js +257 -0
- package/dist/utils/pricing.js.map +1 -0
- package/dist/utils/secret-scanner.js +166 -0
- package/dist/utils/secret-scanner.js.map +1 -0
- package/dist/utils/sessionLabel.js +64 -0
- package/dist/utils/sessionLabel.js.map +1 -0
- package/dist/utils/tags.js +97 -0
- package/dist/utils/tags.js.map +1 -0
- package/dist/utils/thread-context.js +129 -0
- package/dist/utils/thread-context.js.map +1 -0
- package/dist/utils/threadFilter.js +18 -0
- package/dist/utils/threadFilter.js.map +1 -0
- package/dist/utils/threads-titler.js +298 -0
- package/dist/utils/threads-titler.js.map +1 -0
- package/dist/utils/threads.js +383 -0
- package/dist/utils/threads.js.map +1 -0
- package/dist/utils/usage.js +76 -0
- package/dist/utils/usage.js.map +1 -0
- package/dist/verification/compute.js +88 -0
- package/dist/verification/compute.js.map +1 -0
- package/dist/verification/config.js +34 -0
- package/dist/verification/config.js.map +1 -0
- package/dist/web/assets/index-CIr6J4Fw.js +1201 -0
- package/dist/web/assets/index-Ctc8g9Jw.css +1 -0
- package/dist/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
- package/dist/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
- package/dist/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
- package/dist/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-700-normal-CjBOestx.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-700-normal-DrXBdSj3.woff +0 -0
- package/dist/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
- package/dist/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
- package/dist/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
- package/dist/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-ext-700-normal-BjwYoWNd.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-ext-700-normal-LO58E6JB.woff +0 -0
- package/dist/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
- package/dist/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
- package/dist/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
- package/dist/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
- package/dist/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
- package/dist/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
- package/dist/web/assets/inter-greek-700-normal-BUv2fZ6O.woff +0 -0
- package/dist/web/assets/inter-greek-700-normal-C3JjAnD8.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
- package/dist/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
- package/dist/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
- package/dist/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-700-normal-BoQ6DsYi.woff +0 -0
- package/dist/web/assets/inter-greek-ext-700-normal-qfdV9bQt.woff2 +0 -0
- package/dist/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/dist/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
- package/dist/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
- package/dist/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/dist/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
- package/dist/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
- package/dist/web/assets/inter-latin-700-normal-BLAVimhd.woff +0 -0
- package/dist/web/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
- package/dist/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
- package/dist/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
- package/dist/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-700-normal-Ca8adRJv.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-700-normal-TidjK2hL.woff +0 -0
- package/dist/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
- package/dist/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
- package/dist/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
- package/dist/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-700-normal-BZaoP0fm.woff +0 -0
- package/dist/web/assets/inter-vietnamese-700-normal-DlLaEgI2.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/dist/web/favicon.svg +9 -0
- package/dist/web/index.html +15 -0
- package/package.json +79 -9
- package/bin/cli.js +0 -12
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getDb } from '../db/client.js';
|
|
4
|
+
import { RECALL_HOME, ensureRecallHome } from './paths.js';
|
|
5
|
+
import { getThreadContextForSession, } from './thread-context.js';
|
|
6
|
+
/**
|
|
7
|
+
* v0.14b (T5) — derived session titles.
|
|
8
|
+
*
|
|
9
|
+
* Two tiers, same append-only "never lose data" guarantees as aliases/notes:
|
|
10
|
+
*
|
|
11
|
+
* 1. `deriveHeuristicTitle(firstUserMessage)` — pure, sync. Stripped of
|
|
12
|
+
* code fences / inline backticks / URLs, whitespace normalised, first
|
|
13
|
+
* sentence if it fits, else a 60-char slice. Called from the indexer on
|
|
14
|
+
* every session insert.
|
|
15
|
+
*
|
|
16
|
+
* 2. `deriveAgentTitle(sessionId)` — shells out to the user's
|
|
17
|
+
* local `claude` CLI (same plumbing as auto-tag) with a summarisation
|
|
18
|
+
* prompt over the first 20 user messages. Opt-in via the ✨ Generate
|
|
19
|
+
* title button in the transcript header.
|
|
20
|
+
*
|
|
21
|
+
* Durability — three layers, identical to the alias module:
|
|
22
|
+
*
|
|
23
|
+
* 1. SQLite: `auto_title`, `auto_title_source`, `auto_title_generated_at`.
|
|
24
|
+
* 2. SQLite history column: `auto_title_history` (JSON array of prior
|
|
25
|
+
* values; every replacement pushes a row, we never lose one).
|
|
26
|
+
* 3. Plain-text mirror: `$RECALL_HOME/titles/<sessionId>.txt` — grep-able,
|
|
27
|
+
* recoverable from disk even if the SQLite file is wiped.
|
|
28
|
+
*
|
|
29
|
+
* Demotion protection: a `source='heuristic'` write is a no-op if the existing
|
|
30
|
+
* row is `source='agent'`. Rationale — the indexer fires heuristic on every
|
|
31
|
+
* reindex of a session file; without this guard, every reindex of an agent-
|
|
32
|
+
* titled session would clobber the user's explicit ✨ Generate choice.
|
|
33
|
+
*
|
|
34
|
+
* Fallback chain (consumers): `alias → auto_title → first_user_message →
|
|
35
|
+
* id.slice(0,8)`. Manual alias always wins.
|
|
36
|
+
*/
|
|
37
|
+
export const TITLES_DIR = join(RECALL_HOME, 'titles');
|
|
38
|
+
const HEURISTIC_SENTENCE_MAX = 80;
|
|
39
|
+
const HEURISTIC_SLICE_MAX = 60;
|
|
40
|
+
const AGENT_TITLE_MAX = 50;
|
|
41
|
+
// We sample the conversation as `head + tail` rather than just the first N
|
|
42
|
+
// messages so the title reflects BOTH initial intent AND current direction.
|
|
43
|
+
// Sessions where the user pasted off-topic context first (logs, errors from
|
|
44
|
+
// another session) used to produce wildly off-topic titles; with a tail
|
|
45
|
+
// included, the model sees what the conversation actually became.
|
|
46
|
+
const AGENT_HEAD_LIMIT = 5;
|
|
47
|
+
const AGENT_TAIL_LIMIT = 15;
|
|
48
|
+
const AGENT_PER_MESSAGE_CHAR_LIMIT = 500;
|
|
49
|
+
function parseHistory(raw) {
|
|
50
|
+
if (!raw)
|
|
51
|
+
return [];
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (Array.isArray(parsed)) {
|
|
55
|
+
return parsed.filter((e) => !!e &&
|
|
56
|
+
typeof e === 'object' &&
|
|
57
|
+
typeof e.title === 'string' &&
|
|
58
|
+
typeof e.replaced_at === 'string');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
/* fall through */
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Clean up a first-user-message into a ≤80-char title.
|
|
68
|
+
* Deterministic and synchronous — runs on every indexer insert.
|
|
69
|
+
*/
|
|
70
|
+
export function deriveHeuristicTitle(msg) {
|
|
71
|
+
if (!msg)
|
|
72
|
+
return null;
|
|
73
|
+
let t = msg;
|
|
74
|
+
// Strip fenced code blocks, then inline code. Order matters — triple
|
|
75
|
+
// backticks would otherwise match as nested inline pairs.
|
|
76
|
+
t = t.replace(/```[\s\S]*?```/g, ' ');
|
|
77
|
+
t = t.replace(/`[^`]+`/g, ' ');
|
|
78
|
+
// Replace URLs with a short placeholder so "see https://…foo?x=y" doesn't
|
|
79
|
+
// dominate a title.
|
|
80
|
+
t = t.replace(/https?:\/\/\S+/g, '[url]');
|
|
81
|
+
t = t.replace(/\s+/g, ' ').trim();
|
|
82
|
+
if (!t)
|
|
83
|
+
return null;
|
|
84
|
+
const firstSentence = t.match(/^[^.!?\n]{8,}?[.!?]/)?.[0]?.trim();
|
|
85
|
+
const cut = firstSentence && firstSentence.length <= HEURISTIC_SENTENCE_MAX
|
|
86
|
+
? firstSentence
|
|
87
|
+
: t.slice(0, HEURISTIC_SLICE_MAX);
|
|
88
|
+
const out = cut.trim();
|
|
89
|
+
return out || null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build the prompt that `deriveAgentTitle` sends to the local `claude` CLI.
|
|
93
|
+
* Exported so unit tests can assert on the constructed text without invoking
|
|
94
|
+
* the subprocess.
|
|
95
|
+
*
|
|
96
|
+
* Bucket 2: when the session belongs to a thread, a "Thread context" preamble
|
|
97
|
+
* is prepended with the parent + sibling display titles so the model can mint
|
|
98
|
+
* a hierarchy-aware title (for example "Phase A: API design"). Sessions in
|
|
99
|
+
* zero threads get the existing single-session prompt verbatim. Thread-context
|
|
100
|
+
* resolution is wrapped in try/catch so that any DB hiccup never blocks title
|
|
101
|
+
* generation: we log and fall back to the no-context prompt.
|
|
102
|
+
*/
|
|
103
|
+
export function buildAgentTitlePrompt(sessionId) {
|
|
104
|
+
const db = getDb();
|
|
105
|
+
// Two queries to avoid loading every message into Node when sessions have
|
|
106
|
+
// thousands. Head = first N chronologically; tail = last M. Dedupe by rowid
|
|
107
|
+
// so short sessions (<head+tail) don't double-count, then re-sort
|
|
108
|
+
// chronologically before sending to the model.
|
|
109
|
+
const head = db
|
|
110
|
+
.prepare(`SELECT rowid AS rid, content_text
|
|
111
|
+
FROM messages
|
|
112
|
+
WHERE session_id = ? AND role = 'user' AND is_sidechain = 0
|
|
113
|
+
AND content_text IS NOT NULL AND content_text != ''
|
|
114
|
+
ORDER BY COALESCE(timestamp, ''), rowid ASC
|
|
115
|
+
LIMIT ?`)
|
|
116
|
+
.all(sessionId, AGENT_HEAD_LIMIT);
|
|
117
|
+
const tail = db
|
|
118
|
+
.prepare(`SELECT rowid AS rid, content_text
|
|
119
|
+
FROM messages
|
|
120
|
+
WHERE session_id = ? AND role = 'user' AND is_sidechain = 0
|
|
121
|
+
AND content_text IS NOT NULL AND content_text != ''
|
|
122
|
+
ORDER BY COALESCE(timestamp, '') DESC, rowid DESC
|
|
123
|
+
LIMIT ?`)
|
|
124
|
+
.all(sessionId, AGENT_TAIL_LIMIT);
|
|
125
|
+
const byRid = new Map();
|
|
126
|
+
for (const r of head)
|
|
127
|
+
byRid.set(r.rid, r.content_text);
|
|
128
|
+
for (const r of tail)
|
|
129
|
+
byRid.set(r.rid, r.content_text);
|
|
130
|
+
if (byRid.size === 0) {
|
|
131
|
+
throw new Error('no user messages available to summarise');
|
|
132
|
+
}
|
|
133
|
+
const rows = Array.from(byRid.entries())
|
|
134
|
+
.sort((a, b) => a[0] - b[0])
|
|
135
|
+
.map(([, content_text]) => ({ content_text }));
|
|
136
|
+
// Mark the conversational gap so the model knows it's seeing a sample,
|
|
137
|
+
// not a continuous stream. Only insert the marker when both head and tail
|
|
138
|
+
// were saturated AND there's at least one message between them not in the
|
|
139
|
+
// sample (i.e. byRid.size === HEAD + TAIL with no overlap).
|
|
140
|
+
const hasGap = head.length === AGENT_HEAD_LIMIT &&
|
|
141
|
+
tail.length === AGENT_TAIL_LIMIT &&
|
|
142
|
+
byRid.size === AGENT_HEAD_LIMIT + AGENT_TAIL_LIMIT;
|
|
143
|
+
const body = rows
|
|
144
|
+
.map((r, i) => {
|
|
145
|
+
const content = (r.content_text ?? '').slice(0, AGENT_PER_MESSAGE_CHAR_LIMIT);
|
|
146
|
+
if (hasGap && i === AGENT_HEAD_LIMIT) {
|
|
147
|
+
return `--- (middle of session omitted) ---\n${i + 1}. ${content}`;
|
|
148
|
+
}
|
|
149
|
+
return `${i + 1}. ${content}`;
|
|
150
|
+
})
|
|
151
|
+
.join('\n');
|
|
152
|
+
let threadContext = null;
|
|
153
|
+
try {
|
|
154
|
+
threadContext = getThreadContextForSession(sessionId);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
// Per the spec: do not block title generation if thread context resolution
|
|
158
|
+
// throws. Log and continue with the no-context prompt.
|
|
159
|
+
console.error('[autoTitle] thread context resolution failed:', err);
|
|
160
|
+
threadContext = null;
|
|
161
|
+
}
|
|
162
|
+
const sections = [];
|
|
163
|
+
if (threadContext) {
|
|
164
|
+
sections.push(formatThreadContextBlock(threadContext));
|
|
165
|
+
sections.push('');
|
|
166
|
+
}
|
|
167
|
+
sections.push(`You will receive a sample of user messages from a Claude Code session: the first ${AGENT_HEAD_LIMIT}`, `messages (initial intent) and the last ${AGENT_TAIL_LIMIT} messages (current direction).`, 'Write a single descriptive title, max 50 characters, focused on what the user is', 'currently trying to accomplish. If initial intent and current direction differ, prefer', 'the current direction. Output ONLY the title, with no quotes and no trailing punctuation.', '', 'Messages:', body);
|
|
168
|
+
return sections.join('\n');
|
|
169
|
+
}
|
|
170
|
+
const SIBLING_DISPLAY_LIMIT = 5;
|
|
171
|
+
function formatThreadContextBlock(ctx) {
|
|
172
|
+
const lines = [];
|
|
173
|
+
lines.push('Thread context:');
|
|
174
|
+
lines.push(`- This session is part of thread "${ctx.thread_name}".`);
|
|
175
|
+
if (ctx.parent_session) {
|
|
176
|
+
lines.push(`- Parent session: "${ctx.parent_session.title}"`);
|
|
177
|
+
}
|
|
178
|
+
const sibCount = ctx.siblings.length;
|
|
179
|
+
if (sibCount > 0) {
|
|
180
|
+
const shown = ctx.siblings.slice(0, SIBLING_DISPLAY_LIMIT);
|
|
181
|
+
const titles = shown.map((s) => `"${s.title}"`).join(', ');
|
|
182
|
+
const overflow = sibCount > SIBLING_DISPLAY_LIMIT
|
|
183
|
+
? `, and ${sibCount - SIBLING_DISPLAY_LIMIT} more`
|
|
184
|
+
: '';
|
|
185
|
+
lines.push(`- Sibling sessions (${sibCount}): ${titles}${overflow}`);
|
|
186
|
+
}
|
|
187
|
+
lines.push('');
|
|
188
|
+
lines.push("Generate a title that reflects this session's role in the thread.");
|
|
189
|
+
lines.push('If siblings use a pattern like "Phase A / Phase B" or "Wave 1 of 4",');
|
|
190
|
+
lines.push('follow the same pattern.');
|
|
191
|
+
return lines.join('\n');
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Run the user's local `claude` CLI over the first 20 user messages and
|
|
195
|
+
* return a ≤50-char descriptive title. Throws if the CLI is unavailable
|
|
196
|
+
* or exits non-zero. Callers are expected to have already checked the
|
|
197
|
+
* `autoTitle.agentEnabled` config flag.
|
|
198
|
+
*
|
|
199
|
+
* The runner is imported lazily so that headless consumers of autoTitle
|
|
200
|
+
* (tests, the MCP server) don't pay the daemon-only import cost.
|
|
201
|
+
*/
|
|
202
|
+
export async function deriveAgentTitle(sessionId) {
|
|
203
|
+
const prompt = buildAgentTitlePrompt(sessionId);
|
|
204
|
+
const { spawnClaudePrompt, isClaudeCliAvailable } = await import('../daemon/tag-scanner/claude-cli-driver.js');
|
|
205
|
+
if (!isClaudeCliAvailable()) {
|
|
206
|
+
throw new Error('claude CLI not found on PATH');
|
|
207
|
+
}
|
|
208
|
+
// No MCP tools, this is a one-shot text-only summarisation, no DB writes.
|
|
209
|
+
const result = await spawnClaudePrompt(prompt, [], {});
|
|
210
|
+
if (!result.success) {
|
|
211
|
+
throw new Error(`claude CLI exited ${result.exitCode}: ${result.stderr.slice(-500)}`);
|
|
212
|
+
}
|
|
213
|
+
const title = extractTitleFromCliResult(result.stdout);
|
|
214
|
+
if (!title)
|
|
215
|
+
throw new Error('claude CLI returned an empty title');
|
|
216
|
+
return title.slice(0, AGENT_TITLE_MAX);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* `claude -p … --output-format json` emits a JSON envelope with a `result`
|
|
220
|
+
* string. Plain-text output is just the raw title. We accept both.
|
|
221
|
+
*/
|
|
222
|
+
function extractTitleFromCliResult(stdout) {
|
|
223
|
+
const trimmed = stdout.trim();
|
|
224
|
+
if (!trimmed)
|
|
225
|
+
return '';
|
|
226
|
+
try {
|
|
227
|
+
const parsed = JSON.parse(trimmed);
|
|
228
|
+
if (parsed && typeof parsed === 'object') {
|
|
229
|
+
const result = parsed.result;
|
|
230
|
+
if (typeof result === 'string')
|
|
231
|
+
return sanitiseTitle(result);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
/* not JSON — fall through to raw */
|
|
236
|
+
}
|
|
237
|
+
return sanitiseTitle(trimmed);
|
|
238
|
+
}
|
|
239
|
+
function sanitiseTitle(raw) {
|
|
240
|
+
return raw
|
|
241
|
+
.trim()
|
|
242
|
+
// Strip paired wrapping quotes the model sometimes adds despite the prompt.
|
|
243
|
+
.replace(/^["'`]+|["'`]+$/g, '')
|
|
244
|
+
// Collapse internal whitespace + drop trailing punctuation.
|
|
245
|
+
.replace(/\s+/g, ' ')
|
|
246
|
+
.replace(/[.!?]+$/g, '')
|
|
247
|
+
.trim();
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Triple-layer write. Demotion-guarded: a heuristic write never clobbers an
|
|
251
|
+
* existing agent title. Idempotent — writing the same title twice is a no-op.
|
|
252
|
+
*/
|
|
253
|
+
export function setAutoTitle(sessionId, title, source) {
|
|
254
|
+
const trimmed = title.trim();
|
|
255
|
+
if (!trimmed)
|
|
256
|
+
return;
|
|
257
|
+
const db = getDb();
|
|
258
|
+
const existing = db
|
|
259
|
+
.prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
|
|
260
|
+
FROM sessions WHERE id = ?`)
|
|
261
|
+
.get(sessionId);
|
|
262
|
+
if (!existing)
|
|
263
|
+
return; // session not yet indexed; caller races with indexer
|
|
264
|
+
// Demotion guard: heuristic never overwrites an agent title. Reindex fires
|
|
265
|
+
// on every file mtime bump; without this the user's explicit ✨ choice
|
|
266
|
+
// would silently regress every time Claude Code appends a new line.
|
|
267
|
+
if (source === 'heuristic' &&
|
|
268
|
+
existing.auto_title_source === 'agent' &&
|
|
269
|
+
existing.auto_title) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// Idempotent: same title, same source → no write, no history push.
|
|
273
|
+
if (existing.auto_title === trimmed && existing.auto_title_source === source) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const history = parseHistory(existing.auto_title_history);
|
|
277
|
+
const now = new Date().toISOString();
|
|
278
|
+
if (existing.auto_title && existing.auto_title_source) {
|
|
279
|
+
history.push({
|
|
280
|
+
title: existing.auto_title,
|
|
281
|
+
source: existing.auto_title_source,
|
|
282
|
+
replaced_at: now,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
db.prepare(`UPDATE sessions
|
|
286
|
+
SET auto_title = ?,
|
|
287
|
+
auto_title_source = ?,
|
|
288
|
+
auto_title_generated_at = ?,
|
|
289
|
+
auto_title_history = ?
|
|
290
|
+
WHERE id = ?`).run(trimmed, source, Date.now(), JSON.stringify(history), sessionId);
|
|
291
|
+
writeTitleFile(sessionId, trimmed, source, now);
|
|
292
|
+
}
|
|
293
|
+
export function getAutoTitle(sessionId) {
|
|
294
|
+
const row = getDb()
|
|
295
|
+
.prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
|
|
296
|
+
FROM sessions WHERE id = ?`)
|
|
297
|
+
.get(sessionId);
|
|
298
|
+
if (!row)
|
|
299
|
+
return null;
|
|
300
|
+
return {
|
|
301
|
+
auto_title: row.auto_title,
|
|
302
|
+
auto_title_source: row.auto_title_source ?? null,
|
|
303
|
+
auto_title_generated_at: row.auto_title_generated_at,
|
|
304
|
+
auto_title_history: parseHistory(row.auto_title_history),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* One-time startup backfill: fill heuristic titles for every session whose
|
|
309
|
+
* `auto_title` is NULL and `first_user_message` is present. Cheap to re-run
|
|
310
|
+
* on every daemon boot — the NULL check keeps it idempotent after the first
|
|
311
|
+
* pass. Intentionally synchronous; the sessions table is small and this runs
|
|
312
|
+
* before we start servicing HTTP.
|
|
313
|
+
*/
|
|
314
|
+
export function backfillHeuristicTitles() {
|
|
315
|
+
const db = getDb();
|
|
316
|
+
const rows = db
|
|
317
|
+
.prepare(`SELECT id, first_user_message
|
|
318
|
+
FROM sessions
|
|
319
|
+
WHERE auto_title IS NULL
|
|
320
|
+
AND first_user_message IS NOT NULL`)
|
|
321
|
+
.all();
|
|
322
|
+
let updated = 0;
|
|
323
|
+
for (const r of rows) {
|
|
324
|
+
const title = deriveHeuristicTitle(r.first_user_message);
|
|
325
|
+
if (!title)
|
|
326
|
+
continue;
|
|
327
|
+
setAutoTitle(r.id, title, 'heuristic');
|
|
328
|
+
updated += 1;
|
|
329
|
+
}
|
|
330
|
+
return { updated };
|
|
331
|
+
}
|
|
332
|
+
function ensureTitlesDir() {
|
|
333
|
+
ensureRecallHome();
|
|
334
|
+
if (!existsSync(TITLES_DIR))
|
|
335
|
+
mkdirSync(TITLES_DIR, { recursive: true });
|
|
336
|
+
}
|
|
337
|
+
function writeTitleFile(sessionId, title, source, updatedAt) {
|
|
338
|
+
try {
|
|
339
|
+
ensureTitlesDir();
|
|
340
|
+
const filePath = join(TITLES_DIR, `${sessionId}.txt`);
|
|
341
|
+
const header = `# Claude Recall auto-title · session ${sessionId} · source ${source} · updated ${updatedAt}\n`;
|
|
342
|
+
writeFileSync(filePath, header + title + '\n');
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
console.error('[autoTitle] mirror write failed:', err);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=autoTitle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoTitle.js","sourceRoot":"","sources":["../../src/utils/autoTitle.ts"],"names":[],"mappings":"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"}
|