winter-super-cli 2026.6.26 → 2026.6.28

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.
Files changed (122) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/README.md +66 -0
  3. package/package.json +5 -1
  4. package/resources/local/gsap-skills/.claude-plugin/marketplace.json +20 -0
  5. package/resources/local/gsap-skills/.claude-plugin/plugin.json +6 -0
  6. package/resources/local/gsap-skills/.cursor-plugin/marketplace.json +13 -0
  7. package/resources/local/gsap-skills/.cursor-plugin/plugin.json +22 -0
  8. package/resources/local/gsap-skills/.github/copilot-instructions.md +17 -0
  9. package/resources/local/gsap-skills/.github/instructions/react.instructions.md +15 -0
  10. package/resources/local/gsap-skills/.github/instructions/scrolltrigger.instructions.md +18 -0
  11. package/resources/local/gsap-skills/AGENTS.md +27 -0
  12. package/resources/local/gsap-skills/CLAUDE.md +1 -0
  13. package/resources/local/gsap-skills/GEMINI.md +1 -0
  14. package/resources/local/gsap-skills/LICENSE +21 -0
  15. package/resources/local/gsap-skills/README.md +163 -0
  16. package/resources/local/gsap-skills/assets/gsap-green.svg +7 -0
  17. package/resources/local/gsap-skills/assets/gsap-icon-inverted.svg +15 -0
  18. package/resources/local/gsap-skills/assets/gsap-icon-square.svg +1 -0
  19. package/resources/local/gsap-skills/assets/gsap-white.svg +7 -0
  20. package/resources/local/gsap-skills/examples/README.md +29 -0
  21. package/resources/local/gsap-skills/examples/nuxt/app/app.vue +3 -0
  22. package/resources/local/gsap-skills/examples/nuxt/app/composables/useGSAP.ts +91 -0
  23. package/resources/local/gsap-skills/examples/nuxt/app/pages/index.vue +55 -0
  24. package/resources/local/gsap-skills/examples/nuxt/nuxt.config.ts +4 -0
  25. package/resources/local/gsap-skills/examples/nuxt/package.json +18 -0
  26. package/resources/local/gsap-skills/examples/react/App.jsx +46 -0
  27. package/resources/local/gsap-skills/examples/react/index.html +12 -0
  28. package/resources/local/gsap-skills/examples/react/main.jsx +9 -0
  29. package/resources/local/gsap-skills/examples/react/package.json +21 -0
  30. package/resources/local/gsap-skills/examples/react/vite.config.js +7 -0
  31. package/resources/local/gsap-skills/examples/vanilla/index.html +33 -0
  32. package/resources/local/gsap-skills/examples/vanilla/main.js +36 -0
  33. package/resources/local/gsap-skills/examples/vue/app.vue +47 -0
  34. package/resources/local/gsap-skills/examples/vue/index.html +15 -0
  35. package/resources/local/gsap-skills/examples/vue/main.js +9 -0
  36. package/resources/local/gsap-skills/examples/vue/package.json +19 -0
  37. package/resources/local/gsap-skills/examples/vue/vite.config.js +7 -0
  38. package/resources/local/gsap-skills/skills/gsap-core/SKILL.md +254 -0
  39. package/resources/local/gsap-skills/skills/gsap-frameworks/SKILL.md +266 -0
  40. package/resources/local/gsap-skills/skills/gsap-performance/SKILL.md +79 -0
  41. package/resources/local/gsap-skills/skills/gsap-plugins/SKILL.md +433 -0
  42. package/resources/local/gsap-skills/skills/gsap-react/SKILL.md +136 -0
  43. package/resources/local/gsap-skills/skills/gsap-scrolltrigger/SKILL.md +296 -0
  44. package/resources/local/gsap-skills/skills/gsap-timeline/SKILL.md +107 -0
  45. package/resources/local/gsap-skills/skills/gsap-utils/SKILL.md +284 -0
  46. package/resources/local/gsap-skills/skills/llms.txt +39 -0
  47. package/resources/local/hermes-agent-core/AGENTS.md +1132 -0
  48. package/resources/local/hermes-agent-core/LICENSE +21 -0
  49. package/resources/local/hermes-agent-core/README.md +215 -0
  50. package/resources/local/hermes-agent-core/docs/2026-05-07-s6-overlay-dynamic-subagent-gateways.md +434 -0
  51. package/resources/local/hermes-agent-core/hermes-already-has-routines.md +160 -0
  52. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
  53. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
  54. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
  55. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1021 -0
  56. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +277 -0
  57. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +57 -0
  58. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
  59. package/resources/local/hermes-agent-core/skills/github/DESCRIPTION.md +3 -0
  60. package/resources/local/hermes-agent-core/skills/github/codebase-inspection/SKILL.md +116 -0
  61. package/resources/local/hermes-agent-core/skills/github/github-auth/SKILL.md +247 -0
  62. package/resources/local/hermes-agent-core/skills/github/github-auth/scripts/gh-env.sh +66 -0
  63. package/resources/local/hermes-agent-core/skills/github/github-code-review/SKILL.md +481 -0
  64. package/resources/local/hermes-agent-core/skills/github/github-code-review/references/review-output-template.md +74 -0
  65. package/resources/local/hermes-agent-core/skills/github/github-issues/SKILL.md +370 -0
  66. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/bug-report.md +35 -0
  67. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/feature-request.md +31 -0
  68. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/SKILL.md +367 -0
  69. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
  70. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
  71. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
  72. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
  73. package/resources/local/hermes-agent-core/skills/github/github-repo-management/SKILL.md +516 -0
  74. package/resources/local/hermes-agent-core/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
  75. package/resources/local/hermes-agent-core/skills/mcp/DESCRIPTION.md +3 -0
  76. package/resources/local/hermes-agent-core/skills/mcp/native-mcp/SKILL.md +357 -0
  77. package/resources/local/hermes-agent-core/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
  78. package/resources/local/hermes-agent-core/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
  79. package/resources/local/hermes-agent-core/skills/software-development/hermes-s6-container-supervision/SKILL.md +176 -0
  80. package/resources/local/hermes-agent-core/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
  81. package/resources/local/hermes-agent-core/skills/software-development/plan/SKILL.md +58 -0
  82. package/resources/local/hermes-agent-core/skills/software-development/python-debugpy/SKILL.md +375 -0
  83. package/resources/local/hermes-agent-core/skills/software-development/requesting-code-review/SKILL.md +280 -0
  84. package/resources/local/hermes-agent-core/skills/software-development/spike/SKILL.md +197 -0
  85. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/SKILL.md +352 -0
  86. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
  87. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
  88. package/resources/local/hermes-agent-core/skills/software-development/systematic-debugging/SKILL.md +367 -0
  89. package/resources/local/hermes-agent-core/skills/software-development/test-driven-development/SKILL.md +343 -0
  90. package/resources/local/hermes-agent-core/skills/software-development/writing-plans/SKILL.md +297 -0
  91. package/resources/local/manifest.json +12 -0
  92. package/rule.md +2 -0
  93. package/scripts/audit-pack.js +5 -0
  94. package/scripts/smoke-browser.js +53 -0
  95. package/scripts/smoke-package.js +38 -4
  96. package/skill.md +36 -4
  97. package/skills/gsap.md +26 -0
  98. package/skills/hermes-agent.md +17 -0
  99. package/src/agent/agent-definitions.js +4 -4
  100. package/src/agent/runtime.js +206 -5
  101. package/src/agent/subagent-child.js +44 -0
  102. package/src/ai/capability-scorecard.js +193 -14
  103. package/src/ai/hermes-core.js +77 -0
  104. package/src/ai/model-capabilities.js +42 -2
  105. package/src/ai/prompts/system-prompt.js +16 -2
  106. package/src/ai/small-model-amplifier.js +35 -7
  107. package/src/ai/workflow-selector.js +22 -1
  108. package/src/cli/commands.js +21 -1
  109. package/src/cli/config.js +42 -4
  110. package/src/cli/context-loader.js +253 -9
  111. package/src/cli/conversation-format.js +5 -0
  112. package/src/cli/input-controller.js +79 -10
  113. package/src/cli/prompt-builder.js +45 -8
  114. package/src/cli/repl-commands.js +123 -2
  115. package/src/cli/repl.js +183 -87
  116. package/src/cli/slash-commands.js +3 -1
  117. package/src/cli/tui.js +133 -37
  118. package/src/mcp/client.js +46 -5
  119. package/src/tools/agent.js +316 -25
  120. package/src/tools/executor.js +314 -11
  121. package/src/tools/permission.js +20 -17
  122. package/winter.d.ts +112 -10
