winter-super-cli 2026.6.5 → 2026.6.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "winter-super-cli",
3
- "version": "2026.6.5",
3
+ "version": "2026.6.6",
4
4
  "description": "❄️ AI-Powered Development CLI with Interactive REPL",
5
5
  "type": "module",
6
6
  "main": "bin/winter.js",
@@ -57,7 +57,7 @@
57
57
  "diff": "^9.0.0"
58
58
  },
59
59
  "optionalDependencies": {
60
+ "@colbymchenry/codegraph": "^0.7.12",
60
61
  "puppeteer": "^24.43.1"
61
- },
62
- "devDependencies": {}
62
+ }
63
63
  }
@@ -38,6 +38,7 @@ export class AgentRuntime {
38
38
  depth,
39
39
  });
40
40
  const maxToolTurns = amplifier.maxToolTurns || 8;
41
+ let forceTextToolFallback = false;
41
42
 
42
43
  try {
43
44
  for (let i = 0; i < maxToolTurns; i++) {
@@ -46,6 +47,7 @@ export class AgentRuntime {
46
47
  provider: executionProfile.provider,
47
48
  model: executionProfile.model,
48
49
  enableTools: true,
50
+ toolPromptOnly: forceTextToolFallback,
49
51
  requireToolEvidence: requireToolEvidence && !usedTools,
50
52
  }, startedAt, totalUsage);
51
53
 
@@ -73,6 +75,7 @@ export class AgentRuntime {
73
75
  role: 'user',
74
76
  content: repl.buildToolEvidenceCorrection(messages),
75
77
  });
78
+ forceTextToolFallback = true;
76
79
  finalContent = '';
77
80
  continue;
78
81
  }
