@triedotdev/mcp 1.0.105 → 1.0.107
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-HBPTBNFJ.js → chunk-3YDNSKKP.js} +723 -444
- package/dist/chunk-3YDNSKKP.js.map +1 -0
- package/dist/{chunk-HFKOGW7H.js → chunk-C5NK7EGK.js} +2 -2
- package/dist/{chunk-CKYU5JOD.js → chunk-JT2OOIQX.js} +2 -2
- package/dist/{chunk-SPQJC7RA.js → chunk-S2WVHIFG.js} +69 -5
- package/dist/chunk-S2WVHIFG.js.map +1 -0
- package/dist/cli/main.js +2 -2
- package/dist/cli/yolo-daemon.js +3 -3
- package/dist/{guardian-agent-WB6LWRLM.js → guardian-agent-DX4ZQEZ7.js} +3 -3
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-HBPTBNFJ.js.map +0 -1
- package/dist/chunk-SPQJC7RA.js.map +0 -1
- /package/dist/{chunk-HFKOGW7H.js.map → chunk-C5NK7EGK.js.map} +0 -0
- /package/dist/{chunk-CKYU5JOD.js.map → chunk-JT2OOIQX.js.map} +0 -0
- /package/dist/{guardian-agent-WB6LWRLM.js.map → guardian-agent-DX4ZQEZ7.js.map} +0 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getGuardian
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-C5NK7EGK.js";
|
|
4
4
|
import {
|
|
5
|
+
ContextGraph,
|
|
6
|
+
TieredStorage,
|
|
5
7
|
findCrossProjectPatterns,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
getKeyFromKeychain,
|
|
9
|
+
isAIAvailable,
|
|
10
|
+
runAIAnalysis,
|
|
11
|
+
setAPIKey
|
|
12
|
+
} from "./chunk-S2WVHIFG.js";
|
|
8
13
|
import {
|
|
9
|
-
getGuardianState
|
|
10
|
-
getMemoryStats,
|
|
11
|
-
getRecentIssues
|
|
14
|
+
getGuardianState
|
|
12
15
|
} from "./chunk-6JPPYG7F.js";
|
|
13
16
|
import {
|
|
14
17
|
getTrieDirectory,
|
|
@@ -254,11 +257,11 @@ var StreamingManager = class {
|
|
|
254
257
|
|
|
255
258
|
// src/cli/dashboard/index.ts
|
|
256
259
|
import { render } from "ink";
|
|
257
|
-
import
|
|
260
|
+
import React10 from "react";
|
|
258
261
|
|
|
259
262
|
// src/cli/dashboard/App.tsx
|
|
260
|
-
import { useState as
|
|
261
|
-
import { Box as
|
|
263
|
+
import { useState as useState3, useEffect as useEffect4, useCallback as useCallback6, useRef } from "react";
|
|
264
|
+
import { Box as Box12, useInput as useInput8, useApp } from "ink";
|
|
262
265
|
|
|
263
266
|
// src/cli/dashboard/state.tsx
|
|
264
267
|
import React, { createContext, useContext, useReducer } from "react";
|
|
@@ -273,38 +276,36 @@ function getVisibleInsights(state) {
|
|
|
273
276
|
}
|
|
274
277
|
function getMemoryTreeNodes(state) {
|
|
275
278
|
const nodes = [];
|
|
276
|
-
const { expandedNodes,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
nodes.push({ id: "severity-serious", level: 1 });
|
|
286
|
-
nodes.push({ id: "severity-moderate", level: 1 });
|
|
287
|
-
nodes.push({ id: "severity-low", level: 1 });
|
|
288
|
-
}
|
|
279
|
+
const { expandedNodes, snapshot, globalPatterns } = state.memoryTree;
|
|
280
|
+
if (!snapshot) return nodes;
|
|
281
|
+
const fileNodes = snapshot.nodes.filter((n) => n.type === "file");
|
|
282
|
+
const changeNodes = snapshot.nodes.filter((n) => n.type === "change");
|
|
283
|
+
const patternNodes = snapshot.nodes.filter((n) => n.type === "pattern");
|
|
284
|
+
const incidentNodes = snapshot.nodes.filter((n) => n.type === "incident");
|
|
285
|
+
const decisionNodes = snapshot.nodes.filter((n) => n.type === "decision");
|
|
289
286
|
nodes.push({ id: "files", level: 0 });
|
|
290
287
|
if (expandedNodes.has("files")) {
|
|
291
|
-
|
|
292
|
-
for (const issue of issues) {
|
|
293
|
-
byFile.set(issue.file, (byFile.get(issue.file) || 0) + 1);
|
|
294
|
-
}
|
|
295
|
-
Array.from(byFile.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([file]) => nodes.push({ id: `file-${file}`, level: 1 }));
|
|
288
|
+
fileNodes.slice(0, 15).forEach((n) => nodes.push({ id: `file-${n.id}`, level: 1 }));
|
|
296
289
|
}
|
|
297
|
-
nodes.push({ id: "
|
|
298
|
-
if (expandedNodes.has("
|
|
299
|
-
|
|
300
|
-
for (const issue of issues) {
|
|
301
|
-
byAgent.set(issue.agent, (byAgent.get(issue.agent) || 0) + 1);
|
|
302
|
-
}
|
|
303
|
-
Array.from(byAgent.entries()).sort((a, b) => b[1] - a[1]).forEach(([agent]) => nodes.push({ id: `agent-${agent}`, level: 1 }));
|
|
290
|
+
nodes.push({ id: "changes", level: 0 });
|
|
291
|
+
if (expandedNodes.has("changes")) {
|
|
292
|
+
changeNodes.slice(0, 10).forEach((n) => nodes.push({ id: `change-${n.id}`, level: 1 }));
|
|
304
293
|
}
|
|
305
294
|
nodes.push({ id: "patterns", level: 0 });
|
|
306
295
|
if (expandedNodes.has("patterns")) {
|
|
307
|
-
|
|
296
|
+
patternNodes.slice(0, 10).forEach((n) => nodes.push({ id: `pattern-${n.id}`, level: 1 }));
|
|
297
|
+
}
|
|
298
|
+
nodes.push({ id: "incidents", level: 0 });
|
|
299
|
+
if (expandedNodes.has("incidents")) {
|
|
300
|
+
incidentNodes.slice(0, 10).forEach((n) => nodes.push({ id: `incident-${n.id}`, level: 1 }));
|
|
301
|
+
}
|
|
302
|
+
nodes.push({ id: "decisions", level: 0 });
|
|
303
|
+
if (expandedNodes.has("decisions")) {
|
|
304
|
+
decisionNodes.slice(0, 10).forEach((n) => nodes.push({ id: `decision-${n.id}`, level: 1 }));
|
|
305
|
+
}
|
|
306
|
+
nodes.push({ id: "cross-project", level: 0 });
|
|
307
|
+
if (expandedNodes.has("cross-project")) {
|
|
308
|
+
globalPatterns.slice(0, 5).forEach((p) => nodes.push({ id: `global-${p.id}`, level: 1 }));
|
|
308
309
|
}
|
|
309
310
|
return nodes;
|
|
310
311
|
}
|
|
@@ -551,18 +552,41 @@ function dashboardReducer(state, action) {
|
|
|
551
552
|
case "SET_MEMORY_TREE":
|
|
552
553
|
return {
|
|
553
554
|
...state,
|
|
554
|
-
memoryTree: { ...state.memoryTree, loaded: true,
|
|
555
|
+
memoryTree: { ...state.memoryTree, loaded: true, snapshot: action.snapshot, globalPatterns: action.patterns }
|
|
555
556
|
};
|
|
556
557
|
case "SELECT_MEMORY_NODE":
|
|
557
558
|
return { ...state, memoryTree: { ...state.memoryTree, selectedNode: action.nodeId } };
|
|
558
559
|
case "TOGGLE_MEMORY_NODE": {
|
|
559
|
-
const expandable = ["
|
|
560
|
+
const expandable = ["files", "changes", "patterns", "incidents", "decisions", "cross-project"];
|
|
560
561
|
if (!expandable.includes(action.nodeId)) return state;
|
|
561
562
|
const expanded = new Set(state.memoryTree.expandedNodes);
|
|
562
563
|
if (expanded.has(action.nodeId)) expanded.delete(action.nodeId);
|
|
563
564
|
else expanded.add(action.nodeId);
|
|
564
565
|
return { ...state, memoryTree: { ...state.memoryTree, expandedNodes: expanded } };
|
|
565
566
|
}
|
|
567
|
+
case "SET_AGENT_BRAIN":
|
|
568
|
+
return {
|
|
569
|
+
...state,
|
|
570
|
+
agentBrain: {
|
|
571
|
+
...state.agentBrain,
|
|
572
|
+
loaded: true,
|
|
573
|
+
decisions: action.decisions,
|
|
574
|
+
patterns: action.patterns,
|
|
575
|
+
ledgerHash: action.ledgerHash
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
case "SET_CHAT_INPUT":
|
|
579
|
+
return { ...state, chatState: { ...state.chatState, inputBuffer: action.buffer } };
|
|
580
|
+
case "ADD_CHAT_MESSAGE":
|
|
581
|
+
return {
|
|
582
|
+
...state,
|
|
583
|
+
chatState: {
|
|
584
|
+
...state.chatState,
|
|
585
|
+
messages: [...state.chatState.messages, { role: action.role, content: action.content, timestamp: Date.now() }].slice(-20)
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
case "SET_CHAT_LOADING":
|
|
589
|
+
return { ...state, chatState: { ...state.chatState, loading: action.loading } };
|
|
566
590
|
case "SET_AGENT_CONFIG":
|
|
567
591
|
return { ...state, agentConfig: applyAgentConfigPatch(state.agentConfig, action.config) };
|
|
568
592
|
case "NAVIGATE_UP": {
|
|
@@ -663,7 +687,7 @@ function createInitialState() {
|
|
|
663
687
|
watch: { watching: false, directories: 0, recentChanges: [] },
|
|
664
688
|
rawLog: [],
|
|
665
689
|
rawLogPage: 0,
|
|
666
|
-
scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0 },
|
|
690
|
+
scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0, chat: 0 },
|
|
667
691
|
notification: null,
|
|
668
692
|
notificationHistory: [],
|
|
669
693
|
agentInsights: [],
|
|
@@ -683,7 +707,9 @@ function createInitialState() {
|
|
|
683
707
|
},
|
|
684
708
|
goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
|
|
685
709
|
hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
|
|
686
|
-
memoryTree: { loaded: false,
|
|
710
|
+
memoryTree: { loaded: false, snapshot: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["files"]), selectedNode: "files", scrollPosition: 0, lastRefresh: 0 },
|
|
711
|
+
agentBrain: { loaded: false, decisions: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
|
|
712
|
+
chatState: { messages: [], inputBuffer: "", loading: false }
|
|
687
713
|
};
|
|
688
714
|
}
|
|
689
715
|
var DashboardContext = createContext(null);
|
|
@@ -1254,16 +1280,25 @@ import { readFile, writeFile, mkdir } from "fs/promises";
|
|
|
1254
1280
|
import { join } from "path";
|
|
1255
1281
|
|
|
1256
1282
|
// src/cli/dashboard/components/Header.tsx
|
|
1283
|
+
import { useState, useEffect } from "react";
|
|
1257
1284
|
import { Box, Text } from "ink";
|
|
1258
1285
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1286
|
+
var WATCH_FRAMES = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
1259
1287
|
function Header() {
|
|
1260
1288
|
const { state } = useDashboard();
|
|
1261
1289
|
const { signalExtraction, watch, alerts } = state;
|
|
1262
1290
|
const totalExtracted = signalExtraction.decisionsExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
|
|
1291
|
+
const [frame, setFrame] = useState(0);
|
|
1292
|
+
useEffect(() => {
|
|
1293
|
+
if (!watch.watching) return;
|
|
1294
|
+
const id = setInterval(() => setFrame((f) => (f + 1) % WATCH_FRAMES.length), 150);
|
|
1295
|
+
return () => clearInterval(id);
|
|
1296
|
+
}, [watch.watching]);
|
|
1263
1297
|
let statusLabel;
|
|
1264
1298
|
if (watch.watching) {
|
|
1299
|
+
const spinner = WATCH_FRAMES[frame] || "\u25D0";
|
|
1265
1300
|
statusLabel = totalExtracted > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1266
|
-
/* @__PURE__ */ jsx2(Text, { color: "green", children:
|
|
1301
|
+
/* @__PURE__ */ jsx2(Text, { color: "green", children: spinner }),
|
|
1267
1302
|
" ",
|
|
1268
1303
|
/* @__PURE__ */ jsx2(Text, { color: "green", bold: true, children: "Learning" }),
|
|
1269
1304
|
" ",
|
|
@@ -1272,7 +1307,7 @@ function Header() {
|
|
|
1272
1307
|
" signals"
|
|
1273
1308
|
] })
|
|
1274
1309
|
] }) : /* @__PURE__ */ jsxs(Text, { children: [
|
|
1275
|
-
/* @__PURE__ */ jsx2(Text, { color: "green", children:
|
|
1310
|
+
/* @__PURE__ */ jsx2(Text, { color: "green", children: spinner }),
|
|
1276
1311
|
" ",
|
|
1277
1312
|
/* @__PURE__ */ jsx2(Text, { bold: true, children: "Watching" })
|
|
1278
1313
|
] });
|
|
@@ -1301,12 +1336,13 @@ var VIEW_LABELS = {
|
|
|
1301
1336
|
agent: "Agent",
|
|
1302
1337
|
goals: "Goals",
|
|
1303
1338
|
hypotheses: "Hypotheses",
|
|
1304
|
-
memory: "Memory"
|
|
1339
|
+
memory: "Memory",
|
|
1340
|
+
chat: "Chat"
|
|
1305
1341
|
};
|
|
1342
|
+
var TAB_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
|
|
1306
1343
|
function Footer() {
|
|
1307
1344
|
const { state } = useDashboard();
|
|
1308
1345
|
const { view } = state;
|
|
1309
|
-
const label = VIEW_LABELS[view];
|
|
1310
1346
|
let contextHints;
|
|
1311
1347
|
if (view === "goals" && state.goalsPanel.inputMode === "add") {
|
|
1312
1348
|
contextHints = "enter save \xB7 esc cancel";
|
|
@@ -1319,20 +1355,17 @@ function Footer() {
|
|
|
1319
1355
|
} else if (view === "agent") {
|
|
1320
1356
|
contextHints = "j/k nav \xB7 enter expand \xB7 d dismiss";
|
|
1321
1357
|
} else if (view === "memory") {
|
|
1322
|
-
contextHints = "j/k nav \xB7 enter expand
|
|
1358
|
+
contextHints = "j/k nav \xB7 enter expand";
|
|
1359
|
+
} else if (view === "chat") {
|
|
1360
|
+
contextHints = "type to ask \xB7 enter send \xB7 esc clear";
|
|
1323
1361
|
} else if (view === "rawlog") {
|
|
1324
1362
|
contextHints = "n/p pages \xB7 b back";
|
|
1325
1363
|
} else {
|
|
1326
|
-
contextHints = "n/p pages \xB7
|
|
1364
|
+
contextHints = "n/p pages \xB7 c config";
|
|
1327
1365
|
}
|
|
1328
1366
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
1329
1367
|
/* @__PURE__ */ jsxs2(Box2, { justifyContent: "space-between", children: [
|
|
1330
|
-
/* @__PURE__ */
|
|
1331
|
-
/* @__PURE__ */ jsx3(Text2, { color: "green", children: "\u25CF" }),
|
|
1332
|
-
" ",
|
|
1333
|
-
/* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: label }),
|
|
1334
|
-
/* @__PURE__ */ jsx3(Text2, { dimColor: true, children: " (tab to cycle)" })
|
|
1335
|
-
] }),
|
|
1368
|
+
/* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => v === view ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: VIEW_LABELS[v] }, v) : /* @__PURE__ */ jsx3(Text2, { children: VIEW_LABELS[v] }, v)) }),
|
|
1336
1369
|
/* @__PURE__ */ jsx3(Text2, { dimColor: true, children: "q quit" })
|
|
1337
1370
|
] }),
|
|
1338
1371
|
/* @__PURE__ */ jsx3(Text2, { dimColor: true, children: contextHints })
|
|
@@ -1360,21 +1393,31 @@ function Notification() {
|
|
|
1360
1393
|
}
|
|
1361
1394
|
|
|
1362
1395
|
// src/cli/dashboard/components/ConfigDialog.tsx
|
|
1363
|
-
import { useState } from "react";
|
|
1396
|
+
import { useState as useState2 } from "react";
|
|
1364
1397
|
import { Box as Box4, Text as Text4, useInput } from "ink";
|
|
1365
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1398
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1399
|
+
function maskKey(key) {
|
|
1400
|
+
if (!key || key.length < 12) return "Not set";
|
|
1401
|
+
return key.slice(0, 7) + "..." + key.slice(-4);
|
|
1402
|
+
}
|
|
1366
1403
|
function ConfigDialog({ onClose }) {
|
|
1367
1404
|
const { state, dispatch } = useDashboard();
|
|
1368
|
-
const [section, setSection] =
|
|
1369
|
-
const [selectedIndex, setSelectedIndex] =
|
|
1370
|
-
const [editing, setEditing] =
|
|
1371
|
-
const [editBuffer, setEditBuffer] =
|
|
1405
|
+
const [section, setSection] = useState2("main");
|
|
1406
|
+
const [selectedIndex, setSelectedIndex] = useState2(0);
|
|
1407
|
+
const [editing, setEditing] = useState2(false);
|
|
1408
|
+
const [editBuffer, setEditBuffer] = useState2("");
|
|
1409
|
+
const [editIsText, setEditIsText] = useState2(false);
|
|
1372
1410
|
const config = state.agentConfig;
|
|
1411
|
+
const currentKeyDisplay = isAIAvailable() ? maskKey(getKeyFromKeychain() || process.env.ANTHROPIC_API_KEY || null) : "Not set";
|
|
1412
|
+
const keyActive = isAIAvailable();
|
|
1373
1413
|
const mainMenu = [
|
|
1374
|
-
{ label: "
|
|
1414
|
+
{ label: "API Keys", key: "apiKeys", value: keyActive ? "Active" : "Not set", section: "main" },
|
|
1375
1415
|
{ label: "Performance Settings", key: "performance", value: `${config.performance.maxConcurrency} concurrent`, section: "main" },
|
|
1376
1416
|
{ label: "Risk Thresholds", key: "riskThresholds", value: `critical: ${config.riskThresholds.critical}%`, section: "main" }
|
|
1377
1417
|
];
|
|
1418
|
+
const apiKeysItems = [
|
|
1419
|
+
{ label: "Anthropic", key: "anthropic", value: currentKeyDisplay, section: "apiKeys" }
|
|
1420
|
+
];
|
|
1378
1421
|
const performanceItems = [
|
|
1379
1422
|
{ label: "Max Concurrency", key: "maxConcurrency", value: String(config.performance.maxConcurrency), section: "performance" },
|
|
1380
1423
|
{ label: "Timeout (ms)", key: "timeoutMs", value: String(config.performance.timeoutMs), section: "performance" },
|
|
@@ -1387,37 +1430,50 @@ function ConfigDialog({ onClose }) {
|
|
|
1387
1430
|
{ label: "High Threshold", key: "high", value: String(config.riskThresholds.high), section: "riskThresholds" },
|
|
1388
1431
|
{ label: "Medium Threshold", key: "medium", value: String(config.riskThresholds.medium), section: "riskThresholds" }
|
|
1389
1432
|
];
|
|
1390
|
-
const items = section === "main" ? mainMenu : section === "performance" ? performanceItems : section === "riskThresholds" ? riskItems : mainMenu;
|
|
1433
|
+
const items = section === "main" ? mainMenu : section === "apiKeys" ? apiKeysItems : section === "performance" ? performanceItems : section === "riskThresholds" ? riskItems : mainMenu;
|
|
1391
1434
|
useInput((_input, key) => {
|
|
1392
1435
|
if (editing) {
|
|
1393
1436
|
if (key.escape) {
|
|
1394
1437
|
setEditing(false);
|
|
1395
1438
|
setEditBuffer("");
|
|
1439
|
+
setEditIsText(false);
|
|
1396
1440
|
} else if (key.return) {
|
|
1397
1441
|
const item = items[selectedIndex];
|
|
1398
1442
|
if (item) {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
if (item.key === "maxConcurrency" || item.key === "timeoutMs") {
|
|
1404
|
-
patch.performance = { ...config.performance, [item.key]: val };
|
|
1405
|
-
}
|
|
1406
|
-
} else if (section === "riskThresholds") {
|
|
1407
|
-
patch.riskThresholds = { ...config.riskThresholds, [item.key]: val };
|
|
1443
|
+
if (editIsText) {
|
|
1444
|
+
if (item.key === "anthropic" && editBuffer.length > 10) {
|
|
1445
|
+
setAPIKey(editBuffer);
|
|
1446
|
+
dispatch({ type: "ADD_ACTIVITY", message: "API key saved" });
|
|
1408
1447
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1448
|
+
} else {
|
|
1449
|
+
const val = parseInt(editBuffer, 10);
|
|
1450
|
+
if (!isNaN(val)) {
|
|
1451
|
+
const patch = {};
|
|
1452
|
+
if (section === "performance") {
|
|
1453
|
+
if (item.key === "maxConcurrency" || item.key === "timeoutMs") {
|
|
1454
|
+
patch.performance = { ...config.performance, [item.key]: val };
|
|
1455
|
+
}
|
|
1456
|
+
} else if (section === "riskThresholds") {
|
|
1457
|
+
patch.riskThresholds = { ...config.riskThresholds, [item.key]: val };
|
|
1458
|
+
}
|
|
1459
|
+
if (Object.keys(patch).length > 0) {
|
|
1460
|
+
dispatch({ type: "SET_AGENT_CONFIG", config: patch });
|
|
1461
|
+
dispatch({ type: "ADD_ACTIVITY", message: `Config: ${item.label} set to ${val}` });
|
|
1462
|
+
}
|
|
1412
1463
|
}
|
|
1413
1464
|
}
|
|
1414
1465
|
}
|
|
1415
1466
|
setEditing(false);
|
|
1416
1467
|
setEditBuffer("");
|
|
1468
|
+
setEditIsText(false);
|
|
1417
1469
|
} else if (key.backspace || key.delete) {
|
|
1418
1470
|
setEditBuffer(editBuffer.slice(0, -1));
|
|
1419
|
-
} else if (_input
|
|
1420
|
-
|
|
1471
|
+
} else if (_input) {
|
|
1472
|
+
if (editIsText) {
|
|
1473
|
+
setEditBuffer(editBuffer + _input);
|
|
1474
|
+
} else if (/\d/.test(_input)) {
|
|
1475
|
+
setEditBuffer(editBuffer + _input);
|
|
1476
|
+
}
|
|
1421
1477
|
}
|
|
1422
1478
|
return;
|
|
1423
1479
|
}
|
|
@@ -1438,6 +1494,10 @@ function ConfigDialog({ onClose }) {
|
|
|
1438
1494
|
setSection(item.key);
|
|
1439
1495
|
setSelectedIndex(0);
|
|
1440
1496
|
}
|
|
1497
|
+
} else if (section === "apiKeys") {
|
|
1498
|
+
setEditing(true);
|
|
1499
|
+
setEditBuffer("");
|
|
1500
|
+
setEditIsText(true);
|
|
1441
1501
|
} else {
|
|
1442
1502
|
const item = items[selectedIndex];
|
|
1443
1503
|
if (item) {
|
|
@@ -1454,11 +1514,34 @@ function ConfigDialog({ onClose }) {
|
|
|
1454
1514
|
}
|
|
1455
1515
|
}
|
|
1456
1516
|
});
|
|
1457
|
-
const sectionTitle = section === "main" ? "TRIE
|
|
1517
|
+
const sectionTitle = section === "main" ? "TRIE CONFIGURATION" : section === "apiKeys" ? "API KEYS" : section === "performance" ? "PERFORMANCE SETTINGS" : section === "riskThresholds" ? "RISK THRESHOLDS" : "CONFIGURATION";
|
|
1458
1518
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, paddingY: 0, children: [
|
|
1459
1519
|
/* @__PURE__ */ jsx5(Text4, { bold: true, children: sectionTitle }),
|
|
1460
1520
|
/* @__PURE__ */ jsx5(Text4, { children: " " }),
|
|
1461
|
-
|
|
1521
|
+
section === "apiKeys" && !editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1522
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1523
|
+
" ",
|
|
1524
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, children: "Anthropic:" }),
|
|
1525
|
+
" ",
|
|
1526
|
+
/* @__PURE__ */ jsx5(Text4, { children: currentKeyDisplay }),
|
|
1527
|
+
" ",
|
|
1528
|
+
keyActive ? /* @__PURE__ */ jsx5(Text4, { color: "green", children: "\u25CF Active" }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "\u25CB Not set" })
|
|
1529
|
+
] }),
|
|
1530
|
+
/* @__PURE__ */ jsx5(Text4, { children: " " }),
|
|
1531
|
+
/* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " enter to update esc back" })
|
|
1532
|
+
] }),
|
|
1533
|
+
section === "apiKeys" && editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1534
|
+
/* @__PURE__ */ jsx5(Box4, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1535
|
+
editBuffer || /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "sk-ant-..." }),
|
|
1536
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "|" })
|
|
1537
|
+
] }) }),
|
|
1538
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
1539
|
+
" enter save (",
|
|
1540
|
+
process.platform === "darwin" ? "keychain" : "config",
|
|
1541
|
+
") esc cancel"
|
|
1542
|
+
] })
|
|
1543
|
+
] }),
|
|
1544
|
+
section !== "apiKeys" && items.map((item, idx) => {
|
|
1462
1545
|
const isSelected = selectedIndex === idx;
|
|
1463
1546
|
return /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1464
1547
|
isSelected ? /* @__PURE__ */ jsxs4(Text4, { bold: true, color: "green", children: [
|
|
@@ -1475,8 +1558,10 @@ function ConfigDialog({ onClose }) {
|
|
|
1475
1558
|
] }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: item.value })
|
|
1476
1559
|
] }, item.key);
|
|
1477
1560
|
}),
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
|
|
1561
|
+
section !== "apiKeys" && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1562
|
+
/* @__PURE__ */ jsx5(Text4, { children: " " }),
|
|
1563
|
+
/* @__PURE__ */ jsx5(Text4, { dimColor: true, children: section === "main" ? "enter select \xB7 esc close" : "enter edit \xB7 esc/b back" })
|
|
1564
|
+
] })
|
|
1480
1565
|
] });
|
|
1481
1566
|
}
|
|
1482
1567
|
|
|
@@ -1563,6 +1648,7 @@ function OverviewView() {
|
|
|
1563
1648
|
}
|
|
1564
1649
|
|
|
1565
1650
|
// src/cli/dashboard/views/AgentView.tsx
|
|
1651
|
+
import { useEffect as useEffect2, useCallback } from "react";
|
|
1566
1652
|
import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
|
|
1567
1653
|
|
|
1568
1654
|
// src/cli/dashboard/theme.ts
|
|
@@ -1593,22 +1679,6 @@ function formatTimeAgo(timestamp) {
|
|
|
1593
1679
|
const hours = Math.floor(minutes / 60);
|
|
1594
1680
|
return `${hours}h ago`;
|
|
1595
1681
|
}
|
|
1596
|
-
function insightIcon(type) {
|
|
1597
|
-
switch (type) {
|
|
1598
|
-
case "warning":
|
|
1599
|
-
return { icon: "\u25CF", color: colors.critical };
|
|
1600
|
-
case "observation":
|
|
1601
|
-
return { icon: "\u25CB", color: colors.serious };
|
|
1602
|
-
case "suggestion":
|
|
1603
|
-
return { icon: "\u25CB", color: colors.highlight };
|
|
1604
|
-
case "celebration":
|
|
1605
|
-
return { icon: "\u25CF", color: colors.success };
|
|
1606
|
-
case "question":
|
|
1607
|
-
return { icon: "\u25CB", color: colors.moderate };
|
|
1608
|
-
default:
|
|
1609
|
-
return { icon: "\u25CB", color: colors.dim };
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
1682
|
function progressBar(current, total, width = 10) {
|
|
1613
1683
|
if (total <= 0) return colors.dim("\u2591".repeat(width));
|
|
1614
1684
|
const progress = Math.min(1, current / total);
|
|
@@ -1616,18 +1686,43 @@ function progressBar(current, total, width = 10) {
|
|
|
1616
1686
|
const empty = width - filled;
|
|
1617
1687
|
return colors.success("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
|
|
1618
1688
|
}
|
|
1619
|
-
function stripEmojis(s) {
|
|
1620
|
-
return s.replace(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}\u{FE0F}\u{E0020}-\u{E007F}]/gu, "").trim();
|
|
1621
|
-
}
|
|
1622
1689
|
|
|
1623
1690
|
// src/cli/dashboard/views/AgentView.tsx
|
|
1624
1691
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1692
|
+
function timeAgo(iso) {
|
|
1693
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
1694
|
+
const mins = Math.floor(ms / 6e4);
|
|
1695
|
+
if (mins < 60) return `${mins}m ago`;
|
|
1696
|
+
const hrs = Math.floor(mins / 60);
|
|
1697
|
+
if (hrs < 24) return `${hrs}h ago`;
|
|
1698
|
+
return `${Math.floor(hrs / 24)}d ago`;
|
|
1699
|
+
}
|
|
1625
1700
|
function AgentView() {
|
|
1626
1701
|
const { state, dispatch } = useDashboard();
|
|
1627
|
-
const { agentInsights,
|
|
1628
|
-
const totalInsights = agentInsights.length;
|
|
1702
|
+
const { agentInsights, agentBrain, selectedInsight, expandedInsight } = state;
|
|
1629
1703
|
const visibleInsights = getVisibleInsights(state);
|
|
1630
|
-
const
|
|
1704
|
+
const alerts = visibleInsights.filter((i) => i.type === "warning");
|
|
1705
|
+
const { decisions, patterns, loaded } = agentBrain;
|
|
1706
|
+
const loadBrain = useCallback(async () => {
|
|
1707
|
+
try {
|
|
1708
|
+
const workDir = getWorkingDirectory(void 0, true);
|
|
1709
|
+
const storage = new TieredStorage(workDir);
|
|
1710
|
+
const graph = new ContextGraph(workDir);
|
|
1711
|
+
const [decs, snap] = await Promise.all([
|
|
1712
|
+
storage.queryDecisions({ limit: 20 }),
|
|
1713
|
+
graph.getSnapshot()
|
|
1714
|
+
]);
|
|
1715
|
+
const patternData = snap.nodes.filter((n) => n.type === "pattern").map((n) => n.data);
|
|
1716
|
+
dispatch({ type: "SET_AGENT_BRAIN", decisions: decs, patterns: patternData, ledgerHash: null });
|
|
1717
|
+
} catch {
|
|
1718
|
+
dispatch({ type: "ADD_ACTIVITY", message: "Agent brain load error" });
|
|
1719
|
+
}
|
|
1720
|
+
}, [dispatch]);
|
|
1721
|
+
useEffect2(() => {
|
|
1722
|
+
if (!loaded) {
|
|
1723
|
+
void loadBrain();
|
|
1724
|
+
}
|
|
1725
|
+
}, [loaded, loadBrain]);
|
|
1631
1726
|
useInput2((input, key) => {
|
|
1632
1727
|
if (key.upArrow || input === "k") {
|
|
1633
1728
|
dispatch({ type: "NAVIGATE_UP" });
|
|
@@ -1637,148 +1732,176 @@ function AgentView() {
|
|
|
1637
1732
|
dispatch({ type: "TOGGLE_INSIGHT", index: selectedInsight });
|
|
1638
1733
|
} else if (input === "d") {
|
|
1639
1734
|
dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
|
|
1640
|
-
} else if (input === "i") {
|
|
1641
|
-
dispatch({ type: "IGNORE_INSIGHT", index: selectedInsight });
|
|
1642
|
-
} else if (input === "x") {
|
|
1643
|
-
dispatch({ type: "CLEAR_DISMISSED_INSIGHTS" });
|
|
1644
1735
|
}
|
|
1645
1736
|
});
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1737
|
+
const alertCount = alerts.length;
|
|
1738
|
+
const decCount = decisions.length;
|
|
1739
|
+
const patCount = patterns.length;
|
|
1740
|
+
if (alertCount === 0 && decCount === 0 && patCount === 0 && !loaded) {
|
|
1741
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
1742
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
|
|
1743
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Loading..." })
|
|
1744
|
+
] });
|
|
1745
|
+
}
|
|
1746
|
+
if (alertCount === 0 && decCount === 0 && patCount === 0) {
|
|
1747
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
1748
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
|
|
1749
|
+
" ",
|
|
1750
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Proactive code guardian" }),
|
|
1751
|
+
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1752
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1651
1753
|
" ",
|
|
1652
|
-
|
|
1653
|
-
"
|
|
1654
|
-
] })
|
|
1754
|
+
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1755
|
+
" Alerts you about gotchas before you push"
|
|
1756
|
+
] }),
|
|
1757
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1655
1758
|
" ",
|
|
1656
|
-
|
|
1657
|
-
"
|
|
1658
|
-
] })
|
|
1659
|
-
] }),
|
|
1660
|
-
agency && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1661
|
-
"Goals ",
|
|
1662
|
-
agency.goals.active,
|
|
1663
|
-
"/",
|
|
1664
|
-
agency.goals.completed + agency.goals.active,
|
|
1665
|
-
" \xB7 ",
|
|
1666
|
-
"Hypo ",
|
|
1667
|
-
agency.hypotheses.testing,
|
|
1668
|
-
" testing",
|
|
1669
|
-
" \xB7 ",
|
|
1670
|
-
"Risk ",
|
|
1671
|
-
agency.riskLevel,
|
|
1672
|
-
" \xB7 ",
|
|
1673
|
-
agency.effectiveness,
|
|
1674
|
-
"% effective",
|
|
1675
|
-
agency.isQuietHours ? " \xB7 quiet" : ""
|
|
1676
|
-
] }),
|
|
1677
|
-
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1678
|
-
visibleInsights.length === 0 && state.notificationHistory.length === 0 ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1759
|
+
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1760
|
+
" Records decisions with traceable hashes"
|
|
1761
|
+
] }),
|
|
1679
1762
|
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1763
|
+
" ",
|
|
1764
|
+
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1765
|
+
" Learns patterns from your feedback (trie ok / trie bad)"
|
|
1766
|
+
] }),
|
|
1767
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1768
|
+
" ",
|
|
1680
1769
|
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1681
|
-
"
|
|
1770
|
+
" Gets smarter over time"
|
|
1682
1771
|
] }),
|
|
1683
1772
|
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1684
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "
|
|
1685
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "
|
|
1686
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Tracks patterns over time" }),
|
|
1773
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Start watching to get proactive alerts," }),
|
|
1774
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " or run trie tell / trie ok / trie bad to teach it." }),
|
|
1687
1775
|
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1688
1776
|
isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1689
1777
|
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1690
|
-
|
|
1778
|
+
" ",
|
|
1779
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI-enhanced analysis enabled" })
|
|
1691
1780
|
] }) : /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1692
1781
|
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
|
|
1693
|
-
|
|
1782
|
+
" Set ",
|
|
1694
1783
|
/* @__PURE__ */ jsx7(Text6, { bold: true, children: "ANTHROPIC_API_KEY" }),
|
|
1695
|
-
|
|
1784
|
+
" ",
|
|
1785
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "for AI insights" })
|
|
1696
1786
|
] })
|
|
1697
|
-
] })
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1787
|
+
] });
|
|
1788
|
+
}
|
|
1789
|
+
const confidentPatterns = patterns.filter((p) => p.confidence > 0.7).length;
|
|
1790
|
+
const learningPatterns = patterns.filter((p) => p.confidence <= 0.7).length;
|
|
1791
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
1792
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1793
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
|
|
1794
|
+
" ",
|
|
1795
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1796
|
+
alertCount,
|
|
1797
|
+
" alert",
|
|
1798
|
+
alertCount !== 1 ? "s" : "",
|
|
1799
|
+
" ",
|
|
1800
|
+
decCount,
|
|
1801
|
+
" decision",
|
|
1802
|
+
decCount !== 1 ? "s" : "",
|
|
1803
|
+
" ",
|
|
1804
|
+
patCount,
|
|
1805
|
+
" pattern",
|
|
1806
|
+
patCount !== 1 ? "s" : ""
|
|
1807
|
+
] })
|
|
1808
|
+
] }),
|
|
1809
|
+
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1810
|
+
alertCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1811
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: " Alerts" }),
|
|
1812
|
+
alerts.map((insight, idx) => {
|
|
1813
|
+
const isSelected = idx === selectedInsight;
|
|
1814
|
+
const isExpanded = idx === expandedInsight;
|
|
1815
|
+
const ago = formatTimeAgo(insight.timestamp);
|
|
1816
|
+
const msg = insight.message.slice(0, 60) + (insight.message.length > 60 ? "..." : "");
|
|
1817
|
+
const riskColor2 = insight.priority >= 8 ? "red" : insight.priority >= 5 ? "yellow" : void 0;
|
|
1818
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1819
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1820
|
+
isSelected ? /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "green", children: [
|
|
1821
|
+
">",
|
|
1822
|
+
" "
|
|
1823
|
+
] }) : /* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1824
|
+
riskColor2 ? /* @__PURE__ */ jsx7(Text6, { color: riskColor2, children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
|
|
1717
1825
|
" ",
|
|
1718
|
-
|
|
1719
|
-
] }),
|
|
1720
|
-
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1826
|
+
isSelected ? /* @__PURE__ */ jsx7(Text6, { bold: true, children: msg }) : /* @__PURE__ */ jsx7(Text6, { children: msg }),
|
|
1721
1827
|
" ",
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
] }),
|
|
1727
|
-
isExpanded && insight.details && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginLeft: 4, children: [
|
|
1728
|
-
insight.details.issueBreakdown && Object.keys(insight.details.issueBreakdown).length > 0 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1729
|
-
insight.details.issueBreakdown["critical"] ? `${insight.details.issueBreakdown["critical"]} critical` : "",
|
|
1730
|
-
insight.details.issueBreakdown["serious"] ? ` \xB7 ${insight.details.issueBreakdown["serious"]} serious` : "",
|
|
1731
|
-
insight.details.issueBreakdown["moderate"] ? ` \xB7 ${insight.details.issueBreakdown["moderate"]} moderate` : ""
|
|
1732
|
-
] }),
|
|
1733
|
-
insight.details.affectedFiles && insight.details.affectedFiles.length > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1734
|
-
insight.details.affectedFiles.slice(0, 5).map((f, fi) => /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1735
|
-
" ",
|
|
1736
|
-
f
|
|
1737
|
-
] }, fi)),
|
|
1738
|
-
insight.details.affectedFiles.length > 5 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1739
|
-
" +",
|
|
1740
|
-
insight.details.affectedFiles.length - 5,
|
|
1741
|
-
" more"
|
|
1828
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1829
|
+
insight.category,
|
|
1830
|
+
" \xB7 ",
|
|
1831
|
+
ago
|
|
1742
1832
|
] })
|
|
1743
1833
|
] }),
|
|
1744
|
-
insight.
|
|
1745
|
-
|
|
1834
|
+
(isExpanded || isSelected) && insight.suggestedAction && /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1835
|
+
" ",
|
|
1836
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192" }),
|
|
1746
1837
|
" ",
|
|
1747
|
-
insight.
|
|
1838
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
|
|
1748
1839
|
] })
|
|
1749
|
-
] })
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1840
|
+
] }, insight.id);
|
|
1841
|
+
}),
|
|
1842
|
+
/* @__PURE__ */ jsx7(Text6, { children: " " })
|
|
1843
|
+
] }),
|
|
1844
|
+
decCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1845
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: " Decisions" }),
|
|
1846
|
+
decisions.slice(0, 10).map((dec) => {
|
|
1847
|
+
const ago = timeAgo(dec.when);
|
|
1848
|
+
const hash = dec.hash ? dec.hash.slice(0, 6) : "";
|
|
1849
|
+
const active = dec.status === "active";
|
|
1850
|
+
return /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1851
|
+
" ",
|
|
1852
|
+
active ? /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
|
|
1753
1853
|
" ",
|
|
1754
|
-
/* @__PURE__ */
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1854
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1855
|
+
dec.decision.slice(0, 45),
|
|
1856
|
+
dec.decision.length > 45 ? "..." : ""
|
|
1857
|
+
] }),
|
|
1858
|
+
" ",
|
|
1859
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: ago }),
|
|
1860
|
+
hash && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1861
|
+
" ",
|
|
1862
|
+
hash
|
|
1863
|
+
] })
|
|
1864
|
+
] }, dec.id);
|
|
1865
|
+
}),
|
|
1866
|
+
/* @__PURE__ */ jsx7(Text6, { children: " " })
|
|
1867
|
+
] }),
|
|
1868
|
+
patCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1869
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, children: " Patterns" }),
|
|
1870
|
+
confidentPatterns > 0 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1871
|
+
" ",
|
|
1872
|
+
confidentPatterns,
|
|
1873
|
+
" confident ",
|
|
1874
|
+
learningPatterns,
|
|
1875
|
+
" learning"
|
|
1876
|
+
] }),
|
|
1877
|
+
patterns.slice(0, 8).map((pat, idx) => {
|
|
1878
|
+
const conf = Math.round(pat.confidence * 100);
|
|
1879
|
+
const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
|
|
1880
|
+
const desc = pat.description.slice(0, 45) + (pat.description.length > 45 ? "..." : "");
|
|
1881
|
+
return /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1882
|
+
" ",
|
|
1883
|
+
pat.isAntiPattern ? /* @__PURE__ */ jsx7(Text6, { color: "red", children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
|
|
1759
1884
|
" ",
|
|
1760
|
-
/* @__PURE__ */ jsx7(Text6, {
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1885
|
+
/* @__PURE__ */ jsx7(Text6, { children: desc }),
|
|
1886
|
+
" ",
|
|
1887
|
+
confColor ? /* @__PURE__ */ jsxs6(Text6, { color: confColor, children: [
|
|
1888
|
+
conf,
|
|
1889
|
+
"%"
|
|
1890
|
+
] }) : /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1891
|
+
conf,
|
|
1892
|
+
"%"
|
|
1893
|
+
] }),
|
|
1894
|
+
pat.isAntiPattern && /* @__PURE__ */ jsx7(Text6, { color: "red", children: " anti-pattern" })
|
|
1895
|
+
] }, idx);
|
|
1896
|
+
})
|
|
1897
|
+
] }),
|
|
1764
1898
|
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
1765
1899
|
/* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
|
|
1766
|
-
|
|
1767
|
-
/* @__PURE__ */ jsx7(Text6, { color: "
|
|
1768
|
-
" ",
|
|
1769
|
-
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1770
|
-
agentInsights.filter((i) => i.type === "warning").length,
|
|
1771
|
-
" warnings"
|
|
1772
|
-
] })
|
|
1773
|
-
] }),
|
|
1774
|
-
agentInsights.filter((i) => i.type === "suggestion").length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1775
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
|
|
1900
|
+
isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1901
|
+
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1776
1902
|
" ",
|
|
1777
|
-
/* @__PURE__ */
|
|
1778
|
-
|
|
1779
|
-
" suggestions"
|
|
1780
|
-
] })
|
|
1781
|
-
] }),
|
|
1903
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI" })
|
|
1904
|
+
] }) : /* @__PURE__ */ jsx7(Text6, { children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB AI off" }) }),
|
|
1782
1905
|
agentInsights.filter((i) => i.type === "celebration").length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1783
1906
|
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1784
1907
|
" ",
|
|
@@ -1786,20 +1909,15 @@ function AgentView() {
|
|
|
1786
1909
|
agentInsights.filter((i) => i.type === "celebration").length,
|
|
1787
1910
|
" wins"
|
|
1788
1911
|
] })
|
|
1789
|
-
] })
|
|
1790
|
-
isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1791
|
-
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1792
|
-
" ",
|
|
1793
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI" })
|
|
1794
|
-
] }) : /* @__PURE__ */ jsx7(Text6, { children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB AI off" }) })
|
|
1912
|
+
] })
|
|
1795
1913
|
] })
|
|
1796
1914
|
] });
|
|
1797
1915
|
}
|
|
1798
1916
|
|
|
1799
1917
|
// src/cli/dashboard/views/GoalsView.tsx
|
|
1800
|
-
import { useCallback } from "react";
|
|
1918
|
+
import { useCallback as useCallback2 } from "react";
|
|
1801
1919
|
import { Box as Box7, Text as Text7, useInput as useInput3 } from "ink";
|
|
1802
|
-
import { Fragment, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1920
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1803
1921
|
function calculateGoalProgress(goal) {
|
|
1804
1922
|
if (goal.target <= 0) return 0;
|
|
1805
1923
|
const startValue = goal.startValue ?? goal.currentValue;
|
|
@@ -1816,7 +1934,7 @@ function GoalsView() {
|
|
|
1816
1934
|
const activeGoals = goalsPanel.goals.filter((g) => g.status === "active");
|
|
1817
1935
|
const achievedGoals = goalsPanel.goals.filter((g) => g.status === "achieved");
|
|
1818
1936
|
const otherGoals = goalsPanel.goals.filter((g) => g.status !== "active" && g.status !== "achieved");
|
|
1819
|
-
const refreshGoals =
|
|
1937
|
+
const refreshGoals = useCallback2(async () => {
|
|
1820
1938
|
try {
|
|
1821
1939
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1822
1940
|
const agentState = getGuardianState(workDir);
|
|
@@ -1832,7 +1950,7 @@ function GoalsView() {
|
|
|
1832
1950
|
} catch {
|
|
1833
1951
|
}
|
|
1834
1952
|
}, [dispatch]);
|
|
1835
|
-
const addGoal =
|
|
1953
|
+
const addGoal = useCallback2(async (description) => {
|
|
1836
1954
|
if (!description.trim()) return;
|
|
1837
1955
|
try {
|
|
1838
1956
|
const workDir = getWorkingDirectory(void 0, true);
|
|
@@ -1858,7 +1976,7 @@ function GoalsView() {
|
|
|
1858
1976
|
} catch {
|
|
1859
1977
|
}
|
|
1860
1978
|
}, [dispatch, refreshGoals]);
|
|
1861
|
-
const completeGoal =
|
|
1979
|
+
const completeGoal = useCallback2(async (goalId) => {
|
|
1862
1980
|
try {
|
|
1863
1981
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1864
1982
|
const agentState = getGuardianState(workDir);
|
|
@@ -1873,7 +1991,7 @@ function GoalsView() {
|
|
|
1873
1991
|
} catch {
|
|
1874
1992
|
}
|
|
1875
1993
|
}, [dispatch, refreshGoals]);
|
|
1876
|
-
const deleteGoal =
|
|
1994
|
+
const deleteGoal = useCallback2(async (goalId) => {
|
|
1877
1995
|
try {
|
|
1878
1996
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1879
1997
|
const agentState = getGuardianState(workDir);
|
|
@@ -1884,7 +2002,7 @@ function GoalsView() {
|
|
|
1884
2002
|
} catch {
|
|
1885
2003
|
}
|
|
1886
2004
|
}, [dispatch, refreshGoals]);
|
|
1887
|
-
const reactivateGoal =
|
|
2005
|
+
const reactivateGoal = useCallback2(async (goalId) => {
|
|
1888
2006
|
try {
|
|
1889
2007
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1890
2008
|
const agentState = getGuardianState(workDir);
|
|
@@ -1939,7 +2057,7 @@ function GoalsView() {
|
|
|
1939
2057
|
/* @__PURE__ */ jsx8(Text7, { bold: true, color: "green", children: "|" })
|
|
1940
2058
|
] }) }),
|
|
1941
2059
|
/* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " enter save \xB7 esc cancel" })
|
|
1942
|
-
] }) : /* @__PURE__ */ jsx8(
|
|
2060
|
+
] }) : /* @__PURE__ */ jsx8(Fragment2, { children: goalsPanel.goals.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1943
2061
|
/* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " No goals yet." }),
|
|
1944
2062
|
/* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " Press a to add your first goal." })
|
|
1945
2063
|
] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
@@ -2003,16 +2121,16 @@ function GoalsView() {
|
|
|
2003
2121
|
}
|
|
2004
2122
|
|
|
2005
2123
|
// src/cli/dashboard/views/HypothesesView.tsx
|
|
2006
|
-
import { useCallback as
|
|
2124
|
+
import { useCallback as useCallback3 } from "react";
|
|
2007
2125
|
import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
|
|
2008
|
-
import { Fragment as
|
|
2126
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2009
2127
|
function HypothesesView() {
|
|
2010
2128
|
const { state, dispatch } = useDashboard();
|
|
2011
2129
|
const { hypothesesPanel } = state;
|
|
2012
2130
|
const testing = hypothesesPanel.hypotheses.filter((h) => h.status === "testing");
|
|
2013
2131
|
const validated = hypothesesPanel.hypotheses.filter((h) => h.status === "validated");
|
|
2014
2132
|
const invalidated = hypothesesPanel.hypotheses.filter((h) => h.status === "invalidated");
|
|
2015
|
-
const refreshHypotheses =
|
|
2133
|
+
const refreshHypotheses = useCallback3(async () => {
|
|
2016
2134
|
try {
|
|
2017
2135
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2018
2136
|
const agentState = getGuardianState(workDir);
|
|
@@ -2028,7 +2146,7 @@ function HypothesesView() {
|
|
|
2028
2146
|
} catch {
|
|
2029
2147
|
}
|
|
2030
2148
|
}, [dispatch]);
|
|
2031
|
-
const addHypothesis =
|
|
2149
|
+
const addHypothesis = useCallback3(async (statement) => {
|
|
2032
2150
|
if (!statement.trim()) return;
|
|
2033
2151
|
try {
|
|
2034
2152
|
const workDir = getWorkingDirectory(void 0, true);
|
|
@@ -2050,7 +2168,7 @@ function HypothesesView() {
|
|
|
2050
2168
|
} catch {
|
|
2051
2169
|
}
|
|
2052
2170
|
}, [dispatch, refreshHypotheses]);
|
|
2053
|
-
const updateHypothesis =
|
|
2171
|
+
const updateHypothesis = useCallback3(async (hypoId, action) => {
|
|
2054
2172
|
try {
|
|
2055
2173
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2056
2174
|
const agentState = getGuardianState(workDir);
|
|
@@ -2063,7 +2181,7 @@ function HypothesesView() {
|
|
|
2063
2181
|
} catch {
|
|
2064
2182
|
}
|
|
2065
2183
|
}, [dispatch, refreshHypotheses]);
|
|
2066
|
-
const reactivateHypothesis =
|
|
2184
|
+
const reactivateHypothesis = useCallback3(async (hypoId) => {
|
|
2067
2185
|
try {
|
|
2068
2186
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2069
2187
|
const agentState = getGuardianState(workDir);
|
|
@@ -2121,7 +2239,7 @@ function HypothesesView() {
|
|
|
2121
2239
|
/* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "|" })
|
|
2122
2240
|
] }) }),
|
|
2123
2241
|
/* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " enter save \xB7 esc cancel" })
|
|
2124
|
-
] }) : /* @__PURE__ */ jsx9(
|
|
2242
|
+
] }) : /* @__PURE__ */ jsx9(Fragment3, { children: hypothesesPanel.hypotheses.length === 0 ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
2125
2243
|
/* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " No hypotheses yet." }),
|
|
2126
2244
|
/* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Press a to add your first hypothesis." })
|
|
2127
2245
|
] }) : /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
@@ -2182,31 +2300,48 @@ function HypothesesView() {
|
|
|
2182
2300
|
}
|
|
2183
2301
|
|
|
2184
2302
|
// src/cli/dashboard/views/MemoryTreeView.tsx
|
|
2185
|
-
import { useEffect, useCallback as
|
|
2303
|
+
import { useEffect as useEffect3, useCallback as useCallback4 } from "react";
|
|
2186
2304
|
import { Box as Box9, Text as Text9, useInput as useInput5 } from "ink";
|
|
2187
2305
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2306
|
+
var RISK_ORDER = { critical: 0, high: 1, medium: 2, low: 3, unknown: 4 };
|
|
2307
|
+
function riskColor(risk) {
|
|
2308
|
+
switch (risk) {
|
|
2309
|
+
case "critical":
|
|
2310
|
+
return "red";
|
|
2311
|
+
case "high":
|
|
2312
|
+
return "yellow";
|
|
2313
|
+
case "medium":
|
|
2314
|
+
return "blue";
|
|
2315
|
+
default:
|
|
2316
|
+
return void 0;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
function timeAgo2(iso) {
|
|
2320
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
2321
|
+
const mins = Math.floor(ms / 6e4);
|
|
2322
|
+
if (mins < 60) return `${mins}m`;
|
|
2323
|
+
const hrs = Math.floor(mins / 60);
|
|
2324
|
+
if (hrs < 24) return `${hrs}h`;
|
|
2325
|
+
return `${Math.floor(hrs / 24)}d`;
|
|
2191
2326
|
}
|
|
2192
2327
|
function MemoryTreeView() {
|
|
2193
2328
|
const { state, dispatch } = useDashboard();
|
|
2194
2329
|
const { memoryTree } = state;
|
|
2195
|
-
const {
|
|
2196
|
-
const loadData =
|
|
2330
|
+
const { snapshot, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
|
|
2331
|
+
const loadData = useCallback4(async () => {
|
|
2197
2332
|
try {
|
|
2198
2333
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2199
|
-
const
|
|
2200
|
-
|
|
2201
|
-
|
|
2334
|
+
const graph = new ContextGraph(workDir);
|
|
2335
|
+
const [snap, patterns] = await Promise.all([
|
|
2336
|
+
graph.getSnapshot(),
|
|
2202
2337
|
findCrossProjectPatterns(2)
|
|
2203
2338
|
]);
|
|
2204
|
-
dispatch({ type: "SET_MEMORY_TREE",
|
|
2339
|
+
dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns });
|
|
2205
2340
|
} catch {
|
|
2206
|
-
dispatch({ type: "ADD_ACTIVITY", message: "
|
|
2341
|
+
dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
|
|
2207
2342
|
}
|
|
2208
2343
|
}, [dispatch]);
|
|
2209
|
-
|
|
2344
|
+
useEffect3(() => {
|
|
2210
2345
|
if (!loaded) {
|
|
2211
2346
|
void loadData();
|
|
2212
2347
|
}
|
|
@@ -2216,201 +2351,196 @@ function MemoryTreeView() {
|
|
|
2216
2351
|
else if (key.downArrow || _input === "j") dispatch({ type: "NAVIGATE_DOWN" });
|
|
2217
2352
|
else if (key.return) dispatch({ type: "TOGGLE_MEMORY_NODE", nodeId: selectedNode });
|
|
2218
2353
|
});
|
|
2219
|
-
const bySeverity = { critical: [], serious: [], moderate: [], low: [] };
|
|
2220
|
-
for (const issue of issues) {
|
|
2221
|
-
const arr = bySeverity[issue.severity];
|
|
2222
|
-
if (arr) arr.push(issue);
|
|
2223
|
-
}
|
|
2224
|
-
const byFile = /* @__PURE__ */ new Map();
|
|
2225
|
-
for (const issue of issues) {
|
|
2226
|
-
if (!byFile.has(issue.file)) byFile.set(issue.file, []);
|
|
2227
|
-
byFile.get(issue.file).push(issue);
|
|
2228
|
-
}
|
|
2229
|
-
const sortedFiles = Array.from(byFile.entries()).sort((a, b) => b[1].length - a[1].length).slice(0, 10);
|
|
2230
|
-
const byAgent = /* @__PURE__ */ new Map();
|
|
2231
|
-
for (const issue of issues) {
|
|
2232
|
-
if (!byAgent.has(issue.agent)) byAgent.set(issue.agent, []);
|
|
2233
|
-
byAgent.get(issue.agent).push(issue);
|
|
2234
|
-
}
|
|
2235
|
-
const sortedAgents = Array.from(byAgent.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
2236
|
-
const maxCount = Math.max(bySeverity["critical"]?.length || 0, bySeverity["serious"]?.length || 0, bySeverity["moderate"]?.length || 0, bySeverity["low"]?.length || 0, 1);
|
|
2237
|
-
const totalIssues = stats?.totalIssues || issues.length;
|
|
2238
2354
|
const sel = (nodeId) => selectedNode === nodeId;
|
|
2355
|
+
if (!loaded) {
|
|
2356
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
|
|
2357
|
+
/* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
|
|
2358
|
+
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Loading context graph..." })
|
|
2359
|
+
] });
|
|
2360
|
+
}
|
|
2361
|
+
const nodeCount = snapshot?.nodes.length ?? 0;
|
|
2362
|
+
const edgeCount = snapshot?.edges.length ?? 0;
|
|
2363
|
+
if (nodeCount === 0 && globalPatterns.length === 0) {
|
|
2364
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
|
|
2365
|
+
/* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
|
|
2366
|
+
/* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2367
|
+
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " No context data yet." }),
|
|
2368
|
+
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Run trie watch or trie tell to populate the graph." })
|
|
2369
|
+
] });
|
|
2370
|
+
}
|
|
2371
|
+
const fileNodes = snapshot?.nodes.filter((n) => n.type === "file") ?? [];
|
|
2372
|
+
const changeNodes = snapshot?.nodes.filter((n) => n.type === "change") ?? [];
|
|
2373
|
+
const patternNodes = snapshot?.nodes.filter((n) => n.type === "pattern") ?? [];
|
|
2374
|
+
const incidentNodes = snapshot?.nodes.filter((n) => n.type === "incident") ?? [];
|
|
2375
|
+
const decisionNodes = snapshot?.nodes.filter((n) => n.type === "decision") ?? [];
|
|
2376
|
+
const sortedFiles = [...fileNodes].sort(
|
|
2377
|
+
(a, b) => (RISK_ORDER[a.data.riskLevel] ?? 4) - (RISK_ORDER[b.data.riskLevel] ?? 4)
|
|
2378
|
+
);
|
|
2379
|
+
const sortedChanges = [...changeNodes].sort(
|
|
2380
|
+
(a, b) => new Date(b.data.timestamp).getTime() - new Date(a.data.timestamp).getTime()
|
|
2381
|
+
);
|
|
2382
|
+
function renderSectionHeader(id, label, count) {
|
|
2383
|
+
const expanded = expandedNodes.has(id);
|
|
2384
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2385
|
+
sel(id) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2386
|
+
">",
|
|
2387
|
+
" "
|
|
2388
|
+
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2389
|
+
expanded ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2390
|
+
" ",
|
|
2391
|
+
sel(id) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2392
|
+
label,
|
|
2393
|
+
" (",
|
|
2394
|
+
count,
|
|
2395
|
+
")"
|
|
2396
|
+
] }) : /* @__PURE__ */ jsxs9(Text9, { bold: true, children: [
|
|
2397
|
+
label,
|
|
2398
|
+
" (",
|
|
2399
|
+
count,
|
|
2400
|
+
")"
|
|
2401
|
+
] })
|
|
2402
|
+
] });
|
|
2403
|
+
}
|
|
2239
2404
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
|
|
2240
2405
|
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2241
|
-
/* @__PURE__ */ jsx10(Text9, { bold: true, children: "
|
|
2406
|
+
/* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
|
|
2242
2407
|
" ",
|
|
2243
2408
|
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2244
|
-
|
|
2245
|
-
"
|
|
2409
|
+
nodeCount,
|
|
2410
|
+
" nodes ",
|
|
2411
|
+
edgeCount,
|
|
2412
|
+
" edges"
|
|
2246
2413
|
] })
|
|
2247
2414
|
] }),
|
|
2248
2415
|
/* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2416
|
+
renderSectionHeader("files", "Files", fileNodes.length),
|
|
2417
|
+
expandedNodes.has("files") && sortedFiles.slice(0, 15).map((n) => {
|
|
2418
|
+
const nodeId = `file-${n.id}`;
|
|
2419
|
+
const path = n.data.path.split("/").slice(-2).join("/");
|
|
2420
|
+
const risk = n.data.riskLevel;
|
|
2421
|
+
const color = riskColor(risk);
|
|
2422
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2423
|
+
sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2255
2424
|
">",
|
|
2256
2425
|
" "
|
|
2257
2426
|
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2258
|
-
|
|
2427
|
+
" ",
|
|
2428
|
+
color ? /* @__PURE__ */ jsx10(Text9, { color, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2259
2429
|
" ",
|
|
2260
|
-
sel(
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
count,
|
|
2284
|
-
")"
|
|
2285
|
-
] }) : /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2286
|
-
sev,
|
|
2287
|
-
" (",
|
|
2288
|
-
count,
|
|
2289
|
-
")"
|
|
2290
|
-
] }),
|
|
2291
|
-
" ",
|
|
2292
|
-
sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children: barStr }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: barStr })
|
|
2293
|
-
] }),
|
|
2294
|
-
expandedNodes.has(nodeId) && (bySeverity[sev] || []).slice(0, 5).map((issue, i) => {
|
|
2295
|
-
const issueId = `severity-${sev}-${issue.id}`;
|
|
2296
|
-
const filename = issue.file.split("/").pop() || issue.file;
|
|
2297
|
-
const line = issue.line ? `:${issue.line}` : "";
|
|
2298
|
-
const desc = issue.issue.slice(0, 35) + (issue.issue.length > 35 ? "..." : "");
|
|
2299
|
-
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2300
|
-
sel(issueId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2301
|
-
">",
|
|
2302
|
-
" "
|
|
2303
|
-
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2304
|
-
" ",
|
|
2305
|
-
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2306
|
-
filename,
|
|
2307
|
-
line
|
|
2308
|
-
] }),
|
|
2309
|
-
" ",
|
|
2310
|
-
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: desc })
|
|
2311
|
-
] }, i);
|
|
2312
|
-
})
|
|
2313
|
-
] }, sev);
|
|
2314
|
-
}),
|
|
2315
|
-
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2316
|
-
sel("files") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2430
|
+
sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: path }) : /* @__PURE__ */ jsx10(Text9, { children: path }),
|
|
2431
|
+
" ",
|
|
2432
|
+
color ? /* @__PURE__ */ jsx10(Text9, { color, children: risk }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: risk }),
|
|
2433
|
+
" ",
|
|
2434
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2435
|
+
n.data.changeCount,
|
|
2436
|
+
" changes"
|
|
2437
|
+
] }),
|
|
2438
|
+
n.data.incidentCount > 0 && /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2439
|
+
" ",
|
|
2440
|
+
n.data.incidentCount,
|
|
2441
|
+
" incidents"
|
|
2442
|
+
] })
|
|
2443
|
+
] }, n.id);
|
|
2444
|
+
}),
|
|
2445
|
+
renderSectionHeader("changes", "Changes", changeNodes.length),
|
|
2446
|
+
expandedNodes.has("changes") && sortedChanges.slice(0, 10).map((n) => {
|
|
2447
|
+
const nodeId = `change-${n.id}`;
|
|
2448
|
+
const msg = n.data.message.slice(0, 45) + (n.data.message.length > 45 ? "..." : "");
|
|
2449
|
+
const outcome = n.data.outcome;
|
|
2450
|
+
const outcomeColor = outcome === "incident" ? "red" : outcome === "success" ? "green" : void 0;
|
|
2451
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2452
|
+
sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2317
2453
|
">",
|
|
2318
2454
|
" "
|
|
2319
2455
|
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2320
|
-
|
|
2456
|
+
" ",
|
|
2457
|
+
outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2321
2458
|
" ",
|
|
2322
|
-
sel(
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2336
|
-
" (",
|
|
2337
|
-
count,
|
|
2338
|
-
")"
|
|
2339
|
-
] })
|
|
2340
|
-
] }, file);
|
|
2341
|
-
}),
|
|
2342
|
-
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2343
|
-
sel("agents") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2459
|
+
sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: msg }) : /* @__PURE__ */ jsx10(Text9, { children: msg }),
|
|
2460
|
+
" ",
|
|
2461
|
+
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: timeAgo2(n.data.timestamp) })
|
|
2462
|
+
] }, n.id);
|
|
2463
|
+
}),
|
|
2464
|
+
renderSectionHeader("patterns", "Patterns", patternNodes.length),
|
|
2465
|
+
expandedNodes.has("patterns") && patternNodes.slice(0, 10).map((n) => {
|
|
2466
|
+
const nodeId = `pattern-${n.id}`;
|
|
2467
|
+
const conf = Math.round(n.data.confidence * 100);
|
|
2468
|
+
const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
|
|
2469
|
+
const desc = n.data.description.slice(0, 45) + (n.data.description.length > 45 ? "..." : "");
|
|
2470
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2471
|
+
sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2344
2472
|
">",
|
|
2345
2473
|
" "
|
|
2346
2474
|
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2347
|
-
|
|
2475
|
+
" ",
|
|
2476
|
+
n.data.isAntiPattern ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2348
2477
|
" ",
|
|
2349
|
-
sel(
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
sel("patterns") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2478
|
+
sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: desc }) : /* @__PURE__ */ jsx10(Text9, { children: desc }),
|
|
2479
|
+
" ",
|
|
2480
|
+
confColor ? /* @__PURE__ */ jsxs9(Text9, { color: confColor, children: [
|
|
2481
|
+
conf,
|
|
2482
|
+
"%"
|
|
2483
|
+
] }) : /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2484
|
+
conf,
|
|
2485
|
+
"%"
|
|
2486
|
+
] }),
|
|
2487
|
+
n.data.isAntiPattern && /* @__PURE__ */ jsx10(Text9, { color: "red", children: " anti-pattern" })
|
|
2488
|
+
] }, n.id);
|
|
2489
|
+
}),
|
|
2490
|
+
renderSectionHeader("incidents", "Incidents", incidentNodes.length),
|
|
2491
|
+
expandedNodes.has("incidents") && incidentNodes.slice(0, 10).map((n) => {
|
|
2492
|
+
const nodeId = `incident-${n.id}`;
|
|
2493
|
+
const sevColor = n.data.severity === "critical" ? "red" : n.data.severity === "major" ? "yellow" : void 0;
|
|
2494
|
+
const desc = n.data.description.slice(0, 45) + (n.data.description.length > 45 ? "..." : "");
|
|
2495
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2496
|
+
sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2369
2497
|
">",
|
|
2370
2498
|
" "
|
|
2371
2499
|
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2372
|
-
|
|
2500
|
+
" ",
|
|
2501
|
+
sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2373
2502
|
" ",
|
|
2374
|
-
sel(
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
/* @__PURE__ */
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
] }),
|
|
2503
|
+
sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: desc }) : /* @__PURE__ */ jsx10(Text9, { children: desc }),
|
|
2504
|
+
" ",
|
|
2505
|
+
n.data.resolved ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "resolved" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "open" })
|
|
2506
|
+
] }, n.id);
|
|
2507
|
+
}),
|
|
2508
|
+
renderSectionHeader("decisions", "Decisions", decisionNodes.length),
|
|
2509
|
+
expandedNodes.has("decisions") && decisionNodes.slice(0, 10).map((n) => {
|
|
2510
|
+
const nodeId = `decision-${n.id}`;
|
|
2511
|
+
const dec = n.data.decision.slice(0, 45) + (n.data.decision.length > 45 ? "..." : "");
|
|
2512
|
+
const outcomeColor = n.data.outcome === "good" ? "green" : n.data.outcome === "bad" ? "red" : void 0;
|
|
2513
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2514
|
+
sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2515
|
+
">",
|
|
2516
|
+
" "
|
|
2517
|
+
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2518
|
+
" ",
|
|
2519
|
+
outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
|
|
2520
|
+
" ",
|
|
2521
|
+
sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: dec }) : /* @__PURE__ */ jsx10(Text9, { children: dec }),
|
|
2522
|
+
" ",
|
|
2523
|
+
outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: n.data.outcome }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: n.data.outcome })
|
|
2524
|
+
] }, n.id);
|
|
2525
|
+
}),
|
|
2526
|
+
renderSectionHeader("cross-project", "Cross-Project", globalPatterns.length),
|
|
2527
|
+
expandedNodes.has("cross-project") && globalPatterns.slice(0, 5).map((pattern) => {
|
|
2528
|
+
const patternId = `global-${pattern.id}`;
|
|
2529
|
+
const desc = pattern.pattern.slice(0, 40) + (pattern.pattern.length > 40 ? "..." : "");
|
|
2530
|
+
return /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
2531
|
+
sel(patternId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
|
|
2532
|
+
">",
|
|
2533
|
+
" "
|
|
2534
|
+
] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
|
|
2535
|
+
" ",
|
|
2408
2536
|
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
2409
|
-
|
|
2410
|
-
"
|
|
2537
|
+
desc,
|
|
2538
|
+
" \xB7 ",
|
|
2539
|
+
pattern.projects.length,
|
|
2540
|
+
" projects"
|
|
2411
2541
|
] })
|
|
2412
|
-
] })
|
|
2413
|
-
|
|
2542
|
+
] }, pattern.id);
|
|
2543
|
+
})
|
|
2414
2544
|
] });
|
|
2415
2545
|
}
|
|
2416
2546
|
|
|
@@ -2460,19 +2590,153 @@ function RawLogView() {
|
|
|
2460
2590
|
] });
|
|
2461
2591
|
}
|
|
2462
2592
|
|
|
2463
|
-
// src/cli/dashboard/
|
|
2593
|
+
// src/cli/dashboard/views/ChatView.tsx
|
|
2594
|
+
import { useCallback as useCallback5 } from "react";
|
|
2595
|
+
import { Box as Box11, Text as Text11, useInput as useInput7 } from "ink";
|
|
2464
2596
|
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2465
|
-
|
|
2597
|
+
function ChatView() {
|
|
2598
|
+
const { state, dispatch } = useDashboard();
|
|
2599
|
+
const { chatState } = state;
|
|
2600
|
+
const { messages, inputBuffer, loading } = chatState;
|
|
2601
|
+
const sendMessage = useCallback5(async (question) => {
|
|
2602
|
+
dispatch({ type: "ADD_CHAT_MESSAGE", role: "user", content: question });
|
|
2603
|
+
dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
|
|
2604
|
+
dispatch({ type: "SET_CHAT_LOADING", loading: true });
|
|
2605
|
+
try {
|
|
2606
|
+
const workDir = getWorkingDirectory(void 0, true);
|
|
2607
|
+
const storage = new TieredStorage(workDir);
|
|
2608
|
+
const graph = new ContextGraph(workDir);
|
|
2609
|
+
const [decisions, blockers, snap] = await Promise.all([
|
|
2610
|
+
storage.queryDecisions({ limit: 10 }),
|
|
2611
|
+
storage.queryBlockers({ limit: 5 }),
|
|
2612
|
+
graph.getSnapshot()
|
|
2613
|
+
]);
|
|
2614
|
+
const contextParts = [];
|
|
2615
|
+
if (decisions.length > 0) {
|
|
2616
|
+
contextParts.push("Recent decisions:\n" + decisions.map(
|
|
2617
|
+
(d) => `- ${d.decision} (${d.when}${d.hash ? `, hash: ${d.hash.slice(0, 8)}` : ""})`
|
|
2618
|
+
).join("\n"));
|
|
2619
|
+
}
|
|
2620
|
+
if (blockers.length > 0) {
|
|
2621
|
+
contextParts.push("Active blockers:\n" + blockers.map(
|
|
2622
|
+
(b) => `- ${b.blocker} [${b.impact}]`
|
|
2623
|
+
).join("\n"));
|
|
2624
|
+
}
|
|
2625
|
+
const fileNodes = snap.nodes.filter((n) => n.type === "file");
|
|
2626
|
+
const riskFiles = fileNodes.filter((n) => n.data && "riskLevel" in n.data && (n.data.riskLevel === "critical" || n.data.riskLevel === "high")).slice(0, 10);
|
|
2627
|
+
if (riskFiles.length > 0) {
|
|
2628
|
+
contextParts.push("High-risk files:\n" + riskFiles.map(
|
|
2629
|
+
(n) => `- ${n.data.path} (${n.data.riskLevel})`
|
|
2630
|
+
).join("\n"));
|
|
2631
|
+
}
|
|
2632
|
+
const patternNodes = snap.nodes.filter((n) => n.type === "pattern").slice(0, 5);
|
|
2633
|
+
if (patternNodes.length > 0) {
|
|
2634
|
+
contextParts.push("Learned patterns:\n" + patternNodes.map(
|
|
2635
|
+
(n) => `- ${n.data.description} (${Math.round(n.data.confidence * 100)}% confidence)`
|
|
2636
|
+
).join("\n"));
|
|
2637
|
+
}
|
|
2638
|
+
const contextBlock = contextParts.length > 0 ? contextParts.join("\n\n") : "No context data available yet.";
|
|
2639
|
+
const result = await runAIAnalysis({
|
|
2640
|
+
systemPrompt: `You are Trie, a code guardian assistant embedded in a TUI. Answer concisely based on the project context below. Reference specific decisions, patterns, and files when relevant.
|
|
2641
|
+
|
|
2642
|
+
Project context:
|
|
2643
|
+
${contextBlock}`,
|
|
2644
|
+
userPrompt: question,
|
|
2645
|
+
maxTokens: 1024,
|
|
2646
|
+
temperature: 0.4
|
|
2647
|
+
});
|
|
2648
|
+
if (result.success) {
|
|
2649
|
+
dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: result.content });
|
|
2650
|
+
} else {
|
|
2651
|
+
dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: result.error || "Failed to get a response." });
|
|
2652
|
+
}
|
|
2653
|
+
} catch (err) {
|
|
2654
|
+
dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: `Error: ${err instanceof Error ? err.message : "unknown"}` });
|
|
2655
|
+
} finally {
|
|
2656
|
+
dispatch({ type: "SET_CHAT_LOADING", loading: false });
|
|
2657
|
+
}
|
|
2658
|
+
}, [dispatch]);
|
|
2659
|
+
useInput7((input, key) => {
|
|
2660
|
+
if (loading) return;
|
|
2661
|
+
if (key.return && inputBuffer.trim().length > 0) {
|
|
2662
|
+
void sendMessage(inputBuffer.trim());
|
|
2663
|
+
} else if (key.escape) {
|
|
2664
|
+
dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
|
|
2665
|
+
} else if (key.backspace || key.delete) {
|
|
2666
|
+
dispatch({ type: "SET_CHAT_INPUT", buffer: inputBuffer.slice(0, -1) });
|
|
2667
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
2668
|
+
dispatch({ type: "SET_CHAT_INPUT", buffer: inputBuffer + input });
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
if (!isAIAvailable()) {
|
|
2672
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
|
|
2673
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "Chat" }),
|
|
2674
|
+
" ",
|
|
2675
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask Trie anything" }),
|
|
2676
|
+
/* @__PURE__ */ jsx12(Text11, { children: " " }),
|
|
2677
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " AI is not available." }),
|
|
2678
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
2679
|
+
" Press ",
|
|
2680
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "c" }),
|
|
2681
|
+
" to open settings and add your Anthropic API key,"
|
|
2682
|
+
] }),
|
|
2683
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
2684
|
+
" or set ",
|
|
2685
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "ANTHROPIC_API_KEY" }),
|
|
2686
|
+
" in your environment."
|
|
2687
|
+
] })
|
|
2688
|
+
] });
|
|
2689
|
+
}
|
|
2690
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
|
|
2691
|
+
/* @__PURE__ */ jsxs11(Text11, { children: [
|
|
2692
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "Chat" }),
|
|
2693
|
+
" ",
|
|
2694
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask Trie anything" })
|
|
2695
|
+
] }),
|
|
2696
|
+
/* @__PURE__ */ jsx12(Text11, { children: " " }),
|
|
2697
|
+
messages.length === 0 && !loading && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
2698
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " Ask about your codebase, decisions, patterns, or risks." }),
|
|
2699
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " Trie uses your context graph and decision ledger to answer." }),
|
|
2700
|
+
/* @__PURE__ */ jsx12(Text11, { children: " " })
|
|
2701
|
+
] }),
|
|
2702
|
+
messages.map((msg, idx) => /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", marginBottom: 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs11(Text11, { children: [
|
|
2703
|
+
" ",
|
|
2704
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, color: "green", children: "You:" }),
|
|
2705
|
+
" ",
|
|
2706
|
+
msg.content
|
|
2707
|
+
] }) : /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text11, { children: [
|
|
2708
|
+
" ",
|
|
2709
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "Trie:" }),
|
|
2710
|
+
" ",
|
|
2711
|
+
msg.content.slice(0, 500),
|
|
2712
|
+
msg.content.length > 500 ? "..." : ""
|
|
2713
|
+
] }) }) }, idx)),
|
|
2714
|
+
loading && /* @__PURE__ */ jsxs11(Text11, { children: [
|
|
2715
|
+
" ",
|
|
2716
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Thinking..." })
|
|
2717
|
+
] }),
|
|
2718
|
+
/* @__PURE__ */ jsx12(Box11, { flexGrow: 1 }),
|
|
2719
|
+
/* @__PURE__ */ jsx12(Box11, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs11(Text11, { children: [
|
|
2720
|
+
inputBuffer || /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask a question..." }),
|
|
2721
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, color: "green", children: "|" })
|
|
2722
|
+
] }) }),
|
|
2723
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " enter send esc clear" })
|
|
2724
|
+
] });
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
// src/cli/dashboard/App.tsx
|
|
2728
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2729
|
+
var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
|
|
2466
2730
|
function DashboardApp({ onReady }) {
|
|
2467
2731
|
const { state, dispatch } = useDashboard();
|
|
2468
2732
|
const { exit } = useApp();
|
|
2469
|
-
const [showConfig, setShowConfig] =
|
|
2733
|
+
const [showConfig, setShowConfig] = useState3(false);
|
|
2470
2734
|
const dispatchRef = useRef(dispatch);
|
|
2471
2735
|
dispatchRef.current = dispatch;
|
|
2472
2736
|
const stateRef = useRef(state);
|
|
2473
2737
|
stateRef.current = state;
|
|
2474
2738
|
const configPath = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agent.json");
|
|
2475
|
-
const loadConfig =
|
|
2739
|
+
const loadConfig = useCallback6(async () => {
|
|
2476
2740
|
if (!existsSync(configPath)) return;
|
|
2477
2741
|
try {
|
|
2478
2742
|
const raw = await readFile(configPath, "utf-8");
|
|
@@ -2481,14 +2745,14 @@ function DashboardApp({ onReady }) {
|
|
|
2481
2745
|
} catch {
|
|
2482
2746
|
}
|
|
2483
2747
|
}, [configPath]);
|
|
2484
|
-
const persistConfig =
|
|
2748
|
+
const persistConfig = useCallback6(async () => {
|
|
2485
2749
|
try {
|
|
2486
2750
|
await mkdir(getTrieDirectory(getWorkingDirectory(void 0, true)), { recursive: true });
|
|
2487
2751
|
await writeFile(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
|
|
2488
2752
|
} catch {
|
|
2489
2753
|
}
|
|
2490
2754
|
}, [configPath]);
|
|
2491
|
-
const processInsights =
|
|
2755
|
+
const processInsights = useCallback6(async (issues) => {
|
|
2492
2756
|
try {
|
|
2493
2757
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2494
2758
|
const trieAgent = getGuardian(workDir);
|
|
@@ -2514,7 +2778,7 @@ function DashboardApp({ onReady }) {
|
|
|
2514
2778
|
dispatchRef.current({ type: "ADD_ACTIVITY", message: `Trie Agent error: ${error instanceof Error ? error.message : "unknown"}` });
|
|
2515
2779
|
}
|
|
2516
2780
|
}, []);
|
|
2517
|
-
const refreshGoals =
|
|
2781
|
+
const refreshGoals = useCallback6(async () => {
|
|
2518
2782
|
try {
|
|
2519
2783
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2520
2784
|
const agentState = getGuardianState(workDir);
|
|
@@ -2530,7 +2794,7 @@ function DashboardApp({ onReady }) {
|
|
|
2530
2794
|
} catch {
|
|
2531
2795
|
}
|
|
2532
2796
|
}, []);
|
|
2533
|
-
const refreshHypotheses =
|
|
2797
|
+
const refreshHypotheses = useCallback6(async () => {
|
|
2534
2798
|
try {
|
|
2535
2799
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2536
2800
|
const agentState = getGuardianState(workDir);
|
|
@@ -2546,7 +2810,7 @@ function DashboardApp({ onReady }) {
|
|
|
2546
2810
|
} catch {
|
|
2547
2811
|
}
|
|
2548
2812
|
}, []);
|
|
2549
|
-
|
|
2813
|
+
useEffect4(() => {
|
|
2550
2814
|
void loadConfig();
|
|
2551
2815
|
void refreshGoals();
|
|
2552
2816
|
void refreshHypotheses();
|
|
@@ -2587,16 +2851,24 @@ function DashboardApp({ onReady }) {
|
|
|
2587
2851
|
outputManager.setMode("console");
|
|
2588
2852
|
};
|
|
2589
2853
|
}, [loadConfig, onReady, processInsights, refreshGoals, refreshHypotheses]);
|
|
2590
|
-
|
|
2854
|
+
useEffect4(() => {
|
|
2591
2855
|
const interval = setInterval(() => {
|
|
2592
2856
|
dispatchRef.current({ type: "AUTO_DISMISS_NOTIFICATIONS" });
|
|
2593
2857
|
}, 5e3);
|
|
2594
2858
|
return () => clearInterval(interval);
|
|
2595
2859
|
}, []);
|
|
2596
|
-
|
|
2860
|
+
useInput8((input, key) => {
|
|
2597
2861
|
if (showConfig) return;
|
|
2598
2862
|
if (state.view === "goals" && state.goalsPanel.inputMode === "add") return;
|
|
2599
2863
|
if (state.view === "hypotheses" && state.hypothesesPanel.inputMode === "add") return;
|
|
2864
|
+
if (state.view === "chat") {
|
|
2865
|
+
if (key.tab) {
|
|
2866
|
+
const currentIndex = MAIN_VIEWS.indexOf(state.view);
|
|
2867
|
+
const nextIndex = (currentIndex + 1) % MAIN_VIEWS.length;
|
|
2868
|
+
dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
|
|
2869
|
+
}
|
|
2870
|
+
return;
|
|
2871
|
+
}
|
|
2600
2872
|
if (input === "q" || key.escape) {
|
|
2601
2873
|
exit();
|
|
2602
2874
|
process.exit(0);
|
|
@@ -2607,7 +2879,7 @@ function DashboardApp({ onReady }) {
|
|
|
2607
2879
|
dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
|
|
2608
2880
|
return;
|
|
2609
2881
|
}
|
|
2610
|
-
if (input === "
|
|
2882
|
+
if (input === "s") {
|
|
2611
2883
|
setShowConfig(true);
|
|
2612
2884
|
return;
|
|
2613
2885
|
}
|
|
@@ -2633,6 +2905,10 @@ function DashboardApp({ onReady }) {
|
|
|
2633
2905
|
dispatch({ type: "SET_VIEW", view: "memory" });
|
|
2634
2906
|
return;
|
|
2635
2907
|
}
|
|
2908
|
+
if (input === "c") {
|
|
2909
|
+
dispatch({ type: "SET_VIEW", view: "chat" });
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2636
2912
|
if (state.view === "agent" || state.view === "memory") return;
|
|
2637
2913
|
if (input === "b") dispatch({ type: "GO_BACK" });
|
|
2638
2914
|
if (input === "n") dispatch({ type: "NEXT_PAGE" });
|
|
@@ -2641,38 +2917,41 @@ function DashboardApp({ onReady }) {
|
|
|
2641
2917
|
let viewComponent;
|
|
2642
2918
|
switch (state.view) {
|
|
2643
2919
|
case "overview":
|
|
2644
|
-
viewComponent = /* @__PURE__ */
|
|
2920
|
+
viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
|
|
2645
2921
|
break;
|
|
2646
2922
|
case "agent":
|
|
2647
|
-
viewComponent = /* @__PURE__ */
|
|
2923
|
+
viewComponent = /* @__PURE__ */ jsx13(AgentView, {});
|
|
2648
2924
|
break;
|
|
2649
2925
|
case "goals":
|
|
2650
|
-
viewComponent = /* @__PURE__ */
|
|
2926
|
+
viewComponent = /* @__PURE__ */ jsx13(GoalsView, {});
|
|
2651
2927
|
break;
|
|
2652
2928
|
case "hypotheses":
|
|
2653
|
-
viewComponent = /* @__PURE__ */
|
|
2929
|
+
viewComponent = /* @__PURE__ */ jsx13(HypothesesView, {});
|
|
2654
2930
|
break;
|
|
2655
2931
|
case "memory":
|
|
2656
|
-
viewComponent = /* @__PURE__ */
|
|
2932
|
+
viewComponent = /* @__PURE__ */ jsx13(MemoryTreeView, {});
|
|
2657
2933
|
break;
|
|
2658
2934
|
case "rawlog":
|
|
2659
|
-
viewComponent = /* @__PURE__ */
|
|
2935
|
+
viewComponent = /* @__PURE__ */ jsx13(RawLogView, {});
|
|
2936
|
+
break;
|
|
2937
|
+
case "chat":
|
|
2938
|
+
viewComponent = /* @__PURE__ */ jsx13(ChatView, {});
|
|
2660
2939
|
break;
|
|
2661
2940
|
default:
|
|
2662
|
-
viewComponent = /* @__PURE__ */
|
|
2941
|
+
viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
|
|
2663
2942
|
}
|
|
2664
|
-
return /* @__PURE__ */
|
|
2665
|
-
/* @__PURE__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2943
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", height: process.stdout.rows || 40, children: [
|
|
2944
|
+
/* @__PURE__ */ jsx13(Header, {}),
|
|
2945
|
+
/* @__PURE__ */ jsx13(Notification, {}),
|
|
2946
|
+
/* @__PURE__ */ jsx13(Box12, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx13(ConfigDialog, { onClose: () => {
|
|
2668
2947
|
setShowConfig(false);
|
|
2669
2948
|
void persistConfig();
|
|
2670
2949
|
} }) : viewComponent }),
|
|
2671
|
-
/* @__PURE__ */
|
|
2950
|
+
/* @__PURE__ */ jsx13(Footer, {})
|
|
2672
2951
|
] });
|
|
2673
2952
|
}
|
|
2674
2953
|
function App({ onReady }) {
|
|
2675
|
-
return /* @__PURE__ */
|
|
2954
|
+
return /* @__PURE__ */ jsx13(DashboardProvider, { children: /* @__PURE__ */ jsx13(DashboardApp, { onReady }) });
|
|
2676
2955
|
}
|
|
2677
2956
|
|
|
2678
2957
|
// src/cli/dashboard/index.ts
|
|
@@ -2682,7 +2961,7 @@ var InteractiveDashboard = class {
|
|
|
2682
2961
|
getConfigFn = null;
|
|
2683
2962
|
async start() {
|
|
2684
2963
|
this.app = render(
|
|
2685
|
-
|
|
2964
|
+
React10.createElement(App, {
|
|
2686
2965
|
onReady: (handler, getConfig) => {
|
|
2687
2966
|
this.updateHandler = handler;
|
|
2688
2967
|
this.getConfigFn = getConfig;
|
|
@@ -2716,4 +2995,4 @@ export {
|
|
|
2716
2995
|
getOutputManager,
|
|
2717
2996
|
InteractiveDashboard
|
|
2718
2997
|
};
|
|
2719
|
-
//# sourceMappingURL=chunk-
|
|
2998
|
+
//# sourceMappingURL=chunk-3YDNSKKP.js.map
|