@clauderecallhq/cli 0.12.1 → 0.61.2

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 (220) hide show
  1. package/LICENSE +37 -17
  2. package/README.md +316 -106
  3. package/dist/cli.js +1641 -361
  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 +57 -16
  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/installs.js +0 -128
  47. package/dist/commands/installs.js.map +0 -1
  48. package/dist/commands/license.js +0 -39
  49. package/dist/commands/license.js.map +0 -1
  50. package/dist/commands/list.js +0 -47
  51. package/dist/commands/list.js.map +0 -1
  52. package/dist/commands/mcp.js +0 -29
  53. package/dist/commands/mcp.js.map +0 -1
  54. package/dist/commands/open.js +0 -28
  55. package/dist/commands/open.js.map +0 -1
  56. package/dist/commands/paste.js +0 -154
  57. package/dist/commands/paste.js.map +0 -1
  58. package/dist/commands/projects.js +0 -36
  59. package/dist/commands/projects.js.map +0 -1
  60. package/dist/commands/search.js +0 -67
  61. package/dist/commands/search.js.map +0 -1
  62. package/dist/commands/semantic.js +0 -173
  63. package/dist/commands/semantic.js.map +0 -1
  64. package/dist/commands/show.js +0 -121
  65. package/dist/commands/show.js.map +0 -1
  66. package/dist/commands/start.js +0 -47
  67. package/dist/commands/start.js.map +0 -1
  68. package/dist/commands/stats.js +0 -133
  69. package/dist/commands/stats.js.map +0 -1
  70. package/dist/commands/status.js +0 -45
  71. package/dist/commands/status.js.map +0 -1
  72. package/dist/commands/stop.js +0 -29
  73. package/dist/commands/stop.js.map +0 -1
  74. package/dist/commands/thread.js +0 -396
  75. package/dist/commands/thread.js.map +0 -1
  76. package/dist/context/formatter.js +0 -103
  77. package/dist/context/formatter.js.map +0 -1
  78. package/dist/daemon/auto-tag-config.js +0 -103
  79. package/dist/daemon/auto-tag-config.js.map +0 -1
  80. package/dist/daemon/auto-tag-config.test.js +0 -72
  81. package/dist/daemon/auto-tag-config.test.js.map +0 -1
  82. package/dist/daemon/auto-title-config.js +0 -70
  83. package/dist/daemon/auto-title-config.js.map +0 -1
  84. package/dist/daemon/bulk-title-jobs.js +0 -170
  85. package/dist/daemon/bulk-title-jobs.js.map +0 -1
  86. package/dist/daemon/correlator.js +0 -320
  87. package/dist/daemon/correlator.js.map +0 -1
  88. package/dist/daemon/discover.js +0 -316
  89. package/dist/daemon/discover.js.map +0 -1
  90. package/dist/daemon/editor-detection.js +0 -186
  91. package/dist/daemon/editor-detection.js.map +0 -1
  92. package/dist/daemon/entrypoint.js.map +0 -1
  93. package/dist/daemon/git-correlator.js +0 -256
  94. package/dist/daemon/git-correlator.js.map +0 -1
  95. package/dist/daemon/mcp-installer.js +0 -108
  96. package/dist/daemon/mcp-installer.js.map +0 -1
  97. package/dist/daemon/onboarding-state.js +0 -140
  98. package/dist/daemon/onboarding-state.js.map +0 -1
  99. package/dist/daemon/pidfile.js +0 -57
  100. package/dist/daemon/pidfile.js.map +0 -1
  101. package/dist/daemon/ports.js +0 -48
  102. package/dist/daemon/ports.js.map +0 -1
  103. package/dist/daemon/scanProgressRegistry.js +0 -62
  104. package/dist/daemon/scanProgressRegistry.js.map +0 -1
  105. package/dist/daemon/server.js +0 -2010
  106. package/dist/daemon/server.js.map +0 -1
  107. package/dist/daemon/tag-scanner/anthropic-client.js +0 -40
  108. package/dist/daemon/tag-scanner/anthropic-client.js.map +0 -1
  109. package/dist/daemon/tag-scanner/autopilot.js +0 -131
  110. package/dist/daemon/tag-scanner/autopilot.js.map +0 -1
  111. package/dist/daemon/tag-scanner/claude-cli-driver.js +0 -250
  112. package/dist/daemon/tag-scanner/claude-cli-driver.js.map +0 -1
  113. package/dist/daemon/tag-scanner/orchestrator.js +0 -88
  114. package/dist/daemon/tag-scanner/orchestrator.js.map +0 -1
  115. package/dist/daemon/tag-scanner/prompt.js +0 -46
  116. package/dist/daemon/tag-scanner/prompt.js.map +0 -1
  117. package/dist/daemon/tag-scanner/prompt.test.js +0 -48
  118. package/dist/daemon/tag-scanner/prompt.test.js.map +0 -1
  119. package/dist/daemon/tag-scanner/scan-state.js +0 -49
  120. package/dist/daemon/tag-scanner/scan-state.js.map +0 -1
  121. package/dist/daemon/tag-scanner/session-fetcher.js +0 -82
  122. package/dist/daemon/tag-scanner/session-fetcher.js.map +0 -1
  123. package/dist/daemon/tag-scanner/session-fetcher.test.js +0 -34
  124. package/dist/daemon/tag-scanner/session-fetcher.test.js.map +0 -1
  125. package/dist/daemon/tag-scanner/validator.js +0 -50
  126. package/dist/daemon/tag-scanner/validator.js.map +0 -1
  127. package/dist/daemon/tag-scanner/validator.test.js +0 -41
  128. package/dist/daemon/tag-scanner/validator.test.js.map +0 -1
  129. package/dist/daemon/terminal-registry.js +0 -443
  130. package/dist/daemon/terminal-registry.js.map +0 -1
  131. package/dist/daemon/ui.js +0 -64
  132. package/dist/daemon/ui.js.map +0 -1
  133. package/dist/daemon/watcher.js +0 -256
  134. package/dist/daemon/watcher.js.map +0 -1
  135. package/dist/db/client.js +0 -22
  136. package/dist/db/client.js.map +0 -1
  137. package/dist/db/schema.js +0 -496
  138. package/dist/db/schema.js.map +0 -1
  139. package/dist/license/api-base.js +0 -13
  140. package/dist/license/api-base.js.map +0 -1
  141. package/dist/license/manager.js +0 -43
  142. package/dist/license/manager.js.map +0 -1
  143. package/dist/license/public-key.js +0 -19
  144. package/dist/license/public-key.js.map +0 -1
  145. package/dist/license/storage.js +0 -27
  146. package/dist/license/storage.js.map +0 -1
  147. package/dist/license/verify.js +0 -23
  148. package/dist/license/verify.js.map +0 -1
  149. package/dist/mcp/audit.js +0 -126
  150. package/dist/mcp/audit.js.map +0 -1
  151. package/dist/mcp/prompts.js +0 -180
  152. package/dist/mcp/prompts.js.map +0 -1
  153. package/dist/mcp/server.js +0 -502
  154. package/dist/mcp/server.js.map +0 -1
  155. package/dist/mcp/thread-tools.js +0 -363
  156. package/dist/mcp/thread-tools.js.map +0 -1
  157. package/dist/mcp/write-tools.js +0 -239
  158. package/dist/mcp/write-tools.js.map +0 -1
  159. package/dist/parser/jsonl.js +0 -150
  160. package/dist/parser/jsonl.js.map +0 -1
  161. package/dist/semantic/chunker.js +0 -47
  162. package/dist/semantic/chunker.js.map +0 -1
  163. package/dist/semantic/config.js +0 -74
  164. package/dist/semantic/config.js.map +0 -1
  165. package/dist/semantic/embedder.js +0 -54
  166. package/dist/semantic/embedder.js.map +0 -1
  167. package/dist/semantic/fusion.js +0 -38
  168. package/dist/semantic/fusion.js.map +0 -1
  169. package/dist/semantic/model-download.js +0 -69
  170. package/dist/semantic/model-download.js.map +0 -1
  171. package/dist/semantic/pipeline.js +0 -375
  172. package/dist/semantic/pipeline.js.map +0 -1
  173. package/dist/semantic/query.js +0 -42
  174. package/dist/semantic/query.js.map +0 -1
  175. package/dist/semantic/worker.js +0 -78
  176. package/dist/semantic/worker.js.map +0 -1
  177. package/dist/stats/backfill.js +0 -151
  178. package/dist/stats/backfill.js.map +0 -1
  179. package/dist/stats/health.js +0 -102
  180. package/dist/stats/health.js.map +0 -1
  181. package/dist/stats/query.js +0 -385
  182. package/dist/stats/query.js.map +0 -1
  183. package/dist/utils/aliases.js +0 -107
  184. package/dist/utils/aliases.js.map +0 -1
  185. package/dist/utils/autoCollections.js +0 -635
  186. package/dist/utils/autoCollections.js.map +0 -1
  187. package/dist/utils/autoTitle.js +0 -348
  188. package/dist/utils/autoTitle.js.map +0 -1
  189. package/dist/utils/collections.js +0 -446
  190. package/dist/utils/collections.js.map +0 -1
  191. package/dist/utils/format.js +0 -46
  192. package/dist/utils/format.js.map +0 -1
  193. package/dist/utils/notes.js +0 -270
  194. package/dist/utils/notes.js.map +0 -1
  195. package/dist/utils/paths.js +0 -50
  196. package/dist/utils/paths.js.map +0 -1
  197. package/dist/utils/pricing.js +0 -257
  198. package/dist/utils/pricing.js.map +0 -1
  199. package/dist/utils/secret-scanner.js +0 -166
  200. package/dist/utils/secret-scanner.js.map +0 -1
  201. package/dist/utils/sessionLabel.js +0 -64
  202. package/dist/utils/sessionLabel.js.map +0 -1
  203. package/dist/utils/tags.js +0 -97
  204. package/dist/utils/tags.js.map +0 -1
  205. package/dist/utils/thread-context.js +0 -129
  206. package/dist/utils/thread-context.js.map +0 -1
  207. package/dist/utils/threadFilter.js +0 -18
  208. package/dist/utils/threadFilter.js.map +0 -1
  209. package/dist/utils/threads-titler.js +0 -298
  210. package/dist/utils/threads-titler.js.map +0 -1
  211. package/dist/utils/threads.js +0 -383
  212. package/dist/utils/threads.js.map +0 -1
  213. package/dist/utils/usage.js +0 -76
  214. package/dist/utils/usage.js.map +0 -1
  215. package/dist/verification/compute.js +0 -88
  216. package/dist/verification/compute.js.map +0 -1
  217. package/dist/verification/config.js +0 -34
  218. package/dist/verification/config.js.map +0 -1
  219. package/dist/web/assets/index-CIr6J4Fw.js +0 -1201
  220. package/dist/web/assets/index-Ctc8g9Jw.css +0 -1
