@triedotdev/mcp 1.0.117 → 1.0.118

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.
@@ -526,12 +526,25 @@ function dashboardReducer(state, action) {
526
526
  (ni) => !existing.some((ei) => ei.message === ni.message && !ei.dismissed)
527
527
  );
528
528
  const merged = [...newOnes, ...existing].slice(0, 50);
529
+ console.error("[State] ADD_INSIGHTS:", {
530
+ newCount: newOnes.length,
531
+ existingCount: existing.length,
532
+ mergedCount: merged.length,
533
+ newInsights: newOnes.map((i) => ({ id: i.id, type: i.type, message: i.message.slice(0, 50) }))
534
+ });
529
535
  let s = { ...state, agentInsights: merged };
536
+ const newAlerts = newOnes.filter((i) => i.type === "warning" && !i.dismissed).length;
537
+ if (newAlerts > 0) {
538
+ s.unreadNudgesCount = state.unreadNudgesCount + newAlerts;
539
+ }
530
540
  if (newOnes.length > 0) {
531
541
  s = addActivity(s, `Trie Agent: ${newOnes.length} new insight${newOnes.length > 1 ? "s" : ""}`);
532
542
  }
533
543
  return s;
534
544
  }
545
+ case "MARK_NUDGES_READ": {
546
+ return { ...state, unreadNudgesCount: 0 };
547
+ }
535
548
  case "SET_AGENT_INITIALIZED":
536
549
  return { ...state, agentInitialized: action.initialized };
537
550
  case "SET_AGENCY_STATUS":
