@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,298 @@
|
|
|
1
|
+
import { getThread } from './threads.js';
|
|
2
|
+
import { buildAgentTitlePrompt, setAutoTitle, getAutoTitle, } from './autoTitle.js';
|
|
3
|
+
/**
|
|
4
|
+
* v0.7 Bucket 5 - bulk thread title generation.
|
|
5
|
+
*
|
|
6
|
+
* One-click generation of coherent titles for an entire thread. Walks the
|
|
7
|
+
* thread DAG in topology order (origins first by `added_at`, then children
|
|
8
|
+
* breadth-first per origin), generates the parent title first, then each
|
|
9
|
+
* child sees the already-titled ancestors and earlier siblings as STRONG
|
|
10
|
+
* context (not weak). Uses a directive prompt that tells Claude to identify
|
|
11
|
+
* or invent a naming pattern; see `buildBulkTitlePrompt`.
|
|
12
|
+
*
|
|
13
|
+
* Reuses `setAutoTitle` for writes so the three-layer durability
|
|
14
|
+
* (SQLite row + history column + plain-text mirror) is inherited verbatim.
|
|
15
|
+
*
|
|
16
|
+
* Operator words 2026-04-25: "It's got to be silly proof. One click, the
|
|
17
|
+
* whole thing titled." Per-session failures DO NOT abort the walk: every
|
|
18
|
+
* failure is captured in `failed[]` so the user can retry the bad ones
|
|
19
|
+
* without losing the good ones.
|
|
20
|
+
*
|
|
21
|
+
* Cancellation: callers pass an AbortSignal. The walker checks it BEFORE
|
|
22
|
+
* each session's claude-cli spawn. Already-generated titles stay (recoverable
|
|
23
|
+
* via `auto_title_history` if the user dislikes the result). The signal is
|
|
24
|
+
* read on the loop boundary, not threaded into the subprocess: the running
|
|
25
|
+
* spawn finishes naturally before the next iteration is skipped.
|
|
26
|
+
*/
|
|
27
|
+
const AGENT_TITLE_MAX = 50;
|
|
28
|
+
/**
|
|
29
|
+
* Walk a thread's edges in DAG topology order:
|
|
30
|
+
* 1. Origins first, ordered by `added_at` ascending (oldest origin wins
|
|
31
|
+
* so a deterministic order is reproducible across runs).
|
|
32
|
+
* 2. Then children, breadth-first per origin: for each origin, every
|
|
33
|
+
* session whose `parent_session_id` is the origin, then every session
|
|
34
|
+
* whose parent is one of those, etc.
|
|
35
|
+
*
|
|
36
|
+
* Pure helper. Exported for unit tests so the walker can be asserted in
|
|
37
|
+
* isolation without spawning claude-cli.
|
|
38
|
+
*
|
|
39
|
+
* If a thread has no origins (every edge is a child with a parent_session_id
|
|
40
|
+
* that does not appear as another edge's session_id), we treat the parentless
|
|
41
|
+
* children as effective origins so the walker still terminates and visits
|
|
42
|
+
* every session. Defensive: real threads always have at least one origin.
|
|
43
|
+
*/
|
|
44
|
+
export function walkThreadInTopologyOrder(threadId) {
|
|
45
|
+
const detail = getThread(threadId);
|
|
46
|
+
if (!detail)
|
|
47
|
+
return [];
|
|
48
|
+
return walkEdgesInTopologyOrder(detail.edges);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Internal helper exposed via `walkThreadInTopologyOrder` for tests; also
|
|
52
|
+
* reused by `generateThreadTitles` so it does not re-fetch the thread.
|
|
53
|
+
*/
|
|
54
|
+
export function walkEdgesInTopologyOrder(edges) {
|
|
55
|
+
if (edges.length === 0)
|
|
56
|
+
return [];
|
|
57
|
+
const sortedByAddedAt = [...edges].sort((a, b) => {
|
|
58
|
+
if (a.added_at < b.added_at)
|
|
59
|
+
return -1;
|
|
60
|
+
if (a.added_at > b.added_at)
|
|
61
|
+
return 1;
|
|
62
|
+
return 0;
|
|
63
|
+
});
|
|
64
|
+
const childrenByParent = new Map();
|
|
65
|
+
const visited = new Set();
|
|
66
|
+
const order = [];
|
|
67
|
+
for (const e of sortedByAddedAt) {
|
|
68
|
+
if (e.parent_session_id) {
|
|
69
|
+
const list = childrenByParent.get(e.parent_session_id) ?? [];
|
|
70
|
+
list.push(e);
|
|
71
|
+
childrenByParent.set(e.parent_session_id, list);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// First wave: origins by added_at. Defensive: if no origin role is set
|
|
75
|
+
// anywhere, treat every parentless edge as an effective origin.
|
|
76
|
+
const origins = sortedByAddedAt.filter((e) => e.role === 'origin');
|
|
77
|
+
const effectiveOrigins = origins.length > 0
|
|
78
|
+
? origins
|
|
79
|
+
: sortedByAddedAt.filter((e) => !e.parent_session_id);
|
|
80
|
+
const queue = [...effectiveOrigins];
|
|
81
|
+
while (queue.length > 0) {
|
|
82
|
+
const edge = queue.shift();
|
|
83
|
+
if (visited.has(edge.session_id))
|
|
84
|
+
continue;
|
|
85
|
+
visited.add(edge.session_id);
|
|
86
|
+
order.push(edge.session_id);
|
|
87
|
+
// Children of this session, sorted by added_at (already stable from the
|
|
88
|
+
// outer sort but enforced here for clarity).
|
|
89
|
+
const kids = childrenByParent.get(edge.session_id) ?? [];
|
|
90
|
+
for (const k of kids) {
|
|
91
|
+
if (!visited.has(k.session_id))
|
|
92
|
+
queue.push(k);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Tail: any edges we never reached (parent in a different thread, orphaned,
|
|
96
|
+
// or cycle leftovers; the DAG invariant should prevent cycles but we still
|
|
97
|
+
// add unvisited edges in added_at order so no session is silently dropped).
|
|
98
|
+
for (const e of sortedByAddedAt) {
|
|
99
|
+
if (!visited.has(e.session_id)) {
|
|
100
|
+
visited.add(e.session_id);
|
|
101
|
+
order.push(e.session_id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return order;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build the bulk-title prompt: the per-session prompt augmented with a
|
|
108
|
+
* directive instruction telling Claude to identify or invent a naming
|
|
109
|
+
* pattern. The single biggest difference from Bucket 2 is the prompt: instead
|
|
110
|
+
* of a soft hint ("if siblings use a pattern, follow it") we issue a hard
|
|
111
|
+
* directive that scales to N children.
|
|
112
|
+
*
|
|
113
|
+
* Exported so tests and the MCP tool can construct the same text without
|
|
114
|
+
* spawning the subprocess.
|
|
115
|
+
*/
|
|
116
|
+
export function buildBulkTitlePrompt(args) {
|
|
117
|
+
const base = buildAgentTitlePrompt(args.sessionId);
|
|
118
|
+
const directive = [
|
|
119
|
+
'',
|
|
120
|
+
`BULK CONTEXT: You are titling session ${args.current} of ${args.total} in this thread.`,
|
|
121
|
+
'The parent and earlier siblings already have titles (shown above). YOUR JOB:',
|
|
122
|
+
'',
|
|
123
|
+
'1. Identify the naming pattern. If parent is "Build Feature X" and earlier',
|
|
124
|
+
' siblings are "Phase A: API design" and "Phase B: client wiring", the pattern',
|
|
125
|
+
' is "Phase {LETTER}: {topic}".',
|
|
126
|
+
'2. If no pattern is yet established (this is the first child), INVENT a pattern',
|
|
127
|
+
' that will scale to N children. Good patterns: "Phase A/B/C", "Wave 1 of M",',
|
|
128
|
+
' "Step N", or a domain-specific structure if the thread name suggests one.',
|
|
129
|
+
'3. Output a title that follows the pattern AND describes what THIS session',
|
|
130
|
+
' does in 50 characters max.',
|
|
131
|
+
'',
|
|
132
|
+
'Output ONLY the title, no quotes, no trailing punctuation.',
|
|
133
|
+
].join('\n');
|
|
134
|
+
return `${base}\n${directive}`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Internal: read whether a session already has an agent-sourced title. Used
|
|
138
|
+
* by the walker to honour `force: false`. Returns `'agent'`, `'heuristic'`,
|
|
139
|
+
* or null when the session has no auto_title row at all.
|
|
140
|
+
*/
|
|
141
|
+
function currentTitleSource(sessionId) {
|
|
142
|
+
const row = getAutoTitle(sessionId);
|
|
143
|
+
return row?.auto_title_source ?? null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Spawn the user's local `claude` CLI with the bulk-title prompt for a
|
|
147
|
+
* single session. Returns the sanitised title or throws.
|
|
148
|
+
*
|
|
149
|
+
* Lazy import keeps headless consumers (tests, MCP server) from paying the
|
|
150
|
+
* daemon-only import cost; same pattern `deriveAgentTitle` uses.
|
|
151
|
+
*/
|
|
152
|
+
async function spawnBulkTitleCli(args) {
|
|
153
|
+
const { spawnClaudePrompt, isClaudeCliAvailable } = await import('../daemon/tag-scanner/claude-cli-driver.js');
|
|
154
|
+
if (!isClaudeCliAvailable()) {
|
|
155
|
+
throw new Error('claude CLI not found on PATH');
|
|
156
|
+
}
|
|
157
|
+
// No MCP tools, this is a one-shot text-only summarisation, no DB writes.
|
|
158
|
+
const result = await spawnClaudePrompt(args.prompt, [], {
|
|
159
|
+
model: args.model,
|
|
160
|
+
});
|
|
161
|
+
if (!result.success) {
|
|
162
|
+
throw new Error(`claude CLI exited ${result.exitCode}: ${result.stderr.slice(-500)}`);
|
|
163
|
+
}
|
|
164
|
+
const title = extractTitleFromCliResult(result.stdout);
|
|
165
|
+
if (!title)
|
|
166
|
+
throw new Error('claude CLI returned an empty title');
|
|
167
|
+
return title.slice(0, AGENT_TITLE_MAX);
|
|
168
|
+
}
|
|
169
|
+
function extractTitleFromCliResult(stdout) {
|
|
170
|
+
const trimmed = stdout.trim();
|
|
171
|
+
if (!trimmed)
|
|
172
|
+
return '';
|
|
173
|
+
try {
|
|
174
|
+
const parsed = JSON.parse(trimmed);
|
|
175
|
+
if (parsed && typeof parsed === 'object') {
|
|
176
|
+
const result = parsed.result;
|
|
177
|
+
if (typeof result === 'string')
|
|
178
|
+
return sanitiseTitle(result);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
/* not JSON, fall through to raw */
|
|
183
|
+
}
|
|
184
|
+
return sanitiseTitle(trimmed);
|
|
185
|
+
}
|
|
186
|
+
function sanitiseTitle(raw) {
|
|
187
|
+
return raw
|
|
188
|
+
.trim()
|
|
189
|
+
.replace(/^["'`]+|["'`]+$/g, '')
|
|
190
|
+
.replace(/\s+/g, ' ')
|
|
191
|
+
.replace(/[.!?]+$/g, '')
|
|
192
|
+
.trim();
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Bulk-title every session in `threadId` in topology order.
|
|
196
|
+
*
|
|
197
|
+
* Behaviour:
|
|
198
|
+
* - Origins first (by added_at), then children breadth-first per origin.
|
|
199
|
+
* - Per-session: skip when `force=false` AND the session already has an
|
|
200
|
+
* agent-sourced title. Otherwise spawn `claude --print` with the bulk
|
|
201
|
+
* prompt, sanitise the response, and call `setAutoTitle` (preserving
|
|
202
|
+
* three-layer durability).
|
|
203
|
+
* - `signal.aborted`: checked BEFORE each spawn. Remaining sessions are
|
|
204
|
+
* marked skipped with reason `'cancelled'` and the walk returns the
|
|
205
|
+
* accumulated result. Already-written titles stay.
|
|
206
|
+
* - Per-session errors do NOT abort the walk; each failure is captured in
|
|
207
|
+
* `failed[]`. Callers that need fail-fast semantics should set up an
|
|
208
|
+
* AbortController and call `controller.abort()` from `onFailed`.
|
|
209
|
+
*
|
|
210
|
+
* Returns a `TitleGenerationResult` summarising every session visited.
|
|
211
|
+
*/
|
|
212
|
+
export async function generateThreadTitles(threadId, options = {}) {
|
|
213
|
+
const detail = getThread(threadId);
|
|
214
|
+
if (!detail) {
|
|
215
|
+
throw new Error(`thread not found: ${threadId}`);
|
|
216
|
+
}
|
|
217
|
+
const order = walkEdgesInTopologyOrder(detail.edges);
|
|
218
|
+
const total = order.length;
|
|
219
|
+
const force = options.force ?? false;
|
|
220
|
+
const signal = options.signal;
|
|
221
|
+
const generated = [];
|
|
222
|
+
const skipped = [];
|
|
223
|
+
const failed = [];
|
|
224
|
+
for (let i = 0; i < order.length; i++) {
|
|
225
|
+
const sessionId = order[i];
|
|
226
|
+
const current = i + 1;
|
|
227
|
+
if (signal?.aborted) {
|
|
228
|
+
const ev = { sessionId, reason: 'cancelled' };
|
|
229
|
+
skipped.push(ev);
|
|
230
|
+
options.onSkipped?.(ev);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (!force && currentTitleSource(sessionId) === 'agent') {
|
|
234
|
+
const ev = { sessionId, reason: 'already-titled' };
|
|
235
|
+
skipped.push(ev);
|
|
236
|
+
options.onSkipped?.(ev);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
let title;
|
|
240
|
+
try {
|
|
241
|
+
if (testSpawnOverride) {
|
|
242
|
+
title = await testSpawnOverride({ sessionId, current, total });
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const prompt = buildBulkTitlePrompt({ sessionId, current, total });
|
|
246
|
+
title = await spawnBulkTitleCli({
|
|
247
|
+
prompt,
|
|
248
|
+
model: options.model,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
const message = err instanceof Error ? err.message : String(err ?? 'unknown error');
|
|
254
|
+
// A "no user messages" failure is a logical skip, not a hard error.
|
|
255
|
+
// We still surface it via onFailed so the UI can show why it was bypassed,
|
|
256
|
+
// but route through the failed array so the result distinguishes it from
|
|
257
|
+
// intentional skips.
|
|
258
|
+
const ev = { sessionId, error: message };
|
|
259
|
+
failed.push(ev);
|
|
260
|
+
options.onFailed?.(ev);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
setAutoTitle(sessionId, title, 'agent');
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
const message = err instanceof Error ? err.message : String(err ?? 'unknown error');
|
|
268
|
+
const ev = {
|
|
269
|
+
sessionId,
|
|
270
|
+
error: `setAutoTitle failed: ${message}`,
|
|
271
|
+
};
|
|
272
|
+
failed.push(ev);
|
|
273
|
+
options.onFailed?.(ev);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
generated.push(sessionId);
|
|
277
|
+
options.onProgress?.({
|
|
278
|
+
current,
|
|
279
|
+
total,
|
|
280
|
+
sessionId,
|
|
281
|
+
title,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return { generated, skipped, failed };
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Test-only helper that swaps the claude-cli spawn for a pure function. The
|
|
288
|
+
* production path uses the dynamic import in `spawnBulkTitleCli`; tests can
|
|
289
|
+
* override here without touching the subprocess at all.
|
|
290
|
+
*
|
|
291
|
+
* Exported but not re-exported from any module index to keep the surface area
|
|
292
|
+
* narrow. Pass `null` to restore the real spawn.
|
|
293
|
+
*/
|
|
294
|
+
let testSpawnOverride = null;
|
|
295
|
+
export function __setTestSpawnOverride(override) {
|
|
296
|
+
testSpawnOverride = override;
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=threads-titler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads-titler.js","sourceRoot":"","sources":["../../src/utils/threads-titler.ts"],"names":[],"mappings":"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"}
|