winter-super-cli 2026.6.7 → 2026.6.9
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/package.json +1 -1
- package/src/agent/runtime.js +4 -2
- package/src/ai/benchmark.js +5 -5
- package/src/ai/model-capabilities.js +1 -1
- package/src/ai/orchestrator.js +6 -6
- package/src/ai/providers.js +20 -8
- package/src/cache/system.js +1 -1
- package/src/cli/at-context.js +1 -1
- package/src/cli/commands.js +1 -1
- package/src/cli/composer.js +2 -2
- package/src/cli/config.js +1 -1
- package/src/cli/diff-view.js +89 -33
- package/src/cli/ecc.js +2 -2
- package/src/cli/input-controller.js +45 -17
- package/src/cli/markdown-format.js +12 -7
- package/src/cli/repl-commands.js +44 -4
- package/src/cli/repl.js +127 -35
- package/src/cli/slash-commands.js +1 -0
- package/src/cli/spinner.js +7 -1
- package/src/cli/terminal-manager.js +74 -0
- package/src/cli/terminal-ui.js +2 -3
- package/src/cli/tui.js +18 -2
- package/src/codebase-index/indexer.js +1 -1
- package/src/codebase-index/search.js +1 -1
- package/src/codebase-index/watcher.js +1 -1
- package/src/design/commands.js +2 -2
- package/src/mcp/inline-complete.js +6 -6
- package/src/plugins/manager.js +5 -5
- package/src/session/manager.js +1 -1
- package/src/skills/manager.js +8 -8
- package/src/tools/agent.js +1 -1
- package/src/tools/executor.js +1 -1
- package/src/tools/insert-text.js +1 -1
- package/src/tools/interactive.js +1 -1
- package/src/tools/notebook.js +1 -1
- package/src/tools/scheduler.js +1 -1
- package/src/tools/str-replace-all.js +1 -1
- package/src/tools/todo.js +1 -1
- package/src/tools/web-archive.js +1 -1
package/src/cli/repl.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
renderStartupTui,
|
|
17
17
|
renderStatusPanel,
|
|
18
18
|
} from './tui.js';
|
|
19
|
+
import { terminalManager } from './terminal-manager.js';
|
|
19
20
|
import { WinterInputController } from './input-controller.js';
|
|
20
21
|
import { ToolExecutor } from '../tools/executor.js';
|
|
21
22
|
import { SessionManager } from '../session/manager.js';
|
|
@@ -125,6 +126,8 @@ export class WinterREPL {
|
|
|
125
126
|
this.watchers = [];
|
|
126
127
|
this.startupNotices = [];
|
|
127
128
|
this._fixedPanel = Boolean(process.stdout.isTTY) && process.env.WINTER_FIXED_PANEL_TUI !== '0';
|
|
129
|
+
|
|
130
|
+
terminalManager.install();
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
async initCodebaseSearch() {
|
|
@@ -654,22 +657,106 @@ export class WinterREPL {
|
|
|
654
657
|
// Hiển thị prompt lần đầu tiên ngay khi khởi động xong.
|
|
655
658
|
this.showInputPrompt();
|
|
656
659
|
|
|
657
|
-
|
|
660
|
+
// Paste buffer: gom nhiều dòng paste nhanh thành 1 tin nhắn
|
|
661
|
+
this._multilineBuffer = [];
|
|
662
|
+
this._pasteBuffer = [];
|
|
663
|
+
this._pasteTimer = null;
|
|
664
|
+
this._isPasteChunk = false;
|
|
665
|
+
this._pasteChunkTimer = null;
|
|
666
|
+
const PASTE_DELAY = 80;
|
|
667
|
+
|
|
668
|
+
process.stdin.on('data', (chunk) => {
|
|
669
|
+
// If a large chunk or chunk with newlines arrives, it's definitely a paste.
|
|
670
|
+
if (chunk.length > 3 || chunk.includes('\n')) {
|
|
671
|
+
this._isPasteChunk = true;
|
|
672
|
+
if (this._pasteChunkTimer) clearTimeout(this._pasteChunkTimer);
|
|
673
|
+
this._pasteChunkTimer = setTimeout(() => {
|
|
674
|
+
this._isPasteChunk = false;
|
|
675
|
+
}, 150);
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const flushPasteBuffer = () => {
|
|
680
|
+
this._pasteTimer = null;
|
|
681
|
+
if (this._pasteBuffer.length === 0) return;
|
|
682
|
+
|
|
683
|
+
const isSingleLineInput = this._pasteBuffer.length === 1 && !this._isPasteChunk;
|
|
684
|
+
const isJustEmptyEnter = this._pasteBuffer.length === 1 && this._pasteBuffer[0].trim() === '';
|
|
685
|
+
|
|
686
|
+
// Normal single-line submit
|
|
687
|
+
if (isSingleLineInput && this._multilineBuffer.length === 0) {
|
|
688
|
+
const line = this._pasteBuffer[0].trim();
|
|
689
|
+
this._pasteBuffer = [];
|
|
690
|
+
if (!line) {
|
|
691
|
+
if (this.running && !this.readlineClosed) {
|
|
692
|
+
readline.moveCursor(process.stdout, 0, -1);
|
|
693
|
+
readline.clearLine(process.stdout, 0);
|
|
694
|
+
this.rl.prompt(true);
|
|
695
|
+
}
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Command to enter multiline mode manually
|
|
700
|
+
if (line === '/multi' || line === '/m') {
|
|
701
|
+
this._multilineBuffer.push('');
|
|
702
|
+
console.log(`${colors.cyan}│ ${colors.dim}[ Đã bật chế độ gõ nhiều dòng. Nhấn Enter 2 lần (dòng trống) để gửi. ]${colors.reset}`);
|
|
703
|
+
if (this.running && !this.readlineClosed) this.rl.prompt(true);
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
this.submitInputQueue(line);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// We are in multiline/paste mode
|
|
712
|
+
this._multilineBuffer.push(...this._pasteBuffer);
|
|
713
|
+
this._pasteBuffer = [];
|
|
714
|
+
|
|
715
|
+
// If they pressed Enter on an empty line, submit the multiline buffer!
|
|
716
|
+
if (isJustEmptyEnter && this._multilineBuffer.length > 1) {
|
|
717
|
+
// Remove the trailing empty line
|
|
718
|
+
this._multilineBuffer.pop();
|
|
719
|
+
const combined = this._multilineBuffer.join('\n').trim();
|
|
720
|
+
this._multilineBuffer = [];
|
|
721
|
+
this._isPasteChunk = false;
|
|
722
|
+
|
|
723
|
+
if (!combined) {
|
|
724
|
+
if (this.running && !this.readlineClosed) {
|
|
725
|
+
this.closeInputBox();
|
|
726
|
+
this.showInputPrompt();
|
|
727
|
+
}
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
this.submitInputQueue(combined);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Otherwise, we are still collecting! Wait for user to submit.
|
|
736
|
+
readline.clearLine(process.stdout, 0);
|
|
737
|
+
readline.cursorTo(process.stdout, 0);
|
|
738
|
+
const linesCount = this._multilineBuffer.length;
|
|
739
|
+
console.log(`${colors.cyan}│ ${colors.dim}[ Đang nhập nhiều dòng (${linesCount} dòng)... Nhấn Enter ở dòng trống để gửi ]${colors.reset}`);
|
|
740
|
+
if (this.running && !this.readlineClosed) this.rl.prompt(true);
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
this.submitInputQueue = (combined) => {
|
|
658
744
|
this.inputQueue = this.inputQueue
|
|
659
745
|
.then(async () => {
|
|
660
746
|
this.closeInputBox();
|
|
661
|
-
|
|
662
|
-
if (input) {
|
|
663
|
-
await this.handleInput(input);
|
|
664
|
-
} else {
|
|
665
|
-
if (this.running && !this.readlineClosed) this.showInputPrompt();
|
|
666
|
-
}
|
|
747
|
+
await this.handleInput(combined);
|
|
667
748
|
})
|
|
668
749
|
.catch((error) => {
|
|
669
750
|
this.closeInputBox();
|
|
670
751
|
console.log(`\n${colors.red}? Error: ${error.message}${colors.reset}\n`);
|
|
671
752
|
if (this.running && !this.readlineClosed) this.showInputPrompt();
|
|
672
753
|
});
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
this.rl.on('line', (line) => {
|
|
757
|
+
this._pasteBuffer.push(line);
|
|
758
|
+
if (this._pasteTimer) clearTimeout(this._pasteTimer);
|
|
759
|
+
this._pasteTimer = setTimeout(flushPasteBuffer, PASTE_DELAY);
|
|
673
760
|
});
|
|
674
761
|
|
|
675
762
|
this.rl.on('close', async () => {
|
|
@@ -936,9 +1023,12 @@ export class WinterREPL {
|
|
|
936
1023
|
const preview = input.length > 40 ? input.slice(0, 37) + '...' : input;
|
|
937
1024
|
console.log(`${colors.yellow}⧗${colors.reset} ${colors.bright}Queued #${pos}${colors.reset} ${colors.dim}› ${preview}${colors.reset}`);
|
|
938
1025
|
this.taskQueue.push(input);
|
|
1026
|
+
if (!this.readlineClosed) this.showInputPrompt();
|
|
939
1027
|
return;
|
|
940
1028
|
}
|
|
941
|
-
|
|
1029
|
+
this.processInputTask(input).catch(err => {
|
|
1030
|
+
console.log(colors.red + '\nLỗi xử lý hàng đợi: ' + err.message + colors.reset);
|
|
1031
|
+
});
|
|
942
1032
|
}
|
|
943
1033
|
|
|
944
1034
|
async processInputTask(input) {
|
|
@@ -952,6 +1042,12 @@ export class WinterREPL {
|
|
|
952
1042
|
this.history = this.history.slice(-this.maxHistory);
|
|
953
1043
|
}
|
|
954
1044
|
|
|
1045
|
+
// Echo tin nhắn user để xác nhận đã nhận
|
|
1046
|
+
if (!input.startsWith('/') && !input.startsWith('!')) {
|
|
1047
|
+
const preview = input.length > 120 ? input.slice(0, 117) + '...' : input;
|
|
1048
|
+
console.log(`\n${colors.bright}${colors.green}You${colors.reset} ${colors.dim}›${colors.reset} ${colors.white}${preview}${colors.reset}`);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
955
1051
|
if (input.startsWith('!')) {
|
|
956
1052
|
const command = input.slice(1).trim();
|
|
957
1053
|
if (!command) {
|
|
@@ -1030,6 +1126,7 @@ export class WinterREPL {
|
|
|
1030
1126
|
if (this.spinner) this.spinner.stop();
|
|
1031
1127
|
|
|
1032
1128
|
if (this.taskQueue.length > 0) {
|
|
1129
|
+
this.closeInputBox();
|
|
1033
1130
|
const nextTask = this.taskQueue.shift();
|
|
1034
1131
|
setTimeout(() => this.processInputTask(nextTask), 0);
|
|
1035
1132
|
} else {
|
|
@@ -1748,22 +1845,27 @@ ${colors.reset}
|
|
|
1748
1845
|
}
|
|
1749
1846
|
|
|
1750
1847
|
if (chunk.content) {
|
|
1751
|
-
if (!printed) {
|
|
1752
|
-
if (this.spinner) this.spinner.stop();
|
|
1753
|
-
if (!bufferToolModeContent) {
|
|
1754
|
-
process.stdout.write(`\n${colors.white}`);
|
|
1755
|
-
printed = true;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
1848
|
content += chunk.content;
|
|
1759
|
-
|
|
1760
|
-
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
if (this.spinner && printed === false) {
|
|
1852
|
+
if (toolCallParts.length > 0) {
|
|
1853
|
+
const lastCall = toolCallParts[toolCallParts.length - 1];
|
|
1854
|
+
if (lastCall.function?.name) {
|
|
1855
|
+
const args = lastCall.function.arguments || '';
|
|
1856
|
+
let summary = args.replace(/\s+/g, ' ');
|
|
1857
|
+
if (summary.length > 60) summary = '...' + summary.slice(-60);
|
|
1858
|
+
this.spinner.update(`Calling ${lastCall.function.name}... ${summary}`);
|
|
1859
|
+
}
|
|
1860
|
+
} else if (content.length > 0 && bufferToolModeContent) {
|
|
1861
|
+
let summary = content.replace(/\s+/g, ' ');
|
|
1862
|
+
if (summary.length > 60) summary = '...' + summary.slice(-60);
|
|
1863
|
+
this.spinner.update(`Generating... ${summary}`);
|
|
1761
1864
|
}
|
|
1762
1865
|
}
|
|
1763
1866
|
}
|
|
1764
1867
|
|
|
1765
1868
|
if (this.spinner) this.spinner.stop();
|
|
1766
|
-
if (printed) process.stdout.write(colors.reset);
|
|
1767
1869
|
|
|
1768
1870
|
const inlineToolExtraction = this.extractInlineToolCalls(content);
|
|
1769
1871
|
const rawToolCalls = [
|
|
@@ -1776,7 +1878,7 @@ ${colors.reset}
|
|
|
1776
1878
|
const toolCalls = this.normalizeToolCalls(rawToolCalls);
|
|
1777
1879
|
const visibleContent = inlineToolExtraction.content || content;
|
|
1778
1880
|
|
|
1779
|
-
if (
|
|
1881
|
+
if (toolCalls.length === 0 && visibleContent) {
|
|
1780
1882
|
if (options?.requireToolEvidence && this.responseNeedsToolEvidence(visibleContent)) {
|
|
1781
1883
|
return {
|
|
1782
1884
|
assistantMsg: { content: visibleContent },
|
|
@@ -1794,18 +1896,6 @@ ${colors.reset}
|
|
|
1794
1896
|
};
|
|
1795
1897
|
}
|
|
1796
1898
|
|
|
1797
|
-
if (toolCalls.length === 0 && visibleContent) {
|
|
1798
|
-
console.log(`\n${colors.dim}${this.formatAnswerFooter(startedAt, totalUsage)}${colors.reset}\n`);
|
|
1799
|
-
return {
|
|
1800
|
-
assistantMsg: { content: visibleContent },
|
|
1801
|
-
toolCalls,
|
|
1802
|
-
finalContent: visibleContent,
|
|
1803
|
-
finishReason,
|
|
1804
|
-
};
|
|
1805
|
-
} else if (printed && visibleContent) {
|
|
1806
|
-
process.stdout.write('\n');
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
1899
|
return {
|
|
1810
1900
|
assistantMsg: {
|
|
1811
1901
|
content: visibleContent,
|
|
@@ -1974,7 +2064,6 @@ ${colors.reset}
|
|
|
1974
2064
|
const profile = executionProfile || this.selectExecutionProfile(messages, { enableTools: false });
|
|
1975
2065
|
|
|
1976
2066
|
try {
|
|
1977
|
-
process.stdout.write(`\n${colors.white}`);
|
|
1978
2067
|
let isFirst = true;
|
|
1979
2068
|
for await (const chunk of this.ai.streamRequest(messages, {
|
|
1980
2069
|
provider: profile.provider,
|
|
@@ -1982,16 +2071,19 @@ ${colors.reset}
|
|
|
1982
2071
|
enableTools: false,
|
|
1983
2072
|
signal: this.currentAbortController?.signal,
|
|
1984
2073
|
})) {
|
|
2074
|
+
if (isFirst) {
|
|
2075
|
+
isFirst = false;
|
|
2076
|
+
}
|
|
1985
2077
|
if (chunk.usage) this.addUsage(totalUsage, chunk.usage);
|
|
1986
2078
|
if (chunk.content) {
|
|
1987
2079
|
content += chunk.content;
|
|
1988
|
-
process.stdout.write(chunk.content);
|
|
1989
2080
|
}
|
|
1990
2081
|
}
|
|
1991
|
-
|
|
2082
|
+
|
|
2083
|
+
if (this.spinner) this.spinner.stop();
|
|
1992
2084
|
|
|
1993
2085
|
if (content) {
|
|
1994
|
-
|
|
2086
|
+
this.printAssistantAnswer(content, startedAt, totalUsage);
|
|
1995
2087
|
return content;
|
|
1996
2088
|
}
|
|
1997
2089
|
} catch (error) {
|
|
@@ -9,6 +9,7 @@ export const SLASH_COMMANDS = [
|
|
|
9
9
|
{ cmd: '/session', desc: 'Session management' },
|
|
10
10
|
{ cmd: '/sessions', desc: 'List all sessions' },
|
|
11
11
|
{ cmd: '/history', desc: 'Browse recent chat and tool history', usage: '/history [count]' },
|
|
12
|
+
{ cmd: '/tool', desc: 'Inspect recent tool calls and their raw data', usage: '/tool [index]' },
|
|
12
13
|
{ cmd: '/new', desc: 'Start a new conversation' },
|
|
13
14
|
{ cmd: '/clear', desc: 'Clear screen' },
|
|
14
15
|
{ cmd: '/remember', desc: 'Store in memory', usage: '/remember <text>' },
|
package/src/cli/spinner.js
CHANGED
|
@@ -13,8 +13,14 @@ export class Spinner {
|
|
|
13
13
|
const cyan = this.colors.cyan || '';
|
|
14
14
|
const reset = this.colors.reset || '';
|
|
15
15
|
const dim = this.colors.dim || '';
|
|
16
|
+
this.startTime = Date.now();
|
|
16
17
|
this.interval = setInterval(() => {
|
|
17
|
-
|
|
18
|
+
const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
|
|
19
|
+
let timeStr = '';
|
|
20
|
+
if (elapsed >= 5) {
|
|
21
|
+
timeStr = ` (still thinking... ${elapsed}s)`;
|
|
22
|
+
}
|
|
23
|
+
process.stdout.write(`\r\x1b[K${cyan}${this.frames[this.frameIndex]}${reset} ${dim}${this.text}${timeStr}${reset}`);
|
|
18
24
|
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
19
25
|
}, 80);
|
|
20
26
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
|
|
3
|
+
class TerminalManager {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.isPromptVisible = false;
|
|
6
|
+
this.getLinesCountFn = null;
|
|
7
|
+
this.redrawFn = null;
|
|
8
|
+
this.onHideFn = null;
|
|
9
|
+
this._originalLog = console.log;
|
|
10
|
+
this._originalError = console.error;
|
|
11
|
+
this._isIntercepting = false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
install() {
|
|
15
|
+
if (this._isIntercepting) return;
|
|
16
|
+
this._isIntercepting = true;
|
|
17
|
+
|
|
18
|
+
console.log = (...args) => this._interceptLog(this._originalLog, args);
|
|
19
|
+
console.error = (...args) => this._interceptLog(this._originalError, args);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
uninstall() {
|
|
23
|
+
if (!this._isIntercepting) return;
|
|
24
|
+
this._isIntercepting = false;
|
|
25
|
+
console.log = this._originalLog;
|
|
26
|
+
console.error = this._originalError;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setPromptState(isVisible, getLinesCountFn = null, redrawFn = null, onHideFn = null) {
|
|
30
|
+
this.isPromptVisible = isVisible;
|
|
31
|
+
this.getLinesCountFn = getLinesCountFn;
|
|
32
|
+
this.redrawFn = redrawFn;
|
|
33
|
+
this.onHideFn = onHideFn;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
hidePrompt() {
|
|
37
|
+
if (!this.isPromptVisible || !process.stdout.isTTY) return;
|
|
38
|
+
|
|
39
|
+
// Clear the current line first (the readline prompt itself)
|
|
40
|
+
readline.clearLine(process.stdout, 0);
|
|
41
|
+
readline.cursorTo(process.stdout, 0);
|
|
42
|
+
|
|
43
|
+
// If the prompt panel has multiple lines above it, move up and clear
|
|
44
|
+
const linesCount = this.getLinesCountFn ? this.getLinesCountFn() : 0;
|
|
45
|
+
if (linesCount > 1) {
|
|
46
|
+
readline.moveCursor(process.stdout, 0, -(linesCount - 1));
|
|
47
|
+
readline.clearScreenDown(process.stdout);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (this.onHideFn) {
|
|
51
|
+
this.onHideFn();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_interceptLog(originalFn, args) {
|
|
56
|
+
if (!this.isPromptVisible) {
|
|
57
|
+
originalFn.apply(console, args);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Hide prompt
|
|
62
|
+
this.hidePrompt();
|
|
63
|
+
|
|
64
|
+
// Print the actual log
|
|
65
|
+
originalFn.apply(console, args);
|
|
66
|
+
|
|
67
|
+
// Redraw prompt
|
|
68
|
+
if (this.redrawFn) {
|
|
69
|
+
this.redrawFn();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const terminalManager = new TerminalManager();
|
package/src/cli/terminal-ui.js
CHANGED
|
@@ -70,12 +70,11 @@ export function terminalWidth(min = 72, max = 120, fallback = 88) {
|
|
|
70
70
|
|
|
71
71
|
export function supportsUnicodeUi(env = process.env, platform = process.platform) {
|
|
72
72
|
if (env.WINTER_ASCII_UI === '1' || env.WINTER_ASCII_UI === 'true') return false;
|
|
73
|
-
|
|
74
|
-
if (platform !== 'win32') return true;
|
|
75
|
-
return false;
|
|
73
|
+
return true;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
export function getBoxChars() {
|
|
77
|
+
if (supportsUnicodeUi()) return UNICODE_BOX;
|
|
79
78
|
return ASCII_BOX;
|
|
80
79
|
}
|
|
81
80
|
|
package/src/cli/tui.js
CHANGED
|
@@ -176,6 +176,22 @@ export function renderAssistantPanel({ content = '', footer = '', colors, title
|
|
|
176
176
|
export function renderToolPanel({ toolName = 'Tool', summary = '', success = true, colors } = {}) {
|
|
177
177
|
const c = colors || {};
|
|
178
178
|
const status = success ? `${c.brightGreen}✓${c.reset}` : `${c.red}✖${c.reset}`;
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
|
|
180
|
+
if (!summary.includes('\n')) {
|
|
181
|
+
return `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${summary}${c.reset}`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const lines = summary.split('\n');
|
|
185
|
+
const firstLine = lines.shift();
|
|
186
|
+
|
|
187
|
+
const formattedRest = lines.map(line => {
|
|
188
|
+
if (line.startsWith('+')) return ` ${c.green}${line}${c.reset}`;
|
|
189
|
+
if (line.startsWith('-')) return ` ${c.red}${line}${c.reset}`;
|
|
190
|
+
if (line.startsWith('@@')) return ` ${c.cyan}${line}${c.reset}`;
|
|
191
|
+
return ` ${c.dim}${line}${c.reset}`;
|
|
192
|
+
}).join('\n');
|
|
193
|
+
|
|
194
|
+
let output = `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${firstLine}${c.reset}`;
|
|
195
|
+
if (formattedRest) output += `\n${formattedRest}`;
|
|
196
|
+
return output;
|
|
181
197
|
}
|
package/src/design/commands.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* ❄ DESIGN COMMANDS ❄
|
|
3
3
|
* Design system integration with brand guidelines
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -163,7 +163,7 @@ export class DesignCommands {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
console.log(`\n${'='.repeat(60)}`);
|
|
166
|
-
console.log(`${colors.cyan}
|
|
166
|
+
console.log(`${colors.cyan}≡ ${brand} - ${fileName}${colors.reset}`);
|
|
167
167
|
console.log('='.repeat(60));
|
|
168
168
|
console.log('');
|
|
169
169
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* ❄ INLINE COMPLETION — /complete command ❄
|
|
3
3
|
* Provides code completion suggestions based on context.
|
|
4
4
|
* Integrates the existing CompletionProvider into the REPL.
|
|
5
5
|
*/
|
|
@@ -76,15 +76,15 @@ export class InlineComplete {
|
|
|
76
76
|
const width = terminalWidth(76, 116, 92);
|
|
77
77
|
const body = result.completions.map((c, i) => {
|
|
78
78
|
const typeIcon = c.type === 'block-close' ? '}' :
|
|
79
|
-
c.type === 'import' ? '
|
|
79
|
+
c.type === 'import' ? '■' :
|
|
80
80
|
c.type === 'function' ? 'ƒ' :
|
|
81
81
|
c.type === 'method' ? '.' :
|
|
82
82
|
c.type === 'arrow-function' ? '=>' :
|
|
83
83
|
c.type === 'variable' ? '✕' :
|
|
84
|
-
c.type === 'keyword' ? '
|
|
85
|
-
c.type === 'export' ? '
|
|
86
|
-
c.type === 'import-path' ? '
|
|
87
|
-
c.type === 'cached' ? '
|
|
84
|
+
c.type === 'keyword' ? '#' :
|
|
85
|
+
c.type === 'export' ? '^' :
|
|
86
|
+
c.type === 'import-path' ? '►' :
|
|
87
|
+
c.type === 'cached' ? 'v' : '•';
|
|
88
88
|
const confidence = (c.confidence * 100).toFixed(0);
|
|
89
89
|
return ` ${colors.cyan}#${i + 1}${colors.reset} ${typeIcon} ${colors.green}${c.text}${colors.reset}` +
|
|
90
90
|
`\n ${colors.dim}type: ${c.type}, confidence: ${confidence}%${colors.reset}`;
|
package/src/plugins/manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* ❄ PLUGIN MANAGER ❄
|
|
3
3
|
* Manage Winter CLI plugins
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -21,7 +21,7 @@ export class PluginManager {
|
|
|
21
21
|
{
|
|
22
22
|
name: 'winter-core',
|
|
23
23
|
version: '1.0.0',
|
|
24
|
-
icon: '
|
|
24
|
+
icon: '❄',
|
|
25
25
|
description: 'Core Winter CLI functionality',
|
|
26
26
|
hooks: {},
|
|
27
27
|
commands: {},
|
|
@@ -30,7 +30,7 @@ export class PluginManager {
|
|
|
30
30
|
{
|
|
31
31
|
name: 'winter-design',
|
|
32
32
|
version: '1.0.0',
|
|
33
|
-
icon: '
|
|
33
|
+
icon: '*',
|
|
34
34
|
description: 'Design system integration',
|
|
35
35
|
hooks: {},
|
|
36
36
|
commands: {},
|
|
@@ -39,7 +39,7 @@ export class PluginManager {
|
|
|
39
39
|
{
|
|
40
40
|
name: 'winter-coding',
|
|
41
41
|
version: '1.0.0',
|
|
42
|
-
icon: '
|
|
42
|
+
icon: '■',
|
|
43
43
|
description: 'Coding assistance tools',
|
|
44
44
|
hooks: {},
|
|
45
45
|
commands: {},
|
|
@@ -67,7 +67,7 @@ export class PluginManager {
|
|
|
67
67
|
plugins.push({
|
|
68
68
|
name: plugin.default?.name || file.replace('.js', ''),
|
|
69
69
|
version: plugin.default?.version || '1.0.0',
|
|
70
|
-
icon: plugin.default?.icon || '
|
|
70
|
+
icon: plugin.default?.icon || '+',
|
|
71
71
|
description: plugin.default?.description || 'Plugin',
|
|
72
72
|
hooks: plugin.default?.hooks || {},
|
|
73
73
|
commands: plugin.default?.commands || {},
|
package/src/session/manager.js
CHANGED
package/src/skills/manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* ❄ SKILL MANAGER ❄
|
|
3
3
|
* Manage Winter CLI skills
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -19,7 +19,7 @@ export class SkillManager {
|
|
|
19
19
|
return [
|
|
20
20
|
{
|
|
21
21
|
name: 'coding',
|
|
22
|
-
icon: '
|
|
22
|
+
icon: '■',
|
|
23
23
|
description: 'Code analysis, generation, and review',
|
|
24
24
|
prompts: [
|
|
25
25
|
'Analyze this code for issues',
|
|
@@ -29,7 +29,7 @@ export class SkillManager {
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
name: 'design',
|
|
32
|
-
icon: '
|
|
32
|
+
icon: '*',
|
|
33
33
|
description: 'Design system and brand guidelines',
|
|
34
34
|
prompts: [
|
|
35
35
|
'Apply {brand} design patterns',
|
|
@@ -39,7 +39,7 @@ export class SkillManager {
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
name: 'debug',
|
|
42
|
-
icon: '
|
|
42
|
+
icon: '$',
|
|
43
43
|
description: 'Debugging and error analysis',
|
|
44
44
|
prompts: [
|
|
45
45
|
'Find the root cause of this error',
|
|
@@ -49,7 +49,7 @@ export class SkillManager {
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: 'refactor',
|
|
52
|
-
icon: '
|
|
52
|
+
icon: '♻',
|
|
53
53
|
description: 'Code refactoring and improvements',
|
|
54
54
|
prompts: [
|
|
55
55
|
'Simplify this function',
|
|
@@ -69,7 +69,7 @@ export class SkillManager {
|
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
name: 'security',
|
|
72
|
-
icon: '
|
|
72
|
+
icon: '#',
|
|
73
73
|
description: 'Security analysis and best practices',
|
|
74
74
|
prompts: [
|
|
75
75
|
'Find potential security vulnerabilities',
|
|
@@ -79,7 +79,7 @@ export class SkillManager {
|
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
name: 'performance',
|
|
82
|
-
icon: '
|
|
82
|
+
icon: '▶',
|
|
83
83
|
description: 'Performance optimization',
|
|
84
84
|
prompts: [
|
|
85
85
|
'Identify performance bottlenecks',
|
|
@@ -107,7 +107,7 @@ export class SkillManager {
|
|
|
107
107
|
const name = file.replace('.md', '');
|
|
108
108
|
skills.push({
|
|
109
109
|
name,
|
|
110
|
-
icon: '
|
|
110
|
+
icon: '$',
|
|
111
111
|
description: this.extractDescription(content),
|
|
112
112
|
isCustom: true,
|
|
113
113
|
});
|
package/src/tools/agent.js
CHANGED
package/src/tools/executor.js
CHANGED
package/src/tools/insert-text.js
CHANGED
package/src/tools/interactive.js
CHANGED
package/src/tools/notebook.js
CHANGED
package/src/tools/scheduler.js
CHANGED
package/src/tools/todo.js
CHANGED
package/src/tools/web-archive.js
CHANGED