winter-super-cli 2026.6.26 → 2026.6.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -5
- package/README.md +66 -0
- package/package.json +5 -1
- package/resources/local/gsap-skills/.claude-plugin/marketplace.json +20 -0
- package/resources/local/gsap-skills/.claude-plugin/plugin.json +6 -0
- package/resources/local/gsap-skills/.cursor-plugin/marketplace.json +13 -0
- package/resources/local/gsap-skills/.cursor-plugin/plugin.json +22 -0
- package/resources/local/gsap-skills/.github/copilot-instructions.md +17 -0
- package/resources/local/gsap-skills/.github/instructions/react.instructions.md +15 -0
- package/resources/local/gsap-skills/.github/instructions/scrolltrigger.instructions.md +18 -0
- package/resources/local/gsap-skills/AGENTS.md +27 -0
- package/resources/local/gsap-skills/CLAUDE.md +1 -0
- package/resources/local/gsap-skills/GEMINI.md +1 -0
- package/resources/local/gsap-skills/LICENSE +21 -0
- package/resources/local/gsap-skills/README.md +163 -0
- package/resources/local/gsap-skills/assets/gsap-green.svg +7 -0
- package/resources/local/gsap-skills/assets/gsap-icon-inverted.svg +15 -0
- package/resources/local/gsap-skills/assets/gsap-icon-square.svg +1 -0
- package/resources/local/gsap-skills/assets/gsap-white.svg +7 -0
- package/resources/local/gsap-skills/examples/README.md +29 -0
- package/resources/local/gsap-skills/examples/nuxt/app/app.vue +3 -0
- package/resources/local/gsap-skills/examples/nuxt/app/composables/useGSAP.ts +91 -0
- package/resources/local/gsap-skills/examples/nuxt/app/pages/index.vue +55 -0
- package/resources/local/gsap-skills/examples/nuxt/nuxt.config.ts +4 -0
- package/resources/local/gsap-skills/examples/nuxt/package.json +18 -0
- package/resources/local/gsap-skills/examples/react/App.jsx +46 -0
- package/resources/local/gsap-skills/examples/react/index.html +12 -0
- package/resources/local/gsap-skills/examples/react/main.jsx +9 -0
- package/resources/local/gsap-skills/examples/react/package.json +21 -0
- package/resources/local/gsap-skills/examples/react/vite.config.js +7 -0
- package/resources/local/gsap-skills/examples/vanilla/index.html +33 -0
- package/resources/local/gsap-skills/examples/vanilla/main.js +36 -0
- package/resources/local/gsap-skills/examples/vue/app.vue +47 -0
- package/resources/local/gsap-skills/examples/vue/index.html +15 -0
- package/resources/local/gsap-skills/examples/vue/main.js +9 -0
- package/resources/local/gsap-skills/examples/vue/package.json +19 -0
- package/resources/local/gsap-skills/examples/vue/vite.config.js +7 -0
- package/resources/local/gsap-skills/skills/gsap-core/SKILL.md +254 -0
- package/resources/local/gsap-skills/skills/gsap-frameworks/SKILL.md +266 -0
- package/resources/local/gsap-skills/skills/gsap-performance/SKILL.md +79 -0
- package/resources/local/gsap-skills/skills/gsap-plugins/SKILL.md +433 -0
- package/resources/local/gsap-skills/skills/gsap-react/SKILL.md +136 -0
- package/resources/local/gsap-skills/skills/gsap-scrolltrigger/SKILL.md +296 -0
- package/resources/local/gsap-skills/skills/gsap-timeline/SKILL.md +107 -0
- package/resources/local/gsap-skills/skills/gsap-utils/SKILL.md +284 -0
- package/resources/local/gsap-skills/skills/llms.txt +39 -0
- package/resources/local/hermes-agent-core/AGENTS.md +1132 -0
- package/resources/local/hermes-agent-core/LICENSE +21 -0
- package/resources/local/hermes-agent-core/README.md +215 -0
- package/resources/local/hermes-agent-core/docs/2026-05-07-s6-overlay-dynamic-subagent-gateways.md +434 -0
- package/resources/local/hermes-agent-core/hermes-already-has-routines.md +160 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1021 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +277 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +57 -0
- package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
- package/resources/local/hermes-agent-core/skills/github/DESCRIPTION.md +3 -0
- package/resources/local/hermes-agent-core/skills/github/codebase-inspection/SKILL.md +116 -0
- package/resources/local/hermes-agent-core/skills/github/github-auth/SKILL.md +247 -0
- package/resources/local/hermes-agent-core/skills/github/github-auth/scripts/gh-env.sh +66 -0
- package/resources/local/hermes-agent-core/skills/github/github-code-review/SKILL.md +481 -0
- package/resources/local/hermes-agent-core/skills/github/github-code-review/references/review-output-template.md +74 -0
- package/resources/local/hermes-agent-core/skills/github/github-issues/SKILL.md +370 -0
- package/resources/local/hermes-agent-core/skills/github/github-issues/templates/bug-report.md +35 -0
- package/resources/local/hermes-agent-core/skills/github/github-issues/templates/feature-request.md +31 -0
- package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/SKILL.md +367 -0
- package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
- package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
- package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
- package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
- package/resources/local/hermes-agent-core/skills/github/github-repo-management/SKILL.md +516 -0
- package/resources/local/hermes-agent-core/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
- package/resources/local/hermes-agent-core/skills/mcp/DESCRIPTION.md +3 -0
- package/resources/local/hermes-agent-core/skills/mcp/native-mcp/SKILL.md +357 -0
- package/resources/local/hermes-agent-core/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
- package/resources/local/hermes-agent-core/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
- package/resources/local/hermes-agent-core/skills/software-development/hermes-s6-container-supervision/SKILL.md +176 -0
- package/resources/local/hermes-agent-core/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
- package/resources/local/hermes-agent-core/skills/software-development/plan/SKILL.md +58 -0
- package/resources/local/hermes-agent-core/skills/software-development/python-debugpy/SKILL.md +375 -0
- package/resources/local/hermes-agent-core/skills/software-development/requesting-code-review/SKILL.md +280 -0
- package/resources/local/hermes-agent-core/skills/software-development/spike/SKILL.md +197 -0
- package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/SKILL.md +352 -0
- package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
- package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
- package/resources/local/hermes-agent-core/skills/software-development/systematic-debugging/SKILL.md +367 -0
- package/resources/local/hermes-agent-core/skills/software-development/test-driven-development/SKILL.md +343 -0
- package/resources/local/hermes-agent-core/skills/software-development/writing-plans/SKILL.md +297 -0
- package/resources/local/manifest.json +12 -0
- package/rule.md +2 -0
- package/scripts/audit-pack.js +5 -0
- package/scripts/smoke-browser.js +53 -0
- package/scripts/smoke-package.js +38 -4
- package/skill.md +36 -4
- package/skills/gsap.md +26 -0
- package/skills/hermes-agent.md +17 -0
- package/src/agent/agent-definitions.js +4 -4
- package/src/agent/runtime.js +179 -5
- package/src/agent/subagent-child.js +44 -0
- package/src/ai/capability-scorecard.js +193 -14
- package/src/ai/hermes-core.js +77 -0
- package/src/ai/model-capabilities.js +42 -2
- package/src/ai/prompts/system-prompt.js +16 -2
- package/src/ai/small-model-amplifier.js +35 -7
- package/src/ai/workflow-selector.js +22 -1
- package/src/cli/commands.js +21 -1
- package/src/cli/config.js +42 -4
- package/src/cli/context-loader.js +253 -9
- package/src/cli/conversation-format.js +5 -0
- package/src/cli/input-controller.js +79 -10
- package/src/cli/prompt-builder.js +45 -8
- package/src/cli/repl-commands.js +115 -0
- package/src/cli/repl.js +147 -86
- package/src/cli/slash-commands.js +3 -1
- package/src/cli/tui.js +133 -37
- package/src/mcp/client.js +46 -5
- package/src/tools/agent.js +316 -25
- package/src/tools/executor.js +310 -9
- package/src/tools/permission.js +20 -17
- package/winter.d.ts +112 -10
package/src/cli/tui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { terminalWidth, visibleWidth
|
|
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}
|
|
43
|
-
status: `${c.bright}${c.cyan}WINTER${c.reset} ${c.dim}
|
|
44
|
-
hint: `${c.dim}@file${c.reset} attach
|
|
45
|
-
prompt: `${c.bright}${c.green}winter${c.reset} ${c.dim}
|
|
46
|
-
bottom: `${c.dim}
|
|
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
|
|
64
|
-
const
|
|
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
|
|
149
|
+
`${white}Winter dashboard${reset} ${dim}Hermes-style agent core: skills, memory, tools, subagents, gateway discipline.${reset}`,
|
|
72
150
|
'',
|
|
73
|
-
|
|
151
|
+
statusBar,
|
|
74
152
|
'',
|
|
75
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
109
|
-
`${c.brightGreen}
|
|
110
|
-
`${c.brightGreen}
|
|
111
|
-
`${c.brightGreen}
|
|
112
|
-
`${c.brightGreen}
|
|
113
|
-
`${c.brightGreen}
|
|
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
|
|
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}
|
|
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}
|
|
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}
|
|
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
|
|
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
|
-
|
|
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);
|