cmp-standards 2.8.0 → 2.8.1

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 (46) hide show
  1. package/dist/experts/ExpertVotePersistence.d.ts +86 -0
  2. package/dist/experts/ExpertVotePersistence.d.ts.map +1 -0
  3. package/dist/experts/ExpertVotePersistence.js +234 -0
  4. package/dist/experts/ExpertVotePersistence.js.map +1 -0
  5. package/dist/experts/index.d.ts +1 -0
  6. package/dist/experts/index.d.ts.map +1 -1
  7. package/dist/experts/index.js +2 -0
  8. package/dist/experts/index.js.map +1 -1
  9. package/dist/hooks/cloud-post-tool-use.d.ts +5 -0
  10. package/dist/hooks/cloud-post-tool-use.d.ts.map +1 -1
  11. package/dist/hooks/cloud-post-tool-use.js +43 -10
  12. package/dist/hooks/cloud-post-tool-use.js.map +1 -1
  13. package/dist/hooks/cloud-session-start.d.ts.map +1 -1
  14. package/dist/hooks/cloud-session-start.js +64 -0
  15. package/dist/hooks/cloud-session-start.js.map +1 -1
  16. package/dist/hooks/index.d.ts +1 -0
  17. package/dist/hooks/index.d.ts.map +1 -1
  18. package/dist/hooks/index.js +2 -0
  19. package/dist/hooks/index.js.map +1 -1
  20. package/dist/hooks/session-end.d.ts +67 -0
  21. package/dist/hooks/session-end.d.ts.map +1 -0
  22. package/dist/hooks/session-end.js +268 -0
  23. package/dist/hooks/session-end.js.map +1 -0
  24. package/dist/mcp/schemas.d.ts +2 -2
  25. package/dist/performance/Debouncer.d.ts +57 -0
  26. package/dist/performance/Debouncer.d.ts.map +1 -1
  27. package/dist/performance/Debouncer.js +149 -0
  28. package/dist/performance/Debouncer.js.map +1 -1
  29. package/dist/performance/index.d.ts +1 -1
  30. package/dist/performance/index.d.ts.map +1 -1
  31. package/dist/performance/index.js +3 -1
  32. package/dist/performance/index.js.map +1 -1
  33. package/dist/schema/expert-types.d.ts +2 -2
  34. package/dist/services/FeedbackCollector.d.ts +63 -0
  35. package/dist/services/FeedbackCollector.d.ts.map +1 -0
  36. package/dist/services/FeedbackCollector.js +219 -0
  37. package/dist/services/FeedbackCollector.js.map +1 -0
  38. package/dist/services/index.d.ts +2 -1
  39. package/dist/services/index.d.ts.map +1 -1
  40. package/dist/services/index.js +3 -1
  41. package/dist/services/index.js.map +1 -1
  42. package/dist/services/pattern-tracker.d.ts +50 -0
  43. package/dist/services/pattern-tracker.d.ts.map +1 -1
  44. package/dist/services/pattern-tracker.js +148 -0
  45. package/dist/services/pattern-tracker.js.map +1 -1
  46. package/package.json +1 -1
@@ -8,5 +8,6 @@ export { MemoryCheckpointHook, runMemoryCheckpointHook } from './memory-checkpoi
8
8
  export { onSessionStart as cloudSessionStart } from './cloud-session-start.js';
9
9
  export { onPreToolUse as cloudPreToolUse } from './cloud-pre-tool-use.js';
10
10
  export { onPostToolUse as cloudPostToolUse } from './cloud-post-tool-use.js';
11
+ export { onSessionEnd, getSessionSummaries, getSessionStats, SessionEndEvent, SessionSummary, SessionEndResult, } from './session-end.js';
11
12
  export { ExpertReviewHook, ExpertReviewConfig, ReviewRequest, ReviewResult, getExpertReviewHook, resetExpertReviewHook, onExpertReview, } from './expert-review.js';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAGtF,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAG5E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAGtF,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAG5E,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAA"}
