winter-super-cli 2026.6.19 → 2026.6.20

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.
@@ -861,20 +861,20 @@ export class ToolExecutor {
861
861
 
862
862
  async mcp(serverName, toolName, argumentsObject = {}) {
863
863
  if (typeof serverName !== 'string' || serverName.trim() === '') {
864
- return { success: false, error: 'server is required' };
864
+ return { success: false, error: 'server is required', recovery: 'Example: MCP {"server":"filesystem","tool":"read_file","arguments":{}}' };
865
865
  }
866
866
  if (typeof toolName !== 'string' || toolName.trim() === '') {
867
- return { success: false, error: 'tool is required' };
867
+ return { success: false, error: 'tool is required', recovery: 'Example: MCP {"server":"filesystem","tool":"read_file","arguments":{}}' };
868
868
  }
869
869
 
870
870
  const allowed = await this.permissionManager.isMcpServerAllowed(serverName);
871
871
  if (!allowed) {
872
- return { success: false, error: `MCP server not allowlisted: ${serverName}` };
872
+ return { success: false, error: `MCP server not allowlisted: ${serverName}`, recovery: 'Allowlist this MCP server only after verifying it is trusted, then retry the same tool call.' };
873
873
  }
874
874
 
875
875
  const client = await this.getMcpClient(serverName);
876
876
  if (!client) {
877
- return { success: false, error: `MCP server not configured: ${serverName}` };
877
+ return { success: false, error: `MCP server not configured: ${serverName}`, recovery: 'Configure this MCP server in Winter config before calling its tools, or choose a configured server.' };
878
878
  }
879
879
 
880
880
  const retryPolicy = await this.getRetryPolicy();
@@ -882,7 +882,7 @@ export class ToolExecutor {
882
882
  const result = await withRetry(() => client.callTool(toolName, argumentsObject), retryPolicy);
883
883
  return { success: true, server: serverName, tool: toolName, result };
884
884
  } catch (error) {
885
- return { success: false, error: error.message, server: serverName, tool: toolName };
885
+ return { success: false, error: error.message, server: serverName, tool: toolName, recovery: 'Inspect the MCP server error, verify the tool name and arguments, then retry with corrected arguments.' };
886
886
  }
887
887
  }
888
888
 
@@ -1098,7 +1098,7 @@ export class ToolExecutor {
1098
1098
 
1099
1099
  async readFile(filePath) {
1100
1100
  if (!filePath) {
1101
- return { success: false, error: 'file_path is required' };
1101
+ return { success: false, error: 'file_path is required', recovery: 'Example: Read {"file_path":"src/app.js"}' };
1102
1102
  }
1103
1103
 
1104
1104
  try {
@@ -1142,7 +1142,7 @@ export class ToolExecutor {
1142
1142
  ].join(' '),
1143
1143
  };
1144
1144
  }
1145
- return { success: false, error: error.message, code: error?.code, path: filePath };
1145
+ return { success: false, error: error.message, code: error?.code, path: filePath, recovery: 'Check the path, permissions, and workspace boundary. Use Glob to confirm the file exists before retrying.' };
1146
1146
  }
1147
1147
  }
1148
1148
 