@@ -32,6 +32,7 @@ export function classifyModelTier(modelName, provider = '') {
32
32
  /claude-3-5-sonnet/i, /claude-opus/i, /claude-4/i, /claude-sonnet-4/i,
33
33
  /gpt-4o/i, /gpt-4-turbo/i, /o1/i, /o3/i,
34
34
  /gemini-2\.5-pro/i, /gemini-2\.0-ultra/i,
35
+ /minimax-?m2\.5/i, /minimax.*m2\.5/i, /minimax/i,
35
36
  /deepseek-v3/i, /deepseek-r1/i,
36
37
  /llama-4/i, /llama-3-70b/i, /llama3-70b/i, /llama3\.1-70b/i, /llama3\.2-90b/i, /llama3\.3/i,
37
38
  /qwen2\.5-?72b/i, /qwen2\.5-?70b/i, /qwen-?2\.5-?72b/i,
@@ -123,7 +124,7 @@ export function classifyModelTier(modelName, provider = '') {
123
124
  if (pattern.test(name)) return MODEL_TIERS.SMALL;
124
125
  }
125
126
 
126
- if (/tiny/i.test(name) || /mini/i.test(name) || /small/i.test(name) || /nano/i.test(name)) {
127
+ if (/\btiny\b/i.test(name) || /(?:^|[-_:/])mini(?:$|[-_:/])/i.test(name) || /\bsmall\b/i.test(name) || /\bnano\b/i.test(name)) {
127
128
  return MODEL_TIERS.TINY;
128
129
  }
129
130
 
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Dynamic System Prompt Builder
3
3
  * Builds context-aware system prompts based on task, role, and session state.
4
- * Small models get compact structural guidance so the task stays in focus.
4
+ * Winter always gives every model the strongest available agent instructions.
5
5
  */
6
6
 
7
- import { isSmallModel, getModelCapabilityLabel } from '../model-capabilities.js';
8
7
  import { formatRuntimeEnvironmentSummary, getRuntimeEnvironment } from '../../cli/runtime-env.js';
9
8
 
10
9
  const BASE_PRINCIPLES = [
@@ -74,35 +73,6 @@ function appendSharedContext(parts, { environment, session, design, resourceCont
74
73
  }
75
74
  }
76
75
 
77
- function buildCompactSmallModelPrompt(options = {}) {
78
- const { tools = [], modelTier } = options;
79
- const parts = [
80
- 'You are Winter, an AI coding assistant running on a ' + getModelCapabilityLabel(modelTier) + '.',
81
- '',
82
- '## Operating Rules',
83
- '1. Understand the user request first. If project state matters, inspect files before answering.',
84
- '2. Operate as an agent: inspect -> hypothesize -> act -> verify -> final.',
85
- '3. Keep context tight. Use only relevant tools and avoid long explanations.',
86
- '4. For coding/debug: Read/Grep/Glob/logs -> Edit/Write -> Bash/test/browser smoke. Do not guess file paths.',
87
- '5. For UI/design: inspect existing components/styles/resources before changing visuals.',
88
- '6. Final answer in Vietnamese. Mention changed files and verification only.',
89
- '',
90
- ];
91
-
92
- const toolList = formatToolList(tools);
93
- if (toolList) parts.push('## Tools', toolList, '');
94
- appendSharedContext(parts, { ...options, includeResources: false });
95
-
96
- parts.push(
97
- '## Response Shape',
98
- '- If action is needed, use tools instead of describing the action.',
99
- '- If an image is provided, analyze the image directly and tie findings to project files when relevant.',
100
- '- Keep final output short and concrete.',
101
- );
102
-
103
- return parts.filter(Boolean).join('\n');
104
- }
105
-
106
76
  function buildStandardSystemPrompt(options = {}) {
107
77
  const { role = 'coding', tools = [], resourceContext } = options;
108
78
  const parts = [
@@ -113,6 +83,7 @@ function buildStandardSystemPrompt(options = {}) {
113
83
  '',
114
84
  '## Tool Usage',
115
85
  'Use tools when they materially improve correctness. Inspect before editing. Verify after changes.',
86
+ 'Use maximum reasoning discipline for every model tier, including tiny, local, free, and routed models.',
116
87
  'Never invent file paths, APIs, command output, or test results.',
117
88
  'For debug work, locate the first hard failure, patch the root cause, and verify with the closest test/build/browser smoke.',
118
89
  'For design/UI work, inspect the existing interface and design resources first; avoid generic placeholder layouts.',
@@ -139,9 +110,7 @@ export function buildSystemPrompt({
139
110
  modelTier,
140
111
  } = {}) {
141
112
  const options = { role, context, tools, session, environment, design, resourceContext, modelTier };
142
- return isSmallModel(modelTier)
143
- ? buildCompactSmallModelPrompt(options)
144
- : buildStandardSystemPrompt(options);
113
+ return buildStandardSystemPrompt(options);
145
114
  }
146
115
 
147
116
  export function buildFastSystemPrompt({
@@ -149,18 +118,10 @@ export function buildFastSystemPrompt({
149
118
  tools = [],
150
119
  modelTier,
151
120
  } = {}) {
152
- if (modelTier && isSmallModel(modelTier)) {
153
- return [
154
- 'Winter (fast mode - small model). Be concise. Use tools when needed.',
155
- tools.length > 0 ? `Tools: ${tools.join(', ')}` : '',
156
- 'Use a brief private plan, then answer in 1 sentence.',
157
- ].filter(Boolean).join('\n');
158
- }
159
-
160
121
  return [
161
- 'You are Winter (fast mode). Be concise. Use tools when needed.',
122
+ 'You are Winter (fast mode with maximum correctness). Be concise, but inspect and use tools when needed.',
162
123
  tools.length > 0 ? `Tools: ${tools.join(', ')}` : '',
163
- 'Keep responses brief and focused on the immediate task.',
124
+ 'Use a brief private plan, then execute or answer with concrete evidence.',
164
125
  ].filter(Boolean).join('\n');
165
126
  }
166
127
 
@@ -176,15 +137,13 @@ export function buildAgentSystemPrompt(role, { tools = [], modelTier } = {}) {
176
137
  };
177
138
 
178
139
  const base = roleConfigs[role] || roleConfigs.coding;
179
- const smallNote = modelTier && isSmallModel(modelTier)
180
- ? '\n\nYou are running on a small model. Keep context tight, use tools early, and keep final output short.'
181
- : '';
140
+ const strengthNote = '\n\nWinter Strength Mode: use the full agent loop, inspect real code, reason carefully, verify results, and avoid unsupported claims regardless of base model size.';
182
141
 
183
142
  return [
184
143
  `You are Winter (${role} agent).`,
185
144
  base,
186
145
  tools.length > 0 ? `\nTools: ${tools.join(', ')}` : '',
187
- smallNote,
146
+ strengthNote,
188
147
  '\nCRITICAL: Output only the requested format. No extra commentary.',
189
148
  ].filter(Boolean).join('\n');
190
149
  }
@@ -293,6 +293,44 @@ export class AIProviderManager {
293
293
  this.tools = tools;
294
294
  }
295
295
 
296
+ normalizeToolDefinitionsForApi(tools = []) {
297
+ if (!Array.isArray(tools)) return [];
298
+
299
+ return tools
300
+ .map(tool => {
301
+ if (!tool || typeof tool !== 'object') return null;
302
+
303
+ if (tool.type === 'function' && tool.function && typeof tool.function === 'object') {
304
+ return tool;
305
+ }
306
+
307
+ if (tool.name && tool.parameters) {
308
+ return {
309
+ type: 'function',
310
+ function: {
311
+ name: tool.name,
312
+ description: tool.description || '',
313
+ parameters: tool.parameters,
314
+ },
315
+ };
316
+ }
317
+
318
+ if (tool.function?.name) {
319
+ return {
320
+ type: 'function',
321
+ function: {
322
+ name: tool.function.name,
323
+ description: tool.function.description || tool.description || '',
324
+ parameters: tool.function.parameters || tool.parameters || { type: 'object', properties: {} },
325
+ },
326
+ };
327
+ }
328
+
329
+ return null;
330
+ })
331
+ .filter(Boolean);
332
+ }
333
+
296
334
  async chat(message, options = {}) {
297
335
  await this.init();
298
336
  const messages = [
@@ -405,8 +443,9 @@ export class AIProviderManager {
405
443
  }
406
444
  }
407
445
 
408
- if (this.tools.length > 0 && options.enableTools) {
409
- body.tools = this.tools;
446
+ if (this.tools.length > 0 && options.enableTools && !options.toolPromptOnly) {
447
+ const tools = this.normalizeToolDefinitionsForApi(this.tools);
448
+ if (tools.length > 0) body.tools = tools;
410
449
  }
411
450
 
412
451
  const headers = {
@@ -460,8 +499,9 @@ export class AIProviderManager {
460
499
  }
461
500
  }
462
501
 
463
- if (this.tools.length > 0 && options.enableTools) {
464
- body.tools = this.tools;
502
+ if (this.tools.length > 0 && options.enableTools && !options.toolPromptOnly) {
503
+ const tools = this.normalizeToolDefinitionsForApi(this.tools);
504
+ if (tools.length > 0) body.tools = tools;
465
505
  }
466
506
 
467
507
  const headers = {
@@ -586,7 +626,7 @@ export class AIProviderManager {
586
626
  const body = {
587
627
  model: options.model || provider.model,
588
628
  messages: currentMessages,
589
- tools: this.tools.length > 0 ? this.tools : undefined,
629
+ tools: this.tools.length > 0 ? this.normalizeToolDefinitionsForApi(this.tools) : undefined,
590
630
  };
591
631
 
592
632
  const headers = {
@@ -681,13 +721,13 @@ export class AIProviderManager {
681
721
  let reasoningPrompt = '';
682
722
  if (options.reasoningLevel || options.reasoningPrompt) {
683
723
  reasoningPrompt = options.reasoningPrompt || new ReasoningConfig({
684
- level: options.reasoningLevel || REASONING_LEVELS.MEDIUM,
724
+ level: options.reasoningLevel || REASONING_LEVELS.MAX,
685
725
  provider: this.activeProvider,
686
726
  modelTier: this._modelTier,
687
727
  }).getPromptInstructions();
688
728
  } else if (taskInfo) {
689
729
  // Auto-inject based on task complexity for providers without API reasoning
690
- const level = complexityToReasoningLevel(taskInfo.type);
730
+ const level = REASONING_LEVELS.MAX;
691
731
  const config = new ReasoningConfig({
692
732
  level,
693
733
  provider: this.activeProvider,
@@ -1,30 +1,19 @@
1
- import { isSmallModel } from './model-capabilities.js';
2
-
3
1
  export function isWeakTier(modelTier = '') {
4
- return isSmallModel(modelTier);
2
+ return true;
5
3
  }
6
4
 
7
5
  export function buildSmallModelAmplification({ modelTier = '', workflowProfile = 'general', depth = 'standard' } = {}) {
8
- const weak = isWeakTier(modelTier);
9
- if (!weak) {
10
- return {
11
- weak: false,
12
- maxToolTurns: 8,
13
- enforceSelfCritique: false,
14
- hint: '',
15
- };
16
- }
17
-
18
6
  const deepLike = depth === 'deep' || /debug|backend|data|devops|ai/.test(workflowProfile);
19
- const maxToolTurns = deepLike ? 14 : 10;
7
+ const maxToolTurns = deepLike ? 18 : 14;
20
8
 
21
9
  const hint = [
22
- '[Small Model Amplifier]',
23
- '- You are running in weak-model compensation mode.',
10
+ '[Winter Strength Amplifier]',
11
+ '- Every model, including tiny/local/free models, must run at Winter maximum capability.',
24
12
  '- Mandatory loop: PLAN (requirements + files + risks) -> TOOL ACTIONS -> VERIFY -> SELF-CHECK -> FINAL.',
25
13
  '- Do not skip verification. If verification fails, iterate until max loops.',
26
14
  '- Before final answer, run a private self-critique: missing edge cases, missing tests, over-claims, and incorrect assumptions.',
27
15
  '- Prefer concrete evidence from tool outputs over reasoning guesses.',
16
+ '- Use CodeGraph/codebase index context before broad file reads when available.',
28
17
  ].join('\n');
29
18
 
30
19
  return {
@@ -34,4 +23,3 @@ export function buildSmallModelAmplification({ modelTier = '', workflowProfile =
34
23
  hint,
35
24
  };
36
25
  }
37
-
@@ -962,6 +962,150 @@ EXECUTION CONTRACT:
962
962
  );
963
963
  }
964
964
 
965
+ buildPlanSlug(task) {
966
+ return String(task || 'plan')
967
+ .toLowerCase()
968
+ .replace(/[^a-z0-9]+/g, '-')
969
+ .replace(/^-+|-+$/g, '')
970
+ .slice(0, 48) || 'plan';
971
+ }
972
+
973
+ getPlanScaffoldSpec(task, workflow = {}) {
974
+ const slug = this.buildPlanSlug(task);
975
+ const featureName = slug.replace(/-/g, ' ');
976
+ const profile = String(workflow.profile || 'general');
977
+ const family = profile.split('-')[0] || 'general';
978
+
979
+ const common = {
980
+ dirs: ['docs', 'tests'],
981
+ files: {
982
+ 'docs/plan-notes.md': [
983
+ `# ${featureName}`,
984
+ '',
985
+ `- Profile: ${profile}`,
986
+ '- Status: scaffolded by Winter plan apply',
987
+ '',
988
+ ].join('\n'),
989
+ 'tests/README.md': [
990
+ '# Test Plan',
991
+ '',
992
+ '- Add smoke tests for the generated plan.',
993
+ '- Keep verification commands close to the final implementation stack.',
994
+ '',
995
+ ].join('\n'),
996
+ },
997
+ };
998
+
999
+ const specs = {
1000
+ webapp: {
1001
+ dirs: ['src/app', `src/features/${slug}`, 'src/components', 'src/lib', 'tests/e2e'],
1002
+ files: {
1003
+ [`src/features/${slug}/README.md`]: `# ${featureName}\n\nFeature slice for the plan.\n`,
1004
+ [`src/features/${slug}/tasks.md`]: '',
1005
+ 'tests/e2e/README.md': '# E2E Tests\n\nAdd Playwright or browser smoke tests here.\n',
1006
+ },
1007
+ },
1008
+ mobile: {
1009
+ dirs: ['src/navigation', `src/features/${slug}`, 'src/screens', 'src/services', 'src/components', 'src/state', 'tests'],
1010
+ files: {
1011
+ [`src/features/${slug}/README.md`]: `# ${featureName}\n\nMobile feature module for screens, hooks, API calls, and state.\n`,
1012
+ [`src/features/${slug}/tasks.md`]: '',
1013
+ 'src/navigation/README.md': '# Navigation\n\nDefine app navigation graph and route ownership here.\n',
1014
+ 'src/services/README.md': '# Services\n\nPlace API clients, storage adapters, and platform services here.\n',
1015
+ },
1016
+ },
1017
+ backend: {
1018
+ dirs: [`src/modules/${slug}`, `src/modules/${slug}/dto`, `src/modules/${slug}/tests`, 'src/config', 'src/common'],
1019
+ files: {
1020
+ [`src/modules/${slug}/README.md`]: `# ${featureName}\n\nBackend module scaffold for routes/controllers/services/tests.\n`,
1021
+ [`src/modules/${slug}/tasks.md`]: '',
1022
+ 'src/config/README.md': '# Config\n\nDocument environment variables and runtime config here.\n',
1023
+ },
1024
+ },
1025
+ desktop: {
1026
+ dirs: ['src/main', 'src/preload', 'src/renderer', `src/features/${slug}`, 'tests'],
1027
+ files: {
1028
+ [`src/features/${slug}/README.md`]: `# ${featureName}\n\nDesktop feature module scaffold.\n`,
1029
+ [`src/features/${slug}/tasks.md`]: '',
1030
+ 'src/main/README.md': '# Main Process\n\nKeep privileged runtime code here.\n',
1031
+ 'src/preload/README.md': '# Preload\n\nExpose minimal validated IPC APIs here.\n',
1032
+ },
1033
+ },
1034
+ ai: {
1035
+ dirs: ['src/ingestion', 'src/retrieval', 'src/generation', 'src/evals', `src/features/${slug}`],
1036
+ files: {
1037
+ [`src/features/${slug}/README.md`]: `# ${featureName}\n\nAI feature scaffold for pipeline wiring and evals.\n`,
1038
+ [`src/features/${slug}/tasks.md`]: '',
1039
+ 'src/evals/README.md': '# Evals\n\nTrack regression prompts, datasets, and quality thresholds here.\n',
1040
+ },
1041
+ },
1042
+ };
1043
+
1044
+ const spec = specs[family] || {
1045
+ dirs: [`src/features/${slug}`, 'src/lib', 'tests'],
1046
+ files: {
1047
+ [`src/features/${slug}/README.md`]: `# ${featureName}\n\nFeature scaffold generated from Winter plan apply.\n`,
1048
+ [`src/features/${slug}/tasks.md`]: '',
1049
+ },
1050
+ };
1051
+
1052
+ return {
1053
+ slug,
1054
+ family,
1055
+ dirs: [...common.dirs, ...spec.dirs],
1056
+ files: { ...common.files, ...spec.files },
1057
+ };
1058
+ }
1059
+
1060
+ async writeFileIfMissing(filePath, content) {
1061
+ try {
1062
+ await fs.writeFile(filePath, content, { encoding: 'utf8', flag: 'wx' });
1063
+ return true;
1064
+ } catch (error) {
1065
+ if (error?.code === 'EEXIST') return false;
1066
+ throw error;
1067
+ }
1068
+ }
1069
+
1070
+ async applyPlanProfileScaffold({ task, selected, workflow }) {
1071
+ const spec = this.getPlanScaffoldSpec(task, workflow);
1072
+ const created = [];
1073
+ const skipped = [];
1074
+
1075
+ for (const dir of spec.dirs) {
1076
+ const dirPath = path.join(this.projectPath, dir);
1077
+ await fs.mkdir(dirPath, { recursive: true });
1078
+ created.push(dir);
1079
+ }
1080
+
1081
+ const taskListContent = [
1082
+ `# ${selected.title}`,
1083
+ '',
1084
+ `- Task: ${task}`,
1085
+ `- Profile: ${workflow.profile}`,
1086
+ '',
1087
+ '## Steps',
1088
+ ...selected.steps.map(step => `- [ ] ${step}`),
1089
+ '',
1090
+ ].join('\n');
1091
+
1092
+ const files = { ...spec.files };
1093
+ for (const fileName of Object.keys(files)) {
1094
+ if (fileName.endsWith('/tasks.md')) {
1095
+ files[fileName] = taskListContent;
1096
+ }
1097
+ }
1098
+
1099
+ for (const [relativePath, content] of Object.entries(files)) {
1100
+ const filePath = path.join(this.projectPath, relativePath);
1101
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
1102
+ const didCreate = await this.writeFileIfMissing(filePath, content);
1103
+ (didCreate ? created : skipped).push(relativePath);
1104
+ }
1105
+
1106
+ return { ...spec, created, skipped };
1107
+ }
1108
+
965
1109
  async exportPlanArtifact({ task, workflow, selected, outputPath, format = 'md' }) {
966
1110
  const normalizedFormat = format === 'json' ? 'json' : 'md';
967
1111
  const finalPath = this.resolvePlanOutputPath(task, normalizedFormat, outputPath);
@@ -1004,6 +1148,7 @@ EXECUTION CONTRACT:
1004
1148
  }
1005
1149
 
1006
1150
  async applyPlanSkeleton({ task, selected, workflow, exportPath = null }) {
1151
+ const scaffold = await this.applyPlanProfileScaffold({ task, selected, workflow });
1007
1152
  const targetPath = path.join(this.projectPath, '.winter', 'plan-task-list.md');
1008
1153
  const skeleton = [
1009
1154
  '# Plan Task List',
@@ -1012,10 +1157,15 @@ EXECUTION CONTRACT:
1012
1157
  `- Profile: ${workflow.profile}`,
1013
1158
  `- Plan: ${selected.title}`,
1014
1159
  ...(exportPath ? [`- Plan File: ${path.relative(this.projectPath, exportPath) || exportPath}`] : []),
1160
+ `- Scaffold Profile: ${scaffold.family}`,
1015
1161
  '',
1016
1162
  '## TODO',
1017
1163
  ...selected.steps.map(step => `- [ ] ${step}`),
1018
1164
  '',
1165
+ '## Scaffold Created',
1166
+ ...scaffold.created.map(item => `- ${item}`),
1167
+ ...(scaffold.skipped.length ? ['', '## Existing Files Kept', ...scaffold.skipped.map(item => `- ${item}`)] : []),
1168
+ '',
1019
1169
  ].join('\n');
1020
1170
  await fs.mkdir(path.dirname(targetPath), { recursive: true });
1021
1171
  await fs.writeFile(targetPath, skeleton, 'utf8');