winter-super-cli 2026.5.24 → 2026.5.26
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/README.md +1 -1
- package/WINTER.md +6 -0
- package/bin/winter.js +77 -220
- package/package.json +1 -1
- package/resources/local/manifest.json +60 -57
- package/src/ai/providers.js +64 -13
- package/src/ai/providers.test.js +35 -0
- package/src/cli/commands.js +61 -3
- package/src/cli/commands.test.js +179 -0
- package/src/cli/config.js +12 -0
- package/src/cli/repl.js +475 -150
- package/src/cli/repl.test.js +234 -2
- package/src/cli/snowflake-logo.js +15 -7
- package/src/cli/terminal-ui.js +125 -0
- package/src/cli/terminal-ui.test.js +33 -0
- package/src/plugins/manager.js +3 -1
- package/src/session/manager.js +44 -0
- package/src/session/manager.test.js +72 -0
- package/src/tools/executor.js +1 -1
- package/src/tools/executor.test.js +110 -0
- package/resources/local/claude/settings.json +0 -33
- package/resources/local/claude/todos/022bdc3c-e2c0-4a20-a74f-b348ed022c75-agent-022bdc3c-e2c0-4a20-a74f-b348ed022c75.json +0 -1
- package/resources/local/claude/todos/316f0e7d-5512-49fa-8c7f-edc75b777612-agent-316f0e7d-5512-49fa-8c7f-edc75b777612.json +0 -1
- package/resources/local/claude/todos/3676dc17-fca1-4692-934b-ce35e1965af6-agent-3676dc17-fca1-4692-934b-ce35e1965af6.json +0 -1
- package/resources/local/claude/todos/464493de-7f2a-45cf-93e8-ad73214afa10-agent-464493de-7f2a-45cf-93e8-ad73214afa10.json +0 -1
- package/resources/local/claude/todos/51f2e7a7-3f31-4692-a9b2-d3f3906aafea-agent-51f2e7a7-3f31-4692-a9b2-d3f3906aafea.json +0 -1
- package/resources/local/claude/todos/64a67dce-3d62-4a98-a548-b9c91a8e87e8-agent-64a67dce-3d62-4a98-a548-b9c91a8e87e8.json +0 -1
- package/resources/local/claude/todos/727a06e6-0ac2-41ca-8b81-2c14e4d40182-agent-727a06e6-0ac2-41ca-8b81-2c14e4d40182.json +0 -1
- package/resources/local/claude/todos/7d34d296-9b5a-4525-9b68-600d2ae20b59-agent-7d34d296-9b5a-4525-9b68-600d2ae20b59.json +0 -1
- package/resources/local/claude/todos/8c0606f1-5bcc-4176-8125-c5174fd69002-agent-8c0606f1-5bcc-4176-8125-c5174fd69002.json +0 -1
- package/resources/local/claude/todos/905aab16-5225-43f6-8ae4-c94491fd3a6f-agent-905aab16-5225-43f6-8ae4-c94491fd3a6f.json +0 -1
- package/resources/local/claude/todos/9dbe93f0-d62c-4c12-b4eb-0eecc437d625-agent-9dbe93f0-d62c-4c12-b4eb-0eecc437d625.json +0 -1
- package/resources/local/claude/todos/ad48500f-02a5-4f18-970b-82fb595d171f-agent-ad48500f-02a5-4f18-970b-82fb595d171f.json +0 -1
- package/resources/local/claude/todos/af86ea71-9907-4066-907c-68055e6c0081-agent-af86ea71-9907-4066-907c-68055e6c0081.json +0 -1
- package/resources/local/claude/todos/dbb0dc16-5d71-4f1d-a56c-db0741b3d485-agent-dbb0dc16-5d71-4f1d-a56c-db0741b3d485.json +0 -1
- package/resources/local/claude/todos/ff1ac487-eb0f-4c63-9360-fbb0a81bb5ae-agent-ff1ac487-eb0f-4c63-9360-fbb0a81bb5ae.json +0 -1
- package/resources/local/codex/config.toml +0 -84
- package/resources/local/codex/memories/MEMORY.md +0 -972
- package/resources/local/codex/memories/extensions/ad_hoc/instructions.md +0 -13
- package/resources/local/codex/memories/memory_summary.md +0 -188
- package/resources/local/codex/memories/raw_memories.md +0 -1488
- package/resources/local/codex/memories/rollout_summaries/2026-03-27T04-05-14-Iirb-nsis_full_installer_build_cpp_ocr_translator.md +0 -46
- package/resources/local/codex/memories/rollout_summaries/2026-03-28T06-18-17-Si3U-my_translator_overlay_lockfix_portable_nsis.md +0 -112
- package/resources/local/codex/memories/rollout_summaries/2026-04-15T06-42-11-2JMi-qelasy_timeout_and_watch_control_stability.md +0 -90
- package/resources/local/codex/memories/rollout_summaries/2026-04-16T03-12-59-z6Wi-request_all_row_click_detail_navigation.md +0 -42
- package/resources/local/codex/memories/rollout_summaries/2026-04-17T05-49-03-tNBk-my_translator_project_readability_audio_latency_clear_button.md +0 -75
- package/resources/local/codex/memories/rollout_summaries/2026-04-21T04-05-04-EXnh-nsis_packaging_harfbuzz_dll_qml_runtime_debug.md +0 -108
- package/resources/local/codex/memories/rollout_summaries/2026-04-22T03-48-40-VnNG-openclaw_opencode_sync_and_runtime_repair.md +0 -86
- package/resources/local/codex/memories/rollout_summaries/2026-04-22T06-49-49-R8yZ-web_book_user_portal_and_lint_fixes.md +0 -82
- package/resources/local/codex/memories/rollout_summaries/2026-04-22T06-50-35-ZaS1-smoke_admin_rbac_refund_connection_refused.md +0 -35
- package/resources/local/codex/memories/rollout_summaries/2026-04-22T11-05-04-aotT-nextjs_build_fix_statswidget_leaflet_ssr.md +0 -78
- package/resources/local/codex/memories/rollout_summaries/2026-04-23T03-22-24-a5q4-ui_still_looks_cloudflare_only.md +0 -41
- package/resources/local/codex/memories/rollout_summaries/2026-04-23T04-35-47-amlb-bayre247_hero_slide_above_search_form.md +0 -49
- package/resources/local/codex/memories/rollout_summaries/2026-04-23T04-59-21-lZWv-ocr_backend_parity_easyocr_tesseract_paddle_fallback.md +0 -92
- package/resources/local/codex/memories/rollout_summaries/2026-04-23T07-36-22-tPuo-request_workflow_editor_drag_edge_smaller_arrows_roadmap.md +0 -72
- package/resources/local/codex/memories/rollout_summaries/2026-04-24T08-01-05-Gb3B-checkin_shifts_workdays_assignments_and_checkout_overhaul.md +0 -90
- package/resources/local/codex/memories/rollout_summaries/2026-04-25T03-39-02-mbDr-web_book_refund_admin_popup_pagination_responsiveness.md +0 -151
- package/resources/local/codex/memories/rollout_summaries/2026-04-25T09-20-30-4usS-tool_scv_9router_custom_provider_and_paddle_ocr.md +0 -130
- package/resources/local/codex/memories/rollout_summaries/2026-05-06T10-19-38-mt2X-find_db_config_in_web_book_app_env.md +0 -40
- package/resources/local/codex/memories/rollout_summaries/2026-05-06T11-10-23-TkwP-goirong_backend_title_crash_and_client_audio_tcp_tunnel_debu.md +0 -85
- package/resources/local/codex/memories/rollout_summaries/2026-05-09T07-52-18-On1F-chakra_git_cleanup_readme_bilingual_publish_config.md +0 -88
- package/resources/local/codex/memories/rollout_summaries/2026-05-11T08-05-34-oMEl-check_crack_gui_logo_onefile_build.md +0 -68
- package/resources/local/codex/memories/skills/windows-packaged-app-smoke-check/SKILL.md +0 -72
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ To install Winter globally in your system, clone the repository and run:
|
|
|
26
26
|
*De cai dat Winter tren toan he thong, hay clone repository va chay:*
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install -g
|
|
29
|
+
npm install -g winter-super-cli@latest
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
*(Or run directly without installation using node bin/winter.js)*
|
package/WINTER.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Winter Project Rules
|
|
2
2
|
|
|
3
|
+
## 🌨 Core Mission
|
|
4
|
+
- Winter exists to help smaller or weaker models think more clearly, reason more reliably, and code much better.
|
|
5
|
+
- When the task is ambiguous or hard, Winter should use tools, rules, memories, skills, and local resources proactively instead of guessing.
|
|
6
|
+
- The goal is not minimal effort; the goal is strong outcomes, correct execution, and useful engineering judgment.
|
|
7
|
+
|
|
3
8
|
## 📝 Project Overview
|
|
4
9
|
- **Name**: [Tên dự án]
|
|
5
10
|
- **Description**: [Mô tả ngắn về dự án]
|
|
@@ -20,6 +25,7 @@
|
|
|
20
25
|
- Luôn giải thích NGẮN GỌN lý do thực hiện thay đổi trước khi sửa file.
|
|
21
26
|
- Khi gặp lỗi, hãy đề xuất giải pháp thay vì chỉ báo lỗi.
|
|
22
27
|
- KHÔNG tự tiện xóa code cũ của user trừ khi chắc chắn nó không còn dùng hoặc được yêu cầu.
|
|
28
|
+
- Nếu model chưa chắc chắn, hãy tự kéo thêm context bằng tool thay vì đoán.
|
|
23
29
|
|
|
24
30
|
### 3. Git & Commits
|
|
25
31
|
- Viết commit message theo chuẩn Conventional Commits (VD: `feat:`, `fix:`, `docs:`).
|
package/bin/winter.js
CHANGED
|
@@ -5,260 +5,117 @@
|
|
|
5
5
|
* Build by Atus fb: iam.anhtu, github: anhtu1707 with Interactive REPL
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { readFileSync } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
8
10
|
import { WinterREPL } from '../src/cli/repl.js';
|
|
9
11
|
import { ConfigLoader } from '../src/cli/config.js';
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
12
|
+
import { SessionManager } from '../src/session/manager.js';
|
|
13
|
+
import { AIProviderManager } from '../src/ai/providers.js';
|
|
14
|
+
import { CommandParser } from '../src/cli/commands.js';
|
|
13
15
|
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
16
17
|
const version = pkg.version;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (args.length === 0 || args.includes('i') || args.includes('interactive') || args.includes('--session')) {
|
|
23
|
-
// Start interactive REPL mode
|
|
24
|
-
const config = new ConfigLoader();
|
|
25
|
-
const cfg = await config.load();
|
|
26
|
-
|
|
27
|
-
let projectPath = process.cwd();
|
|
28
|
-
let sessionId = null;
|
|
29
|
-
|
|
30
|
-
const sessionIndex = args.indexOf('--session');
|
|
31
|
-
if (sessionIndex !== -1 && args[sessionIndex + 1]) {
|
|
32
|
-
sessionId = args[sessionIndex + 1];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Lấy projectPath từ tham số không phải cờ (nếu có)
|
|
36
|
-
const nonFlagArgs = args.filter(a => !a.startsWith('-') && a !== 'i' && a !== 'interactive' && a !== sessionId);
|
|
37
|
-
if (nonFlagArgs[0]) {
|
|
38
|
-
projectPath = path.resolve(nonFlagArgs[0]);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const repl = new WinterREPL({ projectPath, sessionId, version });
|
|
42
|
-
await repl.start();
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Handle commands
|
|
47
|
-
const [command, ...rest] = args;
|
|
19
|
+
const COMMANDS = new Set([
|
|
20
|
+
'chat', 'call', 'session', 'skill', 'plugin', 'design', 'config', 'init',
|
|
21
|
+
'help', 'project', 'code', 'review',
|
|
22
|
+
]);
|
|
48
23
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
await handleChatWithTools(rest);
|
|
52
|
-
break;
|
|
53
|
-
case 'call':
|
|
54
|
-
await handleCallAll(rest);
|
|
55
|
-
break;
|
|
56
|
-
case 'session':
|
|
57
|
-
await handleSession(rest);
|
|
58
|
-
break;
|
|
59
|
-
case 'skill':
|
|
60
|
-
await handleSkill(rest);
|
|
61
|
-
break;
|
|
62
|
-
case 'plugin':
|
|
63
|
-
await handlePlugin(rest);
|
|
64
|
-
break;
|
|
65
|
-
case 'design':
|
|
66
|
-
await handleDesign(rest);
|
|
67
|
-
break;
|
|
68
|
-
case 'config':
|
|
69
|
-
await handleConfig(rest);
|
|
70
|
-
break;
|
|
71
|
-
case 'init':
|
|
72
|
-
await handleInit(rest);
|
|
73
|
-
break;
|
|
74
|
-
case '--help':
|
|
75
|
-
case '-h':
|
|
76
|
-
printHelp();
|
|
77
|
-
break;
|
|
78
|
-
case '--version':
|
|
79
|
-
case '-v':
|
|
80
|
-
console.log(`❄️ Winter CLI v${version}\n`);
|
|
81
|
-
break;
|
|
82
|
-
default: {
|
|
83
|
-
// If no recognized command, treat the full input as a prompt.
|
|
84
|
-
const config = new ConfigLoader();
|
|
85
|
-
const cfg = await config.load();
|
|
86
|
-
const repl = new WinterREPL({ projectPath: cfg.project?.current || process.cwd() });
|
|
87
|
-
await repl.session.init();
|
|
88
|
-
await repl.ai.init();
|
|
89
|
-
await repl.chat([command, ...rest].join(' '));
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
24
|
+
function isInteractiveRequest(args) {
|
|
25
|
+
return args.length === 0 || args.includes('i') || args.includes('interactive') || args.includes('--session');
|
|
93
26
|
}
|
|
94
27
|
|
|
95
|
-
async function
|
|
96
|
-
const config = new ConfigLoader();
|
|
97
|
-
const message = args.join(' ');
|
|
98
|
-
if (!message) {
|
|
99
|
-
console.log('Usage: winter chat <message>');
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
const cfg = await config.load();
|
|
105
|
-
const repl = new WinterREPL({ projectPath: cfg.project?.current || process.cwd() });
|
|
106
|
-
await repl.session.init();
|
|
107
|
-
await repl.ai.init();
|
|
108
|
-
await repl.chat(message);
|
|
109
|
-
} catch (error) {
|
|
110
|
-
console.error(`\nWinter error: ${error.message}\n`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async function handleCallAll(args) {
|
|
115
|
-
const { AIProviderManager } = await import('../src/ai/providers.js');
|
|
116
|
-
const config = new ConfigLoader();
|
|
117
|
-
const prompt = args.join(' ');
|
|
118
|
-
|
|
119
|
-
if (!prompt) {
|
|
120
|
-
console.log('Usage: winter call <prompt>');
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const ai = new AIProviderManager(config);
|
|
125
|
-
const results = await ai.callAllProviders(prompt);
|
|
126
|
-
|
|
127
|
-
for (const [provider, result] of Object.entries(results)) {
|
|
128
|
-
if (result.error) {
|
|
129
|
-
console.log(`\n[${provider}] ERROR\n${result.error}`);
|
|
130
|
-
} else {
|
|
131
|
-
console.log(`\n[${provider}] ${result.model}\n${result.content}`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async function handleSession(args) {
|
|
137
|
-
const { SessionManager } = await import('../src/session/manager.js');
|
|
28
|
+
async function createRuntime(projectPath, sessionId = null) {
|
|
138
29
|
const config = new ConfigLoader();
|
|
139
30
|
const session = new SessionManager(config);
|
|
140
|
-
await session.init();
|
|
31
|
+
await session.init({ project: projectPath, sessionId });
|
|
141
32
|
|
|
142
|
-
const
|
|
33
|
+
const ai = new AIProviderManager(config);
|
|
34
|
+
await ai.init();
|
|
143
35
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const s = await session.newSession();
|
|
147
|
-
console.log(`✓ New session: ${s.id.substring(0, 8)}`);
|
|
148
|
-
break;
|
|
149
|
-
case 'list':
|
|
150
|
-
const sessions = await session.listSessions();
|
|
151
|
-
console.log(`\nSessions:`);
|
|
152
|
-
sessions.forEach(s => console.log(` ${s.id.substring(0, 8)} - ${s.createdAt}`));
|
|
153
|
-
break;
|
|
154
|
-
default:
|
|
155
|
-
console.log(`Session: ${session.getSessionId().substring(0, 8)}`);
|
|
156
|
-
}
|
|
36
|
+
const parser = new CommandParser({ session, ai, config });
|
|
37
|
+
return { config, session, ai, parser };
|
|
157
38
|
}
|
|
158
39
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
await session.init();
|
|
164
|
-
|
|
165
|
-
const skills = new SkillManager(session);
|
|
166
|
-
const list = await skills.listSkills();
|
|
40
|
+
function printHelp() {
|
|
41
|
+
console.log(`
|
|
42
|
+
WINTER CLI
|
|
43
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
167
44
|
|
|
168
|
-
|
|
169
|
-
list.forEach(s => console.log(` ${s.icon} ${s.name} - ${s.description}`));
|
|
170
|
-
console.log('');
|
|
171
|
-
}
|
|
45
|
+
Usage:
|
|
172
46
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const list = await plugins.listPlugins();
|
|
47
|
+
winter Start interactive REPL
|
|
48
|
+
winter help Show this help
|
|
49
|
+
winter chat <message> Chat with AI
|
|
50
|
+
winter <prompt> Treat plain text as a chat prompt
|
|
178
51
|
|
|
179
|
-
|
|
180
|
-
list.forEach(p => console.log(` ${p.icon} ${p.name} v${p.version}`));
|
|
181
|
-
console.log('');
|
|
182
|
-
}
|
|
52
|
+
Commands:
|
|
183
53
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
54
|
+
winter call <prompt> Call all configured providers
|
|
55
|
+
winter session <action> Session management
|
|
56
|
+
winter skill <action> Skill management
|
|
57
|
+
winter plugin <action> Plugin management
|
|
58
|
+
winter design <action> Design commands
|
|
59
|
+
winter project <action> Project commands
|
|
60
|
+
winter config Show config
|
|
61
|
+
winter init Initialize local state
|
|
62
|
+
winter review Code review mode
|
|
63
|
+
winter code Code analysis mode
|
|
189
64
|
|
|
190
|
-
|
|
191
|
-
await design.execute(args[0], args.slice(1));
|
|
192
|
-
}
|
|
65
|
+
Flags:
|
|
193
66
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const cfg = await config.load();
|
|
197
|
-
console.log(`\n❄️ Configuration:\n`);
|
|
198
|
-
console.log(JSON.stringify(cfg, null, 2));
|
|
199
|
-
console.log('');
|
|
200
|
-
}
|
|
67
|
+
winter -h, --help Show help
|
|
68
|
+
winter -v, --version Show version
|
|
201
69
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// Create necessary directories and files
|
|
205
|
-
console.log('✓ Ready!');
|
|
70
|
+
Version ${version}
|
|
71
|
+
`);
|
|
206
72
|
}
|
|
207
73
|
|
|
208
|
-
function
|
|
209
|
-
|
|
210
|
-
WINTER CLI
|
|
211
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
212
|
-
|
|
213
|
-
Commands:
|
|
74
|
+
async function main() {
|
|
75
|
+
const args = process.argv.slice(2);
|
|
214
76
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
winter session Session management
|
|
220
|
-
winter skill List skills
|
|
221
|
-
winter plugin List plugins
|
|
222
|
-
winter design Design commands
|
|
223
|
-
winter config Show config
|
|
77
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
78
|
+
printHelp();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
224
81
|
|
|
225
|
-
|
|
82
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
83
|
+
console.log(`❄️ Winter CLI v${version}\n`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
226
86
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
/models List configured and cached models
|
|
230
|
-
/codex [section] Browse ~/.codex resources
|
|
231
|
-
/claude [section] Browse ~/.claude resources
|
|
232
|
-
/karpathy Browse ~/karpathy-tools
|
|
233
|
-
/designs [query] List/search awesome-design-md systems
|
|
234
|
-
/agents Read ~/agents.md
|
|
235
|
-
/skills List Winter/Codex/Claude skills
|
|
87
|
+
if (isInteractiveRequest(args)) {
|
|
88
|
+
const config = new ConfigLoader();
|
|
236
89
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return;
|
|
240
|
-
console.log(`
|
|
241
|
-
❄️ WINTER CLI ❄️
|
|
242
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
90
|
+
let projectPath = process.cwd();
|
|
91
|
+
let sessionId = null;
|
|
243
92
|
|
|
244
|
-
|
|
93
|
+
const sessionIndex = args.indexOf('--session');
|
|
94
|
+
if (sessionIndex !== -1 && args[sessionIndex + 1]) {
|
|
95
|
+
sessionId = args[sessionIndex + 1];
|
|
96
|
+
}
|
|
245
97
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
98
|
+
const nonFlagArgs = args.filter(a => !a.startsWith('-') && a !== 'i' && a !== 'interactive' && a !== sessionId);
|
|
99
|
+
if (nonFlagArgs[0]) {
|
|
100
|
+
projectPath = path.resolve(nonFlagArgs[0]);
|
|
101
|
+
}
|
|
249
102
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
winter config Show config
|
|
103
|
+
const repl = new WinterREPL({ projectPath, sessionId, version });
|
|
104
|
+
await repl.start();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
255
107
|
|
|
256
|
-
|
|
108
|
+
const config = new ConfigLoader();
|
|
109
|
+
const projectPath = process.cwd();
|
|
110
|
+
const { parser } = await createRuntime(projectPath);
|
|
111
|
+
const [command] = args;
|
|
257
112
|
|
|
258
|
-
|
|
113
|
+
if (!command || (!command.startsWith('/') && !COMMANDS.has(command))) {
|
|
114
|
+
await parser.parse(['chat', ...args]);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
259
117
|
|
|
260
|
-
|
|
261
|
-
`);
|
|
118
|
+
await parser.parse(args);
|
|
262
119
|
}
|
|
263
120
|
|
|
264
121
|
main().catch(err => {
|
package/package.json
CHANGED
|
@@ -1,57 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
{
|
|
2
|
+
"generatedAt": "2026-05-14T18:37:11.5585557+07:00",
|
|
3
|
+
"root": "resources/local",
|
|
4
|
+
"localResources": [
|
|
5
|
+
{
|
|
6
|
+
"name": "agents.md",
|
|
7
|
+
"path": "resources/local/agents.md",
|
|
8
|
+
"files": 90,
|
|
9
|
+
"bytes": 2546038
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "awesome-design-md",
|
|
13
|
+
"path": "resources/local/awesome-design-md",
|
|
14
|
+
"files": 142,
|
|
15
|
+
"bytes": 1912402
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "claude",
|
|
19
|
+
"path": "resources/local/claude",
|
|
20
|
+
"files": 971,
|
|
21
|
+
"bytes": 17626519
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "codex",
|
|
25
|
+
"path": "resources/local/codex",
|
|
26
|
+
"files": 259,
|
|
27
|
+
"bytes": 3425257
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "karpathy-tools",
|
|
31
|
+
"path": "resources/local/karpathy-tools",
|
|
32
|
+
"files": 2,
|
|
33
|
+
"bytes": 6068
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "manifest.json",
|
|
37
|
+
"path": "resources/local/manifest.json",
|
|
38
|
+
"files": 1,
|
|
39
|
+
"bytes": 2936
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"excludedForSafety": [
|
|
43
|
+
"$HOME/.codex/auth.json",
|
|
44
|
+
"$HOME/.codex/sessions",
|
|
45
|
+
"$HOME/.codex/history.jsonl",
|
|
46
|
+
"$HOME/.codex/*.sqlite*",
|
|
47
|
+
"$HOME/.codex log and tmp/cache runtime folders",
|
|
48
|
+
"$HOME/.claude/history.jsonl",
|
|
49
|
+
"$HOME/.claude/sessions",
|
|
50
|
+
"$HOME/.claude/projects",
|
|
51
|
+
"$HOME/.claude/plugins/cache",
|
|
52
|
+
"runtime logs, tmp, cache, auth, local settings, and session state"
|
|
53
|
+
],
|
|
54
|
+
"redacted": [
|
|
55
|
+
"resources/local/claude/settings.json: excluded from npm package",
|
|
56
|
+
"resources/local/codex/config.toml: excluded from npm package",
|
|
57
|
+
"resources/local/codex/memories: excluded from npm package",
|
|
58
|
+
"resources/local/claude/tasks and todos: excluded from npm package"
|
|
59
|
+
]
|
|
60
|
+
}
|
package/src/ai/providers.js
CHANGED
|
@@ -86,30 +86,81 @@ export class AIProviderManager {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
async loadAuthToken() {
|
|
89
|
+
// 1) Honor explicit environment variables (highest priority)
|
|
90
|
+
const envToken = process.env.CLAUDE_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_TOKEN || null;
|
|
91
|
+
if (envToken) return envToken;
|
|
92
|
+
|
|
93
|
+
// 2) Look into user home directories (platform-agnostic, no hardcoded username)
|
|
89
94
|
try {
|
|
90
95
|
const fs = await import('fs');
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Try
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
const path = await import('path');
|
|
97
|
+
const os = await import('os');
|
|
98
|
+
const home = os.homedir();
|
|
99
|
+
|
|
100
|
+
// Try ~/.codex/auth.json
|
|
101
|
+
const codexAuth = path.join(home, '.codex', 'auth.json');
|
|
102
|
+
if (fs.existsSync(codexAuth)) {
|
|
103
|
+
try {
|
|
104
|
+
const data = JSON.parse(fs.readFileSync(codexAuth, 'utf8'));
|
|
105
|
+
return data.tokens?.access_token || data.access_token || null;
|
|
106
|
+
} catch {}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Try ~/.claude/sessions/*/auth.json
|
|
110
|
+
const claudeSessionsDir = path.join(home, '.claude', 'sessions');
|
|
111
|
+
if (fs.existsSync(claudeSessionsDir)) {
|
|
112
|
+
const entries = await fs.promises.readdir(claudeSessionsDir, { withFileTypes: true });
|
|
113
|
+
for (const e of entries) {
|
|
114
|
+
if (!e.isDirectory()) continue;
|
|
115
|
+
const candidate = path.join(claudeSessionsDir, e.name, 'auth.json');
|
|
116
|
+
if (fs.existsSync(candidate)) {
|
|
117
|
+
try {
|
|
118
|
+
const data = JSON.parse(fs.readFileSync(candidate, 'utf8'));
|
|
119
|
+
return data.tokens?.access_token || data.access_token || null;
|
|
120
|
+
} catch {}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
} catch (err) {
|
|
125
|
+
// ignore and fall through
|
|
102
126
|
}
|
|
127
|
+
|
|
128
|
+
// No token found
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
normalizeProviderName(name) {
|
|
133
|
+
return String(name || '').trim().toLowerCase();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async reload() {
|
|
137
|
+
this.providers = {};
|
|
138
|
+
this.activeProvider = null;
|
|
139
|
+
this.initialized = false;
|
|
140
|
+
await this.init();
|
|
103
141
|
}
|
|
104
142
|
|
|
105
143
|
setProvider(name) {
|
|
106
|
-
|
|
107
|
-
|
|
144
|
+
const providerName = this.normalizeProviderName(name);
|
|
145
|
+
if (this.providers[providerName]) {
|
|
146
|
+
this.activeProvider = providerName;
|
|
108
147
|
return true;
|
|
109
148
|
}
|
|
110
149
|
return false;
|
|
111
150
|
}
|
|
112
151
|
|
|
152
|
+
async switchProvider(name) {
|
|
153
|
+
const providerName = this.normalizeProviderName(name);
|
|
154
|
+
await this.init();
|
|
155
|
+
|
|
156
|
+
if (this.setProvider(providerName)) {
|
|
157
|
+
return providerName;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await this.reload();
|
|
161
|
+
return this.setProvider(providerName) ? providerName : null;
|
|
162
|
+
}
|
|
163
|
+
|
|
113
164
|
getActiveProvider() {
|
|
114
165
|
return this.activeProvider;
|
|
115
166
|
}
|
package/src/ai/providers.test.js
CHANGED
|
@@ -100,3 +100,38 @@ test('callAllProviders calls every ready configured provider', async () => {
|
|
|
100
100
|
globalThis.fetch = originalFetch;
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
|
+
|
|
104
|
+
test('switchProvider reloads config before rejecting a provider', async () => {
|
|
105
|
+
let cfg = {
|
|
106
|
+
defaultProvider: 'ollama',
|
|
107
|
+
ollama: {
|
|
108
|
+
baseURL: 'http://ollama.test/v1',
|
|
109
|
+
model: 'llama3',
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const ai = new AIProviderManager({
|
|
114
|
+
async load() {
|
|
115
|
+
return cfg;
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
ai.loadAuthToken = async () => null;
|
|
119
|
+
|
|
120
|
+
await ai.init();
|
|
121
|
+
assert.equal(ai.getActiveProvider(), 'ollama');
|
|
122
|
+
|
|
123
|
+
cfg = {
|
|
124
|
+
...cfg,
|
|
125
|
+
custom: {
|
|
126
|
+
baseURL: 'http://custom.test/v1',
|
|
127
|
+
apiKey: 'not-required',
|
|
128
|
+
model: 'custom-model',
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const switched = await ai.switchProvider(' CUSTOM ');
|
|
133
|
+
|
|
134
|
+
assert.equal(switched, 'custom');
|
|
135
|
+
assert.equal(ai.getActiveProvider(), 'custom');
|
|
136
|
+
assert.equal(ai.providers.custom.model, 'custom-model');
|
|
137
|
+
});
|