@@ -10,6 +10,8 @@ export { MemoryCheckpointHook, runMemoryCheckpointHook } from './memory-checkpoi
10
10
  export { onSessionStart as cloudSessionStart } from './cloud-session-start.js';
11
11
  export { onPreToolUse as cloudPreToolUse } from './cloud-pre-tool-use.js';
12
12
  export { onPostToolUse as cloudPostToolUse } from './cloud-post-tool-use.js';
13
+ // Session End hook (v2.8 - Analytics)
14
+ export { onSessionEnd, getSessionSummaries, getSessionStats, } from './session-end.js';
13
15
  // Expert Review hook (v2.8)
14
16
  export { ExpertReviewHook, getExpertReviewHook, resetExpertReviewHook, onExpertReview, } from './expert-review.js';
15
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAEtF,gCAAgC;AAChC,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE5E,4BAA4B;AAC5B,OAAO,EACL,gBAAgB,EAIhB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAEtF,gCAAgC;AAChC,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE5E,sCAAsC;AACtC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,eAAe,GAIhB,MAAM,kBAAkB,CAAA;AAEzB,4BAA4B;AAC5B,OAAO,EACL,gBAAgB,EAIhB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file Session End Hook
3
+ * @description Captures session analytics and persists summary for learning
4
+ *
5
+ * Features:
6
+ * - Record session duration and tool usage
7
+ * - Track files modified during session
8
+ * - Count patterns detected and memories created
9
+ * - Enable session-over-session trend analysis
10
+ *
11
+ * @version 1.0.0
12
+ */
13
+ import type { DevSystem } from '../types/index.js';
14
+ export interface SessionEndEvent {
15
+ cwd: string;
16
+ sessionId: string;
17
+ reason?: 'user_exit' | 'timeout' | 'error' | 'unknown';
18
+ }
19
+ export interface SessionSummary {
20
+ id: string;
21
+ sessionId: string;
22
+ system: DevSystem;
23
+ duration: number;
24
+ startedAt: string;
25
+ endedAt: string;
26
+ reason: string;
27
+ toolCalls: Record<string, number>;
28
+ totalToolCalls: number;
29
+ filesModified: string[];
30
+ filesRead: string[];
31
+ tasksStarted: number;
32
+ tasksCompleted: number;
33
+ memoriesCreated: number;
34
+ memoriesAccessed: number;
35
+ patternsDetected: number;
36
+ improvementsGenerated: number;
37
+ cacheHitRate: number;
38
+ debounceSkipRate: number;
39
+ }
40
+ export interface SessionEndResult {
41
+ success: boolean;
42
+ summaryId?: string;
43
+ duration?: number;
44
+ error?: string;
45
+ }
46
+ export declare function onSessionEnd(event: SessionEndEvent): Promise<SessionEndResult>;
47
+ /**
48
+ * Get session summaries for analytics
49
+ */
50
+ export declare function getSessionSummaries(system: DevSystem, limit?: number): Promise<SessionSummary[]>;
51
+ /**
52
+ * Get aggregate statistics across sessions
53
+ */
54
+ export declare function getSessionStats(system: DevSystem, days?: number): Promise<{
55
+ totalSessions: number;
56
+ avgDuration: number;
57
+ totalToolCalls: number;
58
+ avgTasksCompleted: number;
59
+ avgCacheHitRate: number;
60
+ avgDebounceRate: number;
61
+ topTools: Array<{
62
+ tool: string;
63
+ count: number;
64
+ }>;
65
+ }>;
66
+ export default onSessionEnd;
67
+ //# sourceMappingURL=session-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.d.ts","sourceRoot":"","sources":["../../src/hooks/session-end.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAMlD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;CACvD;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IAGd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,cAAc,EAAE,MAAM,CAAA;IAGtB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,SAAS,EAAE,MAAM,EAAE,CAAA;IAGnB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IAGtB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IAGxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,CAAA;IAG7B,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAuBD,wBAAsB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoKpF;AAMD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,SAAS,EACjB,KAAK,SAAK,GACT,OAAO,CAAC,cAAc,EAAE,CAAC,CAqB3B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,SAAI,GAAG,OAAO,CAAC;IAC1E,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjD,CAAC,CAoDD;AA0BD,eAAe,YAAY,CAAA"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * @file Session End Hook
3
+ * @description Captures session analytics and persists summary for learning
4
+ *
5
+ * Features:
6
+ * - Record session duration and tool usage
7
+ * - Track files modified during session
8
+ * - Count patterns detected and memories created
9
+ * - Enable session-over-session trend analysis
10
+ *
11
+ * @version 1.0.0
12
+ */
13
+ import { ulid } from 'ulid';
14
+ import { config } from 'dotenv';
15
+ import { resolve } from 'path';
16
+ import { turso } from '../db/turso-client.js';
17
+ import { upstash } from '../db/upstash-client.js';
18
+ import { getSmartDebouncer } from '../performance/Debouncer.js';
19
+ import { getEmbeddingCache } from '../cache/EmbeddingCache.js';
20
+ import { feedbackCollector } from '../services/FeedbackCollector.js';
21
+ // =============================================================================
22
+ // System Detection (copied from session-start for standalone use)
23
+ // =============================================================================
24
+ function detectSystem(cwd) {
25
+ if (cwd.includes('swarmscale') || cwd.includes('SwarmScale')) {
26
+ return 'SWARMSCALE';
27
+ }
28
+ if (cwd.includes('easycharter') || cwd.includes('charter')) {
29
+ return 'PANEL';
30
+ }
31
+ if (cwd.includes('carlosmartinpavon')) {
32
+ return 'ECOSYSTEM';
33
+ }
34
+ return 'ECOSYSTEM';
35
+ }
36
+ // =============================================================================
37
+ // Hook Implementation
38
+ // =============================================================================
39
+ export async function onSessionEnd(event) {
40
+ // Load environment
41
+ const envPaths = [
42
+ resolve(event.cwd, '.env'),
43
+ resolve(event.cwd, '../.env'),
44
+ resolve(event.cwd, '../../.env')
45
+ ];
46
+ for (const envPath of envPaths) {
47
+ config({ path: envPath });
48
+ }
49
+ const system = detectSystem(event.cwd);
50
+ const endedAt = new Date().toISOString();
51
+ try {
52
+ const db = turso.getClient();
53
+ // 1. Get session info from Redis
54
+ let sessionInfo = null;
55
+ try {
56
+ const cached = await upstash.getCache(`session_metrics:${event.sessionId}`);
57
+ sessionInfo = cached;
58
+ }
59
+ catch {
60
+ // Redis might not be available
61
+ }
62
+ const startedAt = sessionInfo?.startedAt || new Date(Date.now() - 3600000).toISOString();
63
+ const duration = new Date(endedAt).getTime() - new Date(startedAt).getTime();
64
+ // 2. Get task counts for this session
65
+ const taskCounts = await db.execute({
66
+ sql: `SELECT
67
+ SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'active' THEN 1 ELSE 0 END) as started,
68
+ SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'done' THEN 1 ELSE 0 END) as completed
69
+ FROM items
70
+ WHERE system = ? AND type = 'task'`,
71
+ args: [event.sessionId, event.sessionId, system]
72
+ });
73
+ const taskRow = taskCounts.rows[0] || { started: 0, completed: 0 };
74
+ // 3. Get memory counts for this session
75
+ const memoryCounts = await db.execute({
76
+ sql: `SELECT COUNT(*) as created FROM items
77
+ WHERE system = ? AND type = 'memory'
78
+ AND json_extract(content, '$.sessionId') = ?`,
79
+ args: [system, event.sessionId]
80
+ });
81
+ const memoryRow = memoryCounts.rows[0] || { created: 0 };
82
+ // 4. Get pattern counts for this session
83
+ const patternCounts = await db.execute({
84
+ sql: `SELECT COUNT(*) as detected FROM items
85
+ WHERE system = ? AND type = 'pattern'
86
+ AND date(created_at) = date('now')`,
87
+ args: [system]
88
+ });
89
+ const patternRow = patternCounts.rows[0] || { detected: 0 };
90
+ // 5. Get improvement counts
91
+ const improvementCounts = await db.execute({
92
+ sql: `SELECT COUNT(*) as generated FROM items
93
+ WHERE system = ? AND type = 'auto_improvement'
94
+ AND date(created_at) = date('now')`,
95
+ args: [system]
96
+ });
97
+ const improvementRow = improvementCounts.rows[0] || { generated: 0 };
98
+ // 6. Get performance metrics
99
+ const embeddingCache = getEmbeddingCache();
100
+ const cacheStats = embeddingCache.getStats();
101
+ const smartDebouncer = getSmartDebouncer();
102
+ const debounceStats = smartDebouncer.getStats();
103
+ // 7. Get top-scored memories accessed count
104
+ const topScored = await feedbackCollector.getTopScoredMemories(system, 10);
105
+ const memoriesAccessed = topScored.reduce((sum, m) => sum + m.accessCount, 0);
106
+ // 8. Build summary
107
+ const summary = {
108
+ id: `ss_${ulid()}`,
109
+ sessionId: event.sessionId,
110
+ system,
111
+ duration,
112
+ startedAt,
113
+ endedAt,
114
+ reason: event.reason || 'unknown',
115
+ toolCalls: sessionInfo?.toolCalls || {},
116
+ totalToolCalls: Object.values(sessionInfo?.toolCalls || {}).reduce((a, b) => a + b, 0),
117
+ filesModified: sessionInfo?.filesModified || [],
118
+ filesRead: sessionInfo?.filesRead || [],
119
+ tasksStarted: Number(taskRow.started) || 0,
120
+ tasksCompleted: Number(taskRow.completed) || 0,
121
+ memoriesCreated: Number(memoryRow.created) || 0,
122
+ memoriesAccessed,
123
+ patternsDetected: Number(patternRow.detected) || 0,
124
+ improvementsGenerated: Number(improvementRow.generated) || 0,
125
+ cacheHitRate: cacheStats.hitRate,
126
+ debounceSkipRate: debounceStats.skipRate
127
+ };
128
+ // 9. Persist summary
129
+ await db.execute({
130
+ sql: `INSERT INTO items (id, type, system, status, content, created_at, updated_at)
131
+ VALUES (?, 'session_summary', ?, 'active', ?, ?, ?)`,
132
+ args: [
133
+ summary.id,
134
+ system,
135
+ JSON.stringify(summary),
136
+ endedAt,
137
+ endedAt
138
+ ]
139
+ });
140
+ // 10. Cleanup Redis session data
141
+ try {
142
+ await upstash.deleteCache(`session_metrics:${event.sessionId}`);
143
+ await upstash.deleteCache(`session:${event.sessionId}`);
144
+ }
145
+ catch {
146
+ // Redis cleanup is best-effort
147
+ }
148
+ console.log(`[session-end] Session ${event.sessionId} completed:`);
149
+ console.log(` Duration: ${Math.round(duration / 1000 / 60)} minutes`);
150
+ console.log(` Tool calls: ${summary.totalToolCalls}`);
151
+ console.log(` Files modified: ${summary.filesModified.length}`);
152
+ console.log(` Tasks completed: ${summary.tasksCompleted}`);
153
+ console.log(` Cache hit rate: ${(summary.cacheHitRate * 100).toFixed(1)}%`);
154
+ return {
155
+ success: true,
156
+ summaryId: summary.id,
157
+ duration
158
+ };
159
+ }
160
+ catch (error) {
161
+ console.error('[session-end] Error:', error);
162
+ return {
163
+ success: false,
164
+ error: error instanceof Error ? error.message : 'Unknown error'
165
+ };
166
+ }
167
+ }
168
+ // =============================================================================
169
+ // Utility Functions
170
+ // =============================================================================
171
+ /**
172
+ * Get session summaries for analytics
173
+ */
174
+ export async function getSessionSummaries(system, limit = 20) {
175
+ try {
176
+ const db = turso.getClient();
177
+ const result = await db.execute({
178
+ sql: `SELECT content FROM items
179
+ WHERE system = ? AND type = 'session_summary' AND status = 'active'
180
+ ORDER BY created_at DESC
181
+ LIMIT ?`,
182
+ args: [system, limit]
183
+ });
184
+ return result.rows.map(row => {
185
+ const content = typeof row.content === 'string'
186
+ ? JSON.parse(row.content)
187
+ : row.content;
188
+ return content;
189
+ });
190
+ }
191
+ catch (error) {
192
+ console.error('[session-end] Failed to get summaries:', error);
193
+ return [];
194
+ }
195
+ }
196
+ /**
197
+ * Get aggregate statistics across sessions
198
+ */
199
+ export async function getSessionStats(system, days = 7) {
200
+ const summaries = await getSessionSummaries(system, 100);
201
+ if (summaries.length === 0) {
202
+ return {
203
+ totalSessions: 0,
204
+ avgDuration: 0,
205
+ totalToolCalls: 0,
206
+ avgTasksCompleted: 0,
207
+ avgCacheHitRate: 0,
208
+ avgDebounceRate: 0,
209
+ topTools: []
210
+ };
211
+ }
212
+ // Filter to last N days
213
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
214
+ const recent = summaries.filter(s => new Date(s.endedAt).getTime() > cutoff);
215
+ const toolCounts = new Map();
216
+ let totalDuration = 0;
217
+ let totalCalls = 0;
218
+ let totalTasksCompleted = 0;
219
+ let totalCacheRate = 0;
220
+ let totalDebounceRate = 0;
221
+ for (const s of recent) {
222
+ totalDuration += s.duration;
223
+ totalCalls += s.totalToolCalls;
224
+ totalTasksCompleted += s.tasksCompleted;
225
+ totalCacheRate += s.cacheHitRate;
226
+ totalDebounceRate += s.debounceSkipRate;
227
+ for (const [tool, count] of Object.entries(s.toolCalls)) {
228
+ toolCounts.set(tool, (toolCounts.get(tool) || 0) + count);
229
+ }
230
+ }
231
+ const topTools = Array.from(toolCounts.entries())
232
+ .map(([tool, count]) => ({ tool, count }))
233
+ .sort((a, b) => b.count - a.count)
234
+ .slice(0, 10);
235
+ return {
236
+ totalSessions: recent.length,
237
+ avgDuration: recent.length > 0 ? totalDuration / recent.length : 0,
238
+ totalToolCalls: totalCalls,
239
+ avgTasksCompleted: recent.length > 0 ? totalTasksCompleted / recent.length : 0,
240
+ avgCacheHitRate: recent.length > 0 ? totalCacheRate / recent.length : 0,
241
+ avgDebounceRate: recent.length > 0 ? totalDebounceRate / recent.length : 0,
242
+ topTools
243
+ };
244
+ }
245
+ // =============================================================================
246
+ // CLI Entry Point
247
+ // =============================================================================
248
+ if (process.argv[1]?.includes('session-end')) {
249
+ const cwd = process.cwd();
250
+ const sessionId = process.argv[2] || `session_${Date.now()}`;
251
+ const reason = process.argv[3] || 'user_exit';
252
+ onSessionEnd({ cwd, sessionId, reason })
253
+ .then(result => {
254
+ if (result.success) {
255
+ console.log(`Session ended successfully. Summary: ${result.summaryId}`);
256
+ }
257
+ else {
258
+ console.error(`Session end failed: ${result.error}`);
259
+ process.exit(1);
260
+ }
261
+ })
262
+ .catch(error => {
263
+ console.error('Error:', error.message);
264
+ process.exit(1);
265
+ });
266
+ }
267
+ export default onSessionEnd;
268
+ //# sourceMappingURL=session-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.js","sourceRoot":"","sources":["../../src/hooks/session-end.ts"],"names":[],"mappings":"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"}
@@ -139,12 +139,12 @@ export declare const FeedbackSubmitSchema: z.ZodObject<{
139
139
  helpful: z.ZodBoolean;
140
140
  comment: z.ZodOptional<z.ZodString>;
141
141
  }, "strip", z.ZodTypeAny, {
142
- memoryId: string;
143
142
  helpful: boolean;
143
+ memoryId: string;
144
144
  comment?: string | undefined;
145
145
  }, {
146
- memoryId: string;
147
146
  helpful: boolean;
147
+ memoryId: string;
148
148
  comment?: string | undefined;
149
149
  }>;
