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.
Files changed (122) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/README.md +66 -0
  3. package/package.json +5 -1
  4. package/resources/local/gsap-skills/.claude-plugin/marketplace.json +20 -0
  5. package/resources/local/gsap-skills/.claude-plugin/plugin.json +6 -0
  6. package/resources/local/gsap-skills/.cursor-plugin/marketplace.json +13 -0
  7. package/resources/local/gsap-skills/.cursor-plugin/plugin.json +22 -0
  8. package/resources/local/gsap-skills/.github/copilot-instructions.md +17 -0
  9. package/resources/local/gsap-skills/.github/instructions/react.instructions.md +15 -0
  10. package/resources/local/gsap-skills/.github/instructions/scrolltrigger.instructions.md +18 -0
  11. package/resources/local/gsap-skills/AGENTS.md +27 -0
  12. package/resources/local/gsap-skills/CLAUDE.md +1 -0
  13. package/resources/local/gsap-skills/GEMINI.md +1 -0
  14. package/resources/local/gsap-skills/LICENSE +21 -0
  15. package/resources/local/gsap-skills/README.md +163 -0
  16. package/resources/local/gsap-skills/assets/gsap-green.svg +7 -0
  17. package/resources/local/gsap-skills/assets/gsap-icon-inverted.svg +15 -0
  18. package/resources/local/gsap-skills/assets/gsap-icon-square.svg +1 -0
  19. package/resources/local/gsap-skills/assets/gsap-white.svg +7 -0
  20. package/resources/local/gsap-skills/examples/README.md +29 -0
  21. package/resources/local/gsap-skills/examples/nuxt/app/app.vue +3 -0
  22. package/resources/local/gsap-skills/examples/nuxt/app/composables/useGSAP.ts +91 -0
  23. package/resources/local/gsap-skills/examples/nuxt/app/pages/index.vue +55 -0
  24. package/resources/local/gsap-skills/examples/nuxt/nuxt.config.ts +4 -0
  25. package/resources/local/gsap-skills/examples/nuxt/package.json +18 -0
  26. package/resources/local/gsap-skills/examples/react/App.jsx +46 -0
  27. package/resources/local/gsap-skills/examples/react/index.html +12 -0
  28. package/resources/local/gsap-skills/examples/react/main.jsx +9 -0
  29. package/resources/local/gsap-skills/examples/react/package.json +21 -0
  30. package/resources/local/gsap-skills/examples/react/vite.config.js +7 -0
  31. package/resources/local/gsap-skills/examples/vanilla/index.html +33 -0
  32. package/resources/local/gsap-skills/examples/vanilla/main.js +36 -0
  33. package/resources/local/gsap-skills/examples/vue/app.vue +47 -0
  34. package/resources/local/gsap-skills/examples/vue/index.html +15 -0
  35. package/resources/local/gsap-skills/examples/vue/main.js +9 -0
  36. package/resources/local/gsap-skills/examples/vue/package.json +19 -0
  37. package/resources/local/gsap-skills/examples/vue/vite.config.js +7 -0
  38. package/resources/local/gsap-skills/skills/gsap-core/SKILL.md +254 -0
  39. package/resources/local/gsap-skills/skills/gsap-frameworks/SKILL.md +266 -0
  40. package/resources/local/gsap-skills/skills/gsap-performance/SKILL.md +79 -0
  41. package/resources/local/gsap-skills/skills/gsap-plugins/SKILL.md +433 -0
  42. package/resources/local/gsap-skills/skills/gsap-react/SKILL.md +136 -0
  43. package/resources/local/gsap-skills/skills/gsap-scrolltrigger/SKILL.md +296 -0
  44. package/resources/local/gsap-skills/skills/gsap-timeline/SKILL.md +107 -0
  45. package/resources/local/gsap-skills/skills/gsap-utils/SKILL.md +284 -0
  46. package/resources/local/gsap-skills/skills/llms.txt +39 -0
  47. package/resources/local/hermes-agent-core/AGENTS.md +1132 -0
  48. package/resources/local/hermes-agent-core/LICENSE +21 -0
  49. package/resources/local/hermes-agent-core/README.md +215 -0
  50. package/resources/local/hermes-agent-core/docs/2026-05-07-s6-overlay-dynamic-subagent-gateways.md +434 -0
  51. package/resources/local/hermes-agent-core/hermes-already-has-routines.md +160 -0
  52. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
  53. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
  54. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
  55. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1021 -0
  56. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +277 -0
  57. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +57 -0
  58. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
  59. package/resources/local/hermes-agent-core/skills/github/DESCRIPTION.md +3 -0
  60. package/resources/local/hermes-agent-core/skills/github/codebase-inspection/SKILL.md +116 -0
  61. package/resources/local/hermes-agent-core/skills/github/github-auth/SKILL.md +247 -0
  62. package/resources/local/hermes-agent-core/skills/github/github-auth/scripts/gh-env.sh +66 -0
  63. package/resources/local/hermes-agent-core/skills/github/github-code-review/SKILL.md +481 -0
  64. package/resources/local/hermes-agent-core/skills/github/github-code-review/references/review-output-template.md +74 -0
  65. package/resources/local/hermes-agent-core/skills/github/github-issues/SKILL.md +370 -0
  66. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/bug-report.md +35 -0
  67. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/feature-request.md +31 -0
  68. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/SKILL.md +367 -0
  69. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
  70. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
  71. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
  72. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
  73. package/resources/local/hermes-agent-core/skills/github/github-repo-management/SKILL.md +516 -0
  74. package/resources/local/hermes-agent-core/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
  75. package/resources/local/hermes-agent-core/skills/mcp/DESCRIPTION.md +3 -0
  76. package/resources/local/hermes-agent-core/skills/mcp/native-mcp/SKILL.md +357 -0
  77. package/resources/local/hermes-agent-core/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
  78. package/resources/local/hermes-agent-core/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
  79. package/resources/local/hermes-agent-core/skills/software-development/hermes-s6-container-supervision/SKILL.md +176 -0
  80. package/resources/local/hermes-agent-core/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
  81. package/resources/local/hermes-agent-core/skills/software-development/plan/SKILL.md +58 -0
  82. package/resources/local/hermes-agent-core/skills/software-development/python-debugpy/SKILL.md +375 -0
  83. package/resources/local/hermes-agent-core/skills/software-development/requesting-code-review/SKILL.md +280 -0
  84. package/resources/local/hermes-agent-core/skills/software-development/spike/SKILL.md +197 -0
  85. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/SKILL.md +352 -0
  86. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
  87. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
  88. package/resources/local/hermes-agent-core/skills/software-development/systematic-debugging/SKILL.md +367 -0
  89. package/resources/local/hermes-agent-core/skills/software-development/test-driven-development/SKILL.md +343 -0
  90. package/resources/local/hermes-agent-core/skills/software-development/writing-plans/SKILL.md +297 -0
  91. package/resources/local/manifest.json +12 -0
  92. package/rule.md +2 -0
  93. package/scripts/audit-pack.js +5 -0
  94. package/scripts/smoke-browser.js +53 -0
  95. package/scripts/smoke-package.js +38 -4
  96. package/skill.md +36 -4
  97. package/skills/gsap.md +26 -0
  98. package/skills/hermes-agent.md +17 -0
  99. package/src/agent/agent-definitions.js +4 -4
  100. package/src/agent/runtime.js +179 -5
  101. package/src/agent/subagent-child.js +44 -0
  102. package/src/ai/capability-scorecard.js +193 -14
  103. package/src/ai/hermes-core.js +77 -0
  104. package/src/ai/model-capabilities.js +42 -2
  105. package/src/ai/prompts/system-prompt.js +16 -2
  106. package/src/ai/small-model-amplifier.js +35 -7
  107. package/src/ai/workflow-selector.js +22 -1
  108. package/src/cli/commands.js +21 -1
  109. package/src/cli/config.js +42 -4
  110. package/src/cli/context-loader.js +253 -9
  111. package/src/cli/conversation-format.js +5 -0
  112. package/src/cli/input-controller.js +79 -10
  113. package/src/cli/prompt-builder.js +45 -8
  114. package/src/cli/repl-commands.js +115 -0
  115. package/src/cli/repl.js +147 -86
  116. package/src/cli/slash-commands.js +3 -1
  117. package/src/cli/tui.js +133 -37
  118. package/src/mcp/client.js +46 -5
  119. package/src/tools/agent.js +316 -25
  120. package/src/tools/executor.js +310 -9
  121. package/src/tools/permission.js +20 -17
  122. package/winter.d.ts +112 -10