@@ -1210,10 +1210,10 @@ export class ToolExecutor {
1210
1210
 
1211
1211
  async writeFile(filePath, content) {
1212
1212
  if (!filePath) {
1213
- return { success: false, error: 'file_path is required' };
1213
+ return { success: false, error: 'file_path is required', recovery: 'Example: Write {"file_path":"src/app.js","content":"..."}' };
1214
1214
  }
1215
1215
  if (typeof content !== 'string') {
1216
- return { success: false, error: 'content is required', path: filePath };
1216
+ return { success: false, error: 'content is required', path: filePath, recovery: 'Example: Write {"file_path":"src/app.js","content":"..."}' };
1217
1217
  }
1218
1218
 
1219
1219
  try {
@@ -1236,7 +1236,7 @@ export class ToolExecutor {
1236
1236
 
1237
1237
  return { success: true, path: filePath, size: content.length, diff: diffOutput };
1238
1238
  } catch (error) {
1239
- return { success: false, error: error.message, path: filePath };
1239
+ return { success: false, error: error.message, path: filePath, recovery: 'Check that the path is inside the workspace and writable. If editing, use Read first to confirm exact content.' };
1240
1240
  }
1241
1241
  }
1242
1242
 
@@ -1319,7 +1319,7 @@ export class ToolExecutor {
1319
1319
 
1320
1320
  async editFile(filePath, oldString, newString) {
1321
1321
  if (!filePath) {
1322
- return { success: false, error: 'file_path is required' };
1322
+ return { success: false, error: 'file_path is required', recovery: 'Example: Read {"file_path":"src/app.js"}' };
1323
1323
  }
1324
1324
  if (typeof oldString !== 'string' || typeof newString !== 'string') {
1325
1325
  return {
@@ -1355,13 +1355,13 @@ export class ToolExecutor {
1355
1355
 
1356
1356
  return { success: true, path: filePath, replacements: 1, diff: diffOutput };
1357
1357
  } catch (error) {
1358
- return { success: false, error: error.message, path: filePath };
1358
+ return { success: false, error: error.message, path: filePath, recovery: 'Check that the path is inside the workspace and writable. If editing, use Read first to confirm exact content.' };
1359
1359
  }
1360
1360
  }
1361
1361
 
1362
1362
  async bash(command, cwd, timeout = 60000, shell = 'auto') {
1363
1363
  if (typeof command !== 'string' || command.trim() === '') {
1364
- return { success: false, error: 'command is required', exitCode: 1 };
1364
+ return { success: false, error: 'command is required', exitCode: 1, recovery: 'Example: Bash {"command":"npm test"}' };
1365
1365
  }
1366
1366
 
1367
1367
  timeout = parseInt(timeout, 10);
@@ -1402,7 +1402,8 @@ export class ToolExecutor {
1402
1402
  error: error.message,
1403
1403
  stdout: error.stdout || '',
1404
1404
  stderr: error.stderr || '',
1405
- exitCode: error.code || 1
1405
+ exitCode: error.code || 1,
1406
+ recovery: 'Read stderr/stdout, fix the first concrete error, then retry with a corrected command. Do not retry the same failing command unchanged.'
1406
1407
  };
1407
1408
  }
1408
1409
  }
@@ -1466,7 +1467,7 @@ export class ToolExecutor {
1466
1467
  cwd = normalizedRequest.cwd;
1467
1468
 
1468
1469
  if (typeof pattern !== 'string' || pattern.trim() === '') {
1469
- return { success: false, error: 'pattern is required', pattern, cwd };
1470
+ return { success: false, error: 'pattern is required', pattern, cwd, recovery: 'Example: Glob {"pattern":"src/**/*.js"}' };
1470
1471
  }
1471
1472
 
1472
1473
  try {
@@ -1479,7 +1480,7 @@ export class ToolExecutor {
1479
1480
  count: files.length
1480
1481
  };
1481
1482
  } catch (error) {
1482
- return { success: false, error: error.message, pattern, cwd };
1483
+ return { success: false, error: error.message, pattern, cwd, recovery: 'Check the glob pattern and cwd. Example: Glob {"pattern":"src/**/*.js","cwd":"."}' };
1483
1484
  }
1484
1485
  }
1485
1486
 
@@ -1648,7 +1649,7 @@ export class ToolExecutor {
1648
1649
 
1649
1650
  async grep(pattern, searchPath, globPattern, outputMode = 'content', options = {}) {
1650
1651
  if (typeof pattern !== 'string' || pattern === '') {
1651
- return { success: false, error: 'pattern is required', pattern, path: searchPath };
1652
+ return { success: false, error: 'pattern is required', pattern, path: searchPath, recovery: 'Example: Grep {"pattern":"TODO","path":"src"}' };
1652
1653
  }
1653
1654
 
1654
1655
  const caseInsensitive = options.case_insensitive || options.ignoreCase || false;
@@ -1750,7 +1751,7 @@ export class ToolExecutor {
1750
1751
  output_mode: outputMode
1751
1752
  };
1752
1753
  } catch (error) {
1753
- return { success: false, error: error.message, pattern, path: searchPath };
1754
+ return { success: false, error: error.message, pattern, path: searchPath, recovery: 'If this is a regex issue, retry with fixed_string: true. Also verify the search path exists.' };
1754
1755
  }
1755
1756
  }
1756
1757
 
@@ -1854,10 +1855,10 @@ export class ToolExecutor {
1854
1855
 
1855
1856
  async lsp(operation, input, filePath) {
1856
1857
  if (typeof operation !== 'string' || operation.trim() === '') {
1857
- return { success: false, error: 'operation is required' };
1858
+ return { success: false, error: 'operation is required', recovery: 'Example: LSP {"operation":"definition","file_path":"src/app.js"}' };
1858
1859
  }
1859
1860
  if (!filePath) {
1860
- return { success: false, error: 'file_path is required' };
1861
+ return { success: false, error: 'file_path is required', recovery: 'Example: Read {"file_path":"src/app.js"}' };
1861
1862
  }
1862
1863
 
1863
1864
  return {
@@ -1870,10 +1871,10 @@ export class ToolExecutor {
1870
1871
 
1871
1872
  async taskCreate(title, description) {
1872
1873
  if (typeof title !== 'string' || title.trim() === '') {
1873
- return { success: false, error: 'title is required' };
1874
+ return { success: false, error: 'title is required', recovery: 'Example: TaskCreate {"title":"Fix failing executor test","description":"Investigate and patch the failing path"}' };
1874
1875
  }
1875
1876
  if (!this.repl?.session?.createPlan) {
1876
- return { success: false, error: 'session manager is not available' };
1877
+ return { success: false, error: 'session manager is not available', recovery: 'Task tools require an active Winter REPL session. Use the built-in plan/task UI from an interactive session, or continue without task persistence.' };
1877
1878
  }
1878
1879
 
1879
1880
  const task = await this.repl.session.createPlan(title, description);
@@ -1882,29 +1883,29 @@ export class ToolExecutor {
1882
1883
 
1883
1884
  async taskUpdate(taskId, updates) {
1884
1885
  if (typeof taskId !== 'string' || taskId.trim() === '') {
1885
- return { success: false, error: 'task_id is required' };
1886
+ return { success: false, error: 'task_id is required', recovery: 'Example: TaskUpdate {"task_id":"task-123","updates":{"status":"done"}}' };
1886
1887
  }
1887
1888
  if (!this.repl?.session?.updatePlan) {
1888
- return { success: false, error: 'session manager is not available' };
1889
+ return { success: false, error: 'session manager is not available', recovery: 'Task tools require an active Winter REPL session. Use the built-in plan/task UI from an interactive session, or continue without task persistence.' };
1889
1890
  }
1890
1891
 
1891
1892
  const task = await this.repl.session.updatePlan(taskId, updates);
1892
1893
  if (!task) {
1893
- return { success: false, error: 'Task not found', taskId };
1894
+ return { success: false, error: 'Task not found', taskId, recovery: 'Check the task ID from TaskList or the REPL plan UI, then retry TaskUpdate with the exact task_id.' };
1894
1895
  }
1895
1896
  return { success: true, task };
1896
1897
  }
1897
1898
 
1898
1899
  async taskList() {
1899
1900
  if (!this.repl?.session?.getPlans) {
1900
- return { success: false, error: 'session manager is not available' };
1901
+ return { success: false, error: 'session manager is not available', recovery: 'Task tools require an active Winter REPL session. Use the built-in plan/task UI from an interactive session, or continue without task persistence.' };
1901
1902
  }
1902
1903
  return { success: true, tasks: this.repl.session.getPlans() };
1903
1904
  }
1904
1905
 
1905
1906
  async parallelExecute(calls = [], context = {}) {
1906
1907
  if (!Array.isArray(calls) || calls.length === 0) {
1907
- return { success: false, error: 'tools must be a non-empty array' };
1908
+ return { success: false, error: 'tools must be a non-empty array', recovery: 'Example: Parallel {"tools":[{"name":"Read","input":{"file_path":"src/app.js"}}]}' };
1908
1909
  }
1909
1910
 
1910
1911
  const safeCalls = calls.slice(0, 8).map((call, index) => ({
@@ -1948,7 +1949,7 @@ export class ToolExecutor {
1948
1949
 
1949
1950
  async webFetch(url, prompt) {
1950
1951
  if (typeof url !== 'string' || url.trim() === '') {
1951
- return { success: false, error: 'url is required' };
1952
+ return { success: false, error: 'url is required', recovery: 'Example: WebFetch {"url":"https://example.com"}. Include the https:// scheme.' };
1952
1953
  }
1953
1954
 
1954
1955
  try {
@@ -1969,13 +1970,13 @@ export class ToolExecutor {
1969
1970
  length: cleanText.length
1970
1971
  };
1971
1972
  } catch (error) {
1972
- return { success: false, error: error.message, url };
1973
+ return { success: false, error: error.message, url, recovery: 'Verify the URL is reachable and includes https://. If the page needs JavaScript, use BrowserDebug.' };
1973
1974
  }
1974
1975
  }
1975
1976
 
1976
1977
  async webSearch(query) {
1977
1978
  if (typeof query !== 'string' || query.trim() === '') {
1978
- return { success: false, error: 'query is required' };
1979
+ return { success: false, error: 'query is required', recovery: 'Example: WebSearch {"query":"winter cli"}' };
1979
1980
  }
1980
1981
 
1981
1982
  try {
@@ -2001,7 +2002,7 @@ export class ToolExecutor {
2001
2002
  count: results.length,
2002
2003
  };
2003
2004
  } catch (error) {
2004
- return { success: false, error: error.message, query };
2005
+ return { success: false, error: error.message, query, recovery: 'Check network access, simplify the query, then retry WebSearch.' };
2005
2006
  }
2006
2007
  }
2007
2008
 
@@ -2025,7 +2026,7 @@ export class ToolExecutor {
2025
2026
  }
2026
2027
 
2027
2028
  async browserDebug(url, action) {
2028
- if (!url) return { success: false, error: 'url is required' };
2029
+ if (!url) return { success: false, error: 'url is required', recovery: 'Example: WebFetch {"url":"https://example.com"}. Include the https:// scheme.' };
2029
2030
 
2030
2031
  try {
2031
2032
  const retryPolicy = await this.getRetryPolicy();
@@ -2033,7 +2034,7 @@ export class ToolExecutor {
2033
2034
  try {
2034
2035
  puppeteer = (await import('puppeteer')).default;
2035
2036
  } catch (e) {
2036
- return { success: false, error: 'Thư viện puppeteer chưa được cài đặt. AI HÃY TỰ DÙNG TOOL BASH ĐỂ CHẠY LỆNH: npm install puppeteer --no-save' };
2037
+ return { success: false, error: 'Thư viện puppeteer chưa được cài đặt.', recovery: 'Run Bash {"command":"npm install puppeteer --no-save"} if browser automation is required, or use WebFetch for non-JavaScript pages.' };
2037
2038
  }
2038
2039
 
2039
2040
  const browser = await withRetry(() => puppeteer.launch({ headless: 'new' }), retryPolicy);
@@ -2071,7 +2072,7 @@ export class ToolExecutor {
2071
2072
  actionResult
2072
2073
  };
2073
2074
  } catch (e) {
2074
- return { success: false, error: e.message, url };
2075
+ return { success: false, error: e.message, url, recovery: 'Check that the dev server/page is reachable, then retry BrowserDebug with a valid URL and smaller action.' };
2075
2076
  }
2076
2077
  }
2077
2078
 
@@ -2079,14 +2080,14 @@ export class ToolExecutor {
2079
2080
  const inputPath = this.resolveInputPath(input.input_path ?? input.inputPath ?? input.input, cwd);
2080
2081
  const outputPath = this.resolveInputPath(input.output_path ?? input.outputPath ?? input.output, cwd);
2081
2082
  if (!inputPath || !outputPath) {
2082
- return { success: false, error: 'input_path and output_path are required' };
2083
+ return { success: false, error: 'input_path and output_path are required', recovery: 'Example: HtmlEffectiveness {"input_path":"page.md","output_path":"dist/page.html"}' };
2083
2084
  }
2084
2085
 
2085
2086
  const autoInstall = input.auto_install ?? input.autoInstall ?? true;
2086
2087
  const info = await this.htmlFxManager.info();
2087
2088
  if (!info.binaryReady) {
2088
2089
  if (!autoInstall) {
2089
- return { success: false, error: 'html-effectiveness compiler is not installed. Run winter htmlfx install first.' };
2090
+ return { success: false, error: 'html-effectiveness compiler is not installed. Run winter htmlfx install first.', recovery: 'Run winter htmlfx install first, or retry with auto_install: true.' };
2090
2091
  }
2091
2092
  await this.htmlFxManager.ensureInstalled({ update: false });
2092
2093
  }