@triedotdev/mcp 1.0.105 → 1.0.106

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.
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  getGuardian
3
- } from "./chunk-HFKOGW7H.js";
3
+ } from "./chunk-C5NK7EGK.js";
4
4
  import {
5
+ ContextGraph,
6
+ TieredStorage,
5
7
  findCrossProjectPatterns,
6
- isAIAvailable
7
- } from "./chunk-SPQJC7RA.js";
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 React7 from "react";
260
+ import React10 from "react";
258
261
 
259
262
  // src/cli/dashboard/App.tsx
260
- import { useState as useState2, useEffect as useEffect2, useCallback as useCallback4, useRef } from "react";
261
- import { Box as Box11, useInput as useInput7, useApp } from "ink";
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, issues, globalPatterns } = state.memoryTree;
277
- nodes.push({ id: "severity", level: 0 });
278
- if (expandedNodes.has("severity")) {
279
- nodes.push({ id: "severity-critical", level: 1 });
280
- if (expandedNodes.has("severity-critical")) {
281
- issues.filter((i) => i.severity === "critical").slice(0, 5).forEach((issue) => {
282
- nodes.push({ id: `severity-critical-${issue.id}`, level: 2 });
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
- const byFile = /* @__PURE__ */ new Map();
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: "agents", level: 0 });
298
- if (expandedNodes.has("agents")) {
299
- const byAgent = /* @__PURE__ */ new Map();
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
- globalPatterns.slice(0, 5).forEach((p) => nodes.push({ id: `pattern-${p.id}`, level: 1 }));
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, issues: action.issues, stats: action.stats, globalPatterns: action.patterns }
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 = ["severity", "files", "agents", "patterns", "severity-critical", "severity-serious", "severity-moderate", "severity-low"];
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, issues: [], stats: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["severity", "files"]), selectedNode: "severity", scrollPosition: 0, lastRefresh: 0 }
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: "\u25CF" }),
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: "\u25CF" }),
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 \xB7 b back";
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 h help";
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__ */ jsxs2(Text2, { children: [
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] = useState("main");
1369
- const [selectedIndex, setSelectedIndex] = useState(0);
1370
- const [editing, setEditing] = useState(false);
1371
- const [editBuffer, setEditBuffer] = useState("");
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: "Agent Smith Settings", key: "agentSmith", value: config.agentSmith.aiEnhancement ? "AI Enhanced" : "Basic", section: "main" },
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
- const val = parseInt(editBuffer, 10);
1400
- if (!isNaN(val)) {
1401
- const patch = {};
1402
- if (section === "performance") {
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
- if (Object.keys(patch).length > 0) {
1410
- dispatch({ type: "SET_AGENT_CONFIG", config: patch });
1411
- dispatch({ type: "ADD_ACTIVITY", message: `Config: ${item.label} set to ${val}` });
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 && /\d/.test(_input)) {
1420
- setEditBuffer(editBuffer + _input);
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 AGENT CONFIGURATION" : section === "performance" ? "PERFORMANCE SETTINGS" : section === "riskThresholds" ? "RISK THRESHOLDS" : section === "agentSmith" ? "AGENT SMITH SETTINGS" : "CONFIGURATION";
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
- items.map((item, idx) => {
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__ */ jsx5(Text4, { children: " " }),
1479
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: section === "main" ? "enter select \xB7 esc close" : "enter edit \xB7 esc/b back" })
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, agencyStatus, selectedInsight, expandedInsight } = state;
1628
- const totalInsights = agentInsights.length;
1702
+ const { agentInsights, agentBrain, selectedInsight, expandedInsight } = state;
1629
1703
  const visibleInsights = getVisibleInsights(state);
1630
- const activeCount = visibleInsights.length;
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 agency = agencyStatus;
1647
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1648
- /* @__PURE__ */ jsxs6(Text6, { children: [
1649
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Agent Insights" }),
1650
- activeCount > 0 ? /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
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
- activeCount,
1653
- " active"
1654
- ] }) : /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
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
- totalInsights,
1657
- " total"
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
- " The Trie Agent is watching over your code."
1770
+ " Gets smarter over time"
1682
1771
  ] }),