@@ -1,88 +0,0 @@
1
- import { allTagsWithCounts, addTag } from '../../utils/tags.js';
2
- import { buildTagPrompt } from './prompt.js';
3
- import { parseScanResponse } from './validator.js';
4
- import { callAnthropic, withRetry } from './anthropic-client.js';
5
- import { emit } from './scan-state.js';
6
- /**
7
- * Run the scan in the background. Safe to call and not await — the scan
8
- * updates its own `rec` object. The caller subscribes via `subscribe()` for
9
- * progress events.
10
- */
11
- export async function runScan(rec, opts) {
12
- rec.status = 'running';
13
- emit(rec, { type: 'status', status: 'running' });
14
- const knownTags = allTagsWithCounts();
15
- for (const session of opts.sessions) {
16
- if (rec.controller.signal.aborted)
17
- break;
18
- const prompt = buildTagPrompt({
19
- session,
20
- knownTags,
21
- minTags: opts.minTags,
22
- maxTags: opts.maxTags,
23
- });
24
- const baseResult = {
25
- sessionId: session.id,
26
- project: session.project,
27
- alias: session.alias,
28
- first_user_message: session.first_user_message,
29
- current_tags: session.current_tags,
30
- suggestion: null,
31
- error: null,
32
- applied: false,
33
- };
34
- try {
35
- const raw = await withRetry(() => callAnthropic({
36
- apiKey: opts.apiKey,
37
- model: opts.model,
38
- prompt,
39
- signal: rec.controller.signal,
40
- }));
41
- const parsed = parseScanResponse(raw, { maxTags: opts.maxTags });
42
- if (parsed.ok) {
43
- baseResult.suggestion = parsed.data;
44
- }
45
- else {
46
- baseResult.error = parsed.reason;
47
- }
48
- }
49
- catch (err) {
50
- baseResult.error = err instanceof Error ? err.message : String(err);
51
- }
52
- rec.results.push(baseResult);
53
- rec.completed += 1;
54
- emit(rec, { type: 'result', result: baseResult });
55
- emit(rec, { type: 'progress', completed: rec.completed, total: rec.total });
56
- }
57
- if (!rec.controller.signal.aborted) {
58
- rec.status = 'completed';
59
- rec.finishedAt = new Date().toISOString();
60
- const ok = rec.results.filter((r) => r.suggestion && !r.error).length;
61
- const failed = rec.results.filter((r) => r.error).length;
62
- emit(rec, { type: 'done', summary: { ok, failed } });
63
- }
64
- }
65
- /** Apply selected tag suggestions from a completed scan. */
66
- export function applyScanSelection(rec, selection) {
67
- let applied = 0;
68
- let failed = 0;
69
- for (const item of selection) {
70
- const result = rec.results.find((r) => r.sessionId === item.sessionId);
71
- if (!result)
72
- continue;
73
- for (const tag of item.tags) {
74
- try {
75
- const { added } = addTag(item.sessionId, tag);
76
- if (added)
77
- applied += 1;
78
- }
79
- catch (err) {
80
- console.error('[scanner] apply failed:', item.sessionId, tag, err);
81
- failed += 1;
82
- }
83
- }
84
- result.applied = true;
85
- }
86
- return { applied, failed };
87
- }
88
- //# sourceMappingURL=orchestrator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAyB,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAUvC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAe,EAAE,IAAoB;IACjE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM;QAEzC,MAAM,MAAM,GAAG,cAAc,CAAC;YAC5B,OAAO;YACP,SAAS;YACT,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAqB;YACnC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,IAAI;YACX,OAAO,EAAE,KAAK;SACf,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAC/B,aAAa,CAAC;gBACZ,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM;gBACN,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,MAAM;aAC9B,CAAC,CACH,CAAC;YACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBACd,UAAU,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAU,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtE,CAAC;QAED,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;QACzB,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QACtE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QACzD,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,kBAAkB,CAChC,GAAe,EACf,SAAuD;IAEvD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;gBAC9C,IAAI,KAAK;oBAAE,OAAO,IAAI,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;gBACnE,MAAM,IAAI,CAAC,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"}
@@ -1,46 +0,0 @@
1
- /**
2
- * Produce a stable prompt. Known-tags list is truncated to 50 entries and
3
- * sorted by count desc (already sorted by `allTagsWithCounts`).
4
- */
5
- export function buildTagPrompt(input) {
6
- const { session, knownTags, minTags, maxTags } = input;
7
- const topTags = knownTags
8
- .slice(0, 50)
9
- .map((t) => t.tag)
10
- .join(', ');
11
- const currentTagsLine = session.current_tags.length > 0
12
- ? `already applied, do not repeat: [${session.current_tags.join(', ')}]`
13
- : 'currently has no tags';
14
- return [
15
- `You are tagging a software engineering session. Produce ${minTags}-${maxTags} concise, lowercase, hyphen-separated tags that describe:`,
16
- ' - the domain or subsystem touched (auth, db, frontend, ...)',
17
- ' - the kind of work (bugfix, feature, refactor, research, ...)',
18
- ' - any specific tool, library, or product if prominent',
19
- '',
20
- 'Prefer tags from the known-tags list below when applicable — consistency over creativity. Never invent marketing-sounding labels. Never tag based on speculation; only on observed work.',
21
- '',
22
- `known tags (most used first, up to 50): ${topTags || '(none yet)'}`,
23
- '',
24
- 'Session:',
25
- ` project: ${session.project}`,
26
- session.alias ? ` alias: ${JSON.stringify(session.alias)}` : ' alias: (none)',
27
- session.git_branch ? ` git_branch: ${session.git_branch}` : '',
28
- ` ${currentTagsLine}`,
29
- ' first_user_message:',
30
- indent(session.first_user_message, ' '),
31
- ' message_sample:',
32
- indent(session.message_sample, ' '),
33
- '',
34
- `Return a single JSON object matching this schema exactly, with no prose before or after:`,
35
- `{"tags": string[] length ${minTags}-${maxTags}, "confidence": number 0-1, "rationale": string one short sentence}`,
36
- ]
37
- .filter(Boolean)
38
- .join('\n');
39
- }
40
- function indent(text, prefix) {
41
- return text
42
- .split('\n')
43
- .map((line) => prefix + line)
44
- .join('\n');
45
- }
46
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/prompt.ts"],"names":[],"mappings":"AAuBA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACvD,MAAM,OAAO,GAAG,SAAS;SACtB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;SACjB,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,eAAe,GACnB,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAC7B,CAAC,CAAC,oCAAoC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACxE,CAAC,CAAC,uBAAuB,CAAC;IAE9B,OAAO;QACL,2DAA2D,OAAO,IAAI,OAAO,2DAA2D;QACxI,+DAA+D;QAC/D,iEAAiE;QACjE,yDAAyD;QACzD,EAAE;QACF,0LAA0L;QAC1L,EAAE;QACF,2CAA2C,OAAO,IAAI,YAAY,EAAE;QACpE,EAAE;QACF,UAAU;QACV,cAAc,OAAO,CAAC,OAAO,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;QAC/E,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;QAC/D,KAAK,eAAe,EAAE;QACtB,uBAAuB;QACvB,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC;QAC1C,mBAAmB;QACnB,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QACtC,EAAE;QACF,0FAA0F;QAC1F,4BAA4B,OAAO,IAAI,OAAO,qEAAqE;KACpH;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,MAAc;IAC1C,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -1,48 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('buildTagPrompt', () => {
4
- it('includes known tags sorted by popularity', async () => {
5
- const { buildTagPrompt } = await import('./prompt.js');
6
- const out = buildTagPrompt({
7
- session: {
8
- id: 'abc',
9
- alias: null,
10
- project: 'demo',
11
- git_branch: 'main',
12
- first_user_message: 'fix the auth bug',
13
- message_sample: 'system: ...\nuser: fix the auth bug',
14
- current_tags: [],
15
- },
16
- knownTags: [
17
- { tag: 'auth', count: 42 },
18
- { tag: 'feature', count: 10 },
19
- ],
20
- minTags: 2,
21
- maxTags: 4,
22
- });
23
- assert.ok(out.includes('known tags'), 'output should mention known tags');
24
- assert.ok(out.indexOf('auth') < out.indexOf('feature'), 'auth should come before feature');
25
- assert.ok(out.includes('2-4'), 'output should mention 2-4 range');
26
- assert.ok(out.includes('fix the auth bug'), 'output should include first user message');
27
- });
28
- it('mentions current_tags as "already applied, do not repeat"', async () => {
29
- const { buildTagPrompt } = await import('./prompt.js');
30
- const out = buildTagPrompt({
31
- session: {
32
- id: 'x',
33
- alias: 'webhook retry',
34
- project: 'api',
35
- git_branch: null,
36
- first_user_message: 'add exp backoff to webhook delivery',
37
- message_sample: 'user: ...',
38
- current_tags: ['webhook'],
39
- },
40
- knownTags: [],
41
- minTags: 2,
42
- maxTags: 4,
43
- });
44
- assert.match(out, /already applied/i);
45
- assert.ok(out.includes('webhook'), 'output should include the existing tag');
46
- });
47
- });
48
- //# sourceMappingURL=prompt.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/prompt.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,cAAc,CAAC;YACzB,OAAO,EAAE;gBACP,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,MAAM;gBAClB,kBAAkB,EAAE,kBAAkB;gBACtC,cAAc,EAAE,qCAAqC;gBACrD,YAAY,EAAE,EAAE;aACjB;YACD,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC1B,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;aAC9B;YACD,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,kCAAkC,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAC3F,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,0CAA0C,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,cAAc,CAAC;YACzB,OAAO,EAAE;gBACP,EAAE,EAAE,GAAG;gBACP,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,IAAI;gBAChB,kBAAkB,EAAE,qCAAqC;gBACzD,cAAc,EAAE,WAAW;gBAC3B,YAAY,EAAE,CAAC,SAAS,CAAC;aAC1B;YACD,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,wCAAwC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,49 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- const scans = new Map();
3
- export function createScan(total) {
4
- const rec = {
5
- id: randomUUID(),
6
- status: 'pending',
7
- createdAt: new Date().toISOString(),
8
- finishedAt: null,
9
- total,
10
- completed: 0,
11
- results: [],
12
- error: null,
13
- controller: new AbortController(),
14
- listeners: new Set(),
15
- };
16
- scans.set(rec.id, rec);
17
- return rec;
18
- }
19
- export function getScan(id) {
20
- return scans.get(id);
21
- }
22
- export function emit(rec, ev) {
23
- for (const l of rec.listeners)
24
- l(ev);
25
- }
26
- export function subscribe(rec, listener) {
27
- rec.listeners.add(listener);
28
- return () => {
29
- rec.listeners.delete(listener);
30
- };
31
- }
32
- export function cancelScan(id) {
33
- const rec = scans.get(id);
34
- if (!rec)
35
- return false;
36
- rec.controller.abort();
37
- rec.status = 'cancelled';
38
- rec.finishedAt = new Date().toISOString();
39
- emit(rec, { type: 'status', status: 'cancelled' });
40
- return true;
41
- }
42
- export function deleteScan(id) {
43
- return scans.delete(id);
44
- }
45
- /** Used in tests — clears all scans. */
46
- export function clearScansForTest() {
47
- scans.clear();
48
- }
49
- //# sourceMappingURL=scan-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan-state.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/scan-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAmCzC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,GAAG,GAAe;QACtB,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,IAAI;QAChB,KAAK;QACL,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI,eAAe,EAAE;QACjC,SAAS,EAAE,IAAI,GAAG,EAAE;KACrB,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAe,EAAE,EAAa;IACjD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,SAAS;QAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAe,EAAE,QAAiC;IAC1E,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,GAAG,EAAE;QACV,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACvB,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;IACzB,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,iBAAiB;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -1,82 +0,0 @@
1
- import { getDb } from '../../db/client.js';
2
- import { tagsForSession } from '../../utils/tags.js';
3
- /**
4
- * Deterministically pick up to `target` messages from `msgs`, skipping any
5
- * with empty content. When the pool is larger than the target, always keep
6
- * the first and last and spread the remainder evenly across the middle.
7
- */
8
- export function sampleMessages(msgs, target) {
9
- const nonEmpty = msgs.filter((m) => m.content_text && m.content_text.trim().length > 0);
10
- if (nonEmpty.length <= target)
11
- return nonEmpty;
12
- const picks = new Set();
13
- picks.add(0);
14
- picks.add(nonEmpty.length - 1);
15
- const stride = (nonEmpty.length - 2) / Math.max(1, target - 2);
16
- for (let i = 1; i < target - 1; i++) {
17
- picks.add(Math.floor(i * stride));
18
- }
19
- return Array.from(picks)
20
- .sort((a, b) => a - b)
21
- .slice(0, target)
22
- .map((i) => nonEmpty[i]);
23
- }
24
- export function listSessionsForScan(filter) {
25
- const db = getDb();
26
- const params = { limit: filter.limit ?? 500 };
27
- // When caller passes explicit sessionIds, skip the message-count gate —
28
- // the user has already decided which session to scan.
29
- const hasExplicitIds = filter.sessionIds && filter.sessionIds.length > 0;
30
- let where = hasExplicitIds ? '1=1' : 's.message_count > 2';
31
- if (hasExplicitIds) {
32
- const placeholders = filter.sessionIds.map((_, i) => `@sid_${i}`).join(', ');
33
- where += ` AND s.id IN (${placeholders})`;
34
- filter.sessionIds.forEach((id, i) => {
35
- params[`sid_${i}`] = id;
36
- });
37
- }
38
- if (filter.untaggedOnly) {
39
- where += ' AND NOT EXISTS (SELECT 1 FROM session_tags st WHERE st.session_id = s.id)';
40
- }
41
- if (filter.project) {
42
- where += ' AND p.name = @project';
43
- params.project = filter.project;
44
- }
45
- if (filter.collectionId) {
46
- where +=
47
- ' AND s.id IN (SELECT session_id FROM collection_sessions WHERE collection_id = @col)';
48
- params.col = filter.collectionId;
49
- }
50
- const sessions = db
51
- .prepare(`SELECT s.id, p.name AS project, s.git_branch,
52
- NULLIF(sa.alias, '') AS alias,
53
- COALESCE(s.first_user_message, '') AS first_user_message
54
- FROM sessions s
55
- JOIN projects p ON p.id = s.project_id
56
- LEFT JOIN session_aliases sa ON sa.session_id = s.id
57
- WHERE ${where}
58
- ORDER BY COALESCE(s.started_at, '') DESC
59
- LIMIT @limit`)
60
- .all(params);
61
- return sessions.map((s) => {
62
- const msgs = db
63
- .prepare(`SELECT role, COALESCE(content_text, '') AS content_text
64
- FROM messages WHERE session_id = ?
65
- ORDER BY COALESCE(timestamp, ''), rowid`)
66
- .all(s.id);
67
- const sampled = sampleMessages(msgs, 5);
68
- const messageSample = sampled
69
- .map((m) => `${m.role}: ${m.content_text.slice(0, 400)}`)
70
- .join('\n---\n');
71
- return {
72
- id: s.id,
73
- project: s.project,
74
- git_branch: s.git_branch,
75
- alias: s.alias,
76
- first_user_message: s.first_user_message,
77
- message_sample: messageSample,
78
- current_tags: tagsForSession(s.id),
79
- };
80
- });
81
- }
82
- //# sourceMappingURL=session-fetcher.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-fetcher.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/session-fetcher.ts"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('sampleMessages', () => {
4
- it('returns all messages if there are fewer than targetCount', async () => {
5
- const { sampleMessages } = await import('./session-fetcher.js');
6
- const msgs = [
7
- { role: 'user', content_text: 'one' },
8
- { role: 'assistant', content_text: 'two' },
9
- ];
10
- const out = sampleMessages(msgs, 5);
11
- assert.equal(out.length, 2);
12
- });
13
- it('picks first, middle, last when count exceeds target', async () => {
14
- const { sampleMessages } = await import('./session-fetcher.js');
15
- const msgs = Array.from({ length: 20 }, (_, i) => ({
16
- role: 'user',
17
- content_text: `msg-${i}`,
18
- }));
19
- const out = sampleMessages(msgs, 3);
20
- assert.equal(out[0].content_text, 'msg-0');
21
- assert.equal(out[out.length - 1].content_text, 'msg-19');
22
- assert.equal(out.length, 3);
23
- });
24
- it('skips empty content', async () => {
25
- const { sampleMessages } = await import('./session-fetcher.js');
26
- const msgs = [
27
- { role: 'user', content_text: '' },
28
- { role: 'user', content_text: 'real' },
29
- ];
30
- const out = sampleMessages(msgs, 5);
31
- assert.equal(out.length, 1);
32
- });
33
- });
34
- //# sourceMappingURL=session-fetcher.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-fetcher.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/session-fetcher.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG;YACX,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE;YACrC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE;SAC3C,CAAC;QACF,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,MAAe;YACrB,YAAY,EAAE,OAAO,CAAC,EAAE;SACzB,CAAC,CAAC,CAAC;QACJ,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG;YACX,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE;YAClC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE;SACvC,CAAC;QACF,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,50 +0,0 @@
1
- import { z } from 'zod';
2
- import { normalizeTag } from '../../utils/tags.js';
3
- const RawSchema = z.object({
4
- tags: z.array(z.string()).min(1),
5
- confidence: z.number().min(0).max(1),
6
- rationale: z.string().min(1).max(500),
7
- });
8
- /** Strip common wrappers LLMs like to add around JSON. */
9
- function stripFences(raw) {
10
- const trimmed = raw.trim();
11
- if (!trimmed.startsWith('```'))
12
- return trimmed;
13
- return trimmed
14
- .replace(/^```(?:json)?\s*/i, '')
15
- .replace(/```$/i, '')
16
- .trim();
17
- }
18
- export function parseScanResponse(raw, opts = {}) {
19
- const maxTags = opts.maxTags ?? 10;
20
- let obj;
21
- try {
22
- obj = JSON.parse(stripFences(raw));
23
- }
24
- catch {
25
- return { ok: false, reason: 'not valid JSON' };
26
- }
27
- const parsed = RawSchema.safeParse(obj);
28
- if (!parsed.success) {
29
- return {
30
- ok: false,
31
- reason: parsed.error.issues.map((i) => i.message).join('; '),
32
- };
33
- }
34
- const normalized = parsed.data.tags
35
- .map((t) => normalizeTag(t))
36
- .filter((t) => t.length > 0);
37
- const unique = Array.from(new Set(normalized)).slice(0, maxTags);
38
- if (unique.length === 0) {
39
- return { ok: false, reason: 'no usable tags after normalization' };
40
- }
41
- return {
42
- ok: true,
43
- data: {
44
- tags: unique,
45
- confidence: parsed.data.confidence,
46
- rationale: parsed.data.rationale,
47
- },
48
- };
49
- }
50
- //# sourceMappingURL=validator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACtC,CAAC,CAAC;AAYH,0DAA0D;AAC1D,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,OAAO;SACX,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;SAChC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,OAA6B,EAAE;IAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7D,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IACrE,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU;YAClC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS;SACjC;KACF,CAAC;AACJ,CAAC"}
@@ -1,41 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('parseScanResponse', () => {
4
- it('accepts valid JSON payload', async () => {
5
- const { parseScanResponse } = await import('./validator.js');
6
- const r = parseScanResponse('{"tags":["auth","bugfix"],"confidence":0.9,"rationale":"middleware fix"}');
7
- assert.equal(r.ok, true);
8
- if (r.ok)
9
- assert.deepEqual(r.data.tags, ['auth', 'bugfix']);
10
- });
11
- it('strips markdown code fences', async () => {
12
- const { parseScanResponse } = await import('./validator.js');
13
- const r = parseScanResponse('```json\n{"tags":["x","y"],"confidence":0.5,"rationale":"test"}\n```');
14
- assert.equal(r.ok, true);
15
- });
16
- it('normalizes tags via normalizeTag', async () => {
17
- const { parseScanResponse } = await import('./validator.js');
18
- const r = parseScanResponse('{"tags":["#Auth/Flow"," bug FIX "],"confidence":0.8,"rationale":"x"}');
19
- assert.equal(r.ok, true);
20
- if (r.ok)
21
- assert.deepEqual(r.data.tags, ['auth-flow', 'bug-fix']);
22
- });
23
- it('rejects empty tags array', async () => {
24
- const { parseScanResponse } = await import('./validator.js');
25
- const r = parseScanResponse('{"tags":[],"confidence":0.5,"rationale":"x"}');
26
- assert.equal(r.ok, false);
27
- });
28
- it('rejects malformed JSON', async () => {
29
- const { parseScanResponse } = await import('./validator.js');
30
- const r = parseScanResponse('not json at all');
31
- assert.equal(r.ok, false);
32
- });
33
- it('caps tags at maxTags', async () => {
34
- const { parseScanResponse } = await import('./validator.js');
35
- const r = parseScanResponse('{"tags":["a","b","c","d","e","f"],"confidence":0.9,"rationale":"x"}', { maxTags: 3 });
36
- assert.equal(r.ok, true);
37
- if (r.ok)
38
- assert.equal(r.data.tags.length, 3);
39
- });
40
- });
41
- //# sourceMappingURL=validator.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/validator.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,0EAA0E,CAC3E,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,sEAAsE,CACvE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,wEAAwE,CACzE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CAAC,8CAA8C,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,qEAAqE,EACrE,EAAE,OAAO,EAAE,CAAC,EAAE,CACf,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}