package/src/cli/tui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { terminalWidth, visibleWidth, wrapText } from './terminal-ui.js';
1
+ import { terminalWidth, visibleWidth } from './terminal-ui.js';
2
2
 
3
3
  const WINTER_LOGO = [
4
4
  ' __ __ _____ _ _ _______ ______ _____ ',
@@ -14,15 +14,90 @@ function basenameFromPath(filePath, fallback = 'project') {
14
14
  return parts[parts.length - 1] || fallback;
15
15
  }
16
16
 
17
+ function stripAnsi(text = '') {
18
+ return String(text || '').replace(/\x1b\[[0-9;]*m/g, '');
19
+ }
20
+
21
+ function clampText(text = '', max = 72) {
22
+ const value = String(text || '');
23
+ if (visibleWidth(value) <= max) return value;
24
+ const plain = stripAnsi(value);
25
+ return `${plain.slice(0, Math.max(0, max - 3))}...`;
26
+ }
27
+
28
+ function formatCount(value, fallback = 0) {
29
+ const number = Number(value ?? fallback);
30
+ return Number.isFinite(number) ? number : fallback;
31
+ }
32
+
33
+ function summarizeTools(events = []) {
34
+ if (!Array.isArray(events) || events.length === 0) return 'idle';
35
+ return events.slice(-4).map(event => {
36
+ const name = event.toolName || event.tool || event.name || 'tool';
37
+ const ok = event.success === false ? 'fail' : 'ok';
38
+ return `${name}:${ok}`;
39
+ }).join(' ');
40
+ }
41
+
42
+ function summarizeHistory(entries = []) {
43
+ if (!Array.isArray(entries) || entries.length === 0) return [];
44
+ return entries.slice(-4).map(entry => {
45
+ const role = entry.role === 'assistant' ? 'Winter' : entry.role === 'user' ? 'You' : entry.role || 'event';
46
+ const content = typeof entry.content === 'string'
47
+ ? entry.content
48
+ : Array.isArray(entry.content)
49
+ ? entry.content.map(part => part?.text || part?.content || '').join(' ')
50
+ : entry.text || '';
51
+ const compact = clampText(content.replace(/\s+/g, ' ').trim(), 78);
52
+ return compact ? `${role}: ${compact}` : '';
53
+ }).filter(Boolean);
54
+ }
55
+
56
+ function formatRecentHistoryLine(entry) {
57
+ if (typeof entry === 'string') return entry;
58
+ if (!entry || typeof entry !== 'object') return '';
59
+ const role = entry.role === 'assistant' ? 'Winter' : entry.role === 'user' ? 'You' : entry.role || 'event';
60
+ const content = typeof entry.content === 'string'
61
+ ? entry.content
62
+ : Array.isArray(entry.content)
63
+ ? entry.content.map(part => part?.text || part?.content || '').join(' ')
64
+ : entry.text || '';
65
+ const compact = clampText(String(content || '').replace(/\s+/g, ' ').trim(), 78);
66
+ return compact ? `${role}: ${compact}` : '';
67
+ }
68
+
69
+ function sectionLine(label, value, c = {}) {
70
+ return `${c.dim || ''}${label.padEnd(10)}${c.reset || ''} ${value}`;
71
+ }
72
+
17
73
  export function buildTuiSnapshot(repl = {}) {
18
74
  const provider = repl.ai?.getActiveProvider?.() || 'provider';
19
75
  const model = repl.ai?.providers?.[provider]?.model || 'model';
76
+ const context = repl.session?.getContext?.() || {};
77
+ const history = repl.session?.getHistory?.() || [];
78
+ const toolEvents = repl.session?.getToolEvents?.() || [];
79
+ const codebaseStats = repl.codebaseSearcher?.indexer?.getStats?.() || {};
80
+ const activeSkills = Array.isArray(context.activeSkills?.value)
81
+ ? context.activeSkills.value
82
+ : Array.isArray(context.activeSkills)
83
+ ? context.activeSkills
84
+ : [];
85
+
20
86
  return {
21
87
  provider,
22
88
  model,
89
+ modelTier: repl.ai?._modelTier || repl.getActiveModelTier?.() || 'unknown',
23
90
  projectPath: repl.projectPath || process.cwd(),
24
91
  sessionShort: String(repl.session?.getSessionId?.() || 'session').slice(0, 8),
25
92
  projectName: basenameFromPath(repl.projectPath || process.cwd()),
93
+ statusText: repl.isProcessing ? 'running' : 'ready',
94
+ queueText: Array.isArray(repl.taskQueue) && repl.taskQueue.length > 0 ? `${repl.taskQueue.length} queued` : 'empty',
95
+ codebaseFiles: formatCount(codebaseStats.totalFiles),
96
+ codebaseChunks: formatCount(codebaseStats.totalChunks),
97
+ toolSummary: summarizeTools(toolEvents),
98
+ recentHistory: summarizeHistory(history),
99
+ activeSkills: activeSkills.slice(0, 8),
100
+ hermesCore: true,
26
101
  };
27
102
  }
28
103
 
@@ -39,40 +114,57 @@ export function renderInputPanel(snapshot, {
39
114
  : snapshot.provider || snapshot.model || 'model';
40
115
 
41
116
  return {
42
- top: `${c.dim}┌${''.repeat(innerWidth + 2)}┐${c.reset}`,
43
- status: `${c.bright}${c.cyan}WINTER${c.reset} ${c.dim}·${c.reset} ${projectName} ${c.dim}·${c.reset} ${providerModel}`,
44
- hint: `${c.dim}@file${c.reset} attach · ${c.dim}!cmd${c.reset} bash · ${c.dim}^V img${c.reset} paste`,
45
- prompt: `${c.bright}${c.green}winter${c.reset} ${c.dim}›${c.reset} `,
46
- bottom: `${c.dim}└${''.repeat(innerWidth + 2)}┘${c.reset}`,
117
+ top: `${c.dim}+${'-'.repeat(innerWidth + 2)}+${c.reset}`,
118
+ status: `${c.bright}${c.cyan}WINTER${c.reset} ${c.dim}.${c.reset} ${projectName} ${c.dim}.${c.reset} ${providerModel}`,
119
+ hint: `${c.dim}@file${c.reset} attach . ${c.dim}!cmd${c.reset} bash . ${c.dim}Ctrl+V${c.reset}/${c.dim}^V img${c.reset}`,
120
+ prompt: `${c.bright}${c.green}winter${c.reset} ${c.dim}>${c.reset} `,
121
+ bottom: `${c.dim}+${'-'.repeat(innerWidth + 2)}+${c.reset}`,
47
122
  };
48
123
  }
49
124
 
50
125
  export function renderLandingTui(snapshot, { colors } = {}) {
51
126
  const c = colors || {};
52
127
  const W = Math.max(60, Math.min(process.stdout.columns || 80, 140));
53
-
128
+
54
129
  const bright = c.bright || '\x1b[1m';
55
130
  const green = c.brightGreen || c.green || '\x1b[92m';
56
131
  const white = c.white || '\x1b[37m';
57
132
  const dim = c.dim || '\x1b[2m';
58
133
  const reset = c.reset || '\x1b[0m';
59
- const bgBlue = '\x1b[48;5;236m';
134
+ const bgBlue = '\x1b[48;5;236m';
60
135
 
61
136
  const logoLines = WINTER_LOGO.map(line => `${bright}${green}${line}${reset}`);
62
-
63
- const leftStatus = ` ${snapshot.provider} · ${snapshot.model} `;
64
- const rightStatus = ` ESC×2 exit · /help `;
65
- const padding = Math.max(0, W - leftStatus.length - rightStatus.length);
137
+ const leftStatus = ` ${snapshot.provider} / ${snapshot.model} `;
138
+ const rightStatus = ' /tui /help /doctor tools ';
139
+ const padding = Math.max(0, W - stripAnsi(leftStatus).length - stripAnsi(rightStatus).length);
66
140
  const statusBar = `${bgBlue}${white}${leftStatus}${' '.repeat(padding)}${rightStatus}${reset}`;
141
+ const recent = snapshot.recentHistory?.length
142
+ ? snapshot.recentHistory.map(formatRecentHistoryLine).filter(Boolean).map(line => `${dim}- ${line}${reset}`)
143
+ : [`${dim}- No recent messages loaded.${reset}`];
144
+ const skills = snapshot.activeSkills?.length ? snapshot.activeSkills.join(', ') : 'coding, debug, test';
67
145
 
68
146
  return [
69
147
  ...logoLines,
70
148
  '',
71
- `${white}Winter will run commands on your behalf to help you build.${reset}`,
149
+ `${white}Winter dashboard${reset} ${dim}Hermes-style agent core: skills, memory, tools, subagents, gateway discipline.${reset}`,
72
150
  '',
73
- `${white}Directory${reset} ${dim}${snapshot.projectPath}${reset}`,
151
+ statusBar,
74
152
  '',
75
- statusBar
153
+ `${bgBlue}${white} STATUS ${reset}`,
154
+ sectionLine('Project', `${snapshot.projectName} ${dim}${snapshot.projectPath}${reset}`, c),
155
+ sectionLine('Model', `${snapshot.provider}/${snapshot.model} ${dim}${snapshot.modelTier || 'unknown'}${reset}`, c),
156
+ sectionLine('Session', `${snapshot.sessionShort} ${dim}${snapshot.statusText || 'ready'} . queue ${snapshot.queueText || 'empty'}${reset}`, c),
157
+ sectionLine('Codebase', `${snapshot.codebaseFiles || 0} files, ${snapshot.codebaseChunks || 0} chunks`, c),
158
+ sectionLine('Tools', snapshot.toolSummary || 'idle', c),
159
+ '',
160
+ `${bgBlue}${white} AGENT CORE ${reset}`,
161
+ sectionLine('Hermes', 'self-improve . skill lifecycle . session search . subagents . automation', c),
162
+ sectionLine('Skills', skills, c),
163
+ sectionLine('Gateway', 'MCP diagnostics . timeout handling . concrete tool evidence', c),
164
+ '',
165
+ `${bgBlue}${white} RECENT ${reset}`,
166
+ ...recent,
167
+ renderCommandCenter({ colors: c, width: W }),
76
168
  ].join('\n');
77
169
  }
78
170
 
@@ -84,11 +176,11 @@ export function renderStatusPanel(snapshot, { colors, title = 'Status' } = {}) {
84
176
  return [
85
177
  '',
86
178
  header,
87
- `${c.dim}Project :${c.reset} ${snapshot.projectName} (${snapshot.projectPath})`,
88
- `${c.dim}Model :${c.reset} ${snapshot.provider}/${snapshot.model} (${snapshot.modelTier})`,
89
- `${c.dim}Session :${c.reset} ${snapshot.sessionShort} | State: ${snapshot.statusText}`,
90
- `${c.dim}Codebase:${c.reset} ${snapshot.codebaseFiles} files, ${snapshot.codebaseChunks} chunks`,
91
- `${c.dim}Activity:${c.reset} ${snapshot.toolSummary || 'idle'}`,
179
+ sectionLine('Project', `${snapshot.projectName} (${snapshot.projectPath})`, c),
180
+ sectionLine('Model', `${snapshot.provider}/${snapshot.model} (${snapshot.modelTier || 'unknown'})`, c),
181
+ sectionLine('Session', `${snapshot.sessionShort} | ${snapshot.statusText || 'ready'} | queue ${snapshot.queueText || 'empty'}`, c),
182
+ sectionLine('Codebase', `${snapshot.codebaseFiles || 0} files, ${snapshot.codebaseChunks || 0} chunks`, c),
183
+ sectionLine('Activity', snapshot.toolSummary || 'idle', c),
92
184
  ''
93
185
  ].join('\n');
94
186
  }
@@ -101,16 +193,20 @@ export function renderCommandCenter({ colors, width = 80 } = {}) {
101
193
  const c = colors || {};
102
194
  const bgBlue = '\x1b[48;5;236m';
103
195
  const header = `${bgBlue}${c.white} COMMAND CENTER ${c.reset}`;
104
-
196
+ const hint = `${c.dim}Slash commands share one workflow: inspect real state, use tools, verify, then report evidence.${c.reset}`;
197
+
105
198
  return [
106
199
  '',
107
200
  header,
108
- `${c.brightGreen}B${c.reset} ${c.bright}${c.cyan}Build ${c.reset} ${c.dim}/auto /debug /tdd /swe /composer${c.reset}`,
109
- `${c.brightGreen}I${c.reset} ${c.bright}${c.cyan}Inspect${c.reset} ${c.dim}/read /grep /glob /search /context${c.reset}`,
110
- `${c.brightGreen}M${c.reset} ${c.bright}${c.cyan}Model ${c.reset} ${c.dim}/provider /providers /model /models /scorecard${c.reset}`,
111
- `${c.brightGreen}K${c.reset} ${c.bright}${c.cyan}Memory ${c.reset} ${c.dim}/remember /memories /memory-vault /compress${c.reset}`,
112
- `${c.brightGreen}V${c.reset} ${c.bright}${c.cyan}Visual ${c.reset} ${c.dim}/image /paste ^V img /designs /page-agent${c.reset}`,
113
- `${c.brightGreen}S${c.reset} ${c.bright}${c.cyan}System ${c.reset} ${c.dim}/doctor full /stats /permissions /mcp /help${c.reset}`,
201
+ hint,
202
+ `${c.brightGreen}B${c.reset} ${c.bright}${c.cyan}Build ${c.reset} ${c.dim}/auto /debug /tdd /swe /composer /plan fetch${c.reset}`,
203
+ `${c.brightGreen}I${c.reset} ${c.bright}${c.cyan}Inspect ${c.reset} ${c.dim}/read /grep /glob /search /context /doctor tools${c.reset}`,
204
+ `${c.brightGreen}M${c.reset} ${c.bright}${c.cyan}Model ${c.reset} ${c.dim}/provider /providers /model /models /scorecard${c.reset}`,
205
+ `${c.brightGreen}K${c.reset} ${c.bright}${c.cyan}Memory ${c.reset} ${c.dim}/remember /memories /memory-vault /compress /stats${c.reset}`,
206
+ `${c.brightGreen}A${c.reset} ${c.bright}${c.cyan}Agent ${c.reset} ${c.dim}/skills hermes-agent /mcp /resources /agent /parallel${c.reset}`,
207
+ `${c.brightGreen}G${c.reset} ${c.bright}${c.cyan}Gateway ${c.reset} ${c.dim}/mcp list /mcp tools chrome-devtools /permissions list${c.reset}`,
208
+ `${c.brightGreen}V${c.reset} ${c.bright}${c.cyan}Visual ${c.reset} ${c.dim}/image /paste Ctrl+V /designs /page-agent /htmlfx${c.reset}`,
209
+ `${c.brightGreen}S${c.reset} ${c.bright}${c.cyan}System ${c.reset} ${c.dim}/doctor full /stats /resources /help${c.reset}`,
114
210
  ''
115
211
  ].join('\n');
116
212
  }
@@ -119,16 +215,16 @@ export function renderSplitPanel({ title, left = [], right = [], colors, width =
119
215
  const c = colors || {};
120
216
  const bgBlue = '\x1b[48;5;236m';
121
217
  const header = `${bgBlue}${c.white} ${(title || 'Info').toUpperCase()} ${c.reset}`;
122
-
218
+
123
219
  const innerWidth = Math.max(56, width - 4);
124
220
  const leftWidth = Math.floor(innerWidth * 0.5);
125
-
221
+
126
222
  const rows = [];
127
223
  const count = Math.max(left.length, right.length);
128
224
  for (let i = 0; i < count; i++) {
129
225
  const lText = String(left[i] || '');
130
226
  const rText = String(right[i] || '');
131
- const lPlain = lText.replace(/\x1b\[[0-9;]*m/g, '');
227
+ const lPlain = stripAnsi(lText);
132
228
  const lPad = Math.max(0, leftWidth - lPlain.length);
133
229
  rows.push(`${lText}${' '.repeat(lPad)} ${rText}`);
134
230
  }
@@ -145,7 +241,7 @@ export function renderHistoryPanel(entries = [], { colors, title = 'Recent Sessi
145
241
  const c = colors || {};
146
242
  const bgBlue = '\x1b[48;5;236m';
147
243
  const header = `${bgBlue}${c.white} ${title.toUpperCase()} ${c.reset}`;
148
-
244
+
149
245
  const body = entries.length > 0
150
246
  ? entries.map(entry => {
151
247
  const role = entry.role === 'assistant' ? 'Winter' : entry.role === 'user' ? 'You' : entry.role || 'event';
@@ -166,7 +262,7 @@ export function renderAssistantPanel({ content = '', footer = '', colors, title
166
262
  const c = colors || {};
167
263
  const bgBlue = '\x1b[48;5;236m';
168
264
  const header = `${bgBlue}${c.white} ${title.toUpperCase()} ${c.reset}`;
169
-
265
+
170
266
  const parts = [];
171
267
  if (title) parts.push('', header);
172
268
  if (content) parts.push(content);
@@ -176,15 +272,15 @@ export function renderAssistantPanel({ content = '', footer = '', colors, title
176
272
 
177
273
  export function renderToolPanel({ toolName = 'Tool', summary = '', success = true, colors } = {}) {
178
274
  const c = colors || {};
179
- const status = success ? `${c.brightGreen}✓${c.reset}` : `${c.red}✖${c.reset}`;
180
-
275
+ const status = success ? `${c.brightGreen}OK${c.reset}` : `${c.red}FAIL${c.reset}`;
276
+
181
277
  if (!summary.includes('\n')) {
182
- return `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${summary}${c.reset}`;
278
+ return `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}. ${summary}${c.reset}`;
183
279
  }
184
280
 
185
281
  const lines = summary.split('\n');
186
282
  const firstLine = lines.shift();
187
-
283
+
188
284
  const formattedRest = lines.map(line => {
189
285
  if (line.startsWith('+')) return ` ${c.green}${line}${c.reset}`;
190
286
  if (line.startsWith('-')) return ` ${c.red}${line}${c.reset}`;
@@ -192,7 +288,7 @@ export function renderToolPanel({ toolName = 'Tool', summary = '', success = tru
192
288
  return ` ${c.dim}${line}${c.reset}`;
193
289
  }).join('\n');
194
290
 
195
- let output = `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${firstLine}${c.reset}`;
291
+ let output = `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}. ${firstLine}${c.reset}`;
196
292
  if (formattedRest) output += `\n${formattedRest}`;
197
293
  return output;
198
294
  }
package/src/mcp/client.js CHANGED
@@ -1,7 +1,22 @@
1
- import { spawn } from 'child_process';
2
- import { encodeMcpMessage, decodeMcpMessages, createNotification, createRequest } from './protocol.js';
3
-
4
- export class MCPClient {
1
+ import { spawn } from 'child_process';
2
+ import { encodeMcpMessage, decodeMcpMessages, createNotification, createRequest } from './protocol.js';
3
+
4
+ export class MCPRequestTimeoutError extends Error {
5
+ constructor({ method, timeoutMs, requestId, serverName, lastStderr } = {}) {
6
+ const serverText = serverName ? ` on ${serverName}` : '';
7
+ const stderrText = lastStderr ? `; stderr: ${lastStderr}` : '';
8
+ super(`MCP request timed out after ${timeoutMs}ms: ${method}${serverText}${stderrText}`);
9
+ this.name = 'MCPRequestTimeoutError';
10
+ this.code = 'MCP_REQUEST_TIMEOUT';
11
+ this.method = method;
12
+ this.timeoutMs = timeoutMs;
13
+ this.requestId = requestId;
14
+ this.serverName = serverName;
15
+ this.lastStderr = lastStderr;
16
+ }
17
+ }
18
+
19
+ export class MCPClient {
5
20
  constructor(serverConfig = {}) {
6
21
  this.serverConfig = serverConfig;
7
22
  this.process = null;
@@ -94,7 +109,15 @@ export class MCPClient {
94
109
  return new Promise((resolve, reject) => {
95
110
  const timer = setTimeout(() => {
96
111
  this.pending.delete(id);
97
- reject(new Error(`MCP request timed out: ${method}`));
112
+ const error = new MCPRequestTimeoutError({
113
+ method,
114
+ timeoutMs: this.requestTimeoutMs,
115
+ requestId: id,
116
+ serverName: this.serverConfig.name,
117
+ lastStderr: this.lastStderr,
118
+ });
119
+ reject(error);
120
+ this.closeAfterTimeout(error);
98
121
  }, this.requestTimeoutMs);
99
122
  this.pending.set(id, { resolve, reject, timer });
100
123
  this.process.stdin.write(packet, error => {
@@ -138,6 +161,24 @@ export class MCPClient {
138
161
  }
139
162
  }
140
163
 
164
+ closeAfterTimeout(error) {
165
+ this.rejectAllPending(error || new Error('MCP server timed out'));
166
+ if (!this.process) return;
167
+ const processRef = this.process;
168
+ this.process = null;
169
+ this.initialized = false;
170
+ try {
171
+ processRef.stdin?.destroy?.();
172
+ } catch {
173
+ // Best-effort cleanup after a timed-out request.
174
+ }
175
+ try {
176
+ processRef.kill();
177
+ } catch {
178
+ // Process may already be gone.
179
+ }
180
+ }
181
+
141
182
  rejectAllPending(error) {
142
183
  for (const pending of this.pending.values()) {
143
184
  clearTimeout(pending.timer);