150
150
  export declare const TaskStartSchema: z.ZodObject<{
@@ -23,6 +23,19 @@ export interface DebouncerStats {
23
23
  skipRate: number;
24
24
  activeEntries: number;
25
25
  }
26
+ /**
27
+ * Tool-specific debounce windows
28
+ * Different tools have different optimal debounce times
29
+ */
30
+ export declare const TOOL_DEBOUNCE_CONFIG: Record<string, number>;
31
+ /**
32
+ * Get debounce window for a specific tool
33
+ */
34
+ export declare function getToolDebounceMs(toolName: string): number;
35
+ /**
36
+ * Check if a tool should never be debounced (write operations)
37
+ */
38
+ export declare function isWriteOperation(toolName: string): boolean;
26
39
  export declare class Debouncer {
27
40
  private config;
28
41
  private entries;
@@ -84,8 +97,52 @@ export declare class HookDebouncer extends Debouncer {
84
97
  constructor(config?: Partial<DebouncerConfig>);
85
98
  shouldSkipHook(hookName: string, context: Record<string, unknown>): boolean;
86
99
  }
100
+ /**
101
+ * Smart Debouncer with tool-specific windows
102
+ * Uses different debounce times based on tool type
103
+ */
104
+ export declare class SmartDebouncer {
105
+ private entries;
106
+ private maxEntries;
107
+ private debug;
108
+ private stats;
109
+ constructor(options?: {
110
+ maxEntries?: number;
111
+ debug?: boolean;
112
+ });
113
+ /**
114
+ * Check if operation should be skipped based on tool-specific window
115
+ */
116
+ shouldSkip(toolName: string, params: Record<string, unknown>): boolean;
117
+ private trackCall;
118
+ /**
119
+ * Cleanup old entries (uses longest debounce window)
120
+ */
121
+ cleanup(): number;
122
+ /**
123
+ * Get statistics including per-tool breakdown
124
+ */
125
+ getStats(): {
126
+ totalCalls: number;
127
+ skipped: number;
128
+ skipRate: number;
129
+ byTool: Record<string, {
130
+ total: number;
131
+ skipped: number;
132
+ skipRate: number;
133
+ }>;
134
+ };
135
+ /**
136
+ * Reset all state
137
+ */
138
+ reset(): void;
139
+ }
87
140
  export declare function getDebouncer(config?: Partial<DebouncerConfig>): Debouncer;
88
141
  export declare function getEmbeddingDebouncer(config?: Partial<DebouncerConfig>): EmbeddingDebouncer;
89
142
  export declare function getHookDebouncer(config?: Partial<DebouncerConfig>): HookDebouncer;
143
+ export declare function getSmartDebouncer(options?: {
144
+ maxEntries?: number;
145
+ debug?: boolean;
146
+ }): SmartDebouncer;
90
147
  export declare function resetDebouncers(): void;
91
148
  //# sourceMappingURL=Debouncer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Debouncer.d.ts","sourceRoot":"","sources":["../../src/performance/Debouncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,2BAA2B;IAC3B,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB;AAiBD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,KAAK,CAGZ;gBAEW,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAIjD;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IA4BhC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;IAMpE;;OAEG;IACH,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAK/E;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO;IAM1C;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,IAAI,MAAM;IAkBjB;;OAEG;IACH,QAAQ,IAAI,cAAc;IAY1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,SAAS,IAAI,eAAe;IAI5B;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;CAGlD;AAMD;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAQjD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAIxC;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAQjD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;CAI5E;AAUD,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,SAAS,CAKzE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,kBAAkB,CAK3F;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,aAAa,CAKjF;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC"}
1
+ {"version":3,"file":"Debouncer.d.ts","sourceRoot":"","sources":["../../src/performance/Debouncer.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,45 @@ const DEFAULT_CONFIG = {
15
15
  debug: false,
16
16
  };
17
17
  // =============================================================================
18
+ // Smart Debouncing by Tool Type
19
+ // =============================================================================
20
+ /**
21
+ * Tool-specific debounce windows
22
+ * Different tools have different optimal debounce times
23
+ */
24
+ export const TOOL_DEBOUNCE_CONFIG = {
25
+ // Read operations - frequent, short debounce
26
+ 'Read': 1000,
27
+ 'Glob': 2000,
28
+ 'Grep': 2000,
29
+ 'LSP': 1000,
30
+ // Write operations - no debounce (always execute)
31
+ 'Write': 0,
32
+ 'Edit': 0,
33
+ 'NotebookEdit': 0,
34
+ // External operations - longer debounce
35
+ 'WebSearch': 5000,
36
+ 'WebFetch': 5000,
37
+ 'Bash': 3000,
38
+ // Task/Agent operations - medium debounce
39
+ 'Task': 3000,
40
+ 'Skill': 2000,
41
+ // Default for unknown tools
42
+ 'default': 3000
43
+ };
44
+ /**
45
+ * Get debounce window for a specific tool
46
+ */
47
+ export function getToolDebounceMs(toolName) {
48
+ return TOOL_DEBOUNCE_CONFIG[toolName] ?? TOOL_DEBOUNCE_CONFIG['default'];
49
+ }
50
+ /**
51
+ * Check if a tool should never be debounced (write operations)
52
+ */
53
+ export function isWriteOperation(toolName) {
54
+ return ['Write', 'Edit', 'NotebookEdit'].includes(toolName);
55
+ }
56
+ // =============================================================================
18
57
  // Debouncer Implementation
19
58
  // =============================================================================
20
59
  export class Debouncer {
@@ -166,12 +205,115 @@ export class HookDebouncer extends Debouncer {
166
205
  return this.shouldSkip(`hook:${key}`);
167
206
  }
168
207
  }
208
+ /**
209
+ * Smart Debouncer with tool-specific windows
210
+ * Uses different debounce times based on tool type
211
+ */
212
+ export class SmartDebouncer {
213
+ entries = new Map();
214
+ maxEntries;
215
+ debug;
216
+ stats = {
217
+ totalCalls: 0,
218
+ skipped: 0,
219
+ byTool: new Map()
220
+ };
221
+ constructor(options = {}) {
222
+ this.maxEntries = options.maxEntries ?? 500;
223
+ this.debug = options.debug ?? false;
224
+ }
225
+ /**
226
+ * Check if operation should be skipped based on tool-specific window
227
+ */
228
+ shouldSkip(toolName, params) {
229
+ const debounceMs = getToolDebounceMs(toolName);
230
+ // Write operations are never debounced
231
+ if (debounceMs === 0) {
232
+ this.trackCall(toolName, false);
233
+ return false;
234
+ }
235
+ this.stats.totalCalls++;
236
+ const now = Date.now();
237
+ const paramsStr = JSON.stringify(params, Object.keys(params).sort());
238
+ const key = createHash('md5').update(`${toolName}:${paramsStr}`).digest('hex');
239
+ const entry = this.entries.get(key);
240
+ if (entry && now - entry.lastCall < debounceMs) {
241
+ this.stats.skipped++;
242
+ entry.callCount++;
243
+ this.trackCall(toolName, true);
244
+ if (this.debug) {
245
+ console.log(`[SmartDebouncer] Skipping ${toolName} (window: ${debounceMs}ms, called ${entry.callCount}x)`);
246
+ }
247
+ return true;
248
+ }
249
+ // Update or create entry
250
+ this.entries.set(key, { lastCall: now, callCount: 1 });
251
+ // Cleanup if needed
252
+ if (this.entries.size > this.maxEntries) {
253
+ this.cleanup();
254
+ }
255
+ this.trackCall(toolName, false);
256
+ return false;
257
+ }
258
+ trackCall(toolName, skipped) {
259
+ const existing = this.stats.byTool.get(toolName) ?? { total: 0, skipped: 0 };
260
+ existing.total++;
261
+ if (skipped)
262
+ existing.skipped++;
263
+ this.stats.byTool.set(toolName, existing);
264
+ }
265
+ /**
266
+ * Cleanup old entries (uses longest debounce window)
267
+ */
268
+ cleanup() {
269
+ const now = Date.now();
270
+ const maxWindow = Math.max(...Object.values(TOOL_DEBOUNCE_CONFIG));
271
+ let removed = 0;
272
+ for (const [key, entry] of this.entries) {
273
+ if (now - entry.lastCall > maxWindow) {
274
+ this.entries.delete(key);
275
+ removed++;
276
+ }
277
+ }
278
+ return removed;
279
+ }
280
+ /**
281
+ * Get statistics including per-tool breakdown
282
+ */
283
+ getStats() {
284
+ const byTool = {};
285
+ for (const [tool, stats] of this.stats.byTool) {
286
+ byTool[tool] = {
287
+ ...stats,
288
+ skipRate: stats.total > 0 ? stats.skipped / stats.total : 0
289
+ };
290
+ }
291
+ return {
292
+ totalCalls: this.stats.totalCalls,
293
+ skipped: this.stats.skipped,
294
+ skipRate: this.stats.totalCalls > 0 ? this.stats.skipped / this.stats.totalCalls : 0,
295
+ byTool
296
+ };
297
+ }
298
+ /**
299
+ * Reset all state
300
+ */
301
+ reset() {
302
+ this.entries.clear();
303
+ this.stats = {
304
+ totalCalls: 0,
305
+ skipped: 0,
306
+ byTool: new Map()
307
+ };
308
+ }
309
+ }
169
310
  // =============================================================================
170
311
  // Singleton Instances
171
312
  // =============================================================================
172
313
  let globalDebouncer = null;
173
314
  let globalEmbeddingDebouncer = null;
174
315
  let globalHookDebouncer = null;
316
+ let globalSmartDebouncer = null;
175
317
  export function getDebouncer(config) {
176
318
  if (!globalDebouncer) {
177
319
  globalDebouncer = new Debouncer(config);
@@ -190,9 +332,16 @@ export function getHookDebouncer(config) {
190
332
  }
191
333
  return globalHookDebouncer;
192
334
  }
335
+ export function getSmartDebouncer(options) {
336
+ if (!globalSmartDebouncer) {
337
+ globalSmartDebouncer = new SmartDebouncer(options);
338
+ }
339
+ return globalSmartDebouncer;
340
+ }
193
341
  export function resetDebouncers() {
194
342
  globalDebouncer = null;
195
343
  globalEmbeddingDebouncer = null;
196
344
  globalHookDebouncer = null;
345
+ globalSmartDebouncer = null;
197
346
  }
198
347
  //# sourceMappingURL=Debouncer.js.map