1683
1772
  /* @__PURE__ */ jsx7(Text6, { children: " " }),
1684
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Synthesizes insights from all skills" }),
1685
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Suggests specific actions to take" }),
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
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " AI-enhanced insights enabled" })
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
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Set " }),
1782
+ " Set ",
1694
1783
  /* @__PURE__ */ jsx7(Text6, { bold: true, children: "ANTHROPIC_API_KEY" }),
1695
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " for AI insights" })
1784
+ " ",
1785
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "for AI insights" })
1696
1786
  ] })
1697
- ] }) : /* @__PURE__ */ jsx7(Box6, { flexDirection: "column", children: visibleInsights.map((insight, idx) => {
1698
- const isSelected = idx === selectedInsight;
1699
- const isExpanded = idx === expandedInsight;
1700
- const ago = formatTimeAgo(insight.timestamp);
1701
- const { icon, color } = insightIcon(insight.type);
1702
- const cleanMessage = stripEmojis(insight.message);
1703
- const msgMaxLen = 65;
1704
- const msg = cleanMessage.length > msgMaxLen ? cleanMessage.slice(0, msgMaxLen - 3) + "..." : cleanMessage;
1705
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
1706
- /* @__PURE__ */ jsxs6(Text6, { children: [
1707
- isSelected ? /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "green", children: [
1708
- ">",
1709
- " "
1710
- ] }) : /* @__PURE__ */ jsx7(Text6, { children: " " }),
1711
- isSelected ? /* @__PURE__ */ jsxs6(Text6, { children: [
1712
- /* @__PURE__ */ jsx7(Text6, { color: "green", children: icon }),
1713
- " ",
1714
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: msg })
1715
- ] }) : /* @__PURE__ */ jsxs6(Text6, { children: [
1716
- color(icon),
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
- color(msg)
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
- insight.category,
1723
- " \xB7 ",
1724
- ago
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.details.comparison && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1745
- insight.details.trend === "improving" ? "\u2193" : insight.details.trend === "worsening" ? "\u2191" : "\u2192",
1834
+ (isExpanded || isSelected) && insight.suggestedAction && /* @__PURE__ */ jsxs6(Text6, { children: [
1835
+ " ",
1836
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192" }),
1746
1837
  " ",
1747
- insight.details.comparison
1838
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
1748
1839
  ] })
1749
- ] }),
1750
- insight.suggestedAction && (isExpanded || isSelected) && /* @__PURE__ */ jsxs6(Text6, { children: [
1751
- " ",
1752
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192" }),
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__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
1755
- ] }),
1756
- insight.actionCommand && isExpanded && /* @__PURE__ */ jsxs6(Text6, { children: [
1757
- " ",
1758
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "$" }),
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, { color: "green", children: insight.actionCommand })
1761
- ] })
1762
- ] }, insight.id);
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
- agentInsights.filter((i) => i.type === "warning").length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
1767
- /* @__PURE__ */ jsx7(Text6, { color: "red", children: "\u25CF" }),
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__ */ jsxs6(Text6, { dimColor: true, children: [
1778
- agentInsights.filter((i) => i.type === "suggestion").length,
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 = useCallback(async () => {
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 = useCallback(async (description) => {
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 = useCallback(async (goalId) => {
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 = useCallback(async (goalId) => {
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 = useCallback(async (goalId) => {
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(Fragment, { children: goalsPanel.goals.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
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 useCallback2 } from "react";
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 Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
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 = useCallback2(async () => {
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 = useCallback2(async (statement) => {
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 = useCallback2(async (hypoId, action) => {
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 = useCallback2(async (hypoId) => {
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(Fragment2, { children: hypothesesPanel.hypotheses.length === 0 ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
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 useCallback3 } from "react";
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
- function severityBar(count, max, width = 16) {
2189
- const filled = max > 0 ? Math.round(count / max * width) : 0;
2190
- return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
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 { issues, stats, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
2196
- const loadData = useCallback3(async () => {
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 [issueList, memStats, patterns] = await Promise.all([
2200
- getRecentIssues({ workDir, limit: 200, daysBack: 30 }),
2201
- getMemoryStats(workDir),
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", issues: issueList, stats: memStats, patterns });
2339
+ dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns });
2205
2340
  } catch {
2206
- dispatch({ type: "ADD_ACTIVITY", message: "Memory load error" });
2341
+ dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
2207
2342
  }
2208
2343
  }, [dispatch]);
2209
- useEffect(() => {
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: "Memory" }),
2406
+ /* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
2242
2407
  " ",
2243
2408
  /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2244
- totalIssues,
2245
- " issues"
2409
+ nodeCount,
2410
+ " nodes ",
2411
+ edgeCount,
2412
+ " edges"
2246
2413
  ] })
2247
2414
  ] }),
2248
2415
  /* @__PURE__ */ jsx10(Text9, { children: " " }),
2249
- !loaded ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Loading memory data..." }) : issues.length === 0 && globalPatterns.length === 0 ? /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2250
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " No issues in memory yet." }),
2251
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Run a scan to populate the memory tree." })
2252
- ] }) : /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2253
- /* @__PURE__ */ jsxs9(Text9, { children: [
2254
- sel("severity") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
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
- expandedNodes.has("severity") ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2427
+ " ",
2428
+ color ? /* @__PURE__ */ jsx10(Text9, { color, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2259
2429
  " ",
2260
- sel("severity") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By Severity" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By Severity" })
2261
- ] }),
2262
- expandedNodes.has("severity") && ["critical", "serious", "moderate", "low"].map((sev) => {
2263
- const count = bySeverity[sev]?.length || 0;
2264
- const nodeId = `severity-${sev}`;
2265
- const barStr = severityBar(count, maxCount);
2266
- const sevColorMap = { critical: "red", serious: "yellow", moderate: "blue", low: void 0 };
2267
- const sevColor = sevColorMap[sev];
2268
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2269
- /* @__PURE__ */ jsxs9(Text9, { children: [
2270
- sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2271
- ">",
2272
- " "
2273
- ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2274
- " ",
2275
- sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2276
- sev,
2277
- " (",
2278
- count,
2279
- ")"
2280
- ] }) : sevColor ? /* @__PURE__ */ jsxs9(Text9, { color: sevColor, children: [
2281
- sev,
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
- expandedNodes.has("files") ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2456
+ " ",
2457
+ outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2321
2458
  " ",
2322
- sel("files") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By File (Hot Spots)" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By File (Hot Spots)" })
2323
- ] }),
2324
- expandedNodes.has("files") && sortedFiles.map(([file, fileIssues]) => {
2325
- const fileId = `file-${file}`;
2326
- const filename = file.split("/").pop() || file;
2327
- const count = fileIssues.length;
2328
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2329
- sel(fileId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2330
- ">",
2331
- " "
2332
- ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2333
- " ",
2334
- sel(fileId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: filename }) : /* @__PURE__ */ jsx10(Text9, { children: filename }),
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
- expandedNodes.has("agents") ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2475
+ " ",
2476
+ n.data.isAntiPattern ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2348
2477
  " ",
2349
- sel("agents") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By Agent" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By Agent" })
2350
- ] }),
2351
- expandedNodes.has("agents") && sortedAgents.map(([agent, agentIssues]) => {
2352
- const agentId = `agent-${agent}`;
2353
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2354
- sel(agentId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2355
- ">",
2356
- " "
2357
- ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2358
- " ",
2359
- sel(agentId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: agent }) : /* @__PURE__ */ jsx10(Text9, { children: agent }),
2360
- /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2361
- " (",
2362
- agentIssues.length,
2363
- ")"
2364
- ] })
2365
- ] }, agent);
2366
- }),
2367
- /* @__PURE__ */ jsxs9(Text9, { children: [
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
- expandedNodes.has("patterns") ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2500
+ " ",
2501
+ sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2373
2502
  " ",
2374
- sel("patterns") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2375
- "Patterns (",
2376
- globalPatterns.length,
2377
- " recurring)"
2378
- ] }) : /* @__PURE__ */ jsxs9(Text9, { bold: true, children: [
2379
- "Patterns (",
2380
- globalPatterns.length,
2381
- " recurring)"
2382
- ] })
2383
- ] }),
2384
- expandedNodes.has("patterns") && globalPatterns.slice(0, 5).map((pattern) => {
2385
- const patternId = `pattern-${pattern.id}`;
2386
- const desc = pattern.pattern.slice(0, 40) + (pattern.pattern.length > 40 ? "..." : "");
2387
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2388
- sel(patternId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2389
- ">",
2390
- " "
2391
- ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2392
- " ",
2393
- /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2394
- desc,
2395
- " \xB7 ",
2396
- pattern.projects.length,
2397
- " projects"
2398
- ] })
2399
- ] }, pattern.id);
2400
- }),
2401
- /* @__PURE__ */ jsx10(Text9, { children: " " }),
2402
- /* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
2403
- /* @__PURE__ */ jsx10(Text9, { children: stats?.improvementTrend === "improving" ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF Improving" }) : stats?.improvementTrend === "declining" ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF Declining" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB Stable" }) }),
2404
- /* @__PURE__ */ jsxs9(Text9, { children: [
2405
- /* @__PURE__ */ jsx10(Text9, { color: "green", children: stats?.resolvedCount || 0 }),
2406
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " resolved" })
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
- stats?.historicalIssues || 0,
2410
- " historical"
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/App.tsx
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
- var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent"];
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] = useState2(false);
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 = useCallback4(async () => {
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 = useCallback4(async () => {
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 = useCallback4(async (issues) => {
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 = useCallback4(async () => {
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 = useCallback4(async () => {
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
- useEffect2(() => {
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
- useEffect2(() => {
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
- useInput7((input, key) => {
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 === "c") {
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__ */ jsx12(OverviewView, {});
2920
+ viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
2645
2921
  break;
2646
2922
  case "agent":
2647
- viewComponent = /* @__PURE__ */ jsx12(AgentView, {});
2923
+ viewComponent = /* @__PURE__ */ jsx13(AgentView, {});
2648
2924
  break;
2649
2925
  case "goals":
2650
- viewComponent = /* @__PURE__ */ jsx12(GoalsView, {});
2926
+ viewComponent = /* @__PURE__ */ jsx13(GoalsView, {});
2651
2927
  break;
2652
2928
  case "hypotheses":
2653
- viewComponent = /* @__PURE__ */ jsx12(HypothesesView, {});
2929
+ viewComponent = /* @__PURE__ */ jsx13(HypothesesView, {});
2654
2930
  break;
2655
2931
  case "memory":
2656
- viewComponent = /* @__PURE__ */ jsx12(MemoryTreeView, {});
2932
+ viewComponent = /* @__PURE__ */ jsx13(MemoryTreeView, {});
2657
2933
  break;
2658
2934
  case "rawlog":
2659
- viewComponent = /* @__PURE__ */ jsx12(RawLogView, {});
2935
+ viewComponent = /* @__PURE__ */ jsx13(RawLogView, {});
2936
+ break;
2937
+ case "chat":
2938
+ viewComponent = /* @__PURE__ */ jsx13(ChatView, {});
2660
2939
  break;
2661
2940
  default:
2662
- viewComponent = /* @__PURE__ */ jsx12(OverviewView, {});
2941
+ viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
2663
2942
  }
2664
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", height: process.stdout.rows || 40, children: [
2665
- /* @__PURE__ */ jsx12(Header, {}),
2666
- /* @__PURE__ */ jsx12(Notification, {}),
2667
- /* @__PURE__ */ jsx12(Box11, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx12(ConfigDialog, { onClose: () => {
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__ */ jsx12(Footer, {})
2950
+ /* @__PURE__ */ jsx13(Footer, {})
2672
2951
  ] });
2673
2952
  }
2674
2953
  function App({ onReady }) {
2675
- return /* @__PURE__ */ jsx12(DashboardProvider, { children: /* @__PURE__ */ jsx12(DashboardApp, { onReady }) });
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
- React7.createElement(App, {
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-HBPTBNFJ.js.map
2998
+ //# sourceMappingURL=chunk-3YDNSKKP.js.map