@tznthou/ccrecall 0.1.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 (87) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +290 -0
  3. package/README_ZH.md +288 -0
  4. package/dist/api/routes.d.ts +13 -0
  5. package/dist/api/routes.d.ts.map +1 -0
  6. package/dist/api/routes.js +428 -0
  7. package/dist/api/routes.js.map +1 -0
  8. package/dist/api/server.d.ts +7 -0
  9. package/dist/api/server.d.ts.map +1 -0
  10. package/dist/api/server.js +44 -0
  11. package/dist/api/server.js.map +1 -0
  12. package/dist/cli/daemon.d.ts +35 -0
  13. package/dist/cli/daemon.d.ts.map +1 -0
  14. package/dist/cli/daemon.js +163 -0
  15. package/dist/cli/daemon.js.map +1 -0
  16. package/dist/core/compression.d.ts +37 -0
  17. package/dist/core/compression.d.ts.map +1 -0
  18. package/dist/core/compression.js +129 -0
  19. package/dist/core/compression.js.map +1 -0
  20. package/dist/core/database.d.ts +219 -0
  21. package/dist/core/database.d.ts.map +1 -0
  22. package/dist/core/database.js +1513 -0
  23. package/dist/core/database.js.map +1 -0
  24. package/dist/core/index.d.ts +9 -0
  25. package/dist/core/index.d.ts.map +1 -0
  26. package/dist/core/index.js +8 -0
  27. package/dist/core/index.js.map +1 -0
  28. package/dist/core/indexer.d.ts +15 -0
  29. package/dist/core/indexer.d.ts.map +1 -0
  30. package/dist/core/indexer.js +224 -0
  31. package/dist/core/indexer.js.map +1 -0
  32. package/dist/core/lint.d.ts +17 -0
  33. package/dist/core/lint.d.ts.map +1 -0
  34. package/dist/core/lint.js +51 -0
  35. package/dist/core/lint.js.map +1 -0
  36. package/dist/core/log-safe.d.ts +6 -0
  37. package/dist/core/log-safe.d.ts.map +1 -0
  38. package/dist/core/log-safe.js +11 -0
  39. package/dist/core/log-safe.js.map +1 -0
  40. package/dist/core/maintenance-coordinator.d.ts +26 -0
  41. package/dist/core/maintenance-coordinator.d.ts.map +1 -0
  42. package/dist/core/maintenance-coordinator.js +67 -0
  43. package/dist/core/maintenance-coordinator.js.map +1 -0
  44. package/dist/core/memory-service.d.ts +31 -0
  45. package/dist/core/memory-service.d.ts.map +1 -0
  46. package/dist/core/memory-service.js +47 -0
  47. package/dist/core/memory-service.js.map +1 -0
  48. package/dist/core/parser.d.ts +17 -0
  49. package/dist/core/parser.d.ts.map +1 -0
  50. package/dist/core/parser.js +205 -0
  51. package/dist/core/parser.js.map +1 -0
  52. package/dist/core/scanner.d.ts +8 -0
  53. package/dist/core/scanner.d.ts.map +1 -0
  54. package/dist/core/scanner.js +123 -0
  55. package/dist/core/scanner.js.map +1 -0
  56. package/dist/core/summarizer.d.ts +12 -0
  57. package/dist/core/summarizer.d.ts.map +1 -0
  58. package/dist/core/summarizer.js +430 -0
  59. package/dist/core/summarizer.js.map +1 -0
  60. package/dist/core/topic-extractor.d.ts +11 -0
  61. package/dist/core/topic-extractor.d.ts.map +1 -0
  62. package/dist/core/topic-extractor.js +51 -0
  63. package/dist/core/topic-extractor.js.map +1 -0
  64. package/dist/core/types.d.ts +329 -0
  65. package/dist/core/types.d.ts.map +1 -0
  66. package/dist/core/types.js +12 -0
  67. package/dist/core/types.js.map +1 -0
  68. package/dist/core/watcher.d.ts +30 -0
  69. package/dist/core/watcher.d.ts.map +1 -0
  70. package/dist/core/watcher.js +146 -0
  71. package/dist/core/watcher.js.map +1 -0
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +116 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/mcp/server.d.ts +3 -0
  77. package/dist/mcp/server.d.ts.map +1 -0
  78. package/dist/mcp/server.js +32 -0
  79. package/dist/mcp/server.js.map +1 -0
  80. package/dist/mcp/tools.d.ts +39 -0
  81. package/dist/mcp/tools.d.ts.map +1 -0
  82. package/dist/mcp/tools.js +215 -0
  83. package/dist/mcp/tools.js.map +1 -0
  84. package/hooks/README.md +78 -0
  85. package/hooks/session-end.mjs +92 -0
  86. package/hooks/session-start.mjs +112 -0
  87. package/package.json +54 -0