@@ -784,6 +797,7 @@ function createInitialState() {
784
797
  agencyStatus: null,
785
798
  selectedInsight: 0,
786
799
  expandedInsight: null,
800
+ unreadNudgesCount: 0,
787
801
  agentConfig: {
788
802
  agentSmith: {
789
803
  aiEnhancement: true,
@@ -887,7 +901,7 @@ var VIEW_SHORT = {
887
901
  };
888
902
  var TAB_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
889
903
  var CONTEXT_HINTS = {
890
- goals: "j/k nav \xB7 a add \xB7 enter complete \xB7 d delete",
904
+ goals: "j/k nav \xB7 a add \xB7 enter complete \xB7 d delete \xB7 c clear achieved",
891
905
  hypotheses: "j/k nav \xB7 a add \xB7 v validate \xB7 x invalidate",
892
906
  agent: "j/k nav \xB7 enter expand \xB7 d dismiss",
893
907
  memory: "j/k nav \xB7 enter expand",
@@ -895,7 +909,7 @@ var CONTEXT_HINTS = {
895
909
  rawlog: "n/p pages \xB7 b back"
896
910
  };
897
911
  var CONTEXT_HINTS_SHORT = {
898
- goals: "j/k a d",
912
+ goals: "j/k a d c",
899
913
  hypotheses: "j/k a v x",
900
914
  agent: "j/k enter d",
901
915
  memory: "j/k enter",
@@ -904,12 +918,13 @@ var CONTEXT_HINTS_SHORT = {
904
918
  };
905
919
  function Footer() {
906
920
  const { state } = useDashboard();
907
- const { view, goalsPanel, hypothesesPanel } = state;
921
+ const { view, goalsPanel, hypothesesPanel, unreadNudgesCount } = state;
908
922
  const { stdout } = useStdout2();
909
923
  const cols = stdout?.columns || 80;
910
924
  const narrow = cols < 60;
911
925
  const veryNarrow = cols < 40;
912
926
  const labels = narrow ? VIEW_SHORT : VIEW_LABELS;
927
+ const hasUnreadNudges = unreadNudgesCount > 0;
913
928
  let hints;
914
929
  if (view === "goals" && goalsPanel.inputMode === "add") {
915
930
  hints = narrow ? "enter esc" : "enter save \xB7 esc cancel";
@@ -921,7 +936,22 @@ function Footer() {
921
936
  }
922
937
  if (veryNarrow) {
923
938
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
924
- /* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => v === view ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: labels[v] }, v) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }, v)) }),
939
+ /* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => {
940
+ const isAgent = v === "agent";
941
+ const isCurrent = v === view;
942
+ if (isCurrent) {
943
+ return /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: labels[v] }, v);
944
+ } else if (isAgent && hasUnreadNudges) {
945
+ return /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
946
+ labels[v],
947
+ " (",
948
+ unreadNudgesCount,
949
+ ")"
950
+ ] }, v);
951
+ } else {
952
+ return /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }, v);
953
+ }
954
+ }) }),
925
955
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
926
956
  hints,
927
957
  " \xB7 q quit"
@@ -929,7 +959,22 @@ function Footer() {
929
959
  ] });
930
960
  }
931
961
  return /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, justifyContent: "space-between", children: [
932
- /* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => v === view ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: labels[v] }, v) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }, v)) }),
962
+ /* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => {
963
+ const isAgent = v === "agent";
964
+ const isCurrent = v === view;
965
+ if (isCurrent) {
966
+ return /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: labels[v] }, v);
967
+ } else if (isAgent && hasUnreadNudges) {
968
+ return /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
969
+ labels[v],
970
+ " (",
971
+ unreadNudgesCount,
972
+ ")"
973
+ ] }, v);
974
+ } else {
975
+ return /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }, v);
976
+ }
977
+ }) }),
933
978
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
934
979
  hints,
935
980
  " \xB7 q quit"
@@ -1387,6 +1432,17 @@ function AgentView() {
1387
1432
  const visibleInsights = getVisibleInsights(state);
1388
1433
  const alerts = visibleInsights.filter((i) => i.type === "warning");
1389
1434
  const { decisions, patterns, loaded } = agentBrain;
1435
+ useEffect(() => {
1436
+ if (agentInsights.length > 0 || visibleInsights.length > 0) {
1437
+ console.error("[AgentView Debug]", {
1438
+ totalInsights: agentInsights.length,
1439
+ visibleInsights: visibleInsights.length,
1440
+ alerts: alerts.length,
1441
+ insightTypes: agentInsights.map((i) => i.type),
1442
+ visibleTypes: visibleInsights.map((i) => i.type)
1443
+ });
1444
+ }
1445
+ }, [agentInsights, visibleInsights, alerts]);
1390
1446
  const loadBrain = useCallback(async () => {
1391
1447
  try {
1392
1448
  const workDir = getWorkingDirectory(void 0, true);
@@ -1407,6 +1463,11 @@ function AgentView() {
1407
1463
  void loadBrain();
1408
1464
  }
1409
1465
  }, [loaded, loadBrain]);
1466
+ useEffect(() => {
1467
+ if (state.unreadNudgesCount > 0) {
1468
+ dispatch({ type: "MARK_NUDGES_READ" });
1469
+ }
1470
+ }, [dispatch, state.unreadNudgesCount]);
1410
1471
  useInput3((input, key) => {
1411
1472
  if (key.upArrow || input === "k") dispatch({ type: "NAVIGATE_UP" });
1412
1473
  else if (key.downArrow || input === "j") dispatch({ type: "NAVIGATE_DOWN" });
@@ -1627,6 +1688,24 @@ function GoalsView() {
1627
1688
  } catch {
1628
1689
  }
1629
1690
  }, [dispatch, refreshGoals]);
1691
+ const clearAchievedGoals = useCallback2(async () => {
1692
+ try {
1693
+ const workDir = getWorkingDirectory(void 0, true);
1694
+ const agentState = getGuardianState(workDir);
1695
+ await agentState.load();
1696
+ const achieved = goalsPanel.goals.filter((g) => g.status === "achieved");
1697
+ if (achieved.length === 0) {
1698
+ dispatch({ type: "ADD_ACTIVITY", message: "No achieved goals to clear" });
1699
+ return;
1700
+ }
1701
+ for (const goal of achieved) {
1702
+ await agentState.deleteGoal(goal.id);
1703
+ }
1704
+ dispatch({ type: "ADD_ACTIVITY", message: `Cleared ${achieved.length} achieved goal${achieved.length > 1 ? "s" : ""}` });
1705
+ await refreshGoals();
1706
+ } catch {
1707
+ }
1708
+ }, [dispatch, refreshGoals, goalsPanel.goals]);
1630
1709
  useInput4((_input, key) => {
1631
1710
  if (goalsPanel.inputMode === "add") {
1632
1711
  if (key.escape) {
@@ -1650,6 +1729,8 @@ function GoalsView() {
1650
1729
  } else if (_input === "d") {
1651
1730
  const selected = activeGoals[goalsPanel.selectedIndex];
1652
1731
  if (selected) void deleteGoal(selected.id);
1732
+ } else if (_input === "c") {
1733
+ void clearAchievedGoals();
1653
1734
  } else if (_input === "x") {
1654
1735
  const completed = goalsPanel.goals.filter((g) => g.status === "achieved" || g.status === "failed");
1655
1736
  if (completed[0]) void deleteGoal(completed[0].id);
@@ -4554,19 +4635,118 @@ async function spawnLinuxTerminal(command, cwd, title, keepOpen) {
4554
4635
  }
4555
4636
  async function spawnClaudeCodeFix(options) {
4556
4637
  const { file, goal, violation, suggestedFix, cwd } = options;
4557
- const prompt = `Fix this goal violation:
4638
+ const fixScript = `
4639
+ #!/bin/bash
4640
+ set -e
4641
+
4642
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
4643
+ echo "\u{1F527} Trie Agent - Automated Fix"
4644
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
4645
+ echo ""
4646
+ echo "File: ${file}"
4647
+ echo "Goal: ${goal}"
4648
+ echo "Violation: ${violation}"
4649
+ ${suggestedFix ? `echo "Suggested: ${suggestedFix}"` : ""}
4650
+ echo ""
4651
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
4652
+ echo ""
4653
+
4654
+ # Check if file exists
4655
+ if [ ! -f "${file}" ]; then
4656
+ echo "\u274C Error: File not found: ${file}"
4657
+ exit 1
4658
+ fi
4659
+
4660
+ # Check if ANTHROPIC_API_KEY is set
4661
+ if [ -z "\${ANTHROPIC_API_KEY}" ]; then
4662
+ echo "\u274C Error: ANTHROPIC_API_KEY not set"
4663
+ echo ""
4664
+ echo "Please set your API key:"
4665
+ echo " export ANTHROPIC_API_KEY=sk-ant-api03-..."
4666
+ echo ""
4667
+ exit 1
4668
+ fi
4669
+
4670
+ echo "\u{1F4D6} Reading file..."
4671
+ FILE_CONTENT=$(cat "${file}")
4672
+
4673
+ echo "\u{1F916} Analyzing with Claude..."
4674
+ echo ""
4675
+
4676
+ # Create the fix prompt
4677
+ PROMPT="You are fixing a code quality violation.
4558
4678
 
4559
4679
  Goal: ${goal}
4560
- File: ${file}
4561
4680
  Violation: ${violation}
4562
4681
  ${suggestedFix ? `Suggested fix: ${suggestedFix}` : ""}
4563
4682
 
4564
- Please review the file and fix the violation while preserving functionality.`;
4565
- const escapedPrompt = prompt.replace(/"/g, '\\"').replace(/\n/g, "\\n");
4566
- const escapedFile = file.replace(/"/g, '\\"');
4567
- const command = `echo "${escapedPrompt}" | claude --file="${escapedFile}"`;
4683
+ File: ${file}
4684
+
4685
+ Current content:
4686
+ $FILE_CONTENT
4687
+
4688
+ Please fix the violation while:
4689
+ 1. Preserving all functionality
4690
+ 2. Maintaining code style
4691
+ 3. Not breaking anything
4692
+ 4. Following the goal exactly
4693
+
4694
+ Output ONLY the fixed file content, no explanations or markdown fences."
4695
+
4696
+ # Call Claude API to generate fix
4697
+ # Using npx to run a simple Node script
4698
+ FIXED_CONTENT=$(npx --yes -q tsx -e "
4699
+ import Anthropic from '@anthropic-ai/sdk';
4700
+ const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
4701
+ const msg = await client.messages.create({
4702
+ model: 'claude-3-5-sonnet-20241022',
4703
+ max_tokens: 8000,
4704
+ messages: [{ role: 'user', content: \\\`\${PROMPT}\\\` }]
4705
+ });
4706
+ const text = msg.content.find(c => c.type === 'text');
4707
+ console.log(text ? text.text : '');
4708
+ ")
4709
+
4710
+ if [ -z "$FIXED_CONTENT" ]; then
4711
+ echo "\u274C Error: Claude did not generate a fix"
4712
+ exit 1
4713
+ fi
4714
+
4715
+ echo "\u2705 Fix generated!"
4716
+ echo ""
4717
+
4718
+ # Show diff
4719
+ echo "\u{1F4CA} Changes:"
4720
+ echo ""
4721
+ diff -u "${file}" <(echo "$FIXED_CONTENT") || true
4722
+ echo ""
4723
+
4724
+ # Prompt for confirmation
4725
+ read -p "Apply this fix? [y/N] " -n 1 -r
4726
+ echo ""
4727
+
4728
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
4729
+ echo "$FIXED_CONTENT" > "${file}"
4730
+ echo "\u2705 Fix applied to ${file}"
4731
+ echo ""
4732
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
4733
+ echo "\u2728 Done! File has been fixed."
4734
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
4735
+ else
4736
+ echo "\u274C Fix cancelled"
4737
+ fi
4738
+
4739
+ echo ""
4740
+ read -p "Press Enter to close..."
4741
+ `.trim();
4742
+ const { writeFile: writeFile2, chmod, unlink } = await import("fs/promises");
4743
+ const { tmpdir } = await import("os");
4744
+ const { join: join3 } = await import("path");
4745
+ const scriptPath = join3(tmpdir(), `trie-fix-${Date.now()}.sh`);
4746
+ await writeFile2(scriptPath, fixScript, "utf-8");
4747
+ await chmod(scriptPath, 493);
4568
4748
  await spawnTerminal({
4569
- command,
4749
+ command: `bash "${scriptPath}" && rm "${scriptPath}"`,
4570
4750
  cwd,
4571
4751
  title: `Fixing: ${file}`,
4572
4752
  keepOpen: true
@@ -4922,8 +5102,22 @@ Check the new terminal window to see the fix in progress.`;
4922
5102
 
4923
5103
  // src/cli/dashboard/views/ChatView.tsx
4924
5104
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
4925
- async function buildContext(workDir) {
5105
+ async function buildContext(workDir, dashboardState) {
4926
5106
  const parts = [];
5107
+ if (dashboardState?.agentInsights) {
5108
+ const recentNudges = dashboardState.agentInsights.filter((i) => i.type === "warning" && i.category === "quality" && !i.dismissed).slice(0, 5);
5109
+ if (recentNudges.length > 0) {
5110
+ parts.push("Recent goal violations (nudges):\n" + recentNudges.map((n) => {
5111
+ const fileMatch = n.message.match(/in ([^:]+):/);
5112
+ const goalMatch = n.message.match(/Goal "([^"]+)"/);
5113
+ const violationMatch = n.message.match(/: (.+?) \[/);
5114
+ return `- File: ${fileMatch?.[1] || "unknown"}
5115
+ Goal: ${goalMatch?.[1] || "unknown"}
5116
+ Violation: ${violationMatch?.[1] || n.message}
5117
+ Priority: ${n.priority}`;
5118
+ }).join("\n"));
5119
+ }
5120
+ }
4927
5121
  try {
4928
5122
  const guardianState = getGuardianState(workDir);
4929
5123
  await guardianState.load();
@@ -5003,10 +5197,17 @@ function chatHistoryToMessages(history) {
5003
5197
  var SYSTEM_PROMPT = `You are Trie, a code guardian assistant embedded in a terminal TUI.
5004
5198
  You have tools to take actions on the user's codebase \u2014 use them when the user asks you to check files, record incidents, give feedback, query decisions, or save checkpoints.
5005
5199
 
5006
- When the user mentions a goal violation or asks you to fix something detected by the watcher:
5007
- 1. Extract the file path, goal description, and violation details from context
5008
- 2. Use trie_fix_goal_violation to spawn Claude Code in a new terminal
5009
- 3. Claude Code will automatically fix the violation
5200
+ **IMPORTANT: When the user asks to "fix" or "remove" something related to goal violations:**
5201
+ 1. Check the "Recent goal violations (nudges)" section in the project context
5202
+ 2. Extract: file path, goal description, and violation details
5203
+ 3. IMMEDIATELY use trie_fix_goal_violation to spawn Claude Code in a new terminal
5204
+ 4. Do NOT ask for clarification if the context has the violation details
5205
+ 5. Do NOT try to search for files - use the violation info from nudges
5206
+
5207
+ Examples:
5208
+ - User: "fix the emoji violation" \u2192 Look for emoji violations in nudges, call trie_fix_goal_violation
5209
+ - User: "remove emojis from this project" \u2192 Check nudges for emoji violations, call trie_fix_goal_violation
5210
+ - User: "can you fix Dashboard.tsx" \u2192 Check if Dashboard.tsx has violations in nudges, call trie_fix_goal_violation
5010
5211
 
5011
5212
  Answer concisely. Reference specific files, decisions, and patterns when relevant.
5012
5213
  When you use a tool, briefly summarize what you did and what the result was.`;
@@ -5023,7 +5224,7 @@ function ChatView() {
5023
5224
  dispatch({ type: "SET_CHAT_LOADING", loading: true });
5024
5225
  try {
5025
5226
  const workDir = getWorkingDirectory(void 0, true);
5026
- const contextBlock = await buildContext(workDir);
5227
+ const contextBlock = await buildContext(workDir, state);
5027
5228
  const fullSystem = `${SYSTEM_PROMPT}
5028
5229
 
5029
5230
  Project context:
@@ -5095,7 +5296,7 @@ ${contextBlock}`;
5095
5296
  dispatch({ type: "SET_CHAT_LOADING", loading: false });
5096
5297
  loadingRef.current = false;
5097
5298
  }
5098
- }, [dispatch, messages]);
5299
+ }, [dispatch, messages, state]);
5099
5300
  useInput8((input, key) => {
5100
5301
  if (loading) return;
5101
5302
  if (key.return && inputBuffer.trim().length > 0) {
@@ -5312,6 +5513,7 @@ function DashboardApp({ onReady }) {
5312
5513
  dispatchRef.current({ type: "STREAM_UPDATE", update: { type: "raw_log", data: { time, level, message }, timestamp: Date.now() } });
5313
5514
  },
5314
5515
  onNudge: (nudge) => {
5516
+ console.error("[Dashboard] onNudge called:", { message: nudge.message, severity: nudge.severity, file: nudge.file });
5315
5517
  const action = { type: "SHOW_NOTIFICATION", message: nudge.message, severity: nudge.severity };
5316
5518
  if (nudge.file !== void 0) action.file = nudge.file;
5317
5519
  if (nudge.autoHideMs !== void 0) action.autoHideMs = nudge.autoHideMs;
@@ -5328,6 +5530,7 @@ function DashboardApp({ onReady }) {
5328
5530
  relatedIssues: [],
5329
5531
  dismissed: false
5330
5532
  };
5533
+ console.error("[Dashboard] Adding insight:", { id: insight.id, type: insight.type, category: insight.category, priority: insight.priority });
5331
5534
  dispatchRef.current({ type: "ADD_INSIGHTS", insights: [insight] });
5332
5535
  }
5333
5536
  }
@@ -5515,4 +5718,4 @@ export {
5515
5718
  handleCheckpointTool,
5516
5719
  InteractiveDashboard
5517
5720
  };
5518
- //# sourceMappingURL=chunk-EWVU7QUG.js.map
5721
+ //# sourceMappingURL=chunk-OZGDXRLD.js.map