@code-insights/cli 3.6.0 → 4.0.0
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 +53 -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.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-C1mDRV7y.js +0 -607
- package/dashboard-dist/assets/index-_SWpRg6C.css +0 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Facet-only extraction — backfill path for sessions that already have insights.
|
|
2
|
+
// Extracted from analysis.ts to keep each analysis responsibility in its own module.
|
|
3
|
+
import { jsonrepair } from 'jsonrepair';
|
|
4
|
+
import { createLLMClient, isLLMConfigured, loadLLMConfig } from './client.js';
|
|
5
|
+
import { calculateAnalysisCost } from './analysis-pricing.js';
|
|
6
|
+
import { saveAnalysisUsage } from './analysis-usage-db.js';
|
|
7
|
+
import { formatMessagesForAnalysis } from './message-format.js';
|
|
8
|
+
import { extractJsonPayload } from './response-parsers.js';
|
|
9
|
+
import { SHARED_ANALYST_SYSTEM_PROMPT, buildCacheableConversationBlock, buildFacetOnlyInstructions } from './prompts.js';
|
|
10
|
+
import { ANALYSIS_VERSION, saveFacetsToDb, } from './analysis-db.js';
|
|
11
|
+
import { MAX_INPUT_TOKENS, buildSessionMeta } from './analysis-internal.js';
|
|
12
|
+
/**
|
|
13
|
+
* Extract facets only for a session that already has insights (backfill).
|
|
14
|
+
* Uses the full conversation transcript for accurate friction attribution.
|
|
15
|
+
* Falls back to truncation for sessions exceeding token limits.
|
|
16
|
+
*/
|
|
17
|
+
export async function extractFacetsOnly(session, messages, options) {
|
|
18
|
+
if (!isLLMConfigured()) {
|
|
19
|
+
return { success: false, error: 'LLM not configured.' };
|
|
20
|
+
}
|
|
21
|
+
if (messages.length === 0) {
|
|
22
|
+
return { success: false, error: 'No messages found.' };
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const startTime = Date.now();
|
|
26
|
+
const client = createLLMClient();
|
|
27
|
+
let formattedMessages = formatMessagesForAnalysis(messages);
|
|
28
|
+
// Truncate if conversation exceeds token limits (same pattern as PQ analysis)
|
|
29
|
+
const estimatedTokens = client.estimateTokens(formattedMessages);
|
|
30
|
+
if (estimatedTokens > MAX_INPUT_TOKENS) {
|
|
31
|
+
const targetLength = Math.floor((MAX_INPUT_TOKENS / estimatedTokens) * formattedMessages.length * 0.8);
|
|
32
|
+
formattedMessages = formattedMessages.slice(0, targetLength) + '\n\n[... conversation truncated for analysis ...]';
|
|
33
|
+
}
|
|
34
|
+
const sessionMeta = buildSessionMeta(session);
|
|
35
|
+
const response = await client.chat([
|
|
36
|
+
{ role: 'system', content: SHARED_ANALYST_SYSTEM_PROMPT },
|
|
37
|
+
{ role: 'user', content: [
|
|
38
|
+
buildCacheableConversationBlock(formattedMessages),
|
|
39
|
+
{ type: 'text', text: buildFacetOnlyInstructions(session.project_name, session.summary, sessionMeta) },
|
|
40
|
+
] },
|
|
41
|
+
], { signal: options?.signal });
|
|
42
|
+
const jsonPayload = extractJsonPayload(response.content);
|
|
43
|
+
if (!jsonPayload) {
|
|
44
|
+
return { success: false, error: 'No JSON in facet response.' };
|
|
45
|
+
}
|
|
46
|
+
let facets;
|
|
47
|
+
try {
|
|
48
|
+
facets = JSON.parse(jsonPayload);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
facets = JSON.parse(jsonrepair(jsonPayload));
|
|
52
|
+
}
|
|
53
|
+
if (facets) {
|
|
54
|
+
saveFacetsToDb(session.id, facets, ANALYSIS_VERSION);
|
|
55
|
+
}
|
|
56
|
+
// Record analysis cost to analysis_usage table (V7).
|
|
57
|
+
const llmConfig = loadLLMConfig();
|
|
58
|
+
if (llmConfig && response.usage) {
|
|
59
|
+
const costUsd = calculateAnalysisCost(llmConfig.provider, llmConfig.model, {
|
|
60
|
+
inputTokens: response.usage.inputTokens,
|
|
61
|
+
outputTokens: response.usage.outputTokens,
|
|
62
|
+
cacheCreationTokens: response.usage.cacheCreationTokens,
|
|
63
|
+
cacheReadTokens: response.usage.cacheReadTokens,
|
|
64
|
+
});
|
|
65
|
+
saveAnalysisUsage({
|
|
66
|
+
session_id: session.id,
|
|
67
|
+
analysis_type: 'facet',
|
|
68
|
+
provider: llmConfig.provider,
|
|
69
|
+
model: llmConfig.model,
|
|
70
|
+
input_tokens: response.usage.inputTokens,
|
|
71
|
+
output_tokens: response.usage.outputTokens,
|
|
72
|
+
cache_creation_tokens: response.usage.cacheCreationTokens,
|
|
73
|
+
cache_read_tokens: response.usage.cacheReadTokens,
|
|
74
|
+
estimated_cost_usd: costUsd,
|
|
75
|
+
duration_ms: Date.now() - startTime,
|
|
76
|
+
chunk_count: 1,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return { success: true };
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
83
|
+
return { success: false, error: 'Cancelled' };
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: error instanceof Error ? error.message : 'Facet extraction failed',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=facet-extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facet-extraction.js","sourceRoot":"","sources":["../../src/llm/facet-extraction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a friction category to the closest canonical category.
|
|
3
|
+
* Returns the original category if no close match is found.
|
|
4
|
+
*
|
|
5
|
+
* Matching rules (in order):
|
|
6
|
+
* 1. Exact match against canonical list → return as-is
|
|
7
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
8
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
9
|
+
* 3. Substring match (category contains canonical or vice versa) → return canonical
|
|
10
|
+
* 4. No match → return original (novel category)
|
|
11
|
+
*
|
|
12
|
+
* Note: alias targets in FRICTION_ALIASES bypass the canonical check intentionally.
|
|
13
|
+
* e.g., "agent-orchestration-failure" is not canonical but is a valid cluster target.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeFrictionCategory(category: string): string;
|
|
16
|
+
//# sourceMappingURL=friction-normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"friction-normalize.d.ts","sourceRoot":"","sources":["../../src/llm/friction-normalize.ts"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKlE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Friction category normalization.
|
|
2
|
+
// Clusters similar free-form friction categories to canonical ones during aggregation.
|
|
3
|
+
import { CANONICAL_FRICTION_CATEGORIES } from './prompt-constants.js';
|
|
4
|
+
import { normalizeCategory } from './normalize-utils.js';
|
|
5
|
+
// Explicit alias map for clustering emergent category variants.
|
|
6
|
+
// Targets don't need to be in CANONICAL_FRICTION_CATEGORIES —
|
|
7
|
+
// this clusters semantically-equivalent novel categories together.
|
|
8
|
+
// Insert alias lookup runs AFTER exact canonical match but BEFORE Levenshtein,
|
|
9
|
+
// so well-known emergent variants are clustered deterministically.
|
|
10
|
+
const FRICTION_ALIASES = {
|
|
11
|
+
// legacy canonical → new canonical (15→9 taxonomy revision)
|
|
12
|
+
'missing-dependency': 'stale-assumptions',
|
|
13
|
+
'config-drift': 'stale-assumptions',
|
|
14
|
+
'stale-cache': 'stale-assumptions',
|
|
15
|
+
'version-mismatch': 'stale-assumptions',
|
|
16
|
+
'permission-issue': 'stale-assumptions',
|
|
17
|
+
'environment-mismatch': 'stale-assumptions',
|
|
18
|
+
'race-condition': 'wrong-approach',
|
|
19
|
+
'circular-dependency': 'wrong-approach',
|
|
20
|
+
'test-failure': 'wrong-approach',
|
|
21
|
+
'type-error': 'knowledge-gap',
|
|
22
|
+
'api-misunderstanding': 'knowledge-gap',
|
|
23
|
+
// agent orchestration variants → cluster under one emergent name
|
|
24
|
+
'agent-lifecycle-issue': 'agent-orchestration-failure',
|
|
25
|
+
'agent-communication-failure': 'agent-orchestration-failure',
|
|
26
|
+
'agent-communication-breakdown': 'agent-orchestration-failure',
|
|
27
|
+
'agent-lifecycle-management': 'agent-orchestration-failure',
|
|
28
|
+
'agent-shutdown-failure': 'agent-orchestration-failure',
|
|
29
|
+
// rate limit variants → cluster under one emergent name
|
|
30
|
+
'api-rate-limit': 'rate-limit-hit',
|
|
31
|
+
'rate-limiting': 'rate-limit-hit',
|
|
32
|
+
'rate-limited': 'rate-limit-hit',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a friction category to the closest canonical category.
|
|
36
|
+
* Returns the original category if no close match is found.
|
|
37
|
+
*
|
|
38
|
+
* Matching rules (in order):
|
|
39
|
+
* 1. Exact match against canonical list → return as-is
|
|
40
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
41
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
42
|
+
* 3. Substring match (category contains canonical or vice versa) → return canonical
|
|
43
|
+
* 4. No match → return original (novel category)
|
|
44
|
+
*
|
|
45
|
+
* Note: alias targets in FRICTION_ALIASES bypass the canonical check intentionally.
|
|
46
|
+
* e.g., "agent-orchestration-failure" is not canonical but is a valid cluster target.
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeFrictionCategory(category) {
|
|
49
|
+
return normalizeCategory(category, {
|
|
50
|
+
canonicalCategories: CANONICAL_FRICTION_CATEGORIES,
|
|
51
|
+
aliases: FRICTION_ALIASES,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=friction-normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"friction-normalize.js","sourceRoot":"","sources":["../../src/llm/friction-normalize.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,uFAAuF;AAEvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,gEAAgE;AAChE,8DAA8D;AAC9D,mEAAmE;AACnE,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,gBAAgB,GAA2B;IAC/C,4DAA4D;IAC5D,oBAAoB,EAAE,mBAAmB;IACzC,cAAc,EAAE,mBAAmB;IACnC,aAAa,EAAE,mBAAmB;IAClC,kBAAkB,EAAE,mBAAmB;IACvC,kBAAkB,EAAE,mBAAmB;IACvC,sBAAsB,EAAE,mBAAmB;IAC3C,gBAAgB,EAAE,gBAAgB;IAClC,qBAAqB,EAAE,gBAAgB;IACvC,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,eAAe;IAC7B,sBAAsB,EAAE,eAAe;IACvC,iEAAiE;IACjE,uBAAuB,EAAE,6BAA6B;IACtD,6BAA6B,EAAE,6BAA6B;IAC5D,+BAA+B,EAAE,6BAA6B;IAC9D,4BAA4B,EAAE,6BAA6B;IAC3D,wBAAwB,EAAE,6BAA6B;IACvD,wDAAwD;IACxD,gBAAgB,EAAE,gBAAgB;IAClC,eAAe,EAAE,gBAAgB;IACjC,cAAc,EAAE,gBAAgB;CACjC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAgB;IACxD,OAAO,iBAAiB,CAAC,QAAQ,EAAE;QACjC,mBAAmB,EAAE,6BAA6B;QAClD,OAAO,EAAE,gBAAgB;KAC1B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export type { LLMClient, LLMMessage, LLMResponse, ChatOptions } from './types.js';
|
|
2
2
|
export type { LLMProvider, LLMProviderConfig } from './types.js';
|
|
3
3
|
export { createLLMClient, createClientFromConfig, loadLLMConfig, isLLMConfigured, testLLMConfig } from './client.js';
|
|
4
|
-
export { analyzeSession, analyzePromptQuality, findRecurringInsights } from './analysis.js';
|
|
5
|
-
export type { AnalysisResult,
|
|
4
|
+
export { analyzeSession, analyzePromptQuality, findRecurringInsights, extractFacetsOnly } from './analysis.js';
|
|
5
|
+
export type { AnalysisResult, RecurringInsightResult } from './analysis.js';
|
|
6
|
+
export type { InsightRow, SessionData } from './analysis-db.js';
|
|
6
7
|
export { discoverOllamaModels } from './providers/ollama.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC/G,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/server-dist/llm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Public API for the server-side LLM engine.
|
|
2
2
|
export { createLLMClient, createClientFromConfig, loadLLMConfig, isLLMConfigured, testLLMConfig } from './client.js';
|
|
3
|
-
export { analyzeSession, analyzePromptQuality, findRecurringInsights } from './analysis.js';
|
|
3
|
+
export { analyzeSession, analyzePromptQuality, findRecurringInsights, extractFacetsOnly } from './analysis.js';
|
|
4
4
|
export { discoverOllamaModels } from './providers/ollama.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAI7C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAI7C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAG/G,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SQLiteMessageRow, SessionMetadata } from './prompt-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detect the class of a stored user message from its content string.
|
|
4
|
+
* Operates on the DB content field (stringified), not raw JSONL.
|
|
5
|
+
*
|
|
6
|
+
* This mirrors classifyUserMessage() in cli/src/parser/jsonl.ts but works on
|
|
7
|
+
* stored content strings instead of parsed JSONL message objects. The DB stores
|
|
8
|
+
* message content as a plain string — tool-results are JSON arrays stringified,
|
|
9
|
+
* human text is stored as-is.
|
|
10
|
+
*
|
|
11
|
+
* Order matters — most specific checks first.
|
|
12
|
+
*/
|
|
13
|
+
export declare function classifyStoredUserMessage(content: string): 'human' | 'tool-result' | 'system-artifact';
|
|
14
|
+
/**
|
|
15
|
+
* Format SQLite message rows for LLM consumption.
|
|
16
|
+
* Handles snake_case fields and JSON-encoded tool_calls/tool_results.
|
|
17
|
+
*
|
|
18
|
+
* User#N indices only increment for genuine human messages. Tool-results and
|
|
19
|
+
* system artifacts (auto-compacts, slash commands) receive bracketed labels
|
|
20
|
+
* instead. This ensures User#N references in PQ takeaways and evidence fields
|
|
21
|
+
* align with actual human turns, not inflated by tool-result rows.
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatMessagesForAnalysis(messages: SQLiteMessageRow[]): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format a one-line context signals header from V6 session metadata.
|
|
26
|
+
* Returns empty string when no signals are present (pre-V6 sessions with NULL columns).
|
|
27
|
+
*
|
|
28
|
+
* Example output:
|
|
29
|
+
* "Context signals: 3 context compactions (2 auto, 1 manual) — session exceeded context window; slash commands used: /review, /test\n"
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatSessionMetaLine(meta?: SessionMetadata): string;
|
|
32
|
+
//# sourceMappingURL=message-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-format.d.ts","sourceRoot":"","sources":["../../src/llm/message-format.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAW3E;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,iBAAiB,CAiBtG;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,CA6D9E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,MAAM,CAkBpE"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// SQLite message formatting utilities for LLM prompt construction.
|
|
2
|
+
// Extracted from prompts.ts — used by prompt generator functions in prompts.ts.
|
|
3
|
+
/**
|
|
4
|
+
* Detect the class of a stored user message from its content string.
|
|
5
|
+
* Operates on the DB content field (stringified), not raw JSONL.
|
|
6
|
+
*
|
|
7
|
+
* This mirrors classifyUserMessage() in cli/src/parser/jsonl.ts but works on
|
|
8
|
+
* stored content strings instead of parsed JSONL message objects. The DB stores
|
|
9
|
+
* message content as a plain string — tool-results are JSON arrays stringified,
|
|
10
|
+
* human text is stored as-is.
|
|
11
|
+
*
|
|
12
|
+
* Order matters — most specific checks first.
|
|
13
|
+
*/
|
|
14
|
+
export function classifyStoredUserMessage(content) {
|
|
15
|
+
// Tool-result: content is a JSON array containing tool_result blocks.
|
|
16
|
+
// The DB stores these as stringified JSON arrays starting with '['.
|
|
17
|
+
if (content.startsWith('[') && content.includes('"tool_result"'))
|
|
18
|
+
return 'tool-result';
|
|
19
|
+
// Auto-compact summary: Claude Code uses two known prefixes for LLM-initiated
|
|
20
|
+
// context compaction summaries. Both must be checked.
|
|
21
|
+
if (content.startsWith('Here is a summary of our conversation'))
|
|
22
|
+
return 'system-artifact';
|
|
23
|
+
if (content.startsWith('This session is being continued'))
|
|
24
|
+
return 'system-artifact';
|
|
25
|
+
// Slash command or skill load: single-line starting with / followed by a lowercase letter.
|
|
26
|
+
// Requires content.trim() to be short (≤2 lines) to avoid false-positives on messages
|
|
27
|
+
// containing file paths like "/usr/bin/..." as part of a longer instruction.
|
|
28
|
+
const trimmed = content.trim();
|
|
29
|
+
if (/^\/[a-z]/.test(trimmed) && trimmed.split('\n').length <= 2)
|
|
30
|
+
return 'system-artifact';
|
|
31
|
+
return 'human';
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format SQLite message rows for LLM consumption.
|
|
35
|
+
* Handles snake_case fields and JSON-encoded tool_calls/tool_results.
|
|
36
|
+
*
|
|
37
|
+
* User#N indices only increment for genuine human messages. Tool-results and
|
|
38
|
+
* system artifacts (auto-compacts, slash commands) receive bracketed labels
|
|
39
|
+
* instead. This ensures User#N references in PQ takeaways and evidence fields
|
|
40
|
+
* align with actual human turns, not inflated by tool-result rows.
|
|
41
|
+
*/
|
|
42
|
+
export function formatMessagesForAnalysis(messages) {
|
|
43
|
+
let userIndex = 0;
|
|
44
|
+
let assistantIndex = 0;
|
|
45
|
+
return messages
|
|
46
|
+
.map((m) => {
|
|
47
|
+
let roleLabel;
|
|
48
|
+
if (m.type === 'user') {
|
|
49
|
+
const msgClass = classifyStoredUserMessage(m.content);
|
|
50
|
+
if (msgClass === 'tool-result') {
|
|
51
|
+
roleLabel = '[tool-result]';
|
|
52
|
+
}
|
|
53
|
+
else if (msgClass === 'system-artifact') {
|
|
54
|
+
// Auto-compact summaries use two known prefixes — everything else (slash commands,
|
|
55
|
+
// skill loads) is a generic system artifact, not a compaction event.
|
|
56
|
+
const isAutoCompact = m.content.startsWith('Here is a summary of our conversation')
|
|
57
|
+
|| m.content.startsWith('This session is being continued');
|
|
58
|
+
roleLabel = isAutoCompact ? '[auto-compact]' : '[system]';
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Genuine human message — increment counter
|
|
62
|
+
roleLabel = `User#${userIndex++}`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (m.type === 'assistant') {
|
|
66
|
+
roleLabel = `Assistant#${assistantIndex++}`;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
roleLabel = 'System';
|
|
70
|
+
}
|
|
71
|
+
// Parse JSON-encoded tool_calls
|
|
72
|
+
let toolCalls = [];
|
|
73
|
+
try {
|
|
74
|
+
toolCalls = m.tool_calls ? JSON.parse(m.tool_calls) : [];
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
toolCalls = [];
|
|
78
|
+
}
|
|
79
|
+
// Parse JSON-encoded tool_results
|
|
80
|
+
let toolResults = [];
|
|
81
|
+
try {
|
|
82
|
+
toolResults = m.tool_results ? JSON.parse(m.tool_results) : [];
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
toolResults = [];
|
|
86
|
+
}
|
|
87
|
+
const toolInfo = toolCalls.length > 0
|
|
88
|
+
? `\n[Tools used: ${toolCalls.map(t => t.name || 'unknown').join(', ')}]`
|
|
89
|
+
: '';
|
|
90
|
+
// Include thinking content — capped at 1000 chars to stay within token budget
|
|
91
|
+
const thinkingInfo = m.thinking
|
|
92
|
+
? `\n[Thinking: ${m.thinking.slice(0, 1000)}]`
|
|
93
|
+
: '';
|
|
94
|
+
// Include tool results for context — 500 chars per result (error messages need ~300-400 chars)
|
|
95
|
+
const resultInfo = toolResults.length > 0
|
|
96
|
+
? `\n[Tool results: ${toolResults.map(r => (r.output || '').slice(0, 500)).join(' | ')}]`
|
|
97
|
+
: '';
|
|
98
|
+
return `### ${roleLabel}:\n${m.content}${thinkingInfo}${toolInfo}${resultInfo}`;
|
|
99
|
+
})
|
|
100
|
+
.join('\n\n');
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Format a one-line context signals header from V6 session metadata.
|
|
104
|
+
* Returns empty string when no signals are present (pre-V6 sessions with NULL columns).
|
|
105
|
+
*
|
|
106
|
+
* Example output:
|
|
107
|
+
* "Context signals: 3 context compactions (2 auto, 1 manual) — session exceeded context window; slash commands used: /review, /test\n"
|
|
108
|
+
*/
|
|
109
|
+
export function formatSessionMetaLine(meta) {
|
|
110
|
+
if (!meta)
|
|
111
|
+
return '';
|
|
112
|
+
const parts = [];
|
|
113
|
+
const totalCompacts = (meta.compactCount ?? 0) + (meta.autoCompactCount ?? 0);
|
|
114
|
+
if (totalCompacts > 0) {
|
|
115
|
+
const breakdown = [];
|
|
116
|
+
if (meta.autoCompactCount)
|
|
117
|
+
breakdown.push(`${meta.autoCompactCount} auto`);
|
|
118
|
+
if (meta.compactCount)
|
|
119
|
+
breakdown.push(`${meta.compactCount} manual`);
|
|
120
|
+
parts.push(`${totalCompacts} context compaction${totalCompacts > 1 ? 's' : ''} (${breakdown.join(', ')}) — session exceeded context window`);
|
|
121
|
+
}
|
|
122
|
+
if (meta.slashCommands?.length) {
|
|
123
|
+
parts.push(`slash commands used: ${meta.slashCommands.join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
if (parts.length === 0)
|
|
126
|
+
return '';
|
|
127
|
+
return `Context signals: ${parts.join('; ')}\n`;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=message-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-format.js","sourceRoot":"","sources":["../../src/llm/message-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Standard Levenshtein distance between two strings */
|
|
2
|
+
export declare function levenshtein(a: string, b: string): number;
|
|
3
|
+
export interface NormalizerConfig {
|
|
4
|
+
/** Canonical category strings (lowercase kebab-case) */
|
|
5
|
+
canonicalCategories: readonly string[];
|
|
6
|
+
/** Maps known aliases to their target (may be non-canonical cluster targets) */
|
|
7
|
+
aliases: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generic category normalizer. Matching rules (in order):
|
|
11
|
+
* 1. Exact match against canonical list → return as-is
|
|
12
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
13
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
14
|
+
* 3. Substring match (shorter >= 5 chars, >= 50% of longer) → return canonical
|
|
15
|
+
* 4. No match → return original (novel category)
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizeCategory(category: string, config: NormalizerConfig): string;
|
|
18
|
+
/**
|
|
19
|
+
* Convert kebab-case to Title Case. Shared fallback for category label functions.
|
|
20
|
+
*/
|
|
21
|
+
export declare function kebabToTitleCase(kebab: string): string;
|
|
22
|
+
//# sourceMappingURL=normalize-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-utils.d.ts","sourceRoot":"","sources":["../../src/llm/normalize-utils.ts"],"names":[],"mappings":"AAGA,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAmCpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Shared normalization infrastructure for friction, pattern, and prompt-quality categories.
|
|
2
|
+
// Each domain provides its own canonical list, alias map, and label map.
|
|
3
|
+
/** Standard Levenshtein distance between two strings */
|
|
4
|
+
export function levenshtein(a, b) {
|
|
5
|
+
const m = a.length;
|
|
6
|
+
const n = b.length;
|
|
7
|
+
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
|
8
|
+
for (let i = 0; i <= m; i++)
|
|
9
|
+
dp[i][0] = i;
|
|
10
|
+
for (let j = 0; j <= n; j++)
|
|
11
|
+
dp[0][j] = j;
|
|
12
|
+
for (let i = 1; i <= m; i++) {
|
|
13
|
+
for (let j = 1; j <= n; j++) {
|
|
14
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
15
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return dp[m][n];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generic category normalizer. Matching rules (in order):
|
|
22
|
+
* 1. Exact match against canonical list → return as-is
|
|
23
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
24
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
25
|
+
* 3. Substring match (shorter >= 5 chars, >= 50% of longer) → return canonical
|
|
26
|
+
* 4. No match → return original (novel category)
|
|
27
|
+
*/
|
|
28
|
+
export function normalizeCategory(category, config) {
|
|
29
|
+
const lower = category.toLowerCase();
|
|
30
|
+
// 1. Exact match
|
|
31
|
+
for (const canonical of config.canonicalCategories) {
|
|
32
|
+
if (lower === canonical)
|
|
33
|
+
return canonical;
|
|
34
|
+
}
|
|
35
|
+
// 1.5. Explicit alias match
|
|
36
|
+
if (config.aliases[lower])
|
|
37
|
+
return config.aliases[lower];
|
|
38
|
+
// 2. Levenshtein distance <= 2
|
|
39
|
+
let bestMatch = null;
|
|
40
|
+
let bestDistance = Infinity;
|
|
41
|
+
for (const canonical of config.canonicalCategories) {
|
|
42
|
+
const dist = levenshtein(lower, canonical);
|
|
43
|
+
if (dist <= 2 && dist < bestDistance) {
|
|
44
|
+
bestDistance = dist;
|
|
45
|
+
bestMatch = canonical;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (bestMatch)
|
|
49
|
+
return bestMatch;
|
|
50
|
+
// 3. Substring match — only if the shorter string is a significant portion of the longer
|
|
51
|
+
// to avoid false positives like "type" matching "type-error"
|
|
52
|
+
for (const canonical of config.canonicalCategories) {
|
|
53
|
+
const shorter = lower.length < canonical.length ? lower : canonical;
|
|
54
|
+
const longer = lower.length < canonical.length ? canonical : lower;
|
|
55
|
+
if (shorter.length >= 5 && shorter.length / longer.length >= 0.5 && longer.includes(shorter)) {
|
|
56
|
+
return canonical;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 4. No match — novel category
|
|
60
|
+
return category;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Convert kebab-case to Title Case. Shared fallback for category label functions.
|
|
64
|
+
*/
|
|
65
|
+
export function kebabToTitleCase(kebab) {
|
|
66
|
+
return kebab
|
|
67
|
+
.split('-')
|
|
68
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
69
|
+
.join(' ');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=normalize-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-utils.js","sourceRoot":"","sources":["../../src/llm/normalize-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const PATTERN_CATEGORY_LABELS: Record<string, string>;
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a pattern category to the closest canonical category.
|
|
4
|
+
* Returns the original category if no close match is found.
|
|
5
|
+
*
|
|
6
|
+
* Matching rules (in order):
|
|
7
|
+
* 1. Exact match against canonical list → return as-is
|
|
8
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
9
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
10
|
+
* 3. Substring match (category contains canonical or vice versa) → return canonical
|
|
11
|
+
* 4. No match → return original (novel category)
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizePatternCategory(category: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get a human-readable label for a pattern category.
|
|
16
|
+
* Falls back to Title Case conversion for novel categories.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getPatternCategoryLabel(category: string): string;
|
|
19
|
+
//# sourceMappingURL=pattern-normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-normalize.d.ts","sourceRoot":"","sources":["../../src/llm/pattern-normalize.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAS1D,CAAC;AA0DF;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Effective pattern category normalization.
|
|
2
|
+
// Clusters similar free-form pattern categories to canonical ones during aggregation.
|
|
3
|
+
// Delegates to normalize-utils.ts for the shared levenshtein/normalizeCategory algorithm.
|
|
4
|
+
import { CANONICAL_PATTERN_CATEGORIES } from './prompt-constants.js';
|
|
5
|
+
import { normalizeCategory, kebabToTitleCase } from './normalize-utils.js';
|
|
6
|
+
// Human-readable labels for each canonical category.
|
|
7
|
+
// Used in dashboard display (e.g., "structured-planning" → "Structured Planning").
|
|
8
|
+
export const PATTERN_CATEGORY_LABELS = {
|
|
9
|
+
'structured-planning': 'Structured Planning',
|
|
10
|
+
'incremental-implementation': 'Incremental Implementation',
|
|
11
|
+
'verification-workflow': 'Verification Workflow',
|
|
12
|
+
'systematic-debugging': 'Systematic Debugging',
|
|
13
|
+
'self-correction': 'Self-Correction',
|
|
14
|
+
'context-gathering': 'Context Gathering',
|
|
15
|
+
'domain-expertise': 'Domain Expertise',
|
|
16
|
+
'effective-tooling': 'Effective Tooling',
|
|
17
|
+
};
|
|
18
|
+
// Explicit alias map for clustering emergent category variants.
|
|
19
|
+
// Targets don't need to be in CANONICAL_PATTERN_CATEGORIES —
|
|
20
|
+
// this clusters semantically-equivalent novel categories together.
|
|
21
|
+
// Insert alias lookup runs AFTER exact canonical match but BEFORE Levenshtein,
|
|
22
|
+
// so well-known emergent variants are clustered deterministically.
|
|
23
|
+
const PATTERN_ALIASES = {
|
|
24
|
+
// structured-planning variants
|
|
25
|
+
'task-decomposition': 'structured-planning',
|
|
26
|
+
'plan-first': 'structured-planning',
|
|
27
|
+
'upfront-planning': 'structured-planning',
|
|
28
|
+
'phased-approach': 'structured-planning',
|
|
29
|
+
'task-breakdown': 'structured-planning',
|
|
30
|
+
'planning-before-implementation': 'structured-planning',
|
|
31
|
+
// effective-tooling variants
|
|
32
|
+
'agent-delegation': 'effective-tooling',
|
|
33
|
+
'agent-orchestration': 'effective-tooling',
|
|
34
|
+
'specialized-agents': 'effective-tooling',
|
|
35
|
+
'multi-agent': 'effective-tooling',
|
|
36
|
+
'tool-leverage': 'effective-tooling',
|
|
37
|
+
// verification-workflow variants
|
|
38
|
+
'build-test-verify': 'verification-workflow',
|
|
39
|
+
'test-driven-development': 'verification-workflow',
|
|
40
|
+
'tdd': 'verification-workflow',
|
|
41
|
+
'test-first': 'verification-workflow',
|
|
42
|
+
'pre-commit-checks': 'verification-workflow',
|
|
43
|
+
// systematic-debugging variants
|
|
44
|
+
'binary-search-debugging': 'systematic-debugging',
|
|
45
|
+
'methodical-debugging': 'systematic-debugging',
|
|
46
|
+
'log-based-debugging': 'systematic-debugging',
|
|
47
|
+
'debugging-methodology': 'systematic-debugging',
|
|
48
|
+
// self-correction variants
|
|
49
|
+
'course-correction': 'self-correction',
|
|
50
|
+
'pivot-on-failure': 'self-correction',
|
|
51
|
+
'backtracking': 'self-correction',
|
|
52
|
+
// context-gathering variants
|
|
53
|
+
'code-reading-first': 'context-gathering',
|
|
54
|
+
'codebase-exploration': 'context-gathering',
|
|
55
|
+
'understanding-before-changing': 'context-gathering',
|
|
56
|
+
// domain-expertise variants
|
|
57
|
+
'framework-knowledge': 'domain-expertise',
|
|
58
|
+
'types-first': 'domain-expertise',
|
|
59
|
+
'type-driven-development': 'domain-expertise',
|
|
60
|
+
'schema-first': 'domain-expertise',
|
|
61
|
+
// incremental-implementation variants
|
|
62
|
+
'small-steps': 'incremental-implementation',
|
|
63
|
+
'iterative-building': 'incremental-implementation',
|
|
64
|
+
'iterative-development': 'incremental-implementation',
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Normalize a pattern category to the closest canonical category.
|
|
68
|
+
* Returns the original category if no close match is found.
|
|
69
|
+
*
|
|
70
|
+
* Matching rules (in order):
|
|
71
|
+
* 1. Exact match against canonical list → return as-is
|
|
72
|
+
* 1.5. Explicit alias match → return alias target (may be non-canonical)
|
|
73
|
+
* 2. Levenshtein distance <= 2 → return canonical match
|
|
74
|
+
* 3. Substring match (category contains canonical or vice versa) → return canonical
|
|
75
|
+
* 4. No match → return original (novel category)
|
|
76
|
+
*/
|
|
77
|
+
export function normalizePatternCategory(category) {
|
|
78
|
+
return normalizeCategory(category, {
|
|
79
|
+
canonicalCategories: CANONICAL_PATTERN_CATEGORIES,
|
|
80
|
+
aliases: PATTERN_ALIASES,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get a human-readable label for a pattern category.
|
|
85
|
+
* Falls back to Title Case conversion for novel categories.
|
|
86
|
+
*/
|
|
87
|
+
export function getPatternCategoryLabel(category) {
|
|
88
|
+
return PATTERN_CATEGORY_LABELS[category] ?? kebabToTitleCase(category);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=pattern-normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-normalize.js","sourceRoot":"","sources":["../../src/llm/pattern-normalize.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sFAAsF;AACtF,0FAA0F;AAE1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE3E,qDAAqD;AACrD,mFAAmF;AACnF,MAAM,CAAC,MAAM,uBAAuB,GAA2B;IAC7D,qBAAqB,EAAE,qBAAqB;IAC5C,4BAA4B,EAAE,4BAA4B;IAC1D,uBAAuB,EAAE,uBAAuB;IAChD,sBAAsB,EAAE,sBAAsB;IAC9C,iBAAiB,EAAE,iBAAiB;IACpC,mBAAmB,EAAE,mBAAmB;IACxC,kBAAkB,EAAE,kBAAkB;IACtC,mBAAmB,EAAE,mBAAmB;CACzC,CAAC;AAEF,gEAAgE;AAChE,6DAA6D;AAC7D,mEAAmE;AACnE,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,eAAe,GAA2B;IAC9C,+BAA+B;IAC/B,oBAAoB,EAAE,qBAAqB;IAC3C,YAAY,EAAE,qBAAqB;IACnC,kBAAkB,EAAE,qBAAqB;IACzC,iBAAiB,EAAE,qBAAqB;IACxC,gBAAgB,EAAE,qBAAqB;IACvC,gCAAgC,EAAE,qBAAqB;IAEvD,6BAA6B;IAC7B,kBAAkB,EAAE,mBAAmB;IACvC,qBAAqB,EAAE,mBAAmB;IAC1C,oBAAoB,EAAE,mBAAmB;IACzC,aAAa,EAAE,mBAAmB;IAClC,eAAe,EAAE,mBAAmB;IAEpC,iCAAiC;IACjC,mBAAmB,EAAE,uBAAuB;IAC5C,yBAAyB,EAAE,uBAAuB;IAClD,KAAK,EAAE,uBAAuB;IAC9B,YAAY,EAAE,uBAAuB;IACrC,mBAAmB,EAAE,uBAAuB;IAE5C,gCAAgC;IAChC,yBAAyB,EAAE,sBAAsB;IACjD,sBAAsB,EAAE,sBAAsB;IAC9C,qBAAqB,EAAE,sBAAsB;IAC7C,uBAAuB,EAAE,sBAAsB;IAE/C,2BAA2B;IAC3B,mBAAmB,EAAE,iBAAiB;IACtC,kBAAkB,EAAE,iBAAiB;IACrC,cAAc,EAAE,iBAAiB;IAEjC,6BAA6B;IAC7B,oBAAoB,EAAE,mBAAmB;IACzC,sBAAsB,EAAE,mBAAmB;IAC3C,+BAA+B,EAAE,mBAAmB;IAEpD,4BAA4B;IAC5B,qBAAqB,EAAE,kBAAkB;IACzC,aAAa,EAAE,kBAAkB;IACjC,yBAAyB,EAAE,kBAAkB;IAC7C,cAAc,EAAE,kBAAkB;IAElC,sCAAsC;IACtC,aAAa,EAAE,4BAA4B;IAC3C,oBAAoB,EAAE,4BAA4B;IAClD,uBAAuB,EAAE,4BAA4B;CACtD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACvD,OAAO,iBAAiB,CAAC,QAAQ,EAAE;QACjC,mBAAmB,EAAE,4BAA4B;QACjD,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,OAAO,uBAAuB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACzE,CAAC"}
|