@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.
Files changed (218) hide show
  1. package/LICENSE +37 -17
  2. package/README.md +110 -22
  3. package/dist/cli.js +1641 -353
  4. package/dist/daemon/entrypoint.js +1872 -54
  5. package/dist/mcp-server.js +930 -0
  6. package/dist/share/fonts/Inter-Bold.woff +0 -0
  7. package/dist/share/fonts/Inter-Regular.woff +0 -0
  8. package/dist/share/fonts/JetBrainsMono-Regular.woff +0 -0
  9. package/dist/web/assets/_brand-Bw9uSB4O.js +1 -0
  10. package/dist/web/assets/captureNode-9CVj9vYC.js +2 -0
  11. package/dist/web/assets/card-a-minimal-ujNERzX7.js +1 -0
  12. package/dist/web/assets/card-b-terminal-DpJ_tVpg.js +1 -0
  13. package/dist/web/assets/card-c-gradient-CZXVGuNd.js +1 -0
  14. package/dist/web/assets/card-d-dashboard-CHKD-PnB.js +1 -0
  15. package/dist/web/assets/dist-CWaokT35.js +56 -0
  16. package/dist/web/assets/index-B-HrjaDy.css +1 -0
  17. package/dist/web/assets/index-BZYcD76T.js +633 -0
  18. package/dist/web/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  19. package/dist/web/assets/patterns-BPeZb9N0.js +1 -0
  20. package/dist/web/assets/stats-BSwqSiFU.js +1 -0
  21. package/dist/web/assets/thread-D2AXyhOx.js +1 -0
  22. package/dist/web/index.html +8 -2
  23. package/package.json +58 -18
  24. package/scripts/postinstall.mjs +38 -0
  25. package/dist/cli.js.map +0 -1
  26. package/dist/commands/activate.js +0 -69
  27. package/dist/commands/activate.js.map +0 -1
  28. package/dist/commands/audit-secrets.js +0 -103
  29. package/dist/commands/audit-secrets.js.map +0 -1
  30. package/dist/commands/blame.js +0 -35
  31. package/dist/commands/blame.js.map +0 -1
  32. package/dist/commands/config-verification.js +0 -18
  33. package/dist/commands/config-verification.js.map +0 -1
  34. package/dist/commands/context.js +0 -144
  35. package/dist/commands/context.js.map +0 -1
  36. package/dist/commands/correlate.js +0 -70
  37. package/dist/commands/correlate.js.map +0 -1
  38. package/dist/commands/digest.js +0 -78
  39. package/dist/commands/digest.js.map +0 -1
  40. package/dist/commands/health.js +0 -62
  41. package/dist/commands/health.js.map +0 -1
  42. package/dist/commands/index.js +0 -247
  43. package/dist/commands/index.js.map +0 -1
  44. package/dist/commands/install-extension.js +0 -138
  45. package/dist/commands/install-extension.js.map +0 -1
  46. package/dist/commands/license.js +0 -39
  47. package/dist/commands/license.js.map +0 -1
  48. package/dist/commands/list.js +0 -47
  49. package/dist/commands/list.js.map +0 -1
  50. package/dist/commands/mcp.js +0 -29
  51. package/dist/commands/mcp.js.map +0 -1
  52. package/dist/commands/open.js +0 -28
  53. package/dist/commands/open.js.map +0 -1
  54. package/dist/commands/paste.js +0 -154
  55. package/dist/commands/paste.js.map +0 -1
  56. package/dist/commands/projects.js +0 -36
  57. package/dist/commands/projects.js.map +0 -1
  58. package/dist/commands/search.js +0 -67
  59. package/dist/commands/search.js.map +0 -1
  60. package/dist/commands/semantic.js +0 -173
  61. package/dist/commands/semantic.js.map +0 -1
  62. package/dist/commands/show.js +0 -121
  63. package/dist/commands/show.js.map +0 -1
  64. package/dist/commands/start.js +0 -47
  65. package/dist/commands/start.js.map +0 -1
  66. package/dist/commands/stats.js +0 -133
  67. package/dist/commands/stats.js.map +0 -1
  68. package/dist/commands/status.js +0 -45
  69. package/dist/commands/status.js.map +0 -1
  70. package/dist/commands/stop.js +0 -29
  71. package/dist/commands/stop.js.map +0 -1
  72. package/dist/commands/thread.js +0 -396
  73. package/dist/commands/thread.js.map +0 -1
  74. package/dist/context/formatter.js +0 -103
  75. package/dist/context/formatter.js.map +0 -1
  76. package/dist/daemon/auto-tag-config.js +0 -103
  77. package/dist/daemon/auto-tag-config.js.map +0 -1
  78. package/dist/daemon/auto-tag-config.test.js +0 -72
  79. package/dist/daemon/auto-tag-config.test.js.map +0 -1
  80. package/dist/daemon/auto-title-config.js +0 -70
  81. package/dist/daemon/auto-title-config.js.map +0 -1
  82. package/dist/daemon/bulk-title-jobs.js +0 -170
  83. package/dist/daemon/bulk-title-jobs.js.map +0 -1
  84. package/dist/daemon/correlator.js +0 -320
  85. package/dist/daemon/correlator.js.map +0 -1
  86. package/dist/daemon/discover.js +0 -316
  87. package/dist/daemon/discover.js.map +0 -1
  88. package/dist/daemon/editor-detection.js +0 -186
  89. package/dist/daemon/editor-detection.js.map +0 -1
  90. package/dist/daemon/entrypoint.js.map +0 -1
  91. package/dist/daemon/git-correlator.js +0 -256
  92. package/dist/daemon/git-correlator.js.map +0 -1
  93. package/dist/daemon/mcp-installer.js +0 -108
  94. package/dist/daemon/mcp-installer.js.map +0 -1
  95. package/dist/daemon/onboarding-state.js +0 -140
  96. package/dist/daemon/onboarding-state.js.map +0 -1
  97. package/dist/daemon/pidfile.js +0 -57
  98. package/dist/daemon/pidfile.js.map +0 -1
  99. package/dist/daemon/ports.js +0 -48
  100. package/dist/daemon/ports.js.map +0 -1
  101. package/dist/daemon/scanProgressRegistry.js +0 -62
  102. package/dist/daemon/scanProgressRegistry.js.map +0 -1
  103. package/dist/daemon/server.js +0 -2010
  104. package/dist/daemon/server.js.map +0 -1
  105. package/dist/daemon/tag-scanner/anthropic-client.js +0 -40
  106. package/dist/daemon/tag-scanner/anthropic-client.js.map +0 -1
  107. package/dist/daemon/tag-scanner/autopilot.js +0 -131
  108. package/dist/daemon/tag-scanner/autopilot.js.map +0 -1
  109. package/dist/daemon/tag-scanner/claude-cli-driver.js +0 -250
  110. package/dist/daemon/tag-scanner/claude-cli-driver.js.map +0 -1
  111. package/dist/daemon/tag-scanner/orchestrator.js +0 -88
  112. package/dist/daemon/tag-scanner/orchestrator.js.map +0 -1
  113. package/dist/daemon/tag-scanner/prompt.js +0 -46
  114. package/dist/daemon/tag-scanner/prompt.js.map +0 -1
  115. package/dist/daemon/tag-scanner/prompt.test.js +0 -48
  116. package/dist/daemon/tag-scanner/prompt.test.js.map +0 -1
  117. package/dist/daemon/tag-scanner/scan-state.js +0 -49
  118. package/dist/daemon/tag-scanner/scan-state.js.map +0 -1
  119. package/dist/daemon/tag-scanner/session-fetcher.js +0 -82
  120. package/dist/daemon/tag-scanner/session-fetcher.js.map +0 -1
  121. package/dist/daemon/tag-scanner/session-fetcher.test.js +0 -34
  122. package/dist/daemon/tag-scanner/session-fetcher.test.js.map +0 -1
  123. package/dist/daemon/tag-scanner/validator.js +0 -50
  124. package/dist/daemon/tag-scanner/validator.js.map +0 -1
  125. package/dist/daemon/tag-scanner/validator.test.js +0 -41
  126. package/dist/daemon/tag-scanner/validator.test.js.map +0 -1
  127. package/dist/daemon/terminal-registry.js +0 -443
  128. package/dist/daemon/terminal-registry.js.map +0 -1
  129. package/dist/daemon/ui.js +0 -64
  130. package/dist/daemon/ui.js.map +0 -1
  131. package/dist/daemon/watcher.js +0 -256
  132. package/dist/daemon/watcher.js.map +0 -1
  133. package/dist/db/client.js +0 -22
  134. package/dist/db/client.js.map +0 -1
  135. package/dist/db/schema.js +0 -496
  136. package/dist/db/schema.js.map +0 -1
  137. package/dist/license/api-base.js +0 -13
  138. package/dist/license/api-base.js.map +0 -1
  139. package/dist/license/manager.js +0 -43
  140. package/dist/license/manager.js.map +0 -1
  141. package/dist/license/public-key.js +0 -19
  142. package/dist/license/public-key.js.map +0 -1
  143. package/dist/license/storage.js +0 -27
  144. package/dist/license/storage.js.map +0 -1
  145. package/dist/license/verify.js +0 -23
  146. package/dist/license/verify.js.map +0 -1
  147. package/dist/mcp/audit.js +0 -126
  148. package/dist/mcp/audit.js.map +0 -1
  149. package/dist/mcp/prompts.js +0 -180
  150. package/dist/mcp/prompts.js.map +0 -1
  151. package/dist/mcp/server.js +0 -502
  152. package/dist/mcp/server.js.map +0 -1
  153. package/dist/mcp/thread-tools.js +0 -363
  154. package/dist/mcp/thread-tools.js.map +0 -1
  155. package/dist/mcp/write-tools.js +0 -239
  156. package/dist/mcp/write-tools.js.map +0 -1
  157. package/dist/parser/jsonl.js +0 -150
  158. package/dist/parser/jsonl.js.map +0 -1
  159. package/dist/semantic/chunker.js +0 -47
  160. package/dist/semantic/chunker.js.map +0 -1
  161. package/dist/semantic/config.js +0 -74
  162. package/dist/semantic/config.js.map +0 -1
  163. package/dist/semantic/embedder.js +0 -54
  164. package/dist/semantic/embedder.js.map +0 -1
  165. package/dist/semantic/fusion.js +0 -38
  166. package/dist/semantic/fusion.js.map +0 -1
  167. package/dist/semantic/model-download.js +0 -69
  168. package/dist/semantic/model-download.js.map +0 -1
  169. package/dist/semantic/pipeline.js +0 -375
  170. package/dist/semantic/pipeline.js.map +0 -1
  171. package/dist/semantic/query.js +0 -42
  172. package/dist/semantic/query.js.map +0 -1
  173. package/dist/semantic/worker.js +0 -78
  174. package/dist/semantic/worker.js.map +0 -1
  175. package/dist/stats/backfill.js +0 -151
  176. package/dist/stats/backfill.js.map +0 -1
  177. package/dist/stats/health.js +0 -102
  178. package/dist/stats/health.js.map +0 -1
  179. package/dist/stats/query.js +0 -385
  180. package/dist/stats/query.js.map +0 -1
  181. package/dist/utils/aliases.js +0 -107
  182. package/dist/utils/aliases.js.map +0 -1
  183. package/dist/utils/autoCollections.js +0 -635
  184. package/dist/utils/autoCollections.js.map +0 -1
  185. package/dist/utils/autoTitle.js +0 -348
  186. package/dist/utils/autoTitle.js.map +0 -1
  187. package/dist/utils/collections.js +0 -446
  188. package/dist/utils/collections.js.map +0 -1
  189. package/dist/utils/format.js +0 -46
  190. package/dist/utils/format.js.map +0 -1
  191. package/dist/utils/notes.js +0 -270
  192. package/dist/utils/notes.js.map +0 -1
  193. package/dist/utils/paths.js +0 -50
  194. package/dist/utils/paths.js.map +0 -1
  195. package/dist/utils/pricing.js +0 -257
  196. package/dist/utils/pricing.js.map +0 -1
  197. package/dist/utils/secret-scanner.js +0 -166
  198. package/dist/utils/secret-scanner.js.map +0 -1
  199. package/dist/utils/sessionLabel.js +0 -64
  200. package/dist/utils/sessionLabel.js.map +0 -1
  201. package/dist/utils/tags.js +0 -97
  202. package/dist/utils/tags.js.map +0 -1
  203. package/dist/utils/thread-context.js +0 -129
  204. package/dist/utils/thread-context.js.map +0 -1
  205. package/dist/utils/threadFilter.js +0 -18
  206. package/dist/utils/threadFilter.js.map +0 -1
  207. package/dist/utils/threads-titler.js +0 -298
  208. package/dist/utils/threads-titler.js.map +0 -1
  209. package/dist/utils/threads.js +0 -383
  210. package/dist/utils/threads.js.map +0 -1
  211. package/dist/utils/usage.js +0 -76
  212. package/dist/utils/usage.js.map +0 -1
  213. package/dist/verification/compute.js +0 -88
  214. package/dist/verification/compute.js.map +0 -1
  215. package/dist/verification/config.js +0 -34
  216. package/dist/verification/config.js.map +0 -1
  217. package/dist/web/assets/index-CIr6J4Fw.js +0 -1201
  218. package/dist/web/assets/index-Ctc8g9Jw.css +0 -1
