@triedotdev/mcp 1.0.163 → 1.0.164
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/dist/{chunk-XSKLOBD2.js → chunk-D6E4Q4I6.js} +328 -19
- package/dist/chunk-D6E4Q4I6.js.map +1 -0
- package/dist/{chunk-GL62CXU4.js → chunk-OKK4QNK3.js} +2 -2
- package/dist/cli/yolo-daemon.js +1 -1
- package/dist/index.js +2 -2
- package/dist/server/mcp-server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-XSKLOBD2.js.map +0 -1
- /package/dist/{chunk-GL62CXU4.js.map → chunk-OKK4QNK3.js.map} +0 -0
|
@@ -13,6 +13,9 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
getOutputManager
|
|
15
15
|
} from "./chunk-VR4VWXXU.js";
|
|
16
|
+
import {
|
|
17
|
+
getInsightStore
|
|
18
|
+
} from "./chunk-T63OHG4Q.js";
|
|
16
19
|
import {
|
|
17
20
|
LearningEngine,
|
|
18
21
|
exportToJson,
|
|
@@ -697,10 +700,11 @@ function dashboardReducer(state, action) {
|
|
|
697
700
|
const gotchas = action.storageGotchas ?? state.memoryTree.storageGotchas;
|
|
698
701
|
const facts = action.storageFacts ?? state.memoryTree.storageFacts;
|
|
699
702
|
const nudges = action.storageNudges ?? state.memoryTree.storageNudges;
|
|
703
|
+
const insights = action.storageInsights ?? state.memoryTree.storageInsights;
|
|
700
704
|
const expanded = new Set(state.memoryTree.expandedNodes);
|
|
701
705
|
if (blocks.length > 0) expanded.add("ledger-chain");
|
|
702
706
|
if (gotchas.length > 0) expanded.add("gotchas");
|
|
703
|
-
if (nudges.length > 0) expanded.add("patterns");
|
|
707
|
+
if (nudges.length > 0 || insights.length > 0) expanded.add("patterns");
|
|
704
708
|
return {
|
|
705
709
|
...state,
|
|
706
710
|
memoryTree: {
|
|
@@ -712,6 +716,7 @@ function dashboardReducer(state, action) {
|
|
|
712
716
|
storageFacts: facts,
|
|
713
717
|
storageGotchas: gotchas,
|
|
714
718
|
storageNudges: nudges,
|
|
719
|
+
storageInsights: insights,
|
|
715
720
|
ledgerBlocks: blocks,
|
|
716
721
|
expandedNodes: expanded
|
|
717
722
|
}
|
|
@@ -976,7 +981,7 @@ function createInitialState() {
|
|
|
976
981
|
},
|
|
977
982
|
goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningGoalId: null, scanningProgress: "" },
|
|
978
983
|
hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningHypothesisId: null, scanningProgress: "" },
|
|
979
|
-
memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageFacts: [], storageGotchas: [], storageNudges: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
|
|
984
|
+
memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageFacts: [], storageGotchas: [], storageNudges: [], storageInsights: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
|
|
980
985
|
agentBrain: { loaded: false, governance: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
|
|
981
986
|
chatState: { messages: [], inputBuffer: "", loading: false, progress: null, messageQueue: [], currentSessionId: null, currentSessionTitle: null },
|
|
982
987
|
chatArchivePanel: { sessions: [], selectedIndex: 0, showArchived: false, loading: false, inputMode: "browse", inputBuffer: "" },
|
|
@@ -1977,8 +1982,8 @@ function AgentView() {
|
|
|
1977
1982
|
if (!insight) return;
|
|
1978
1983
|
try {
|
|
1979
1984
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1980
|
-
const { getInsightStore } = await import("./insight-store-EC4PLSAW.js");
|
|
1981
|
-
const store =
|
|
1985
|
+
const { getInsightStore: getInsightStore2 } = await import("./insight-store-EC4PLSAW.js");
|
|
1986
|
+
const store = getInsightStore2(workDir);
|
|
1982
1987
|
await store.dismissInsight(insight.id);
|
|
1983
1988
|
const { getStorage: getStorage2 } = await import("./tiered-storage-FHHAJR4P.js");
|
|
1984
1989
|
const storage = getStorage2(workDir);
|
|
@@ -2813,7 +2818,7 @@ function timeAgo2(iso) {
|
|
|
2813
2818
|
function MemoryTreeView() {
|
|
2814
2819
|
const { state, dispatch } = useDashboard();
|
|
2815
2820
|
const { memoryTree } = state;
|
|
2816
|
-
const { snapshot, globalPatterns, storageGovernance, storageFacts, storageGotchas, storageNudges, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
|
|
2821
|
+
const { snapshot, globalPatterns, storageGovernance, storageFacts, storageGotchas, storageNudges, storageInsights, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
|
|
2817
2822
|
const { stdout } = useStdout8();
|
|
2818
2823
|
const cols = stdout?.columns || 80;
|
|
2819
2824
|
const narrow = cols < 60;
|
|
@@ -2823,6 +2828,7 @@ function MemoryTreeView() {
|
|
|
2823
2828
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2824
2829
|
const graph = new ContextGraph(workDir);
|
|
2825
2830
|
const storage = new TieredStorage(workDir);
|
|
2831
|
+
const insightStore = getInsightStore(workDir);
|
|
2826
2832
|
const [snap, patterns, governance2, facts, gotchas, nudges, blocks] = await Promise.all([
|
|
2827
2833
|
graph.getSnapshot(),
|
|
2828
2834
|
findCrossProjectPatterns(2),
|
|
@@ -2832,7 +2838,9 @@ function MemoryTreeView() {
|
|
|
2832
2838
|
storage.queryNudges({ limit: 20, resolved: false }).catch(() => []),
|
|
2833
2839
|
getLedgerBlocks(workDir).catch(() => [])
|
|
2834
2840
|
]);
|
|
2835
|
-
|
|
2841
|
+
await insightStore.load();
|
|
2842
|
+
const insights = insightStore.getActiveInsights(10);
|
|
2843
|
+
dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns, storageGovernance: governance2, storageFacts: facts, storageGotchas: gotchas, storageNudges: nudges, storageInsights: insights, ledgerBlocks: blocks });
|
|
2836
2844
|
} catch (err) {
|
|
2837
2845
|
dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
|
|
2838
2846
|
}
|
|
@@ -2909,7 +2917,7 @@ function MemoryTreeView() {
|
|
|
2909
2917
|
const order = { critical: 0, high: 1 };
|
|
2910
2918
|
return (order[a.data.riskLevel] ?? 2) - (order[b.data.riskLevel] ?? 2);
|
|
2911
2919
|
});
|
|
2912
|
-
const totalEntries = productGovernance.length + learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length + ledgerBlocks.length;
|
|
2920
|
+
const totalEntries = productGovernance.length + learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + (storageInsights?.length ?? 0) + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length + ledgerBlocks.length;
|
|
2913
2921
|
const expandedGovernance = expandedItemId?.startsWith("decision-") ? governance.find((g) => `decision-${g.id}` === expandedItemId) : null;
|
|
2914
2922
|
const expandedIncident = expandedItemId?.startsWith("incident-") ? incidentNodes.find((n) => `incident-${n.id}` === expandedItemId) : null;
|
|
2915
2923
|
const expandedGotcha = expandedItemId?.startsWith("gotcha-") ? storageGotchas.find((g) => `gotcha-${g.id}` === expandedItemId) ?? null : null;
|
|
@@ -3175,15 +3183,39 @@ function MemoryTreeView() {
|
|
|
3175
3183
|
] })
|
|
3176
3184
|
] }, g.id);
|
|
3177
3185
|
}),
|
|
3178
|
-
renderHeader("patterns", "Learned Signals", learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + patternNodes.length, learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && patternNodes.length === 0 ? "-- Trie learns as you work" : void 0),
|
|
3186
|
+
renderHeader("patterns", "Learned Signals", (storageInsights?.length ?? 0) + learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + patternNodes.length, (storageInsights?.length ?? 0) === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && patternNodes.length === 0 ? "-- Trie learns as you work" : void 0),
|
|
3179
3187
|
expandedNodes.has("patterns") && /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
3180
|
-
(
|
|
3188
|
+
(storageInsights?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
3181
3189
|
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3182
3190
|
" ",
|
|
3183
3191
|
" ",
|
|
3184
|
-
"
|
|
3192
|
+
"Learnings"
|
|
3185
3193
|
] }),
|
|
3186
|
-
|
|
3194
|
+
storageInsights.slice(0, 5).map((insight) => {
|
|
3195
|
+
const descWidth = Math.max(30, contentWidth - 15);
|
|
3196
|
+
const desc = insight.message.length > descWidth ? insight.message.slice(0, descWidth - 3) + "..." : insight.message;
|
|
3197
|
+
const categoryLabel = insight.category === "security" ? "[sec]" : insight.category === "performance" ? "[perf]" : insight.category === "quality" ? "[qual]" : "[learn]";
|
|
3198
|
+
const confidenceColor = insight.priority >= 7 ? "green" : insight.priority >= 4 ? "yellow" : "white";
|
|
3199
|
+
return /* @__PURE__ */ jsxs10(Text10, { wrap: "truncate", children: [
|
|
3200
|
+
" ",
|
|
3201
|
+
/* @__PURE__ */ jsx11(Text10, { dimColor: true, children: categoryLabel }),
|
|
3202
|
+
" ",
|
|
3203
|
+
/* @__PURE__ */ jsx11(Text10, { children: desc }),
|
|
3204
|
+
narrow ? null : /* @__PURE__ */ jsxs10(Text10, { color: confidenceColor, dimColor: true, children: [
|
|
3205
|
+
" ",
|
|
3206
|
+
insight.priority,
|
|
3207
|
+
"/10"
|
|
3208
|
+
] })
|
|
3209
|
+
] }, insight.id);
|
|
3210
|
+
})
|
|
3211
|
+
] }),
|
|
3212
|
+
(storageNudges?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 ? 1 : 0, children: [
|
|
3213
|
+
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3214
|
+
" ",
|
|
3215
|
+
" ",
|
|
3216
|
+
(storageInsights?.length ?? 0) > 0 ? "Raw Detections" : "AI Detections"
|
|
3217
|
+
] }),
|
|
3218
|
+
storageNudges.slice(0, (storageInsights?.length ?? 0) > 0 ? 3 : 5).map((n) => {
|
|
3187
3219
|
const descWidth = Math.max(30, contentWidth - 15);
|
|
3188
3220
|
const desc = n.message.length > descWidth ? n.message.slice(0, descWidth - 3) + "..." : n.message;
|
|
3189
3221
|
const severityColor = n.severity === "critical" ? "red" : n.severity === "high" ? "yellow" : "cyan";
|
|
@@ -3199,7 +3231,7 @@ function MemoryTreeView() {
|
|
|
3199
3231
|
] }, n.id);
|
|
3200
3232
|
})
|
|
3201
3233
|
] }),
|
|
3202
|
-
learnedSignals.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageNudges?.length ?? 0) > 0 ? 1 : 0, children: [
|
|
3234
|
+
learnedSignals.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 ? 1 : 0, children: [
|
|
3203
3235
|
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3204
3236
|
" ",
|
|
3205
3237
|
" ",
|
|
@@ -3220,7 +3252,7 @@ function MemoryTreeView() {
|
|
|
3220
3252
|
] }, g.id);
|
|
3221
3253
|
})
|
|
3222
3254
|
] }),
|
|
3223
|
-
(storageFacts?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 ? 1 : 0, children: [
|
|
3255
|
+
(storageFacts?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 ? 1 : 0, children: [
|
|
3224
3256
|
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3225
3257
|
" ",
|
|
3226
3258
|
" ",
|
|
@@ -3241,8 +3273,8 @@ function MemoryTreeView() {
|
|
|
3241
3273
|
] }, f.id);
|
|
3242
3274
|
})
|
|
3243
3275
|
] }),
|
|
3244
|
-
patternNodes.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0 ? 1 : 0, children: [
|
|
3245
|
-
((storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0) && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3276
|
+
patternNodes.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0 ? 1 : 0, children: [
|
|
3277
|
+
((storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0) && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3246
3278
|
" ",
|
|
3247
3279
|
" ",
|
|
3248
3280
|
"Patterns"
|
|
@@ -3253,7 +3285,7 @@ function MemoryTreeView() {
|
|
|
3253
3285
|
const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
|
|
3254
3286
|
const descWidth = Math.max(30, contentWidth - 15);
|
|
3255
3287
|
const desc = n.data.description.length > descWidth ? n.data.description.slice(0, descWidth - 3) + "..." : n.data.description;
|
|
3256
|
-
const hasPreceding = (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0;
|
|
3288
|
+
const hasPreceding = (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0;
|
|
3257
3289
|
return /* @__PURE__ */ jsxs10(Text10, { wrap: "truncate", children: [
|
|
3258
3290
|
sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "> " }) : hasPreceding ? " " : " ",
|
|
3259
3291
|
!hasPreceding && " ",
|
|
@@ -3273,7 +3305,7 @@ function MemoryTreeView() {
|
|
|
3273
3305
|
] }, n.id);
|
|
3274
3306
|
})
|
|
3275
3307
|
] }),
|
|
3276
|
-
patternNodes.length === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3308
|
+
patternNodes.length === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && (storageInsights?.length ?? 0) === 0 && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3277
3309
|
" ",
|
|
3278
3310
|
" ",
|
|
3279
3311
|
"No signals learned yet. Trie will extract insights as you work."
|
|
@@ -9983,7 +10015,248 @@ var InteractiveDashboard = class {
|
|
|
9983
10015
|
import { watch, existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
|
|
9984
10016
|
import { stat, readFile as readFile5 } from "fs/promises";
|
|
9985
10017
|
import { join as join4, extname as extname3, basename } from "path";
|
|
10018
|
+
import { createHash as createHash3 } from "crypto";
|
|
10019
|
+
|
|
10020
|
+
// src/agent/signal-summarizer.ts
|
|
10021
|
+
import Anthropic2 from "@anthropic-ai/sdk";
|
|
9986
10022
|
import { createHash as createHash2 } from "crypto";
|
|
10023
|
+
var SIGNAL_THRESHOLD = 5;
|
|
10024
|
+
var SUMMARIZE_PROMPT = `You are an AI that learns patterns about a codebase from repeated issues.
|
|
10025
|
+
|
|
10026
|
+
Given a batch of similar code quality issues, extract a LEARNING about the codebase's tendencies. Don't summarize or count issues - identify what this pattern reveals about the codebase or team habits.
|
|
10027
|
+
|
|
10028
|
+
Good learnings (what we want):
|
|
10029
|
+
- "Type safety tends to be weak in this codebase"
|
|
10030
|
+
- "Error handling is often skipped in async code"
|
|
10031
|
+
- "The dashboard module has inconsistent patterns"
|
|
10032
|
+
- "State management doesn't follow a clear convention"
|
|
10033
|
+
|
|
10034
|
+
Bad learnings (avoid these):
|
|
10035
|
+
- "5 type safety issues detected" (just counting)
|
|
10036
|
+
- "Consider adding null checks" (action without insight)
|
|
10037
|
+
- "Issues found in src/dashboard" (no actual learning)
|
|
10038
|
+
|
|
10039
|
+
Respond with JSON:
|
|
10040
|
+
{
|
|
10041
|
+
"learning": "One sentence stating what Trie learned about this codebase (a tendency, habit, or pattern)",
|
|
10042
|
+
"evidence": "Brief explanation of what patterns led to this conclusion",
|
|
10043
|
+
"suggestedAction": "What could improve this tendency",
|
|
10044
|
+
"category": "quality" | "security" | "performance" | "pattern",
|
|
10045
|
+
"confidence": 1-10 (how confident is this learning based on evidence)
|
|
10046
|
+
}`;
|
|
10047
|
+
var SignalSummarizer = class {
|
|
10048
|
+
client = null;
|
|
10049
|
+
projectPath;
|
|
10050
|
+
processedBatches = /* @__PURE__ */ new Set();
|
|
10051
|
+
constructor(projectPath) {
|
|
10052
|
+
this.projectPath = projectPath;
|
|
10053
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
10054
|
+
if (apiKey) {
|
|
10055
|
+
this.client = new Anthropic2({ apiKey });
|
|
10056
|
+
}
|
|
10057
|
+
}
|
|
10058
|
+
/**
|
|
10059
|
+
* Check if we have enough nudges to generate a signal
|
|
10060
|
+
*/
|
|
10061
|
+
async checkAndSummarize() {
|
|
10062
|
+
const storage = getStorage(this.projectPath);
|
|
10063
|
+
await storage.initialize();
|
|
10064
|
+
const nudges = await storage.queryNudges({ resolved: false, limit: 100 });
|
|
10065
|
+
if (nudges.length < SIGNAL_THRESHOLD) {
|
|
10066
|
+
return null;
|
|
10067
|
+
}
|
|
10068
|
+
const batches = this.groupNudges(nudges);
|
|
10069
|
+
for (const batch of batches) {
|
|
10070
|
+
if (batch.nudges.length >= SIGNAL_THRESHOLD && !this.processedBatches.has(batch.key)) {
|
|
10071
|
+
const insight = await this.summarizeBatch(batch);
|
|
10072
|
+
if (insight) {
|
|
10073
|
+
this.processedBatches.add(batch.key);
|
|
10074
|
+
return insight;
|
|
10075
|
+
}
|
|
10076
|
+
}
|
|
10077
|
+
}
|
|
10078
|
+
return null;
|
|
10079
|
+
}
|
|
10080
|
+
/**
|
|
10081
|
+
* Group nudges by similarity (same goal, same category, similar files)
|
|
10082
|
+
*/
|
|
10083
|
+
groupNudges(nudges) {
|
|
10084
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10085
|
+
for (const nudge of nudges) {
|
|
10086
|
+
const goalMatch = nudge.message.match(/Goal "([^"]+)" violated/);
|
|
10087
|
+
const goalPattern = goalMatch?.[1];
|
|
10088
|
+
const key = goalPattern ? `goal:${goalPattern}` : `category:${nudge.category || "general"}`;
|
|
10089
|
+
if (!groups.has(key)) {
|
|
10090
|
+
groups.set(key, {
|
|
10091
|
+
key,
|
|
10092
|
+
nudges: [],
|
|
10093
|
+
category: nudge.category || "quality",
|
|
10094
|
+
goalPattern,
|
|
10095
|
+
files: []
|
|
10096
|
+
});
|
|
10097
|
+
}
|
|
10098
|
+
const batch = groups.get(key);
|
|
10099
|
+
batch.nudges.push(nudge);
|
|
10100
|
+
if (nudge.file && !batch.files.includes(nudge.file)) {
|
|
10101
|
+
batch.files.push(nudge.file);
|
|
10102
|
+
}
|
|
10103
|
+
}
|
|
10104
|
+
return Array.from(groups.values());
|
|
10105
|
+
}
|
|
10106
|
+
/**
|
|
10107
|
+
* Use AI to summarize a batch of nudges into an insight
|
|
10108
|
+
*/
|
|
10109
|
+
async summarizeBatch(batch) {
|
|
10110
|
+
if (!this.client) {
|
|
10111
|
+
return this.createFallbackInsight(batch);
|
|
10112
|
+
}
|
|
10113
|
+
try {
|
|
10114
|
+
const nudgeDescriptions = batch.nudges.slice(0, 10).map((n) => `- ${n.message}${n.file ? ` (${n.file})` : ""}`).join("\n");
|
|
10115
|
+
const response = await this.client.messages.create({
|
|
10116
|
+
model: "claude-3-haiku-20240307",
|
|
10117
|
+
max_tokens: 512,
|
|
10118
|
+
temperature: 0.3,
|
|
10119
|
+
messages: [{
|
|
10120
|
+
role: "user",
|
|
10121
|
+
content: `${SUMMARIZE_PROMPT}
|
|
10122
|
+
|
|
10123
|
+
Batch of ${batch.nudges.length} similar issues:
|
|
10124
|
+
${nudgeDescriptions}
|
|
10125
|
+
|
|
10126
|
+
Files affected: ${batch.files.slice(0, 5).join(", ")}${batch.files.length > 5 ? ` (+${batch.files.length - 5} more)` : ""}`
|
|
10127
|
+
}]
|
|
10128
|
+
});
|
|
10129
|
+
const text = response.content[0]?.type === "text" ? response.content[0].text : "";
|
|
10130
|
+
const parsed = this.parseResponse(text);
|
|
10131
|
+
if (!parsed) {
|
|
10132
|
+
return this.createFallbackInsight(batch);
|
|
10133
|
+
}
|
|
10134
|
+
const insight = {
|
|
10135
|
+
id: `signal-${createHash2("sha256").update(batch.key + Date.now()).digest("hex").slice(0, 12)}`,
|
|
10136
|
+
type: "observation",
|
|
10137
|
+
message: parsed.learning,
|
|
10138
|
+
context: parsed.evidence,
|
|
10139
|
+
suggestedAction: parsed.suggestedAction,
|
|
10140
|
+
relatedIssues: batch.nudges.map((n) => n.id),
|
|
10141
|
+
priority: parsed.confidence,
|
|
10142
|
+
timestamp: Date.now(),
|
|
10143
|
+
dismissed: false,
|
|
10144
|
+
category: parsed.category,
|
|
10145
|
+
details: {
|
|
10146
|
+
affectedFiles: batch.files,
|
|
10147
|
+
issueBreakdown: { [batch.category]: batch.nudges.length },
|
|
10148
|
+
summary: parsed.learning
|
|
10149
|
+
}
|
|
10150
|
+
};
|
|
10151
|
+
const insightStore = getInsightStore(this.projectPath);
|
|
10152
|
+
await insightStore.load();
|
|
10153
|
+
await insightStore.addInsight(insight);
|
|
10154
|
+
const storage = getStorage(this.projectPath);
|
|
10155
|
+
for (const nudge of batch.nudges) {
|
|
10156
|
+
await storage.resolveNudge(nudge.id, "auto-fixed");
|
|
10157
|
+
}
|
|
10158
|
+
return insight;
|
|
10159
|
+
} catch (error) {
|
|
10160
|
+
console.error("[SignalSummarizer] AI summarization failed:", error);
|
|
10161
|
+
return this.createFallbackInsight(batch);
|
|
10162
|
+
}
|
|
10163
|
+
}
|
|
10164
|
+
/**
|
|
10165
|
+
* Parse AI response
|
|
10166
|
+
*/
|
|
10167
|
+
parseResponse(text) {
|
|
10168
|
+
try {
|
|
10169
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
10170
|
+
if (!jsonMatch) return null;
|
|
10171
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
10172
|
+
return {
|
|
10173
|
+
learning: parsed.learning || "Pattern detected",
|
|
10174
|
+
evidence: parsed.evidence,
|
|
10175
|
+
suggestedAction: parsed.suggestedAction || "Review affected files",
|
|
10176
|
+
category: parsed.category || "quality",
|
|
10177
|
+
confidence: Math.min(10, Math.max(1, parsed.confidence || 5))
|
|
10178
|
+
};
|
|
10179
|
+
} catch {
|
|
10180
|
+
return null;
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
/**
|
|
10184
|
+
* Create a fallback insight without AI
|
|
10185
|
+
*/
|
|
10186
|
+
createFallbackInsight(batch) {
|
|
10187
|
+
let message;
|
|
10188
|
+
let suggestedAction;
|
|
10189
|
+
if (batch.goalPattern) {
|
|
10190
|
+
const pattern = batch.goalPattern.toLowerCase();
|
|
10191
|
+
if (pattern.includes("type") || pattern.includes("safety")) {
|
|
10192
|
+
message = `Type safety tends to be weak in this codebase`;
|
|
10193
|
+
} else if (pattern.includes("error") || pattern.includes("handling")) {
|
|
10194
|
+
message = `Error handling is often incomplete`;
|
|
10195
|
+
} else if (pattern.includes("test")) {
|
|
10196
|
+
message = `Test coverage appears insufficient`;
|
|
10197
|
+
} else if (pattern.includes("security") || pattern.includes("auth")) {
|
|
10198
|
+
message = `Security practices need attention`;
|
|
10199
|
+
} else {
|
|
10200
|
+
message = `"${batch.goalPattern}" compliance tends to be inconsistent`;
|
|
10201
|
+
}
|
|
10202
|
+
suggestedAction = `Establish stricter conventions for ${pattern}`;
|
|
10203
|
+
} else {
|
|
10204
|
+
if (batch.category === "security") {
|
|
10205
|
+
message = `Security practices need strengthening`;
|
|
10206
|
+
} else if (batch.category === "performance") {
|
|
10207
|
+
message = `Performance optimizations are often overlooked`;
|
|
10208
|
+
} else {
|
|
10209
|
+
message = `Code quality patterns are inconsistent`;
|
|
10210
|
+
}
|
|
10211
|
+
suggestedAction = `Review ${batch.category} conventions across the codebase`;
|
|
10212
|
+
}
|
|
10213
|
+
return {
|
|
10214
|
+
id: `signal-${createHash2("sha256").update(batch.key + Date.now()).digest("hex").slice(0, 12)}`,
|
|
10215
|
+
type: "observation",
|
|
10216
|
+
message,
|
|
10217
|
+
suggestedAction,
|
|
10218
|
+
relatedIssues: batch.nudges.map((n) => n.id),
|
|
10219
|
+
priority: 5,
|
|
10220
|
+
timestamp: Date.now(),
|
|
10221
|
+
dismissed: false,
|
|
10222
|
+
category: batch.category || "quality",
|
|
10223
|
+
details: {
|
|
10224
|
+
affectedFiles: batch.files,
|
|
10225
|
+
issueBreakdown: { [batch.category]: batch.nudges.length }
|
|
10226
|
+
}
|
|
10227
|
+
};
|
|
10228
|
+
}
|
|
10229
|
+
/**
|
|
10230
|
+
* Force summarization of all current nudge batches
|
|
10231
|
+
*/
|
|
10232
|
+
async summarizeAll() {
|
|
10233
|
+
const storage = getStorage(this.projectPath);
|
|
10234
|
+
await storage.initialize();
|
|
10235
|
+
const nudges = await storage.queryNudges({ resolved: false, limit: 100 });
|
|
10236
|
+
const batches = this.groupNudges(nudges);
|
|
10237
|
+
const insights = [];
|
|
10238
|
+
for (const batch of batches) {
|
|
10239
|
+
if (batch.nudges.length >= SIGNAL_THRESHOLD) {
|
|
10240
|
+
const insight = await this.summarizeBatch(batch);
|
|
10241
|
+
if (insight) {
|
|
10242
|
+
insights.push(insight);
|
|
10243
|
+
}
|
|
10244
|
+
}
|
|
10245
|
+
}
|
|
10246
|
+
return insights;
|
|
10247
|
+
}
|
|
10248
|
+
};
|
|
10249
|
+
var summarizers = /* @__PURE__ */ new Map();
|
|
10250
|
+
function getSignalSummarizer(projectPath) {
|
|
10251
|
+
let summarizer = summarizers.get(projectPath);
|
|
10252
|
+
if (!summarizer) {
|
|
10253
|
+
summarizer = new SignalSummarizer(projectPath);
|
|
10254
|
+
summarizers.set(projectPath, summarizer);
|
|
10255
|
+
}
|
|
10256
|
+
return summarizer;
|
|
10257
|
+
}
|
|
10258
|
+
|
|
10259
|
+
// src/tools/watch.ts
|
|
9987
10260
|
var WATCH_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
9988
10261
|
".ts",
|
|
9989
10262
|
".tsx",
|
|
@@ -11353,7 +11626,7 @@ ${recentNudges || "(none)"}
|
|
|
11353
11626
|
*/
|
|
11354
11627
|
async persistNudge(params) {
|
|
11355
11628
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
11356
|
-
const nudgeId =
|
|
11629
|
+
const nudgeId = createHash3("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
|
|
11357
11630
|
const nudge = {
|
|
11358
11631
|
id: nudgeId,
|
|
11359
11632
|
message: params.message,
|
|
@@ -11380,10 +11653,46 @@ ${recentNudges || "(none)"}
|
|
|
11380
11653
|
const storage = getStorage(this.watchedDirectory);
|
|
11381
11654
|
await storage.storeNudge(nudge);
|
|
11382
11655
|
console.debug(`[Watch] \u2713 Persisted nudge to storage: ${nudge.message.slice(0, 60)}...`);
|
|
11656
|
+
void this.checkSignalThreshold();
|
|
11383
11657
|
} catch (error) {
|
|
11384
11658
|
console.error("[Watch] Failed to persist nudge to storage:", error);
|
|
11385
11659
|
}
|
|
11386
11660
|
}
|
|
11661
|
+
/**
|
|
11662
|
+
* Check if we have enough nudges (5+) to generate an AI-summarized signal.
|
|
11663
|
+
* Runs periodically after nudge persistence to batch similar issues into insights.
|
|
11664
|
+
*/
|
|
11665
|
+
async checkSignalThreshold() {
|
|
11666
|
+
try {
|
|
11667
|
+
const summarizer = getSignalSummarizer(this.watchedDirectory);
|
|
11668
|
+
const insight = await summarizer.checkAndSummarize();
|
|
11669
|
+
if (insight) {
|
|
11670
|
+
getOutputManager().nudge(
|
|
11671
|
+
`Trie learned: ${insight.message}`,
|
|
11672
|
+
"info",
|
|
11673
|
+
void 0,
|
|
11674
|
+
15e3
|
|
11675
|
+
);
|
|
11676
|
+
if (!isInteractiveMode()) {
|
|
11677
|
+
console.error(` [+] Learning: ${insight.message}`);
|
|
11678
|
+
if (insight.suggestedAction) {
|
|
11679
|
+
console.error(` Suggestion: ${insight.suggestedAction}`);
|
|
11680
|
+
}
|
|
11681
|
+
}
|
|
11682
|
+
if (this.streamingManager) {
|
|
11683
|
+
this.streamingManager.reportSignalExtraction({
|
|
11684
|
+
governance: 1,
|
|
11685
|
+
// Insights are a form of governance
|
|
11686
|
+
facts: 0,
|
|
11687
|
+
blockers: 0,
|
|
11688
|
+
questions: 0
|
|
11689
|
+
});
|
|
11690
|
+
}
|
|
11691
|
+
}
|
|
11692
|
+
} catch (error) {
|
|
11693
|
+
console.debug("[Watch] Signal threshold check failed:", error);
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11387
11696
|
getNudges() {
|
|
11388
11697
|
return {
|
|
11389
11698
|
content: [
|
|
@@ -11441,4 +11750,4 @@ export {
|
|
|
11441
11750
|
InteractiveDashboard,
|
|
11442
11751
|
TrieWatchTool
|
|
11443
11752
|
};
|
|
11444
|
-
//# sourceMappingURL=chunk-
|
|
11753
|
+
//# sourceMappingURL=chunk-D6E4Q4I6.js.map
|