@code-insights/cli 3.6.1 → 4.0.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.
- package/CHANGELOG.md +52 -0
- package/README.md +40 -4
- package/dashboard-dist/assets/index-D1JDyyu5.js +660 -0
- package/dashboard-dist/assets/index-kwbCW1n2.css +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/commands/reflect.d.ts +3 -0
- package/dist/commands/reflect.d.ts.map +1 -0
- package/dist/commands/reflect.js +457 -0
- package/dist/commands/reflect.js.map +1 -0
- package/dist/commands/reset.d.ts.map +1 -1
- package/dist/commands/reset.js +3 -1
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/stats/actions/patterns.d.ts +3 -0
- package/dist/commands/stats/actions/patterns.d.ts.map +1 -0
- package/dist/commands/stats/actions/patterns.js +140 -0
- package/dist/commands/stats/actions/patterns.js.map +1 -0
- package/dist/commands/stats/data/aggregation-helpers.d.ts +23 -0
- package/dist/commands/stats/data/aggregation-helpers.d.ts.map +1 -0
- package/dist/commands/stats/data/aggregation-helpers.js +128 -0
- package/dist/commands/stats/data/aggregation-helpers.js.map +1 -0
- package/dist/commands/stats/data/aggregation.d.ts +3 -35
- package/dist/commands/stats/data/aggregation.d.ts.map +1 -1
- package/dist/commands/stats/data/aggregation.js +8 -290
- package/dist/commands/stats/data/aggregation.js.map +1 -1
- package/dist/commands/stats/data/time-series.d.ts +24 -0
- package/dist/commands/stats/data/time-series.d.ts.map +1 -0
- package/dist/commands/stats/data/time-series.js +162 -0
- package/dist/commands/stats/data/time-series.js.map +1 -0
- package/dist/commands/stats/index.d.ts.map +1 -1
- package/dist/commands/stats/index.js +7 -1
- package/dist/commands/stats/index.js.map +1 -1
- package/dist/commands/sync.d.ts +19 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +67 -1
- package/dist/commands/sync.js.map +1 -1
- package/dist/constants/llm-providers.js +1 -1
- package/dist/constants/llm-providers.js.map +1 -1
- package/dist/db/client.d.ts +7 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +11 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrate.d.ts +10 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +96 -0
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/read.d.ts +5 -0
- package/dist/db/read.d.ts.map +1 -1
- package/dist/db/read.js +20 -3
- package/dist/db/read.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +2 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/db/write.d.ts.map +1 -1
- package/dist/db/write.js +8 -2
- package/dist/db/write.js.map +1 -1
- package/dist/index.js +39 -3
- package/dist/index.js.map +1 -1
- package/dist/parser/jsonl.d.ts +19 -1
- package/dist/parser/jsonl.d.ts.map +1 -1
- package/dist/parser/jsonl.js +109 -3
- package/dist/parser/jsonl.js.map +1 -1
- package/dist/providers/codex.js +4 -1
- package/dist/providers/codex.js.map +1 -1
- package/dist/providers/copilot-cli.js +3 -0
- package/dist/providers/copilot-cli.js.map +1 -1
- package/dist/providers/copilot.js +3 -0
- package/dist/providers/copilot.js.map +1 -1
- package/dist/providers/cursor.js +3 -0
- package/dist/providers/cursor.js.map +1 -1
- package/dist/types.d.ts +109 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/date-utils.d.ts +6 -0
- package/dist/utils/date-utils.d.ts.map +1 -0
- package/dist/utils/date-utils.js +26 -0
- package/dist/utils/date-utils.js.map +1 -0
- package/dist/utils/telemetry.d.ts +1 -1
- package/dist/utils/telemetry.d.ts.map +1 -1
- package/dist/utils/telemetry.js +1 -1
- package/dist/utils/telemetry.js.map +1 -1
- package/package.json +2 -1
- package/server-dist/export/agent-rules.d.ts.map +1 -1
- package/server-dist/export/agent-rules.js +15 -4
- package/server-dist/export/agent-rules.js.map +1 -1
- package/server-dist/export/knowledge-base.d.ts.map +1 -1
- package/server-dist/export/knowledge-base.js +30 -4
- package/server-dist/export/knowledge-base.js.map +1 -1
- package/server-dist/index.d.ts.map +1 -1
- package/server-dist/index.js +4 -0
- package/server-dist/index.js.map +1 -1
- package/server-dist/llm/analysis-db.d.ts +51 -0
- package/server-dist/llm/analysis-db.d.ts.map +1 -0
- package/server-dist/llm/analysis-db.js +208 -0
- package/server-dist/llm/analysis-db.js.map +1 -0
- package/server-dist/llm/analysis-internal.d.ts +36 -0
- package/server-dist/llm/analysis-internal.d.ts.map +1 -0
- package/server-dist/llm/analysis-internal.js +23 -0
- package/server-dist/llm/analysis-internal.js.map +1 -0
- package/server-dist/llm/analysis-pricing.d.ts +25 -0
- package/server-dist/llm/analysis-pricing.d.ts.map +1 -0
- package/server-dist/llm/analysis-pricing.js +74 -0
- package/server-dist/llm/analysis-pricing.js.map +1 -0
- package/server-dist/llm/analysis-usage-db.d.ts +45 -0
- package/server-dist/llm/analysis-usage-db.d.ts.map +1 -0
- package/server-dist/llm/analysis-usage-db.js +35 -0
- package/server-dist/llm/analysis-usage-db.js.map +1 -0
- package/server-dist/llm/analysis.d.ts +9 -79
- package/server-dist/llm/analysis.d.ts.map +1 -1
- package/server-dist/llm/analysis.js +119 -375
- package/server-dist/llm/analysis.js.map +1 -1
- package/server-dist/llm/facet-extraction.d.ts +14 -0
- package/server-dist/llm/facet-extraction.d.ts.map +1 -0
- package/server-dist/llm/facet-extraction.js +91 -0
- package/server-dist/llm/facet-extraction.js.map +1 -0
- package/server-dist/llm/friction-normalize.d.ts +16 -0
- package/server-dist/llm/friction-normalize.d.ts.map +1 -0
- package/server-dist/llm/friction-normalize.js +54 -0
- package/server-dist/llm/friction-normalize.js.map +1 -0
- package/server-dist/llm/index.d.ts +3 -2
- package/server-dist/llm/index.d.ts.map +1 -1
- package/server-dist/llm/index.js +1 -1
- package/server-dist/llm/index.js.map +1 -1
- package/server-dist/llm/message-format.d.ts +32 -0
- package/server-dist/llm/message-format.d.ts.map +1 -0
- package/server-dist/llm/message-format.js +129 -0
- package/server-dist/llm/message-format.js.map +1 -0
- package/server-dist/llm/normalize-utils.d.ts +22 -0
- package/server-dist/llm/normalize-utils.d.ts.map +1 -0
- package/server-dist/llm/normalize-utils.js +71 -0
- package/server-dist/llm/normalize-utils.js.map +1 -0
- package/server-dist/llm/pattern-normalize.d.ts +19 -0
- package/server-dist/llm/pattern-normalize.d.ts.map +1 -0
- package/server-dist/llm/pattern-normalize.js +90 -0
- package/server-dist/llm/pattern-normalize.js.map +1 -0
- package/server-dist/llm/prompt-constants.d.ts +9 -0
- package/server-dist/llm/prompt-constants.d.ts.map +1 -0
- package/server-dist/llm/prompt-constants.js +169 -0
- package/server-dist/llm/prompt-constants.js.map +1 -0
- package/server-dist/llm/prompt-quality-analysis.d.ts +8 -0
- package/server-dist/llm/prompt-quality-analysis.d.ts.map +1 -0
- package/server-dist/llm/prompt-quality-analysis.js +133 -0
- package/server-dist/llm/prompt-quality-analysis.js.map +1 -0
- package/server-dist/llm/prompt-quality-normalize.d.ts +26 -0
- package/server-dist/llm/prompt-quality-normalize.d.ts.map +1 -0
- package/server-dist/llm/prompt-quality-normalize.js +116 -0
- package/server-dist/llm/prompt-quality-normalize.js.map +1 -0
- package/server-dist/llm/prompt-types.d.ts +124 -0
- package/server-dist/llm/prompt-types.d.ts.map +1 -0
- package/server-dist/llm/prompt-types.js +4 -0
- package/server-dist/llm/prompt-types.js.map +1 -0
- package/server-dist/llm/prompts.d.ts +57 -100
- package/server-dist/llm/prompts.d.ts.map +1 -1
- package/server-dist/llm/prompts.js +606 -232
- package/server-dist/llm/prompts.js.map +1 -1
- package/server-dist/llm/providers/anthropic.d.ts.map +1 -1
- package/server-dist/llm/providers/anthropic.js +12 -0
- package/server-dist/llm/providers/anthropic.js.map +1 -1
- package/server-dist/llm/providers/gemini.d.ts.map +1 -1
- package/server-dist/llm/providers/gemini.js +10 -2
- package/server-dist/llm/providers/gemini.js.map +1 -1
- package/server-dist/llm/providers/ollama.d.ts.map +1 -1
- package/server-dist/llm/providers/ollama.js +3 -1
- package/server-dist/llm/providers/ollama.js.map +1 -1
- package/server-dist/llm/providers/openai.d.ts.map +1 -1
- package/server-dist/llm/providers/openai.js +4 -1
- package/server-dist/llm/providers/openai.js.map +1 -1
- package/server-dist/llm/recurring-insights.d.ts +26 -0
- package/server-dist/llm/recurring-insights.d.ts.map +1 -0
- package/server-dist/llm/recurring-insights.js +119 -0
- package/server-dist/llm/recurring-insights.js.map +1 -0
- package/server-dist/llm/reflect-prompts.d.ts +55 -0
- package/server-dist/llm/reflect-prompts.d.ts.map +1 -0
- package/server-dist/llm/reflect-prompts.js +151 -0
- package/server-dist/llm/reflect-prompts.js.map +1 -0
- package/server-dist/llm/response-parsers.d.ts +8 -0
- package/server-dist/llm/response-parsers.d.ts.map +1 -0
- package/server-dist/llm/response-parsers.js +151 -0
- package/server-dist/llm/response-parsers.js.map +1 -0
- package/server-dist/llm/types.d.ts +23 -1
- package/server-dist/llm/types.d.ts.map +1 -1
- package/server-dist/llm/types.js +10 -1
- package/server-dist/llm/types.js.map +1 -1
- package/server-dist/routes/analysis.d.ts.map +1 -1
- package/server-dist/routes/analysis.js +107 -282
- package/server-dist/routes/analysis.js.map +1 -1
- package/server-dist/routes/analytics.d.ts.map +1 -1
- package/server-dist/routes/analytics.js +3 -1
- package/server-dist/routes/analytics.js.map +1 -1
- package/server-dist/routes/export.d.ts.map +1 -1
- package/server-dist/routes/export.js +19 -27
- package/server-dist/routes/export.js.map +1 -1
- package/server-dist/routes/facets.d.ts +4 -0
- package/server-dist/routes/facets.d.ts.map +1 -0
- package/server-dist/routes/facets.js +208 -0
- package/server-dist/routes/facets.js.map +1 -0
- package/server-dist/routes/insights.d.ts.map +1 -1
- package/server-dist/routes/insights.js +12 -11
- package/server-dist/routes/insights.js.map +1 -1
- package/server-dist/routes/reflect.d.ts +4 -0
- package/server-dist/routes/reflect.d.ts.map +1 -0
- package/server-dist/routes/reflect.js +332 -0
- package/server-dist/routes/reflect.js.map +1 -0
- package/server-dist/routes/route-helpers.d.ts +124 -0
- package/server-dist/routes/route-helpers.d.ts.map +1 -0
- package/server-dist/routes/route-helpers.js +242 -0
- package/server-dist/routes/route-helpers.js.map +1 -0
- package/server-dist/routes/sessions.d.ts.map +1 -1
- package/server-dist/routes/sessions.js +29 -5
- package/server-dist/routes/sessions.js.map +1 -1
- package/server-dist/routes/shared-aggregation.d.ts +82 -0
- package/server-dist/routes/shared-aggregation.d.ts.map +1 -0
- package/server-dist/routes/shared-aggregation.js +384 -0
- package/server-dist/routes/shared-aggregation.js.map +1 -0
- package/dashboard-dist/assets/index-BaKju1iW.js +0 -607
- package/dashboard-dist/assets/index-_SWpRg6C.css +0 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// Shared aggregation logic for facets and reflect routes.
|
|
2
|
+
// Extracted to avoid ~150 lines of duplication between the two routes.
|
|
3
|
+
import { normalizeFrictionCategory } from '../llm/friction-normalize.js';
|
|
4
|
+
import { normalizePatternCategory, getPatternCategoryLabel } from '../llm/pattern-normalize.js';
|
|
5
|
+
import { normalizePromptQualityCategory, PQ_CATEGORY_LABELS } from '../llm/prompt-quality-normalize.js';
|
|
6
|
+
import { CANONICAL_PQ_STRENGTH_CATEGORIES } from '../llm/prompt-constants.js';
|
|
7
|
+
// ISO week regex: matches YYYY-WNN format (e.g., 2026-W10)
|
|
8
|
+
const ISO_WEEK_RE = /^(\d{4})-W(\d{2})$/;
|
|
9
|
+
/**
|
|
10
|
+
* Parse an ISO week string (YYYY-WNN) into UTC Monday/Sunday boundaries.
|
|
11
|
+
* Returns { start: Monday 00:00 UTC, end: next Monday 00:00 UTC } (exclusive end).
|
|
12
|
+
*
|
|
13
|
+
* ISO 8601 week rules: week 1 contains the first Thursday of the year,
|
|
14
|
+
* weeks start on Monday. We use the "Thursday trick": Jan 4 is always
|
|
15
|
+
* in week 1, so we find that Monday, then step to the target week.
|
|
16
|
+
*/
|
|
17
|
+
export function parseIsoWeek(weekStr) {
|
|
18
|
+
const match = ISO_WEEK_RE.exec(weekStr);
|
|
19
|
+
if (!match)
|
|
20
|
+
return null;
|
|
21
|
+
const year = parseInt(match[1], 10);
|
|
22
|
+
const week = parseInt(match[2], 10);
|
|
23
|
+
if (week < 1 || week > 53)
|
|
24
|
+
return null;
|
|
25
|
+
// Jan 4 is always in ISO week 1. Find that Monday.
|
|
26
|
+
const jan4 = new Date(Date.UTC(year, 0, 4));
|
|
27
|
+
const jan4Day = jan4.getUTCDay(); // 0=Sun, 1=Mon, ..., 6=Sat
|
|
28
|
+
// Days to Monday of week 1: if Sunday (0), go back 6; else go back (day - 1)
|
|
29
|
+
const daysToMonday = jan4Day === 0 ? 6 : jan4Day - 1;
|
|
30
|
+
const week1Monday = new Date(jan4.getTime() - daysToMonday * 86400000);
|
|
31
|
+
// Offset to the target week's Monday
|
|
32
|
+
const start = new Date(week1Monday.getTime() + (week - 1) * 7 * 86400000);
|
|
33
|
+
const end = new Date(start.getTime() + 7 * 86400000);
|
|
34
|
+
return { start, end };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format a Date (representing a Monday) as an ISO week string (YYYY-WNN).
|
|
38
|
+
* Used when generating week inventory from a list of Mondays.
|
|
39
|
+
*/
|
|
40
|
+
export function formatIsoWeek(monday) {
|
|
41
|
+
// Find which ISO week number this Monday belongs to.
|
|
42
|
+
// The Monday's Thursday (3 days ahead) determines the year and week.
|
|
43
|
+
const thursday = new Date(monday.getTime() + 3 * 86400000);
|
|
44
|
+
const year = thursday.getUTCFullYear();
|
|
45
|
+
// Find the Monday of week 1 for this ISO year
|
|
46
|
+
const jan4 = new Date(Date.UTC(year, 0, 4));
|
|
47
|
+
const jan4Day = jan4.getUTCDay();
|
|
48
|
+
const daysToMonday = jan4Day === 0 ? 6 : jan4Day - 1;
|
|
49
|
+
const week1Monday = new Date(jan4.getTime() - daysToMonday * 86400000);
|
|
50
|
+
const weekNum = Math.round((monday.getTime() - week1Monday.getTime()) / (7 * 86400000)) + 1;
|
|
51
|
+
return `${year}-W${String(weekNum).padStart(2, '0')}`;
|
|
52
|
+
}
|
|
53
|
+
export function buildPeriodFilter(period) {
|
|
54
|
+
const now = new Date();
|
|
55
|
+
if (period === '7d')
|
|
56
|
+
return new Date(now.getTime() - 7 * 86400000).toISOString();
|
|
57
|
+
if (period === '30d')
|
|
58
|
+
return new Date(now.getTime() - 30 * 86400000).toISOString();
|
|
59
|
+
if (period === '90d')
|
|
60
|
+
return new Date(now.getTime() - 90 * 86400000).toISOString();
|
|
61
|
+
return null; // 'all'
|
|
62
|
+
}
|
|
63
|
+
export function buildWhereClause(period, project, source) {
|
|
64
|
+
// Always exclude soft-deleted sessions from aggregations
|
|
65
|
+
const conditions = ['s.deleted_at IS NULL'];
|
|
66
|
+
const params = [];
|
|
67
|
+
// ISO week period: use precise Monday-to-Monday UTC boundaries
|
|
68
|
+
const isoWeekBounds = parseIsoWeek(period);
|
|
69
|
+
if (isoWeekBounds) {
|
|
70
|
+
conditions.push('s.started_at >= ?');
|
|
71
|
+
params.push(isoWeekBounds.start.toISOString());
|
|
72
|
+
conditions.push('s.started_at < ?');
|
|
73
|
+
params.push(isoWeekBounds.end.toISOString());
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const periodStart = buildPeriodFilter(period);
|
|
77
|
+
if (periodStart) {
|
|
78
|
+
conditions.push('s.started_at >= ?');
|
|
79
|
+
params.push(periodStart);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (project) {
|
|
83
|
+
conditions.push('s.project_id = ?');
|
|
84
|
+
params.push(project);
|
|
85
|
+
}
|
|
86
|
+
if (source) {
|
|
87
|
+
conditions.push('s.source_tool = ?');
|
|
88
|
+
params.push(source);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
where: `WHERE ${conditions.join(' AND ')}`,
|
|
92
|
+
params,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Run all aggregation queries needed for facet analysis and synthesis.
|
|
97
|
+
* Aggregation is done in code (SQL), not by LLMs — LLMs synthesize, they don't count.
|
|
98
|
+
*
|
|
99
|
+
* project and source are passed separately so streak can build its own
|
|
100
|
+
* period-free where clause (streak measures continuity across all time).
|
|
101
|
+
*/
|
|
102
|
+
export function getAggregatedData(db, where, params, project, source) {
|
|
103
|
+
const hasWhere = where.length > 0;
|
|
104
|
+
const extraPrefix = hasWhere ? 'AND' : 'WHERE';
|
|
105
|
+
const frictionCategories = db.prepare(`
|
|
106
|
+
SELECT
|
|
107
|
+
json_extract(je.value, '$.category') as category,
|
|
108
|
+
COUNT(*) as count,
|
|
109
|
+
AVG(CASE
|
|
110
|
+
WHEN json_extract(je.value, '$.severity') = 'high' THEN 3
|
|
111
|
+
WHEN json_extract(je.value, '$.severity') = 'medium' THEN 2
|
|
112
|
+
ELSE 1
|
|
113
|
+
END) as avg_severity,
|
|
114
|
+
json_group_array(json_extract(je.value, '$.description')) as examples,
|
|
115
|
+
json_group_array(sf.session_id) as session_ids
|
|
116
|
+
FROM session_facets sf
|
|
117
|
+
JOIN sessions s ON sf.session_id = s.id
|
|
118
|
+
CROSS JOIN json_each(sf.friction_points) je
|
|
119
|
+
${where}
|
|
120
|
+
GROUP BY category
|
|
121
|
+
ORDER BY count DESC, avg_severity DESC
|
|
122
|
+
`).all(...params);
|
|
123
|
+
// Fetch effective patterns with confidence >= 50.
|
|
124
|
+
// Category-based grouping happens in code (post-query) after normalizePatternCategory()
|
|
125
|
+
// to handle any LLM variants that were stored before normalization was applied at write time.
|
|
126
|
+
// extraPrefix handles the case where where is '' (tests pass empty string) vs a WHERE clause.
|
|
127
|
+
const effectivePatternsRaw = db.prepare(`
|
|
128
|
+
SELECT
|
|
129
|
+
json_extract(je.value, '$.category') as category,
|
|
130
|
+
json_extract(je.value, '$.description') as description,
|
|
131
|
+
json_extract(je.value, '$.confidence') as confidence,
|
|
132
|
+
json_extract(je.value, '$.driver') as driver
|
|
133
|
+
FROM session_facets sf
|
|
134
|
+
JOIN sessions s ON sf.session_id = s.id
|
|
135
|
+
CROSS JOIN json_each(sf.effective_patterns) je
|
|
136
|
+
${where}
|
|
137
|
+
${extraPrefix} json_extract(je.value, '$.confidence') >= 50
|
|
138
|
+
ORDER BY json_extract(je.value, '$.confidence') DESC
|
|
139
|
+
`).all(...params);
|
|
140
|
+
const outcomeDistribution = db.prepare(`
|
|
141
|
+
SELECT outcome_satisfaction, COUNT(*) as count
|
|
142
|
+
FROM session_facets sf JOIN sessions s ON sf.session_id = s.id
|
|
143
|
+
${where}
|
|
144
|
+
GROUP BY outcome_satisfaction
|
|
145
|
+
`).all(...params);
|
|
146
|
+
const workflowDistribution = db.prepare(`
|
|
147
|
+
SELECT workflow_pattern, COUNT(*) as count
|
|
148
|
+
FROM session_facets sf JOIN sessions s ON sf.session_id = s.id
|
|
149
|
+
${where}
|
|
150
|
+
${extraPrefix} sf.workflow_pattern IS NOT NULL
|
|
151
|
+
GROUP BY workflow_pattern
|
|
152
|
+
`).all(...params);
|
|
153
|
+
const characterDistribution = db.prepare(`
|
|
154
|
+
SELECT session_character, COUNT(*) as count
|
|
155
|
+
FROM sessions s
|
|
156
|
+
${where}
|
|
157
|
+
${extraPrefix} s.session_character IS NOT NULL
|
|
158
|
+
GROUP BY session_character
|
|
159
|
+
`).all(...params);
|
|
160
|
+
const totalRow = db.prepare(`SELECT COUNT(*) as count FROM session_facets sf JOIN sessions s ON sf.session_id = s.id ${where}`).get(...params);
|
|
161
|
+
const totalAllRow = db.prepare(`SELECT COUNT(*) as count FROM sessions s ${where}`).get(...params);
|
|
162
|
+
// Parse examples and session_ids from json_group_array output, then normalize via alias + Levenshtein clustering
|
|
163
|
+
const parsedFriction = frictionCategories.map(fc => ({
|
|
164
|
+
...fc,
|
|
165
|
+
examples: JSON.parse(fc.examples),
|
|
166
|
+
session_ids: JSON.parse(fc.session_ids),
|
|
167
|
+
}));
|
|
168
|
+
const normalizedFriction = new Map();
|
|
169
|
+
for (const fc of parsedFriction) {
|
|
170
|
+
const normalized = normalizeFrictionCategory(fc.category);
|
|
171
|
+
const existing = normalizedFriction.get(normalized);
|
|
172
|
+
if (existing) {
|
|
173
|
+
existing.count += fc.count;
|
|
174
|
+
existing.total_severity += fc.avg_severity * fc.count;
|
|
175
|
+
existing.examples.push(...fc.examples);
|
|
176
|
+
existing.session_ids.push(...fc.session_ids);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
normalizedFriction.set(normalized, {
|
|
180
|
+
count: fc.count,
|
|
181
|
+
total_severity: fc.avg_severity * fc.count,
|
|
182
|
+
examples: [...fc.examples],
|
|
183
|
+
session_ids: [...fc.session_ids],
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Partition: separate rate-limit-hit entries from general friction.
|
|
188
|
+
// Rate limits are a billing/plan constraint — surfaced as a usage insight, not friction.
|
|
189
|
+
// The alias map already normalizes all rate limit variants to "rate-limit-hit".
|
|
190
|
+
// A regex sweep catches creative LLM variants ("throttled-by-api", etc.) that bypass
|
|
191
|
+
// both the alias map and Levenshtein clustering.
|
|
192
|
+
const RATE_LIMIT_CATEGORY = 'rate-limit-hit';
|
|
193
|
+
const RATE_LIMIT_REGEX = /rate.?limit|throttl/i;
|
|
194
|
+
let rateLimitInfo = null;
|
|
195
|
+
// Accumulated data for rateLimitInfo, merged from exact match + regex sweep
|
|
196
|
+
let rateLimitCount = 0;
|
|
197
|
+
let rateLimitSessionIds = [];
|
|
198
|
+
let rateLimitExamples = [];
|
|
199
|
+
const rateLimitEntry = normalizedFriction.get(RATE_LIMIT_CATEGORY);
|
|
200
|
+
if (rateLimitEntry) {
|
|
201
|
+
rateLimitCount += rateLimitEntry.count;
|
|
202
|
+
rateLimitSessionIds.push(...rateLimitEntry.session_ids);
|
|
203
|
+
rateLimitExamples.push(...rateLimitEntry.examples);
|
|
204
|
+
normalizedFriction.delete(RATE_LIMIT_CATEGORY);
|
|
205
|
+
}
|
|
206
|
+
// Regex sweep over remaining entries to catch variants the alias map missed
|
|
207
|
+
for (const [category, entry] of normalizedFriction) {
|
|
208
|
+
if (RATE_LIMIT_REGEX.test(category)) {
|
|
209
|
+
rateLimitCount += entry.count;
|
|
210
|
+
rateLimitSessionIds.push(...entry.session_ids);
|
|
211
|
+
rateLimitExamples.push(...entry.examples);
|
|
212
|
+
normalizedFriction.delete(category);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (rateLimitCount > 0) {
|
|
216
|
+
const uniqueSessions = new Set(rateLimitSessionIds);
|
|
217
|
+
rateLimitInfo = {
|
|
218
|
+
count: rateLimitCount,
|
|
219
|
+
sessionsAffected: uniqueSessions.size,
|
|
220
|
+
examples: rateLimitExamples.slice(0, 3),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
const mergedFriction = Array.from(normalizedFriction.entries())
|
|
224
|
+
.map(([category, data]) => ({
|
|
225
|
+
category,
|
|
226
|
+
count: data.count,
|
|
227
|
+
avg_severity: data.total_severity / data.count,
|
|
228
|
+
examples: data.examples.slice(0, 10),
|
|
229
|
+
}))
|
|
230
|
+
.sort((a, b) => b.count - a.count || b.avg_severity - a.avg_severity);
|
|
231
|
+
// frictionTotal reflects only non-rate-limit friction (rate limits partitioned separately)
|
|
232
|
+
const frictionTotal = mergedFriction.reduce((sum, fc) => sum + fc.count, 0);
|
|
233
|
+
// Aggregate effective patterns by normalized category.
|
|
234
|
+
// Each row from effectivePatternsRaw is a single pattern entry — we group by normalized
|
|
235
|
+
// category in code so normalizePatternCategory() can handle LLM variants at query time.
|
|
236
|
+
const normalizedPatterns = new Map();
|
|
237
|
+
for (const row of effectivePatternsRaw) {
|
|
238
|
+
// Skip entries with null category or description (malformed JSON in older sessions)
|
|
239
|
+
if (!row.category || !row.description)
|
|
240
|
+
continue;
|
|
241
|
+
const normalized = normalizePatternCategory(row.category);
|
|
242
|
+
const existing = normalizedPatterns.get(normalized);
|
|
243
|
+
if (existing) {
|
|
244
|
+
existing.count += 1;
|
|
245
|
+
existing.total_confidence += row.confidence ?? 0;
|
|
246
|
+
existing.descriptions.push(row.description);
|
|
247
|
+
// Track driver breakdown — null/missing driver is silently skipped (transition period)
|
|
248
|
+
if (row.driver) {
|
|
249
|
+
existing.drivers[row.driver] = (existing.drivers[row.driver] ?? 0) + 1;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
const drivers = {};
|
|
254
|
+
if (row.driver) {
|
|
255
|
+
drivers[row.driver] = 1;
|
|
256
|
+
}
|
|
257
|
+
normalizedPatterns.set(normalized, {
|
|
258
|
+
count: 1,
|
|
259
|
+
total_confidence: row.confidence ?? 0,
|
|
260
|
+
descriptions: [row.description],
|
|
261
|
+
drivers,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const effectivePatterns = Array.from(normalizedPatterns.entries())
|
|
266
|
+
.map(([category, data]) => ({
|
|
267
|
+
category,
|
|
268
|
+
label: getPatternCategoryLabel(category),
|
|
269
|
+
frequency: data.count,
|
|
270
|
+
avg_confidence: data.count > 0 ? data.total_confidence / data.count : 0,
|
|
271
|
+
descriptions: data.descriptions.slice(0, 10),
|
|
272
|
+
drivers: data.drivers,
|
|
273
|
+
}))
|
|
274
|
+
.sort((a, b) => b.frequency - a.frequency || b.avg_confidence - a.avg_confidence);
|
|
275
|
+
// Count distinct source tools within scope (for hero card stat pill)
|
|
276
|
+
const sourceToolRow = db.prepare(`SELECT COUNT(DISTINCT source_tool) as count FROM sessions s ${where}`).get(...params);
|
|
277
|
+
// Streak: count consecutive days (backward from today) with at least one session.
|
|
278
|
+
// Always uses all-time scope — filtering by period would cap streak at the window size.
|
|
279
|
+
// Respects project and source filters since those are user-scope constraints.
|
|
280
|
+
const { where: streakWhere, params: streakParams } = buildWhereClause('all', project, source);
|
|
281
|
+
const sessionDates = db.prepare(`SELECT DISTINCT date(started_at) as session_date FROM sessions s ${streakWhere} ORDER BY session_date DESC`).all(...streakParams);
|
|
282
|
+
// Compare dates as YYYY-MM-DD strings in UTC to match SQLite's date() output.
|
|
283
|
+
// Using toISOString().slice(0,10) avoids local timezone shifting the day boundary.
|
|
284
|
+
const todayUTC = new Date().toISOString().slice(0, 10);
|
|
285
|
+
const yesterdayUTC = new Date(Date.now() - 86400000).toISOString().slice(0, 10);
|
|
286
|
+
let streak = 0;
|
|
287
|
+
// baseline is the date we expect for the next streak entry.
|
|
288
|
+
// Start at today; if first session is yesterday, reset baseline to yesterday so
|
|
289
|
+
// the loop can continue counting backward from there correctly.
|
|
290
|
+
let baseline = null;
|
|
291
|
+
for (const { session_date } of sessionDates) {
|
|
292
|
+
if (baseline === null) {
|
|
293
|
+
// First entry: must be today or yesterday to start an active streak
|
|
294
|
+
if (session_date === todayUTC) {
|
|
295
|
+
baseline = todayUTC;
|
|
296
|
+
}
|
|
297
|
+
else if (session_date === yesterdayUTC) {
|
|
298
|
+
baseline = yesterdayUTC;
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
break; // Gap from today — no active streak
|
|
302
|
+
}
|
|
303
|
+
streak++;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
// Subsequent entries: must be exactly one day before current baseline
|
|
307
|
+
const prevDay = new Date(baseline + 'T00:00:00Z');
|
|
308
|
+
prevDay.setUTCDate(prevDay.getUTCDate() - 1);
|
|
309
|
+
const expectedPrev = prevDay.toISOString().slice(0, 10);
|
|
310
|
+
if (session_date !== expectedPrev)
|
|
311
|
+
break;
|
|
312
|
+
baseline = expectedPrev;
|
|
313
|
+
streak++;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const { pqDeficits, pqStrengths } = aggregatePQFindings(db, where, params);
|
|
317
|
+
return {
|
|
318
|
+
frictionCategories: mergedFriction,
|
|
319
|
+
effectivePatterns,
|
|
320
|
+
outcomeDistribution: Object.fromEntries(outcomeDistribution.map(o => [o.outcome_satisfaction, o.count])),
|
|
321
|
+
workflowDistribution: Object.fromEntries(workflowDistribution.map(w => [w.workflow_pattern, w.count])),
|
|
322
|
+
characterDistribution: Object.fromEntries(characterDistribution.map(ch => [ch.session_character, ch.count])),
|
|
323
|
+
totalSessions: totalRow.count,
|
|
324
|
+
frictionTotal,
|
|
325
|
+
totalAllSessions: totalAllRow.count,
|
|
326
|
+
rateLimitInfo,
|
|
327
|
+
streak,
|
|
328
|
+
sourceToolCount: sourceToolRow.count,
|
|
329
|
+
pqDeficits,
|
|
330
|
+
pqStrengths,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Aggregate prompt quality findings from the insights table for the given scope.
|
|
335
|
+
* Returns deficits and strengths as separate arrays, pre-filtered to count >= 2.
|
|
336
|
+
* Count is session-level (unique session IDs), not finding-level — more honest signal.
|
|
337
|
+
*
|
|
338
|
+
* Uses the same where/params scope as getAggregatedData so period/project/source filters apply.
|
|
339
|
+
*/
|
|
340
|
+
export function aggregatePQFindings(db, where, params) {
|
|
341
|
+
const hasWhere = where.length > 0;
|
|
342
|
+
const extraPrefix = hasWhere ? 'AND' : 'WHERE';
|
|
343
|
+
const rows = db.prepare(`
|
|
344
|
+
SELECT i.metadata, i.session_id
|
|
345
|
+
FROM insights i
|
|
346
|
+
JOIN sessions s ON i.session_id = s.id
|
|
347
|
+
${where}
|
|
348
|
+
${extraPrefix} i.type = 'prompt_quality'
|
|
349
|
+
`).all(...params);
|
|
350
|
+
const deficitCounts = new Map();
|
|
351
|
+
const strengthCounts = new Map();
|
|
352
|
+
const strengthSet = new Set(CANONICAL_PQ_STRENGTH_CATEGORIES);
|
|
353
|
+
for (const row of rows) {
|
|
354
|
+
let metadata;
|
|
355
|
+
try {
|
|
356
|
+
metadata = JSON.parse(row.metadata);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
const findings = metadata.findings;
|
|
362
|
+
if (!Array.isArray(findings))
|
|
363
|
+
continue;
|
|
364
|
+
for (const finding of findings) {
|
|
365
|
+
if (typeof finding?.category !== 'string')
|
|
366
|
+
continue;
|
|
367
|
+
const normalized = normalizePromptQualityCategory(finding.category);
|
|
368
|
+
const bucket = strengthSet.has(normalized) ? strengthCounts : deficitCounts;
|
|
369
|
+
if (!bucket.has(normalized))
|
|
370
|
+
bucket.set(normalized, new Set());
|
|
371
|
+
bucket.get(normalized).add(row.session_id);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const toSorted = (map) => [...map.entries()]
|
|
375
|
+
.map(([category, sessions]) => ({
|
|
376
|
+
category,
|
|
377
|
+
label: PQ_CATEGORY_LABELS[category] ?? category,
|
|
378
|
+
count: sessions.size,
|
|
379
|
+
}))
|
|
380
|
+
.filter(e => e.count >= 2)
|
|
381
|
+
.sort((a, b) => b.count - a.count);
|
|
382
|
+
return { pqDeficits: toSorted(deficitCounts), pqStrengths: toSorted(strengthCounts) };
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=shared-aggregation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-aggregation.js","sourceRoot":"","sources":["../../src/routes/shared-aggregation.ts"],"names":[],"mappings":"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"}
|