@@ -0,0 +1,430 @@
1
+ /** 摘要引擎版本(每次規則改動時遞增,讓 backfill 可追蹤) */
2
+ export const SUMMARY_VERSION = 1;
3
+ const MAX_INTENT_LEN = 120;
4
+ const MAX_SUMMARY_LEN = 300;
5
+ const MAX_ACTIVITY_LEN = 80;
6
+ const MAX_FILES = 30;
7
+ // ── Noise Filter ──
8
+ /** 排除的路徑模式(反向索引噪音過濾) */
9
+ const NOISE_PATH_PATTERNS = [
10
+ /node_modules\//,
11
+ /\.git\//,
12
+ /\/dist\//,
13
+ /\/build\//,
14
+ /\/\.next\//,
15
+ /\/\.cache\//,
16
+ /\/\.vite\//,
17
+ /\/coverage\//,
18
+ ];
19
+ function isNoisePath(filePath) {
20
+ return NOISE_PATH_PATTERNS.some(p => p.test(filePath));
21
+ }
22
+ // ── Greeting / Continuation Filter ──
23
+ const SKIP_PATTERNS = [
24
+ /^(hey|hi|hello|yo|sup)\b/i,
25
+ /^(thanks|thank you|thx)\b/i,
26
+ /^(ok|okay|sure|yes|no|yep|nope|got it|sounds good)\b/i,
27
+ /^(continue|go ahead|proceed|keep going|carry on|let's go|go)\b/i,
28
+ /^(繼續|好的|沒問題|開始|來吧)\b/,
29
+ ];
30
+ /** 是否為空洞開頭(greeting / continuation / 太短) */
31
+ function isHollowMessage(text) {
32
+ const trimmed = text.trim();
33
+ if (trimmed.length < 5)
34
+ return true;
35
+ return SKIP_PATTERNS.some(p => p.test(trimmed));
36
+ }
37
+ // ── Intent Extraction ──
38
+ function truncate(text, max) {
39
+ if (text.length <= max)
40
+ return text;
41
+ return text.slice(0, max - 1) + '…';
42
+ }
43
+ /** 從 user messages 提取意圖文字:跳過 greeting,找第一句實質內容 */
44
+ function extractIntent(userMessages) {
45
+ for (const msg of userMessages) {
46
+ const text = msg.contentText?.trim();
47
+ if (!text)
48
+ continue;
49
+ if (isHollowMessage(text))
50
+ continue;
51
+ // 取第一行或前 N 字作為意圖
52
+ const firstLine = text.split('\n')[0].trim();
53
+ return truncate(firstLine, MAX_INTENT_LEN);
54
+ }
55
+ // fallback: 如果所有 user message 都是空洞的,取第一筆有內容的
56
+ for (const msg of userMessages) {
57
+ const text = msg.contentText?.trim();
58
+ if (text && text.length > 0) {
59
+ return truncate(text.split('\n')[0].trim(), MAX_INTENT_LEN);
60
+ }
61
+ }
62
+ return '';
63
+ }
64
+ // ── Activity Summary ──
65
+ /** 從 tool 使用統計和檔案數量生成動作概要 */
66
+ function buildActivityText(toolCounts, fileCount) {
67
+ if (toolCounts.size === 0 && fileCount === 0)
68
+ return '';
69
+ const parts = [];
70
+ // 主要 mutation tools 優先顯示
71
+ const mutationTools = ['Edit', 'Write', 'Bash'];
72
+ for (const tool of mutationTools) {
73
+ const count = toolCounts.get(tool);
74
+ if (count && count > 0) {
75
+ parts.push(`${tool}×${count}`);
76
+ }
77
+ }
78
+ // 如果沒有 mutation tools,顯示 discovery tools
79
+ if (parts.length === 0) {
80
+ const discoveryTools = ['Read', 'Grep', 'Glob'];
81
+ for (const tool of discoveryTools) {
82
+ const count = toolCounts.get(tool);
83
+ if (count && count > 0) {
84
+ parts.push(`${tool}×${count}`);
85
+ }
86
+ }
87
+ }
88
+ if (fileCount > 0) {
89
+ parts.push(`${fileCount} files`);
90
+ }
91
+ return truncate(parts.join(', '), MAX_ACTIVITY_LEN);
92
+ }
93
+ // ── Outcome Inference ──
94
+ const GIT_COMMIT_RE = /\bgit\s+commit\b/;
95
+ const TEST_COMMAND_RE = /\b(npm\s+test|npx\s+vitest|pnpm\s+(test|vitest)|pytest|jest|cargo\s+test|go\s+test)\b/;
96
+ const OUTCOME_LABELS = {
97
+ 'committed': '→ committed',
98
+ 'tested': '→ tested',
99
+ 'in-progress': '→ in-progress',
100
+ 'quick-qa': '(Q&A)',
101
+ };
102
+ /** 從最後幾輪的 tool 模式推斷 outcome */
103
+ function inferOutcome(messages) {
104
+ const signals = {
105
+ gitCommitInvoked: false,
106
+ testCommandRan: false,
107
+ endedWithEdits: false,
108
+ isQuickQA: false,
109
+ };
110
+ // 掃描 Bash tool 的 input 內容尋找 git commit / test 指令(先掃再判 quick-qa)
111
+ for (const msg of messages) {
112
+ if (!msg.hasToolUse || !msg.contentJson)
113
+ continue;
114
+ try {
115
+ const content = JSON.parse(msg.contentJson);
116
+ for (const block of content) {
117
+ if (typeof block !== 'object' || block === null)
118
+ continue;
119
+ const b = block;
120
+ if (b.type !== 'tool_use')
121
+ continue;
122
+ const name = b.name;
123
+ if (name !== 'Bash')
124
+ continue;
125
+ const input = b.input;
126
+ const command = input?.command ?? '';
127
+ if (GIT_COMMIT_RE.test(command)) {
128
+ signals.gitCommitInvoked = true;
129
+ }
130
+ if (TEST_COMMAND_RE.test(command)) {
131
+ signals.testCommandRan = true;
132
+ }
133
+ }
134
+ }
135
+ catch { /* malformed contentJson */ }
136
+ }
137
+ // 最後 3 輪的 tool 模式
138
+ const lastFew = messages.slice(-3);
139
+ const lastToolNames = lastFew.flatMap(m => m.toolNames);
140
+ if (lastToolNames.some(t => t === 'Edit' || t === 'Write')) {
141
+ signals.endedWithEdits = true;
142
+ }
143
+ // 推斷(保守:只在高信心時標記)
144
+ // 先檢查具體 outcome,再判斷 quick-qa(避免短 session 有明確動作但被誤判)
145
+ if (signals.gitCommitInvoked)
146
+ return { status: 'committed', signals };
147
+ if (signals.testCommandRan)
148
+ return { status: 'tested', signals };
149
+ if (signals.endedWithEdits)
150
+ return { status: 'in-progress', signals };
151
+ // Quick QA:短 session 且幾乎無 tool_use,且無具體 outcome
152
+ const toolUseCount = messages.filter(m => m.hasToolUse).length;
153
+ if (messages.length < 6 && toolUseCount <= 1) {
154
+ signals.isQuickQA = true;
155
+ return { status: 'quick-qa', signals };
156
+ }
157
+ return { status: null, signals };
158
+ }
159
+ // ── Multi-Signal Tags ──
160
+ /** 文字 regex 標籤規則(擴充至 20+ 條) */
161
+ const TEXT_TAG_RULES = [
162
+ // 原有 8 條
163
+ { pattern: /\b(fix|bug|error|broken|crash|issue)\b/, tag: 'bug-fix' },
164
+ { pattern: /\b(refactor|rename|restructure|cleanup|simplify)\b/, tag: 'refactor' },
165
+ { pattern: /\b(test|spec|vitest|jest|pytest|coverage)\b/, tag: 'testing' },
166
+ { pattern: /\b(deploy|release|version|publish|ci|cd)\b/, tag: 'deployment' },
167
+ { pattern: /\b(auth|login|token|password|oauth)\b/, tag: 'auth' },
168
+ { pattern: /\b(style|css|theme|layout|responsive)\b/, tag: 'ui' },
169
+ { pattern: /\b(doc|readme|jsdoc|comment|changelog)\b/, tag: 'docs' },
170
+ { pattern: /\b(config|env|setup|install|init)\b/, tag: 'config' },
171
+ // 新增
172
+ { pattern: /\b(perf|performance|optimize|speed|slow|fast|cache)\b/, tag: 'performance' },
173
+ { pattern: /\b(database|sql|sqlite|postgres|mysql|migration|schema)\b/, tag: 'database' },
174
+ { pattern: /\b(api|endpoint|route|rest|graphql|grpc)\b/, tag: 'api' },
175
+ { pattern: /\b(security|vulnerability|xss|csrf|injection|sanitize)\b/, tag: 'security' },
176
+ { pattern: /\b(docker|container|kubernetes|k8s|compose)\b/, tag: 'infra' },
177
+ { pattern: /\b(build|webpack|vite|esbuild|bundle|compile)\b/, tag: 'build' },
178
+ { pattern: /\b(type|typescript|interface|generic|typing)\b/, tag: 'types' },
179
+ { pattern: /\b(lint|eslint|prettier|format)\b/, tag: 'lint' },
180
+ { pattern: /\b(hook|middleware|plugin|extension)\b/, tag: 'architecture' },
181
+ { pattern: /\b(upload|download|file|image|asset|media)\b/, tag: 'files' },
182
+ { pattern: /\b(email|notification|alert|webhook)\b/, tag: 'messaging' },
183
+ { pattern: /\b(i18n|l10n|translate|locale|language)\b/, tag: 'i18n' },
184
+ ];
185
+ /** 路徑 → 標籤推斷規則(module-level 避免每次呼叫重建 regex) */
186
+ const PATH_TAG_RULES = [
187
+ { test: (p) => /\.(css|scss|sass|less|styled)/.test(p) || /\/styles?\//.test(p), tag: 'ui' },
188
+ { test: (p) => /\.(test|spec)\.(ts|tsx|js|jsx)/.test(p) || /\/__tests__\//.test(p) || /\/tests?\//.test(p), tag: 'testing' },
189
+ { test: (p) => /migration/.test(p) || /\.sql$/.test(p), tag: 'database' },
190
+ { test: (p) => /docker|compose/.test(p) || /\.dockerfile$/i.test(p), tag: 'infra' },
191
+ { test: (p) => /\.md$/.test(p) || /readme/i.test(p) || /changelog/i.test(p), tag: 'docs' },
192
+ { test: (p) => /\.(json|ya?ml|toml|ini|env)$/.test(p) && !/package-lock|yarn\.lock/.test(p), tag: 'config' },
193
+ { test: (p) => /auth|login/.test(p), tag: 'auth' },
194
+ { test: (p) => /route|api|endpoint/.test(p), tag: 'api' },
195
+ ];
196
+ /** 從檔案路徑推斷標籤 */
197
+ function tagsFromPaths(filePaths) {
198
+ const tags = new Set();
199
+ for (const p of filePaths) {
200
+ const lower = p.toLowerCase();
201
+ for (const rule of PATH_TAG_RULES) {
202
+ if (rule.test(lower))
203
+ tags.add(rule.tag);
204
+ }
205
+ }
206
+ return tags;
207
+ }
208
+ /** 從工具使用模式推斷標籤 */
209
+ function tagsFromToolPatterns(toolCounts) {
210
+ const tags = new Set();
211
+ const editCount = toolCounts.get('Edit') ?? 0;
212
+ const readCount = toolCounts.get('Read') ?? 0;
213
+ const bashCount = toolCounts.get('Bash') ?? 0;
214
+ const writeCount = toolCounts.get('Write') ?? 0;
215
+ // 大量 Read + 少量 Edit = code review
216
+ if (readCount > 5 && editCount <= 1 && writeCount === 0)
217
+ tags.add('code-review');
218
+ // 大量 Edit = refactor(如果還沒有 bug-fix tag)
219
+ if (editCount > 5)
220
+ tags.add('refactor');
221
+ // Bash 密集 = debugging 或 deployment
222
+ if (bashCount > 5 && editCount <= 2)
223
+ tags.add('debugging');
224
+ // 大量 Write = scaffolding / 新功能
225
+ if (writeCount > 3)
226
+ tags.add('scaffolding');
227
+ return tags;
228
+ }
229
+ /** outcome → tag 映射 */
230
+ function tagsFromOutcome(status) {
231
+ const tags = new Set();
232
+ if (status === 'committed')
233
+ tags.add('committed');
234
+ if (status === 'tested')
235
+ tags.add('tested');
236
+ return tags;
237
+ }
238
+ // ── File Path Extraction + session_files ──
239
+ /** tool name → operation 映射 */
240
+ const TOOL_OPERATION_MAP = {
241
+ Read: 'read',
242
+ Edit: 'edit',
243
+ Write: 'write',
244
+ Glob: 'discovery',
245
+ Grep: 'discovery',
246
+ };
247
+ /** tool name → file_path input key 映射 */
248
+ const FILE_PATH_KEYS = {
249
+ Read: 'file_path',
250
+ Edit: 'file_path',
251
+ Write: 'file_path',
252
+ Glob: 'path',
253
+ Grep: 'path',
254
+ };
255
+ /** 從 messages 提取所有檔案事件 */
256
+ function extractFileEvents(messages) {
257
+ const events = [];
258
+ for (let seq = 0; seq < messages.length; seq++) {
259
+ const msg = messages[seq];
260
+ if (!msg.hasToolUse || !msg.contentJson)
261
+ continue;
262
+ try {
263
+ const content = JSON.parse(msg.contentJson);
264
+ for (const block of content) {
265
+ if (typeof block !== 'object' || block === null)
266
+ continue;
267
+ const b = block;
268
+ if (b.type !== 'tool_use')
269
+ continue;
270
+ const name = b.name;
271
+ const pathKey = FILE_PATH_KEYS[name];
272
+ if (!pathKey)
273
+ continue;
274
+ const input = b.input;
275
+ const filePath = input?.[pathKey];
276
+ if (typeof filePath !== 'string' || !filePath)
277
+ continue;
278
+ if (isNoisePath(filePath))
279
+ continue;
280
+ const operation = TOOL_OPERATION_MAP[name] ?? 'discovery';
281
+ events.push({ filePath, operation, sequence: seq });
282
+ }
283
+ }
284
+ catch { /* malformed contentJson */ }
285
+ }
286
+ return events;
287
+ }
288
+ /** 從 file events 聚合成 session_files 記錄 */
289
+ function aggregateFileEvents(events) {
290
+ const map = new Map();
291
+ for (const e of events) {
292
+ const key = `${e.filePath}::${e.operation}`;
293
+ const existing = map.get(key);
294
+ if (existing) {
295
+ existing.count++;
296
+ if (e.sequence < existing.firstSeenSeq)
297
+ existing.firstSeenSeq = e.sequence;
298
+ if (e.sequence > existing.lastSeenSeq)
299
+ existing.lastSeenSeq = e.sequence;
300
+ }
301
+ else {
302
+ map.set(key, {
303
+ filePath: e.filePath,
304
+ operation: e.operation,
305
+ count: 1,
306
+ firstSeenSeq: e.sequence,
307
+ lastSeenSeq: e.sequence,
308
+ });
309
+ }
310
+ }
311
+ return [...map.values()];
312
+ }
313
+ // ── Duration ──
314
+ function computeDuration(startedAt, endedAt) {
315
+ if (!startedAt || !endedAt)
316
+ return null;
317
+ const start = new Date(startedAt).getTime();
318
+ const end = new Date(endedAt).getTime();
319
+ if (isNaN(start) || isNaN(end) || end <= start)
320
+ return null;
321
+ return Math.round((end - start) / 1000);
322
+ }
323
+ // ── Active Time ──
324
+ const IDLE_THRESHOLD_SECONDS = 300;
325
+ /** 計算 active time:累加相鄰 message 間 ≤ 5 分鐘的間隔秒數 */
326
+ export function computeActiveTime(messages) {
327
+ const withTimestamp = messages.filter(m => m.timestamp != null);
328
+ if (withTimestamp.length < 2)
329
+ return null;
330
+ const sorted = [...withTimestamp].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
331
+ let activeSeconds = 0;
332
+ for (let i = 1; i < sorted.length; i++) {
333
+ const gap = (new Date(sorted[i].timestamp).getTime() - new Date(sorted[i - 1].timestamp).getTime()) / 1000;
334
+ if (gap <= IDLE_THRESHOLD_SECONDS) {
335
+ activeSeconds += gap;
336
+ }
337
+ }
338
+ return Math.round(activeSeconds);
339
+ }
340
+ /** 為一組 ParsedLine 產生結構化摘要 + session_files */
341
+ export function summarizeSession(messages, startedAt = null, endedAt = null) {
342
+ const emptySummary = {
343
+ intentText: '',
344
+ activityText: '',
345
+ outcomeStatus: null,
346
+ outcomeSignals: { gitCommitInvoked: false, testCommandRan: false, endedWithEdits: false, isQuickQA: false },
347
+ summaryText: '',
348
+ tags: '',
349
+ filesTouched: '',
350
+ toolsUsed: '',
351
+ summaryVersion: SUMMARY_VERSION,
352
+ durationSeconds: null,
353
+ activeDurationSeconds: null,
354
+ };
355
+ if (messages.length === 0) {
356
+ return { summary: emptySummary, sessionFiles: [] };
357
+ }
358
+ // ── File events + session_files ──
359
+ const fileEvents = extractFileEvents(messages);
360
+ const sessionFiles = aggregateFileEvents(fileEvents);
361
+ // ── filesTouched(向後相容,逗號分隔) ──
362
+ const uniqueFiles = [...new Set(fileEvents.map(e => e.filePath))];
363
+ const filesTouched = uniqueFiles.slice(0, MAX_FILES).join(',');
364
+ // ── toolsUsed(向後相容) ──
365
+ const toolCounts = new Map();
366
+ for (const msg of messages) {
367
+ for (const name of msg.toolNames) {
368
+ toolCounts.set(name, (toolCounts.get(name) ?? 0) + 1);
369
+ }
370
+ }
371
+ const toolsUsed = [...toolCounts.entries()]
372
+ .sort((a, b) => b[1] - a[1])
373
+ .map(([name, count]) => `${name}:${count}`)
374
+ .join(',');
375
+ // ── Intent ──
376
+ const userMessages = messages.filter(m => m.role === 'user' && m.contentText);
377
+ const intentText = extractIntent(userMessages);
378
+ // ── Activity ──
379
+ const activityText = buildActivityText(toolCounts, uniqueFiles.length);
380
+ // ── Outcome ──
381
+ const { status: outcomeStatus, signals: outcomeSignals } = inferOutcome(messages);
382
+ // ── Tags(多信號交叉) ──
383
+ const tagSet = new Set();
384
+ // 文字 regex
385
+ const corpus = messages.map(m => m.contentText ?? '').join(' ').toLowerCase();
386
+ for (const rule of TEXT_TAG_RULES) {
387
+ if (rule.pattern.test(corpus))
388
+ tagSet.add(rule.tag);
389
+ }
390
+ // 路徑推斷
391
+ for (const tag of tagsFromPaths(uniqueFiles))
392
+ tagSet.add(tag);
393
+ // 工具模式推斷
394
+ for (const tag of tagsFromToolPatterns(toolCounts))
395
+ tagSet.add(tag);
396
+ // outcome 標籤
397
+ for (const tag of tagsFromOutcome(outcomeStatus))
398
+ tagSet.add(tag);
399
+ const tags = [...tagSet].join(',');
400
+ // ── Duration ──
401
+ const durationSeconds = computeDuration(startedAt, endedAt);
402
+ const activeDurationSeconds = computeActiveTime(messages);
403
+ // ── Composite summaryText ──
404
+ const summaryParts = [];
405
+ if (intentText)
406
+ summaryParts.push(intentText);
407
+ if (activityText)
408
+ summaryParts.push(activityText);
409
+ if (outcomeStatus) {
410
+ summaryParts.push(OUTCOME_LABELS[outcomeStatus] ?? '');
411
+ }
412
+ const summaryText = truncate(summaryParts.filter(Boolean).join(' | '), MAX_SUMMARY_LEN);
413
+ return {
414
+ summary: {
415
+ intentText,
416
+ activityText,
417
+ outcomeStatus,
418
+ outcomeSignals,
419
+ summaryText,
420
+ tags,
421
+ filesTouched,
422
+ toolsUsed,
423
+ summaryVersion: SUMMARY_VERSION,
424
+ durationSeconds,
425
+ activeDurationSeconds,
426
+ },
427
+ sessionFiles,
428
+ };
429
+ }
430
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/core/summarizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** tag/filesTouched 欄位支援:SessionMeta 或 SessionSummary 都能傳入(結構化型別) */
2
+ interface TopicSource {
3
+ tags: string | null;
4
+ filesTouched: string | null;
5
+ }
6
+ /** 將原始字串正規化為 topic_key:以 / \ . 拆 segment 後各自 normalize、過濾 stopword/太短,再組合 */
7
+ export declare function normalizeTopicKey(raw: string): string | null;
8
+ /** 從結構化欄位(tags, filesTouched)抽出 topic keys,已 normalize + dedup + sort */
9
+ export declare function extractFromSession(source: TopicSource): string[];
10
+ export {};
11
+ //# sourceMappingURL=topic-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topic-extractor.d.ts","sourceRoot":"","sources":["../../src/core/topic-extractor.ts"],"names":[],"mappings":"AACA,qEAAqE;AACrE,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAgBD,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS5D;AAQD,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAmBhE"}
@@ -0,0 +1,51 @@
1
+ const MIN_TOPIC_LENGTH = 3;
2
+ const STOPWORDS = new Set([
3
+ // 通用英文
4
+ 'the', 'and', 'for', 'with', 'from', 'this', 'that', 'not', 'but', 'are', 'was',
5
+ 'has', 'had', 'can', 'will', 'you', 'all', 'any', 'new', 'old', 'our',
6
+ // 通用 code words(會混淆 topic)
7
+ 'index', 'main', 'test', 'tests', 'spec', 'specs', 'types', 'type', 'util', 'utils',
8
+ 'helper', 'helpers', 'common', 'shared', 'src', 'lib', 'dist', 'build',
9
+ 'node_modules', 'tmp', 'temp', 'mock', 'mocks', 'fixture', 'fixtures',
10
+ 'config', 'constants', 'const', 'let', 'var', 'function', 'return', 'error',
11
+ 'data', 'value', 'result',
12
+ ]);
13
+ /** 將原始字串正規化為 topic_key:以 / \ . 拆 segment 後各自 normalize、過濾 stopword/太短,再組合 */
14
+ export function normalizeTopicKey(raw) {
15
+ if (!raw)
16
+ return null;
17
+ const s = raw.trim().toLowerCase();
18
+ if (!s)
19
+ return null;
20
+ const segments = s.split(/[\\/.]/)
21
+ .map(seg => seg.replace(/[^a-z0-9_-]/g, '-').replace(/-+/g, '-').replace(/^-+|-+$/g, ''))
22
+ .filter(seg => seg.length >= MIN_TOPIC_LENGTH && !STOPWORDS.has(seg));
23
+ if (segments.length === 0)
24
+ return null;
25
+ return segments.join('-');
26
+ }
27
+ function extractTopicsFromFile(filePath) {
28
+ const basename = filePath.split(/[\\/]/).pop() ?? '';
29
+ const k = normalizeTopicKey(basename);
30
+ return k ? [k] : [];
31
+ }
32
+ /** 從結構化欄位(tags, filesTouched)抽出 topic keys,已 normalize + dedup + sort */
33
+ export function extractFromSession(source) {
34
+ const topics = new Set();
35
+ if (source.tags) {
36
+ for (const raw of source.tags.split(',')) {
37
+ const k = normalizeTopicKey(raw);
38
+ if (k)
39
+ topics.add(k);
40
+ }
41
+ }
42
+ if (source.filesTouched) {
43
+ for (const filePath of source.filesTouched.split(',')) {
44
+ for (const t of extractTopicsFromFile(filePath)) {
45
+ topics.add(t);
46
+ }
47
+ }
48
+ }
49
+ return Array.from(topics).sort();
50
+ }
51
+ //# sourceMappingURL=topic-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topic-extractor.js","sourceRoot":"","sources":["../../src/core/topic-extractor.ts"],"names":[],"mappings":"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"}