@@ -1,166 +0,0 @@
1
- /**
2
- * Secret scanner. Used in two places:
3
- *
4
- * 1. `recall paste` — pre-archive gate. Refuses (by default) to store content
5
- * that matches a known high-severity pattern unless --force is passed.
6
- * 2. UI warnings — Notes editor can call this client-side to show a
7
- * "this note looks like it contains a secret" banner before save.
8
- *
9
- * Patterns are deliberately conservative: we'd rather let through a fake secret
10
- * than mask a real one. Users can always override with --force if they really
11
- * want to archive something that matches a pattern (e.g. a sample key in docs).
12
- */
13
- const PATTERNS = [
14
- // --- Well-known provider keys ---
15
- { name: 'Anthropic API key', regex: /sk-ant-[a-zA-Z0-9_\-]{40,}/g, severity: 'high' },
16
- { name: 'OpenAI API key', regex: /sk-(?:proj-)?[a-zA-Z0-9]{32,}/g, severity: 'high' },
17
- { name: 'AWS access key ID', regex: /AKIA[0-9A-Z]{16}/g, severity: 'high' },
18
- { name: 'GitHub PAT', regex: /gh[pousr]_[A-Za-z0-9]{20,}/g, severity: 'high' },
19
- { name: 'Stripe live/test key', regex: /(?:sk|rk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/g, severity: 'high' },
20
- { name: 'Slack token', regex: /xox[abprs]-[A-Za-z0-9\-]{10,}/g, severity: 'high' },
21
- { name: 'Google API key', regex: /AIza[0-9A-Za-z_\-]{35}/g, severity: 'high' },
22
- { name: 'Private key block', regex: /-----BEGIN (?:RSA |DSA |EC |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/g, severity: 'high' },
23
- // --- Other named providers ---
24
- { name: 'Apify token', regex: /apify_api_[A-Za-z0-9]{20,}/g, severity: 'high' },
25
- { name: 'Notion integration', regex: /(?:secret_|ntn_)[A-Za-z0-9]{40,}/g, severity: 'high' },
26
- { name: 'Vercel token', regex: /vercel_[A-Za-z0-9]{24,}/g, severity: 'high' },
27
- { name: 'Supabase service key', regex: /sbp_[A-Za-z0-9]{40,}/g, severity: 'high' },
28
- { name: 'SendGrid key', regex: /SG\.[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}/g, severity: 'high' },
29
- { name: 'Mailgun key', regex: /key-[a-f0-9]{32}/g, severity: 'high' },
30
- { name: 'Twilio SID', regex: /AC[a-f0-9]{32}/g, severity: 'high' },
31
- { name: 'Discord bot token', regex: /[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27,38}/g, severity: 'high' },
32
- { name: 'npm token', regex: /npm_[A-Za-z0-9]{36}/g, severity: 'high' },
33
- { name: 'HuggingFace token', regex: /hf_[A-Za-z0-9]{30,}/g, severity: 'high' },
34
- { name: 'Replicate token', regex: /r8_[A-Za-z0-9]{32,}/g, severity: 'high' },
35
- { name: 'Figma token', regex: /figd_[A-Za-z0-9_\-]{30,}/g, severity: 'high' },
36
- { name: 'Linear key', regex: /lin_api_[A-Za-z0-9]{30,}/g, severity: 'high' },
37
- { name: 'DigitalOcean token', regex: /dop_v1_[a-f0-9]{64}/g, severity: 'high' },
38
- // --- Generic catch-alls (broad; run last so named matches win dedup) ---
39
- //
40
- // Provider-prefixed tokens follow an observable pattern:
41
- // <lowercase-provider>_(api|pat|token|sk|pk|key|auth)_<high-entropy-blob>
42
- // The 20+ char blob filters out common english words and short IDs.
43
- // Requires at least one digit in the blob to avoid matching labels like
44
- // `stripe_api_key_configuration`.
45
- { name: 'Generic provider token', regex: /\b[a-z][a-z0-9]{2,20}_(?:api|pat|token|sk|pk|key|auth)_(?=[A-Za-z0-9_\-]*\d)[A-Za-z0-9_\-]{20,}\b/g, severity: 'high' },
46
- // Bearer tokens in Authorization headers.
47
- { name: 'Bearer token', regex: /\b[Bb]earer\s+[A-Za-z0-9_\-\.=]{24,}\b/g, severity: 'medium' },
48
- // --- Webhook URLs that embed a token in the path ---
49
- // These URLs are themselves credentials — anyone with the URL can post
50
- // to the channel, so leaking one is identical to leaking a key.
51
- { name: 'Slack webhook URL',
52
- regex: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{20,}/g,
53
- severity: 'high' },
54
- { name: 'Discord webhook URL',
55
- regex: /https:\/\/(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_\-]{40,}/g,
56
- severity: 'high' },
57
- { name: 'Teams webhook URL',
58
- regex: /https:\/\/[a-zA-Z0-9.\-]+\.webhook\.office\.com\/webhookb2\/[A-Za-z0-9@_\-\/]{30,}/g,
59
- severity: 'high' },
60
- // High-entropy blob immediately following a secret-y keyword. Catches the
61
- // markdown-doc leak case where the secret is on its own line in a code
62
- // fence, e.g.:
63
- //
64
- // **Webhook signing secret** (copy exactly):
65
- // ```
66
- // b02233572afa9fe5ce33083a5984f1b2c23986c337a9d3a3422daa02de61867e
67
- // ```
68
- //
69
- // The keyword and value can be separated by up to 200 chars of glue
70
- // (whitespace, fence markers, parenthetical notes). The 32-char minimum
71
- // on the blob avoids false-positives on short hashes / IDs while still
72
- // catching 64-char hex (32-byte) and 40-char hex (20-byte) secrets.
73
- { name: 'Secret near keyword',
74
- regex: /\b(?:webhook[_\s\-]?secret|signing[_\s\-]?secret|webhook[_\s\-]?signing[_\s\-]?secret|api[_\s\-]?secret|client[_\s\-]?secret|private[_\s\-]?key|access[_\s\-]?token|auth[_\s\-]?token|api[_\s\-]?key)\b[\s\S]{0,200}?\b(?:[a-fA-F0-9]{32,}|[A-Za-z0-9+/_\-]{20,}(?:\.[A-Za-z0-9+/_\-]{10,}){1,2}|[A-Za-z0-9+/_\-]{40,}={0,2})\b/gi,
75
- severity: 'high' },
76
- // --- Formats, not providers ---
77
- { name: 'JWT', regex: /eyJ[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}/g, severity: 'medium' },
78
- { name: 'URL with password', regex: /https?:\/\/[^:\s/@]+:[^@\s]{6,}@[^\s/]+/g, severity: 'high' },
79
- // Password / secret / token / api-key assignments. The lookbehind blocks
80
- // matches inside camelCase identifiers (e.g. `mySecretLogger`) but allows
81
- // env-var style names where the keyword is preceded by `_` (e.g.
82
- // `WEBHOOK_SECRET=`, `LEMONSQUEEZY_WEBHOOK_SECRET=`, `STRIPE_API_KEY=`).
83
- // The 16+ char value charset deliberately excludes `.` and `:` so that
84
- // `secret = process.env.X` and `apiKey: args.resendApiKey` (code, not
85
- // values) do not get redacted.
86
- { name: 'Password assignment',
87
- regex: /(?<![A-Za-z])(?:password|passwd|pwd|secret|token|api[_\-]?key|access[_\-]?key|auth[_\-]?token|webhook[_\-]?secret|client[_\-]?secret|private[_\-]?key)\b\s*[:=]\s*["']?[A-Za-z0-9_\-+/=]{16,}/gi,
88
- severity: 'high' },
89
- ];
90
- function mask(s) {
91
- if (s.length <= 8)
92
- return s.slice(0, 2) + '•'.repeat(Math.max(0, s.length - 4)) + s.slice(-2);
93
- const head = s.slice(0, Math.min(6, Math.floor(s.length / 3)));
94
- const tail = s.slice(-Math.min(4, Math.floor(s.length / 4)));
95
- return `${head}${'•'.repeat(Math.max(3, s.length - head.length - tail.length))}${tail}`;
96
- }
97
- export function scanForSecrets(text) {
98
- if (!text)
99
- return [];
100
- // The raw secret is held in this local scope only — dedup key is hashed
101
- // (cheap non-cryptographic hash is fine; we just need uniqueness, not
102
- // unpredictability) and the plaintext never escapes the function.
103
- const seen = new Set();
104
- const out = [];
105
- for (const p of PATTERNS) {
106
- p.regex.lastIndex = 0;
107
- for (const m of text.matchAll(p.regex)) {
108
- const raw = m[0];
109
- const key = `${p.name}::${fingerprint(raw)}`;
110
- if (seen.has(key))
111
- continue;
112
- seen.add(key);
113
- out.push({
114
- pattern: p.name,
115
- maskedPreview: mask(raw),
116
- offset: m.index ?? 0,
117
- severity: p.severity,
118
- });
119
- }
120
- }
121
- return out;
122
- }
123
- /** Small non-cryptographic hash (djb2). Dedup only — never reversed. */
124
- function fingerprint(s) {
125
- let h = 5381;
126
- for (let i = 0; i < s.length; i++)
127
- h = ((h << 5) + h + s.charCodeAt(i)) | 0;
128
- return (h >>> 0).toString(36);
129
- }
130
- export function hasHighSeveritySecret(text) {
131
- return scanForSecrets(text).some((m) => m.severity === 'high');
132
- }
133
- /**
134
- * Redact every detected secret in-place with a masked preview. Used on the
135
- * indexing hot path so secrets that appear in raw session JSONL never make
136
- * it into ~/.recall/db.sqlite (or the FTS index, the plain-text mirrors,
137
- * or the exported context markdown).
138
- *
139
- * The original JSONL at ~/.claude/projects/ is NEVER modified — that's the
140
- * durability invariant. The redaction only affects our derived store, so a
141
- * user who really needs the cleartext can still recover it from source.
142
- *
143
- * Returns the redacted string and the count of unique secrets redacted.
144
- * `count` is useful for telemetry / UI badges ("3 secrets auto-redacted
145
- * in this session").
146
- */
147
- export function redactSecrets(text) {
148
- if (!text)
149
- return { redacted: text, count: 0 };
150
- let redacted = text;
151
- let count = 0;
152
- const seen = new Set();
153
- for (const p of PATTERNS) {
154
- p.regex.lastIndex = 0;
155
- redacted = redacted.replace(p.regex, (m) => {
156
- const key = `${p.name}::${fingerprint(m)}`;
157
- if (!seen.has(key)) {
158
- seen.add(key);
159
- count += 1;
160
- }
161
- return `[REDACTED ${p.name}: ${mask(m)}]`;
162
- });
163
- }
164
- return { redacted, count };
165
- }
166
- //# sourceMappingURL=secret-scanner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"secret-scanner.js","sourceRoot":"","sources":["../../src/utils/secret-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyBH,MAAM,QAAQ,GAAiB;IAC7B,mCAAmC;IACnC,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,6BAA6B,EAAsB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,gBAAgB,EAAQ,KAAK,EAAE,gCAAgC,EAAmB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,mBAAmB,EAAgC,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,YAAY,EAAY,KAAK,EAAE,6BAA6B,EAAsB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,8CAA8C,EAAK,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,aAAa,EAAW,KAAK,EAAE,gCAAgC,EAAmB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,gBAAgB,EAAQ,KAAK,EAAE,yBAAyB,EAA0B,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,oEAAoE,EAAE,QAAQ,EAAE,MAAM,EAAE;IAE/H,gCAAgC;IAChC,EAAE,IAAI,EAAE,aAAa,EAAW,KAAK,EAAE,6BAA6B,EAAsB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,oBAAoB,EAAI,KAAK,EAAE,mCAAmC,EAAgB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,cAAc,EAAU,KAAK,EAAE,0BAA0B,EAAyB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,uBAAuB,EAA4B,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,cAAc,EAAU,KAAK,EAAE,+CAA+C,EAAI,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,aAAa,EAAW,KAAK,EAAE,mBAAmB,EAAgC,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,YAAY,EAAY,KAAK,EAAE,iBAAiB,EAAkC,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,6CAA6C,EAAM,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,WAAW,EAAa,KAAK,EAAE,sBAAsB,EAA6B,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,sBAAsB,EAA6B,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,iBAAiB,EAAO,KAAK,EAAE,sBAAsB,EAA6B,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,aAAa,EAAW,KAAK,EAAE,2BAA2B,EAAwB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,YAAY,EAAY,KAAK,EAAE,2BAA2B,EAAwB,QAAQ,EAAE,MAAM,EAAE;IAC5G,EAAE,IAAI,EAAE,oBAAoB,EAAI,KAAK,EAAE,sBAAsB,EAA6B,QAAQ,EAAE,MAAM,EAAE;IAE5G,0EAA0E;IAC1E,EAAE;IACF,yDAAyD;IACzD,4EAA4E;IAC5E,oEAAoE;IACpE,wEAAwE;IACxE,kCAAkC;IAClC,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,oGAAoG,EAAE,QAAQ,EAAE,MAAM,EAAE;IACjK,0CAA0C;IAC1C,EAAE,IAAI,EAAE,cAAc,EAAU,KAAK,EAAE,yCAAyC,EAAU,QAAQ,EAAE,QAAQ,EAAE;IAE9G,sDAAsD;IACtD,uEAAuE;IACvE,gEAAgE;IAChE,EAAE,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,kFAAkF;QACzF,QAAQ,EAAE,MAAM,EAAE;IACpB,EAAE,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,6FAA6F;QACpG,QAAQ,EAAE,MAAM,EAAE;IACpB,EAAE,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,qFAAqF;QAC5F,QAAQ,EAAE,MAAM,EAAE;IAEpB,0EAA0E;IAC1E,uEAAuE;IACvE,eAAe;IACf,EAAE;IACF,+CAA+C;IAC/C,QAAQ;IACR,qEAAqE;IACrE,QAAQ;IACR,EAAE;IACF,oEAAoE;IACpE,wEAAwE;IACxE,uEAAuE;IACvE,oEAAoE;IACpE,EAAE,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,mUAAmU;QAC1U,QAAQ,EAAE,MAAM,EAAE;IAEpB,iCAAiC;IACjC,EAAE,IAAI,EAAE,KAAK,EAAmB,KAAK,EAAE,mEAAmE,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAChI,EAAE,IAAI,EAAE,mBAAmB,EAAK,KAAK,EAAE,0CAA0C,EAAS,QAAQ,EAAE,MAAM,EAAE;IAC5G,yEAAyE;IACzE,0EAA0E;IAC1E,iEAAiE;IACjE,yEAAyE;IACzE,uEAAuE;IACvE,sEAAsE;IACtE,+BAA+B;IAC/B,EAAE,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,iMAAiM;QACxM,QAAQ,EAAE,MAAM,EAAE;CACrB,CAAC;AAEF,SAAS,IAAI,CAAC,CAAS;IACrB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,GAAG,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,wEAAwE;IACxE,sEAAsE;IACtE,kEAAkE;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,CAAC,CAAC,IAAI;gBACf,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC;gBACxB,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;gBACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wEAAwE;AACxE,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5E,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAC/C,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE;YACzC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;YACD,OAAO,aAAa,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC"}
@@ -1,64 +0,0 @@
1
- /**
2
- * Session label resolution. Implements the standard fallback chain used
3
- * everywhere a session needs a human-readable name.
4
- *
5
- * Precedence (mirrors AliasEditor + SessionsPane):
6
- * 1. Agent ✨ auto_title wins unconditionally — clicking ✨ is a deliberate
7
- * request to display THIS title.
8
- * 2. Manual alias beats heuristic-only auto_title.
9
- * 3. Heuristic auto_title beats correlator-set ('auto') alias — fixes
10
- * child sessions that inherited a noisy terminal-tab name like "claude"
11
- * or "test test" from a wrongly-linked terminal.
12
- * 4. Otherwise: alias → auto_title → first_user_message → id.slice(0,8).
13
- *
14
- * Callers without `aliasSource` / `autoTitleSource` collapse to the simpler
15
- * legacy chain (alias → auto_title → first_user_message → id) — kept for
16
- * backward compatibility with consumers that don't yet plumb source fields.
17
- *
18
- * Pure function with no DB access. Tests live at `test/sessionLabel.test.mjs`.
19
- */
20
- const FIRST_MESSAGE_MAX_LEN = 60;
21
- function nonEmpty(value) {
22
- if (value == null)
23
- return null;
24
- const trimmed = value.trim();
25
- return trimmed.length > 0 ? trimmed : null;
26
- }
27
- function truncateFirstMessage(raw) {
28
- const firstLine = raw.split('\n', 1)[0].trim();
29
- if (!firstLine)
30
- return null;
31
- return firstLine.length > FIRST_MESSAGE_MAX_LEN
32
- ? firstLine.slice(0, FIRST_MESSAGE_MAX_LEN)
33
- : firstLine;
34
- }
35
- export function resolveSessionLabel(input) {
36
- const alias = nonEmpty(input.alias);
37
- const autoTitle = nonEmpty(input.autoTitle);
38
- const firstMessage = nonEmpty(input.firstUserMessage);
39
- const aliasSource = input.aliasSource ?? null;
40
- const autoTitleSource = input.autoTitleSource ?? null;
41
- // 1. Agent title always wins.
42
- if (autoTitle && autoTitleSource === 'agent')
43
- return autoTitle;
44
- // 2. Manual alias beats a heuristic auto_title.
45
- if (alias && aliasSource === 'manual')
46
- return alias;
47
- // 3. Any auto_title beats an auto-set alias (terminal-tab inheritance fix).
48
- // Also covers the legacy callers (no source fields): if both exist with
49
- // no source info, prefer alias unless we explicitly know it's auto.
50
- if (autoTitle && (aliasSource === 'auto' || alias === null))
51
- return autoTitle;
52
- // 4. Fall through to the legacy chain.
53
- if (alias)
54
- return alias;
55
- if (autoTitle)
56
- return autoTitle;
57
- if (firstMessage) {
58
- const truncated = truncateFirstMessage(firstMessage);
59
- if (truncated)
60
- return truncated;
61
- }
62
- return input.sessionId.slice(0, 8);
63
- }
64
- //# sourceMappingURL=sessionLabel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sessionLabel.js","sourceRoot":"","sources":["../../src/utils/sessionLabel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAajC,SAAS,QAAQ,CAAC,KAAgC;IAChD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACvC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,SAAS,CAAC,MAAM,GAAG,qBAAqB;QAC7C,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC;QAC3C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAwB;IAC1D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;IAC9C,MAAM,eAAe,GAAG,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC;IAEtD,8BAA8B;IAC9B,IAAI,SAAS,IAAI,eAAe,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/D,gDAAgD;IAChD,IAAI,KAAK,IAAI,WAAW,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEpD,4EAA4E;IAC5E,2EAA2E;IAC3E,uEAAuE;IACvE,IAAI,SAAS,IAAI,CAAC,WAAW,KAAK,MAAM,IAAI,KAAK,KAAK,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9E,uCAAuC;IACvC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,SAAS;YAAE,OAAO,SAAS,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -1,97 +0,0 @@
1
- import { writeFileSync } 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
- /**
6
- * Tags for sessions. Three durability layers, same pattern as aliases + notes:
7
- *
8
- * 1. session_tags — the current (session_id, tag) many-to-many state.
9
- * 2. tag_events — append-only audit log of every add/remove. Never trimmed.
10
- * 3. ~/.recall/tags.json — plain-text mirror on disk, rewritten after every
11
- * mutation. Contains both current state AND the full event log, so tags
12
- * can be reconstructed end-to-end from this file alone.
13
- */
14
- export const TAGS_BACKUP_FILE = join(RECALL_HOME, 'tags.json');
15
- /** Normalize user input into a canonical tag token. */
16
- export function normalizeTag(raw) {
17
- return raw
18
- .trim()
19
- .toLowerCase()
20
- .replace(/^#+/, '')
21
- .replace(/[\s/\\]+/g, '-')
22
- .replace(/[^a-z0-9\-._]/g, '')
23
- .slice(0, 40);
24
- }
25
- export function addTag(sessionId, rawTag) {
26
- const tag = normalizeTag(rawTag);
27
- if (!tag)
28
- throw new Error('tag must contain at least one alphanumeric character');
29
- const db = getDb();
30
- const now = new Date().toISOString();
31
- const exists = db
32
- .prepare('SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?')
33
- .get(sessionId, tag);
34
- if (exists) {
35
- return { tag, added: false };
36
- }
37
- const txn = db.transaction(() => {
38
- db.prepare('INSERT INTO session_tags (session_id, tag, created_at) VALUES (?, ?, ?)').run(sessionId, tag, now);
39
- db.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'add', ?)").run(sessionId, tag, now);
40
- });
41
- txn();
42
- backupTags();
43
- return { tag, added: true };
44
- }
45
- export function removeTag(sessionId, rawTag) {
46
- const tag = normalizeTag(rawTag);
47
- if (!tag)
48
- return { tag: '', removed: false };
49
- const db = getDb();
50
- const now = new Date().toISOString();
51
- const existed = db
52
- .prepare('SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?')
53
- .get(sessionId, tag);
54
- if (!existed)
55
- return { tag, removed: false };
56
- const txn = db.transaction(() => {
57
- db.prepare('DELETE FROM session_tags WHERE session_id = ? AND tag = ?').run(sessionId, tag);
58
- db.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'remove', ?)").run(sessionId, tag, now);
59
- });
60
- txn();
61
- backupTags();
62
- return { tag, removed: true };
63
- }
64
- export function tagsForSession(sessionId) {
65
- return getDb()
66
- .prepare('SELECT tag FROM session_tags WHERE session_id = ? ORDER BY tag')
67
- .all(sessionId).map((r) => r.tag);
68
- }
69
- export function allTagsWithCounts() {
70
- return getDb()
71
- .prepare(`SELECT tag, COUNT(*) AS count FROM session_tags
72
- GROUP BY tag ORDER BY count DESC, tag ASC`)
73
- .all();
74
- }
75
- export function backupTags() {
76
- try {
77
- ensureRecallHome();
78
- const db = getDb();
79
- const currentTags = db
80
- .prepare('SELECT session_id, tag, created_at FROM session_tags ORDER BY session_id, tag')
81
- .all();
82
- const events = db
83
- .prepare('SELECT id, session_id, tag, action, at FROM tag_events ORDER BY at ASC, id ASC')
84
- .all();
85
- const payload = {
86
- schema: 'claude-recall.tags.v1',
87
- backed_up_at: new Date().toISOString(),
88
- current: currentTags,
89
- events,
90
- };
91
- writeFileSync(TAGS_BACKUP_FILE, JSON.stringify(payload, null, 2));
92
- }
93
- catch (err) {
94
- console.error('[tags] backup failed:', err);
95
- }
96
- }
97
- //# sourceMappingURL=tags.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/utils/tags.ts"],"names":[],"mappings":"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"}
@@ -1,129 +0,0 @@
1
- import { getDb } from '../db/client.js';
2
- /**
3
- * v0.15b prep — thread-context resolver for agent-tier auto-title generation.
4
- *
5
- * When the user clicks "Generate title" on a session that already lives inside
6
- * a thread, the LLM should know who the parent and siblings are so it can
7
- * mint a title that reflects the session's role in the hierarchy
8
- * ("Phase A: API design") instead of a generic single-session summary.
9
- *
10
- * This module is read-only against the existing `threads` and `thread_edges`
11
- * tables. It does not mutate state, does not write mirrors, and never throws
12
- * on a missing edge — callers in `autoTitle.ts` fall back to the no-context
13
- * prompt when this returns null.
14
- *
15
- * Multi-thread tie-break: if a session belongs to multiple threads, we pick
16
- * the thread the session was added to most recently (by `thread_edges.added_at`
17
- * for that session's edge). Rationale: the user's last action is the strongest
18
- * signal of which thread they consider "current." A generated title that
19
- * reflects an older, possibly archived thread would feel stale.
20
- *
21
- * Title fallback chain (consumers should rely on this helper rather than
22
- * re-implementing it): `alias → auto_title → first_user_message → id.slice(0,8)`.
23
- * Same chain used by `displayTitleFor` in autoCollections.ts and the web UI.
24
- */
25
- const DISPLAY_TITLE_MAX = 80;
26
- /**
27
- * Display title with the canonical fallback chain. Trims, takes the first
28
- * line, caps at 80 chars with an ellipsis. Returns the 8-char id slice when
29
- * nothing else is available so the prompt always has *something* to refer to.
30
- */
31
- function displayTitleFor(row) {
32
- if (row.alias && row.alias.trim())
33
- return row.alias.trim();
34
- if (row.auto_title && row.auto_title.trim())
35
- return row.auto_title.trim();
36
- const msg = (row.first_user_message ?? '').trim();
37
- if (!msg)
38
- return row.id.slice(0, 8);
39
- const firstLine = msg.split('\n')[0].trim();
40
- return firstLine.length > DISPLAY_TITLE_MAX
41
- ? firstLine.slice(0, DISPLAY_TITLE_MAX) + '…'
42
- : firstLine;
43
- }
44
- function loadDisplayRow(sessionId) {
45
- const db = getDb();
46
- const row = db
47
- .prepare(`SELECT s.id AS id,
48
- sa.alias AS alias,
49
- s.auto_title AS auto_title,
50
- s.first_user_message AS first_user_message
51
- FROM sessions s
52
- LEFT JOIN session_aliases sa ON sa.session_id = s.id
53
- WHERE s.id = ?`)
54
- .get(sessionId);
55
- return row ?? null;
56
- }
57
- function loadDisplayTitle(sessionId) {
58
- const row = loadDisplayRow(sessionId);
59
- if (!row)
60
- return sessionId.slice(0, 8);
61
- return displayTitleFor(row);
62
- }
63
- /**
64
- * Resolve the most-relevant thread context for a session.
65
- *
66
- * Returns null when:
67
- * - the session does not exist, OR
68
- * - the session has no rows in `thread_edges`, OR
69
- * - the only matching threads are archived.
70
- */
71
- export function getThreadContextForSession(sessionId) {
72
- if (!sessionId)
73
- return null;
74
- const db = getDb();
75
- // Pick the most-recently-added edge for this session across non-archived
76
- // threads. ORDER BY added_at DESC ensures the user's last action wins;
77
- // LIMIT 1 collapses ties deterministically (by primary key tie-break SQLite
78
- // applies — stable enough for our purposes since we only need ONE thread).
79
- const edge = db
80
- .prepare(`SELECT e.thread_id AS thread_id,
81
- t.name AS thread_name,
82
- e.parent_session_id AS parent_session_id,
83
- e.added_at AS added_at
84
- FROM thread_edges e
85
- JOIN threads t ON t.id = e.thread_id
86
- WHERE e.session_id = ?
87
- AND t.archived = 0
88
- ORDER BY e.added_at DESC
89
- LIMIT 1`)
90
- .get(sessionId);
91
- if (!edge)
92
- return null;
93
- const parent_session = edge.parent_session_id
94
- ? {
95
- id: edge.parent_session_id,
96
- title: loadDisplayTitle(edge.parent_session_id),
97
- }
98
- : null;
99
- const excludeIds = edge.parent_session_id
100
- ? [sessionId, edge.parent_session_id]
101
- : [sessionId];
102
- const placeholders = excludeIds.map(() => '?').join(', ');
103
- const siblingRows = db
104
- .prepare(`SELECT e.session_id AS session_id,
105
- s.id AS id,
106
- sa.alias AS alias,
107
- s.auto_title AS auto_title,
108
- s.first_user_message AS first_user_message
109
- FROM thread_edges e
110
- LEFT JOIN sessions s ON s.id = e.session_id
111
- LEFT JOIN session_aliases sa ON sa.session_id = e.session_id
112
- WHERE e.thread_id = ?
113
- AND e.session_id NOT IN (${placeholders})
114
- ORDER BY e.added_at ASC`)
115
- .all(edge.thread_id, ...excludeIds);
116
- const siblings = siblingRows.map((r) => ({
117
- id: r.session_id,
118
- // If the sibling row's session is missing (foreign-key gap, shouldn't
119
- // happen but defensive), fall back to its id slice.
120
- title: r.id ? displayTitleFor(r) : r.session_id.slice(0, 8),
121
- }));
122
- return {
123
- thread_id: edge.thread_id,
124
- thread_name: edge.thread_name,
125
- parent_session,
126
- siblings,
127
- };
128
- }
129
- //# sourceMappingURL=thread-context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"thread-context.js","sourceRoot":"","sources":["../../src/utils/thread-context.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Thread name typeahead filter. Pure helper used by the SessionThreadsRow
3
- * "+ Add to thread" picker (v0.15a Bucket 1 fix 5).
4
- *
5
- * Case-insensitive substring match against `thread.name`. Empty query returns
6
- * the input unchanged so the caller can show the full list before any typing.
7
- * Whitespace-only queries are treated as empty.
8
- *
9
- * Stays in `src/utils/` (instead of `src/web/`) so unit tests under `test/`
10
- * can import it directly from the compiled `dist/`.
11
- */
12
- export function filterThreadsByName(threads, query) {
13
- const norm = query.trim().toLowerCase();
14
- if (!norm)
15
- return [...threads];
16
- return threads.filter((t) => t.name.toLowerCase().includes(norm));
17
- }
18
- //# sourceMappingURL=threadFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"threadFilter.js","sourceRoot":"","sources":["../../src/utils/threadFilter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,MAAM,UAAU,mBAAmB,CACjC,OAAqB,EACrB,KAAa;IAEb,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACpE,CAAC"}