@@ -30,7 +30,14 @@ export class ToolExecutor {
30
30
  constructor(repl) {
31
31
  this.repl = repl;
32
32
  this.projectPath = repl?.projectPath || process.cwd();
33
- this.allowedCommands = ['git', 'npm', 'node', 'python', 'code', 'pnpm', 'yarn', 'bun', 'pip', 'cargo', 'rustc', 'echo', 'printf', 'cat', 'ls', 'dir', 'type', 'copy', 'mkdir', 'get-childitem', 'set-content', 'get-content', 'test-path', 'get-date'];
33
+ this.allowedCommands = [
34
+ 'git', 'npm', 'npx', 'node', 'python', 'code', 'pnpm', 'yarn', 'bun', 'pip', 'cargo', 'rustc',
35
+ 'echo', 'printf', 'cat', 'ls', 'dir', 'type', 'copy', 'mkdir', 'get-childitem', 'set-content',
36
+ 'get-content', 'test-path', 'get-date',
37
+ 'ping', 'test-connection', 'curl', 'wget', 'iwr', 'irm', 'invoke-webrequest', 'invoke-restmethod',
38
+ 'nslookup', 'resolve-dnsname', 'tracert', 'traceroute', 'pathping', 'dig', 'ipconfig', 'ifconfig',
39
+ 'ip', 'netstat', 'speedtest', 'speedtest-cli', 'measure-command',
40
+ ];
34
41
  this.blockedPatterns = [
35
42
  { pattern: /\brm\s+-[^\n;|&]*r[^\n;|&]*f\b|\brm\s+-[^\n;|&]*f[^\n;|&]*r\b/i, label: 'rm -rf' },
36
43
  { pattern: /\bremove-item\b[^\n;|&]*(?:-recurse\b[^\n;|&]*-force\b|-force\b[^\n;|&]*-recurse\b)/i, label: 'Remove-Item -Recurse -Force' },
@@ -334,18 +341,68 @@ export class ToolExecutor {
334
341
  {
335
342
  type: 'function',
336
343
  name: 'Agent',
337
- description: 'Spawn a subagent to execute a complex task with planning, execution, and verification workflow.',
344
+ description: 'Spawn and await a real isolated subagent conversation with scoped tools, timeout, execution, verification, and result passing.',
338
345
  parameters: {
339
346
  type: 'object',
340
347
  properties: {
341
348
  task: { type: 'string', description: 'Task description for the agent' },
349
+ role: { type: 'string', description: 'Agent role/profile, e.g. general, debug, review, design, research, swe' },
350
+ context: { type: 'string', description: 'Parent context to pass into the subagent' },
351
+ tools: { type: 'array', items: { type: 'string' }, description: 'Optional restricted tool allowlist for this subagent' },
352
+ process_isolation: { type: 'boolean', description: 'Run subagent in a child process. Defaults true in live REPL.' },
342
353
  max_steps: { type: 'number', description: 'Maximum execution steps (default: 10, max: 25)' },
354
+ timeout_ms: { type: 'number', description: 'Timeout for the subagent run' },
343
355
  provider: { type: 'string', description: 'AI provider to use for this agent' },
344
356
  cwd: { type: 'string', description: 'Working directory' },
345
357
  },
346
358
  required: ['task']
347
359
  }
348
360
  },
361
+ {
362
+ type: 'function',
363
+ name: 'DelegateTask',
364
+ description: 'Delegate a task to a real subagent and wait for summary, changed files, tool evidence, usage, and errors. Alias of Agent with clearer delegation semantics.',
365
+ parameters: {
366
+ type: 'object',
367
+ properties: {
368
+ goal: { type: 'string', description: 'Goal or task for the delegated subagent' },
369
+ task: { type: 'string', description: 'Task description for the delegated subagent' },
370
+ role: { type: 'string', description: 'Agent role/profile' },
371
+ context: { type: 'string', description: 'Parent context to pass into the subagent' },
372
+ tools: { type: 'array', items: { type: 'string' }, description: 'Restricted tool allowlist' },
373
+ process_isolation: { type: 'boolean', description: 'Run subagent in a child process. Defaults true in live REPL.' },
374
+ max_steps: { type: 'number', description: 'Maximum execution steps' },
375
+ timeout_ms: { type: 'number', description: 'Timeout for the delegated run' },
376
+ provider: { type: 'string', description: 'AI provider to use for this subagent' },
377
+ cwd: { type: 'string', description: 'Working directory' },
378
+ }
379
+ }
380
+ },
381
+ {
382
+ type: 'function',
383
+ name: 'ParallelAgent',
384
+ description: 'Run multiple real delegated subagents concurrently and aggregate their summaries, changed files, tool evidence, and failures.',
385
+ parameters: {
386
+ type: 'object',
387
+ properties: {
388
+ tasks: {
389
+ type: 'array',
390
+ items: {
391
+ type: 'object',
392
+ properties: {
393
+ goal: { type: 'string' },
394
+ task: { type: 'string' },
395
+ role: { type: 'string' },
396
+ tools: { type: 'array', items: { type: 'string' } },
397
+ }
398
+ }
399
+ },
400
+ concurrency: { type: 'number', description: 'Maximum subagents to run at once, capped at 6' },
401
+ timeout_ms: { type: 'number', description: 'Timeout per subagent' },
402
+ },
403
+ required: ['tasks']
404
+ }
405
+ },
349
406
  {
350
407
  type: 'function',
351
408
  name: 'InsertText',
@@ -388,6 +445,25 @@ export class ToolExecutor {
388
445
  required: ['url']
389
446
  }
390
447
  },
448
+ {
449
+ type: 'function',
450
+ name: 'VisibleBrowser',
451
+ description: 'Launch and control a real visible Chrome/Chromium browser with Puppeteer. Use when the user asks Winter to actually click, type, navigate, inspect, or screenshot a page and chrome-devtools MCP is unavailable. Actions: open, navigate, click, type, evaluate, screenshot, snapshot.',
452
+ parameters: {
453
+ type: 'object',
454
+ properties: {
455
+ url: { type: 'string', description: 'URL to open or navigate to. Defaults to about:blank.' },
456
+ action: { type: 'string', description: 'open, navigate, click, type, evaluate, screenshot, or snapshot' },
457
+ selector: { type: 'string', description: 'CSS selector for click/type/snapshot targeting' },
458
+ text: { type: 'string', description: 'Text to type for action=type' },
459
+ script: { type: 'string', description: 'JavaScript expression/function body for action=evaluate' },
460
+ wait_for: { type: 'string', description: 'Optional CSS selector to wait for after navigation/action' },
461
+ screenshot_path: { type: 'string', description: 'Optional output PNG path for action=screenshot' },
462
+ keep_open: { type: 'boolean', description: 'Leave the browser open after action. Default false.' },
463
+ browser: { type: 'string', description: 'chrome or chromium. Defaults to chrome.' }
464
+ }
465
+ }
466
+ },
391
467
  {
392
468
  type: 'function',
393
469
  name: 'OpenBrowser',
@@ -544,6 +620,8 @@ export class ToolExecutor {
544
620
  return await this.parallelExecute(input.tools ?? input.calls ?? [], { cwd });
545
621
  case 'BrowserDebug':
546
622
  return await this.browserDebug(input.url ?? input.uri, input.action);
623
+ case 'VisibleBrowser':
624
+ return await this.visibleBrowser(input, cwd);
547
625
  case 'OpenBrowser':
548
626
  return await this.openBrowser(input.url ?? input.uri ?? input.href, input.browser);
549
627
  case 'WebFetch':
@@ -563,7 +641,35 @@ export class ToolExecutor {
563
641
  case 'AskUserQuestion':
564
642
  return await this.interactiveTool.askQuestion(input.questions ?? input.question);
565
643
  case 'Agent':
566
- return await this.agentTool.run(input.task, { maxSteps: input.max_steps ?? input.maxSteps, provider: input.provider, cwd: input.cwd });
644
+ return await this.agentTool.run(input.task, {
645
+ role: input.role ?? input.agent,
646
+ context: input.context,
647
+ tools: input.tools,
648
+ processIsolation: input.process_isolation ?? input.processIsolation,
649
+ maxSteps: input.max_steps ?? input.maxSteps,
650
+ timeoutMs: input.timeout_ms ?? input.timeoutMs,
651
+ provider: input.provider,
652
+ cwd: input.cwd,
653
+ });
654
+ case 'DelegateTask':
655
+ return await this.agentTool.run(input.task ?? input.goal, {
656
+ role: input.role ?? input.agent,
657
+ context: input.context,
658
+ tools: input.tools,
659
+ processIsolation: input.process_isolation ?? input.processIsolation,
660
+ maxSteps: input.max_steps ?? input.maxSteps,
661
+ timeoutMs: input.timeout_ms ?? input.timeoutMs,
662
+ provider: input.provider,
663
+ cwd: input.cwd,
664
+ });
665
+ case 'ParallelAgent':
666
+ return await this.agentTool.runParallel(input.tasks, {
667
+ concurrency: input.concurrency,
668
+ timeoutMs: input.timeout_ms ?? input.timeoutMs,
669
+ processIsolation: input.process_isolation ?? input.processIsolation,
670
+ provider: input.provider,
671
+ cwd: input.cwd,
672
+ });
567
673
  case 'InsertText':
568
674
  return await this.insertTextTool.insert(this.resolveInputPath(input.file_path ?? input.path ?? input.file, cwd), input.insert_text ?? input.text ?? input.content, input);
569
675
  case 'StrReplaceAll':
@@ -586,7 +692,7 @@ export class ToolExecutor {
586
692
  return {
587
693
  success: false,
588
694
  error: `Unknown tool: ${toolName}`,
589
- availableTools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'TaskCreate', 'TaskUpdate', 'TaskList', 'MCP', 'Parallel', 'OpenBrowser', 'BrowserDebug', 'WebFetch', 'WebSearch', 'WebArchive', 'HtmlEffectiveness', 'NotebookRead', 'NotebookEdit', 'TodoWrite', 'TodoList', 'ScheduleWakeup', 'AskUserQuestion', 'Agent', 'InsertText', 'StrReplaceAll'],
695
+ availableTools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'TaskCreate', 'TaskUpdate', 'TaskList', 'MCP', 'Parallel', 'OpenBrowser', 'VisibleBrowser', 'BrowserDebug', 'WebFetch', 'WebSearch', 'WebArchive', 'HtmlEffectiveness', 'NotebookRead', 'NotebookEdit', 'TodoWrite', 'TodoList', 'ScheduleWakeup', 'AskUserQuestion', 'Agent', 'DelegateTask', 'ParallelAgent', 'InsertText', 'StrReplaceAll'],
590
696
  recovery: 'Call one of the available tools. For file writes use Write with { "file_path": "...", "content": "..." }. For shell commands use Bash with { "command": "..." }.',
591
697
  };
592
698
  }
@@ -730,9 +836,9 @@ export class ToolExecutor {
730
836
  return { success: true, coerced: true, args: { notebook_path: notebookPath, cell_id: cellId, new_source: newSource } };
731
837
  }
732
838
 
733
- if (toolName === 'WebFetch' || toolName === 'WebArchive' || toolName === 'BrowserDebug') {
839
+ if (toolName === 'WebFetch' || toolName === 'WebArchive' || toolName === 'BrowserDebug' || toolName === 'VisibleBrowser') {
734
840
  const url = pick('url', 'uri', 'href');
735
- if (!url) {
841
+ if (!url && toolName !== 'VisibleBrowser') {
736
842
  return { success: false, error: 'url is required', recovery: `Example: ${toolName} {"url":"https://example.com"}` };
737
843
  }
738
844
  const next = { ...args, url };
@@ -745,6 +851,21 @@ export class ToolExecutor {
745
851
  return { success: true, coerced: true, args: { ...args, url, browser } };
746
852
  }
747
853
 
854
+ if (toolName === 'Agent' || toolName === 'DelegateTask') {
855
+ const task = pick('task', 'goal', 'prompt', 'description');
856
+ if (!task) {
857
+ return { success: false, error: 'task is required', recovery: `Example: ${toolName} {"task":"Inspect the failing test and report the first blocker"}` };
858
+ }
859
+ return { success: true, coerced: true, args: { ...args, task } };
860
+ }
861
+
862
+ if (toolName === 'ParallelAgent') {
863
+ if (!Array.isArray(args.tasks) || args.tasks.length === 0) {
864
+ return { success: false, error: 'tasks array is required', recovery: 'Example: ParallelAgent {"tasks":[{"goal":"Review auth"},{"goal":"Inspect tests"}]}' };
865
+ }
866
+ return { success: true, coerced: true, args };
867
+ }
868
+
748
869
  if (toolName === 'WebSearch') {
749
870
  const query = pick('query', 'q', 'search', 'search_query', 'searchQuery');
750
871
  if (!query) {
@@ -783,6 +904,9 @@ export class ToolExecutor {
783
904
  const cfg = await this.getRuntimeConfig();
784
905
  const permissionCommands = cfg.permissions?.allowlist?.commands || [];
785
906
  const sandbox = cfg.sandbox || {};
907
+ if (sandbox.enabled === false) {
908
+ return { success: true };
909
+ }
786
910
  const sandboxCommands = sandbox.enabled === false ? [] : (sandbox.allowedCommands || this.allowedCommands);
787
911
  const allowed = new Set([
788
912
  ...this.allowedCommands,
@@ -842,14 +966,19 @@ export class ToolExecutor {
842
966
  const summary = {
843
967
  success: result.success !== false,
844
968
  };
845
- for (const key of ['error', 'path', 'count', 'exitCode', 'server', 'tool']) {
969
+ for (const key of ['error', 'path', 'count', 'exitCode', 'server', 'tool', 'url', 'title', 'action', 'visible', 'controlled', 'keptOpen', 'agentId', 'role', 'status', 'summary', 'processIsolated', 'childPid']) {
846
970
  if (result[key] !== undefined) summary[key] = result[key];
847
971
  }
848
972
  if (typeof result.stdout === 'string') summary.stdout = result.stdout.slice(0, 1000);
849
973
  if (typeof result.stderr === 'string') summary.stderr = result.stderr.slice(0, 1000);
850
974
  if (typeof result.content === 'string') summary.content = result.content.slice(0, 1000);
975
+ if (typeof result.domSnippet === 'string') summary.domSnippet = result.domSnippet.slice(0, 1000);
976
+ if (Array.isArray(result.consoleErrors)) summary.consoleErrors = result.consoleErrors.slice(-10);
977
+ if (Array.isArray(result.networkErrors)) summary.networkErrors = result.networkErrors.slice(-10);
851
978
  if (Array.isArray(result.files)) summary.files = result.files.slice(0, 20);
852
979
  if (Array.isArray(result.matches)) summary.matches = result.matches.slice(0, 20);
980
+ if (Array.isArray(result.changedFiles)) summary.changedFiles = result.changedFiles.slice(0, 20);
981
+ if (Array.isArray(result.toolSummaries)) summary.toolSummaries = result.toolSummaries.slice(0, 20);
853
982
  return summary;
854
983
  }
855
984
 
@@ -907,10 +1036,32 @@ export class ToolExecutor {
907
1036
 
908
1037
  const retryPolicy = await this.getRetryPolicy();
909
1038
  try {
910
- const result = await withRetry(() => client.callTool(toolName, argumentsObject), retryPolicy);
1039
+ const result = await withRetry(() => client.callTool(toolName, argumentsObject), {
1040
+ ...retryPolicy,
1041
+ retryable: error => error?.code !== 'MCP_REQUEST_TIMEOUT',
1042
+ });
911
1043
  return { success: true, server: serverName, tool: toolName, result };
912
1044
  } catch (error) {
913
- 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.' };
1045
+ if (error?.code === 'MCP_REQUEST_TIMEOUT') {
1046
+ await client.close();
1047
+ this.mcpClients.delete(serverName);
1048
+ return {
1049
+ success: false,
1050
+ error: error.message,
1051
+ code: error.code,
1052
+ server: serverName,
1053
+ tool: toolName,
1054
+ timeoutMs: error.timeoutMs,
1055
+ recovery: `MCP server "${serverName}" did not answer "${toolName}" before the timeout. Do not blindly retry the same call. First run /mcp tools ${serverName} to confirm the server responds, narrow the tool arguments, or increase this server's requestTimeoutMs if the tool is expected to be slow.`,
1056
+ };
1057
+ }
1058
+ return {
1059
+ success: false,
1060
+ error: error.message,
1061
+ server: serverName,
1062
+ tool: toolName,
1063
+ recovery: `MCP tool "${toolName}" failed on server "${serverName}". Check the server stderr/logs and compare the arguments with /mcp tools ${serverName}; retry only after correcting the failing input.`,
1064
+ };
914
1065
  }
915
1066
  }
916
1067
 
@@ -1007,6 +1158,15 @@ export class ToolExecutor {
1007
1158
  browseropen: 'OpenBrowser',
1008
1159
  openchrome: 'OpenBrowser',
1009
1160
  launchchrome: 'OpenBrowser',
1161
+ visiblebrowser: 'VisibleBrowser',
1162
+ visible_browser: 'VisibleBrowser',
1163
+ browsercontrol: 'VisibleBrowser',
1164
+ browser_control: 'VisibleBrowser',
1165
+ browseraction: 'VisibleBrowser',
1166
+ chromecontrol: 'VisibleBrowser',
1167
+ chrome_control: 'VisibleBrowser',
1168
+ clickbrowser: 'VisibleBrowser',
1169
+ browserclick: 'VisibleBrowser',
1010
1170
  browserdebug: 'BrowserDebug',
1011
1171
  browser: 'BrowserDebug',
1012
1172
  browserinspect: 'BrowserDebug',
@@ -1049,6 +1209,13 @@ export class ToolExecutor {
1049
1209
  agent: 'Agent',
1050
1210
  subagent: 'Agent',
1051
1211
  agentrun: 'Agent',
1212
+ delegatetask: 'DelegateTask',
1213
+ delegate: 'DelegateTask',
1214
+ taskdelegate: 'DelegateTask',
1215
+ spawnagent: 'DelegateTask',
1216
+ parallelagent: 'ParallelAgent',
1217
+ multiagent: 'ParallelAgent',
1218
+ parallelagents: 'ParallelAgent',
1052
1219
  };
1053
1220
  return aliases[normalized] || raw;
1054
1221
  }
@@ -1078,6 +1245,7 @@ export class ToolExecutor {
1078
1245
  case 'WebFetch':
1079
1246
  case 'WebArchive':
1080
1247
  case 'BrowserDebug':
1248
+ case 'VisibleBrowser':
1081
1249
  return { url: value };
1082
1250
  case 'TaskCreate':
1083
1251
  case 'TodoWrite':
@@ -1085,6 +1253,7 @@ export class ToolExecutor {
1085
1253
  case 'ScheduleWakeup':
1086
1254
  return { prompt: value };
1087
1255
  case 'Agent':
1256
+ case 'DelegateTask':
1088
1257
  return { task: value };
1089
1258
  default:
1090
1259
  return { input: value };
@@ -2109,6 +2278,138 @@ export class ToolExecutor {
2109
2278
  }
2110
2279
  }
2111
2280
 
2281
+ async visibleBrowser(input = {}, cwd = this.projectPath) {
2282
+ const url = String(input.url ?? input.uri ?? input.href ?? 'about:blank');
2283
+ const action = String(input.action || (url ? 'open' : 'snapshot')).toLowerCase();
2284
+ const selector = input.selector || input.css || input.target;
2285
+ const text = input.text ?? input.value ?? input.input;
2286
+ const script = input.script ?? input.js ?? input.code;
2287
+ const waitFor = input.wait_for ?? input.waitFor;
2288
+ const keepOpen = input.keep_open === true || input.keepOpen === true;
2289
+ const browserName = String(input.browser || 'chrome').toLowerCase();
2290
+ const screenshotPath = input.screenshot_path ?? input.screenshotPath;
2291
+
2292
+ let puppeteer;
2293
+ try {
2294
+ puppeteer = (await import('puppeteer')).default;
2295
+ } catch {
2296
+ return {
2297
+ success: false,
2298
+ error: 'Thư viện puppeteer chưa được cài đặt.',
2299
+ recovery: 'Run Bash {"command":"npm install puppeteer --no-save"} or configure chrome-devtools MCP, then retry VisibleBrowser.',
2300
+ };
2301
+ }
2302
+
2303
+ let browser;
2304
+ try {
2305
+ const launchOptions = {
2306
+ headless: false,
2307
+ defaultViewport: null,
2308
+ args: ['--start-maximized'],
2309
+ };
2310
+ if (browserName === 'chrome') {
2311
+ launchOptions.channel = 'chrome';
2312
+ }
2313
+
2314
+ browser = await puppeteer.launch(launchOptions).catch(async error => {
2315
+ if (launchOptions.channel) {
2316
+ const fallbackOptions = { ...launchOptions };
2317
+ delete fallbackOptions.channel;
2318
+ return await puppeteer.launch(fallbackOptions);
2319
+ }
2320
+ throw error;
2321
+ });
2322
+
2323
+ const page = await browser.newPage();
2324
+ const consoleLogs = [];
2325
+ const networkErrors = [];
2326
+ page.on('console', msg => {
2327
+ if (['error', 'warning'].includes(msg.type())) {
2328
+ consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
2329
+ }
2330
+ });
2331
+ page.on('requestfailed', request => {
2332
+ networkErrors.push(`${request.method()} ${request.url()} - ${request.failure()?.errorText}`);
2333
+ });
2334
+
2335
+ if (url && url !== 'about:blank') {
2336
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
2337
+ } else {
2338
+ await page.goto('about:blank', { waitUntil: 'domcontentloaded', timeout: 30000 });
2339
+ }
2340
+
2341
+ let actionResult = null;
2342
+ if (waitFor) {
2343
+ await page.waitForSelector(waitFor, { timeout: 15000 });
2344
+ }
2345
+
2346
+ if (action === 'navigate' || action === 'open') {
2347
+ actionResult = { navigated: page.url() };
2348
+ } else if (action === 'click') {
2349
+ if (!selector) throw new Error('selector is required for VisibleBrowser action=click');
2350
+ await page.waitForSelector(selector, { timeout: 15000 });
2351
+ await page.click(selector);
2352
+ actionResult = { clicked: selector };
2353
+ } else if (action === 'type' || action === 'fill') {
2354
+ if (!selector) throw new Error('selector is required for VisibleBrowser action=type');
2355
+ await page.waitForSelector(selector, { timeout: 15000 });
2356
+ await page.click(selector, { clickCount: 3 });
2357
+ await page.type(selector, String(text ?? ''), { delay: 10 });
2358
+ actionResult = { typed: selector, text: String(text ?? '') };
2359
+ } else if (action === 'evaluate' || action === 'eval') {
2360
+ if (!script) throw new Error('script is required for VisibleBrowser action=evaluate');
2361
+ actionResult = await page.evaluate(source => (0, eval)(source), String(script));
2362
+ } else if (action === 'screenshot') {
2363
+ const outputPath = screenshotPath
2364
+ ? this.resolveInputPath(screenshotPath, cwd)
2365
+ : path.join(cwd, '.winter', `visible-browser-${Date.now()}.png`);
2366
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
2367
+ await page.screenshot({ path: outputPath, fullPage: true });
2368
+ actionResult = { screenshotPath: outputPath };
2369
+ } else if (action === 'snapshot') {
2370
+ actionResult = selector
2371
+ ? await page.$eval(selector, el => el.outerHTML.slice(0, 3000))
2372
+ : await page.evaluate(() => document.body?.innerHTML?.slice(0, 3000) || '');
2373
+ } else {
2374
+ throw new Error(`Unsupported VisibleBrowser action: ${action}`);
2375
+ }
2376
+
2377
+ const title = await page.title().catch(() => '');
2378
+ const currentUrl = page.url();
2379
+ const domSnippet = await page.evaluate(() => document.body?.innerText?.slice(0, 1600) || '').catch(() => '');
2380
+
2381
+ if (!keepOpen) {
2382
+ await browser.close();
2383
+ }
2384
+
2385
+ return {
2386
+ success: true,
2387
+ visible: true,
2388
+ controlled: true,
2389
+ browser: browserName,
2390
+ action,
2391
+ url: currentUrl,
2392
+ title,
2393
+ actionResult,
2394
+ consoleErrors: consoleLogs.slice(-10),
2395
+ networkErrors: networkErrors.slice(-10),
2396
+ domSnippet,
2397
+ keptOpen: keepOpen,
2398
+ };
2399
+ } catch (error) {
2400
+ if (browser && !keepOpen) {
2401
+ await browser.close().catch(() => {});
2402
+ }
2403
+ return {
2404
+ success: false,
2405
+ error: error.message,
2406
+ url,
2407
+ action,
2408
+ recovery: 'Use a valid URL and CSS selector. If Chrome launch fails, install Chrome or retry with browser:"chromium"; for persistent live control use chrome-devtools MCP.',
2409
+ };
2410
+ }
2411
+ }
2412
+
2112
2413
  buildBrowserLaunchCommand(url = 'about:blank', browser = 'chrome', platform = process.platform) {
2113
2414
  const targetUrl = String(url || 'about:blank');
2114
2415
  const targetBrowser = String(browser || 'chrome').toLowerCase();
@@ -13,18 +13,20 @@ export class PermissionManager {
13
13
  const permissions = cfg.permissions || {};
14
14
  const allowlist = permissions.allowlist || {};
15
15
 
16
- return {
17
- promptByDefault: permissions.promptByDefault !== false,
18
- allowedTools: new Set([...(allowlist.tools || []), ...DEFAULT_ALLOWED]),
19
- allowedCommands: new Set(allowlist.commands || []),
20
- allowedServers: new Set(allowlist.mcpServers || []),
21
- };
22
- }
23
-
24
- async isAllowedTool(toolName) {
25
- const policy = await this.getPolicy();
26
- return policy.allowedTools.has(toolName);
27
- }
16
+ return {
17
+ promptByDefault: permissions.promptByDefault !== false,
18
+ fullAccess: cfg.sandbox?.enabled === false,
19
+ allowedTools: new Set([...(allowlist.tools || []), ...DEFAULT_ALLOWED]),
20
+ allowedCommands: new Set(allowlist.commands || []),
21
+ allowedServers: new Set(allowlist.mcpServers || []),
22
+ };
23
+ }
24
+
25
+ async isAllowedTool(toolName) {
26
+ const policy = await this.getPolicy();
27
+ if (policy.fullAccess) return true;
28
+ return policy.allowedTools.has(toolName);
29
+ }
28
30
 
29
31
  async shouldPromptForTool(toolName) {
30
32
  const policy = await this.getPolicy();
@@ -37,11 +39,12 @@ export class PermissionManager {
37
39
  return await this.shouldPromptForTool(toolName);
38
40
  }
39
41
 
40
- async isMcpServerAllowed(serverName) {
41
- if (!serverName) return false;
42
- const policy = await this.getPolicy();
43
- return policy.allowedServers.has(serverName);
44
- }
42
+ async isMcpServerAllowed(serverName) {
43
+ if (!serverName) return false;
44
+ const policy = await this.getPolicy();
45
+ if (policy.fullAccess) return true;
46
+ return policy.allowedServers.has(serverName);
47
+ }
45
48
 
46
49
  async allowTool(toolName) {
47
50
  if (!this.config?.load || !this.config?.save) return;
package/winter.d.ts CHANGED
@@ -56,7 +56,7 @@ declare module './src/cli/snowflake-logo.js' {
56
56
  export function providerStatus(name: string, status: string): string;
57
57
  }
58
58
 
59
- declare module './src/cli/tui.js' {
59
+ declare module './src/cli/tui.js' {
60
60
  export interface TuiHistoryEntry {
61
61
  role?: 'user' | 'assistant' | string;
62
62
  content?: string;
@@ -157,10 +157,98 @@ declare module './src/cli/tui.js' {
157
157
  width?: number;
158
158
  title?: string;
159
159
  }): string;
160
- }
161
-
162
- declare module './src/cli/repl.js' {
163
- export interface WinterREPLOptions {
160
+ }
161
+
162
+ declare module './src/ai/capability-scorecard.js' {
163
+ export interface CapabilityProbe {
164
+ key: string;
165
+ label: string;
166
+ ok?: boolean;
167
+ }
168
+
169
+ export interface CapabilityArea {
170
+ id: string;
171
+ label: string;
172
+ weight: number;
173
+ target: string;
174
+ passed: number;
175
+ total: number;
176
+ score: number;
177
+ percent: number;
178
+ probes: CapabilityProbe[];
179
+ checks: CapabilityProbe[];
180
+ }
181
+
182
+ export interface CapabilityGap {
183
+ id: string;
184
+ label: string;
185
+ missing: string[];
186
+ }
187
+
188
+ export interface CapabilityScorecard {
189
+ target: number;
190
+ overall: number;
191
+ score: number;
192
+ maxScore: number;
193
+ status: 'ready' | 'below-target';
194
+ competitors: Array<{
195
+ name: string;
196
+ strengths: string[];
197
+ }>;
198
+ areas: CapabilityArea[];
199
+ gaps: CapabilityGap[];
200
+ }
201
+
202
+ export const WINTER_CAPABILITY_TARGET: number;
203
+ export function assessWinterCapabilities(repl?: Record<string, unknown>): Promise<CapabilityScorecard>;
204
+ export function formatCapabilityScorecard(
205
+ report: CapabilityScorecard,
206
+ options?: { colors?: Record<string, string> }
207
+ ): string;
208
+ }
209
+
210
+ declare module './src/ai/hermes-core.js' {
211
+ export interface HermesCoreSignals {
212
+ agent: boolean;
213
+ skills: boolean;
214
+ memory: boolean;
215
+ automation: boolean;
216
+ gateway: boolean;
217
+ tui: boolean;
218
+ mcp: boolean;
219
+ }
220
+
221
+ export const HERMES_CORE_RESOURCE: string;
222
+ export function detectHermesCoreSignals(input?: {
223
+ taskText?: string;
224
+ projectSignals?: string[];
225
+ }): HermesCoreSignals;
226
+ export function shouldApplyHermesCore(input?: {
227
+ taskText?: string;
228
+ projectSignals?: string[];
229
+ }): boolean;
230
+ export function buildHermesCoreContract(options?: { compact?: boolean }): string;
231
+ }
232
+
233
+ declare module './src/ai/small-model-amplifier.js' {
234
+ export interface SmallModelAmplification {
235
+ weak: boolean;
236
+ maxToolTurns: number;
237
+ enforceSelfCritique: boolean;
238
+ hint: string;
239
+ }
240
+
241
+ export function isWeakTier(modelTier?: string): boolean;
242
+ export function buildCodingMasteryContract(options?: { compact?: boolean }): string;
243
+ export function buildSmallModelAmplification(options?: {
244
+ modelTier?: string;
245
+ workflowProfile?: string;
246
+ depth?: string;
247
+ }): SmallModelAmplification;
248
+ }
249
+
250
+ declare module './src/cli/repl.js' {
251
+ export interface WinterREPLOptions {
164
252
  projectPath?: string;
165
253
  sessionId?: string | null;
166
254
  version?: string;
@@ -176,11 +264,25 @@ declare module './src/cli/repl.js' {
176
264
  start(): Promise<void>;
177
265
  showStatus(): void;
178
266
  showTuiDashboard(): void;
179
- showInputPrompt(): void;
180
- closeInputBox(): void;
181
- buildInputPanel(): {
182
- top: string;
183
- status: string;
267
+ showInputPrompt(): void;
268
+ closeInputBox(): void;
269
+ chat(message: string, imageAttachments?: unknown[]): Promise<void>;
270
+ runConversation(messages: unknown[], label?: string, tools?: unknown[] | null): Promise<{
271
+ finalContent: string;
272
+ usedTools: boolean;
273
+ usedMutatingTools: boolean;
274
+ autoVerified?: boolean;
275
+ autoVerificationPassed?: boolean;
276
+ }>;
277
+ inferVerificationCommands(task?: string): Promise<string[]>;
278
+ runVerification(commands?: string[] | null): Promise<{
279
+ passed: boolean;
280
+ details: Array<{ cmd: string; passed: boolean; output: string }>;
281
+ }>;
282
+ runAutoHealing(task: string): Promise<void>;
283
+ buildInputPanel(): {
284
+ top: string;
285
+ status: string;
184
286
  hint: string;
185
287
  prompt: string;
186
288
  bottom: string;