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
package/src/cli/repl.js CHANGED
@@ -427,6 +427,7 @@ export class WinterREPL {
427
427
  const shouldDrop = (entry) => {
428
428
  const text = typeof entry === 'string' ? entry : entry?.text || '';
429
429
  return text.startsWith('[Required local resources]')
430
+ || text.startsWith('[Auto-loaded resource application profile]')
430
431
  || text.startsWith('[Auto-applied skills]')
431
432
  || text.startsWith('[Project rule file')
432
433
  || text.startsWith('[Startup local resource index]')
@@ -442,7 +443,11 @@ export class WinterREPL {
442
443
  `awesome-design-md: ${resourcePaths.designs}`,
443
444
  `karpathy-tools: ${resourcePaths.karpathy}`,
444
445
  `page-agent: ${resourcePaths.pageAgent}`,
446
+ `hermes-agent-core: ${resourcePaths.hermesAgentCore}`,
447
+ `gsap-skills: ${resourcePaths.gsapSkills}`,
445
448
  `ecc: ${resourcePaths.ecc}`,
449
+ `codex: ${resourcePaths.codex.root}`,
450
+ `claude: ${resourcePaths.claude.root}`,
446
451
  ];
447
452
  await this.session.replaceMemory(
448
453
  '[Startup local resource index]',
@@ -671,8 +676,8 @@ export class WinterREPL {
671
676
  }
672
677
  }
673
678
 
674
- await this.bootstrapProjectCapabilities();
675
679
  await this.compactStartupMemories({ projectInstructionFiles, autoCreateDocs });
680
+ await this.bootstrapProjectCapabilities();
676
681
 
677
682
  // Codebase Index is intentionally lazy/on-demand. Top-tier coding agents do
678
683
  // not make first-run chat pay for a repo-wide scan, and this also prevents
@@ -718,6 +723,7 @@ export class WinterREPL {
718
723
  this._pasteTimer = null;
719
724
  this._isPasteChunk = false;
720
725
  this._pasteChunkTimer = null;
726
+ this._pasteCounter = 0;
721
727
  const PASTE_DELAY = 80;
722
728
 
723
729
  process.stdin.on('data', (chunk) => {
@@ -736,7 +742,7 @@ export class WinterREPL {
736
742
  }
737
743
  });
738
744
 
739
- const flushPasteBuffer = () => {
745
+ const flushPasteBuffer = async () => {
740
746
  this._pasteTimer = null;
741
747
  if (this._pasteBuffer.length === 0) return;
742
748
 
@@ -772,6 +778,19 @@ export class WinterREPL {
772
778
  this._multilineBuffer.push(...this._pasteBuffer);
773
779
  this._pasteBuffer = [];
774
780
 
781
+ if (this.shouldAutoPersistBufferedPaste(this._multilineBuffer, { isPasteChunk: this._isPasteChunk })) {
782
+ const pastedText = this._multilineBuffer.join('\n').trimEnd();
783
+ if (this.shouldPersistPastedText(pastedText)) {
784
+ const paste = await this.persistPastedText(pastedText);
785
+ this._multilineBuffer = [];
786
+ this._isPasteChunk = false;
787
+ const reference = this.formatPastedTextReference(paste);
788
+ console.log(`${colors.cyan}│ ${colors.dim}${reference}${colors.reset}`);
789
+ this.submitInputQueue(reference);
790
+ return;
791
+ }
792
+ }
793
+
775
794
  // If they pressed Enter on an empty line, submit the multiline buffer!
776
795
  if (isJustEmptyEnter && this._multilineBuffer.length > 1) {
777
796
  // Remove the trailing empty line
@@ -788,6 +807,14 @@ export class WinterREPL {
788
807
  return;
789
808
  }
790
809
 
810
+ if (this.shouldPersistPastedText(combined)) {
811
+ const paste = await this.persistPastedText(combined);
812
+ const reference = this.formatPastedTextReference(paste);
813
+ console.log(`${colors.cyan}│ ${colors.dim}${reference}${colors.reset}`);
814
+ this.submitInputQueue(reference);
815
+ return;
816
+ }
817
+
791
818
  this.submitInputQueue(combined);
792
819
  return;
793
820
  }
@@ -816,7 +843,14 @@ export class WinterREPL {
816
843
  this.rl.on('line', (line) => {
817
844
  this._pasteBuffer.push(line);
818
845
  if (this._pasteTimer) clearTimeout(this._pasteTimer);
819
- this._pasteTimer = setTimeout(flushPasteBuffer, PASTE_DELAY);
846
+ this._pasteTimer = setTimeout(() => {
847
+ void flushPasteBuffer().catch((error) => {
848
+ this._pasteBuffer = [];
849
+ this._multilineBuffer = [];
850
+ console.log(`\n${colors.red}? Paste error: ${error.message}${colors.reset}\n`);
851
+ if (this.running && !this.readlineClosed) this.showInputPrompt();
852
+ });
853
+ }, PASTE_DELAY);
820
854
  });
821
855
 
822
856
  this.rl.on('close', async () => {
@@ -863,6 +897,55 @@ export class WinterREPL {
863
897
  return this.inputController.handleDirectClipboardPaste();
864
898
  }
865
899
 
900
+ getPasteStorageDir() {
901
+ return path.join(this.config?.winterDir || path.join(homedir(), '.winter'), 'pastes');
902
+ }
903
+
904
+ normalizePastedText(text = '') {
905
+ return String(text || '')
906
+ .replace(/\x1b\[200~/g, '')
907
+ .replace(/\x1b\[201~/g, '')
908
+ .replace(/\r\n/g, '\n')
909
+ .replace(/\r/g, '\n');
910
+ }
911
+
912
+ getPastedTextLineCount(text = '') {
913
+ const value = this.normalizePastedText(text);
914
+ if (!value) return 0;
915
+ return value.split(/\r\n|\r|\n/).length;
916
+ }
917
+
918
+ shouldPersistPastedText(text = '', { minLines = 8, minChars = 4000 } = {}) {
919
+ const value = this.normalizePastedText(text);
920
+ return this.getPastedTextLineCount(value) >= minLines || value.length >= minChars;
921
+ }
922
+
923
+ shouldAutoPersistBufferedPaste(buffer = [], { isPasteChunk = false } = {}) {
924
+ if (!Array.isArray(buffer) || buffer.length === 0) return false;
925
+ const manualMultiline = buffer[0] === '';
926
+ const text = this.normalizePastedText(buffer.join('\n')).trimEnd();
927
+ return Boolean(text) && this.shouldPersistPastedText(text) && (isPasteChunk || !manualMultiline);
928
+ }
929
+
930
+ async persistPastedText(text = '') {
931
+ const content = this.normalizePastedText(text);
932
+ const dir = this.getPasteStorageDir();
933
+ await fs.mkdir(dir, { recursive: true });
934
+ this._pasteCounter = Number(this._pasteCounter || 0) + 1;
935
+ const filePath = path.join(dir, `paste_${this._pasteCounter}_${Date.now()}.txt`);
936
+ await fs.writeFile(filePath, content, 'utf8');
937
+ return {
938
+ index: this._pasteCounter,
939
+ path: filePath,
940
+ lines: this.getPastedTextLineCount(content),
941
+ chars: content.length,
942
+ };
943
+ }
944
+
945
+ formatPastedTextReference(paste = {}) {
946
+ return `[Pasted text #${paste.index || 1}: ${paste.lines || 0} lines -> ${paste.path}]`;
947
+ }
948
+
866
949
  buildInputPanel() {
867
950
  return this.inputController.buildInputPanel();
868
951
  }
@@ -1744,14 +1827,14 @@ ${colors.reset}
1744
1827
  case 'review':
1745
1828
  return byName(['Read', 'Grep', 'Glob', 'Bash', 'WebFetch']);
1746
1829
  case 'debug':
1747
- return byName(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob', 'OpenBrowser', 'BrowserDebug', 'WebFetch', 'MCP', 'Parallel']);
1830
+ return byName(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob', 'OpenBrowser', 'VisibleBrowser', 'BrowserDebug', 'WebFetch', 'MCP', 'Parallel']);
1748
1831
  case 'research':
1749
1832
  return byName(['Read', 'Grep', 'Glob', 'WebFetch', 'WebSearch', 'Parallel']);
1750
1833
  case 'design':
1751
1834
  case 'ui':
1752
- return byName(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob', 'OpenBrowser', 'BrowserDebug', 'WebFetch', 'MCP']);
1835
+ return byName(['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob', 'OpenBrowser', 'VisibleBrowser', 'BrowserDebug', 'WebFetch', 'MCP']);
1753
1836
  default:
1754
- return byName(['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'OpenBrowser', 'BrowserDebug', 'WebFetch', 'WebSearch', 'MCP', 'Parallel', 'Agent']);
1837
+ return byName(['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'OpenBrowser', 'VisibleBrowser', 'BrowserDebug', 'WebFetch', 'WebSearch', 'MCP', 'Parallel', 'Agent', 'DelegateTask', 'ParallelAgent']);
1755
1838
  }
1756
1839
  }
1757
1840
 
@@ -1944,7 +2027,7 @@ ${colors.reset}
1944
2027
  'For browser interaction tasks you MUST use tools, not prose:',
1945
2028
  '1. If chrome-devtools MCP is configured, call MCP {"server":"chrome-devtools","tool":"list"} first if needed.',
1946
2029
  '2. Use chrome-devtools MCP tools such as new_page/navigate_page, take_snapshot, click, fill/fill_form, evaluate_script, list_network_requests, and take_screenshot in visible Chrome.',
1947
- '3. Use WebFetch only for static text extraction. WebFetch cannot click buttons, fill forms, or preserve page state. BrowserDebug is headless and should be fallback only.',
2030
+ '3. Use WebFetch only for static text extraction. WebFetch cannot click buttons, fill forms, or preserve page state. Use VisibleBrowser when MCP is unavailable and the user needs visible browser control. BrowserDebug is headless and should be fallback only.',
1948
2031
  '4. Do not say "đã bấm", "đã điền", "đã mở", or "đã kiểm tra" until a browser/MCP tool result proves it.',
1949
2032
  '',
1950
2033
  `Original user request: ${request}`,
@@ -1962,7 +2045,7 @@ ${colors.reset}
1962
2045
  'DO NOT say "I have updated/created/fixed" without a tool call proving it.',
1963
2046
  'DO NOT describe what you would do. Actually DO IT with tool calls.',
1964
2047
  '',
1965
- 'Available tools: Read, Write, Edit, Bash, Glob, Grep, OpenBrowser, BrowserDebug, WebFetch, WebSearch, MCP.',
2048
+ 'Available tools: Read, Write, Edit, Bash, Glob, Grep, OpenBrowser, VisibleBrowser, BrowserDebug, WebFetch, WebSearch, MCP.',
1966
2049
  '',
1967
2050
  'If native tool calls are not supported, output exactly one fallback tool call:',
1968
2051
  '<invoke name="Read"><parameter name="path">README.md</parameter></invoke>',
@@ -1985,7 +2068,7 @@ ${colors.reset}
1985
2068
  const hints = [];
1986
2069
 
1987
2070
  if (/\b(click|fill|submit|press|select|navigate|bam|dien|chon|nhan|vao|bấm|điền|chọn|nhấn|vào)\b/i.test(text) && /\b(web|website|page|url|http|chrome|browser|form|button|link|trang|nut|nút|dang ky|dang nhap|khach hang|đăng ký|đăng nhập|khách hàng)\b/i.test(text)) {
1988
- hints.push('TOOL HINT: This is a live browser interaction. Do NOT use WebFetch alone. Prefer visible Chrome via MCP {"server":"chrome-devtools","tool":"list"} then chrome-devtools tools new_page/navigate_page, take_snapshot, click, fill/fill_form, evaluate_script, list_network_requests, and take_screenshot. Only use BrowserDebug as headless fallback. Only claim click/fill/navigation after MCP or BrowserDebug evidence.');
2071
+ hints.push('TOOL HINT: This is a live browser interaction. Do NOT use WebFetch alone. Prefer visible Chrome via MCP {"server":"chrome-devtools","tool":"list"} then chrome-devtools tools new_page/navigate_page, take_snapshot, click, fill/fill_form, evaluate_script, list_network_requests, and take_screenshot. If MCP is unavailable, call VisibleBrowser for real visible Puppeteer control. Only use BrowserDebug as headless fallback. Only claim click/fill/navigation after MCP, VisibleBrowser, or BrowserDebug evidence.');
1989
2072
  }
1990
2073
 
1991
2074
  // Detect file reading requests
@@ -2108,6 +2191,9 @@ ${colors.reset}
2108
2191
  if ((options?.requireToolEvidence && this.responseNeedsToolEvidence(assistantMsg.content)) || isFakeCompletion) {
2109
2192
  return { assistantMsg, toolCalls, finalContent: '', finishReason: 'tool_evidence_required' };
2110
2193
  }
2194
+ if (options?.deferFinalContent) {
2195
+ return { assistantMsg, toolCalls, finalContent: assistantMsg.content, finishReason };
2196
+ }
2111
2197
  this.printAssistantAnswer(assistantMsg.content, startedAt, totalUsage);
2112
2198
  return { assistantMsg, toolCalls, finalContent: assistantMsg.content, finishReason };
2113
2199
  }
@@ -2122,7 +2208,7 @@ ${colors.reset}
2122
2208
  const toolCallParts = [];
2123
2209
  let finishReason = null;
2124
2210
  let printed = false;
2125
- const bufferToolModeContent = options?.enableTools === true;
2211
+ const bufferToolModeContent = false;
2126
2212
 
2127
2213
  for await (const chunk of this.ai.streamRequest(messages, options)) {
2128
2214
  if (chunk.usage) this.addUsage(totalUsage, chunk.usage);
@@ -2239,6 +2325,14 @@ ${colors.reset}
2239
2325
  finishReason: 'tool_evidence_required',
2240
2326
  };
2241
2327
  }
2328
+ if (options?.deferFinalContent) {
2329
+ return {
2330
+ assistantMsg: { content: visibleContent },
2331
+ toolCalls,
2332
+ finalContent: visibleContent,
2333
+ finishReason,
2334
+ };
2335
+ }
2242
2336
  this.printAssistantAnswer(visibleContent, startedAt, totalUsage);
2243
2337
  return {
2244
2338
  assistantMsg: { content: visibleContent },
@@ -2275,7 +2369,7 @@ ${colors.reset}
2275
2369
  '/provider', '/model', '/models', '/providers',
2276
2370
  '/theme:toggle', '/tui',
2277
2371
  '/auto', '/debug', '/doctor', '/context', '/scorecard', '/swe',
2278
- '/read', '/write', '/glob', '/grep', '/bash',
2372
+ '/read', '/write', '/glob', '/grep', '/bash', '/browser', '/paste',
2279
2373
  '/codex', '/claude', '/karpathy', '/agents',
2280
2374
  '/resources', '/designs', '/skills',
2281
2375
  '/ecc',
@@ -2374,7 +2468,7 @@ ${colors.reset}
2374
2468
  const executionProfile = this.selectExecutionProfile(messages, { enableTools: false });
2375
2469
  const latestUserText = this.getLatestUserText(messages);
2376
2470
  const browserInteraction = this.isBrowserInteractionRequest(latestUserText);
2377
- const hasBrowserEvidence = toolSummaries.some(summary => /^(MCP|BrowserDebug|OpenBrowser):/i.test(summary));
2471
+ const hasBrowserEvidence = toolSummaries.some(summary => /^(MCP|VisibleBrowser|BrowserDebug|OpenBrowser):/i.test(summary));
2378
2472
  const finalMessages = [
2379
2473
  ...messages,
2380
2474
  {
@@ -2387,7 +2481,7 @@ ${colors.reset}
2387
2481
  'Start with the actual outcome, then mention only the most relevant files/commands. Avoid broad generic advice.',
2388
2482
  'If a tool failed, explain the concrete failure briefly and answer with the available evidence.',
2389
2483
  'Do not repeat the plan. Do not re-summarize unrelated project context. Do not claim memory/tool state that is not visible in the transcript.',
2390
- browserInteraction && !hasBrowserEvidence ? 'Important: The user asked for browser interaction, but no MCP/BrowserDebug/OpenBrowser result is available. You must say the browser action was NOT performed; do not claim you clicked, filled, navigated, or inspected pages.' : '',
2484
+ browserInteraction && !hasBrowserEvidence ? 'Important: The user asked for browser interaction, but no MCP/VisibleBrowser/BrowserDebug/OpenBrowser result is available. You must say the browser action was NOT performed; do not claim you clicked, filled, navigated, or inspected pages.' : '',
2391
2485
  toolSummaries.length ? `Tool summary:\n${toolSummaries.join('\n')}` : '',
2392
2486
  ].filter(Boolean).join('\n'),
2393
2487
  },
@@ -2412,7 +2506,7 @@ ${colors.reset}
2412
2506
  this.addUsage(totalUsage, response.usage);
2413
2507
  let content = response.choices?.[0]?.message?.content || '';
2414
2508
  if (browserInteraction && !hasBrowserEvidence && this.detectFakeCompletion(content)) {
2415
- content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng lại yêu cầu để Winter gọi đúng browser tool.';
2509
+ content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/VisibleBrowser/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng VisibleBrowser để Winter gọi đúng browser tool.';
2416
2510
  }
2417
2511
 
2418
2512
  if (this.spinner) this.spinner.stop();
@@ -2457,7 +2551,7 @@ ${colors.reset}
2457
2551
  if (this.spinner) this.spinner.stop();
2458
2552
 
2459
2553
  if (validation.browserInteraction && !validation.hasBrowserEvidence && this.detectFakeCompletion(content)) {
2460
- content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng lại yêu cầu để Winter gọi đúng browser tool.';
2554
+ content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/VisibleBrowser/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng VisibleBrowser để Winter gọi đúng browser tool.';
2461
2555
  }
2462
2556
 
2463
2557
  if (content) {
@@ -2481,7 +2575,7 @@ ${colors.reset}
2481
2575
  this.addUsage(totalUsage, response.usage);
2482
2576
  content = response.choices?.[0]?.message?.content || '';
2483
2577
  if (validation.browserInteraction && !validation.hasBrowserEvidence && this.detectFakeCompletion(content)) {
2484
- content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng lại yêu cầu để Winter gọi đúng browser tool.';
2578
+ content = 'Chưa thực hiện được thao tác trên trình duyệt: lượt này không có bằng chứng từ MCP/VisibleBrowser/BrowserDebug/OpenBrowser, nên Winter chặn câu trả lời để tránh báo sai. Hãy bật chrome-devtools MCP hoặc dùng VisibleBrowser để Winter gọi đúng browser tool.';
2485
2579
  }
2486
2580
  if (content) {
2487
2581
  this.printAssistantAnswer(content, startedAt, totalUsage);
@@ -2889,7 +2983,7 @@ ${colors.reset}
2889
2983
  messages.push({ role: 'system', content: toolHint });
2890
2984
  }
2891
2985
 
2892
- const { finalContent, usedMutatingTools } = await this.runConversation(messages, 'Thinking', tools);
2986
+ const { finalContent, usedMutatingTools, autoVerified } = await this.runConversation(messages, 'Thinking', tools);
2893
2987
 
2894
2988
  const allToolCalls = [];
2895
2989
  for (const msg of messages) {
@@ -2914,7 +3008,7 @@ ${colors.reset}
2914
3008
  });
2915
3009
 
2916
3010
  // Tự động verify: nếu AI đã dùng tools (sửa code), chạy test/build.
2917
- if (finalContent && this.shouldAutoVerifyAfterTools(message, usedMutatingTools)) {
3011
+ if (!autoVerified && finalContent && this.shouldAutoVerifyAfterTools(message, usedMutatingTools)) {
2918
3012
  const sessionContext = this.session?.getContext?.() || {};
2919
3013
  const profile = String(sessionContext.workflowProfile || 'general');
2920
3014
  const amplifier = sessionContext.smallModelAmplifier || {};
@@ -2965,7 +3059,7 @@ ${colors.reset}
2965
3059
  ].filter(Boolean).join('\n');
2966
3060
 
2967
3061
  const amplifier = buildSmallModelAmplification({
2968
- modelTier: this.ai?._modelTier || 'medium',
3062
+ modelTier: this.getActiveModelTier(),
2969
3063
  workflowProfile: workflow.profile,
2970
3064
  depth: workflow.depth,
2971
3065
  });
@@ -3115,35 +3209,10 @@ Do NOT stop until all errors are resolved.`;
3115
3209
  }
3116
3210
 
3117
3211
  async runAgent(role, task) {
3118
- const agentDefinition = await this.agentRegistry.get(role || 'general');
3119
- const context = await this.getProjectContext(task);
3120
- const messages = [
3121
- { role: 'system', content: this.getAgentDefinitionSystemPrompt(agentDefinition, context) }
3122
- ];
3123
-
3124
- const promptHistory = this.getCompressedPromptHistory({
3125
- limit: 40,
3126
- keepRecent: 16,
3127
- maxTotalChars: 16000,
3128
- });
3129
- if (promptHistory.summary) {
3130
- messages.push({ role: 'system', content: `Compressed prior conversation:\n${promptHistory.summary}` });
3131
- }
3132
- for (const entry of promptHistory.entries) {
3133
- messages.push({ role: entry.role, content: entry.content });
3134
- }
3135
-
3136
- messages.push({ role: 'user', content: `Task: ${task}` });
3137
-
3138
- const agentTools = this.getAgentToolsForDefinition(agentDefinition);
3139
- const { finalContent, usedMutatingTools } = await this.runConversation(messages, `Subagent [${agentDefinition.id}]`, agentTools);
3140
-
3141
- await this.session.addToHistory({ role: 'user', content: `[subagent:${agentDefinition.id}] ${task}` });
3142
- await this.session.addToHistory({ role: 'assistant', content: finalContent });
3143
-
3144
- if (finalContent && this.shouldAutoVerifyAfterTools(task, usedMutatingTools)) {
3145
- await this.verifyAndHeal(messages, agentTools, 2);
3146
- }
3212
+ const result = await this.tools.agentTool.run(task, { role: role || 'general' });
3213
+ await this.session.addToHistory({ role: 'user', content: `[subagent:${result.role || role || 'general'}] ${task}` });
3214
+ await this.session.addToHistory({ role: 'assistant', content: result.finalContent || result.summary || result.error || '' });
3215
+ return result;
3147
3216
  }
3148
3217
 
3149
3218
  async listAgentDefinitions() {
@@ -3420,6 +3489,14 @@ Light mode enabled for safety. Heavy codebase, graph, and git context are skippe
3420
3489
  await this.session.replaceMemory('[Required local resources]', requiredLocalResources, 'resource');
3421
3490
  }
3422
3491
 
3492
+ const projectInstructionFiles = await this.readProjectInstructionFiles();
3493
+ const resourceApplicationProfile = await this.contextLoader.getResourceApplicationProfile({ projectInstructionFiles });
3494
+ if (resourceApplicationProfile) {
3495
+ await this.session.updateContext('resourceApplicationProfile', resourceApplicationProfile);
3496
+ await this.session.replaceMemory('[Auto-loaded resource application profile]', resourceApplicationProfile, 'resource');
3497
+ this.startupNotice('resource profile loaded');
3498
+ }
3499
+
3423
3500
  const skillSnapshot = await this.inferStartupSkills();
3424
3501
  await this.session.updateContext('availableSkillCatalog', skillSnapshot.availableSkills);
3425
3502
  await this.session.updateContext('activeSkills', skillSnapshot.activeSkills);
@@ -3431,43 +3508,7 @@ Light mode enabled for safety. Heavy codebase, graph, and git context are skippe
3431
3508
  }
3432
3509
 
3433
3510
  async inferStartupSkills() {
3434
- const catalog = await this.getStartupSkillCatalog();
3435
- const signals = await this.getProjectSignals();
3436
- const normalizedSignals = new Set(signals.map(value => value.toLowerCase()));
3437
-
3438
- const hasAny = (...items) => items.some(item => normalizedSignals.has(item));
3439
- const activeSkills = new Set([
3440
- 'coding',
3441
- 'debug',
3442
- 'refactor',
3443
- 'test',
3444
- ]);
3445
-
3446
- if (hasAny('react', 'next', 'nextjs', 'tsx', 'jsx', 'vue', 'svelte', 'vite')) {
3447
- ['vercel-react-best-practices', 'web-design-guidelines', 'frontend-design', 'design'].forEach(skill => activeSkills.add(skill));
3448
- }
3449
-
3450
- if (hasAny('design', 'ui', 'ux', 'css', 'tailwind', 'styled-components', 'scss', 'style', 'component')) {
3451
- ['web-design-guidelines', 'frontend-design', 'design'].forEach(skill => activeSkills.add(skill));
3452
- }
3453
-
3454
- if (hasAny('claude', 'agent', 'mcp', 'plugin', 'skill', 'automation', 'workflow')) {
3455
- ['skill-creator', 'claude-automation-recommender', 'claude-md-improver', 'agent-development', 'hook-development', 'command-development', 'plugin-dev'].forEach(skill => activeSkills.add(skill));
3456
- }
3457
-
3458
- if (hasAny('docs', 'markdown', 'md', 'readme', 'documentation')) {
3459
- ['claude-md-improver', 'docs', 'writing-rules'].forEach(skill => activeSkills.add(skill));
3460
- }
3461
-
3462
- if (hasAny('figma', 'design-md', 'brand', 'brand-guidelines', 'style-guide')) {
3463
- ['vibefigma', 'web-design-guidelines'].forEach(skill => activeSkills.add(skill));
3464
- }
3465
-
3466
- const filtered = [...activeSkills].filter(skill => catalog.has(skill));
3467
- return {
3468
- availableSkills: [...catalog],
3469
- activeSkills: filtered,
3470
- };
3511
+ return this.contextLoader.inferStartupSkills();
3471
3512
  }
3472
3513
 
3473
3514
  async getStartupSkillCatalog() {
@@ -3647,6 +3688,9 @@ Light mode enabled for safety. Heavy codebase, graph, and git context are skippe
3647
3688
  case undefined:
3648
3689
  case 'list':
3649
3690
  console.log(`${colors.cyan}Permission Allowlist:${colors.reset}`);
3691
+ console.log(` Full access: ${config.sandbox?.enabled === false ? 'on' : 'off'}`);
3692
+ console.log(` Sandbox enabled: ${config.sandbox?.enabled !== false}`);
3693
+ console.log(` Restrict workspace: ${config.sandbox?.restrictToWorkspace !== false}`);
3650
3694
  console.log(` Tools: ${(config.permissions.allowlist.tools || []).join(', ') || 'none'}`);
3651
3695
  console.log(` Commands: ${(config.permissions.allowlist.commands || []).join(', ') || 'none'}`);
3652
3696
  console.log(` MCP Servers: ${(config.permissions.allowlist.mcpServers || []).join(', ') || 'none'}`);
@@ -3673,8 +3717,25 @@ Light mode enabled for safety. Heavy codebase, graph, and git context are skippe
3673
3717
  console.log(`${colors.green}✓ Updated prompt policy${colors.reset}`);
3674
3718
  break;
3675
3719
  }
3720
+ case 'full': {
3721
+ const value = String(rest[0] || 'on').toLowerCase();
3722
+ const enabled = !(value === 'off' || value === 'false' || value === '0' || value === 'no');
3723
+ if (typeof this.config.setFullAccess === 'function') {
3724
+ await this.config.setFullAccess(enabled);
3725
+ } else {
3726
+ config.sandbox = {
3727
+ ...(config.sandbox || {}),
3728
+ enabled: !enabled,
3729
+ restrictToWorkspace: !enabled,
3730
+ };
3731
+ config.permissions.promptByDefault = !enabled;
3732
+ await this.config.save(config);
3733
+ }
3734
+ console.log(`${colors.green}Full access ${enabled ? 'enabled' : 'disabled'}${colors.reset}`);
3735
+ break;
3736
+ }
3676
3737
  default:
3677
- console.log(`${colors.yellow}Usage: /permissions <list|allow|prompt>${colors.reset}`);
3738
+ console.log(`${colors.yellow}Usage: /permissions <list|allow|prompt|full>${colors.reset}`);
3678
3739
  }
3679
3740
  }
3680
3741
 
@@ -36,13 +36,14 @@ export const SLASH_COMMANDS = [
36
36
  { cmd: '/grep', desc: 'Search files', usage: '/grep <pattern>' },
37
37
  { cmd: '/bash', desc: 'Run command', usage: '/bash <command>' },
38
38
  { cmd: '/image', desc: 'Analyze image/screenshot or clipboard image', usage: '/image [file] [question]' },
39
+ { cmd: '/paste', desc: 'Read clipboard text or image', usage: '/paste [prompt]' },
39
40
  { cmd: '/design', desc: 'Design commands', sub: ['search', 'add', 'apply', 'list', 'preview'] },
40
41
  { cmd: '/designs', desc: 'List/search awesome-design-md systems', usage: '/designs [query]' },
41
42
  { cmd: '/skill', desc: 'Skills management', sub: ['list', 'enable', 'create'] },
42
43
  { cmd: '/skills', desc: 'List local Winter/Codex/Claude skills' },
43
44
  { cmd: '/plugin', desc: 'Plugin management', sub: ['list', 'install', 'remove'] },
44
45
  { cmd: '/mcp', desc: 'MCP server management', sub: ['list', 'add', 'preset', 'install', 'remove', 'allow', 'tools'] },
45
- { cmd: '/permissions', desc: 'Permission allowlist', sub: ['list', 'allow', 'prompt'] },
46
+ { cmd: '/permissions', desc: 'Permission allowlist', sub: ['list', 'allow', 'prompt', 'full'] },
46
47
  { cmd: '/stats', desc: 'Tool usage statistics' },
47
48
  { cmd: '/replay', desc: 'Replay recent session/tool events', usage: '/replay [count]' },
48
49
  { cmd: '/diff', desc: 'Preview git diff', usage: '/diff [--cached|--confirm]' },
@@ -57,6 +58,7 @@ export const SLASH_COMMANDS = [
57
58
  { cmd: '/composer', desc: 'Multi-file editing mode (like Cursor Composer)', usage: '/composer <task>' },
58
59
  { cmd: '/complete', desc: 'Trigger inline code completion', usage: '/complete <file> [line] [col]' },
59
60
  { cmd: '/browse', desc: 'Browse URL in Chrome via browser automation', usage: '/browse <url>' },
61
+ { cmd: '/browser', desc: 'Control visible Chrome', usage: '/browser <open|click|type|screenshot|snapshot|eval> [url] [--selector css] [--text value] [--keep-open]' },
60
62
  { cmd: '/ensemble', desc: 'Run all AI providers in parallel', usage: '/ensemble <prompt>' },
61
63
  { cmd: '/vote', desc: 'Run multiple models and vote for best answer', usage: '/vote <prompt>' },
62
64
  { cmd: '/orchestrate', desc: 'Full pipeline: classify → parallel → merge → review', usage: '/orchestrate <task>' },