From 4b75f66d36183f13926f400f81f105117dd4c4da Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Fri, 13 Feb 2026 11:28:18 -0500 Subject: [PATCH] Revert to pre-AI-SDK state (commit 67e568f6b) This commit reverts the codebase to the state before AI SDK migration work began. Target commit: 67e568f6b - refactor: replace fetch_instructions with skill tool and built-in skills (#10913) Date: January 29, 2026 This removes approximately 152 commits of AI SDK migration work. A follow-up PR will add back bug fixes and features that are unrelated to AI SDK. Co-Authored-By: Claude Sonnet 4.5 --- .env.sample | 6 + .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/config.yml | 3 + .github/workflows/cli-release.yml | 394 --- .gitignore | 1 - .roo/commands/cli-release.md | 40 +- .../1_extraction_workflow.xml | 244 +- .../2_documentation_patterns.xml | 357 +++ .../2_verification_workflow.xml | 85 - .../3_analysis_techniques.xml | 349 +++ .roo/rules-docs-extractor/3_output_format.xml | 133 - .../4_communication_guidelines.xml | 298 ++ .roo/rules-integration-tester/1_workflow.xml | 198 ++ .../2_test_patterns.xml | 303 ++ .../3_best_practices.xml | 104 + .../4_common_mistakes.xml | 109 + .../5_test_environment.xml | 209 ++ .roo/rules-issue-investigator/1_workflow.xml | 2 +- .../2_best_practices.xml | 1 - .../rules-issue-investigator/4_tool_usage.xml | 6 - .roo/rules-issue-investigator/5_examples.xml | 2 +- .../6_communication.xml | 8 +- .roo/rules-issue-writer/1_workflow.xml | 1494 +++++++--- .../2_github_issue_templates.xml | 190 ++ .roo/rules-issue-writer/3_best_practices.xml | 307 +- .../4_common_mistakes_to_avoid.xml | 215 +- .roo/rules-issue-writer/5_examples.xml | 134 - .../rules-issue-writer/5_github_cli_usage.xml | 342 +++ .../1_mode_creation_workflow.xml | 301 ++ .../2_xml_structuring_best_practices.xml | 220 ++ .../3_mode_configuration_patterns.xml | 261 ++ .../4_instruction_file_templates.xml | 367 +++ .../5_complete_mode_examples.xml | 214 ++ .../6_mode_testing_validation.xml | 207 ++ .../7_validation_cohesion_checking.xml | 201 ++ .roomodes | 170 +- CHANGELOG.md | 79 - apps/cli/CHANGELOG.md | 48 +- apps/cli/README.md | 122 +- apps/cli/docs/AGENT_LOOP.md | 5 +- apps/cli/install.sh | 2 +- apps/cli/package.json | 9 +- apps/cli/scripts/build.sh | 343 --- apps/cli/scripts/release.sh | 711 +++++ .../agent/__tests__/extension-client.test.ts | 8 + apps/cli/src/agent/agent-state.ts | 5 +- apps/cli/src/agent/ask-dispatcher.ts | 43 +- apps/cli/src/agent/extension-host.ts | 66 +- apps/cli/src/agent/json-event-emitter.ts | 18 + apps/cli/src/commands/cli/run.ts | 26 +- apps/cli/src/index.ts | 3 +- .../lib/storage/__tests__/settings.test.ts | 27 +- .../src/lib/utils/__tests__/extension.test.ts | 73 +- apps/cli/src/lib/utils/context-window.ts | 10 +- apps/cli/src/lib/utils/extension.ts | 23 +- apps/cli/src/lib/utils/version.ts | 26 +- apps/cli/src/types/constants.ts | 2 +- apps/cli/src/types/types.ts | 8 +- .../cli/src/ui/components/ChatHistoryItem.tsx | 5 +- .../src/ui/components/tools/BrowserTool.tsx | 87 + apps/cli/src/ui/components/tools/index.ts | 3 + apps/cli/src/ui/components/tools/types.ts | 12 +- apps/cli/src/ui/components/tools/utils.ts | 8 + apps/cli/src/ui/types.ts | 8 + apps/cli/src/ui/utils/tools.ts | 23 + apps/cli/tsup.config.ts | 1 + .../src/suite/tools/read-file.test.ts | 7 +- apps/vscode-nightly/esbuild.mjs | 16 - apps/web-evals/next-env.d.ts | 1 - apps/web-evals/next.config.ts | 5 +- apps/web-evals/package.json | 4 +- .../app/api/runs/[id]/logs/[taskId]/route.ts | 74 + .../app/api/runs/[id]/logs/failed/route.ts | 147 + apps/web-roo-code/next.config.ts | 6 +- apps/web-roo-code/package.json | 29 +- apps/web-roo-code/src/app/cloud/page.tsx | 10 +- apps/web-roo-code/src/app/linear/page.tsx | 413 --- .../src/app/pr-fixer/content-a.tsx | 2 +- apps/web-roo-code/src/app/provider/page.tsx | 2 +- .../src/app/reviewer/content-b.ts | 2 +- apps/web-roo-code/src/app/reviewer/content.ts | 2 +- .../src/components/chromes/nav-bar.tsx | 228 +- .../src/components/homepage/features.tsx | 2 +- .../components/homepage/install-section.tsx | 2 +- .../src/components/homepage/testimonials.tsx | 2 +- .../homepage/use-examples-section.tsx | 6 +- .../components/linear/linear-issue-demo.tsx | 442 --- .../src/components/ui/navigation-menu.tsx | 117 - apps/web-roo-code/src/images.d.ts | 30 - package.json | 1 - .../CloudSettingsService.parsing.test.ts | 1 + .../__tests__/custom-tool-registry.spec.ts | 2 +- packages/core/src/debug-log/index.ts | 14 - packages/evals/README.md | 2 +- .../cli/__tests__/messageLogDeduper.test.ts | 2 +- packages/evals/src/cli/index.ts | 8 +- packages/evals/src/cli/processTask.ts | 12 +- packages/evals/src/cli/runCi.ts | 6 +- packages/evals/src/cli/runEvals.ts | 10 +- packages/evals/src/cli/runTaskInCli.ts | 13 +- packages/evals/src/cli/runTaskInVscode.ts | 14 +- packages/evals/src/cli/runUnitTest.ts | 6 +- packages/evals/src/cli/types.ts | 4 +- packages/evals/src/cli/utils.ts | 4 +- packages/evals/src/db/db.ts | 2 +- packages/evals/src/db/index.ts | 14 +- .../src/db/queries/__tests__/copyRun.spec.ts | 24 +- .../src/db/queries/__tests__/runs.test.ts | 6 +- packages/evals/src/db/queries/copyRun.ts | 6 +- packages/evals/src/db/queries/runs.ts | 12 +- packages/evals/src/db/queries/taskMetrics.ts | 8 +- packages/evals/src/db/queries/tasks.ts | 10 +- packages/evals/src/db/queries/toolErrors.ts | 8 +- packages/evals/src/db/schema.ts | 2 +- packages/evals/src/index.ts | 4 +- packages/evals/tsconfig.json | 3 - packages/types/npm/package.metadata.json | 2 +- packages/types/src/__tests__/cloud.test.ts | 37 - packages/types/src/__tests__/ipc.test.ts | 4 +- packages/types/src/__tests__/skills.test.ts | 144 - packages/types/src/cloud.ts | 3 +- packages/types/src/events.ts | 46 +- packages/types/src/global-settings.ts | 34 +- packages/types/src/index.ts | 1 - packages/types/src/ipc.ts | 14 +- packages/types/src/message.ts | 15 +- packages/types/src/mode.ts | 44 +- packages/types/src/provider-settings.ts | 169 +- packages/types/src/providers/anthropic.ts | 22 - packages/types/src/providers/azure.ts | 403 --- packages/types/src/providers/bedrock.ts | 27 - packages/types/src/providers/cerebras.ts | 58 + packages/types/src/providers/chutes.ts | 421 +++ packages/types/src/providers/deepinfra.ts | 14 + packages/types/src/providers/doubao.ts | 44 + packages/types/src/providers/featherless.ts | 58 + packages/types/src/providers/fireworks.ts | 12 - packages/types/src/providers/groq.ts | 84 + packages/types/src/providers/huggingface.ts | 17 + packages/types/src/providers/index.ts | 39 +- .../types/src/providers/io-intelligence.ts | 44 + packages/types/src/providers/openai-codex.ts | 16 +- packages/types/src/providers/openai.ts | 5 +- packages/types/src/providers/openrouter.ts | 6 +- packages/types/src/providers/unbound.ts | 14 + .../types/src/providers/vercel-ai-gateway.ts | 4 - packages/types/src/providers/vertex.ts | 27 +- packages/types/src/providers/xai.ts | 4 - packages/types/src/providers/zai.ts | 30 - packages/types/src/skills.ts | 81 - packages/types/src/task.ts | 6 +- packages/types/src/telemetry.ts | 2 - packages/types/src/tool-params.ts | 89 +- packages/types/src/tool.ts | 11 +- packages/types/src/vscode-extension-host.ts | 119 +- pnpm-lock.yaml | 2460 +++++++++-------- releases/3.46.0-release.png | Bin 1420313 -> 0 bytes releases/3.47.0-release.png | Bin 1235066 -> 0 bytes scripts/code-server.js | 71 - src/__tests__/command-mentions.spec.ts | 16 + src/__tests__/extension.spec.ts | 36 - .../history-resume-delegation.spec.ts | 324 +-- .../nested-delegation-resume.spec.ts | 20 +- src/__tests__/provider-delegation.spec.ts | 86 +- .../removeClineFromStack-delegation.spec.ts | 290 -- src/api/index.ts | 65 +- .../__tests__/anthropic-vertex.spec.ts | 1393 ++++++++-- src/api/providers/__tests__/anthropic.spec.ts | 905 +++--- src/api/providers/__tests__/azure.spec.ts | 432 --- ...openai-compatible-provider-timeout.spec.ts | 119 + .../base-openai-compatible-provider.spec.ts | 548 ++++ .../providers/__tests__/base-provider.spec.ts | 3 +- src/api/providers/__tests__/baseten.spec.ts | 447 --- .../__tests__/bedrock-custom-arn.spec.ts | 36 +- .../__tests__/bedrock-error-handling.spec.ts | 692 ++--- .../bedrock-inference-profiles.spec.ts | 12 + .../__tests__/bedrock-invokedModelId.spec.ts | 362 ++- .../__tests__/bedrock-native-tools.spec.ts | 813 +++--- .../__tests__/bedrock-reasoning.spec.ts | 323 ++- .../__tests__/bedrock-vpc-endpoint.spec.ts | 118 +- src/api/providers/__tests__/bedrock.spec.ts | 644 ++--- src/api/providers/__tests__/cerebras.spec.ts | 249 ++ src/api/providers/__tests__/chutes.spec.ts | 336 +++ src/api/providers/__tests__/deepinfra.spec.ts | 386 +++ src/api/providers/__tests__/deepseek.spec.ts | 654 ++--- .../providers/__tests__/featherless.spec.ts | 259 ++ src/api/providers/__tests__/fireworks.spec.ts | 1240 ++++----- .../__tests__/gemini-handler.spec.ts | 278 +- src/api/providers/__tests__/gemini.spec.ts | 410 +-- src/api/providers/__tests__/groq.spec.ts | 192 ++ .../__tests__/io-intelligence.spec.ts | 303 ++ src/api/providers/__tests__/lite-llm.spec.ts | 1154 +++++--- .../__tests__/lm-studio-timeout.spec.ts | 72 +- .../__tests__/lmstudio-native-tools.spec.ts | 401 ++- src/api/providers/__tests__/lmstudio.spec.ts | 292 +- src/api/providers/__tests__/minimax.spec.ts | 620 +++-- src/api/providers/__tests__/mistral.spec.ts | 788 +++--- src/api/providers/__tests__/moonshot.spec.ts | 16 +- .../providers/__tests__/native-ollama.spec.ts | 400 ++- .../openai-codex-native-tool-calls.spec.ts | 215 +- .../providers/__tests__/openai-codex.spec.ts | 105 +- .../__tests__/openai-native-reasoning.spec.ts | 556 ---- .../__tests__/openai-native-tools.spec.ts | 401 +-- .../__tests__/openai-native-usage.spec.ts | 775 +++--- .../providers/__tests__/openai-native.spec.ts | 1890 ++++++++----- .../__tests__/openai-timeout.spec.ts | 106 +- .../__tests__/openai-usage-tracking.spec.ts | 482 +--- src/api/providers/__tests__/openai.spec.ts | 1053 ++++--- .../providers/__tests__/openrouter.spec.ts | 1062 +++---- .../__tests__/qwen-code-native-tools.spec.ts | 661 +++-- src/api/providers/__tests__/requesty.spec.ts | 604 ++-- src/api/providers/__tests__/roo.spec.ts | 906 +++--- src/api/providers/__tests__/sambanova.spec.ts | 691 +---- src/api/providers/__tests__/unbound.spec.ts | 549 ++++ .../__tests__/vercel-ai-gateway.spec.ts | 450 +-- src/api/providers/__tests__/vertex.spec.ts | 331 +-- src/api/providers/__tests__/vscode-lm.spec.ts | 11 +- src/api/providers/__tests__/xai.spec.ts | 1077 ++++---- src/api/providers/__tests__/zai.spec.ts | 570 ++-- src/api/providers/anthropic-vertex.ts | 396 ++- src/api/providers/anthropic.ts | 479 ++-- src/api/providers/azure.ts | 211 -- .../base-openai-compatible-provider.ts | 260 ++ src/api/providers/base-provider.ts | 11 +- src/api/providers/baseten.ts | 169 +- src/api/providers/bedrock.ts | 1432 ++++++++-- src/api/providers/cerebras.ts | 362 +++ src/api/providers/chutes.ts | 209 ++ src/api/providers/deepinfra.ts | 163 ++ src/api/providers/deepseek.ts | 269 +- src/api/providers/doubao.ts | 81 + src/api/providers/fake-ai.ts | 13 +- src/api/providers/featherless.ts | 113 + .../fetchers/__tests__/chutes.spec.ts | 342 +++ .../fetchers/__tests__/modelCache.spec.ts | 42 + src/api/providers/fetchers/chutes.ts | 89 + src/api/providers/fetchers/deepinfra.ts | 71 + src/api/providers/fetchers/huggingface.ts | 252 ++ src/api/providers/fetchers/io-intelligence.ts | 158 ++ src/api/providers/fetchers/modelCache.ts | 24 +- src/api/providers/fetchers/openrouter.ts | 10 - src/api/providers/fetchers/unbound.ts | 52 + src/api/providers/fireworks.ts | 190 +- src/api/providers/gemini.ts | 530 ++-- src/api/providers/groq.ts | 19 + src/api/providers/huggingface.ts | 137 + src/api/providers/index.ts | 10 +- src/api/providers/io-intelligence.ts | 44 + src/api/providers/lite-llm.ts | 394 ++- src/api/providers/lm-studio.ts | 284 +- src/api/providers/minimax.ts | 396 ++- src/api/providers/mistral.ts | 343 +-- src/api/providers/moonshot.ts | 32 +- src/api/providers/native-ollama.ts | 455 ++- src/api/providers/openai-codex.ts | 1230 +++++++-- src/api/providers/openai-compatible.ts | 110 +- src/api/providers/openai-native.ts | 1760 +++++++++--- src/api/providers/openai.ts | 655 +++-- src/api/providers/openrouter.ts | 734 +++-- src/api/providers/qwen-code.ts | 294 +- src/api/providers/requesty.ts | 314 +-- src/api/providers/roo.ts | 455 +-- src/api/providers/router-provider.ts | 87 + src/api/providers/sambanova.ts | 193 +- src/api/providers/unbound.ts | 207 ++ src/api/providers/vercel-ai-gateway.ts | 266 +- src/api/providers/vertex.ts | 408 +-- src/api/providers/vscode-lm.ts | 11 +- src/api/providers/xai.ts | 262 +- src/api/providers/zai.ts | 194 +- src/api/transform/__tests__/ai-sdk.spec.ts | 1073 +------ .../__tests__/bedrock-converse-format.spec.ts | 559 ++++ .../__tests__/cache-breakpoints.spec.ts | 274 -- .../transform/__tests__/gemini-format.spec.ts | 487 ++++ .../__tests__/image-cleaning.spec.ts | 18 +- .../transform/__tests__/model-params.spec.ts | 32 +- .../transform/__tests__/openai-format.spec.ts | 92 +- src/api/transform/__tests__/reasoning.spec.ts | 123 - src/api/transform/ai-sdk.ts | 626 +---- src/api/transform/bedrock-converse-format.ts | 209 ++ src/api/transform/cache-breakpoints.ts | 126 - .../__tests__/cache-strategy.spec.ts | 1112 ++++++++ .../transform/cache-strategy/base-strategy.ts | 172 ++ .../cache-strategy/multi-point-strategy.ts | 314 +++ src/api/transform/cache-strategy/types.ts | 68 + .../caching/__tests__/anthropic.spec.ts | 181 ++ .../caching/__tests__/gemini.spec.ts | 266 ++ .../__tests__/vercel-ai-gateway.spec.ts | 233 ++ .../caching/__tests__/vertex.spec.ts | 178 ++ src/api/transform/caching/anthropic.ts | 41 + src/api/transform/caching/gemini.ts | 47 + .../transform/caching/vercel-ai-gateway.ts | 30 + src/api/transform/caching/vertex.ts | 49 + src/api/transform/gemini-format.ts | 199 ++ src/api/transform/image-cleaning.ts | 42 +- src/api/transform/model-params.ts | 14 +- src/api/transform/openai-format.ts | 416 ++- src/api/transform/reasoning.ts | 14 +- src/api/transform/stream.ts | 16 - src/api/transform/zai-format.ts | 242 ++ .../assistant-message/NativeToolCallParser.ts | 210 +- .../__tests__/NativeToolCallParser.spec.ts | 373 +-- ...resentAssistantMessage-custom-tool.spec.ts | 42 +- .../presentAssistantMessage-images.spec.ts | 75 +- ...esentAssistantMessage-unknown-tool.spec.ts | 42 +- .../presentAssistantMessage.ts | 220 +- .../auto-approval/__tests__/commands.spec.ts | 101 - src/core/auto-approval/commands.ts | 4 +- src/core/auto-approval/index.ts | 9 +- src/core/condense/__tests__/condense.spec.ts | 64 +- .../__tests__/foldedFileContext.spec.ts | 4 +- src/core/condense/__tests__/index.spec.ts | 479 +--- .../__tests__/nested-condense.spec.ts | 22 +- .../__tests__/rewind-after-condense.spec.ts | 98 +- src/core/condense/index.ts | 274 +- src/core/config/ContextProxy.ts | 21 +- src/core/config/ProviderSettingsManager.ts | 50 +- .../config/__tests__/ContextProxy.spec.ts | 58 +- .../CustomModesManager.yamlEdgeCases.spec.ts | 35 +- .../__tests__/CustomModesSettings.spec.ts | 39 +- src/core/config/__tests__/ModeConfig.spec.ts | 56 +- .../__tests__/ProviderSettingsManager.spec.ts | 133 +- .../__tests__/context-management.spec.ts | 34 +- .../__tests__/truncation.spec.ts | 53 +- src/core/context-management/index.ts | 41 +- .../__tests__/context-error-handling.test.ts | 38 + .../context-error-handling.ts | 21 +- .../__tests__/getEnvironmentDetails.spec.ts | 18 + src/core/environment/getEnvironmentDetails.ts | 32 + src/core/mentions/__tests__/index.spec.ts | 139 +- .../processUserContentMentions.spec.ts | 146 +- src/core/mentions/index.ts | 281 +- .../mentions/processUserContentMentions.ts | 113 +- src/core/message-manager/index.ts | 2 +- .../partial-reads-enabled.snap | 127 + .../__tests__/add-custom-instructions.spec.ts | 24 + .../__tests__/custom-system-prompt.spec.ts | 201 ++ src/core/prompts/__tests__/sections.spec.ts | 3 + .../prompts/__tests__/system-prompt.spec.ts | 68 + src/core/prompts/responses.ts | 22 +- .../__tests__/custom-instructions.spec.ts | 140 +- .../__tests__/custom-system-prompt.spec.ts | 134 + .../prompts/sections/custom-instructions.ts | 93 +- .../prompts/sections/custom-system-prompt.ts | 87 + src/core/prompts/sections/skills.ts | 5 +- src/core/prompts/system.ts | 47 + .../__tests__/filter-tools-for-mode.spec.ts | 91 - .../prompts/tools/filter-tools-for-mode.ts | 16 +- .../native-tools/__tests__/converters.spec.ts | 16 +- .../native-tools/__tests__/read_file.spec.ts | 169 +- .../tools/native-tools/browser_action.ts | 76 + src/core/prompts/tools/native-tools/edit.ts | 48 - src/core/prompts/tools/native-tools/index.ts | 14 +- .../prompts/tools/native-tools/read_file.ts | 173 +- .../tools/native-tools/search_and_replace.ts | 44 + src/core/prompts/types.ts | 2 + .../__tests__/apiMessages.spec.ts | 86 - .../__tests__/delegationMeta.spec.ts | 178 -- .../__tests__/messageUtils.spec.ts | 115 - .../__tests__/rooMessage.spec.ts | 262 -- .../__tests__/rooMessages.spec.ts | 277 -- .../__tests__/taskMessages.spec.ts | 35 +- src/core/task-persistence/apiMessages.ts | 156 +- .../__tests__/anthropicToRoo.spec.ts | 1075 ------- .../converters/anthropicToRoo.ts | 321 --- src/core/task-persistence/delegationMeta.ts | 138 - src/core/task-persistence/index.ts | 36 - src/core/task-persistence/messageUtils.ts | 69 - src/core/task-persistence/rooMessage.ts | 331 --- src/core/task-persistence/taskMessages.ts | 16 +- src/core/task-persistence/taskMetadata.ts | 7 + src/core/task/Task.ts | 1561 +++++------ src/core/task/__tests__/Task.dispose.test.ts | 2 + .../task/__tests__/Task.persistence.spec.ts | 498 ---- src/core/task/__tests__/Task.spec.ts | 281 +- src/core/task/__tests__/Task.throttle.test.ts | 2 + .../flushPendingToolResultsToHistory.spec.ts | 112 +- .../task/__tests__/grace-retry-errors.spec.ts | 2 +- .../task/__tests__/grounding-sources.test.ts | 7 +- .../mergeConsecutiveApiMessages.spec.ts | 8 +- .../__tests__/native-tools-filtering.spec.ts | 4 +- .../__tests__/reasoning-preservation.test.ts | 256 +- .../task/__tests__/task-tool-history.spec.ts | 13 +- .../__tests__/validateToolResultIds.spec.ts | 270 +- src/core/task/build-tools.ts | 15 +- src/core/task/mergeConsecutiveApiMessages.ts | 37 +- src/core/task/validateToolResultIds.ts | 213 +- src/core/tools/ApplyPatchTool.ts | 38 +- src/core/tools/AttemptCompletionTool.ts | 96 +- src/core/tools/BrowserActionTool.ts | 280 ++ src/core/tools/EditTool.ts | 279 -- src/core/tools/ExecuteCommandTool.ts | 11 +- src/core/tools/NewTaskTool.ts | 8 +- src/core/tools/ReadFileTool.ts | 1132 ++++---- src/core/tools/SearchAndReplaceTool.ts | 305 +- src/core/tools/SkillTool.ts | 2 +- src/core/tools/ToolRepetitionDetector.ts | 22 + src/core/tools/UseMcpToolTool.ts | 37 +- ...rowserActionTool.coordinateScaling.spec.ts | 84 + .../BrowserActionTool.screenshot.spec.ts | 25 + .../__tests__/ToolRepetitionDetector.spec.ts | 178 +- .../__tests__/applyPatchTool.partial.spec.ts | 190 -- .../attemptCompletionDelegation.spec.ts | 260 -- .../__tests__/attemptCompletionTool.spec.ts | 125 - src/core/tools/__tests__/editTool.spec.ts | 423 --- src/core/tools/__tests__/newTaskTool.spec.ts | 14 +- src/core/tools/__tests__/readFileTool.spec.ts | 2294 +++++++++++---- .../__tests__/searchAndReplaceTool.spec.ts | 417 ++- src/core/tools/__tests__/skillTool.spec.ts | 16 +- .../tools/__tests__/useMcpToolTool.spec.ts | 241 +- .../tools/__tests__/validateToolUse.spec.ts | 66 +- .../__tests__/truncateDefinitions.spec.ts | 160 ++ src/core/tools/helpers/fileTokenBudget.ts | 9 + src/core/tools/helpers/truncateDefinitions.ts | 44 + src/core/tools/validateToolUse.ts | 38 +- .../webview/BrowserSessionPanelManager.ts | 310 +++ src/core/webview/ClineProvider.ts | 1103 +++----- .../ClineProvider.apiHandlerRebuild.spec.ts | 5 - .../ClineProvider.lockApiConfig.spec.ts | 372 --- .../webview/__tests__/ClineProvider.spec.ts | 496 ++-- .../ClineProvider.sticky-mode.spec.ts | 9 +- .../ClineProvider.sticky-profile.spec.ts | 9 +- .../ClineProvider.taskHistory.spec.ts | 178 +- ...ateSystemPrompt.browser-capability.spec.ts | 81 + .../removeClineFromStack-delegation.spec.ts | 210 -- .../__tests__/skillsMessageHandler.spec.ts | 415 --- ...ebviewMessageHandler.lockApiConfig.spec.ts | 68 - ...webviewMessageHandler.routerModels.spec.ts | 6 + .../__tests__/webviewMessageHandler.spec.ts | 63 + src/core/webview/generateSystemPrompt.ts | 32 +- src/core/webview/skillsMessageHandler.ts | 208 -- src/core/webview/webviewMessageHandler.ts | 224 +- src/esbuild.mjs | 16 - src/extension.ts | 21 +- .../__tests__/api-send-message.spec.ts | 1 - src/extension/api.ts | 140 +- src/i18n/locales/ca/common.json | 14 +- src/i18n/locales/ca/skills.json | 16 - src/i18n/locales/de/common.json | 14 +- src/i18n/locales/de/skills.json | 16 - src/i18n/locales/en/common.json | 9 + src/i18n/locales/en/skills.json | 16 - src/i18n/locales/es/common.json | 14 +- src/i18n/locales/es/skills.json | 16 - src/i18n/locales/fr/common.json | 14 +- src/i18n/locales/fr/skills.json | 16 - src/i18n/locales/hi/common.json | 14 +- src/i18n/locales/hi/skills.json | 16 - src/i18n/locales/id/common.json | 14 +- src/i18n/locales/id/skills.json | 16 - src/i18n/locales/it/common.json | 14 +- src/i18n/locales/it/skills.json | 16 - src/i18n/locales/ja/common.json | 14 +- src/i18n/locales/ja/skills.json | 16 - src/i18n/locales/ko/common.json | 14 +- src/i18n/locales/ko/skills.json | 16 - src/i18n/locales/nl/common.json | 14 +- src/i18n/locales/nl/skills.json | 16 - src/i18n/locales/pl/common.json | 14 +- src/i18n/locales/pl/skills.json | 16 - src/i18n/locales/pt-BR/common.json | 14 +- src/i18n/locales/pt-BR/skills.json | 16 - src/i18n/locales/ru/common.json | 14 +- src/i18n/locales/ru/skills.json | 16 - src/i18n/locales/tr/common.json | 14 +- src/i18n/locales/tr/skills.json | 16 - src/i18n/locales/vi/common.json | 14 +- src/i18n/locales/vi/skills.json | 16 - src/i18n/locales/zh-CN/common.json | 14 +- src/i18n/locales/zh-CN/skills.json | 16 - src/i18n/locales/zh-TW/common.json | 14 +- src/i18n/locales/zh-TW/skills.json | 16 - src/integrations/editor/DiffViewProvider.ts | 6 +- .../misc/__tests__/export-markdown.spec.ts | 10 - .../extract-text-large-files.spec.ts | 221 ++ .../misc/__tests__/indentation-reader.spec.ts | 639 ----- .../misc/__tests__/read-file-tool.spec.ts | 147 + .../__tests__/read-file-with-budget.spec.ts | 321 +++ src/integrations/misc/export-markdown.ts | 114 +- src/integrations/misc/extract-text.ts | 92 +- src/integrations/misc/indentation-reader.ts | 469 ---- .../misc/read-file-with-budget.ts | 182 ++ src/integrations/terminal/README.md | 66 + src/package.json | 31 +- src/services/browser/BrowserSession.ts | 913 ++++++ src/services/browser/UrlContentFetcher.ts | 143 + .../browser/__tests__/BrowserSession.spec.ts | 628 +++++ .../__tests__/UrlContentFetcher.spec.ts | 369 +++ src/services/browser/browserDiscovery.ts | 181 ++ .../checkpoints/ShadowCheckpointService.ts | 11 +- .../__tests__/ShadowCheckpointService.spec.ts | 78 - .../__tests__/service-factory.spec.ts | 21 +- .../embedders/__tests__/gemini.spec.ts | 27 +- src/services/code-index/embedders/gemini.ts | 29 +- .../roo-config/__tests__/index.spec.ts | 23 - src/services/roo-config/index.ts | 44 - src/services/skills/SkillsManager.ts | 450 +-- .../skills/__tests__/SkillsManager.spec.ts | 953 +------ .../generate-built-in-skills.spec.ts | 175 ++ src/services/skills/built-in-skills.ts | 428 +++ .../built-in/create-mcp-server/SKILL.md | 304 ++ .../skills/built-in/create-mode/SKILL.md | 57 + .../skills/generate-built-in-skills.ts | 302 ++ src/shared/ProfileValidator.ts | 9 + src/shared/__tests__/ProfileValidator.spec.ts | 34 + .../__tests__/checkExistApiConfig.spec.ts | 1 + src/shared/__tests__/embeddingModels.spec.ts | 95 - src/shared/__tests__/modes.spec.ts | 20 +- src/shared/api.ts | 5 + src/shared/browserUtils.ts | 95 + src/shared/checkExistApiConfig.ts | 8 +- src/shared/embeddingModels.ts | 4 +- src/shared/globalFileNames.ts | 1 - src/shared/skills.ts | 16 +- src/shared/tools.ts | 75 +- src/types/requesty-ai-sdk.d.ts | 58 - src/utils/__tests__/json-schema.spec.ts | 76 +- src/utils/__tests__/tool-id.spec.ts | 8 - webview-ui/browser-panel.html | 12 + webview-ui/src/browser-panel.tsx | 12 + .../BrowserPanelStateProvider.tsx | 61 + .../browser-session/BrowserSessionPanel.tsx | 106 + .../src/components/chat/Announcement.tsx | 3 +- .../src/components/chat/ApiConfigSelector.tsx | 14 - .../components/chat/AutoApproveDropdown.tsx | 5 + .../src/components/chat/BatchDiffApproval.tsx | 4 +- .../components/chat/BatchFilePermission.tsx | 4 +- .../chat/BatchListFilesPermission.tsx | 45 - .../src/components/chat/BrowserActionRow.tsx | 195 ++ .../src/components/chat/BrowserSessionRow.tsx | 1137 ++++++++ .../chat/BrowserSessionStatusRow.tsx | 34 + webview-ui/src/components/chat/ChatRow.tsx | 198 +- .../src/components/chat/ChatTextArea.tsx | 19 +- webview-ui/src/components/chat/ChatView.tsx | 389 +-- .../src/components/chat/SlashCommandItem.tsx | 84 + .../components/chat/SystemPromptWarning.tsx | 17 + webview-ui/src/components/chat/TaskHeader.tsx | 57 +- .../chat/__tests__/ApiConfigSelector.spec.tsx | 2 - .../BatchListFilesPermission.spec.tsx | 103 - .../BrowserSessionRow.aspect-ratio.spec.tsx | 55 + ...owserSessionRow.disconnect-button.spec.tsx | 42 + .../chat/__tests__/BrowserSessionRow.spec.tsx | 126 + .../__tests__/ChatRow.diff-actions.spec.tsx | 195 +- .../ChatTextArea.lockApiConfig.spec.tsx | 156 -- .../__tests__/ChatView.keyboard-fix.spec.tsx | 4 + .../ChatView.notification-sound.spec.tsx | 113 +- .../ChatView.preserve-images.spec.tsx | 479 ---- .../chat/__tests__/ChatView.spec.tsx | 68 +- .../chat/__tests__/FollowUpSuggest.spec.tsx | 98 - .../src/components/common/CodeBlock.tsx | 35 +- .../src/components/history/HistoryPreview.tsx | 1 - .../src/components/history/HistoryView.tsx | 6 +- .../src/components/history/SubtaskRow.tsx | 91 +- .../src/components/history/TaskGroupItem.tsx | 23 +- .../history/__tests__/HistoryPreview.spec.tsx | 12 +- .../history/__tests__/SubtaskRow.spec.tsx | 213 -- .../history/__tests__/TaskGroupItem.spec.tsx | 150 +- .../history/__tests__/useGroupedTasks.spec.ts | 213 +- webview-ui/src/components/history/types.ts | 29 +- .../src/components/history/useGroupedTasks.ts | 38 +- webview-ui/src/components/modes/ModesView.tsx | 62 + .../src/components/settings/ApiOptions.tsx | 727 ++--- .../settings/AutoApproveSettings.tsx | 4 + .../components/settings/AutoApproveToggle.tsx | 8 + .../components/settings/BrowserSettings.tsx | 243 ++ .../settings/ContextManagementSettings.tsx | 68 + .../components/settings/CreateSkillDialog.tsx | 289 -- .../settings/CreateSlashCommandDialog.tsx | 156 -- .../src/components/settings/ModelPicker.tsx | 14 +- .../src/components/settings/SettingsView.tsx | 61 +- .../src/components/settings/SkillItem.tsx | 113 - .../components/settings/SkillsSettings.tsx | 387 --- .../settings/SlashCommandsSettings.tsx | 323 ++- .../ApiOptions.provider-filtering.spec.tsx | 2 + .../settings/__tests__/ApiOptions.spec.tsx | 27 - .../__tests__/AutoApproveToggle.spec.tsx | 1 + .../ContextManagementSettings.spec.tsx | 86 +- .../__tests__/CreateSkillDialog.spec.tsx | 516 ---- .../SettingsView.change-detection.spec.tsx | 66 +- .../settings/__tests__/SettingsView.spec.tsx | 48 +- .../SettingsView.unsaved-changes.spec.tsx | 66 +- .../settings/__tests__/SkillItem.spec.tsx | 233 -- .../__tests__/SkillsSettings.spec.tsx | 450 --- .../__tests__/SlashCommandsSettings.spec.tsx | 445 +-- .../src/components/settings/constants.ts | 20 +- .../settings/providers/Anthropic.tsx | 4 +- .../components/settings/providers/Azure.tsx | 75 - .../components/settings/providers/Bedrock.tsx | 2 +- .../settings/providers/Cerebras.tsx | 50 + .../components/settings/providers/Chutes.tsx | 76 + .../settings/providers/DeepInfra.tsx | 100 + .../components/settings/providers/Doubao.tsx | 53 + .../settings/providers/Featherless.tsx | 50 + .../components/settings/providers/Gemini.tsx | 28 +- .../components/settings/providers/Groq.tsx | 50 + .../settings/providers/HuggingFace.tsx | 277 ++ .../settings/providers/IOIntelligence.tsx | 80 + .../settings/providers/OpenAICompatible.tsx | 8 +- .../components/settings/providers/Unbound.tsx | 197 ++ .../components/settings/providers/Vertex.tsx | 29 +- .../providers/__tests__/Gemini.spec.tsx | 147 +- .../providers/__tests__/HuggingFace.spec.tsx | 300 ++ .../providers/__tests__/Vertex.spec.tsx | 178 +- .../components/settings/providers/index.ts | 10 +- .../settings/utils/providerModelConfig.ts | 23 +- webview-ui/src/components/ui/checkbox.tsx | 2 +- .../hooks/__tests__/useSelectedModel.spec.ts | 22 +- .../components/ui/hooks/useRouterModels.ts | 4 +- .../components/ui/hooks/useSelectedModel.ts | 134 +- webview-ui/src/components/ui/input.tsx | 2 +- webview-ui/src/components/ui/textarea.tsx | 2 +- .../welcome/WelcomeViewProvider.tsx | 10 +- .../src/context/ExtensionStateContext.tsx | 57 +- .../__tests__/ExtensionStateContext.spec.tsx | 151 +- .../__tests__/useAutoApprovalState.spec.ts | 8 +- webview-ui/src/hooks/useAutoApprovalState.ts | 1 + .../src/hooks/useAutoApprovalToggles.ts | 3 + webview-ui/src/i18n/locales/ca/chat.json | 68 +- webview-ui/src/i18n/locales/ca/prompts.json | 8 + webview-ui/src/i18n/locales/ca/settings.json | 156 +- webview-ui/src/i18n/locales/de/chat.json | 68 +- webview-ui/src/i18n/locales/de/prompts.json | 8 + webview-ui/src/i18n/locales/de/settings.json | 156 +- webview-ui/src/i18n/locales/en/chat.json | 70 +- webview-ui/src/i18n/locales/en/prompts.json | 8 + webview-ui/src/i18n/locales/en/settings.json | 178 +- webview-ui/src/i18n/locales/es/chat.json | 68 +- webview-ui/src/i18n/locales/es/prompts.json | 8 + webview-ui/src/i18n/locales/es/settings.json | 156 +- webview-ui/src/i18n/locales/fr/chat.json | 68 +- webview-ui/src/i18n/locales/fr/prompts.json | 8 + webview-ui/src/i18n/locales/fr/settings.json | 156 +- webview-ui/src/i18n/locales/hi/chat.json | 68 +- webview-ui/src/i18n/locales/hi/prompts.json | 8 + webview-ui/src/i18n/locales/hi/settings.json | 157 +- webview-ui/src/i18n/locales/id/chat.json | 68 +- webview-ui/src/i18n/locales/id/prompts.json | 8 + webview-ui/src/i18n/locales/id/settings.json | 186 +- webview-ui/src/i18n/locales/it/chat.json | 68 +- webview-ui/src/i18n/locales/it/prompts.json | 8 + webview-ui/src/i18n/locales/it/settings.json | 157 +- webview-ui/src/i18n/locales/ja/chat.json | 68 +- webview-ui/src/i18n/locales/ja/prompts.json | 8 + webview-ui/src/i18n/locales/ja/settings.json | 157 +- webview-ui/src/i18n/locales/ko/chat.json | 68 +- webview-ui/src/i18n/locales/ko/prompts.json | 8 + webview-ui/src/i18n/locales/ko/settings.json | 157 +- webview-ui/src/i18n/locales/nl/chat.json | 72 +- webview-ui/src/i18n/locales/nl/prompts.json | 8 + webview-ui/src/i18n/locales/nl/settings.json | 157 +- webview-ui/src/i18n/locales/pl/chat.json | 72 +- webview-ui/src/i18n/locales/pl/prompts.json | 8 + webview-ui/src/i18n/locales/pl/settings.json | 157 +- webview-ui/src/i18n/locales/pt-BR/chat.json | 68 +- .../src/i18n/locales/pt-BR/prompts.json | 8 + .../src/i18n/locales/pt-BR/settings.json | 157 +- webview-ui/src/i18n/locales/ru/chat.json | 68 +- webview-ui/src/i18n/locales/ru/prompts.json | 8 + webview-ui/src/i18n/locales/ru/settings.json | 157 +- webview-ui/src/i18n/locales/tr/chat.json | 68 +- webview-ui/src/i18n/locales/tr/prompts.json | 8 + webview-ui/src/i18n/locales/tr/settings.json | 157 +- webview-ui/src/i18n/locales/vi/chat.json | 68 +- webview-ui/src/i18n/locales/vi/prompts.json | 8 + webview-ui/src/i18n/locales/vi/settings.json | 157 +- webview-ui/src/i18n/locales/zh-CN/chat.json | 68 +- .../src/i18n/locales/zh-CN/prompts.json | 8 + .../src/i18n/locales/zh-CN/settings.json | 157 +- webview-ui/src/i18n/locales/zh-TW/chat.json | 72 +- .../src/i18n/locales/zh-TW/prompts.json | 8 + .../src/i18n/locales/zh-TW/settings.json | 154 +- webview-ui/src/index.css | 4 - .../utils/__tests__/batchConsecutive.spec.ts | 116 - .../src/utils/__tests__/validate.spec.ts | 5 + webview-ui/src/utils/batchConsecutive.ts | 38 - webview-ui/src/utils/formatPathTooltip.ts | 2 +- webview-ui/src/utils/validate.ts | 54 +- webview-ui/vite.config.ts | 3 +- 678 files changed, 60413 insertions(+), 52234 deletions(-) create mode 100644 .env.sample delete mode 100644 .github/workflows/cli-release.yml create mode 100644 .roo/rules-docs-extractor/2_documentation_patterns.xml delete mode 100644 .roo/rules-docs-extractor/2_verification_workflow.xml create mode 100644 .roo/rules-docs-extractor/3_analysis_techniques.xml delete mode 100644 .roo/rules-docs-extractor/3_output_format.xml create mode 100644 .roo/rules-docs-extractor/4_communication_guidelines.xml create mode 100644 .roo/rules-integration-tester/1_workflow.xml create mode 100644 .roo/rules-integration-tester/2_test_patterns.xml create mode 100644 .roo/rules-integration-tester/3_best_practices.xml create mode 100644 .roo/rules-integration-tester/4_common_mistakes.xml create mode 100644 .roo/rules-integration-tester/5_test_environment.xml create mode 100644 .roo/rules-issue-writer/2_github_issue_templates.xml delete mode 100644 .roo/rules-issue-writer/5_examples.xml create mode 100644 .roo/rules-issue-writer/5_github_cli_usage.xml create mode 100644 .roo/rules-mode-writer/1_mode_creation_workflow.xml create mode 100644 .roo/rules-mode-writer/2_xml_structuring_best_practices.xml create mode 100644 .roo/rules-mode-writer/3_mode_configuration_patterns.xml create mode 100644 .roo/rules-mode-writer/4_instruction_file_templates.xml create mode 100644 .roo/rules-mode-writer/5_complete_mode_examples.xml create mode 100644 .roo/rules-mode-writer/6_mode_testing_validation.xml create mode 100644 .roo/rules-mode-writer/7_validation_cohesion_checking.xml delete mode 100755 apps/cli/scripts/build.sh create mode 100755 apps/cli/scripts/release.sh create mode 100644 apps/cli/src/ui/components/tools/BrowserTool.tsx create mode 100644 apps/web-evals/src/app/api/runs/[id]/logs/[taskId]/route.ts create mode 100644 apps/web-evals/src/app/api/runs/[id]/logs/failed/route.ts delete mode 100644 apps/web-roo-code/src/app/linear/page.tsx delete mode 100644 apps/web-roo-code/src/components/linear/linear-issue-demo.tsx delete mode 100644 apps/web-roo-code/src/components/ui/navigation-menu.tsx delete mode 100644 apps/web-roo-code/src/images.d.ts delete mode 100644 packages/types/src/__tests__/skills.test.ts delete mode 100644 packages/types/src/providers/azure.ts create mode 100644 packages/types/src/providers/cerebras.ts create mode 100644 packages/types/src/providers/chutes.ts create mode 100644 packages/types/src/providers/deepinfra.ts create mode 100644 packages/types/src/providers/doubao.ts create mode 100644 packages/types/src/providers/featherless.ts create mode 100644 packages/types/src/providers/groq.ts create mode 100644 packages/types/src/providers/huggingface.ts create mode 100644 packages/types/src/providers/io-intelligence.ts create mode 100644 packages/types/src/providers/unbound.ts delete mode 100644 packages/types/src/skills.ts delete mode 100644 releases/3.46.0-release.png delete mode 100644 releases/3.47.0-release.png delete mode 100644 scripts/code-server.js delete mode 100644 src/__tests__/removeClineFromStack-delegation.spec.ts delete mode 100644 src/api/providers/__tests__/azure.spec.ts create mode 100644 src/api/providers/__tests__/base-openai-compatible-provider-timeout.spec.ts create mode 100644 src/api/providers/__tests__/base-openai-compatible-provider.spec.ts delete mode 100644 src/api/providers/__tests__/baseten.spec.ts create mode 100644 src/api/providers/__tests__/cerebras.spec.ts create mode 100644 src/api/providers/__tests__/chutes.spec.ts create mode 100644 src/api/providers/__tests__/deepinfra.spec.ts create mode 100644 src/api/providers/__tests__/featherless.spec.ts create mode 100644 src/api/providers/__tests__/groq.spec.ts create mode 100644 src/api/providers/__tests__/io-intelligence.spec.ts delete mode 100644 src/api/providers/__tests__/openai-native-reasoning.spec.ts create mode 100644 src/api/providers/__tests__/unbound.spec.ts delete mode 100644 src/api/providers/azure.ts create mode 100644 src/api/providers/base-openai-compatible-provider.ts create mode 100644 src/api/providers/cerebras.ts create mode 100644 src/api/providers/chutes.ts create mode 100644 src/api/providers/deepinfra.ts create mode 100644 src/api/providers/doubao.ts create mode 100644 src/api/providers/featherless.ts create mode 100644 src/api/providers/fetchers/__tests__/chutes.spec.ts create mode 100644 src/api/providers/fetchers/chutes.ts create mode 100644 src/api/providers/fetchers/deepinfra.ts create mode 100644 src/api/providers/fetchers/huggingface.ts create mode 100644 src/api/providers/fetchers/io-intelligence.ts create mode 100644 src/api/providers/fetchers/unbound.ts create mode 100644 src/api/providers/groq.ts create mode 100644 src/api/providers/huggingface.ts create mode 100644 src/api/providers/io-intelligence.ts create mode 100644 src/api/providers/router-provider.ts create mode 100644 src/api/providers/unbound.ts create mode 100644 src/api/transform/__tests__/bedrock-converse-format.spec.ts delete mode 100644 src/api/transform/__tests__/cache-breakpoints.spec.ts create mode 100644 src/api/transform/__tests__/gemini-format.spec.ts create mode 100644 src/api/transform/bedrock-converse-format.ts delete mode 100644 src/api/transform/cache-breakpoints.ts create mode 100644 src/api/transform/cache-strategy/__tests__/cache-strategy.spec.ts create mode 100644 src/api/transform/cache-strategy/base-strategy.ts create mode 100644 src/api/transform/cache-strategy/multi-point-strategy.ts create mode 100644 src/api/transform/cache-strategy/types.ts create mode 100644 src/api/transform/caching/__tests__/anthropic.spec.ts create mode 100644 src/api/transform/caching/__tests__/gemini.spec.ts create mode 100644 src/api/transform/caching/__tests__/vercel-ai-gateway.spec.ts create mode 100644 src/api/transform/caching/__tests__/vertex.spec.ts create mode 100644 src/api/transform/caching/anthropic.ts create mode 100644 src/api/transform/caching/gemini.ts create mode 100644 src/api/transform/caching/vercel-ai-gateway.ts create mode 100644 src/api/transform/caching/vertex.ts create mode 100644 src/api/transform/gemini-format.ts create mode 100644 src/api/transform/zai-format.ts delete mode 100644 src/core/auto-approval/__tests__/commands.spec.ts create mode 100644 src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap create mode 100644 src/core/prompts/__tests__/custom-system-prompt.spec.ts create mode 100644 src/core/prompts/sections/__tests__/custom-system-prompt.spec.ts create mode 100644 src/core/prompts/sections/custom-system-prompt.ts delete mode 100644 src/core/prompts/tools/__tests__/filter-tools-for-mode.spec.ts create mode 100644 src/core/prompts/tools/native-tools/browser_action.ts delete mode 100644 src/core/prompts/tools/native-tools/edit.ts create mode 100644 src/core/prompts/tools/native-tools/search_and_replace.ts delete mode 100644 src/core/task-persistence/__tests__/apiMessages.spec.ts delete mode 100644 src/core/task-persistence/__tests__/delegationMeta.spec.ts delete mode 100644 src/core/task-persistence/__tests__/messageUtils.spec.ts delete mode 100644 src/core/task-persistence/__tests__/rooMessage.spec.ts delete mode 100644 src/core/task-persistence/__tests__/rooMessages.spec.ts delete mode 100644 src/core/task-persistence/converters/__tests__/anthropicToRoo.spec.ts delete mode 100644 src/core/task-persistence/converters/anthropicToRoo.ts delete mode 100644 src/core/task-persistence/delegationMeta.ts delete mode 100644 src/core/task-persistence/messageUtils.ts delete mode 100644 src/core/task-persistence/rooMessage.ts delete mode 100644 src/core/task/__tests__/Task.persistence.spec.ts create mode 100644 src/core/tools/BrowserActionTool.ts delete mode 100644 src/core/tools/EditTool.ts create mode 100644 src/core/tools/__tests__/BrowserActionTool.coordinateScaling.spec.ts create mode 100644 src/core/tools/__tests__/BrowserActionTool.screenshot.spec.ts delete mode 100644 src/core/tools/__tests__/applyPatchTool.partial.spec.ts delete mode 100644 src/core/tools/__tests__/attemptCompletionDelegation.spec.ts delete mode 100644 src/core/tools/__tests__/editTool.spec.ts create mode 100644 src/core/tools/helpers/__tests__/truncateDefinitions.spec.ts create mode 100644 src/core/tools/helpers/fileTokenBudget.ts create mode 100644 src/core/tools/helpers/truncateDefinitions.ts create mode 100644 src/core/webview/BrowserSessionPanelManager.ts delete mode 100644 src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts create mode 100644 src/core/webview/__tests__/generateSystemPrompt.browser-capability.spec.ts delete mode 100644 src/core/webview/__tests__/removeClineFromStack-delegation.spec.ts delete mode 100644 src/core/webview/__tests__/skillsMessageHandler.spec.ts delete mode 100644 src/core/webview/__tests__/webviewMessageHandler.lockApiConfig.spec.ts delete mode 100644 src/core/webview/skillsMessageHandler.ts delete mode 100644 src/i18n/locales/ca/skills.json delete mode 100644 src/i18n/locales/de/skills.json delete mode 100644 src/i18n/locales/en/skills.json delete mode 100644 src/i18n/locales/es/skills.json delete mode 100644 src/i18n/locales/fr/skills.json delete mode 100644 src/i18n/locales/hi/skills.json delete mode 100644 src/i18n/locales/id/skills.json delete mode 100644 src/i18n/locales/it/skills.json delete mode 100644 src/i18n/locales/ja/skills.json delete mode 100644 src/i18n/locales/ko/skills.json delete mode 100644 src/i18n/locales/nl/skills.json delete mode 100644 src/i18n/locales/pl/skills.json delete mode 100644 src/i18n/locales/pt-BR/skills.json delete mode 100644 src/i18n/locales/ru/skills.json delete mode 100644 src/i18n/locales/tr/skills.json delete mode 100644 src/i18n/locales/vi/skills.json delete mode 100644 src/i18n/locales/zh-CN/skills.json delete mode 100644 src/i18n/locales/zh-TW/skills.json create mode 100644 src/integrations/misc/__tests__/extract-text-large-files.spec.ts delete mode 100644 src/integrations/misc/__tests__/indentation-reader.spec.ts create mode 100644 src/integrations/misc/__tests__/read-file-tool.spec.ts create mode 100644 src/integrations/misc/__tests__/read-file-with-budget.spec.ts delete mode 100644 src/integrations/misc/indentation-reader.ts create mode 100644 src/integrations/misc/read-file-with-budget.ts create mode 100644 src/integrations/terminal/README.md create mode 100644 src/services/browser/BrowserSession.ts create mode 100644 src/services/browser/UrlContentFetcher.ts create mode 100644 src/services/browser/__tests__/BrowserSession.spec.ts create mode 100644 src/services/browser/__tests__/UrlContentFetcher.spec.ts create mode 100644 src/services/browser/browserDiscovery.ts create mode 100644 src/services/skills/__tests__/generate-built-in-skills.spec.ts create mode 100644 src/services/skills/built-in-skills.ts create mode 100644 src/services/skills/built-in/create-mcp-server/SKILL.md create mode 100644 src/services/skills/built-in/create-mode/SKILL.md create mode 100644 src/services/skills/generate-built-in-skills.ts delete mode 100644 src/shared/__tests__/embeddingModels.spec.ts create mode 100644 src/shared/browserUtils.ts delete mode 100644 src/types/requesty-ai-sdk.d.ts create mode 100644 webview-ui/browser-panel.html create mode 100644 webview-ui/src/browser-panel.tsx create mode 100644 webview-ui/src/components/browser-session/BrowserPanelStateProvider.tsx create mode 100644 webview-ui/src/components/browser-session/BrowserSessionPanel.tsx delete mode 100644 webview-ui/src/components/chat/BatchListFilesPermission.tsx create mode 100644 webview-ui/src/components/chat/BrowserActionRow.tsx create mode 100644 webview-ui/src/components/chat/BrowserSessionRow.tsx create mode 100644 webview-ui/src/components/chat/BrowserSessionStatusRow.tsx create mode 100644 webview-ui/src/components/chat/SlashCommandItem.tsx create mode 100644 webview-ui/src/components/chat/SystemPromptWarning.tsx delete mode 100644 webview-ui/src/components/chat/__tests__/BatchListFilesPermission.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/BrowserSessionRow.aspect-ratio.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/BrowserSessionRow.disconnect-button.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/BrowserSessionRow.spec.tsx delete mode 100644 webview-ui/src/components/chat/__tests__/ChatTextArea.lockApiConfig.spec.tsx delete mode 100644 webview-ui/src/components/chat/__tests__/ChatView.preserve-images.spec.tsx delete mode 100644 webview-ui/src/components/history/__tests__/SubtaskRow.spec.tsx create mode 100644 webview-ui/src/components/settings/BrowserSettings.tsx delete mode 100644 webview-ui/src/components/settings/CreateSkillDialog.tsx delete mode 100644 webview-ui/src/components/settings/CreateSlashCommandDialog.tsx delete mode 100644 webview-ui/src/components/settings/SkillItem.tsx delete mode 100644 webview-ui/src/components/settings/SkillsSettings.tsx delete mode 100644 webview-ui/src/components/settings/__tests__/CreateSkillDialog.spec.tsx delete mode 100644 webview-ui/src/components/settings/__tests__/SkillItem.spec.tsx delete mode 100644 webview-ui/src/components/settings/__tests__/SkillsSettings.spec.tsx delete mode 100644 webview-ui/src/components/settings/providers/Azure.tsx create mode 100644 webview-ui/src/components/settings/providers/Cerebras.tsx create mode 100644 webview-ui/src/components/settings/providers/Chutes.tsx create mode 100644 webview-ui/src/components/settings/providers/DeepInfra.tsx create mode 100644 webview-ui/src/components/settings/providers/Doubao.tsx create mode 100644 webview-ui/src/components/settings/providers/Featherless.tsx create mode 100644 webview-ui/src/components/settings/providers/Groq.tsx create mode 100644 webview-ui/src/components/settings/providers/HuggingFace.tsx create mode 100644 webview-ui/src/components/settings/providers/IOIntelligence.tsx create mode 100644 webview-ui/src/components/settings/providers/Unbound.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/HuggingFace.spec.tsx delete mode 100644 webview-ui/src/utils/__tests__/batchConsecutive.spec.ts delete mode 100644 webview-ui/src/utils/batchConsecutive.ts diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000000..aebe5cca44a --- /dev/null +++ b/.env.sample @@ -0,0 +1,6 @@ +POSTHOG_API_KEY=key-goes-here + +# Roo Code Cloud / Local Development +CLERK_BASE_URL=https://epic-chamois-85.clerk.accounts.dev +ROO_CODE_API_URL=http://localhost:3000 +ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy/v1 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e2e8fa34b63..a3daa0f144e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # These owners will be the default owners for everything in the repo -* @mrubens @cte @jr @hannesrudolph @daniel-lxs +* @mrubens @cte @jr diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8c7969776da..0351ad19301 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: Feature Request + url: https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests + about: Share and vote on feature requests for Roo Code - name: Leave a Review url: https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline&ssr=false#review-details about: Enjoying Roo Code? Leave a review here! diff --git a/.github/workflows/cli-release.yml b/.github/workflows/cli-release.yml deleted file mode 100644 index 20961a9f2d3..00000000000 --- a/.github/workflows/cli-release.yml +++ /dev/null @@ -1,394 +0,0 @@ -name: CLI Release - -on: - workflow_dispatch: - inputs: - version: - description: 'Version to release (e.g., 0.1.0). Leave empty to use package.json version.' - required: false - type: string - dry_run: - description: 'Dry run (build and test but do not create release).' - required: false - type: boolean - default: false - -jobs: - # Build CLI for each platform. - build: - strategy: - fail-fast: false - matrix: - include: - - os: macos-latest - platform: darwin-arm64 - runs-on: macos-latest - - os: ubuntu-latest - platform: linux-x64 - runs-on: ubuntu-latest - - os: ubuntu-24.04-arm - platform: linux-arm64 - runs-on: ubuntu-24.04-arm - - runs-on: ${{ matrix.runs-on }} - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Node.js and pnpm - uses: ./.github/actions/setup-node-pnpm - - - name: Get version - id: version - run: | - if [ -n "${{ inputs.version }}" ]; then - VERSION="${{ inputs.version }}" - else - VERSION=$(node -p "require('./apps/cli/package.json').version") - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT - echo "Using version: $VERSION" - - - name: Build extension bundle - run: pnpm bundle - - - name: Build CLI - run: pnpm --filter @roo-code/cli build - - - name: Create release tarball - id: tarball - env: - VERSION: ${{ steps.version.outputs.version }} - PLATFORM: ${{ matrix.platform }} - run: | - RELEASE_DIR="roo-cli-${PLATFORM}" - TARBALL="roo-cli-${PLATFORM}.tar.gz" - - # Clean up any previous build. - rm -rf "$RELEASE_DIR" - rm -f "$TARBALL" - - # Create directory structure. - mkdir -p "$RELEASE_DIR/bin" - mkdir -p "$RELEASE_DIR/lib" - mkdir -p "$RELEASE_DIR/extension" - - # Copy CLI dist files. - echo "Copying CLI files..." - cp -r apps/cli/dist/* "$RELEASE_DIR/lib/" - - # Create package.json for npm install. - echo "Creating package.json..." - node -e " - const pkg = require('./apps/cli/package.json'); - const newPkg = { - name: '@roo-code/cli', - version: '$VERSION', - type: 'module', - dependencies: { - '@inkjs/ui': pkg.dependencies['@inkjs/ui'], - '@trpc/client': pkg.dependencies['@trpc/client'], - 'commander': pkg.dependencies.commander, - 'fuzzysort': pkg.dependencies.fuzzysort, - 'ink': pkg.dependencies.ink, - 'p-wait-for': pkg.dependencies['p-wait-for'], - 'react': pkg.dependencies.react, - 'superjson': pkg.dependencies.superjson, - 'zustand': pkg.dependencies.zustand - } - }; - console.log(JSON.stringify(newPkg, null, 2)); - " > "$RELEASE_DIR/package.json" - - # Copy extension bundle. - echo "Copying extension bundle..." - cp -r src/dist/* "$RELEASE_DIR/extension/" - - # Add package.json to extension directory for CommonJS. - echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json" - - # Find and copy ripgrep binary. - echo "Looking for ripgrep binary..." - RIPGREP_PATH=$(find node_modules -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1) - if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then - echo "Found ripgrep at: $RIPGREP_PATH" - mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin" - cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/" - chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg" - mkdir -p "$RELEASE_DIR/bin" - cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/" - chmod +x "$RELEASE_DIR/bin/rg" - else - echo "Warning: ripgrep binary not found" - fi - - # Create the wrapper script - echo "Creating wrapper script..." - printf '%s\n' '#!/usr/bin/env node' \ - '' \ - "import { fileURLToPath } from 'url';" \ - "import { dirname, join } from 'path';" \ - '' \ - 'const __filename = fileURLToPath(import.meta.url);' \ - 'const __dirname = dirname(__filename);' \ - '' \ - '// Set environment variables for the CLI' \ - "process.env.ROO_CLI_ROOT = join(__dirname, '..');" \ - "process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');" \ - "process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');" \ - '' \ - '// Import and run the actual CLI' \ - "await import(join(__dirname, '..', 'lib', 'index.js'));" \ - > "$RELEASE_DIR/bin/roo" - - chmod +x "$RELEASE_DIR/bin/roo" - - # Create empty .env file. - touch "$RELEASE_DIR/.env" - - # Create tarball. - echo "Creating tarball..." - tar -czvf "$TARBALL" "$RELEASE_DIR" - - # Clean up release directory. - rm -rf "$RELEASE_DIR" - - # Create checksum. - if command -v sha256sum &> /dev/null; then - sha256sum "$TARBALL" > "${TARBALL}.sha256" - elif command -v shasum &> /dev/null; then - shasum -a 256 "$TARBALL" > "${TARBALL}.sha256" - fi - - echo "tarball=$TARBALL" >> $GITHUB_OUTPUT - echo "Created: $TARBALL" - ls -la "$TARBALL" - - - name: Verify tarball - env: - PLATFORM: ${{ matrix.platform }} - run: | - TARBALL="roo-cli-${PLATFORM}.tar.gz" - - # Create temp directory for verification. - VERIFY_DIR=$(mktemp -d) - - # Extract and verify structure. - tar -xzf "$TARBALL" -C "$VERIFY_DIR" - - echo "Verifying tarball contents..." - ls -la "$VERIFY_DIR/roo-cli-${PLATFORM}/" - - # Check required files exist. - test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/bin/roo" || { echo "Missing bin/roo"; exit 1; } - test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/lib/index.js" || { echo "Missing lib/index.js"; exit 1; } - test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/package.json" || { echo "Missing package.json"; exit 1; } - test -d "$VERIFY_DIR/roo-cli-${PLATFORM}/extension" || { echo "Missing extension directory"; exit 1; } - - echo "Tarball verification passed!" - - # Cleanup. - rm -rf "$VERIFY_DIR" - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: cli-${{ matrix.platform }} - path: | - roo-cli-${{ matrix.platform }}.tar.gz - roo-cli-${{ matrix.platform }}.tar.gz.sha256 - retention-days: 7 - - # Create GitHub release with all platform artifacts. - release: - needs: build - runs-on: ubuntu-latest - if: ${{ !inputs.dry_run }} - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get version - id: version - run: | - if [ -n "${{ inputs.version }}" ]; then - VERSION="${{ inputs.version }}" - else - VERSION=$(node -p "require('./apps/cli/package.json').version") - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Prepare release files - run: | - mkdir -p release - find artifacts -name "*.tar.gz" -exec cp {} release/ \; - find artifacts -name "*.sha256" -exec cp {} release/ \; - ls -la release/ - - - name: Extract changelog - id: changelog - env: - VERSION: ${{ steps.version.outputs.version }} - run: | - CHANGELOG_FILE="apps/cli/CHANGELOG.md" - - if [ -f "$CHANGELOG_FILE" ]; then - # Extract content between version headers. - CONTENT=$(awk -v version="$VERSION" ' - BEGIN { found = 0; content = ""; target = "[" version "]" } - /^## \[/ { - if (found) { exit } - if (index($0, target) > 0) { found = 1; next } - } - found { content = content $0 "\n" } - END { print content } - ' "$CHANGELOG_FILE") - - if [ -n "$CONTENT" ]; then - echo "Found changelog content" - echo "content<> $GITHUB_OUTPUT - echo "$CONTENT" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "No changelog content found for version $VERSION" - echo "content=" >> $GITHUB_OUTPUT - fi - else - echo "No changelog file found" - echo "content=" >> $GITHUB_OUTPUT - fi - - - name: Generate checksums summary - id: checksums - run: | - echo "checksums<> $GITHUB_OUTPUT - cat release/*.sha256 >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Check for existing release - id: check_release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ steps.version.outputs.tag }} - run: | - if gh release view "$TAG" &> /dev/null; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - - - name: Delete existing release - if: steps.check_release.outputs.exists == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ steps.version.outputs.tag }} - run: | - echo "Deleting existing release $TAG..." - gh release delete "$TAG" --yes || true - git push origin ":refs/tags/$TAG" || true - - - name: Create GitHub Release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VERSION: ${{ steps.version.outputs.version }} - TAG: ${{ steps.version.outputs.tag }} - CHANGELOG_CONTENT: ${{ steps.changelog.outputs.content }} - CHECKSUMS: ${{ steps.checksums.outputs.checksums }} - run: | - NOTES_FILE=$(mktemp) - - if [ -n "$CHANGELOG_CONTENT" ]; then - echo "## What's New" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "$CHANGELOG_CONTENT" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - fi - - echo "## Installation" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo '```bash' >> "$NOTES_FILE" - echo "curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE" - echo '```' >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "Or install a specific version:" >> "$NOTES_FILE" - echo '```bash' >> "$NOTES_FILE" - echo "ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE" - echo '```' >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "## Requirements" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "- Node.js 20 or higher" >> "$NOTES_FILE" - echo "- macOS Apple Silicon (M1/M2/M3/M4), Linux x64, or Linux ARM64" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "## Usage" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo '```bash' >> "$NOTES_FILE" - echo "# Run a task" >> "$NOTES_FILE" - echo 'roo "What is this project?"' >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "# See all options" >> "$NOTES_FILE" - echo "roo --help" >> "$NOTES_FILE" - echo '```' >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "## Platform Support" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "This release includes binaries for:" >> "$NOTES_FILE" - echo '- `roo-cli-darwin-arm64.tar.gz` - macOS Apple Silicon (M1/M2/M3)' >> "$NOTES_FILE" - echo '- `roo-cli-linux-x64.tar.gz` - Linux x64' >> "$NOTES_FILE" - echo '- `roo-cli-linux-arm64.tar.gz` - Linux ARM64' >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo "## Checksums" >> "$NOTES_FILE" - echo "" >> "$NOTES_FILE" - echo '```' >> "$NOTES_FILE" - echo "$CHECKSUMS" >> "$NOTES_FILE" - echo '```' >> "$NOTES_FILE" - - gh release create "$TAG" \ - --title "Roo Code CLI v$VERSION" \ - --notes-file "$NOTES_FILE" \ - --prerelease \ - release/* - - rm -f "$NOTES_FILE" - echo "Release created: https://github.com/${{ github.repository }}/releases/tag/$TAG" - - # Summary job for dry runs - summary: - needs: build - runs-on: ubuntu-latest - if: ${{ inputs.dry_run }} - - steps: - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Show build summary - run: | - echo "## Dry Run Complete" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "The following artifacts were built:" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - find artifacts -name "*.tar.gz" | while read f; do - SIZE=$(ls -lh "$f" | awk '{print $5}') - echo "- $(basename $f) ($SIZE)" >> $GITHUB_STEP_SUMMARY - done - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Checksums" >> $GITHUB_STEP_SUMMARY - echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - cat artifacts/*/*.sha256 >> $GITHUB_STEP_SUMMARY - echo "\`\`\`" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index 1dbcdc6a362..364b391a012 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ bin/ # Local prompts and rules /local-prompts -AGENTS.local.md # Test environment .test_env diff --git a/.roo/commands/cli-release.md b/.roo/commands/cli-release.md index 5e68e4df2d1..70b3698528d 100644 --- a/.roo/commands/cli-release.md +++ b/.roo/commands/cli-release.md @@ -1,5 +1,5 @@ --- -description: "Prepare a new release of the Roo Code CLI" +description: "Create a new release of the Roo Code CLI" argument-hint: "[version-description]" mode: code --- @@ -84,3 +84,41 @@ mode: code - [ ] All CI checks pass" \ --base main ``` + +7. Wait for PR approval and merge: + + - Request review if required by your workflow + - Ensure CI checks pass + - Merge the PR using: `gh pr merge --squash --delete-branch` + - Or merge via the GitHub UI + +8. Run the release script from the monorepo root: + + ```bash + # Ensure you're on the updated main branch after the PR merge + git checkout main + git pull origin main + + # Run the release script + ./apps/cli/scripts/release.sh + ``` + + The release script will automatically: + + - Build the extension and CLI + - Create a platform-specific tarball + - Verify the installation works correctly (runs --help, --version, and e2e test) + - Extract changelog content and include it in the GitHub release notes + - Create the GitHub release with the tarball attached + +9. After a successful release, verify: + - Check the release page: https://github.com/RooCodeInc/Roo-Code/releases + - Verify the "What's New" section contains the changelog content + - Test installation: `curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh` + +**Notes:** + +- The release script requires GitHub CLI (`gh`) to be installed and authenticated +- If a release already exists for the tag, the script will prompt to delete and recreate it +- The script creates a tarball for the current platform only (darwin-arm64, darwin-x64, linux-arm64, or linux-x64) +- Multi-platform releases require running the script on each platform and manually uploading additional tarballs diff --git a/.roo/rules-docs-extractor/1_extraction_workflow.xml b/.roo/rules-docs-extractor/1_extraction_workflow.xml index 200e48da0c7..c707fa78092 100644 --- a/.roo/rules-docs-extractor/1_extraction_workflow.xml +++ b/.roo/rules-docs-extractor/1_extraction_workflow.xml @@ -1,113 +1,163 @@ - - Extract raw facts from a codebase about a feature or aspect. - Output is structured data for documentation teams to use. - Do NOT write documentation. Do NOT format prose. Do NOT make structure decisions. - + + The Docs Extractor mode has exactly two workflow paths: + 1) Verify provided documentation for factual accuracy against the codebase + 2) Generate source material for user-facing docs about a requested feature or aspect of the codebase - - - Identify Target - - Parse the user's request to identify the feature/aspect - Clarify scope if ambiguous (ask one question max) - - + Outputs are designed to support explanatory documentation (not merely descriptive): + - Capture why users need steps and why certain actions are restricted + - Surface constraints, limitations, and trade‑offs + - Provide troubleshooting playbooks (symptoms → causes → fixes → prevention) + - Recommend targeted visuals for complex states (not step‑by‑step screenshots) - - Discover Code - - Use codebase_search to find relevant files - Identify entry points, components, and related code - Map the boundaries of the feature - - + This mode does not generate final user documentation; it produces verification and source-material reports for docs teams. + - - Extract Facts + + + Parse Request - Read code and extract facts into categories (see fact_categories) - Record file paths as sources for each fact - Do NOT interpret, summarize, or explain - just extract + Identify the feature/aspect in the user's request. + Decide path: verification vs. source-material generation. + For source-material: capture audience (user or developer) and depth (overview vs task-focused). + For verification: identify the documentation to be verified (provided text/links/files). + Note any specific areas to emphasize or check. - - Output Structured Data + + Discover Feature - Write extraction to .roo/extraction/EXTRACT-[feature].yaml - Use the output schema (see output_format.xml) + Locate relevant code and assets using appropriate discovery methods. + Identify entry points and key components that affect user experience. + Map the high-level workflow a user follows. - - - - - - Feature name as it appears in code - File paths where feature is implemented - Entry points (commands, UI elements, API endpoints) - - - - - - What the feature does (from code logic) - Inputs it accepts - Outputs it produces - Side effects (files created, state changed, etc.) - - - - - - Settings/options that affect behavior - Default values - Valid ranges or allowed values - Where configured (settings file, env var, UI) - - - - - - Prerequisites and dependencies - Limitations (what it cannot do) - Permissions required - Compatibility requirements - - + - - - Error conditions in code - Error messages (exact text) - Recovery paths in code - - + + UI components and their interactions + User workflows and decision points + Configuration that changes user-visible behavior + Error states, messages, and recovery + Benefits, limits, prerequisites, and version notes + Why this exists: user goals, constraints, and design intent + “Cannot do” boundaries: permissions, invariants, and business rules + Troubleshooting: symptoms, likely causes, diagnostics, fixes, prevention + Common pitfalls and anti‑patterns (what to avoid and why) + Decision rationale and trade‑offs that affect user choices + Complex UI states that merit visuals (criteria for screenshots/diagrams) + - - - UI components involved - User-visible labels and text - Interaction patterns - - + + + Generate Source Material for User-Facing Docs + Extract concise, user-oriented facts and structure them for documentation teams. + + + Scope and Audience + + Confirm the feature/aspect and intended audience. + List primary tasks the audience performs with this feature. + + + + Extract User-Facing Facts + + Summarize what the feature does and key benefits. + Explain why users need this (jobs-to-be-done, outcomes) and when to use it. + Document step-by-step user workflows and UI interactions. + Capture configuration options that impact user behavior (name, default, effect). + Clarify constraints, limits, and “cannot do” cases with rationale. + Identify common pitfalls and anti-patterns; include “Do/Don’t” guidance. + List common errors with user-facing messages, diagnostics, fixes, and prevention. + Record prerequisites, permissions, and compatibility/version notes. + Flag complex states that warrant visuals (what to show and why), not every step. + + + + Create Source Material Report + + Organize findings using user-focused structure (benefits, use cases, how it works, configuration, FAQ, troubleshooting). + Include short code/UI snippets or paths where relevant. + Create `EXTRACTION-[feature].md` with findings. + Highlight items that need visuals (screenshots/diagrams). + + + - Executive summary of the feature/aspect + - Why it matters (goals, value, when to use) + - User workflows and interactions + - Configuration and setup affecting users (with defaults and impact) + - Constraints and limitations (with rationale) + - Common scenarios and troubleshooting playbooks (symptoms → causes → fixes → prevention) + - Do/Don’t and anti‑patterns + - Recommended visuals (what complex states to illustrate and why) + - FAQ and tips + - Version/compatibility notes + + + + - - - Other features this interacts with - External APIs or services called - Events emitted or consumed - - - + + Verify Documentation Accuracy + Check provided documentation against codebase reality and actual UX. + + + Analyze Provided Documentation + + Parse the documentation to identify claims and descriptions. + Extract technical or user-facing specifics mentioned. + Note workflows, configuration, and examples described. + + + + Verify Against Codebase + + Check claims against actual implementation and UX. + Verify endpoints/parameters if referenced. + Confirm configuration options and defaults. + Validate code snippets and examples. + Ensure described workflows match implementation. + + + + Create Verification Report + + Categorize findings by severity (Critical, Major, Minor). + List inaccuracies with the correct information. + Identify missing important information. + Provide specific corrections and suggestions. + Create `VERIFICATION-[feature].md` with findings. + + + - Verification summary (Accurate/Needs Updates) + - Critical inaccuracies that could mislead users + - Corrections and missing information + - Explanatory gaps (missing “why”, constraints, or decision rationale) + - Troubleshooting coverage gaps (missing symptoms/diagnostics/fixes/prevention) + - Visual recommendations (which complex states warrant screenshots/diagrams) + - Suggestions for clarity improvements + + + + + - - Extract facts, not opinions - Include source file paths for every fact - Use code identifiers and exact strings from source - Do NOT paraphrase - quote when possible - Do NOT decide what's important - extract everything relevant - Do NOT format for end users - output is for docs team - + + + Audience and scope captured + User workflows and UI interactions documented + User-impacting configuration recorded + Common errors and troubleshooting documented + Report organized for documentation team use + + + All documentation claims verified + Inaccuracies identified and corrected + Missing information noted + Suggestions for improvement provided + Clear verification report created + + \ No newline at end of file diff --git a/.roo/rules-docs-extractor/2_documentation_patterns.xml b/.roo/rules-docs-extractor/2_documentation_patterns.xml new file mode 100644 index 00000000000..da743483dab --- /dev/null +++ b/.roo/rules-docs-extractor/2_documentation_patterns.xml @@ -0,0 +1,357 @@ + + + Standard templates for structuring extracted documentation. + + + + +# [Feature Name] + +[Description of what the feature does and why a user should care.] + +### Key Features +- [Benefit-oriented feature 1] +- [Benefit-oriented feature 2] +- [Benefit-oriented feature 3] + +--- + +## Use Case + +**Before**: [Description of the old way] +- [Pain point 1] +- [Pain point 2] + +**With this feature**: [Description of the new experience.] + +## How it Works + +[Simple explanation of the feature's operation.] + +[Suggest visual representations where helpful.] + +--- + +## Configuration + +[Explanation of relevant settings.] + +1. **[Setting Name]**: + - **Setting**: `[technical_name]` + - **Description**: [What this does.] + - **Default**: [Default value and its meaning.] + +2. **[Setting Name]**: + - **Setting**: `[technical_name]` + - **Description**: [What this does.] + - **Default**: [Default value and its meaning.] + +--- + +## FAQ + +**"[User question]"** +- [Answer.] +- [Optional tip.] + +**"[User question]"** +- [Answer.] +- [Optional tip.] + + + + +# [Feature Name] Technical Documentation + +## Table of Contents +1. Overview +2. Quick Start +3. Architecture +4. API Reference +5. Configuration +6. User Guide +7. Developer Guide +8. Security +9. Performance +10. Troubleshooting +11. FAQ +12. Changelog +13. References + +[Use this as an internal source-material outline for technical sections; not for final docs.] + + + + + + + + + + --- + Separate sections. + + + + + + + + Show tool output or UI elements. + Use actual file paths and setting names. + Include common errors and solutions. + + + + + + + + + + + + + + + Tutorials + Use cases + Troubleshooting + Benefits + + + + + + + Code examples + API specs + Integration patterns + Performance + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Link Text](#section-anchor) + [See Configuration Guide](#configuration) + + + + [Link Text](https://external.url) + [Official Documentation](https://docs.example.com) + + + + + + + + + + + \ No newline at end of file diff --git a/.roo/rules-docs-extractor/2_verification_workflow.xml b/.roo/rules-docs-extractor/2_verification_workflow.xml deleted file mode 100644 index 4635d8eb45b..00000000000 --- a/.roo/rules-docs-extractor/2_verification_workflow.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - Compare provided documentation against actual codebase implementation. - Output is a structured diff of claims vs reality. - Do NOT rewrite the docs. Do NOT suggest wording. Just report discrepancies. - - - - - Receive Documentation - - User provides documentation to verify (text, file, or URL) - Identify the feature/aspect being documented - - - - - Extract Claims - - Parse the documentation into discrete claims - Tag each claim with a category (behavior, config, constraint, etc.) - Record the exact quote from the documentation - - - - - Verify Against Code - - For each claim, find the relevant code - Compare claim to actual implementation - Record: ACCURATE, INACCURATE, OUTDATED, MISSING_CONTEXT, or UNVERIFIABLE - For inaccuracies, record what the code actually does - - - - - Output Verification Report - - Write verification to .roo/extraction/VERIFY-[feature].yaml - Use the output schema (see output_format.xml) - - - - - - - Claim matches implementation - - - Claim contradicts implementation - What the code actually does - - - Claim was once true but code has changed - Current behavior - - - Claim is true but omits important information - The missing context - - - Cannot find code to verify this claim - Search paths attempted - - - - - behavior - configuration - constraint - error_handling - ui - integration - prerequisite - - - - Verify facts, not writing quality - Report what code does, not what docs should say - Include source file paths as evidence - Do NOT suggest documentation rewrites - Do NOT evaluate if docs are "good" - only if they're accurate - Quote exact code when showing discrepancies - - \ No newline at end of file diff --git a/.roo/rules-docs-extractor/3_analysis_techniques.xml b/.roo/rules-docs-extractor/3_analysis_techniques.xml new file mode 100644 index 00000000000..12b3d1fd266 --- /dev/null +++ b/.roo/rules-docs-extractor/3_analysis_techniques.xml @@ -0,0 +1,349 @@ + + + Heuristics for analyzing a codebase to extract reliable, user-facing documentation. + This file contains technique checklists only—no tool instructions or invocations. + + + + + Find and analyze UI components and their interactions + + Start from feature or route directories and enumerate components related to the requested topic. + Differentiate container vs presentational components; note composition patterns. + Trace inputs/outputs: props, state, context, events, and side effects. + Record conditional rendering that affects user-visible states. + + + Primary components and responsibilities. + Props/state/context that change behavior. + High-level dependency/composition map. + + + + + Analyze styling and visual elements + + Identify design tokens and utility classes used to drive layout and state. + Capture responsive behavior and breakpoint rules that materially change UX. + Document visual affordances tied to state (loading, error, disabled). + + + Key classes/selectors influencing layout/state. + Responsive behavior summary and breakpoints. + + + + + Map user interactions and navigation flows + + Route definitions and navigation + Form submissions and validations + Button clicks and event handlers + State changes and UI updates + Loading and error states + + + Outline entry points and expected outcomes for each primary flow. + Summarize validation rules and failure states the user can encounter. + Record redirects and deep-link behavior relevant to the feature. + + + Flow diagrams or bullet sequences for main tasks. + Validation conditions and error messages. + Navigation transitions and guards. + + + + + Analyze how the system communicates with users + + Error messages and alerts + Success notifications + Loading indicators + Tooltips and help text + Confirmation dialogs + Progress indicators + + + Map message triggers to the user actions that cause them. + Capture severity, persistence, and dismissal behavior. + Note localization or accessibility considerations in messages. + + + Catalog of messages with purpose and conditions. + Loading/progress patterns and timeouts. + + + + + Check for accessibility features and compliance + + ARIA labels and roles + Keyboard navigation support + Screen reader compatibility + Focus management + Color contrast considerations + + + Confirm interactive elements have clear focus and labels. + Describe keyboard-only navigation paths for core flows. + + + Accessibility gaps affecting task completion. + + + + + Analyze responsive design and mobile experience + + Breakpoint definitions + Mobile-specific components + Touch event handlers + Viewport configurations + Media queries + + + Summarize layout changes across breakpoints that alter workflow. + Note touch targets and gestures required on mobile. + + + Table of key differences per breakpoint. + + + + + + + Understand feature entry points and control flow + + Identify main functions, controllers, or route handlers. + Trace execution and decision branches. + Document input validation and preconditions. + + + Entry points list and short purpose statements. + Decision matrix or flow sketch. + + + + + Extract API specifications from code + + + + HTTP method and route path + Path/query parameters + Request/response schemas + Status codes and error bodies + + + + + Schema and input types + Resolvers and return types + Field arguments and constraints + + + + + + + Map dependencies and integration points + + Imports and module boundaries + Package and runtime dependencies + External API/SDK usage + DB connections and migrations + Messaging/queue/event streams + Filesystem or network side effects + + + Dependency graph summary and hot spots. + List of external integrations and auth methods. + + + + + Extract data models, schemas, and type definitions + + + - interfaces, types, classes, enums + + + - Schema definitions, migration files, ORM models + + + - JSON Schema, Joi/Yup/Zod schemas, validation decorators + + + + Canonical definitions and field constraints. + Entity relationships and ownership. + + + + + Identify and document business rules + + Complex conditionals + Calculation functions + Validation rules + State machines + Domain-specific constants and algorithms + + + Why the logic exists (business need) + When the logic applies (conditions) + What the logic does (transformation) + Edge cases and invariants + Impact of changes + + + + + Document error handling and recovery + + try/catch blocks and error boundaries + Custom error classes and codes + Logging, fallbacks, retries, circuit breakers + + + Error taxonomy and user-facing messages. + Recovery/rollback strategies and timeouts. + + + + + Identify security measures and vulnerabilities + + JWT, sessions, OAuth, API keys + RBAC, permission checks, ownership validation + Encryption, hashing, sensitive data handling + Sanitization and injection prevention + + + Threat surfaces and mitigations relevant to the feature. + + + + + Identify performance factors and optimization opportunities + + Expensive loops/algorithms + DB query patterns (e.g., N+1) + Caching strategies + Concurrency and async usage + Batching and resource pooling + Memory management and object lifetimes + + + Time/space complexity + DB query counts + API response times + Memory usage + Concurrency handling + + + + + Assess test coverage at a useful granularity + + + Function-level coverage and edge cases + + + Workflow coverage and contract boundaries + + + Endpoint success/failure paths and schemas + + + + List of critical behaviors missing tests. + + + + + Extract configuration options and their impacts + + .env files, config files, CLI args, feature flags + + + Default values and valid ranges + Behavioral impact of each option + Dependencies between options + Security implications + + + + + + + Map user workflows through the feature + + Identify entry points (UI, API, CLI) + Trace user actions and decision points + Map data transformations + Identify outcomes and completion criteria + + + Flow diagrams, procedures, decision trees, state diagrams + + + + + Document integration with other systems + + Sync API calls, async messaging, events, batch processing, streaming + + + Protocols, auth, error handling, data transforms, SLAs + + + + + + + Summarize version constraints and compatibility + + package manifests, READMEs, migration guides, breaking changes docs + + + Minimum/recommended versions and notable constraints. + + + + + Track deprecations and migrations + + Explicit deprecation notices and TODO markers + Legacy code paths and adapters + + + Deprecation date and removal timeline + Migration path and alternatives + + + + + + + + Public APIs documented with inputs/outputs and errors + Examples for complex features + Error scenarios covered with recovery guidance + Config options explained with defaults and impacts + Security considerations addressed + + + + + Cyclomatic complexity + Code duplication + Test coverage and gaps + Documentation coverage for user-visible behaviors + Known technical debt affecting UX + + + + \ No newline at end of file diff --git a/.roo/rules-docs-extractor/3_output_format.xml b/.roo/rules-docs-extractor/3_output_format.xml deleted file mode 100644 index 185f7b23b80..00000000000 --- a/.roo/rules-docs-extractor/3_output_format.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - Structured data output formats for extraction and verification. - All output is YAML. No prose. No markdown formatting. - This data feeds into documentation-writer mode. - - - - Schema for EXTRACT-[feature].yaml files - - - - - Schema for VERIFY-[feature].yaml files - - - - - Use YAML, not JSON or markdown - Include source file:line for every fact - Quote exact strings from code using double quotes - Use null for unknown/missing values, not empty strings - Keep descriptions factual and brief - one line max - Do NOT add commentary, suggestions, or explanations - - - - EXTRACT-[feature-slug].yaml - VERIFY-[feature-slug].yaml - .roo/extraction/ - - \ No newline at end of file diff --git a/.roo/rules-docs-extractor/4_communication_guidelines.xml b/.roo/rules-docs-extractor/4_communication_guidelines.xml new file mode 100644 index 00000000000..43ec8479fc6 --- /dev/null +++ b/.roo/rules-docs-extractor/4_communication_guidelines.xml @@ -0,0 +1,298 @@ + + + Guidelines for user communication and output formatting. + + + + + Act on the user's request immediately. + Only ask for clarification if the request is ambiguous. + + + + + Multiple features with similar names are found. + The request is ambiguous. + The user explicitly asks for options. + + + + + + + Starting a major analysis phase. + Extraction is complete. + Unexpected complexity is found. + + + + + + + + + + + Alert user to security concerns found during analysis. + + + Note deprecated features needing migration docs. + + + Highlight code that lacks inline documentation. + + + Warn about complex dependency chains. + + + + + + + + + + + + + + + Use # for main title, ## for major sections, ### for subsections. + Never skip heading levels. + + + + Always specify language for syntax highlighting (e.g., typescript, json, bash). + Include file paths as comments where relevant. + +```typescript +// src/auth/auth.service.ts +export class AuthService { + async validateUser(email: string, password: string): Promise { + // Implementation + } +} +``` + + + + + Use tables for structured data like configs. + Include headers and align columns. + Keep cell content brief. + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `JWT_SECRET` | string | - | Secret key for JWT signing | +| `JWT_EXPIRATION` | string | '15m' | Token expiration time | + + + + + Use bullets for unordered lists, numbers for sequential steps. + Keep list items parallel in structure. + + + + + + [Link text](#section-anchor) + Use lowercase, hyphenated anchors. Test all links. + + + + [Link text](https://example.com) + Use HTTPS. Link to official docs. + + + + `path/to/file.ts` + Use relative paths from project root, in backticks. + + + + + + + > ⚠️ **Warning**: [message] + Security, breaking changes, deprecations. + + + > 📝 **Note**: [message] + Important info, clarifications. + + + > 💡 **Tip**: [message] + Best practices, optimizations. + + + + + +--- +Feature: Authentication System +Version: 2.1.0 +Last Updated: 2024-01-15 +Status: Stable +--- + + + + + + + + Be direct, not conversational. + Use active voice. + Lead with benefits. + Use concrete examples. + Keep paragraphs short. + Avoid unnecessary technical details. + + + + + Technical and direct. + Standard programming terms. + Code snippets, implementation details. + + + Instructional, step-by-step. + Simple language, no jargon. + Screenshots, real-world scenarios. + + + + + + + Summary of analysis performed. + Key findings or issues identified. + Report file location. + Recommended next steps. + + + +Feature extraction complete for the authentication system. + +**Extraction Report**: `EXTRACTION-authentication-system.md` + +**Technical Summary**: +- JWT-based authentication with refresh tokens +- 5 API endpoints (login, logout, refresh, register, profile) +- 12 configuration options +- bcrypt password hashing, rate limiting + +**Non-Technical Summary**: +- Users can register, login, and manage sessions +- Supports "remember me" functionality +- Automatic session refresh for seamless experience +- Account lockout after failed attempts + +**Documentation Considerations**: +- Token expiration times need clear explanation +- Password requirements should be prominently displayed +- Error messages need user-friendly translations + +The extraction report contains all details needed for comprehensive documentation. + + + +Documentation verification complete for the authentication system. + +**Verification Report**: `VERIFICATION-authentication-system.md` + +**Overall Assessment**: Needs Updates + +**Critical Issues Found**: +1. JWT_SECRET documented as optional, but it's required +2. Token expiration listed as 30m, actual is 15m +3. Missing documentation for rate limiting feature + +**Technical Corrections**: 7 items +**Missing Information**: 4 sections +**Clarity Improvements**: 3 suggestions + +Please review the verification report for specific corrections needed. + + + + + + + + Could not find a feature matching "[feature name]". Similar features found: + - [List similar features] + Document one of these instead? + + + + + + Code for [feature] has limited inline documentation. Extracting from code structure, tests, and usage patterns. + + + + + + This feature is complex. Choose documentation scope: + - Document comprehensively + - Focus on core functionality + - Split into multiple documents + + + + + + + + No placeholder content remains. + Code examples are correct. + Links and cross-references work. + Tables are formatted correctly. + Version info is included. + Filename follows conventions. + + + \ No newline at end of file diff --git a/.roo/rules-integration-tester/1_workflow.xml b/.roo/rules-integration-tester/1_workflow.xml new file mode 100644 index 00000000000..b0ebc535e2b --- /dev/null +++ b/.roo/rules-integration-tester/1_workflow.xml @@ -0,0 +1,198 @@ + + + Understand Test Requirements + + Use ask_followup_question to determine what type of integration test is needed: + + + What type of integration test would you like me to create or work on? + + New E2E test for a specific feature or workflow + Fix or update an existing integration test + Create test utilities or helpers for common patterns + Debug failing integration tests + + + + + + + Gather Test Specifications + + Based on the test type, gather detailed requirements: + + For New E2E Tests: + - What specific user workflow or feature needs testing? + - What are the expected inputs and outputs? + - What edge cases or error scenarios should be covered? + - Are there specific API interactions to validate? + - What events should be monitored during the test? + + For Existing Test Issues: + - Which test file is failing or needs updates? + - What specific error messages or failures are occurring? + - What changes in the codebase might have affected the test? + + For Test Utilities: + - What common patterns are being repeated across tests? + - What helper functions would improve test maintainability? + + Use multiple ask_followup_question calls if needed to gather complete information. + + + + + Explore Existing Test Patterns + + Use codebase_search FIRST to understand existing test patterns and similar functionality: + + For New Tests: + - Search for similar test scenarios in apps/vscode-e2e/src/suite/ + - Find existing test utilities and helpers + - Identify patterns for the type of functionality being tested + + For Test Fixes: + - Search for the failing test file and related code + - Find similar working tests for comparison + - Look for recent changes that might have broken the test + + Example searches: + - "file creation test mocha" for file operation tests + - "task completion waitUntilCompleted" for task monitoring patterns + - "api message validation" for API interaction tests + + After codebase_search, use: + - read_file on relevant test files to understand structure + - list_code_definition_names on test directories + - search_files for specific test patterns or utilities + + + + + Analyze Test Environment and Setup + + Examine the test environment configuration: + + 1. Read the test runner configuration: + - apps/vscode-e2e/package.json for test scripts + - apps/vscode-e2e/src/runTest.ts for test setup + - Any test configuration files + + 2. Understand the test workspace setup: + - How test workspaces are created + - What files are available during tests + - How the extension API is accessed + + 3. Review existing test utilities: + - Helper functions for common operations + - Event listening patterns + - Assertion utilities + - Cleanup procedures + + Document findings including: + - Test environment structure + - Available utilities and helpers + - Common patterns and best practices + + + + + Design Test Structure + + Plan the test implementation based on gathered information: + + For New Tests: + - Define test suite structure with suite/test blocks + - Plan setup and teardown procedures + - Identify required test data and fixtures + - Design event listeners and validation points + - Plan for both success and failure scenarios + + For Test Fixes: + - Identify the root cause of the failure + - Plan the minimal changes needed to fix the issue + - Consider if the test needs to be updated due to code changes + - Plan for improved error handling or debugging + + Create a detailed test plan including: + - Test file structure and organization + - Required setup and cleanup + - Specific assertions and validations + - Error handling and edge cases + + + + + Implement Test Code + + Implement the test following established patterns: + + CRITICAL: Never write a test file with a single write_to_file call. + Always implement tests in parts: + + 1. Start with the basic test structure (suite, setup, teardown) + 2. Add individual test cases one by one + 3. Implement helper functions separately + 4. Add event listeners and validation logic incrementally + + Follow these implementation guidelines: + - Use suite() and test() blocks following Mocha TDD style + - Always use the global api object for extension interactions + - Implement proper async/await patterns with waitFor utility + - Use waitUntilCompleted and waitUntilAborted helpers for task monitoring + - Listen to and validate appropriate events (message, taskCompleted, etc.) + - Test both positive flows and error scenarios + - Validate message content using proper type assertions + - Create reusable test utilities when patterns emerge + - Use meaningful test descriptions that explain the scenario + - Always clean up tasks with cancelCurrentTask or clearCurrentTask + - Ensure tests are independent and can run in any order + + + + + Run and Validate Tests + + Execute the tests to ensure they work correctly: + + ALWAYS use the correct working directory and commands: + - Working directory: apps/vscode-e2e + - Test command: npm run test:run + - For specific tests: TEST_FILE="filename.test" npm run test:run + - Example: cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run + + Test execution process: + 1. Run the specific test file first + 2. Check for any failures or errors + 3. Analyze test output and logs + 4. Debug any issues found + 5. Re-run tests after fixes + + If tests fail: + - Add console.log statements to track execution flow + - Log important events like task IDs, file paths, and AI responses + - Check test output carefully for error messages and stack traces + - Verify file creation in correct workspace directories + - Ensure proper event handling and timeouts + + + + + Document and Complete + + Finalize the test implementation: + + 1. Add comprehensive comments explaining complex test logic + 2. Document any new test utilities or patterns created + 3. Ensure test descriptions clearly explain what is being tested + 4. Verify all cleanup procedures are in place + 5. Confirm tests can run independently and in any order + + Provide the user with: + - Summary of tests created or fixed + - Instructions for running the tests + - Any new patterns or utilities that can be reused + - Recommendations for future test improvements + + + \ No newline at end of file diff --git a/.roo/rules-integration-tester/2_test_patterns.xml b/.roo/rules-integration-tester/2_test_patterns.xml new file mode 100644 index 00000000000..62bef1631bb --- /dev/null +++ b/.roo/rules-integration-tester/2_test_patterns.xml @@ -0,0 +1,303 @@ + + + Standard Mocha TDD structure for integration tests + + Basic Test Suite Structure + + ```typescript + import { suite, test, suiteSetup, suiteTeardown } from 'mocha'; + import * as assert from 'assert'; + import * as vscode from 'vscode'; + import { waitFor, waitUntilCompleted, waitUntilAborted } from '../utils/testUtils'; + + suite('Feature Name Tests', () => { + let testWorkspaceDir: string; + let testFiles: { [key: string]: string } = {}; + + suiteSetup(async () => { + // Setup test workspace and files + testWorkspaceDir = vscode.workspace.workspaceFolders![0].uri.fsPath; + // Create test files in workspace + }); + + suiteTeardown(async () => { + // Cleanup test files and tasks + await api.cancelCurrentTask(); + }); + + test('should perform specific functionality', async () => { + // Test implementation + }); + }); + ``` + + + + + Event Listening Pattern + + ```typescript + test('should handle task completion events', async () => { + const events: any[] = []; + + const messageListener = (message: any) => { + events.push({ type: 'message', data: message }); + }; + + const taskCompletedListener = (result: any) => { + events.push({ type: 'taskCompleted', data: result }); + }; + + api.onDidReceiveMessage(messageListener); + api.onTaskCompleted(taskCompletedListener); + + try { + // Perform test actions + await api.startTask('test prompt'); + await waitUntilCompleted(); + + // Validate events + assert(events.some(e => e.type === 'taskCompleted')); + } finally { + // Cleanup listeners + api.onDidReceiveMessage(() => {}); + api.onTaskCompleted(() => {}); + } + }); + ``` + + + + + File Creation Test Pattern + + ```typescript + test('should create files in workspace', async () => { + const fileName = 'test-file.txt'; + const expectedContent = 'test content'; + + await api.startTask(`Create a file named ${fileName} with content: ${expectedContent}`); + await waitUntilCompleted(); + + // Check multiple possible locations + const possiblePaths = [ + path.join(testWorkspaceDir, fileName), + path.join(process.cwd(), fileName), + // Add other possible locations + ]; + + let fileFound = false; + let actualContent = ''; + + for (const filePath of possiblePaths) { + if (fs.existsSync(filePath)) { + actualContent = fs.readFileSync(filePath, 'utf8'); + fileFound = true; + break; + } + } + + assert(fileFound, `File ${fileName} not found in any expected location`); + assert.strictEqual(actualContent.trim(), expectedContent); + }); + ``` + + + + + + + Basic Task Execution + + ```typescript + // Start a task and wait for completion + await api.startTask('Your prompt here'); + await waitUntilCompleted(); + ``` + + + + + Task with Auto-Approval Settings + + ```typescript + // Enable auto-approval for specific actions + await api.updateSettings({ + alwaysAllowWrite: true, + alwaysAllowExecute: true + }); + + await api.startTask('Create and execute a script'); + await waitUntilCompleted(); + ``` + + + + + Message Validation + + ```typescript + const messages: any[] = []; + api.onDidReceiveMessage((message) => { + messages.push(message); + }); + + await api.startTask('test prompt'); + await waitUntilCompleted(); + + // Validate specific message types + const toolMessages = messages.filter(m => + m.type === 'say' && m.say === 'api_req_started' + ); + assert(toolMessages.length > 0, 'Expected tool execution messages'); + ``` + + + + + + + Task Abortion Handling + + ```typescript + test('should handle task abortion', async () => { + await api.startTask('long running task'); + + // Abort after short delay + setTimeout(() => api.abortTask(), 1000); + + await waitUntilAborted(); + + // Verify task was properly aborted + const status = await api.getTaskStatus(); + assert.strictEqual(status, 'aborted'); + }); + ``` + + + + + Error Message Validation + + ```typescript + test('should handle invalid input gracefully', async () => { + const errorMessages: any[] = []; + + api.onDidReceiveMessage((message) => { + if (message.type === 'error' || message.text?.includes('error')) { + errorMessages.push(message); + } + }); + + await api.startTask('invalid prompt that should fail'); + await waitFor(() => errorMessages.length > 0, 5000); + + assert(errorMessages.length > 0, 'Expected error messages'); + }); + ``` + + + + + + + File Location Helper + + ```typescript + function findFileInWorkspace(fileName: string, workspaceDir: string): string | null { + const possiblePaths = [ + path.join(workspaceDir, fileName), + path.join(process.cwd(), fileName), + path.join(os.tmpdir(), fileName), + // Add other common locations + ]; + + for (const filePath of possiblePaths) { + if (fs.existsSync(filePath)) { + return filePath; + } + } + + return null; + } + ``` + + + + + Event Collection Helper + + ```typescript + class EventCollector { + private events: any[] = []; + + constructor(private api: any) { + this.setupListeners(); + } + + private setupListeners() { + this.api.onDidReceiveMessage((message: any) => { + this.events.push({ type: 'message', timestamp: Date.now(), data: message }); + }); + + this.api.onTaskCompleted((result: any) => { + this.events.push({ type: 'taskCompleted', timestamp: Date.now(), data: result }); + }); + } + + getEvents(type?: string) { + return type ? this.events.filter(e => e.type === type) : this.events; + } + + clear() { + this.events = []; + } + } + ``` + + + + + + + Comprehensive Logging + + ```typescript + test('should log execution flow for debugging', async () => { + console.log('Starting test execution'); + + const events: any[] = []; + api.onDidReceiveMessage((message) => { + console.log('Received message:', JSON.stringify(message, null, 2)); + events.push(message); + }); + + console.log('Starting task with prompt'); + await api.startTask('test prompt'); + + console.log('Waiting for task completion'); + await waitUntilCompleted(); + + console.log('Task completed, events received:', events.length); + console.log('Final workspace state:', fs.readdirSync(testWorkspaceDir)); + }); + ``` + + + + + State Validation + + ```typescript + function validateTestState(description: string) { + console.log(`=== ${description} ===`); + console.log('Workspace files:', fs.readdirSync(testWorkspaceDir)); + console.log('Current working directory:', process.cwd()); + console.log('Task status:', api.getTaskStatus?.() || 'unknown'); + console.log('========================'); + } + ``` + + + + \ No newline at end of file diff --git a/.roo/rules-integration-tester/3_best_practices.xml b/.roo/rules-integration-tester/3_best_practices.xml new file mode 100644 index 00000000000..e495ea5f0ae --- /dev/null +++ b/.roo/rules-integration-tester/3_best_practices.xml @@ -0,0 +1,104 @@ + + + - Always use suite() and test() blocks following Mocha TDD style + - Use descriptive test names that explain the scenario being tested + - Implement proper setup and teardown in suiteSetup() and suiteTeardown() + - Create test files in the VSCode workspace directory during suiteSetup() + - Store file paths in a test-scoped object for easy reference across tests + - Ensure tests are independent and can run in any order + - Clean up all test files and tasks in suiteTeardown() to avoid test pollution + + + + - Always use the global api object for extension interactions + - Implement proper async/await patterns with the waitFor utility + - Use waitUntilCompleted and waitUntilAborted helpers for task monitoring + - Set appropriate auto-approval settings (alwaysAllowWrite, alwaysAllowExecute) for the functionality being tested + - Listen to and validate appropriate events (message, taskCompleted, taskAborted, etc.) + - Always clean up tasks with cancelCurrentTask or clearCurrentTask after tests + - Use meaningful timeouts that account for actual task execution time + + + + - Be aware that files may be created in the workspace directory (/tmp/roo-test-workspace-*) rather than expected locations + - Always check multiple possible file locations when verifying file creation + - Use flexible file location checking that searches workspace directories + - Verify files exist after creation to catch setup issues early + - Account for the fact that the workspace directory is created by runTest.ts + - The AI may use internal tools instead of the documented tools - verify outcomes rather than methods + + + + - Add multiple event listeners (taskStarted, taskCompleted, taskAborted) for better debugging + - Don't rely on parsing AI messages to detect tool usage - the AI's message format may vary + - Use terminal shell execution events (onDidStartTerminalShellExecution, onDidEndTerminalShellExecution) for command tracking + - Tool executions are reported via api_req_started messages with type="say" and say="api_req_started" + - Focus on testing outcomes (files created, commands executed) rather than message parsing + - There is no "tool_result" message type - tool results appear in "completion_result" or "text" messages + + + + - Test both positive flows and error scenarios + - Validate message content using proper type assertions + - Implement proper error handling and edge cases + - Use try-catch blocks around critical test operations + - Log important events like task IDs, file paths, and AI responses for debugging + - Check test output carefully for error messages and stack traces + + + + - Remove unnecessary waits for specific tool executions - wait for task completion instead + - Simplify message handlers to only capture essential error information + - Use the simplest possible test structure that verifies the outcome + - Avoid complex message parsing logic that depends on AI behavior + - Terminal events are more reliable than message parsing for command execution verification + - Keep prompts simple and direct - complex instructions may confuse the AI + + + + - Add console.log statements to track test execution flow + - Log important events like task IDs, file paths, and AI responses + - Use codebase_search first to find similar test patterns before writing new tests + - Create helper functions for common file location checks + - Use descriptive variable names for file paths and content + - Always log the expected vs actual locations when tests fail + - Add comprehensive comments explaining complex test logic + + + + - Create reusable test utilities when patterns emerge + - Implement helper functions for common operations like file finding + - Use event collection utilities for consistent event handling + - Create assertion helpers for common validation patterns + - Document any new test utilities or patterns created + - Share common utilities across test files to reduce duplication + + + + - Keep prompts simple and direct - complex instructions may lead to unexpected behavior + - Allow for variations in how the AI accomplishes tasks + - The AI may not always use the exact tool you specify in the prompt + - Be prepared to adapt tests based on actual AI behavior rather than expected behavior + - The AI may interpret instructions creatively - test results rather than implementation details + - The AI will not see the files in the workspace directory, you must tell it to assume they exist and proceed + + + + - ALWAYS use the correct working directory: apps/vscode-e2e + - The test command is: npm run test:run + - To run specific tests use environment variable: TEST_FILE="filename.test" npm run test:run + - Example: cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run + - Never use npm test directly as it doesn't exist + - Always check available scripts with npm run if unsure + - Run tests incrementally during development to catch issues early + + + + - Never write a test file with a single write_to_file tool call + - Always implement tests in parts: structure first, then individual test cases + - Group related tests in the same suite + - Use consistent naming conventions for test files and functions + - Separate test utilities into their own files when they become substantial + - Follow the existing project structure and conventions + + \ No newline at end of file diff --git a/.roo/rules-integration-tester/4_common_mistakes.xml b/.roo/rules-integration-tester/4_common_mistakes.xml new file mode 100644 index 00000000000..88a74736432 --- /dev/null +++ b/.roo/rules-integration-tester/4_common_mistakes.xml @@ -0,0 +1,109 @@ + + + - Writing a test file with a single write_to_file tool call instead of implementing in parts + - Not using proper Mocha TDD structure with suite() and test() blocks + - Forgetting to implement suiteSetup() and suiteTeardown() for proper cleanup + - Creating tests that depend on each other or specific execution order + - Not cleaning up tasks and files after test completion + - Using describe/it blocks instead of the required suite/test blocks + + + + - Not using the global api object for extension interactions + - Forgetting to set auto-approval settings (alwaysAllowWrite, alwaysAllowExecute) when testing functionality that requires user approval + - Not implementing proper async/await patterns with waitFor utilities + - Using incorrect timeout values that are too short for actual task execution + - Not properly cleaning up tasks with cancelCurrentTask or clearCurrentTask + - Assuming the AI will use specific tools instead of testing outcomes + + + + - Assuming files will be created in the expected location without checking multiple paths + - Not accounting for the workspace directory being created by runTest.ts + - Creating test files in temporary directories instead of the VSCode workspace directory + - Not verifying files exist after creation during setup + - Forgetting that the AI may not see files in the workspace directory + - Not using flexible file location checking that searches workspace directories + + + + - Relying on parsing AI messages to detect tool usage instead of using proper event listeners + - Expecting tool results in "tool_result" message type (which doesn't exist) + - Not listening to terminal shell execution events for command tracking + - Depending on specific message formats that may vary + - Not implementing proper event cleanup after tests + - Parsing complex AI conversation messages instead of focusing on outcomes + + + + - Using npm test instead of npm run test:run + - Not using the correct working directory (apps/vscode-e2e) + - Running tests from the wrong directory + - Not checking available scripts with npm run when unsure + - Forgetting to use TEST_FILE environment variable for specific tests + - Not running tests incrementally during development + + + + - Not adding sufficient logging to track test execution flow + - Not logging important events like task IDs, file paths, and AI responses + - Not using codebase_search to find similar test patterns before writing new tests + - Not checking test output carefully for error messages and stack traces + - Not validating test state at critical points + - Assuming test failures are due to code issues without checking test logic + + + + - Using complex instructions that may confuse the AI + - Expecting the AI to use exact tools specified in prompts + - Not allowing for variations in how the AI accomplishes tasks + - Testing implementation details instead of outcomes + - Not adapting tests based on actual AI behavior + - Forgetting to tell the AI to assume files exist in the workspace directory + + + + - Adding unnecessary waits for specific tool executions + - Using complex message parsing logic that depends on AI behavior + - Not using the simplest possible test structure + - Depending on specific AI message formats + - Not using terminal events for reliable command execution verification + - Making tests too brittle by depending on exact AI responses + + + + - Not understanding that files may be created in /tmp/roo-test-workspace-* directories + - Assuming the AI can see files in the workspace directory + - Not checking multiple possible file locations when verifying creation + - Creating files outside the VSCode workspace during tests + - Not properly setting up the test workspace in suiteSetup() + - Forgetting to clean up workspace files in suiteTeardown() + + + + - Expecting specific message types for tool execution results + - Not understanding that ClineMessage types have specific values + - Trying to parse tool execution from AI conversation messages + - Not checking packages/types/src/message.ts for valid message types + - Depending on message parsing instead of outcome verification + - Not using api_req_started messages to verify tool execution + + + + - Using timeouts that are too short for actual task execution + - Not accounting for AI processing time in test timeouts + - Waiting for specific tool executions instead of task completion + - Not implementing proper retry logic for flaky operations + - Using fixed delays instead of condition-based waiting + - Not considering that some operations may take longer in CI environments + + + + - Not creating test files in the correct workspace directory + - Using hardcoded paths that don't work across different environments + - Not storing file paths in test-scoped objects for easy reference + - Creating test data that conflicts with other tests + - Not cleaning up test data properly after tests complete + - Using test data that's too complex for the AI to handle reliably + + \ No newline at end of file diff --git a/.roo/rules-integration-tester/5_test_environment.xml b/.roo/rules-integration-tester/5_test_environment.xml new file mode 100644 index 00000000000..8e872b1dfc4 --- /dev/null +++ b/.roo/rules-integration-tester/5_test_environment.xml @@ -0,0 +1,209 @@ + + + VSCode E2E testing framework using Mocha and VSCode Test + + - Mocha TDD framework for test structure + - VSCode Test framework for extension testing + - Custom test utilities and helpers + - Event-driven testing patterns + - Workspace-based test execution + + + + + apps/vscode-e2e/src/suite/ + apps/vscode-e2e/src/utils/ + apps/vscode-e2e/src/runTest.ts + apps/vscode-e2e/package.json + packages/types/ + + + + apps/vscode-e2e + + npm run test:run + TEST_FILE="filename.test" npm run test:run + cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run + npm run + + + - Never use npm test directly as it doesn't exist + - Always use the correct working directory + - Use TEST_FILE environment variable for specific tests + - Check available scripts with npm run if unsure + + + + + Global api object for extension interactions + + + - api.startTask(prompt: string): Start a new task + - api.cancelCurrentTask(): Cancel the current task + - api.clearCurrentTask(): Clear the current task + - api.abortTask(): Abort the current task + - api.getTaskStatus(): Get current task status + + + - api.onDidReceiveMessage(callback): Listen to messages + - api.onTaskCompleted(callback): Listen to task completion + - api.onTaskAborted(callback): Listen to task abortion + - api.onTaskStarted(callback): Listen to task start + - api.onDidStartTerminalShellExecution(callback): Terminal start events + - api.onDidEndTerminalShellExecution(callback): Terminal end events + + + - api.updateSettings(settings): Update extension settings + - api.getSettings(): Get current settings + + + + + + + + Wait for a condition to be true + await waitFor(() => condition, timeout) + await waitFor(() => fs.existsSync(filePath), 5000) + + + Wait until current task is completed + await waitUntilCompleted() + Default timeout for task completion + + + Wait until current task is aborted + await waitUntilAborted() + Default timeout for task abortion + + + + + + Helper to find files in multiple possible locations + Use when files might be created in different workspace directories + + + Utility to collect and analyze events during test execution + Use for comprehensive event tracking and validation + + + Custom assertion functions for common test patterns + Use for consistent validation across tests + + + + + + + Test workspaces are created by runTest.ts + /tmp/roo-test-workspace-* + vscode.workspace.workspaceFolders![0].uri.fsPath + + + + Create all test files in suiteSetup() before any tests run + Always create files in the VSCode workspace directory + Verify files exist after creation to catch setup issues early + Clean up all test files in suiteTeardown() to avoid test pollution + Store file paths in a test-scoped object for easy reference + + + + The AI will not see the files in the workspace directory + Tell the AI to assume files exist and proceed as if they do + Always verify outcomes rather than relying on AI file visibility + + + + + Understanding message types for proper event handling + Check packages/types/src/message.ts for valid message types + + + + say + api_req_started + Indicates tool execution started + JSON with tool name and execution details + Most reliable way to verify tool execution + + + + Contains tool execution results + Tool results appear here, not in "tool_result" type + + + + General AI conversation messages + Format may vary, don't rely on parsing these for tool detection + + + + + + Settings to enable automatic approval of AI actions + + Enable for file creation/modification tests + Enable for command execution tests + Enable for browser-related tests + + + ```typescript + await api.updateSettings({ + alwaysAllowWrite: true, + alwaysAllowExecute: true + }); + ``` + + Without proper auto-approval settings, the AI won't be able to perform actions without user approval + + + + + Use console.log for tracking test execution flow + + - Log test phase transitions + - Log important events and data + - Log file paths and workspace state + - Log expected vs actual outcomes + + + + + Helper functions to validate test state at critical points + + - Workspace file listing + - Current working directory + - Task status + - Event counts + + + + + Tools for analyzing test failures + + - Stack trace analysis + - Event timeline reconstruction + - File system state comparison + - Message flow analysis + + + + + + + Appropriate timeout values for different operations + Use generous timeouts for task completion (30+ seconds) + Shorter timeouts for file system operations (5-10 seconds) + Medium timeouts for event waiting (10-15 seconds) + + + + Proper cleanup to avoid resource leaks + Always clean up event listeners after tests + Cancel or clear tasks in teardown + Remove test files to avoid disk space issues + + + \ No newline at end of file diff --git a/.roo/rules-issue-investigator/1_workflow.xml b/.roo/rules-issue-investigator/1_workflow.xml index 4d2528e7753..561b2751202 100644 --- a/.roo/rules-issue-investigator/1_workflow.xml +++ b/.roo/rules-issue-investigator/1_workflow.xml @@ -70,7 +70,7 @@ Draft Comment - Draft a comment for the GitHub issue that explains your findings and suggested solution in a conversational, human-like tone. Start the comment with "Hey @roomote-agent,". + Draft a comment for the GitHub issue that explains your findings and suggested solution in a conversational, human-like tone. diff --git a/.roo/rules-issue-investigator/2_best_practices.xml b/.roo/rules-issue-investigator/2_best_practices.xml index 1445822ccdd..31ad2c22678 100644 --- a/.roo/rules-issue-investigator/2_best_practices.xml +++ b/.roo/rules-issue-investigator/2_best_practices.xml @@ -52,7 +52,6 @@ Does the draft comment sound conversational and human? - Does the draft comment start with "Hey @roomote-agent,"? Have I avoided technical jargon where possible? Is the tone helpful and not condescending? diff --git a/.roo/rules-issue-investigator/4_tool_usage.xml b/.roo/rules-issue-investigator/4_tool_usage.xml index f34f57f5ffd..c43c41a8c36 100644 --- a/.roo/rules-issue-investigator/4_tool_usage.xml +++ b/.roo/rules-issue-investigator/4_tool_usage.xml @@ -23,16 +23,10 @@ Use `gh issue view [URL] --json title,body,labels,comments` to fetch initial details. Use `gh issue comment [URL] --body "..."` to add comments, but only after explicit user approval. Always wrap the comment body in quotes to handle special characters. - When posting a comment, the body must start with "Hey @roomote-agent," exactly. gh issue view https://github.com/RooCodeInc/Roo-Code/issues/123 --json title,body - - ]]> - -gh issue comment https://github.com/RooCodeInc/Roo-Code/issues/123 --body "Hey @roomote-agent, I've investigated and proposed a theoretical fix above." ]]> diff --git a/.roo/rules-issue-investigator/5_examples.xml b/.roo/rules-issue-investigator/5_examples.xml index af417e3e69d..dbd4ae2f23c 100644 --- a/.roo/rules-issue-investigator/5_examples.xml +++ b/.roo/rules-issue-investigator/5_examples.xml @@ -70,7 +70,7 @@ Formulate a solution and draft a comment. -"Hey @roomote-agent, I took a look at this issue and it seems like the problem is in the `handleLogin` function in `src/auth/login.ts`. There's an empty `try...catch` block that is likely catching the login error and preventing any message from being shown to the user. +"Hey, I took a look at this issue and it seems like the problem is in the `handleLogin` function in `src/auth/login.ts`. There's an empty `try...catch` block that is likely catching the login error and preventing any message from being shown to the user. A good first step to fixing this would be to add some logging to the `catch` block to see what error is actually happening. Then, we should probably implement proper error feedback to the user on the login page. This should solve the issue of the silent failure." diff --git a/.roo/rules-issue-investigator/6_communication.xml b/.roo/rules-issue-investigator/6_communication.xml index 6ed68c0043b..348ecf18782 100644 --- a/.roo/rules-issue-investigator/6_communication.xml +++ b/.roo/rules-issue-investigator/6_communication.xml @@ -2,20 +2,18 @@ Be conversational and helpful, not robotic. Write comments as if you are a human developer collaborating on the project. - Always start any GitHub issue comment body with "Hey @roomote-agent,". Analysis complete. The investigation has yielded the following result. - Starting comments with "Hey," instead of "Hey @roomote-agent,". - Hey @roomote-agent, I took a look at this and found something interesting... - Hey @roomote-agent, I've been digging into this issue, and I think I've found a possible cause. + Hey, I took a look at this and found something interesting... + I've been digging into this issue, and I think I've found a possible cause. - Start every GitHub issue comment with "Hey @roomote-agent,". + Start with a friendly opening. State your main finding or hypothesis clearly but not definitively. Provide context, like file paths and function names. Propose a next step or a theoretical solution. diff --git a/.roo/rules-issue-writer/1_workflow.xml b/.roo/rules-issue-writer/1_workflow.xml index 0dc2e279d2a..99ef7db5d9d 100644 --- a/.roo/rules-issue-writer/1_workflow.xml +++ b/.roo/rules-issue-writer/1_workflow.xml @@ -1,391 +1,1161 @@ - - This mode focuses solely on assembling a template-free GitHub issue prompt for an AI coding agent. - It integrates codebase exploration to ground the prompt in reality while keeping the output non-technical. - It also captures the user-facing value/impact (who is affected, how often, and why it matters) to support prioritization, all in plain language. - - - - - - Codebase exploration is iterative and may repeat as many times as needed based on user-agent back-and-forth. - - Early-stop and escalate-once apply per iteration; when new info arrives, start a fresh iteration. - - One-tool-per-message is respected; narrate succinct progress and update TODOs each iteration. - - - - New details from the user (environment, steps, screenshots, constraints) - - Clarifications that change scope or target component/feature - - Discrepancies found between user claims and code - - Reclassification between Bug and Enhancement - - - - - - Treat the user's FIRST message as the issue description; do not ask if they want to create an issue. - - Begin immediately: initialize a focused TODO list and start repository detection before discovery. - - CLI submission via gh happens only after the user confirms during the merged review/submit step. - - - - [ ] Detect repository context (OWNER/REPO, monorepo, roots) - [ ] Perform targeted codebase discovery (iteration 1) - [ ] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - - - Kickoff + Initialize Issue Creation Process - Rephrase the user's goal and outline a brief plan, then proceed without delay. - Maintain low narrative verbosity; use structured outputs for details. + IMPORTANT: This mode assumes the first user message is already a request to create an issue. + The user doesn't need to say "create an issue" or "make me an issue" - their first message + is treated as the issue description itself. + + When the session starts, immediately: + 1. Treat the user's first message as the issue description + 2. Initialize the workflow by using the update_todo_list tool + 3. Begin the issue creation process without asking what they want to do + + + + [ ] Detect current repository information + [ ] Determine repository structure (monorepo/standard) + [ ] Perform initial codebase discovery + [ ] Analyze user request to determine issue type + [ ] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + - - Detect Current Repository Information - - Verify we're in a Git repository and capture the GitHub remote for safe submission. + + Detect current repository information + + CRITICAL FIRST STEP: Verify we're in a git repository and get repository information. + + 1. Check if we're in a git repository: + + git rev-parse --is-inside-work-tree 2>/dev/null || echo "not-git-repo" + + + If the output is "not-git-repo", immediately stop and inform the user: + + + + This mode must be run from within a GitHub repository. Please navigate to a git repository and try again. + + + + 2. If in a git repository, get the repository information: + + git remote get-url origin 2>/dev/null | sed -E 's/.*[:/]([^/]+)\/([^/]+)(\.git)?$/\1\/\2/' | sed 's/\.git$//' + + + Store this as REPO_FULL_NAME for use throughout the workflow. + + If no origin remote exists, stop with: + + + No GitHub remote found. This mode requires a GitHub repository with an 'origin' remote configured. + + + + Update todo after detecting repository: + + + [x] Detect current repository information + [-] Determine repository structure (monorepo/standard) + [ ] Perform initial codebase discovery + [ ] Analyze user request to determine issue type + [ ] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - 1) Check if inside a git repository: - - git rev-parse --is-inside-work-tree 2>/dev/null || echo "not-git-repo" - + + Determine Repository Structure + + Check if this is a monorepo or standard repository by looking for common patterns. + + First, check for monorepo indicators: + 1. Look for workspace configuration: + - package.json with "workspaces" field + - lerna.json + - pnpm-workspace.yaml + - rush.json + + 2. Check for common monorepo directory patterns: + + . + false + + + Look for directories like: + - apps/ (application packages) + - packages/ (shared packages) + - services/ (service packages) + - libs/ (library packages) + - modules/ (module packages) + - src/ (main source if not using workspaces) + + If monorepo detected: + - Dynamically discover packages by looking for package.json files in detected directories + - Build a list of available packages with their paths + + Based on the user's description, try to identify which package they're referring to. + If unclear, ask for clarification: + + + I see this is a monorepo with multiple packages. Which specific package or application is your issue related to? + + [Dynamically generated list of discovered packages] + Let me describe which package: [specify] + + + + If standard repository: + - Skip package selection + - Use repository root for all searches + + Store the repository context for all future codebase searches and explorations. + + Update todo after determining context: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [-] Perform initial codebase discovery + [ ] Analyze user request to determine issue type + [ ] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - If the output is "not-git-repo", stop: - - - This mode must be run from within a GitHub repository. Navigate to a git repository and try again. - - + + Perform Initial Codebase Discovery + + Now that we know the repository structure, immediately search the codebase to understand + what the user is talking about before determining the issue type. + + DISCOVERY ACTIVITIES: + + 1. Extract keywords and concepts from the user's INITIAL MESSAGE (their issue description) + 2. Search the codebase to verify these concepts exist + 3. Build understanding of the actual implementation + 4. Identify relevant files, components, and code patterns + + + [Keywords from user's initial message/description] + [Repository or package path from step 2] + + + Additional searches based on initial findings: + - If error mentioned: search for exact error strings + - If feature mentioned: search for related functionality + - If component mentioned: search for implementation details + + + [repository or package path] + [specific patterns found in initial search] + + + Document findings: + - Components/features found that match user's description + - Actual implementation details discovered + - Related code sections identified + - Any discrepancies between user description and code reality + + Update todos: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [-] Analyze user request to determine issue type + [ ] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - 2) Get origin remote and normalize to OWNER/REPO: - - git remote get-url origin 2>/dev/null | sed -E 's/.*[:/]([^/]+)\/([^/]+)(\.git)?$/\1\/\2/' | sed 's/\.git$//' - + + Analyze Request to Determine Issue Type + + Using the codebase discoveries from step 2, analyze the user's request to determine + the appropriate issue type with informed context. + + CRITICAL GUIDANCE FOR ISSUE TYPE SELECTION: + For issues that affect user workflows or require behavior changes: + - PREFER the feature proposal template over bug report + - Focus on explaining WHO is affected and WHEN this happens + - Describe the user impact before diving into technical details + + Based on your findings, classify the issue: + + Bug indicators (verified against code): + - Error messages that match actual error handling in code + - Broken functionality in existing features found in codebase + - Regression from previous behavior documented in code/tests + - Code paths that don't work as documented + + Feature indicators (verified against code): + - New functionality not found in current codebase + - Enhancement to existing features found in code + - Missing capabilities compared to similar features + - Integration points that could be extended + - WORKFLOW IMPROVEMENTS: When existing behavior works but doesn't meet user needs + + IMPORTANT: Use your codebase findings to inform the question: + + + Based on your request about [specific feature/component found in code], what type of issue would you like to create? + + [Order based on codebase findings and user description] + Bug Report - [Specific component] is not working as expected + Feature Proposal - Add [specific capability] to [existing component] + + + + Update todos: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [-] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - If no origin remote exists, stop: - - - No GitHub 'origin' remote found. Configure a GitHub remote and retry. - - - - Record the normalized OWNER/REPO (e.g., owner/repo) as [OWNER_REPO] to pass via --repo during submission. - - 3) Combined monorepo check and roots discovery (single command): - - set -e; if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "not-git-repo"; exit 0; fi; OWNER_REPO=$(git remote get-url origin 2>/dev/null | sed -E 's/.*[:/]([^/]+)\/([^/]+)(\.git)?$/\1\/\2/' | sed 's/\.git$//'); IS_MONO=false; [ -f package.json ] && grep -q '"workspaces"' package.json && IS_MONO=true; for f in lerna.json pnpm-workspace.yaml rush.json; do [ -f "$f" ] && IS_MONO=true; done; ROOTS="."; if [ "$IS_MONO" = true ]; then ROOTS=$(git ls-files -z | tr '\0' '\n' | grep -E '^(apps|packages|services|libs)/[^/]+/package\.json$' | sed -E 's#/package\.json$##' | sort -u | paste -sd, -); [ -z "$ROOTS" ] && ROOTS=$(find . -maxdepth 3 -name package.json -not -path "./node_modules/*" -print0 | xargs -0 -n1 dirname | grep -E '^(\.|\.\/(apps|packages|services|libs)\/[^/]+)$' | sort -u | paste -sd, -); fi; echo "OWNER_REPO=$OWNER_REPO"; echo "IS_MONOREPO=$IS_MONO"; echo "ROOTS=$ROOTS" - - - Interpretation: - - If output contains OWNER_REPO, IS_MONOREPO, and ROOTS, record them and treat Step 3 as satisfied. - - If output is "not-git-repo", stop as above. - - If IS_MONOREPO=true but ROOTS is empty, perform Step 3 to determine roots manually. - - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [ ] Perform targeted codebase discovery (iteration N) - [ ] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - + + Gather and Verify Additional Information + + Based on the issue type and initial codebase discovery, gather information while + continuously verifying against the actual code implementation. + + CRITICAL FOR FEATURE REQUESTS: Be fact-driven and challenge assumptions! + When users describe current behavior as problematic for a feature request, you MUST verify + their claims against the actual code. If their description doesn't match reality, this + might actually be a bug report, not a feature request. + + For Bug Reports: + 1. When user describes steps to reproduce: + - Search for the UI components/commands mentioned + - Verify the code paths that would be executed + - Check for existing error handling or known issues + + 2. When user provides error messages: + - Search for exact error strings in codebase + - Find where errors are thrown + - Understand the conditions that trigger them + + 3. For version information: + - Check package.json for actual version + - Look for version-specific code or migrations + + Example verification searches: + + [repository or package path] + [exact error message from user] + + + + [feature or component name] implementation + [repository or package path] + + + For Feature Requests - AGGRESSIVE VERIFICATION WITH CONCRETE EXAMPLES: + 1. When user claims current behavior is X: + - ALWAYS search for the actual implementation + - Read the relevant code to verify their claim + - Check CSS/styling files if UI-related + - Look at configuration files + - Examine test files to understand expected behavior + - TRACE THE DATA FLOW: Follow values from where they're calculated to where they're used + + 2. CRITICAL: Look for existing variables/code that could be reused: + - Search for variables that are calculated but not used where expected + - Identify existing patterns that could be extended + - Find similar features that work correctly for comparison + + 3. If discrepancy found between claim and code: + - Do NOT proceed without clarification + - Present CONCRETE before/after examples with actual values + - Show exactly what happens vs what should happen + - Ask if this might be a bug instead + + Example verification approach: + User says: "Feature X doesn't work properly" + + Your investigation should follow this pattern: + a) What is calculated: Search for where X is computed/defined + b) Where it's stored: Find variables/state holding the value + c) Where it's used: Trace all usages of that value + d) What's missing: Identify gaps in the flow + + Present findings with concrete examples: + + + I investigated the implementation and found something interesting: + + Current behavior: + - The value is calculated at [file:line]: `value = computeX()` + - It's stored in variable `calculatedValue` at [file:line] + - BUT it's only used for [purpose A] at [file:line] + - It's NOT used for [purpose B] where you expected it + + Concrete example: + - When you do [action], the system calculates [value] + - This value goes to [location A] + - But [location B] still uses [old/different value] + + Is this the issue you're experiencing? This seems like the calculated value isn't being used where it should be. + + Yes, exactly! The value is calculated but not used in the right place + No, the issue is that the calculation itself is wrong + Actually, I see now that [location B] should use a different value + + + + 4. Continue verification until facts are established: + - If user confirms it's a bug, switch to bug report workflow + - If user provides more specific context, search again + - Do not accept vague claims without code verification + + 5. For genuine feature requests after verification: + - Document what the code currently does (with evidence and line numbers) + - Show the exact data flow: input → processing → output + - Confirm what the user wants changed with concrete examples + - Ensure the request is based on accurate understanding + + CRITICAL: For feature requests, if user's description doesn't match codebase reality: + - Challenge the assumption with code evidence AND concrete examples + - Show actual vs expected behavior with specific values + - Suggest it might be a bug if code shows different intent + - Ask for clarification repeatedly if needed + - Do NOT proceed until facts are established + + Only proceed when you have: + - Verified current behavior in code with line-by-line analysis + - Confirmed user's understanding matches reality + - Determined if it's truly a feature request or actually a bug + - Identified any existing code that could be reused for the fix + + Update todos after verification: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [-] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - - Determine Repository Structure (Monorepo/Standard) - - If Step 2's combined detection output includes IS_MONOREPO and ROOTS, mark this step complete and proceed to Step 4. Otherwise, use the manual process below. + + Determine Contribution Intent with Context + + Before asking about contribution, perform a quick technical assessment to provide context: + + 1. Search for complexity indicators: + - Number of files that would need changes + - Existing tests that would need updates + - Dependencies and integration points + + 2. Look for contribution helpers: + - CONTRIBUTING.md guidelines + - Existing similar implementations + - Test patterns to follow + + + CONTRIBUTING guide setup development + + + Based on findings, provide informed context in the question: + + + Based on my analysis, this [issue type] involves [brief complexity assessment from code exploration]. Are you interested in implementing this yourself, or are you reporting it for the project team to handle? + + Just reporting the problem - the project team can design the solution + I want to contribute and implement this myself + I'd like to provide issue scoping to help whoever implements it + + + + Update todos based on response: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [If contributing: [-] Perform issue scoping (if contributing)] + [If not contributing: [-] Perform issue scoping (skipped - not contributing)] + [-] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - Identify whether this is a monorepo and record the search root(s). + + Issue Scoping for Contributors + + ONLY perform this step if the user wants to contribute or provide issue scoping. + + This step performs a comprehensive, aggressive investigation to create detailed technical + scoping that can guide implementation. The process involves multiple sub-phases: + + + + Perform an exhaustive investigation to produce a comprehensive technical solution + with extreme detail, suitable for automated fix workflows. + + + + Expand the todo list to include detailed investigation steps + + When starting the issue scoping phase, update the main todo list to include + the detailed investigation steps: + + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [-] Perform issue scoping (if contributing) + [ ] Extract keywords from the issue description + [ ] Perform initial broad codebase search + [ ] Analyze search results and identify key components + [ ] Deep dive into relevant files and implementations + [ ] Form initial hypothesis about the issue/feature + [ ] Attempt to disprove hypothesis through further investigation + [ ] Identify all affected files and dependencies + [ ] Map out the complete implementation approach + [ ] Document technical risks and edge cases + [ ] Formulate comprehensive technical solution + [ ] Create detailed acceptance criteria + [ ] Prepare issue scoping summary + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + + + + Extract all relevant keywords, concepts, and technical terms + + - Identify primary technical concepts from user's description + - Extract error messages or specific symptoms + - Note any mentioned file paths or components + - List related features or functionality + - Include synonyms and related terms + + + Update the main todo list to mark "Extract keywords" as complete and move to next phase + + + + + Perform multiple rounds of increasingly focused searches + + + Use codebase_search with all extracted keywords to get an overview of relevant code. + + [Combined keywords from extraction phase] + [Repository or package path] + + + + + Based on initial results, identify key components and search for: + - Related class/function definitions + - Import statements and dependencies + - Configuration files + - Test files that might reveal expected behavior + + + + Search for specific implementation details: + - Error handling patterns + - State management + - API endpoints or routes + - Database queries or models + - UI components and their interactions + + + + Look for: + - Edge cases in the code + - Integration points with other systems + - Configuration options that affect behavior + - Feature flags or conditional logic + + + + After completing all search iterations, update the todo list to show progress + + + + + Thoroughly analyze all relevant files discovered + + - Use list_code_definition_names to understand file structure + - Read complete files to understand full context + - Trace execution paths through the code + - Identify all dependencies and imports + - Map relationships between components + + + Document findings including: + - File paths and their purposes + - Key functions and their responsibilities + - Data flow through the system + - External dependencies + - Potential impact areas + + + + + Form a comprehensive hypothesis about the issue or feature + + - Identify the most likely root cause + - Trace the bug through the execution path + - Determine why the current implementation fails + - Consider environmental factors + + + - Identify the optimal integration points + - Determine required architectural changes + - Plan the implementation approach + - Consider scalability and maintainability + + + + + Aggressively attempt to disprove the hypothesis + + + - Look for similar features implemented differently + - Check for deprecated code that might interfere + + + - Search for configuration that could change behavior + - Look for environment-specific code paths + + + - Find existing tests that might contradict hypothesis + - Look for test cases that reveal edge cases + + + - Search for comments explaining design decisions + - Look for TODO or FIXME comments related to the area + + + + If hypothesis is disproven, return to search phase with new insights. + If hypothesis stands, proceed to solution formulation. + + + + + Create a comprehensive technical solution - PRIORITIZE SIMPLICITY + + CRITICAL: Before proposing any solution, ask yourself: + 1. What existing variables/functions can I reuse? + 2. What's the minimal change that fixes the issue? + 3. Can I leverage existing patterns in the codebase? + 4. Is there a simpler approach I'm overlooking? + + The best solution often reuses existing code rather than creating new complexity. + + + + ALWAYS consider backwards compatibility: + 1. Will existing data/configurations still work with the new code? + 2. Can we detect and handle legacy formats automatically? + 3. What migration paths are needed for existing users? + 4. Are there ways to make changes additive rather than breaking? + 5. Document any compatibility considerations clearly + + + + FIRST, identify what can be reused: + - Variables that are already calculated but not used where needed + - Functions that already do what we need + - Patterns in similar features we can follow + - Configuration that already exists but isn't applied + + Example finding: + "The variable `calculatedValue` already contains what we need at line X, + we just need to use it at line Y instead of recalculating" + + + + - Start with the SIMPLEST possible fix + - Exact files to modify with line numbers + - Prefer changing variable usage over creating new logic + - Specific code changes required (minimal diff) + - Order of implementation steps + - Migration strategy if needed + + + + - All files that import affected code + - API contracts that must be maintained + - Existing tests that validate current behavior + - Configuration changes required (prefer reusing existing) + - Documentation updates needed + + + + - Unit tests to add or modify + - Integration tests required + - Edge cases to test + - Performance testing needs + - Manual testing scenarios + + + + - Breaking changes identified + - Performance implications + - Security considerations + - Backward compatibility issues + - Rollback strategy + + + + + + Create extremely detailed acceptance criteria + + Given [detailed context including system state] + When [specific user or system action] + Then [exact expected outcome] + And [additional verifiable outcomes] + But [what should NOT happen] + + Include: + - Specific UI changes with exact text/behavior + - API response formats + - Database state changes + - Performance requirements + - Error handling scenarios + + + - Each criterion must be independently testable + - Include both positive and negative test cases + - Specify exact error messages and codes + - Define performance thresholds where applicable + + + + + Format the comprehensive issue scoping section + - . - false - +### Root Cause / Implementation Target +[Detailed explanation of the core issue or feature target, focusing on the practical problem first] - 2) Monorepo indicators: - - package.json with "workspaces" - - lerna.json, pnpm-workspace.yaml, rush.json - - Top-level directories like apps/, packages/, services/, libs/ +### Affected Components +- **Primary Files:** + - `path/to/file1.ts` (lines X-Y): [Purpose and changes needed] + - `path/to/file2.ts` (lines A-B): [Purpose and changes needed] - If monorepo is detected: - - Discover package roots by locating package.json files under these directories - - Prefer scoping searches to the package most aligned with the user's description - - Ask for package selection if ambiguous +- **Secondary Impact:** + - Files that import affected components + - Related test files + - Documentation files - If standard repository: - - Use repository root for searches +### Current Implementation Analysis +[Detailed explanation of how the current code works, with specific examples showing the data flow] +Example: "The function at line X calculates [value] by [method], which results in [actual behavior]" - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [-] Perform targeted codebase discovery (iteration N) - [ ] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - +### Proposed Implementation - - Codebase-Aware Context Discovery (Iterative) - - Purpose: Understand the context of the user's description by exploring the codebase. This step is repeatable. - - Discovery workflow (respect one-tool-per-message): - 1) Extract keywords, component names, error phrases, and concepts from the user's message or latest reply. - 2) Run semantic search: - - [Keywords from user's description or latest reply] - - - 3) Refine with targeted regex where helpful: - - . - [exact error strings|component names|feature flags] - - - 4) Read key files for verification when necessary: - - [relevant file path from search hits] - - - Guidance: - - Early-stop per iteration when top hits converge (~70%) or you can name the exact feature/component involved. - - Escalate-once per iteration if signals conflict: run one refined batch, then proceed. - - Keep findings internal; do NOT include file paths, line numbers, stack traces, or diffs in the final prompt. - - Iteration rules: - - After ANY new user input or clarification, return to this step with updated keywords. - - Update internal notes and TODOs to reflect the current iteration (e.g., iteration 2, 3, ...). +#### Step 1: [First implementation step] +- File: `path/to/file.ts` +- Changes: [Specific code changes] +- Rationale: [Why this change is needed] - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [-] Perform targeted codebase discovery (iteration N) - [ ] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - +#### Step 2: [Second implementation step] +[Continue for all steps...] - - Clarify Missing Details (Guided by Findings) - - Ask minimal, targeted questions grounded by what you found in code. - - For Bug reports: - - I’m verifying the behavior around [feature/component inferred from code]. Could you provide a minimal reproduction and quick impact details? - - Repro format: 1) Environment/setup 2) Steps 3) Expected 4) Actual 5) Variations (only if you tried them) - Impact: Who is affected and how often does this happen? - Cost: Approximate time or outcome cost per occurrence (optional) - - - - For Enhancements: - - To capture the improvement well, what is the user goal and value in plain language? - - State the user goal and when it occurs - Describe the desired behavior conceptually (no code) - Value: Who benefits and what improves (speed, clarity, fewer errors, conversions)? - - - - Discrepancies: - - If you found contradictions between description and code, present concrete, plain-language examples (no code) and ask for confirmation. - - Loop-back: - - After receiving any answer, return to Step 4 (Discovery) with the new information and repeat as needed. +### Code Architecture Considerations +- Design patterns to follow +- Existing patterns in codebase to match +- Architectural constraints - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [x] Perform targeted codebase discovery (iteration N) - [-] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - +### Testing Requirements +- Unit Tests: + - [ ] Test case 1: [Description] + - [ ] Test case 2: [Description] +- Integration Tests: + - [ ] Test scenario 1: [Description] +- Edge Cases: + - [ ] Edge case 1: [Description] - - Classify Type (Provisional and Repeatable) - - Use the user's description plus verified findings to choose: - - Bug indicators: matched error strings; broken behavior in existing features; regression indicators. - - Enhancement indicators: capability absent; extension of existing feature; workflow improvement. - - Impact snapshot (optional): Severity (Blocker/High/Medium/Low) and Reach (Few/Some/Many). If uncertain, omit and proceed. - - Confirm with the user if uncertain: - - Based on the behavior around [feature/component], should we frame this as a Bug or an Enhancement? - - Bug Report - Enhancement - - - - Reclassification: - - If later evidence or user info changes the type, reclassify and loop back to Step 4 for a fresh discovery iteration. +### Performance Impact +- Expected performance change: [Increase/Decrease/Neutral] +- Benchmarking needed: [Yes/No, specifics] +- Optimization opportunities: [List any] - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [x] Perform targeted codebase discovery (iteration N) - [x] Clarify missing details (repro or desired outcome) - [-] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - +### Security Considerations +- Input validation requirements +- Authentication/Authorization changes +- Data exposure risks - - Assemble Issue Body - - Build a concise, non-technical issue body. Omit empty sections entirely. - - Format: - ``` - ## Type - Bug | Enhancement - - ## Problem / Value - [One or two sentences that capture the problem and why it matters in plain language] - - ## Context - [Who is affected and when it happens] - [Enhancement: desired behavior conceptually, in the user's words] - [Bug: current observed behavior in plain language] - - ## Reproduction (Bug only, if available) - 1) Steps (each action/command) - 2) Expected result - 3) Actual result - 4) Variations tried (include only if the user explicitly provided them) - - ## Constraints/Preferences - [Performance, accessibility, UX, or other considerations] - ``` - - Rules: - - Keep non-technical; do NOT include code paths, line numbers, stack traces, or diffs. - - Ground the wording in verified behavior, but keep implementation details internal. - - Sourcing: Do not infer or fabricate reproduction details or “Variations tried.” Include them only if explicitly provided by the user; otherwise omit the line. - - Quoting fidelity: If the user lists “Variations tried,” include them faithfully (verbatim or clearly paraphrased without adding new items). - - Value framing: Ensure the “Problem / Value” explains why it matters (impact on users or outcomes) in plain language. - - Title: Produce a concise Title (≤ 80 chars) prefixed with [BUG] or [ENHANCEMENT]; when helpful, append a brief value phrase in parentheses, e.g., “(blocks new runs)”. - - Iteration note: - - If new info arrives after drafting, loop back to Step 4, then update this draft accordingly. +### Migration Strategy +[If applicable, how to migrate existing data/functionality] - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [x] Perform targeted codebase discovery (iteration N) - [x] Clarify missing details (repro or desired outcome) - [x] Classify type (Bug | Enhancement) - [-] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) - - - - +### Rollback Plan +[How to safely rollback if issues arise] - - Review and Submit (Single-Step) - - Present the full current issue details in a code block. Offer two submission options; any other response is treated as a change request. - - - Review the current issue details. Select one of the options below or specify any changes or other workflow you would like me to perform: - -```md -Title: [ISSUE_TITLE] - -[ISSUE_BODY] -``` - - Submit now - Submit now and assign to me - - - - Responses: - - If "Submit now": - Prepare: - - Title: derive from Summary (≤ 80 chars, plain language) - - Body: the finalized issue body - - Execute: - - gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")" - - - - If "Submit now and assign to me": - Execute (assignment at creation; falls back to edit if needed): - - ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")" --assignee "@me") || true; if [ -z "$ISSUE_URL" ]; then ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")"); gh issue edit "$ISSUE_URL" --add-assignee "@me"; fi; echo "$ISSUE_URL" - - - - Any other response: - - Collect requested edits and apply them - - Loop back to Step 4 (Discovery) if new information affects context - - Re-assemble in Step 7 - - Rerun this step and present the updated issue details - - On success: Capture the created issue URL from stdout and complete: - - - Created issue: [URL] - - - - On failure: Present the error succinctly and offer to retry after fixing gh setup (installation/auth). Provide the computed Title and Body inline so the user can submit manually if needed. +### Dependencies and Breaking Changes +- External dependencies affected: [List] +- API contract changes: [List] +- Breaking changes for users: [List with mitigation] + ]]> + + + + Additional considerations for monorepo repositories: + - Scope all searches to the identified package (if monorepo) + - Check for cross-package dependencies + - Verify against package-specific conventions + - Look for package-specific configuration + - Check if changes affect multiple packages + - Identify shared dependencies that might be impacted + - Look for workspace-specific scripts or tooling + - Consider package versioning implications + + After completing the comprehensive issue scoping, update the main todo list to show + all investigation steps are complete: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Extract keywords from the issue description + [x] Perform initial broad codebase search + [x] Analyze search results and identify key components + [x] Deep dive into relevant files and implementations + [x] Form initial hypothesis about the issue/feature + [x] Attempt to disprove hypothesis through further investigation + [x] Identify all affected files and dependencies + [x] Map out the complete implementation approach + [x] Document technical risks and edge cases + [x] Formulate comprehensive technical solution + [x] Create detailed acceptance criteria + [x] Prepare issue scoping summary + [-] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + - - - [x] Detect repository context (OWNER/REPO, monorepo, roots) - [x] Perform targeted codebase discovery (iteration N) - [x] Clarify missing details (repro or desired outcome) - [x] Classify type (Bug | Enhancement) - [x] Assemble Issue Body - [x] Review and submit (Submit now | Submit now and assign to me) - - - - - - - - Repository detection (git repo present and origin remote configured) is performed before any submission. - Issue is submitted via gh after choosing "Submit now" or "Submit now and assign to me", and the created issue URL is returned. - When "Submit now and assign to me" is chosen, the issue is assigned to the current GitHub user using --assignee "@me" (or gh issue edit fallback). - Submission uses Title and Body only and specifies --repo [OWNER_REPO] discovered in Step 2; no temporary files or file paths are used. - Language is plain and user-centric; no technical artifacts included in the issue body. - Content grounded by repeated codebase exploration cycles as needed. - Early-stop/escalate-once applied per iteration; unlimited iterations across the conversation. - The merged step offers "Submit now" or "Submit now and assign to me"; any other response is treated as a change request and the step is shown again with the full current issue details. - + + Check for Repository Issue Templates + + Check if the repository has custom issue templates and use them. If not, create a simple generic template. + + 1. Check for issue templates in standard locations: + + .github/ISSUE_TEMPLATE + true + + + 2. Also check for single template file: + + .github + false + + + Look for files like: + - .github/ISSUE_TEMPLATE/*.md + - .github/ISSUE_TEMPLATE/*.yml + - .github/ISSUE_TEMPLATE/*.yaml + - .github/issue_template.md + - .github/ISSUE_TEMPLATE.md + + 3. If templates are found: + a. Parse the template files to extract: + - Template name and description + - Required fields + - Template body structure + - Labels to apply + + b. For YAML templates, look for: + - name: Template display name + - description: Template description + - labels: Default labels + - body: Form fields or markdown template + + c. For Markdown templates, look for: + - Front matter with metadata + - Template structure with placeholders + + 4. If multiple templates exist, ask user to choose: + + I found the following issue templates in this repository. Which one would you like to use? + + [Template 1 name]: [Template 1 description] + [Template 2 name]: [Template 2 description] + + + + 5. If no templates are found: + - Create a simple generic template based on issue type + - For bugs: Basic structure with description, steps to reproduce, expected vs actual + - For features: Problem description, proposed solution, impact + + 6. Store the selected/created template information: + - Template content/structure + - Required fields + - Default labels + - Any special formatting requirements + + Update todos: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Check for repository issue templates + [-] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue + + + + + + + Draft Issue Content + + Create the issue body using the template from step 8 and all verified information from codebase exploration. + + If using a repository template: + - Fill in the template fields with gathered information + - Include code references and findings where appropriate + - Respect the template's structure and formatting + + If using a generated template (no repo templates found): + + For Bug Reports: + ``` + ## Description + [Clear description of the bug with code context] + + ## Steps to Reproduce + 1. [Step with relevant code paths] + 2. [Step with component references] + 3. [Continue with specific details] + + ## Expected Behavior + [What should happen based on code logic] + + ## Actual Behavior + [What actually happens] + + ## Additional Context + - Version: [from package.json if found] + - Environment: [any relevant details] + - Error logs: [if any] + + ## Code Investigation + [Include findings from codebase exploration] + - Relevant files: [list with line numbers] + - Possible cause: [hypothesis from code review] + + [If user is contributing, add the comprehensive issue scoping section from step 7] + ``` + + For Feature Requests: + ``` + ## Problem Description + [What problem does this solve, who is affected, when it happens] + + ## Current Behavior + [How it works now with specific examples] + + ## Proposed Solution + [What should change] + + ## Impact + [Who benefits and how] + + ## Technical Context + [Findings from codebase exploration] + - Similar features: [code references] + - Integration points: [from exploration] + - Architecture considerations: [if any] + + [If contributing, add the comprehensive issue scoping section from step 7] + ``` + + Update todos: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Check for repository issue templates + [x] Draft issue content + [-] Review and confirm with user + [ ] Create GitHub issue + + + + + + + Review and Confirm with User + + Present the complete drafted issue to the user for review, highlighting the + code-verified information: + + + I've prepared the following GitHub issue based on my analysis of the codebase and your description. I've verified the technical details against the actual implementation. Please review: + + [Show the complete formatted issue content] + + Key verifications made: + - ✓ Component locations confirmed in code + - ✓ Error messages matched to source + - ✓ Architecture compatibility checked + [List other relevant verifications] + + Would you like me to create this issue, or would you like to make any changes? + + Yes, create this issue in the detected repository + Modify the problem description + Add more technical details + Change the title to: [let me specify] + + + + If user requests changes, make them and show the updated version for confirmation. + + After confirmation: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Check for repository issue templates + [x] Draft issue content + [x] Review and confirm with user + [-] Prepare issue for submission + [ ] Handle submission choice + + + + + + + Prepare Issue for Submission + + Once user confirms the issue content, prepare it for submission: + + First, perform final duplicate check with refined search based on our findings: + + gh issue list --repo $REPO_FULL_NAME --search "[key terms from verified analysis]" --state all --limit 10 + + + If no exact duplicates are found, save the issue content to a temporary file within the project: + + + ./github_issue_draft.md + [The complete formatted issue body from step 8] + [calculated line count] + + + After saving the issue draft, ask the user how they would like to proceed: + + + I've saved the issue draft to ./github_issue_draft.md. The issue is ready for submission with the following details: + + Title: "[Descriptive title with component name]" + Labels: [appropriate labels based on issue type] + Repository: $REPO_FULL_NAME + + How would you like to proceed? + + Submit the issue now to the repository + Let me make some edits to the issue first + I'll submit it manually later + + + + Based on the user's response: + + If "Submit the issue now": + - Use gh issue create with the saved file + - Provide the created issue URL and number + - Clean up the temporary file + - Complete the workflow + + If "Let me make some edits": + - Ask what changes they'd like to make + - Update the draft file with their changes + - Return to the submission question + + If "I'll submit it manually": + - Inform them the draft is saved at the configured location + - Provide the gh command they can use later + - Complete the workflow without submission + + Update todos based on the outcome: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Check for repository issue templates + [x] Draft issue content + [x] Review and confirm with user + [x] Prepare issue for submission + [-] Handle submission choice + + + + + + + Handle Submission Choice + + This step handles the user's choice from step 9. + + OPTION 1: Submit the issue now + If the user chooses to submit immediately: + + + gh issue create --repo $REPO_FULL_NAME --title "[Descriptive title]" --body-file ./github_issue_draft.md --label "[appropriate labels]" + + + Label selection based on findings: + - Bug: Use "bug" label + - Feature: Use "enhancement" label + - If affects multiple packages in monorepo: add "affects-multiple" label + + After successful creation: + - Capture and display the issue URL + - Clean up the temporary file: + + rm ./github_issue_draft.md + + - Provide a summary of key findings included + + OPTION 2: Make edits + If the user wants to edit: + + + What changes would you like to make to the issue? + + Update the title + Modify the problem description + Add or remove technical details + Change the labels or other metadata + + + + - Apply the requested changes to the draft + - Update the file with write_to_file + - Return to step 9 to ask about submission again + + OPTION 3: Manual submission + If the user will submit manually: + + Provide clear instructions: + "The issue draft has been saved to ./github_issue_draft.md + + To submit it later, you can use: + gh issue create --repo $REPO_FULL_NAME --title "[Your title]" --body-file ./github_issue_draft.md --label "[labels]" + + Or you can copy the content and create the issue through the GitHub web interface." + + Final todo update: + + + [x] Detect current repository information + [x] Determine repository structure (monorepo/standard) + [x] Perform initial codebase discovery + [x] Analyze user request to determine issue type + [x] Gather and verify additional information + [x] Determine if user wants to contribute + [x] Perform issue scoping (if contributing) + [x] Check for repository issue templates + [x] Draft issue content + [x] Review and confirm with user + [x] Prepare issue for submission + [x] Handle submission choice + + + + \ No newline at end of file diff --git a/.roo/rules-issue-writer/2_github_issue_templates.xml b/.roo/rules-issue-writer/2_github_issue_templates.xml new file mode 100644 index 00000000000..36b44125dd1 --- /dev/null +++ b/.roo/rules-issue-writer/2_github_issue_templates.xml @@ -0,0 +1,190 @@ + + + This mode prioritizes using repository-specific issue templates over hardcoded ones. + If no templates exist in the repository, simple generic templates are created on the fly. + + + + + .github/ISSUE_TEMPLATE/*.yml + .github/ISSUE_TEMPLATE/*.yaml + .github/ISSUE_TEMPLATE/*.md + .github/issue_template.md + .github/ISSUE_TEMPLATE.md + + + + Display name of the template + Brief description of when to use this template + Default issue title (optional) + Array of labels to apply + Array of default assignees + Array of form elements or markdown content + + + + + Static markdown content + + The markdown content to display + + + + + Single-line text input + + Unique identifier + Display label + Help text + Placeholder text + Default value + Boolean + + + + + Multi-line text input + + Unique identifier + Display label + Help text + Placeholder text + Default value + Boolean + Language for syntax highlighting + + + + + Dropdown selection + + Unique identifier + Display label + Help text + Array of options + Boolean + + + + + Multiple checkbox options + + Unique identifier + Display label + Help text + Array of checkbox items + + + + + + + Optional YAML front matter with: + - name: Template name + - about: Template description + - title: Default title + - labels: Comma-separated or array + - assignees: Comma-separated or array + + + Markdown content with sections and placeholders + Common patterns: + - Headers with ## + - Placeholder text in brackets or as comments + - Checklists with - [ ] + - Code blocks with ``` + + + + + + + When no repository templates exist, create simple templates based on issue type. + These should be minimal and focused on gathering essential information. + + + + + - Description: Clear explanation of the bug + - Steps to Reproduce: Numbered list + - Expected Behavior: What should happen + - Actual Behavior: What actually happens + - Additional Context: Version, environment, logs + - Code Investigation: Findings from exploration (if any) + + ["bug"] + + + + + - Problem Description: What problem this solves + - Current Behavior: How it works now + - Proposed Solution: What should change + - Impact: Who benefits and how + - Technical Context: Code findings (if any) + + ["enhancement", "proposal"] + + + + + + When parsing YAML templates: + 1. Use a YAML parser to extract the structure + 2. Convert form elements to markdown sections + 3. Preserve required field indicators + 4. Include descriptions as help text + 5. Maintain the intended flow of the template + + + + When parsing Markdown templates: + 1. Extract front matter if present + 2. Identify section headers + 3. Look for placeholder patterns + 4. Preserve formatting and structure + 5. Replace generic placeholders with user's information + + + + For template selection: + 1. If only one template exists, use it automatically + 2. If multiple exist, let user choose based on name/description + 3. Match template to issue type when possible (bug vs feature) + 4. Respect template metadata (labels, assignees, etc.) + + + + + + Fill templates intelligently using gathered information: + - Map user's description to appropriate sections + - Include code investigation findings where relevant + - Preserve template structure and formatting + - Don't leave placeholder text unfilled + - Add contributor scoping if user is contributing + + + + + + + + + + + + + When no templates exist, create appropriate generic templates on the fly. + Keep them simple and focused on essential information. + + + + - Don't overwhelm with too many fields + - Focus on problem description first + - Include technical details only if user is contributing + - Use clear, simple section headers + - Adapt based on issue type (bug vs feature) + + + \ No newline at end of file diff --git a/.roo/rules-issue-writer/3_best_practices.xml b/.roo/rules-issue-writer/3_best_practices.xml index b6f90c8014b..f2f149ed262 100644 --- a/.roo/rules-issue-writer/3_best_practices.xml +++ b/.roo/rules-issue-writer/3_best_practices.xml @@ -1,147 +1,172 @@ - - This mode assembles a template-free issue body grounded by codebase exploration and can submit it via GitHub CLI after explicit confirmation. - Submission uses Title and Body only and targets the detected repository after the merged Review and Submit step. - - - - Treat the user's FIRST message as the issue description; do not ask if they want to create an issue. - - Start with repository detection (verify git repo; resolve OWNER/REPO from origin), then determine repository structure (monorepo/standard). - - After detection, begin codebase discovery scoped to the repository root or the selected package (in monorepos). - - Keep final output non-technical; implementation details remain internal. + - CRITICAL: This mode assumes the user's FIRST message is already an issue description + - Do NOT ask "What would you like to do?" or "Do you want to create an issue?" + - Immediately start the issue creation workflow when the user begins talking + - Treat their initial message as the problem/feature description + - Begin with repository detection and codebase discovery right away + - The user is already in "issue creation mode" by choosing this mode - - - - - Always pair the problem with user-facing value: who is impacted, when it occurs, and why it matters. - - Keep value non-technical (clarity, time saved, fewer errors, better UX, improved accessibility, reduced confusion). - - - - Severity: Blocker | High | Medium | Low (optional) - - Reach: Few | Some | Many (optional) - - - - - - - Reproduction steps - - Variations tried - - Environment details - - - - Problem/Value statement (plain-language synthesis from user wording) - - Context (who/when) based on user input; keep code-based signals internal - - - - Never fabricate “Variations tried.” If not provided, omit. - - If critical details are missing, ask targeted questions; otherwise proceed with omissions. - - - - - - Use a single merged "Review and Submit" step with options: - - Submit now - - Submit now and assign to me - Any other response is treated as a change request and the step is rerun after applying edits. - - - Submission requires repository detection (git present, origin configured). Capture normalized OWNER/REPO (e.g., owner/repo) and store as [OWNER_REPO] for submission. - - - Always specify the target using --repo "[OWNER_REPO]" to avoid ambiguity and ensure the correct repository is used. - - - When "Submit now and assign to me" is chosen, create using: --assignee "@me". - If creation with --assignee fails (e.g., permissions), create the issue without an assignee and immediately run: - gh issue edit --add-assignee "@me". - - - Use --body with robust quoting (for example: --body "$(printf '%s\n' "[ISSUE_BODY]")") or a heredoc; do not create temporary files or reference file paths. Always include --repo "[OWNER_REPO]" and echo the resulting issue URL. - In execute_command calls, output only the command string; never include XML tags, CDATA markers, code fences, or backticks in the command payload. - - - On gh errors (installation/auth), present the error and offer to retry after fixing gh setup. Surface the computed Title and Body inline - so the user can submit manually if needed. - - - - - - - Use semantic search first to find relevant areas. - - Refine with targeted regex for exact strings (errors, component names, flags). - - Read key files to verify behavior; keep evidence internal. - - Early-stop when hits converge (~70%) or you can name the exact feature/component. - - Escalate-once if signals conflict; run one refined batch, then proceed. - - - 1) codebase_search → 2) search_files → 3) read_file (as needed) - - - In monorepos, scope searches to the selected package when the context is clear; otherwise ask for the relevant package/app if ambiguous. - - - Keep language plain and exclude technical artifacts (paths, line numbers, stack traces, diffs) from the final issue body. - - - - - - - Ask minimal, targeted questions based on what you found in code. - - For bugs: request a minimal reproduction (environment, steps, expected, actual, variations). - - For enhancements: capture user goal, desired behavior in plain language, and any constraints. - - Present discrepancies in plain language (no code) and confirm understanding. - - - - - - - - - - Omit sections that would be empty. - - Do not include "Variations tried" unless explicitly provided by the user. - - Keep language plain and user-centric. - - Exclude technical artifacts (paths, lines, stacks, diffs). - - - - - - At each review stage, present the full current issue details (Title + Body) in a markdown code block. - - Offer "Submit now" or "Submit now and assign to me" suggestions; treat any other response as a change request and rerun the step after applying edits. - - - - - Tool preambles: restate goal briefly, outline a short plan, narrate progress succinctly, summarize final delta. - - One-tool-per-message: await results before continuing. - - Discovery budget: default max 3 searches before escalate-once; stop when sufficient. - - Early-stop: when top hits converge or target is identifiable. - - Verbosity: low narrative; detail appears only in structured outputs. - - + + + - ALWAYS check for repository-specific issue templates before creating issues + - Use templates from .github/ISSUE_TEMPLATE/ directory if they exist + - Parse both YAML (.yml/.yaml) and Markdown (.md) template formats + - If multiple templates exist, let the user choose the appropriate one + - If no templates exist, create a simple generic template on the fly + - NEVER fall back to hardcoded templates - always use repo templates or generate minimal ones + - Respect template metadata like labels, assignees, and title patterns + - Fill templates intelligently using gathered information from codebase exploration + + + + - Focus on helping users describe problems clearly, not solutions + - The project team will design solutions unless the user explicitly wants to contribute + - Don't push users to provide technical details they may not have + - Make it easy for non-technical users to report issues effectively + + CRITICAL: Lead with user impact: + - Always explain WHO is affected and WHEN the problem occurs + - Use concrete examples with actual values, not abstractions + - Show before/after scenarios with specific data + - Example: "Users trying to [action] see [actual result] instead of [expected result]" + + + + - ALWAYS verify user claims against actual code implementation + - For feature requests, aggressively check if current behavior matches user's description + - If code shows different intent than user describes, it might be a bug not a feature + - Present code evidence when challenging user assumptions + - Do not be agreeable - be fact-driven and question discrepancies + - Continue verification until facts are established + - A "feature request" where code shows the feature should already work is likely a bug + + CRITICAL additions for thorough analysis: + - Trace data flow from where values are created to where they're used + - Look for existing variables/functions that already contain needed data + - Check if the issue is just missing usage of existing code + - Follow imports and exports to understand data availability + - Identify patterns in similar features that work correctly + + + + - Always search for existing similar issues before creating a new one + - Check for and use repository issue templates before creating content + - Include specific version numbers and environment details + - Use code blocks with syntax highlighting for code snippets + - Make titles descriptive but concise (e.g., "Dark theme: Submit button invisible due to white-on-grey text") + - For bugs, always test if the issue is reproducible + - Include screenshots or mockups when relevant (ask user to provide) + - Link to related issues or PRs if found during exploration + + CRITICAL: Use concrete examples throughout: + - Show actual data values, not just descriptions + - Include specific file paths and line numbers + - Demonstrate the data flow with real examples + - Bad: "The value is incorrect" + - Good: "The function returns '123' when it should return '456'" + + + + - Only perform issue scoping if user wants to contribute + - Reference specific files and line numbers from codebase exploration + - Ensure technical proposals align with project architecture + - Include implementation steps and issue scoping + - Provide clear acceptance criteria in Given/When/Then format + - Consider trade-offs and alternative approaches + + CRITICAL: Prioritize simple solutions: + - ALWAYS check if needed functionality already exists before proposing new code + - Look for existing variables that just need to be passed/used differently + - Prefer using existing patterns over creating new ones + - The best fix often involves minimal code changes + - Example: "Use existing `modeInfo` from line 234 in export" vs "Create new mode tracking system" + + + + ALWAYS consider backwards compatibility: + - Think about existing data/configurations already in use + - Propose solutions that handle both old and new formats gracefully + - Consider migration paths for existing users + - Document any breaking changes clearly + - Prefer additive changes over breaking changes when possible + + - - Be direct and concise; avoid jargon in the final issue body. - - Keep questions optional and easy to answer with suggested options. - - Emphasize WHO is affected and WHEN it happens. + - Be supportive and encouraging to problem reporters + - Don't overwhelm users with technical questions upfront + - Clearly indicate when technical sections are optional + - Guide contributors through the additional requirements + - Make the "submit now" option clear for problem reporters + - When presenting template choices, include template descriptions to help users choose + - Explain that you're using the repository's own templates for consistency + + + + Always check these locations in order: + 1. .github/ISSUE_TEMPLATE/*.yml or *.yaml (GitHub form syntax) + 2. .github/ISSUE_TEMPLATE/*.md (Markdown templates) + 3. .github/issue_template.md (single template) + 4. .github/ISSUE_TEMPLATE.md (alternate naming) + + + + For YAML templates: + - Extract form elements and convert to appropriate markdown sections + - Preserve required field indicators + - Include field descriptions as context + - Respect dropdown options and checkbox lists + + For Markdown templates: + - Parse front matter for metadata + - Identify section headers and structure + - Replace placeholder text with actual information + - Maintain formatting and hierarchy + + + + - Map gathered information to template sections intelligently + - Don't leave placeholder text in the final issue + - Add code investigation findings to relevant sections + - Include contributor scoping in appropriate section if applicable + - Preserve the template's intended structure and flow + + + + When no templates exist: + - Create minimal, focused templates + - Use simple section headers + - Focus on essential information only + - Adapt structure based on issue type + - Don't overwhelm with unnecessary fields + + + + + Before proposing ANY solution: + 1. Use codebase_search extensively to find all related code + 2. Read multiple files to understand the full context + 3. Trace variable usage from creation to consumption + 4. Look for similar working features to understand patterns + 5. Identify what already exists vs what's actually missing + + + + When designing solutions: + 1. Check if the data/function already exists somewhere + 2. Look for configuration options before code changes + 3. Prefer passing existing variables over creating new ones + 4. Use established patterns from similar features + 5. Aim for minimal diff size + + + + Always include: + - Exact file paths and line numbers + - Variable/function names as they appear in code + - Before/after code snippets showing minimal changes + - Clear explanation of why the simple fix works + + \ No newline at end of file diff --git a/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml b/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml index 4077edfb4d3..a8dd9b590b0 100644 --- a/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml +++ b/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml @@ -1,109 +1,126 @@ - - Asking "What would you like to do?" at start instead of treating the first message as the issue description - - Delaying the workflow with unnecessary questions before discovery - - Not immediately beginning codebase-aware discovery (semantic search → regex refine → read key files) - - Skipping repository detection (git + origin) before discovery or submission - - Not validating repository context before gh commands + - CRITICAL: Asking "What would you like to do?" when mode starts + - Waiting for user to say "create an issue" or "make me an issue" + - Not treating the first user message as the issue description + - Delaying the workflow start with unnecessary questions + - Asking if they want to create an issue when they've already chosen this mode + - Not immediately beginning repository detection and codebase discovery - - - - Submitting without explicit user confirmation ("Submit now") - - Targeting the wrong repository by relying on current directory defaults; always pass --repo OWNER/REPO detected in Step 2 - - Performing PR prep, complexity estimates, or technical scoping - - - - - Splitting final review and submission into multiple steps - Creates redundant prompts and inconsistent state; leads to janky UX - Use a single merged "Review and Submit" step offering only: Submit now, Submit now and assign to me; treat any other response as a change request - - - Not offering "Submit now and assign to me" - Forces manual assignment later; reduces efficiency - Provide the assignment option and use gh issue create --assignee "@me"; if that fails, immediately run gh issue edit --add-assignee "@me" - - - Using temporary files or --body-file for issue body submission - Introduces filesystem dependencies and leaks paths; contradicts single-command policy - Use inline --body with robust quoting, e.g., --body "$(printf '%s\n' "[ISSUE_BODY]")"; do not reference any file paths - - - Omitting --repo or relying on current directory defaults - May submit to the wrong repository in multi-repo or worktree contexts - Always pass --repo [OWNER_REPO] detected in Step 2 - - - Attempting submission without prior repository detection - Commands may target the wrong repo or fail - Detect git repo and ensure origin is configured before any gh commands - - - - - - Inventing or inferring “Variations tried” when the user didn’t provide any - Misleads triage and wastes time reproducing non-existent attempts - Omit the “Variations tried” line entirely unless explicitly provided; if needed, ask a targeted question first - - - Framing only the problem without the value/impact - Makes prioritization harder; obscures who benefits and why it matters - Pair the problem with a plain-language value statement (who, when, why it matters) - - - Overstating impact without user signal - Damages credibility and misguides prioritization - Use conservative, plain language; if unsure, omit severity/reach or ask a single targeted question - - - + - - Vague descriptions like "doesn't work" without who/when impact - - Missing minimal reproduction for bugs (environment, steps, expected, actual, variations) - - Enhancement requests that skip the user goal or desired behavior in plain language - - Titles/summaries that don't quickly communicate the issue + - Vague descriptions like "doesn't work" or "broken" + - Missing reproduction steps for bugs + - Feature requests without clear problem statements + - Not explaining the impact on users + - Forgetting to specify when/how the problem occurs + - Using wrong labels or no labels + - Titles that don't summarize the issue + - Not checking for duplicates - - - - Including code paths, line numbers, stack traces, or diffs in the final issue body - - Adding labels, metadata, or repository details to the body - - Leaving empty section placeholders instead of omitting the section - - Using technical jargon instead of plain, user-centric language - - - - Skipping semantic search and jumping straight to assumptions - Leads to misclassification and inaccurate context + + + - Asking for technical details from non-contributing users + - Performing issue scoping before confirming user wants to contribute + - Requiring acceptance criteria from problem reporters + - Making the process too complex for simple problem reports + - Not clearly indicating the "submit now" option + - Overwhelming users with contributor requirements upfront + - Using hardcoded templates instead of repository templates + - Not checking for issue templates before creating content + - Ignoring template metadata like labels and assignees + + + + - Starting implementation before approval + - Not providing detailed issue scoping when contributing + - Missing acceptance criteria for contributed features + - Forgetting to include technical context from code exploration + - Not considering trade-offs and alternatives + - Proposing solutions without understanding current architecture + + + + Not tracing data flow completely through the system + Missing that data already exists leads to proposing unnecessary new code - - Start with codebase_search on extracted keywords - - Refine with search_files for exact strings (errors, component names, flags) - - read_file only as needed to verify behavior; keep evidence internal - - Early-stop when hits converge or you can name the exact feature/component - - Escalate-once if signals conflict (one refined pass), then proceed + - Use codebase_search extensively to find ALL related code + - Trace variables from creation to consumption + - Check if needed data is already calculated but not used + - Look for similar working features as patterns - - - - Accepting user claims that contradict the codebase without verification - Produces misleading or incorrect issue framing + + Bad: "Add mode tracking to import function" + Good: "The export already includes mode info at line 234, just use it in import at line 567" + + + + + Proposing complex new systems when simple fixes exist + Creates unnecessary complexity, maintenance burden, and potential bugs - - Verify claims against the implementation; trace data from creation → usage - - Compare with similar working features to ground expectations - - If discrepancies arise, present concrete, plain-language examples (no code) and confirm + - ALWAYS check if functionality already exists first + - Look for minimal changes that solve the problem + - Prefer using existing variables/functions differently + - Aim for the smallest possible diff - - - - - Asking broad, unfocused questions instead of targeted ones based on findings - - Demanding technical details from non-technical users - - Failing to provide easy, suggested answer formats (repro scaffold, goal statement) - - - - - Mixing internal technical evidence into the final body - - Ignoring the issue format or adding extra sections - - Using inconsistent tone or switching between technical and non-technical language - + + Bad: "Create new state management system for mode tracking" + Good: "Pass existing modeInfo variable from line 45 to the function at line 78" + + + + + Not reading actual code before proposing solutions + Solutions don't match the actual codebase structure + + - Always read the relevant files first + - Verify exact line numbers and content + - Check imports/exports to understand data availability + - Look at similar features that work correctly + + + + + Creating new patterns instead of following existing ones + Inconsistent codebase, harder to maintain + + - Find similar features that work correctly + - Follow the same patterns and structures + - Reuse existing utilities and helpers + - Maintain consistency with the codebase style + + + + + Using hardcoded templates when repository templates exist + Issues don't follow repository conventions, may be rejected or need reformatting + + - Always check .github/ISSUE_TEMPLATE/ directory first + - Parse and use repository templates when available + - Only create generic templates when none exist + + + + + Not properly parsing YAML template structure + Missing required fields, incorrect formatting, lost metadata + + - Parse YAML templates to extract all form elements + - Convert form elements to appropriate markdown sections + - Preserve field requirements and descriptions + - Maintain dropdown options and checkbox lists + + + + + Leaving placeholder text in final issue + Unprofessional appearance, confusion about what information is needed + + - Replace all placeholders with actual information + - Remove instruction text meant for template users + - Fill every section with relevant content + - Add "N/A" for truly inapplicable sections + + \ No newline at end of file diff --git a/.roo/rules-issue-writer/5_examples.xml b/.roo/rules-issue-writer/5_examples.xml deleted file mode 100644 index 6c19018e6c2..00000000000 --- a/.roo/rules-issue-writer/5_examples.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - Examples of assembling template-free issue prompts grounded by codebase exploration, with optional CLI submission after explicit confirmation. - Repository detection precedes submission; review and submission occur in a single merged step offering "Submit now" or "Submit now and assign to me". Any other response is treated as a change request. - - - - - In dark theme the Submit button is almost invisible on the New Run page. - - - - -dark theme submit button visibility - - - -. -Submit|button|dark|theme - - ]]> - - - Internal: matches found in UI components related to theme; wording grounded to user impact. - - - Scroll to bottom -> Look for Submit -2) Expected result: Clearly visible, high-contrast Submit button -3) Actual result: Button appears nearly invisible in dark theme -4) Variations tried: Different browsers (Chrome/Firefox) show same result - ]]> - - - - - I accidentally click "Copy Run" sometimes; would be great to have a simple confirmation. - - - - -Copy Run confirmation - - ]]> - - - Internal: feature entry point identified; keep final output non-technical and user-centric. - - - - - - - - Dark theme Submit button is invisible; I'd like to file this. - - Scroll to bottom -> Look for Submit -2) Expected result: Clearly visible, high-contrast Submit button -3) Actual result: Button appears nearly invisible in dark theme - ]]> - - - Review the current issue details. Select one of the options below or specify any changes or other workflow you would like me to perform: - -```md -Title: [ISSUE_TITLE] - -[ISSUE_BODY] -``` - - Submit now - Submit now and assign to me - - - - - gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")" - - - - ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")" --assignee "@me") || true; if [ -z "$ISSUE_URL" ]; then ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")"); gh issue edit "$ISSUE_URL" --add-assignee "@me"; fi; echo "$ISSUE_URL" - - - - If a change request is provided, collect the requested edits, update the draft (re-run discovery if new info affects context), then rerun this merged step. - - - https://github.com/OWNER/REPO/issues/123 - - - - - Issues are template-free (Title + Body only). - Repository detection (git + origin → OWNER/REPO) occurs before submission and is passed explicitly via --repo [OWNER_REPO]. - Never use --body-file or temporary files; submit with inline --body only (no file paths). - Review and submission happen in one merged step offering "Submit now" or "Submit now and assign to me"; any other response is treated as a change request. - All discovery is internal; keep final output plain-language. - - \ No newline at end of file diff --git a/.roo/rules-issue-writer/5_github_cli_usage.xml b/.roo/rules-issue-writer/5_github_cli_usage.xml new file mode 100644 index 00000000000..1792be87ebb --- /dev/null +++ b/.roo/rules-issue-writer/5_github_cli_usage.xml @@ -0,0 +1,342 @@ + + + The GitHub CLI (gh) provides comprehensive tools for interacting with GitHub. + Here's when and how to use each command in the issue creation workflow. + + Note: This mode prioritizes using repository-specific issue templates over + hardcoded ones. Templates are detected and used dynamically from the repository. + + + + + + ALWAYS use this FIRST before creating any issue to check for duplicates. + Search for keywords from the user's problem description. + + + + gh issue list --repo $REPO_FULL_NAME --search "dark theme button visibility" --state all --limit 20 + + + + --search: Search query for issue titles and bodies + --state: all, open, or closed + --label: Filter by specific labels + --limit: Number of results to show + --json: Get structured JSON output + + + + + + Use for more advanced searches across issues and pull requests. + Supports GitHub's advanced search syntax. + + + + gh search issues --repo $REPO_FULL_NAME "dark theme button" --limit 10 + + + + + + + Use when you find a potentially related issue and need full details. + Check if the user's issue is already reported or related. + + + + gh issue view 123 --repo $REPO_FULL_NAME --comments + + + + --comments: Include issue comments + --json: Get structured data + --web: Open in browser + + + + + + + + Use to check for issue templates in the repository before creating issues. + This is not a gh command but necessary for template detection. + + + Check for templates in standard location: + + .github/ISSUE_TEMPLATE + true + + + Check for single template file: + + .github + false + + + + + + + Read template files to parse their structure and content. + Used after detecting template files. + + + Read YAML template: + + .github/ISSUE_TEMPLATE/bug_report.yml + + + Read Markdown template: + + .github/ISSUE_TEMPLATE/feature_request.md + + + + + + + + These commands should ONLY be used if the user has indicated they want to + contribute the implementation. Skip these for problem reporters. + + + + + Get repository information and recent activity. + + + + gh repo view $REPO_FULL_NAME --json defaultBranchRef,description,updatedAt + + + + + + + Check recent PRs that might be related to the issue. + Look for PRs that modified relevant code. + + + + gh search prs --repo $REPO_FULL_NAME "dark theme" --limit 10 --state all + + + + + + + For bug reports from contributors, check recent commits that might have introduced the issue. + Use after cloning the repository locally. + + + + git log --oneline --grep="theme" -n 20 + + + + + + + + + Only use after: + 1. Confirming no duplicates exist + 2. Checking for and using repository templates + 3. Gathering all required information + 4. Determining if user is contributing or just reporting + 5. Getting user confirmation + + + + gh issue create --repo $REPO_FULL_NAME --title "[Descriptive title of the bug]" --body-file /tmp/issue_body.md --label "bug" + + + + + gh issue create --repo $REPO_FULL_NAME --title "[Problem-focused title]" --body-file /tmp/issue_body.md --label "proposal" --label "enhancement" + + + + --title: Issue title (required) + --body: Issue body text + --body-file: Read body from file + --label: Add labels (can use multiple times) + --assignee: Assign to user + --project: Add to project + --web: Open in browser to create + + + + + + + + ONLY use if user wants to add additional information after creation. + + + + gh issue comment 456 --repo $REPO_FULL_NAME --body "Additional context or comments." + + + + + + + Use if user realizes they need to update the issue after creation. + Can update title, body, or labels. + + + + gh issue edit 456 --repo $REPO_FULL_NAME --title "[Updated title]" --body "[Updated body]" + + + + + + + + After user selects issue type, immediately search for related issues: + 1. Use `gh issue list --search` with keywords from their description + 2. Show any similar issues found + 3. Ask if they want to continue or comment on existing issue + + + + Template detection (NEW): + 1. Use list_files to check .github/ISSUE_TEMPLATE/ directory + 2. Read any template files found (YAML or Markdown) + 3. Parse template structure and metadata + 4. If multiple templates, let user choose + 5. If no templates, prepare to create generic one + + + + Decision point for contribution: + 1. Ask user if they want to contribute implementation + 2. If yes: Use contributor commands for codebase investigation + 3. If no: Skip directly to creating a problem-focused issue + 4. This saves time for problem reporters + + + + During codebase exploration (CONTRIBUTORS ONLY): + 1. Clone repo locally if needed: `gh repo clone $REPO_FULL_NAME` + 2. Use `git log` to find recent changes to affected files + 3. Use `gh search prs` for related pull requests + 4. Include findings in the technical context section + + + + When creating the issue: + 1. Use repository template if found, or generic template if not + 2. Fill template with gathered information + 3. Format differently based on contributor vs problem reporter + 4. Save formatted body to temporary file + 5. Use `gh issue create` with appropriate labels from template + 6. Capture the returned issue URL + 7. Show user the created issue URL + + + + + + When creating issues with long bodies: + 1. Save to temporary file: `cat > /tmp/issue_body.md << 'EOF'` + 2. Use --body-file flag with gh issue create + 3. Clean up after: `rm /tmp/issue_body.md` + + + + Use specific search terms: + - Include error messages in quotes + - Use label filters when appropriate + - Limit results to avoid overwhelming output + + + + Use --json flag for structured data when needed: + - Easier to parse programmatically + - Consistent format across commands + - Example: `gh issue list --json number,title,state` + + + + + + If search finds exact duplicate: + - Show the existing issue to user using `gh issue view` + - Ask if they want to add a comment instead + - Use `gh issue comment` if they agree + + + + If `gh issue create` fails: + - Check error message (auth, permissions, network) + - Ensure gh is authenticated: `gh auth status` + - Save the drafted issue content for user + - Suggest using --web flag to create in browser + + + + Ensure GitHub CLI is authenticated: + - Check status: `gh auth status` + - Login if needed: `gh auth login` + - Select appropriate scopes for issue creation + + + + + + gh issue create - Create new issue + gh issue list - List and search issues + gh issue view - View issue details + gh issue comment - Add comment to issue + gh issue edit - Edit existing issue + gh issue close - Close an issue + gh issue reopen - Reopen closed issue + + + + gh search issues - Search issues and PRs + gh search prs - Search pull requests + gh search repos - Search repositories + + + + gh repo view - View repository info + gh repo clone - Clone repository + + + + + + When parsing YAML templates: + - Extract 'name' for template identification + - Get 'labels' array for automatic labeling + - Parse 'body' array for form elements + - Convert form elements to markdown sections + - Preserve 'required' field indicators + + + + When parsing Markdown templates: + - Check for YAML front matter + - Extract metadata (labels, assignees) + - Identify section headers + - Replace placeholder text + - Maintain formatting structure + + + + 1. Detect templates with list_files + 2. Read templates with read_file + 3. Parse structure and metadata + 4. Let user choose if multiple exist + 5. Fill template with information + 6. Create issue with template content + + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/1_mode_creation_workflow.xml b/.roo/rules-mode-writer/1_mode_creation_workflow.xml new file mode 100644 index 00000000000..77a1728599f --- /dev/null +++ b/.roo/rules-mode-writer/1_mode_creation_workflow.xml @@ -0,0 +1,301 @@ + + + This workflow guides you through creating new custom modes or editing existing modes + for the Roo Code Software, ensuring comprehensive understanding and cohesive implementation. + + + + + Determine User Intent + + Identify whether the user wants to create a new mode or edit an existing one + + + + + User mentions a specific mode by name or slug + User references a mode directory path (e.g., .roo/rules-[mode-slug]) + User asks to modify, update, enhance, or fix an existing mode + User says "edit this mode" or "change this mode" + + + + + User asks to create a new mode + User describes a new capability not covered by existing modes + User says "make a mode for" or "create a mode that" + + + + + + I want to make sure I understand correctly. Are you looking to create a brand new mode or modify an existing one? + + Create a new mode for a specific purpose + Edit an existing mode to add new capabilities + Fix issues in an existing mode + Enhance an existing mode with better workflows + + + + + + + + + + Gather Requirements for New Mode + + Understand what the user wants the new mode to accomplish + + + Ask about the mode's primary purpose and use cases + Identify what types of tasks the mode should handle + Determine what tools and file access the mode needs + Clarify any special behaviors or restrictions + + + + What is the primary purpose of this new mode? What types of tasks should it handle? + + A mode for writing and maintaining documentation + A mode for database schema design and migrations + A mode for API endpoint development and testing + A mode for performance optimization and profiling + + + + + + + Design Mode Configuration + + Create the mode definition with all required fields + + + + Unique identifier (lowercase, hyphens allowed) + Keep it short and descriptive (e.g., "api-dev", "docs-writer") + + + Display name with optional emoji + Use an emoji that represents the mode's purpose + + + Detailed description of the mode's role and expertise + + Start with "You are Roo Code, a [specialist type]..." + List specific areas of expertise + Mention key technologies or methodologies + + + + Tool groups the mode can access + + + + + + + + + + + + Clear description for the Orchestrator + Explain specific scenarios and task types + + + + Do not include customInstructions in the .roomodes configuration. + All detailed instructions should be placed in XML files within + the .roo/rules-[mode-slug]/ directory instead. + + + + + Implement File Restrictions + + Configure appropriate file access permissions + + + Restrict edit access to specific file types + +groups: + - read + - - edit + - fileRegex: \.(md|txt|rst)$ + description: Documentation files only + - command + + + + Use regex patterns to limit file editing scope + Provide clear descriptions for restrictions + Consider the principle of least privilege + + + + + Create XML Instruction Files + + Design structured instruction files in .roo/rules-[mode-slug]/ + + + Main workflow and step-by-step processes + Guidelines and conventions + Reusable code patterns and examples + Specific tool usage instructions + Complete workflow examples + + + Use semantic tag names that describe content + Nest tags hierarchically for better organization + Include code examples in CDATA sections when needed + Add comments to explain complex sections + + + + + + + Immerse in Existing Mode + + Fully understand the existing mode before making any changes + + + Locate and read the mode configuration in .roomodes + Read all XML instruction files in .roo/rules-[mode-slug]/ + Analyze the mode's current capabilities and limitations + Understand the mode's role in the broader ecosystem + + + + What specific aspects of the mode would you like to change or enhance? + + Add new capabilities or tool permissions + Fix issues with current workflows or instructions + Improve the mode's roleDefinition or whenToUse description + Enhance XML instructions for better clarity + + + + + + + Analyze Change Impact + + Understand how proposed changes will affect the mode + + + Compatibility with existing workflows + Impact on file permissions and tool access + Consistency with mode's core purpose + Integration with other modes + + + + I've analyzed the existing mode. Here's what I understand about your requested changes. Is this correct? + + Yes, that's exactly what I want to change + Mostly correct, but let me clarify some details + No, I meant something different + I'd like to add additional changes + + + + + + + Plan Modifications + + Create a detailed plan for modifying the mode + + + Identify which files need to be modified + Determine if new XML instruction files are needed + Check for potential conflicts or contradictions + Plan the order of changes for minimal disruption + + + + + Implement Changes + + Apply the planned modifications to the mode + + + Update .roomodes configuration if needed + Modify existing XML instruction files + Create new XML instruction files if required + Update examples and documentation + + + + + + + + Validate Cohesion and Consistency + + Ensure all changes are cohesive and don't contradict each other + + + + Mode slug follows naming conventions + File restrictions align with mode purpose + Tool permissions are appropriate + whenToUse clearly differentiates from other modes + + + All XML files follow consistent structure + No contradicting instructions between files + Examples align with stated workflows + Tool usage matches granted permissions + + + Mode integrates well with Orchestrator + Clear boundaries with other modes + Handoff points are well-defined + + + + + I've completed the validation checks. Would you like me to review any specific aspect in more detail? + + Review the file permission patterns + Check for workflow contradictions + Verify integration with other modes + Everything looks good, proceed to testing + + + + + + + Test and Refine + + Verify the mode works as intended + + + Mode appears in the mode list + File restrictions work correctly + Instructions are clear and actionable + Mode integrates well with Orchestrator + All examples are accurate and helpful + Changes don't break existing functionality (for edits) + New capabilities work as expected + + + + + + Create mode in .roomodes for project-specific modes + Create mode in global custom_modes.yaml for system-wide modes + Use list_files to verify .roo folder structure + Test file regex patterns with search_files + Use codebase_search to find existing mode implementations + Read all XML files in a mode directory to understand its structure + Always validate changes for cohesion and consistency + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/2_xml_structuring_best_practices.xml b/.roo/rules-mode-writer/2_xml_structuring_best_practices.xml new file mode 100644 index 00000000000..639f855c0c0 --- /dev/null +++ b/.roo/rules-mode-writer/2_xml_structuring_best_practices.xml @@ -0,0 +1,220 @@ + + + XML tags help Claude parse prompts more accurately, leading to higher-quality outputs. + This guide covers best practices for structuring mode instructions using XML. + + + + + Clearly separate different parts of your instructions and ensure well-structured content + + + Reduce errors caused by Claude misinterpreting parts of your instructions + + + Easily find, add, remove, or modify parts of instructions without rewriting everything + + + Having Claude use XML tags in its output makes it easier to extract specific parts of responses + + + + + + Use the same tag names throughout your instructions + + Always use for workflow steps, not sometimes or + + + + + Tag names should clearly describe their content + + detailed_steps + error_handling + validation_rules + + + stuff + misc + data1 + + + + + Nest tags to show relationships and structure + + + + Gather requirements + Validate inputs + + + Process data + Generate output + + + + + + + + + For step-by-step processes + + + + + For providing code examples and demonstrations + + + + + For rules and best practices + + + + + For documenting how to use specific tools + + + + + + + Use consistent indentation (2 or 4 spaces) for nested elements + + + Add line breaks between major sections for readability + + + Use XML comments to explain complex sections + + + Use CDATA for code blocks or content with special characters: + ]]> + + + Use attributes for metadata, elements for content: + + + The actual step content + + + + + + + + Avoid completely flat structures without hierarchy + +Do this +Then this +Finally this + + ]]> + + + Do this + Then this + Finally this + + + ]]> + + + + Don't mix naming conventions + + Mixing camelCase, snake_case, and kebab-case in tag names + + + Pick one convention (preferably snake_case for XML) and stick to it + + + + + Avoid tags that don't convey meaning + data, info, stuff, thing, item + user_input, validation_result, error_message, configuration + + + + + + Reference XML content in instructions: + "Using the workflow defined in <workflow> tags..." + + + Combine XML structure with other techniques like multishot prompting + + + Use XML tags in expected outputs to make parsing easier + + + Create reusable XML templates for common patterns + + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/3_mode_configuration_patterns.xml b/.roo/rules-mode-writer/3_mode_configuration_patterns.xml new file mode 100644 index 00000000000..82a5f845ac4 --- /dev/null +++ b/.roo/rules-mode-writer/3_mode_configuration_patterns.xml @@ -0,0 +1,261 @@ + + + Common patterns and templates for creating different types of modes, with examples from existing modes in the Roo-Code software. + + + + + + Modes focused on specific technical domains or tasks + + + Deep expertise in a particular area + Restricted file access based on domain + Specialized tool usage patterns + + - + You are Roo Code, an API development specialist with expertise in: + - RESTful API design and implementation + - GraphQL schema design + - API documentation with OpenAPI/Swagger + - Authentication and authorization patterns + - Rate limiting and caching strategies + - API versioning and deprecation + + You ensure APIs are: + - Well-documented and discoverable + - Following REST principles or GraphQL best practices + - Secure and performant + - Properly versioned and maintainable + whenToUse: >- + Use this mode when designing, implementing, or refactoring APIs. + This includes creating new endpoints, updating API documentation, + implementing authentication, or optimizing API performance. + groups: + - read + - - edit + - fileRegex: (api/.*\.(ts|js)|.*\.openapi\.yaml|.*\.graphql|docs/api/.*)$ + description: API implementation files, OpenAPI specs, and API documentation + - command + - mcp + ]]> + + + + + Modes that guide users through multi-step processes + + + Step-by-step workflow guidance + Heavy use of ask_followup_question + Process validation at each step + + - + You are Roo Code, a migration specialist who guides users through + complex migration processes: + - Database schema migrations + - Framework version upgrades + - API version migrations + - Dependency updates + - Breaking change resolutions + + You provide: + - Step-by-step migration plans + - Automated migration scripts + - Rollback strategies + - Testing approaches for migrations + whenToUse: >- + Use this mode when performing any kind of migration or upgrade. + This mode will analyze the current state, plan the migration, + and guide you through each step with validation. + groups: + - read + - edit + - command + ]]> + + + + + Modes focused on code analysis and reporting + + + Read-heavy operations + Limited or no edit permissions + Comprehensive reporting outputs + + - + You are Roo Code, a security analysis specialist focused on: + - Identifying security vulnerabilities + - Analyzing authentication and authorization + - Reviewing data validation and sanitization + - Checking for common security anti-patterns + - Evaluating dependency vulnerabilities + - Assessing API security + + You provide detailed security reports with: + - Vulnerability severity ratings + - Specific remediation steps + - Security best practice recommendations + whenToUse: >- + Use this mode to perform security audits on codebases. + This mode will analyze code for vulnerabilities, check + dependencies, and provide actionable security recommendations. + groups: + - read + - command + - - edit + - fileRegex: (SECURITY\.md|\.github/security/.*|docs/security/.*)$ + description: Security documentation files only + ]]> + + + + + Modes for generating new content or features + + + Broad file creation permissions + Template and boilerplate generation + Interactive design process + + - + You are Roo Code, a UI component design specialist who creates: + - Reusable React/Vue/Angular components + - Component documentation and examples + - Storybook stories + - Unit tests for components + - Accessibility-compliant interfaces + + You follow design system principles and ensure components are: + - Highly reusable and composable + - Well-documented with examples + - Fully tested + - Accessible (WCAG compliant) + - Performance optimized + whenToUse: >- + Use this mode when creating new UI components or refactoring + existing ones. This mode helps design component APIs, implement + the components, and create comprehensive documentation. + groups: + - read + - - edit + - fileRegex: (components/.*|stories/.*|__tests__/.*\.test\.(tsx?|jsx?))$ + description: Component files, stories, and component tests + - browser + - command + ]]> + + + + + + For modes that only work with documentation + + + + + For modes that work with test files + + + + + For modes that manage configuration + + + + + For modes that need broad access + + + + + + + Use lowercase with hyphens + api-dev, test-writer, docs-manager + apiDev, test_writer, DocsManager + + + + Use title case with descriptive emoji + 🔧 API Developer, 📝 Documentation Writer + api developer, DOCUMENTATION WRITER + + + + + 🧪 + 📝 + 🎨 + 🪲 + 🏗️ + 🔒 + 🔌 + 🗄️ + + ⚙️ + + + + + + + Ensure whenToUse is clear for Orchestrator mode + + Specify concrete task types the mode handles + Include trigger keywords or phrases + Differentiate from similar modes + Mention specific file types or areas + + + + + Define clear boundaries between modes + + Avoid overlapping responsibilities + Make handoff points explicit + Use switch_mode when appropriate + Document mode interactions + + + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/4_instruction_file_templates.xml b/.roo/rules-mode-writer/4_instruction_file_templates.xml new file mode 100644 index 00000000000..3afcfa28f45 --- /dev/null +++ b/.roo/rules-mode-writer/4_instruction_file_templates.xml @@ -0,0 +1,367 @@ + + + Templates and examples for creating XML instruction files that provide + detailed guidance for each mode's behavior and workflows. + + + + Number files to indicate execution order + Use descriptive names that indicate content + Keep related instructions together + + 1_workflow.xml - Main workflow and processes + 2_best_practices.xml - Guidelines and conventions + 3_common_patterns.xml - Reusable code patterns + 4_tool_usage.xml - Specific tool instructions + 5_examples.xml - Complete workflow examples + 6_error_handling.xml - Error scenarios and recovery + 7_communication.xml - User interaction guidelines + + + + + Template for main workflow files (1_workflow.xml) + + + + + Template for best practices files (2_best_practices.xml) + + + + + Template for tool usage files (4_tool_usage.xml) + + + + + Template for example files (5_examples.xml) + + + + + Template for communication guidelines (7_communication.xml) + + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/5_complete_mode_examples.xml b/.roo/rules-mode-writer/5_complete_mode_examples.xml new file mode 100644 index 00000000000..7c8f8a4cdef --- /dev/null +++ b/.roo/rules-mode-writer/5_complete_mode_examples.xml @@ -0,0 +1,214 @@ + + + + Edit the test mode to add support for performance testing and benchmarking + + + + I want to edit the test mode to add benchmark testing capabilities + + + + + Determine user intent and clarify scope + +I understand you want to edit the test mode to add performance testing capabilities. Before we proceed, let me confirm the scope of changes. What specific performance testing features do you need? + +Add benchmark testing with Vitest's bench API +Include performance profiling and memory usage tracking +Add load testing capabilities for API endpoints +All of the above - comprehensive performance testing suite + + + ]]> + User selected: Add benchmark testing with Vitest's bench API + + + + Immerse in existing test mode configuration + +.roomodes + + ]]> + Found test mode configuration with current roleDefinition and file restrictions + + + + Explore existing test mode instructions + +.roo/rules-test +true + + ]]> + +.roo/rules-test/1_workflow.xml + + ]]> + Understood current test workflows and patterns + + + + Validate changes for cohesion + +I've analyzed the test mode. Adding benchmark testing would require: +1. Updating the roleDefinition to include performance testing expertise +2. Modifying file restrictions to include .bench.ts files +3. Adding new workflow instructions for benchmark creation +4. Including Vitest bench API examples + +This aligns well with the existing testing focus. Should I proceed with all these changes? + +Yes, implement all the changes as described +Start with just the roleDefinition and file restrictions +Focus only on the workflow instructions first +Let me review the specific changes before proceeding + + + ]]> + User selected: Yes, implement all the changes as described + + + + Update mode configuration in .roomodes + +.roomodes + +<<<<<<< SEARCH + roleDefinition: |- + You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization +======= + roleDefinition: |- + You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization - Benchmark testing with Vitest bench API - Performance profiling and optimization - Memory usage analysis in tests +>>>>>>> REPLACE + + + ]]> + + + + Update file restrictions to include benchmark files + +.roomodes + +<<<<<<< SEARCH + - fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$) + description: Test files, mocks, and Vitest configuration +======= + - fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|\.bench\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$) + description: Test files, benchmarks, mocks, and Vitest configuration +>>>>>>> REPLACE + + + ]]> + + + + Create new benchmark workflow instructions + +.roo/rules-test/5_benchmark_testing.xml + + + + Guidelines for creating and maintaining performance benchmarks using Vitest bench API + + + + + Basic benchmark structure + { + bench('Array.push', () => { + const arr = []; + for (let i = 0; i < 1000; i++) { + arr.push(i); + } + }); + + bench('Array spread', () => { + let arr = []; + for (let i = 0; i < 1000; i++) { + arr = [...arr, i]; + } + }); +}); + ]]> + + + + + Use meaningful benchmark names that describe what's being measured + Include baseline comparisons when optimizing code + Run benchmarks in isolation to avoid interference + Document performance expectations and thresholds + + + +38 + + ]]> + + + + Validate all changes for consistency + +I've completed all the changes to add benchmark testing capabilities to the test mode: + +1. ✓ Updated roleDefinition to include benchmark expertise +2. ✓ Modified file restrictions to include .bench.ts files +3. ✓ Created new benchmark workflow instructions +4. ✓ Added Vitest bench API examples + +All changes are cohesive and align with the existing test mode structure. Would you like me to test any specific aspect of these changes? + +Test creating a new benchmark file to verify file permissions +Review the complete changes one more time +Everything looks good, the mode is ready +Create a simple benchmark example to test + + + ]]> + + + + + +I've successfully enhanced the test mode with benchmark testing capabilities: + +1. Updated the roleDefinition to include: + - Benchmark testing with Vitest bench API + - Performance profiling and optimization + - Memory usage analysis in tests + +2. Modified file restrictions to include .bench.ts files, allowing the mode to create and edit benchmark files + +3. Created new workflow instructions at .roo/rules-test/5_benchmark_testing.xml with: + - Basic benchmark patterns + - Best practices for performance testing + - Example code using Vitest's bench API + +All changes have been validated for cohesion and consistency with the existing test mode structure. The mode now supports comprehensive performance testing alongside its existing unit and integration testing capabilities. + + + ]]> + + + Always immerse yourself in the existing mode before making changes + Use ask_followup_question aggressively to clarify scope and validate changes + Validate all changes for cohesion and consistency + Update all relevant parts: configuration, file restrictions, and instructions + Test changes to ensure they work as expected + + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/6_mode_testing_validation.xml b/.roo/rules-mode-writer/6_mode_testing_validation.xml new file mode 100644 index 00000000000..db65b31c22b --- /dev/null +++ b/.roo/rules-mode-writer/6_mode_testing_validation.xml @@ -0,0 +1,207 @@ + + + Guidelines for testing and validating newly created modes to ensure they function correctly and integrate well with the Roo Code ecosystem. + + + + + + Mode slug is unique and follows naming conventions + No spaces, lowercase, hyphens only + + + All required fields are present and non-empty + slug, name, roleDefinition, groups + + + No customInstructions field in .roomodes + All instructions must be in XML files in .roo/rules-[slug]/ + + + File restrictions use valid regex patterns + +. +your_file_regex_here + + ]]> + + + whenToUse clearly differentiates from other modes + Compare with existing mode descriptions + + + + + + XML files are well-formed and valid + No syntax errors, proper closing tags + + + Instructions follow XML best practices + Semantic tag names, proper nesting + + + Examples use correct tool syntax + Tool parameters match current API + + + File paths in examples are consistent + Use project-relative paths + + + + + + Mode appears in mode list + Switch to the new mode and verify it loads + + + Tool permissions work as expected + Try using each tool group and verify access + + + File restrictions are enforced + Attempt to edit allowed and restricted files + + + Mode handles edge cases gracefully + Test with minimal input, errors, edge cases + + + + + + + Configuration Testing + + Verify mode appears in available modes list + Check that mode metadata displays correctly + Confirm mode can be activated + + +I've created the mode configuration. Can you see the new mode in your mode list? + +Yes, I can see the new mode and switch to it +No, the mode doesn't appear in the list +The mode appears but has errors when switching + + + ]]> + + + + Permission Testing + + + Use read tools on various files + All read operations should work + + + Try editing allowed file types + Edits succeed for matching patterns + + + Try editing restricted file types + FileRestrictionError for non-matching files + + + + + + Workflow Testing + + Execute main workflow from start to finish + Test each decision point + Verify error handling + Check completion criteria + + + + + Integration Testing + + Orchestrator mode compatibility + Mode switching functionality + Tool handoff between modes + Consistent behavior with other modes + + + + + + + Mode doesn't appear in list + + Syntax error in YAML + Invalid mode slug + File not saved + + Check YAML syntax, validate slug format + + + + File restriction not working + + Invalid regex pattern + Escaping issues in regex + Wrong file path format + + Test regex pattern, use proper escaping + + + + + Mode not following instructions + + Instructions not in .roo/rules-[slug]/ folder + XML parsing errors + Conflicting instructions + + Verify file locations and XML validity + + + + + + Verify instruction files exist in correct location + +.roo +true + + ]]> + + + + Check mode configuration syntax + +.roomodes + + ]]> + + + + Test file restriction patterns + +. +your_file_pattern_here + + ]]> + + + + + Test incrementally as you build the mode + Start with minimal configuration and add complexity + Document any special requirements or dependencies + Consider edge cases and error scenarios + Get feedback from potential users of the mode + + \ No newline at end of file diff --git a/.roo/rules-mode-writer/7_validation_cohesion_checking.xml b/.roo/rules-mode-writer/7_validation_cohesion_checking.xml new file mode 100644 index 00000000000..a327a1e4659 --- /dev/null +++ b/.roo/rules-mode-writer/7_validation_cohesion_checking.xml @@ -0,0 +1,201 @@ + + + Guidelines for thoroughly validating mode changes to ensure cohesion, + consistency, and prevent contradictions across all mode components. + + + + + + Every change must be reviewed in context of the entire mode + + + Read all existing XML instruction files + Verify new changes align with existing patterns + Check for duplicate or conflicting instructions + Ensure terminology is consistent throughout + + + + + + Use ask_followup_question extensively to clarify ambiguities + + + User's intent is unclear + Multiple interpretations are possible + Changes might conflict with existing functionality + Impact on other modes needs clarification + + +I notice this change might affect how the mode interacts with file permissions. Should we also update the file regex patterns to match? + +Yes, update the file regex to include the new file types +No, keep the current file restrictions as they are +Let me explain what file types I need to work with +Show me the current file restrictions first + + + ]]> + + + + + Actively search for and resolve contradictions + + + + Permission Mismatch + Instructions reference tools the mode doesn't have access to + Either grant the tool permission or update the instructions + + + Workflow Conflicts + Different XML files describe conflicting workflows + Consolidate workflows and ensure single source of truth + + + Role Confusion + Mode's roleDefinition doesn't match its actual capabilities + Update roleDefinition to accurately reflect the mode's purpose + + + + + + + + Before making any changes + + Read and understand all existing mode files + Create a mental model of current mode behavior + Identify potential impact areas + Ask clarifying questions about intended changes + + + + + While making changes + + Document each change and its rationale + Cross-reference with other files after each change + Verify examples still work with new changes + Update related documentation immediately + + + + + After changes are complete + + + All XML files are well-formed and valid + File naming follows established patterns + Tag names are consistent across files + No orphaned or unused instructions + + + + roleDefinition accurately describes the mode + whenToUse is clear and distinguishable + Tool permissions match instruction requirements + File restrictions align with mode purpose + Examples are accurate and functional + + + + Mode boundaries are well-defined + Handoff points to other modes are clear + No overlap with other modes' responsibilities + Orchestrator can correctly route to this mode + + + + + + + + Maintain consistent tone and terminology + + Use the same terms for the same concepts throughout + Keep instruction style consistent across files + Maintain the same level of detail in similar sections + + + + + Ensure instructions flow logically + + Prerequisites come before dependent steps + Complex concepts build on simpler ones + Examples follow the explained patterns + + + + + Ensure all aspects are covered without gaps + + Every mentioned tool has usage instructions + All workflows have complete examples + Error scenarios are addressed + + + + + + + + Before we proceed with changes, I want to ensure I understand the full scope. What is the main goal of these modifications? + + Add new functionality while keeping existing features + Fix issues with current implementation + Refactor for better organization + Expand the mode's capabilities into new areas + + + + + + + This change might affect other parts of the mode. How should we handle the impact on [specific area]? + + Update all affected areas to maintain consistency + Keep the existing behavior for backward compatibility + Create a migration path from old to new behavior + Let me review the impact first + + + + + + + I've completed the changes and validation. Which aspect would you like me to test more thoroughly? + + Test the new workflow end-to-end + Verify file permissions work correctly + Check integration with other modes + Review all changes one more time + + + + + + + + Instructions reference tools not in the mode's groups + Either add the tool group or remove the instruction + + + File regex doesn't match described file types + Update regex pattern to match intended files + + + Examples don't follow stated best practices + Update examples to demonstrate best practices + + + Duplicate instructions in different files + Consolidate to single location and reference + + + \ No newline at end of file diff --git a/.roomodes b/.roomodes index ba17940035a..01f6ed45050 100644 --- a/.roomodes +++ b/.roomodes @@ -1,4 +1,46 @@ customModes: + - slug: test + name: 🧪 Test + roleDefinition: |- + You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization + Your focus is on maintaining high test quality and coverage across the codebase, working primarily with: - Test files in __tests__ directories - Mock implementations in __mocks__ - Test utilities and helpers - Vitest configuration and setup + You ensure tests are: - Well-structured and maintainable - Following Vitest best practices - Properly typed with TypeScript - Providing meaningful coverage - Using appropriate mocking strategies + whenToUse: Use this mode when you need to write, modify, or maintain tests for the codebase. + description: Write, modify, and maintain tests. + groups: + - read + - browser + - command + - - edit + - fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$) + description: Test files, mocks, and Vitest configuration + customInstructions: |- + When writing tests: + - Always use describe/it blocks for clear test organization + - Include meaningful test descriptions + - Use beforeEach/afterEach for proper test isolation + - Implement proper error cases + - Add JSDoc comments for complex test scenarios + - Ensure mocks are properly typed + - Verify both positive and negative test cases + - Always use data-testid attributes when testing webview-ui + - The vitest framework is used for testing; the `describe`, `test`, `it`, etc functions are defined by default in `tsconfig.json` and therefore don't need to be imported + - Tests must be run from the same directory as the `package.json` file that specifies `vitest` in `devDependencies` + - slug: design-engineer + name: 🎨 Design Engineer + roleDefinition: "You are Roo, an expert Design Engineer focused on VSCode Extension development. Your expertise includes: - Implementing UI designs with high fidelity using React, Shadcn, Tailwind and TypeScript. - Ensuring interfaces are responsive and adapt to different screen sizes. - Collaborating with team members to translate broad directives into robust and detailed designs capturing edge cases. - Maintaining uniformity and consistency across the user interface." + whenToUse: Implement UI designs and ensure consistency. + description: Implement UI designs; ensure consistency. + groups: + - read + - - edit + - fileRegex: \.(css|html|json|mdx?|jsx?|tsx?|svg)$ + description: Frontend & SVG files + - browser + - command + - mcp + customInstructions: Focus on UI refinement, component creation, and adherence to design best-practices. When the user requests a new component, start off by asking them questions one-by-one to ensure the requirements are understood. Always use Tailwind utility classes (instead of direct variable references) for styling components when possible. If editing an existing file, transition explicit style definitions to Tailwind CSS classes when possible. Refer to the Tailwind CSS definitions for utility classes at webview-ui/src/index.css. Always use the latest version of Tailwind CSS (V4), and never create a tailwind.config.js file. Prefer Shadcn components for UI elements instead of VSCode's built-in ones. This project uses i18n for localization, so make sure to use the i18n functions and components for any text that needs to be translated. Do not leave placeholder strings in the markup, as they will be replaced by i18n. Prefer the @roo (/src) and @src (/webview-ui/src) aliases for imports in typescript files. Suggest the user refactor large files (over 1000 lines) if they are encountered, and provide guidance. Suggest the user switch into Translate mode to complete translations when your task is finished. + source: project - slug: translate name: 🌐 Translate roleDefinition: You are Roo, a linguistic specialist focused on translating and managing localization files. Your responsibility is to help maintain and update translation files for the application, ensuring consistency and accuracy across all language resources. @@ -31,6 +73,42 @@ customModes: - edit - command source: project + - slug: integration-tester + name: 🧪 Integration Tester + roleDefinition: |- + You are Roo, an integration testing specialist focused on VSCode E2E tests with expertise in: - Writing and maintaining integration tests using Mocha and VSCode Test framework - Testing Roo Code API interactions and event-driven workflows - Creating complex multi-step task scenarios and mode switching sequences - Validating message formats, API responses, and event emission patterns - Test data generation and fixture management - Coverage analysis and test scenario identification + Your focus is on ensuring comprehensive integration test coverage for the Roo Code extension, working primarily with: - E2E test files in apps/vscode-e2e/src/suite/ - Test utilities and helpers - API type definitions in packages/types/ - Extension API testing patterns + You ensure integration tests are: - Comprehensive and cover critical user workflows - Following established Mocha TDD patterns - Using async/await with proper timeout handling - Validating both success and failure scenarios - Properly typed with TypeScript + whenToUse: Write, modify, or maintain integration tests. + description: Write and maintain integration tests. + groups: + - read + - command + - - edit + - fileRegex: (apps/vscode-e2e/.*\.(ts|js)$|packages/types/.*\.ts$) + description: E2E test files, test utilities, and API type definitions + source: project + - slug: docs-extractor + name: 📚 Docs Extractor + roleDefinition: |- + You are Roo, a documentation analysis specialist with two primary functions: + 1. Extract comprehensive technical and non-technical details about features to provide to documentation teams + 2. Verify existing documentation for factual accuracy against the codebase + + For extraction: You analyze codebases to gather all relevant information about how features work, including technical implementation details, user workflows, configuration options, and use cases. You organize this information clearly for documentation teams to use. + + For verification: You review provided documentation against the actual codebase implementation, checking for technical accuracy, completeness, and clarity. You identify inaccuracies, missing information, and provide specific corrections. + + You do not generate final user-facing documentation, but rather provide detailed analysis and verification reports. + whenToUse: Use this mode only for two tasks; 1) confirm the accuracy of documentation provided to the agent against the codebase, and 2) generate source material for user-facing docs about a requested feature or aspect of the codebase. + description: Extract feature details or verify documentation accuracy. + groups: + - read + - - edit + - fileRegex: (EXTRACTION-.*\.md$|VERIFICATION-.*\.md$|DOCS-TEMP-.*\.md$|\.roo/docs-extractor/.*\.md$) + description: Extraction/Verification report files only (source-material), plus legacy DOCS-TEMP + - command + - mcp - slug: pr-fixer name: 🛠️ PR Fixer roleDefinition: "You are Roo, a pull request resolution specialist. Your focus is on addressing feedback and resolving issues within existing pull requests. Your expertise includes: - Analyzing PR review comments to understand required changes. - Checking CI/CD workflow statuses to identify failing tests. - Fetching and analyzing test logs to diagnose failures. - Identifying and resolving merge conflicts. - Guiding the user through the resolution process." @@ -41,6 +119,16 @@ customModes: - edit - command - mcp + - slug: issue-investigator + name: 🕵️ Issue Investigator + roleDefinition: You are Roo, a GitHub issue investigator. Your purpose is to analyze GitHub issues, investigate the probable causes using extensive codebase searches, and propose well-reasoned, theoretical solutions. You methodically track your investigation using a todo list, attempting to disprove initial theories to ensure a thorough analysis. Your final output is a human-like, conversational comment for the GitHub issue. + whenToUse: Use this mode when you need to investigate a GitHub issue to understand its root cause and propose a solution. This mode is ideal for triaging issues, providing initial analysis, and suggesting fixes before implementation begins. It uses the `gh` CLI for issue interaction. + description: Investigates GitHub issues + groups: + - read + - command + - mcp + source: project - slug: merge-resolver name: 🔀 Merge Resolver roleDefinition: |- @@ -73,39 +161,6 @@ customModes: - command - mcp source: project - - slug: docs-extractor - name: 📚 Docs Extractor - roleDefinition: |- - You are Roo Code, a codebase analyst who extracts raw facts for documentation teams. - You do NOT write documentation. You extract and organize information. - - Two functions: - 1. Extract: Gather facts about a feature/aspect from the codebase - 2. Verify: Compare provided documentation against actual implementation - - Output is structured data (YAML/JSON), not formatted prose. - No templates, no markdown formatting, no document structure decisions. - Let documentation-writer mode handle all writing. - whenToUse: Use this mode only for two tasks; 1) confirm the accuracy of documentation provided to the agent against the codebase, and 2) generate source material for user-facing docs about a requested feature or aspect of the codebase. - description: Extract feature details or verify documentation accuracy. - groups: - - read - - - edit - - fileRegex: \.roo/extraction/.*\.(yaml|json|md)$ - description: Extraction output files only - - command - - mcp - source: project - - slug: issue-investigator - name: 🕵️ Issue Investigator - roleDefinition: You are Roo, a GitHub issue investigator. Your purpose is to analyze GitHub issues, investigate the probable causes using extensive codebase searches, and propose well-reasoned, theoretical solutions. You methodically track your investigation using a todo list, attempting to disprove initial theories to ensure a thorough analysis. Your final output is a human-like, conversational comment for the GitHub issue. - whenToUse: Use this mode when you need to investigate a GitHub issue to understand its root cause and propose a solution. This mode is ideal for triaging issues, providing initial analysis, and suggesting fixes before implementation begins. It uses the `gh` CLI for issue interaction. - description: Investigates GitHub issues - groups: - - read - - command - - mcp - source: project - slug: issue-writer name: 📝 Issue Writer roleDefinition: |- @@ -128,21 +183,56 @@ customModes: - [ ] Detect repository context (OWNER/REPO, monorepo, roots) - [ ] Perform targeted codebase discovery (iteration 1) - [ ] Clarify missing details (repro or desired outcome) - [ ] Classify type (Bug | Enhancement) - [ ] Assemble Issue Body - [ ] Review and submit (Submit now | Submit now and assign to me) + [ ] Detect current repository information + [ ] Determine repository structure (monorepo/standard) + [ ] Perform initial codebase discovery + [ ] Analyze user request to determine issue type + [ ] Gather and verify additional information + [ ] Determine if user wants to contribute + [ ] Perform issue scoping (if contributing) + [ ] Draft issue content + [ ] Review and confirm with user + [ ] Create GitHub issue - whenToUse: Use this mode when you need to create a GitHub issue. Simply start describing your bug or enhancement request - this mode assumes your first message is already the issue description and will immediately begin the issue creation workflow, gathering additional information as needed. + whenToUse: Use this mode when you need to create a GitHub issue. Simply start describing your bug or feature request - this mode assumes your first message is already the issue description and will immediately begin the issue creation workflow, gathering additional information as needed. description: Create well-structured GitHub issues. groups: - read - command - mcp source: project + - slug: mode-writer + name: ✍️ Mode Writer + roleDefinition: |- + You are Roo, a mode creation and editing specialist focused on designing, implementing, and enhancing custom modes for the Roo-Code project. Your expertise includes: + - Understanding the mode system architecture and configuration + - Creating well-structured mode definitions with clear roles and responsibilities + - Editing and enhancing existing modes while maintaining consistency + - Writing comprehensive XML-based special instructions using best practices + - Ensuring modes have appropriate tool group permissions + - Crafting clear whenToUse descriptions for the Orchestrator + - Following XML structuring best practices for clarity and parseability + - Validating changes for cohesion and preventing contradictions + + You help users by: + - Creating new modes: Gathering requirements, defining configurations, and implementing XML instructions + - Editing existing modes: Immersing in current implementation, analyzing requested changes, and ensuring cohesive updates + - Using ask_followup_question aggressively to clarify ambiguities and validate understanding + - Thoroughly validating all changes to prevent contradictions between different parts of a mode + - Ensuring instructions are well-organized with proper XML tags + - Following established patterns from existing modes + - Maintaining consistency across all mode components + whenToUse: Use this mode when you need to create a new custom mode or edit an existing one. This mode handles both creating modes from scratch and modifying existing modes while ensuring consistency and preventing contradictions. + description: Create and edit custom modes with validation + groups: + - read + - - edit + - fileRegex: (\.roomodes$|\.roo/.*\.xml$|\.yaml$) + description: Mode configuration files and XML instructions + - command + - mcp + source: project diff --git a/CHANGELOG.md b/CHANGELOG.md index e006ce210fd..4d932eae0d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,84 +1,5 @@ # Roo Code Changelog -## [3.47.3] - 2026-02-06 - -- Remove "Enable URL context" and "Enable Grounding with Google search" checkboxes that are no longer needed (PR #11253 by @roomote) -- Revert refactor that appended environment details into existing blocks, restoring original behavior (PR #11256 by @mrubens) -- Revert removal of stripAppendedEnvironmentDetails and helpers, restoring necessary utility functions (PR #11255 by @mrubens) - -## [3.47.2] - 2026-02-05 - -- Add support for .agents/skills directory (PR #11181 by @roomote) -- Fix: Restore Gemini thought signature round-tripping after AI SDK migration (PR #11237 by @hannesrudolph) -- Fix: Capture and round-trip thinking signature for Bedrock Claude (PR #11238 by @hannesrudolph) - -## [3.47.1] - 2026-02-05 - -- Fix: Correct Bedrock model ID for Claude Opus 4.6, resolving model selection issues for Bedrock users (#11231 by @cogwirrel, PR #11232 by @roomote) -- Fix: Guard against empty-string baseURL in provider constructors, preventing connection errors when baseURL is accidentally set to empty string (PR #11233 by @hannesrudolph) -- Chore: Remove unused stripAppendedEnvironmentDetails and helpers to clean up codebase (#11228 by @hannesrudolph, PR #11226 by @hannesrudolph) - -## [3.47.0] - 2026-02-05 - -![3.47.0 Release - Claude Opus 4.6 & GPT-5.3-Codex](/releases/3.47.0-release.png) - -- Add Claude Opus 4.6 support across all providers (#11223 by @hannesrudolph, PR #11224 by @hannesrudolph and @PeterDaveHello) -- Add GPT-5.3-Codex model to OpenAI - ChatGPT provider (PR #11225 by @roomote) -- Migrate Gemini and Vertex providers to AI SDK for improved reliability and consistency (PR #11180 by @daniel-lxs) -- Improve Skills and Slash Commands settings UI with multi-mode support (PR #11157 by @brunobergher) -- Add support for AGENTS.local.md personal override files (PR #11183 by @roomote) -- Add Kimi K2.5 model to Fireworks provider (PR #11177 by @daniel-lxs) -- Improve CLI dev experience and Roo provider API key support (PR #11203 by @cte) -- Fix: Preserve reasoning parts in AI SDK message conversion (#11199 by @hannesrudolph, PR #11217 by @hannesrudolph) -- Refactor: Append environment details into existing blocks for cleaner context (#11200 by @hannesrudolph, PR #11198 by @hannesrudolph) -- Fix: Resolve race condition causing provider switch during CLI mode changes (PR #11205 by @cte) -- Roo Code CLI v0.0.50 (PR #11204 by @cte) -- Chore: Remove dead toolFormat code from getEnvironmentDetails (#11206 by @hannesrudolph, PR #11207 by @roomote) -- Refactor: Simplify docs-extractor mode to focus on raw fact extraction (PR #11129 by @hannesrudolph) -- Revert then re-land AI SDK reasoning fix (PR #11216 by @mrubens, PR #11196 by @hannesrudolph) - -## [3.46.2] - 2026-02-03 - -- Fix: Queue messages during command execution instead of losing them (PR #11140 by @mrubens) -- Fix: Transform tool blocks to text before condensing to prevent context corruption (PR #10975 by @daniel-lxs) -- Fix: Add image content support to MCP tool responses (PR #10874 by @roomote) -- Fix: Remove deprecated text-embedding-004 and migrate code index to gemini-embedding-001 (PR #11038 by @roomote) -- Feat: Use custom Base URL for OpenRouter model list fetch (#11150 by @sebastianlang84, PR #11154 by @roomote) -- Feat: Migrate Mistral provider to AI SDK (PR #11089 by @daniel-lxs) -- Feat: Migrate SambaNova provider to AI SDK (PR #11153 by @roomote) -- Feat: Migrate xAI provider to AI SDK (PR #11158 by @roomote) -- Chore: Remove Feature Request from issue template options (PR #11141 by @roomote) -- Fix: IPC improvements for task cancellation and queued message handling (PR #11162 by @cte) - -## [3.46.1] - 2026-01-30 - -- Fix: Sanitize tool_use_id in tool_result blocks to match API history, preventing message format errors (PR #11131 by @daniel-lxs) -- Add: Mode dropdown to change skill mode dynamically, allowing more flexible skill configuration (PR #11102 by @SannidhyaSah) -- Add: Import settings option in the initial welcome screen for easier onboarding (#10992 by @emeraldcheshire, PR #10994 by @roomote) -- Chore: Treat extension .env as optional to simplify development setup (PR #11116 by @hannesrudolph) - -## [3.46.0] - 2026-01-30 - -![3.46.0 Release - Parallel Processing Power](/releases/3.46.0-release.png) - -- Parallel tool calls enabled by default for improved performance (PR #11031 by @daniel-lxs) -- Codex-inspired read_file refactor introduces indentation mode for extracting complete semantic code blocks without mid-function truncation, ideal when targeting specific lines from search results or errors (#10239 by @pwilkin, PR #10981 by @hannesrudolph) -- Lossless terminal output with new read_command_output tool allows retrieving full command output from truncated executions with pagination and regex filtering (#10941 by @hannesrudolph, PR #10944 by @hannesrudolph) -- New skill system replaces fetch_instructions with a dedicated skill tool and built-in skills for create-mcp-server and create-mode, with configurable skill locations and mandatory skill checks (#11062 by @hannesrudolph, PR #11084 by @hannesrudolph) -- Skills management UI added to settings panel for managing workspace and global skills (#10513 by @SannidhyaSah, PR #10844 by @SannidhyaSah) -- AI SDK provider migrations: Moonshot (PR #11063 by @daniel-lxs), DeepSeek (PR #11079 by @daniel-lxs), Cerebras (PR #11086 by @daniel-lxs), Groq (PR #11088 by @daniel-lxs), and Fireworks (PR #11118 by @daniel-lxs) now use the AI SDK for better streaming and tool support -- Add OpenAI-compatible base provider infrastructure for AI SDK migrations (PR #11063 by @daniel-lxs) -- Add AI SDK dependencies and message conversion utilities (PR #11047 by @daniel-lxs) -- React Compiler integration added to webview-ui for automatic memoization and performance improvements (#9916 by @In-line, PR #9565 by @In-line) -- Fix: Include reserved output tokens in task header percentage calculation (PR #11034 by @app/roomote) -- Fix: Calculate header percentage based on available input space (PR #11054 by @app/roomote) -- Fix: Prevent time-travel bug in parallel tool calling (PR #11046 by @daniel-lxs) -- Docs: Clarify read_command_output search param should be omitted when not filtering (PR #11056 by @hannesrudolph) -- Add pnpm serve command for code-server development (PR #10964 by @mrubens) -- Update Next.js to latest version (PR #11108 by @cte) -- Replace bespoke navigation menu with shadcn navigation menu on website (PR #11117 by @app/roomote) -- Add Linear integration marketing page to website (PR #11028 by @app/roomote) - ## [3.45.0] - 2026-01-27 ![3.45.0 Release - Smart Code Folding](/releases/3.45.0-release.png) diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md index ae12d4591b3..0babc28fd80 100644 --- a/apps/cli/CHANGELOG.md +++ b/apps/cli/CHANGELOG.md @@ -5,52 +5,6 @@ All notable changes to the `@roo-code/cli` package will be documented in this fi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.0.53] - 2026-02-12 - -### Changed - -- **Auto-Approve by Default**: The CLI now auto-approves all actions (tools, commands, browser, MCP) by default. Followup questions auto-select the first suggestion after a 60-second timeout. -- **New `--require-approval` Flag**: Replaced `-y`/`--yes`/`--dangerously-skip-permissions` flags with a new `-a, --require-approval` flag for users who want manual approval prompts before actions execute. - -### Fixed - -- Spamming the escape key to cancel a running task no longer crashes the cli. - -## [0.0.52] - 2026-02-09 - -### Added - -- **Linux Support**: Added support for `linux-arm64`. - -## [0.0.51] - 2026-02-06 - -### Changed - -- **Default Model Update**: Changed the default model from Opus 4.5 to Opus 4.6 for improved performance and capabilities - -## [0.0.50] - 2026-02-05 - -### Added - -- **Linux Support**: The CLI now supports Linux platforms in addition to macOS -- **Roo Provider API Key Support**: Allow `--api-key` flag and `ROO_API_KEY` environment variable for the roo provider instead of requiring cloud auth token -- **Exit on Error**: New `--exit-on-error` flag to exit immediately on API request errors instead of retrying, useful for CI/CD pipelines - -### Changed - -- **Improved Dev Experience**: Dev scripts now use `tsx` for running directly from source without building first -- **Path Resolution Fixes**: Fixed path resolution in [`version.ts`](src/lib/utils/version.ts), [`extension.ts`](src/lib/utils/extension.ts), and [`extension-host.ts`](src/agent/extension-host.ts) to work from both source and bundled locations -- **Debug Logging**: Debug log file (`~/.roo/cli-debug.log`) is now disabled by default unless `--debug` flag is passed -- Updated README with complete environment variable table and dev workflow documentation - -### Fixed - -- Corrected example in install script - -### Removed - -- Dropped macOS 13 support - ## [0.0.49] - 2026-01-18 ### Added @@ -78,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Skip onboarding flow when a provider is explicitly specified via `--provider` flag or saved in settings -- Unified permission flags: Combined approval-skipping flags into a single option for Claude Code-like CLI compatibility +- Unified permission flags: Combined `-y`, `--yes`, and `--dangerously-skip-permissions` into a single option for Claude Code-like CLI compatibility - Improved Roo Code Router authentication flow and error messaging ### Fixed diff --git a/apps/cli/README.md b/apps/cli/README.md index 0e49140b91d..8814c68702d 100644 --- a/apps/cli/README.md +++ b/apps/cli/README.md @@ -19,7 +19,7 @@ curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/i **Requirements:** - Node.js 20 or higher -- macOS Apple Silicon (M1/M2/M3/M4) or Linux x64 +- macOS (Intel or Apple Silicon) or Linux (x64 or ARM64) **Custom installation directory:** @@ -66,39 +66,40 @@ pnpm --filter @roo-code/cli build ### Interactive Mode (Default) -By default, the CLI auto-approves actions and runs in interactive TUI mode: +By default, the CLI prompts for approval before executing actions: ```bash export OPENROUTER_API_KEY=sk-or-v1-... -roo "What is this project?" -w ~/Documents/my-project +roo "What is this project?" -w ~/Documents/my-project ``` You can also run without a prompt and enter it interactively in TUI mode: ```bash -roo -w ~/Documents/my-project +roo ~/Documents/my-project ``` In interactive mode: -- Tool executions are auto-approved -- Commands are auto-approved -- Followup questions show suggestions with a 60-second timeout, then auto-select the first suggestion -- Browser and MCP actions are auto-approved +- Tool executions prompt for yes/no approval +- Commands prompt for yes/no approval +- Followup questions show suggestions and wait for user input +- Browser and MCP actions prompt for approval -### Approval-Required Mode (`--require-approval`) +### Non-Interactive Mode (`-y`) -If you want manual approval prompts, enable approval-required mode: +For automation and scripts, use `-y` to auto-approve all actions: ```bash -roo "Refactor the utils.ts file" --require-approval -w ~/Documents/my-project +roo "Refactor the utils.ts file" -y -w ~/Documents/my-project ``` -In approval-required mode: +In non-interactive mode: -- Tool, command, browser, and MCP actions prompt for yes/no approval -- Followup questions wait for manual input (no auto-timeout) +- Tool, command, browser, and MCP actions are auto-approved +- Followup questions show a 60-second timeout, then auto-select the first suggestion +- Typing any key cancels the timeout and allows manual input ### Roo Code Cloud Authentication @@ -146,23 +147,21 @@ Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when yo ## Options -| Option | Description | Default | -| --------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------- | -| `[prompt]` | Your prompt (positional argument, optional) | None | -| `--prompt-file ` | Read prompt from a file instead of command line argument | None | -| `-w, --workspace ` | Workspace path to operate in | Current directory | -| `-p, --print` | Print response and exit (non-interactive mode) | `false` | -| `-e, --extension ` | Path to the extension bundle directory | Auto-detected | -| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` | -| `-a, --require-approval` | Require manual approval before actions execute | `false` | -| `-k, --api-key ` | API key for the LLM provider | From env var | -| `--provider ` | API provider (roo, anthropic, openai, openrouter, etc.) | `openrouter` (or `roo` if authenticated) | -| `-m, --model ` | Model to use | `anthropic/claude-opus-4.6` | -| `--mode ` | Mode to start in (code, architect, ask, debug, etc.) | `code` | -| `-r, --reasoning-effort ` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` | -| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` | -| `--oneshot` | Exit upon task completion | `false` | -| `--output-format ` | Output format with `--print`: `text`, `json`, or `stream-json` | `text` | +| Option | Description | Default | +| --------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------- | +| `[prompt]` | Your prompt (positional argument, optional) | None | +| `-w, --workspace ` | Workspace path to operate in | Current directory | +| `-e, --extension ` | Path to the extension bundle directory | Auto-detected | +| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` | +| `-x, --exit-on-complete` | Exit the process when task completes (useful for testing) | `false` | +| `-y, --yes` | Non-interactive mode: auto-approve all actions | `false` | +| `-k, --api-key ` | API key for the LLM provider | From env var | +| `-p, --provider ` | API provider (anthropic, openai, openrouter, etc.) | `openrouter` | +| `-m, --model ` | Model to use | `anthropic/claude-sonnet-4.5` | +| `-M, --mode ` | Mode to start in (code, architect, ask, debug, etc.) | `code` | +| `-r, --reasoning-effort ` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` | +| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` | +| `--no-tui` | Disable TUI, use plain text output | `false` | ## Auth Commands @@ -176,14 +175,13 @@ Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when yo The CLI will look for API keys in environment variables if not provided via `--api-key`: -| Provider | Environment Variable | -| ----------------- | --------------------------- | -| roo | `ROO_API_KEY` | -| anthropic | `ANTHROPIC_API_KEY` | -| openai-native | `OPENAI_API_KEY` | -| openrouter | `OPENROUTER_API_KEY` | -| gemini | `GOOGLE_API_KEY` | -| vercel-ai-gateway | `VERCEL_AI_GATEWAY_API_KEY` | +| Provider | Environment Variable | +| ------------- | -------------------- | +| anthropic | `ANTHROPIC_API_KEY` | +| openai | `OPENAI_API_KEY` | +| openrouter | `OPENROUTER_API_KEY` | +| google/gemini | `GOOGLE_API_KEY` | +| ... | ... | **Authentication Environment Variables:** @@ -233,8 +231,8 @@ The CLI will look for API keys in environment variables if not provided via `--a ## Development ```bash -# Run directly from source (no build required) -pnpm dev --provider roo --api-key $ROO_API_KEY --print "Hello" +# Watch mode for development +pnpm dev # Run tests pnpm test @@ -246,41 +244,19 @@ pnpm check-types pnpm lint ``` -By default the `start` script points `ROO_CODE_PROVIDER_URL` at `http://localhost:8080/proxy` for local development. To point at the production API instead, override the environment variable: - -```bash -ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy pnpm dev --provider roo --api-key $ROO_API_KEY --print "Hello" -``` - ## Releasing -Official releases are created via the GitHub Actions workflow at `.github/workflows/cli-release.yml`. - -To trigger a release: - -1. Go to **Actions** → **CLI Release** -2. Click **Run workflow** -3. Optionally specify a version (defaults to `package.json` version) -4. Click **Run workflow** - -The workflow will: - -1. Build the CLI on all platforms (macOS Apple Silicon, Linux x64) -2. Create platform-specific tarballs with bundled ripgrep -3. Verify each tarball -4. Create a GitHub release with all tarballs attached - -### Local Builds - -For local development and testing, use the build script: +To create a new release, execute the /cli-release slash command: ```bash -# Build tarball for your current platform -./apps/cli/scripts/build.sh +roo "/cli-release" -w ~/Documents/Roo-Code -y +``` -# Build and install locally -./apps/cli/scripts/build.sh --install +The workflow will: -# Fast build (skip verification) -./apps/cli/scripts/build.sh --skip-verify -``` +1. Bump the version +2. Update the CHANGELOG +3. Build the extension and CLI +4. Create a platform-specific tarball (for your current OS/architecture) +5. Test the install script +6. Create a GitHub release with the tarball attached diff --git a/apps/cli/docs/AGENT_LOOP.md b/apps/cli/docs/AGENT_LOOP.md index a512d47a500..a7b1d9eed40 100644 --- a/apps/cli/docs/AGENT_LOOP.md +++ b/apps/cli/docs/AGENT_LOOP.md @@ -242,8 +242,7 @@ Routes asks to appropriate handlers: - Uses type guards: `isIdleAsk()`, `isInteractiveAsk()`, etc. - Coordinates between `OutputManager` and `PromptManager` -- By default, the CLI auto-approves tool/command/browser/MCP actions -- In `--require-approval` mode, those actions prompt for manual approval +- In non-interactive mode (`-y` flag), auto-approves everything ### OutputManager @@ -321,7 +320,7 @@ if (isInteractiveAsk(ask)) { Enable with `-d` flag. Logs go to `~/.roo/cli-debug.log`: ```bash -roo -d -P "Build something" --no-tui +roo -d -y -P "Build something" --no-tui ``` View logs: diff --git a/apps/cli/install.sh b/apps/cli/install.sh index 2576ec6cce8..1b01e51aa58 100755 --- a/apps/cli/install.sh +++ b/apps/cli/install.sh @@ -278,7 +278,7 @@ print_success() { echo "" echo " ${BOLD}Example:${NC}" echo " export OPENROUTER_API_KEY=sk-or-v1-..." - echo " cd ~/my-project && roo \"What is this project?\"" + echo " roo ~/my-project -P \"What is this project?\"" echo "" } diff --git a/apps/cli/package.json b/apps/cli/package.json index 028d024e810..6348bbe020a 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "@roo-code/cli", - "version": "0.0.53", + "version": "0.0.49", "description": "Roo Code CLI - Run the Roo Code agent from the command line", "private": true, "type": "module", @@ -15,8 +15,11 @@ "test": "vitest run", "build": "tsup", "build:extension": "pnpm --filter roo-cline bundle", - "dev": "ROO_AUTH_BASE_URL=https://app.roocode.com ROO_SDK_BASE_URL=https://cloud-api.roocode.com ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy tsx src/index.ts", - "dev:local": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy tsx src/index.ts", + "build:all": "pnpm --filter roo-cline bundle && tsup", + "dev": "tsup --watch", + "start": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy node dist/index.js", + "start:production": "node dist/index.js", + "release": "scripts/release.sh", "clean": "rimraf dist .turbo" }, "dependencies": { diff --git a/apps/cli/scripts/build.sh b/apps/cli/scripts/build.sh deleted file mode 100755 index 97a33c384c8..00000000000 --- a/apps/cli/scripts/build.sh +++ /dev/null @@ -1,343 +0,0 @@ -#!/bin/bash -# Roo Code CLI Local Build Script -# -# Usage: -# ./apps/cli/scripts/build.sh [options] -# -# Options: -# --install Install locally after building -# --skip-verify Skip end-to-end verification tests (faster builds) -# -# Examples: -# ./apps/cli/scripts/build.sh # Build for local testing -# ./apps/cli/scripts/build.sh --install # Build and install locally -# ./apps/cli/scripts/build.sh --skip-verify # Fast local build -# -# This script builds the CLI for your current platform. For official releases -# with multi-platform support, use the GitHub Actions workflow instead: -# .github/workflows/cli-release.yml -# -# Prerequisites: -# - pnpm installed -# - Run from the monorepo root directory - -set -e - -# Parse arguments -LOCAL_INSTALL=false -SKIP_VERIFY=false - -while [[ $# -gt 0 ]]; do - case $1 in - --install) - LOCAL_INSTALL=true - shift - ;; - --skip-verify) - SKIP_VERIFY=true - shift - ;; - -*) - echo "Unknown option: $1" >&2 - exit 1 - ;; - *) - shift - ;; - esac -done - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -BOLD='\033[1m' -NC='\033[0m' - -info() { printf "${GREEN}==>${NC} %s\n" "$1"; } -warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; } -error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; } -step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; } - -# Get script directory and repo root -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" -CLI_DIR="$REPO_ROOT/apps/cli" - -# Detect current platform -detect_platform() { - OS=$(uname -s | tr '[:upper:]' '[:lower:]') - ARCH=$(uname -m) - - case "$OS" in - darwin) OS="darwin" ;; - linux) OS="linux" ;; - *) error "Unsupported OS: $OS" ;; - esac - - case "$ARCH" in - x86_64|amd64) ARCH="x64" ;; - arm64|aarch64) ARCH="arm64" ;; - *) error "Unsupported architecture: $ARCH" ;; - esac - - PLATFORM="${OS}-${ARCH}" -} - -# Check prerequisites -check_prerequisites() { - step "1/6" "Checking prerequisites..." - - if ! command -v pnpm &> /dev/null; then - error "pnpm is not installed." - fi - - if ! command -v node &> /dev/null; then - error "Node.js is not installed." - fi - - info "Prerequisites OK" -} - -# Get version -get_version() { - VERSION=$(node -p "require('$CLI_DIR/package.json').version") - GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") - VERSION="${VERSION}-local.${GIT_SHORT_HASH}" - - info "Version: $VERSION" -} - -# Build everything -build() { - step "2/6" "Building extension bundle..." - cd "$REPO_ROOT" - pnpm bundle - - step "3/6" "Building CLI..." - pnpm --filter @roo-code/cli build - - info "Build complete" -} - -# Create release tarball -create_tarball() { - step "4/6" "Creating release tarball for $PLATFORM..." - - RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}" - TARBALL="roo-cli-${PLATFORM}.tar.gz" - - # Clean up any previous build - rm -rf "$RELEASE_DIR" - rm -f "$REPO_ROOT/$TARBALL" - - # Create directory structure - mkdir -p "$RELEASE_DIR/bin" - mkdir -p "$RELEASE_DIR/lib" - mkdir -p "$RELEASE_DIR/extension" - - # Copy CLI dist files - info "Copying CLI files..." - cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/" - - # Create package.json for npm install - info "Creating package.json..." - node -e " - const pkg = require('$CLI_DIR/package.json'); - const newPkg = { - name: '@roo-code/cli', - version: '$VERSION', - type: 'module', - dependencies: { - '@inkjs/ui': pkg.dependencies['@inkjs/ui'], - '@trpc/client': pkg.dependencies['@trpc/client'], - 'commander': pkg.dependencies.commander, - 'fuzzysort': pkg.dependencies.fuzzysort, - 'ink': pkg.dependencies.ink, - 'p-wait-for': pkg.dependencies['p-wait-for'], - 'react': pkg.dependencies.react, - 'superjson': pkg.dependencies.superjson, - 'zustand': pkg.dependencies.zustand - } - }; - console.log(JSON.stringify(newPkg, null, 2)); - " > "$RELEASE_DIR/package.json" - - # Copy extension bundle - info "Copying extension bundle..." - cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/" - - # Add package.json to extension directory for CommonJS - echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json" - - # Find and copy ripgrep binary - info "Looking for ripgrep binary..." - RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1) - if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then - info "Found ripgrep at: $RIPGREP_PATH" - mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin" - cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/" - chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg" - mkdir -p "$RELEASE_DIR/bin" - cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/" - chmod +x "$RELEASE_DIR/bin/rg" - else - warn "ripgrep binary not found - users will need ripgrep installed" - fi - - # Create the wrapper script - info "Creating wrapper script..." - cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF' -#!/usr/bin/env node - -import { fileURLToPath } from 'url'; -import { dirname, join } from 'path'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -// Set environment variables for the CLI -process.env.ROO_CLI_ROOT = join(__dirname, '..'); -process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension'); -process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg'); - -// Import and run the actual CLI -await import(join(__dirname, '..', 'lib', 'index.js')); -WRAPPER_EOF - - chmod +x "$RELEASE_DIR/bin/roo" - - # Create empty .env file - touch "$RELEASE_DIR/.env" - - # Create tarball - info "Creating tarball..." - cd "$REPO_ROOT" - tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")" - - # Clean up release directory - rm -rf "$RELEASE_DIR" - - # Show size - TARBALL_PATH="$REPO_ROOT/$TARBALL" - TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}') - info "Created: $TARBALL ($TARBALL_SIZE)" -} - -# Verify local installation -verify_local_install() { - if [ "$SKIP_VERIFY" = true ]; then - step "5/6" "Skipping verification (--skip-verify)" - return - fi - - step "5/6" "Verifying installation..." - - VERIFY_DIR="$REPO_ROOT/.verify-release" - VERIFY_INSTALL_DIR="$VERIFY_DIR/cli" - VERIFY_BIN_DIR="$VERIFY_DIR/bin" - - rm -rf "$VERIFY_DIR" - mkdir -p "$VERIFY_DIR" - - TARBALL_PATH="$REPO_ROOT/$TARBALL" - - ROO_LOCAL_TARBALL="$TARBALL_PATH" \ - ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \ - ROO_BIN_DIR="$VERIFY_BIN_DIR" \ - ROO_VERSION="$VERSION" \ - "$CLI_DIR/install.sh" || { - rm -rf "$VERIFY_DIR" - error "Installation verification failed!" - } - - # Test --help - if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then - rm -rf "$VERIFY_DIR" - error "CLI --help check failed!" - fi - info "CLI --help check passed" - - # Test --version - if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then - rm -rf "$VERIFY_DIR" - error "CLI --version check failed!" - fi - info "CLI --version check passed" - - cd "$REPO_ROOT" - rm -rf "$VERIFY_DIR" - - info "Verification passed!" -} - -# Install locally -install_local() { - if [ "$LOCAL_INSTALL" = false ]; then - step "6/6" "Skipping install (use --install to auto-install)" - return - fi - - step "6/6" "Installing locally..." - - TARBALL_PATH="$REPO_ROOT/$TARBALL" - - ROO_LOCAL_TARBALL="$TARBALL_PATH" \ - ROO_VERSION="$VERSION" \ - "$CLI_DIR/install.sh" || { - error "Local installation failed!" - } - - info "Local installation complete!" -} - -# Print summary -print_summary() { - echo "" - printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n" - echo "" - echo " Tarball: $REPO_ROOT/$TARBALL" - echo "" - - if [ "$LOCAL_INSTALL" = true ]; then - echo " Installed to: ~/.roo/cli" - echo " Binary: ~/.local/bin/roo" - echo "" - echo " Test it out:" - echo " roo --version" - echo " roo --help" - else - echo " To install manually:" - echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh" - echo "" - echo " Or re-run with --install:" - echo " ./apps/cli/scripts/build.sh --install" - fi - echo "" - echo " For official multi-platform releases, use the GitHub Actions workflow:" - echo " .github/workflows/cli-release.yml" - echo "" -} - -# Main -main() { - echo "" - printf "${BLUE}${BOLD}" - echo " ╭─────────────────────────────────╮" - echo " │ Roo Code CLI Local Build │" - echo " ╰─────────────────────────────────╯" - printf "${NC}" - echo "" - - detect_platform - check_prerequisites - get_version - build - create_tarball - verify_local_install - install_local - print_summary -} - -main diff --git a/apps/cli/scripts/release.sh b/apps/cli/scripts/release.sh new file mode 100755 index 00000000000..7e736db3dbc --- /dev/null +++ b/apps/cli/scripts/release.sh @@ -0,0 +1,711 @@ +#!/bin/bash +# Roo Code CLI Release Script +# +# Usage: +# ./apps/cli/scripts/release.sh [options] [version] +# +# Options: +# --dry-run Run all steps except creating the GitHub release +# --local Build for local testing only (no GitHub checks, no changelog prompts) +# --install Install locally after building (only with --local) +# --skip-verify Skip end-to-end verification tests (faster local builds) +# +# Examples: +# ./apps/cli/scripts/release.sh # Use version from package.json +# ./apps/cli/scripts/release.sh 0.1.0 # Specify version +# ./apps/cli/scripts/release.sh --dry-run # Test the release flow without pushing +# ./apps/cli/scripts/release.sh --dry-run 0.1.0 # Dry run with specific version +# ./apps/cli/scripts/release.sh --local # Build for local testing +# ./apps/cli/scripts/release.sh --local --install # Build and install locally +# ./apps/cli/scripts/release.sh --local --skip-verify # Fast local build +# +# This script: +# 1. Builds the extension and CLI +# 2. Creates a tarball for the current platform +# 3. Creates a GitHub release and uploads the tarball (unless --dry-run or --local) +# +# Prerequisites: +# - GitHub CLI (gh) installed and authenticated (not needed for --local) +# - pnpm installed +# - Run from the monorepo root directory + +set -e + +# Parse arguments +DRY_RUN=false +LOCAL_BUILD=false +LOCAL_INSTALL=false +SKIP_VERIFY=false +VERSION_ARG="" + +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRY_RUN=true + shift + ;; + --local) + LOCAL_BUILD=true + shift + ;; + --install) + LOCAL_INSTALL=true + shift + ;; + --skip-verify) + SKIP_VERIFY=true + shift + ;; + -*) + echo "Unknown option: $1" >&2 + exit 1 + ;; + *) + VERSION_ARG="$1" + shift + ;; + esac +done + +# Validate option combinations +if [ "$LOCAL_INSTALL" = true ] && [ "$LOCAL_BUILD" = false ]; then + echo "Error: --install can only be used with --local" >&2 + exit 1 +fi + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +BOLD='\033[1m' +NC='\033[0m' + +info() { printf "${GREEN}==>${NC} %s\n" "$1"; } +warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; } +error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; } +step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; } + +# Get script directory and repo root +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" +CLI_DIR="$REPO_ROOT/apps/cli" + +# Detect current platform +detect_platform() { + OS=$(uname -s | tr '[:upper:]' '[:lower:]') + ARCH=$(uname -m) + + case "$OS" in + darwin) OS="darwin" ;; + linux) OS="linux" ;; + *) error "Unsupported OS: $OS" ;; + esac + + case "$ARCH" in + x86_64|amd64) ARCH="x64" ;; + arm64|aarch64) ARCH="arm64" ;; + *) error "Unsupported architecture: $ARCH" ;; + esac + + PLATFORM="${OS}-${ARCH}" +} + +# Check prerequisites +check_prerequisites() { + step "1/8" "Checking prerequisites..." + + # Skip GitHub CLI checks for local builds + if [ "$LOCAL_BUILD" = false ]; then + if ! command -v gh &> /dev/null; then + error "GitHub CLI (gh) is not installed. Install it with: brew install gh" + fi + + if ! gh auth status &> /dev/null; then + error "GitHub CLI is not authenticated. Run: gh auth login" + fi + fi + + if ! command -v pnpm &> /dev/null; then + error "pnpm is not installed." + fi + + if ! command -v node &> /dev/null; then + error "Node.js is not installed." + fi + + info "Prerequisites OK" +} + +# Get version +get_version() { + if [ -n "$VERSION_ARG" ]; then + VERSION="$VERSION_ARG" + else + VERSION=$(node -p "require('$CLI_DIR/package.json').version") + fi + + # For local builds, append a local suffix with git short hash + # This creates versions like: 0.1.0-local.abc1234 + if [ "$LOCAL_BUILD" = true ]; then + GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") + # Only append suffix if not already a local version + if ! echo "$VERSION" | grep -qE '\-local\.'; then + VERSION="${VERSION}-local.${GIT_SHORT_HASH}" + fi + fi + + # Validate semver format (allow -local.hash suffix) + if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then + error "Invalid version format: $VERSION (expected semver like 0.1.0)" + fi + + TAG="cli-v$VERSION" + info "Version: $VERSION (tag: $TAG)" +} + +# Extract changelog content for a specific version +# Returns the content between the version header and the next version header (or EOF) +get_changelog_content() { + CHANGELOG_FILE="$CLI_DIR/CHANGELOG.md" + + if [ ! -f "$CHANGELOG_FILE" ]; then + warn "No CHANGELOG.md found at $CHANGELOG_FILE" + CHANGELOG_CONTENT="" + return + fi + + # Try to find the version section (handles both "[0.0.43]" and "[0.0.43] - date" formats) + # Also handles "Unreleased" marker + VERSION_PATTERN="^\#\# \[${VERSION}\]" + + # Check if the version exists in the changelog + if ! grep -qE "$VERSION_PATTERN" "$CHANGELOG_FILE"; then + warn "No changelog entry found for version $VERSION" + # Skip prompts for local builds + if [ "$LOCAL_BUILD" = true ]; then + info "Skipping changelog prompt for local build" + CHANGELOG_CONTENT="" + return + fi + warn "Please add an entry to $CHANGELOG_FILE before releasing" + echo "" + echo "Expected format:" + echo " ## [$VERSION] - $(date +%Y-%m-%d)" + echo " " + echo " ### Added" + echo " - Your changes here" + echo "" + read -p "Continue without changelog content? [y/N] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + error "Aborted. Please add a changelog entry and try again." + fi + CHANGELOG_CONTENT="" + return + fi + + # Extract content between this version and the next version header (or EOF) + # Uses awk to capture everything between ## [VERSION] and the next ## [ + # Using index() with "[VERSION]" ensures exact matching (1.0.1 won't match 1.0.10) + CHANGELOG_CONTENT=$(awk -v version="$VERSION" ' + BEGIN { found = 0; content = ""; target = "[" version "]" } + /^## \[/ { + if (found) { exit } + if (index($0, target) > 0) { found = 1; next } + } + found { content = content $0 "\n" } + END { print content } + ' "$CHANGELOG_FILE") + + # Trim leading/trailing whitespace + CHANGELOG_CONTENT=$(echo "$CHANGELOG_CONTENT" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') + + if [ -n "$CHANGELOG_CONTENT" ]; then + info "Found changelog content for version $VERSION" + else + warn "Changelog entry for $VERSION appears to be empty" + fi +} + +# Build everything +build() { + step "2/8" "Building extension bundle..." + cd "$REPO_ROOT" + pnpm bundle + + step "3/8" "Building CLI..." + pnpm --filter @roo-code/cli build + + info "Build complete" +} + +# Create release tarball +create_tarball() { + step "4/8" "Creating release tarball for $PLATFORM..." + + RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}" + TARBALL="roo-cli-${PLATFORM}.tar.gz" + + # Clean up any previous build + rm -rf "$RELEASE_DIR" + rm -f "$REPO_ROOT/$TARBALL" + + # Create directory structure + mkdir -p "$RELEASE_DIR/bin" + mkdir -p "$RELEASE_DIR/lib" + mkdir -p "$RELEASE_DIR/extension" + + # Copy CLI dist files + info "Copying CLI files..." + cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/" + + # Create package.json for npm install (runtime dependencies that can't be bundled) + info "Creating package.json..." + node -e " + const pkg = require('$CLI_DIR/package.json'); + const newPkg = { + name: '@roo-code/cli', + version: '$VERSION', + type: 'module', + dependencies: { + '@inkjs/ui': pkg.dependencies['@inkjs/ui'], + '@trpc/client': pkg.dependencies['@trpc/client'], + 'commander': pkg.dependencies.commander, + 'fuzzysort': pkg.dependencies.fuzzysort, + 'ink': pkg.dependencies.ink, + 'p-wait-for': pkg.dependencies['p-wait-for'], + 'react': pkg.dependencies.react, + 'superjson': pkg.dependencies.superjson, + 'zustand': pkg.dependencies.zustand + } + }; + console.log(JSON.stringify(newPkg, null, 2)); + " > "$RELEASE_DIR/package.json" + + # Copy extension bundle + info "Copying extension bundle..." + cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/" + + # Add package.json to extension directory to mark it as CommonJS + # This is necessary because the main package.json has "type": "module" + # but the extension bundle is CommonJS + echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json" + + # Find and copy ripgrep binary + # The extension looks for ripgrep at: appRoot/node_modules/@vscode/ripgrep/bin/rg + # The CLI sets appRoot to the CLI package root, so we need to put ripgrep there + info "Looking for ripgrep binary..." + RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1) + if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then + info "Found ripgrep at: $RIPGREP_PATH" + # Create the expected directory structure for the extension to find ripgrep + mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin" + cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/" + chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg" + # Also keep a copy in bin/ for direct access + mkdir -p "$RELEASE_DIR/bin" + cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/" + chmod +x "$RELEASE_DIR/bin/rg" + else + warn "ripgrep binary not found - users will need ripgrep installed" + fi + + # Create the wrapper script + info "Creating wrapper script..." + cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF' +#!/usr/bin/env node + +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Set environment variables for the CLI +// ROO_CLI_ROOT is the installed CLI package root (where node_modules/@vscode/ripgrep is) +process.env.ROO_CLI_ROOT = join(__dirname, '..'); +process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension'); +process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg'); + +// Import and run the actual CLI +await import(join(__dirname, '..', 'lib', 'index.js')); +WRAPPER_EOF + + chmod +x "$RELEASE_DIR/bin/roo" + + # Create empty .env file to suppress dotenvx warnings + touch "$RELEASE_DIR/.env" + + # Create empty .env file to suppress dotenvx warnings + touch "$RELEASE_DIR/.env" + + # Create tarball + info "Creating tarball..." + cd "$REPO_ROOT" + tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")" + + # Clean up release directory + rm -rf "$RELEASE_DIR" + + # Show size + TARBALL_PATH="$REPO_ROOT/$TARBALL" + TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}') + info "Created: $TARBALL ($TARBALL_SIZE)" +} + +# Verify local installation +verify_local_install() { + if [ "$SKIP_VERIFY" = true ]; then + step "5/8" "Skipping verification (--skip-verify)" + return + fi + + step "5/8" "Verifying local installation..." + + VERIFY_DIR="$REPO_ROOT/.verify-release" + VERIFY_INSTALL_DIR="$VERIFY_DIR/cli" + VERIFY_BIN_DIR="$VERIFY_DIR/bin" + + # Clean up any previous verification directory + rm -rf "$VERIFY_DIR" + mkdir -p "$VERIFY_DIR" + + # Run the actual install script with the local tarball + info "Running install script with local tarball..." + TARBALL_PATH="$REPO_ROOT/$TARBALL" + + ROO_LOCAL_TARBALL="$TARBALL_PATH" \ + ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \ + ROO_BIN_DIR="$VERIFY_BIN_DIR" \ + ROO_VERSION="$VERSION" \ + "$CLI_DIR/install.sh" || { + echo "" + warn "Install script failed. Showing tarball contents:" + tar -tzf "$TARBALL_PATH" 2>&1 || true + echo "" + rm -rf "$VERIFY_DIR" + error "Installation verification failed! The install script could not complete successfully." + } + + # Verify the CLI runs correctly with basic commands + info "Testing installed CLI..." + + # Test --help + if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then + echo "" + warn "CLI --help output:" + "$VERIFY_BIN_DIR/roo" --help 2>&1 || true + echo "" + rm -rf "$VERIFY_DIR" + error "CLI --help check failed! The release tarball may have missing dependencies." + fi + info "CLI --help check passed" + + # Test --version + if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then + echo "" + warn "CLI --version output:" + "$VERIFY_BIN_DIR/roo" --version 2>&1 || true + echo "" + rm -rf "$VERIFY_DIR" + error "CLI --version check failed! The release tarball may have missing dependencies." + fi + info "CLI --version check passed" + + # Run a simple end-to-end test to verify the CLI actually works + info "Running end-to-end verification test..." + + # Create a temporary workspace for the test + VERIFY_WORKSPACE="$VERIFY_DIR/workspace" + mkdir -p "$VERIFY_WORKSPACE" + + # Run the CLI with a simple prompt + if timeout 60 "$VERIFY_BIN_DIR/roo" --yes --oneshot -w "$VERIFY_WORKSPACE" "1+1=?" > "$VERIFY_DIR/test-output.log" 2>&1; then + info "End-to-end test passed" + else + EXIT_CODE=$? + echo "" + warn "End-to-end test failed (exit code: $EXIT_CODE). Output:" + cat "$VERIFY_DIR/test-output.log" 2>&1 || true + echo "" + rm -rf "$VERIFY_DIR" + error "CLI end-to-end test failed! The CLI may be broken." + fi + + # Clean up verification directory + cd "$REPO_ROOT" + rm -rf "$VERIFY_DIR" + + info "Local verification passed!" +} + +# Create checksum +create_checksum() { + step "6/8" "Creating checksum..." + cd "$REPO_ROOT" + + if command -v sha256sum &> /dev/null; then + sha256sum "$TARBALL" > "${TARBALL}.sha256" + elif command -v shasum &> /dev/null; then + shasum -a 256 "$TARBALL" > "${TARBALL}.sha256" + else + warn "No sha256sum or shasum found, skipping checksum" + return + fi + + info "Checksum: $(cat "${TARBALL}.sha256")" +} + +# Check if release already exists +check_existing_release() { + step "7/8" "Checking for existing release..." + + if gh release view "$TAG" &> /dev/null; then + warn "Release $TAG already exists" + read -p "Do you want to delete it and create a new one? [y/N] " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + info "Deleting existing release..." + gh release delete "$TAG" --yes + # Also delete the tag if it exists + git tag -d "$TAG" 2>/dev/null || true + git push origin ":refs/tags/$TAG" 2>/dev/null || true + else + error "Aborted. Use a different version or delete the existing release manually." + fi + fi +} + +# Create GitHub release +create_release() { + step "8/8" "Creating GitHub release..." + cd "$REPO_ROOT" + + # Get the current commit SHA for the release target + COMMIT_SHA=$(git rev-parse HEAD) + + # Verify the commit exists on GitHub before attempting to create the release + # This prevents the "Release.target_commitish is invalid" error + info "Verifying commit ${COMMIT_SHA:0:8} exists on GitHub..." + git fetch origin 2>/dev/null || true + if ! git branch -r --contains "$COMMIT_SHA" 2>/dev/null | grep -q "origin/"; then + warn "Commit ${COMMIT_SHA:0:8} has not been pushed to GitHub" + echo "" + echo "The release script needs to create a release at your current commit," + echo "but this commit hasn't been pushed to GitHub yet." + echo "" + read -p "Push current branch to origin now? [Y/n] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + info "Pushing to origin..." + git push origin HEAD || error "Failed to push to origin. Please push manually and try again." + else + error "Aborted. Please push your commits to GitHub and try again." + fi + fi + info "Commit verified on GitHub" + + # Build the What's New section from changelog content + WHATS_NEW_SECTION="" + if [ -n "$CHANGELOG_CONTENT" ]; then + WHATS_NEW_SECTION="## What's New + +$CHANGELOG_CONTENT + +" + fi + + RELEASE_NOTES=$(cat << EOF +${WHATS_NEW_SECTION}## Installation + +\`\`\`bash +curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh +\`\`\` + +Or install a specific version: +\`\`\`bash +ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh +\`\`\` + +## Requirements + +- Node.js 20 or higher +- macOS (Intel or Apple Silicon) or Linux (x64 or ARM64) + +## Usage + +\`\`\`bash +# Run a task +roo "What is this project?" + +# See all options +roo --help +\`\`\` + +## Platform Support + +This release includes: +- \`roo-cli-${PLATFORM}.tar.gz\` - Built on $(uname -s) $(uname -m) + +> **Note:** Additional platforms will be added as needed. If you need a different platform, please open an issue. + +## Checksum + +\`\`\` +$(cat "${TARBALL}.sha256" 2>/dev/null || echo "N/A") +\`\`\` +EOF +) + + info "Creating release at commit: ${COMMIT_SHA:0:8}" + + # Create release (gh will create the tag automatically) + info "Creating release..." + RELEASE_FILES="$TARBALL" + if [ -f "${TARBALL}.sha256" ]; then + RELEASE_FILES="$RELEASE_FILES ${TARBALL}.sha256" + fi + + gh release create "$TAG" \ + --title "Roo Code CLI v$VERSION" \ + --notes "$RELEASE_NOTES" \ + --prerelease \ + --target "$COMMIT_SHA" \ + $RELEASE_FILES + + info "Release created!" +} + +# Cleanup +cleanup() { + info "Cleaning up..." + cd "$REPO_ROOT" + rm -f "$TARBALL" "${TARBALL}.sha256" +} + +# Print summary +print_summary() { + echo "" + printf "${GREEN}${BOLD}✓ Release v$VERSION created successfully!${NC}\n" + echo "" + echo " Release URL: https://github.com/RooCodeInc/Roo-Code/releases/tag/$TAG" + echo "" + echo " Install with:" + echo " curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" + echo "" +} + +# Print dry-run summary +print_dry_run_summary() { + echo "" + printf "${YELLOW}${BOLD}✓ Dry run complete for v$VERSION${NC}\n" + echo "" + echo " The following artifacts were created:" + echo " - $TARBALL" + if [ -f "${TARBALL}.sha256" ]; then + echo " - ${TARBALL}.sha256" + fi + echo "" + echo " To complete the release, run without --dry-run:" + echo " ./apps/cli/scripts/release.sh $VERSION" + echo "" + echo " Or manually upload the tarball to a new GitHub release." + echo "" +} + +# Print local build summary +print_local_summary() { + echo "" + printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n" + echo "" + echo " Tarball: $REPO_ROOT/$TARBALL" + if [ -f "${TARBALL}.sha256" ]; then + echo " Checksum: $REPO_ROOT/${TARBALL}.sha256" + fi + echo "" + echo " To install manually:" + echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh" + echo "" + echo " Or re-run with --install to install automatically:" + echo " ./apps/cli/scripts/release.sh --local --install" + echo "" +} + +# Install locally using the install script +install_local() { + step "7/8" "Installing locally..." + + TARBALL_PATH="$REPO_ROOT/$TARBALL" + + ROO_LOCAL_TARBALL="$TARBALL_PATH" \ + ROO_VERSION="$VERSION" \ + "$CLI_DIR/install.sh" || { + error "Local installation failed!" + } + + info "Local installation complete!" +} + +# Print local install summary +print_local_install_summary() { + echo "" + printf "${GREEN}${BOLD}✓ Local build installed for v$VERSION${NC}\n" + echo "" + echo " Tarball: $REPO_ROOT/$TARBALL" + echo " Installed to: ~/.roo/cli" + echo " Binary: ~/.local/bin/roo" + echo "" + echo " Test it out:" + echo " roo --version" + echo " roo --help" + echo "" +} + +# Main +main() { + echo "" + printf "${BLUE}${BOLD}" + echo " ╭─────────────────────────────────╮" + echo " │ Roo Code CLI Release Script │" + echo " ╰─────────────────────────────────╯" + printf "${NC}" + + if [ "$DRY_RUN" = true ]; then + printf "${YELLOW} (DRY RUN MODE)${NC}\n" + elif [ "$LOCAL_BUILD" = true ]; then + printf "${YELLOW} (LOCAL BUILD MODE)${NC}\n" + fi + echo "" + + detect_platform + check_prerequisites + get_version + get_changelog_content + build + create_tarball + verify_local_install + create_checksum + + if [ "$LOCAL_BUILD" = true ]; then + step "7/8" "Skipping GitHub checks (local build)" + if [ "$LOCAL_INSTALL" = true ]; then + install_local + print_local_install_summary + else + step "8/8" "Skipping installation (use --install to auto-install)" + print_local_summary + fi + elif [ "$DRY_RUN" = true ]; then + step "7/8" "Skipping existing release check (dry run)" + step "8/8" "Skipping GitHub release creation (dry run)" + print_dry_run_summary + else + check_existing_release + create_release + cleanup + print_summary + fi +} + +main diff --git a/apps/cli/src/agent/__tests__/extension-client.test.ts b/apps/cli/src/agent/__tests__/extension-client.test.ts index 7a63fe0174c..3d87a30200f 100644 --- a/apps/cli/src/agent/__tests__/extension-client.test.ts +++ b/apps/cli/src/agent/__tests__/extension-client.test.ts @@ -93,6 +93,13 @@ describe("detectAgentState", () => { expect(state.requiredAction).toBe("answer") }) + it("should detect waiting for browser_action_launch approval", () => { + const messages = [createMessage({ type: "ask", ask: "browser_action_launch", partial: false })] + const state = detectAgentState(messages) + expect(state.state).toBe(AgentLoopState.WAITING_FOR_INPUT) + expect(state.requiredAction).toBe("approve") + }) + it("should detect waiting for use_mcp_server approval", () => { const messages = [createMessage({ type: "ask", ask: "use_mcp_server", partial: false })] const state = detectAgentState(messages) @@ -195,6 +202,7 @@ describe("Type Guards", () => { expect(isInteractiveAsk("tool")).toBe(true) expect(isInteractiveAsk("command")).toBe(true) expect(isInteractiveAsk("followup")).toBe(true) + expect(isInteractiveAsk("browser_action_launch")).toBe(true) expect(isInteractiveAsk("use_mcp_server")).toBe(true) }) diff --git a/apps/cli/src/agent/agent-state.ts b/apps/cli/src/agent/agent-state.ts index d1451d62fdd..ca4a099ccab 100644 --- a/apps/cli/src/agent/agent-state.ts +++ b/apps/cli/src/agent/agent-state.ts @@ -116,7 +116,7 @@ export enum AgentLoopState { */ export type RequiredAction = | "none" // No action needed (running/streaming) - | "approve" // Can approve/reject (tool, command, mcp) + | "approve" // Can approve/reject (tool, command, browser, mcp) | "answer" // Need to answer a question (followup) | "retry_or_new_task" // Can retry or start new task (api_req_failed) | "proceed_or_new_task" // Can proceed or start new task (mistake_limit) @@ -221,6 +221,7 @@ function getRequiredAction(ask: ClineAsk): RequiredAction { return "answer" case "command": case "tool": + case "browser_action_launch": case "use_mcp_server": return "approve" case "command_output": @@ -263,6 +264,8 @@ function getStateDescription(state: AgentLoopState, ask?: ClineAsk): string { return "Agent wants to execute a command. Approve or reject." case "tool": return "Agent wants to perform a file operation. Approve or reject." + case "browser_action_launch": + return "Agent wants to use the browser. Approve or reject." case "use_mcp_server": return "Agent wants to use an MCP server. Approve or reject." default: diff --git a/apps/cli/src/agent/ask-dispatcher.ts b/apps/cli/src/agent/ask-dispatcher.ts index 44e861ae9b8..8d57e4547cd 100644 --- a/apps/cli/src/agent/ask-dispatcher.ts +++ b/apps/cli/src/agent/ask-dispatcher.ts @@ -59,11 +59,6 @@ export interface AskDispatcherOptions { */ nonInteractive?: boolean - /** - * Whether to exit on API request errors instead of retrying. - */ - exitOnError?: boolean - /** * Whether to disable ask handling (for TUI mode). * In TUI mode, the TUI handles asks directly. @@ -92,7 +87,6 @@ export class AskDispatcher { private promptManager: PromptManager private sendMessage: (message: WebviewMessage) => void private nonInteractive: boolean - private exitOnError: boolean private disabled: boolean /** @@ -106,7 +100,6 @@ export class AskDispatcher { this.promptManager = options.promptManager this.sendMessage = options.sendMessage this.nonInteractive = options.nonInteractive ?? false - this.exitOnError = options.exitOnError ?? false this.disabled = options.disabled ?? false } @@ -244,7 +237,7 @@ export class AskDispatcher { } /** - * Handle interactive asks (followup, command, tool, use_mcp_server). + * Handle interactive asks (followup, command, tool, browser_action_launch, use_mcp_server). * These require user approval or input. */ private async handleInteractiveAsk(ts: number, ask: ClineAsk, text: string): Promise { @@ -258,6 +251,9 @@ export class AskDispatcher { case "tool": return await this.handleToolApproval(ts, text) + case "browser_action_launch": + return await this.handleBrowserApproval(ts, text) + case "use_mcp_server": return await this.handleMcpApproval(ts, text) @@ -441,6 +437,32 @@ export class AskDispatcher { } } + /** + * Handle browser action approval. + */ + private async handleBrowserApproval(ts: number, text: string): Promise { + this.outputManager.output("\n[browser action request]") + if (text) { + this.outputManager.output(` Action: ${text}`) + } + this.outputManager.markDisplayed(ts, text || "", false) + + if (this.nonInteractive) { + // Auto-approved by extension settings + return { handled: true } + } + + try { + const approved = await this.promptManager.promptForYesNo("Allow browser action? (y/n): ") + this.sendApprovalResponse(approved) + return { handled: true, response: approved ? "yesButtonClicked" : "noButtonClicked" } + } catch { + this.outputManager.output("[Defaulting to: no]") + this.sendApprovalResponse(false) + return { handled: true, response: "noButtonClicked" } + } + } + /** * Handle MCP server access approval. */ @@ -496,11 +518,6 @@ export class AskDispatcher { this.outputManager.output(` Error: ${text || "Unknown error"}`) this.outputManager.markDisplayed(ts, text || "", false) - if (this.exitOnError) { - console.error(`[CLI] API request failed: ${text || "Unknown error"}`) - process.exit(1) - } - if (this.nonInteractive) { this.outputManager.output("\n[retrying api request]") // Auto-retry in non-interactive mode diff --git a/apps/cli/src/agent/extension-host.ts b/apps/cli/src/agent/extension-host.ts index 4a0e941b4bb..e1f55a30d1f 100644 --- a/apps/cli/src/agent/extension-host.ts +++ b/apps/cli/src/agent/extension-host.ts @@ -24,7 +24,7 @@ import type { WebviewMessage, } from "@roo-code/types" import { createVSCodeAPI, IExtensionHost, ExtensionHostEventMap, setRuntimeConfigValues } from "@roo-code/vscode-shim" -import { DebugLogger, setDebugLogEnabled } from "@roo-code/core/cli" +import { DebugLogger } from "@roo-code/core/cli" import type { SupportedProvider } from "@/types/index.js" import type { User } from "@/lib/sdk/index.js" @@ -43,25 +43,10 @@ const cliLogger = new DebugLogger("CLI") // Get the CLI package root directory (for finding node_modules/@vscode/ripgrep) // When running from a release tarball, ROO_CLI_ROOT is set by the wrapper script. -// In development, we fall back to finding the CLI package root by walking up to package.json. -// This works whether running from dist/ (bundled) or src/agent/ (tsx dev). +// In development, we fall back to calculating from __dirname. +// After bundling with tsup, the code is in dist/index.js (flat), so we go up one level. const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function findCliPackageRoot(): string { - let dir = __dirname - - while (dir !== path.dirname(dir)) { - if (fs.existsSync(path.join(dir, "package.json"))) { - return dir - } - - dir = path.dirname(dir) - } - - return path.resolve(__dirname, "..") -} - -const CLI_PACKAGE_ROOT = process.env.ROO_CLI_ROOT || findCliPackageRoot() +const CLI_PACKAGE_ROOT = process.env.ROO_CLI_ROOT || path.resolve(__dirname, "..") export interface ExtensionHostOptions { mode: string @@ -79,10 +64,6 @@ export interface ExtensionHostOptions { ephemeral: boolean debug: boolean exitOnComplete: boolean - /** - * When true, exit the process on API request errors instead of retrying. - */ - exitOnError?: boolean /** * When true, completely disables all direct stdout/stderr output. * Use this when running in TUI mode where Ink controls the terminal. @@ -173,11 +154,6 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac this.options = options - // Enable file-based debug logging only when --debug is passed. - if (options.debug) { - setDebugLogEnabled(true) - } - // Set up quiet mode early, before any extension code runs. // This suppresses console output from the extension during load. this.setupQuietMode() @@ -203,7 +179,6 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac promptManager: this.promptManager, sendMessage: (msg) => this.sendToExtension(msg), nonInteractive: options.nonInteractive, - exitOnError: options.exitOnError, disabled: options.disableOutput, // TUI mode handles asks directly. }) @@ -214,6 +189,7 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac const baseSettings: RooCodeSettings = { mode: this.options.mode, commandExecutionTimeout: 30, + browserToolEnabled: false, enableCheckpoints: false, ...getProviderSettings(this.options.provider, this.options.apiKey, this.options.model), } @@ -226,6 +202,7 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac alwaysAllowWrite: true, alwaysAllowWriteOutsideWorkspace: true, alwaysAllowWriteProtected: true, + alwaysAllowBrowser: true, alwaysAllowMcp: true, alwaysAllowModeSwitch: true, alwaysAllowSubtasks: true, @@ -426,16 +403,12 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac public markWebviewReady(): void { this.isReady = true - // Apply CLI settings to the runtime config and context proxy BEFORE - // sending webviewDidLaunch. This prevents a race condition where the - // webviewDidLaunch handler's first-time init sync reads default state - // (apiProvider: "anthropic") instead of the CLI-provided settings. + // Send initial webview messages to trigger proper extension initialization. + // This is critical for the extension to start sending state updates properly. + this.sendToExtension({ type: "webviewDidLaunch" }) + setRuntimeConfigValues("roo-cline", this.initialSettings as Record) this.sendToExtension({ type: "updateSettings", updatedSettings: this.initialSettings }) - - // Now trigger extension initialization. The context proxy should already - // have CLI-provided values when the webviewDidLaunch handler runs. - this.sendToExtension({ type: "webviewDidLaunch" }) } public isInInitialSetup(): boolean { @@ -475,25 +448,6 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac const cleanup = () => { this.client.off("taskCompleted", completeHandler) this.client.off("error", errorHandler) - - if (messageHandler) { - this.client.off("message", messageHandler) - } - } - - // When exitOnError is enabled, listen for api_req_retry_delayed messages - // (sent by Task.ts during auto-approval retry backoff) and exit immediately. - let messageHandler: ((msg: ClineMessage) => void) | null = null - - if (this.options.exitOnError) { - messageHandler = (msg: ClineMessage) => { - if (msg.type === "say" && msg.say === "api_req_retry_delayed") { - cleanup() - reject(new Error(msg.text?.split("\n")[0] || "API request failed")) - } - } - - this.client.on("message", messageHandler) } this.client.once("taskCompleted", completeHandler) diff --git a/apps/cli/src/agent/json-event-emitter.ts b/apps/cli/src/agent/json-event-emitter.ts index 578c52d2b80..a1a404e5556 100644 --- a/apps/cli/src/agent/json-event-emitter.ts +++ b/apps/cli/src/agent/json-event-emitter.ts @@ -258,6 +258,15 @@ export class JsonEventEmitter { break } + case "browser_action": + case "browser_action_result": + this.emitEvent({ + type: "tool_result", + subtype: "browser", + tool_result: { name: "browser_action", output: msg.text }, + }) + break + case "mcp_server_response": this.emitEvent({ type: "tool_result", @@ -327,6 +336,15 @@ export class JsonEventEmitter { }) break + case "browser_action_launch": + this.emitEvent({ + type: "tool_use", + id: msg.ts, + subtype: "browser", + tool_use: { name: "browser_action", input: { raw: msg.text } }, + }) + break + case "use_mcp_server": this.emitEvent({ type: "tool_use", diff --git a/apps/cli/src/commands/cli/run.ts b/apps/cli/src/commands/cli/run.ts index 1ce2f4a1f11..663ed5cf750 100644 --- a/apps/cli/src/commands/cli/run.ts +++ b/apps/cli/src/commands/cli/run.ts @@ -65,10 +65,8 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption flagOptions.reasoningEffort || settings.reasoningEffort || DEFAULT_FLAGS.reasoningEffort const effectiveProvider = flagOptions.provider ?? settings.provider ?? (rooToken ? "roo" : "openrouter") const effectiveWorkspacePath = flagOptions.workspace ? path.resolve(flagOptions.workspace) : process.cwd() - const legacyRequireApprovalFromSettings = - settings.requireApproval ?? - (settings.dangerouslySkipPermissions === undefined ? undefined : !settings.dangerouslySkipPermissions) - const effectiveRequireApproval = flagOptions.requireApproval || legacyRequireApprovalFromSettings || false + const effectiveDangerouslySkipPermissions = + flagOptions.yes || flagOptions.dangerouslySkipPermissions || settings.dangerouslySkipPermissions || false const effectiveExitOnComplete = flagOptions.print || flagOptions.oneshot || settings.oneshot || false const extensionHostOptions: ExtensionHostOptions = { @@ -79,8 +77,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption model: effectiveModel, workspacePath: effectiveWorkspacePath, extensionPath: path.resolve(flagOptions.extension || getDefaultExtensionPath(__dirname)), - nonInteractive: !effectiveRequireApproval, - exitOnError: flagOptions.exitOnError, + nonInteractive: effectiveDangerouslySkipPermissions, ephemeral: flagOptions.ephemeral, debug: flagOptions.debug, exitOnComplete: effectiveExitOnComplete, @@ -115,18 +112,15 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption extensionHostOptions.apiKey = rooToken extensionHostOptions.user = me.user } catch { - // If an explicit API key was provided via flag or env var, fall through - // to the general API key resolution below instead of exiting. - if (!flagOptions.apiKey && !getApiKeyFromEnv(extensionHostOptions.provider)) { - console.error("[CLI] Your Roo Code Router token is not valid.") - console.error("[CLI] Please run: roo auth login") - console.error("[CLI] Or use --api-key or set ROO_API_KEY to provide your own API key.") - process.exit(1) - } + console.error("[CLI] Your Roo Code Router token is not valid.") + console.error("[CLI] Please run: roo auth login") + process.exit(1) } + } else { + console.error("[CLI] Your Roo Code Router token is missing.") + console.error("[CLI] Please run: roo auth login") + process.exit(1) } - // If no rooToken, fall through to the general API key resolution below - // which will check flagOptions.apiKey and ROO_API_KEY env var. } // Validations diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index a1fd1be89e1..5b663c2bdcd 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -18,7 +18,7 @@ program .option("-p, --print", "Print response and exit (non-interactive mode)", false) .option("-e, --extension ", "Path to the extension bundle directory") .option("-d, --debug", "Enable debug output (includes detailed debug information)", false) - .option("-a, --require-approval", "Require manual approval for actions", false) + .option("-y, --yes, --dangerously-skip-permissions", "Auto-approve all prompts (use with caution)", false) .option("-k, --api-key ", "API key for the LLM provider") .option("--provider ", "API provider (roo, anthropic, openai, openrouter, etc.)") .option("-m, --model ", "Model to use", DEFAULT_FLAGS.model) @@ -28,7 +28,6 @@ program "Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh)", DEFAULT_FLAGS.reasoningEffort, ) - .option("--exit-on-error", "Exit on API request errors instead of retrying", false) .option("--ephemeral", "Run without persisting state (uses temporary storage)", false) .option("--oneshot", "Exit upon task completion", false) .option( diff --git a/apps/cli/src/lib/storage/__tests__/settings.test.ts b/apps/cli/src/lib/storage/__tests__/settings.test.ts index 30f1dbe8ecb..c133f733b92 100644 --- a/apps/cli/src/lib/storage/__tests__/settings.test.ts +++ b/apps/cli/src/lib/storage/__tests__/settings.test.ts @@ -103,7 +103,7 @@ describe("Settings Storage", () => { await saveSettings({ mode: "architect", provider: "anthropic" as const, - model: "claude-opus-4.6", + model: "claude-opus-4.5", reasoningEffort: "medium" as const, }) @@ -112,7 +112,7 @@ describe("Settings Storage", () => { expect(settings.mode).toBe("architect") expect(settings.provider).toBe("anthropic") - expect(settings.model).toBe("claude-opus-4.6") + expect(settings.model).toBe("claude-opus-4.5") expect(settings.reasoningEffort).toBe("medium") }) @@ -179,20 +179,20 @@ describe("Settings Storage", () => { expect(loaded.reasoningEffort).toBe("low") }) - it("should support requireApproval setting", async () => { - await saveSettings({ requireApproval: true }) + it("should support dangerouslySkipPermissions setting", async () => { + await saveSettings({ dangerouslySkipPermissions: true }) const loaded = await loadSettings() - expect(loaded.requireApproval).toBe(true) + expect(loaded.dangerouslySkipPermissions).toBe(true) }) - it("should support all settings together including requireApproval", async () => { + it("should support all settings together including dangerouslySkipPermissions", async () => { const allSettings = { mode: "architect", provider: "anthropic" as const, model: "claude-sonnet-4-20250514", reasoningEffort: "high" as const, - requireApproval: true, + dangerouslySkipPermissions: true, } await saveSettings(allSettings) @@ -202,7 +202,7 @@ describe("Settings Storage", () => { expect(loaded.provider).toBe("anthropic") expect(loaded.model).toBe("claude-sonnet-4-20250514") expect(loaded.reasoningEffort).toBe("high") - expect(loaded.requireApproval).toBe(true) + expect(loaded.dangerouslySkipPermissions).toBe(true) }) it("should support oneshot setting", async () => { @@ -218,7 +218,7 @@ describe("Settings Storage", () => { provider: "anthropic" as const, model: "claude-sonnet-4-20250514", reasoningEffort: "high" as const, - requireApproval: true, + dangerouslySkipPermissions: true, oneshot: true, } @@ -229,15 +229,8 @@ describe("Settings Storage", () => { expect(loaded.provider).toBe("anthropic") expect(loaded.model).toBe("claude-sonnet-4-20250514") expect(loaded.reasoningEffort).toBe("high") - expect(loaded.requireApproval).toBe(true) - expect(loaded.oneshot).toBe(true) - }) - - it("should still load legacy dangerouslySkipPermissions setting", async () => { - await saveSettings({ dangerouslySkipPermissions: true }) - const loaded = await loadSettings() - expect(loaded.dangerouslySkipPermissions).toBe(true) + expect(loaded.oneshot).toBe(true) }) }) }) diff --git a/apps/cli/src/lib/utils/__tests__/extension.test.ts b/apps/cli/src/lib/utils/__tests__/extension.test.ts index 4b4a2db5850..31fdbe87f00 100644 --- a/apps/cli/src/lib/utils/__tests__/extension.test.ts +++ b/apps/cli/src/lib/utils/__tests__/extension.test.ts @@ -21,26 +21,9 @@ describe("getDefaultExtensionPath", () => { it("should return monorepo path when extension.js exists there", () => { const mockDirname = "/test/apps/cli/dist" - const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist") + const expectedMonorepoPath = path.resolve(mockDirname, "../../../src/dist") - // Walk-up: dist/ has no package.json, apps/cli/ does - vi.mocked(fs.existsSync).mockImplementation((p) => { - const s = String(p) - - if (s === path.join(mockDirname, "package.json")) { - return false - } - - if (s === path.join("/test/apps/cli", "package.json")) { - return true - } - - if (s === path.join(expectedMonorepoPath, "extension.js")) { - return true - } - - return false - }) + vi.mocked(fs.existsSync).mockReturnValue(true) const result = getDefaultExtensionPath(mockDirname) @@ -50,18 +33,9 @@ describe("getDefaultExtensionPath", () => { it("should return package path when extension.js does not exist in monorepo path", () => { const mockDirname = "/test/apps/cli/dist" - const expectedPackagePath = path.resolve("/test/apps/cli", "extension") - - // Walk-up finds package.json at apps/cli/, but no extension.js in monorepo path - vi.mocked(fs.existsSync).mockImplementation((p) => { - const s = String(p) + const expectedPackagePath = path.resolve(mockDirname, "../extension") - if (s === path.join("/test/apps/cli", "package.json")) { - return true - } - - return false - }) + vi.mocked(fs.existsSync).mockReturnValue(false) const result = getDefaultExtensionPath(mockDirname) @@ -69,45 +43,12 @@ describe("getDefaultExtensionPath", () => { }) it("should check monorepo path first", () => { - const mockDirname = "/test/apps/cli/dist" - - vi.mocked(fs.existsSync).mockImplementation((p) => { - const s = String(p) - - if (s === path.join("/test/apps/cli", "package.json")) { - return true - } - - return false - }) + const mockDirname = "/some/path" + vi.mocked(fs.existsSync).mockReturnValue(false) getDefaultExtensionPath(mockDirname) - const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist") + const expectedMonorepoPath = path.resolve(mockDirname, "../../../src/dist") expect(fs.existsSync).toHaveBeenCalledWith(path.join(expectedMonorepoPath, "extension.js")) }) - - it("should work when called from source directory (tsx dev)", () => { - const mockDirname = "/test/apps/cli/src/commands/cli" - const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist") - - // Walk-up: no package.json in src subdirs, found at apps/cli/ - vi.mocked(fs.existsSync).mockImplementation((p) => { - const s = String(p) - - if (s === path.join("/test/apps/cli", "package.json")) { - return true - } - - if (s === path.join(expectedMonorepoPath, "extension.js")) { - return true - } - - return false - }) - - const result = getDefaultExtensionPath(mockDirname) - - expect(result).toBe(expectedMonorepoPath) - }) }) diff --git a/apps/cli/src/lib/utils/context-window.ts b/apps/cli/src/lib/utils/context-window.ts index df878e16b02..c1224c8b1ec 100644 --- a/apps/cli/src/lib/utils/context-window.ts +++ b/apps/cli/src/lib/utils/context-window.ts @@ -48,10 +48,18 @@ function getModelIdForProvider(config: ProviderSettings): string | undefined { return config.requestyModelId case "litellm": return config.litellmModelId + case "deepinfra": + return config.deepInfraModelId + case "huggingface": + return config.huggingFaceModelId + case "unbound": + return config.unboundModelId case "vercel-ai-gateway": return config.vercelAiGatewayModelId + case "io-intelligence": + return config.ioIntelligenceModelId default: - // For anthropic, bedrock, vertex, gemini, xai, etc. + // For anthropic, bedrock, vertex, gemini, xai, groq, etc. return config.apiModelId } } diff --git a/apps/cli/src/lib/utils/extension.ts b/apps/cli/src/lib/utils/extension.ts index f49b2df8651..904940ec004 100644 --- a/apps/cli/src/lib/utils/extension.ts +++ b/apps/cli/src/lib/utils/extension.ts @@ -17,26 +17,17 @@ export function getDefaultExtensionPath(dirname: string): string { } } - // Find the CLI package root (apps/cli) by walking up to the nearest package.json. - // This works whether called from dist/ (bundled) or src/commands/cli/ (tsx dev). - let packageRoot = dirname - - while (packageRoot !== path.dirname(packageRoot)) { - if (fs.existsSync(path.join(packageRoot, "package.json"))) { - break - } - - packageRoot = path.dirname(packageRoot) - } - - // The extension is at ../../src/dist relative to apps/cli (monorepo/src/dist) - const monorepoPath = path.resolve(packageRoot, "../../src/dist") + // __dirname is apps/cli/dist when bundled + // The extension is at src/dist (relative to monorepo root) + // So from apps/cli/dist, we need to go ../../../src/dist + const monorepoPath = path.resolve(dirname, "../../../src/dist") + // Try monorepo path first (for development) if (fs.existsSync(path.join(monorepoPath, "extension.js"))) { return monorepoPath } - // Fallback: when installed via curl script, extension is at apps/cli/extension - const packagePath = path.resolve(packageRoot, "extension") + // Fallback: when installed via curl script, extension is at ../extension + const packagePath = path.resolve(dirname, "../extension") return packagePath } diff --git a/apps/cli/src/lib/utils/version.ts b/apps/cli/src/lib/utils/version.ts index c599963bdc6..e4f2ce59b21 100644 --- a/apps/cli/src/lib/utils/version.ts +++ b/apps/cli/src/lib/utils/version.ts @@ -1,24 +1,6 @@ -import fs from "fs" -import path from "path" -import { fileURLToPath } from "url" +import { createRequire } from "module" -// Walk up from the current file to find the nearest package.json. -// This works whether running from source (tsx src/lib/utils/) or bundle (dist/). -function findVersion(): string { - let dir = path.dirname(fileURLToPath(import.meta.url)) +const require = createRequire(import.meta.url) +const packageJson = require("../package.json") - while (dir !== path.dirname(dir)) { - const candidate = path.join(dir, "package.json") - - if (fs.existsSync(candidate)) { - const packageJson = JSON.parse(fs.readFileSync(candidate, "utf-8")) - return packageJson.version - } - - dir = path.dirname(dir) - } - - return "0.0.0" -} - -export const VERSION = findVersion() +export const VERSION = packageJson.version diff --git a/apps/cli/src/types/constants.ts b/apps/cli/src/types/constants.ts index 6c54348a9ca..5b3dc577786 100644 --- a/apps/cli/src/types/constants.ts +++ b/apps/cli/src/types/constants.ts @@ -3,7 +3,7 @@ import { reasoningEffortsExtended } from "@roo-code/types" export const DEFAULT_FLAGS = { mode: "code", reasoningEffort: "medium" as const, - model: "anthropic/claude-opus-4.6", + model: "anthropic/claude-opus-4.5", } export const REASONING_EFFORTS = [...reasoningEffortsExtended, "unspecified", "disabled"] diff --git a/apps/cli/src/types/types.ts b/apps/cli/src/types/types.ts index 162f7bac7b7..05392ccca86 100644 --- a/apps/cli/src/types/types.ts +++ b/apps/cli/src/types/types.ts @@ -24,8 +24,8 @@ export type FlagOptions = { print: boolean extension?: string debug: boolean - requireApproval: boolean - exitOnError: boolean + yes: boolean + dangerouslySkipPermissions: boolean apiKey?: string provider?: SupportedProvider model?: string @@ -57,9 +57,7 @@ export interface CliSettings { model?: string /** Default reasoning effort level */ reasoningEffort?: ReasoningEffortFlagOptions - /** Require manual approval for tools/commands/browser/MCP actions */ - requireApproval?: boolean - /** @deprecated Legacy inverse setting kept for backward compatibility */ + /** Auto-approve all prompts (use with caution) */ dangerouslySkipPermissions?: boolean /** Exit upon task completion */ oneshot?: boolean diff --git a/apps/cli/src/ui/components/ChatHistoryItem.tsx b/apps/cli/src/ui/components/ChatHistoryItem.tsx index e5bbc79366c..c51b0faddbc 100644 --- a/apps/cli/src/ui/components/ChatHistoryItem.tsx +++ b/apps/cli/src/ui/components/ChatHistoryItem.tsx @@ -10,13 +10,14 @@ import { getToolRenderer } from "./tools/index.js" /** * Tool categories for styling */ -type ToolCategory = "file" | "directory" | "search" | "command" | "mode" | "completion" | "other" +type ToolCategory = "file" | "directory" | "search" | "command" | "browser" | "mode" | "completion" | "other" function getToolCategory(toolName: string): ToolCategory { const fileTools = ["readFile", "read_file", "writeToFile", "write_to_file", "applyDiff", "apply_diff"] const dirTools = ["listFiles", "list_files", "listFilesRecursive", "listFilesTopLevel"] const searchTools = ["searchFiles", "search_files"] const commandTools = ["executeCommand", "execute_command"] + const browserTools = ["browserAction", "browser_action"] const modeTools = ["switchMode", "switch_mode", "newTask", "new_task"] const completionTools = ["attemptCompletion", "attempt_completion", "askFollowupQuestion", "ask_followup_question"] @@ -24,6 +25,7 @@ function getToolCategory(toolName: string): ToolCategory { if (dirTools.includes(toolName)) return "directory" if (searchTools.includes(toolName)) return "search" if (commandTools.includes(toolName)) return "command" + if (browserTools.includes(toolName)) return "browser" if (modeTools.includes(toolName)) return "mode" if (completionTools.includes(toolName)) return "completion" return "other" @@ -37,6 +39,7 @@ const CATEGORY_COLORS: Record = { directory: theme.toolHeader, search: theme.warningColor, command: theme.successColor, + browser: theme.focusColor, mode: theme.userHeader, completion: theme.successColor, other: theme.toolHeader, diff --git a/apps/cli/src/ui/components/tools/BrowserTool.tsx b/apps/cli/src/ui/components/tools/BrowserTool.tsx new file mode 100644 index 00000000000..5e6d51857ab --- /dev/null +++ b/apps/cli/src/ui/components/tools/BrowserTool.tsx @@ -0,0 +1,87 @@ +import { Box, Text } from "ink" + +import * as theme from "../../theme.js" +import { Icon } from "../Icon.js" + +import type { ToolRendererProps } from "./types.js" +import { getToolDisplayName, getToolIconName } from "./utils.js" + +const ACTION_LABELS: Record = { + launch: "Launch Browser", + click: "Click", + hover: "Hover", + type: "Type Text", + press: "Press Key", + scroll_down: "Scroll Down", + scroll_up: "Scroll Up", + resize: "Resize Window", + close: "Close Browser", + screenshot: "Take Screenshot", +} + +export function BrowserTool({ toolData }: ToolRendererProps) { + const iconName = getToolIconName(toolData.tool) + const displayName = getToolDisplayName(toolData.tool) + const action = toolData.action || "" + const url = toolData.url || "" + const coordinate = toolData.coordinate || "" + const content = toolData.content || "" // May contain text for type action. + + const actionLabel = ACTION_LABELS[action] || action + + return ( + + {/* Header */} + + + + {" "} + {displayName} + + {action && ( + + {" "} + → {actionLabel} + + )} + + + {/* Action details */} + + {/* URL for launch action */} + {url && ( + + url: + + {url} + + + )} + + {/* Coordinates for click/hover actions */} + {coordinate && ( + + at: + {coordinate} + + )} + + {/* Text content for type action */} + {content && action === "type" && ( + + text: + "{content}" + + )} + + {/* Key for press action */} + {content && action === "press" && ( + + key: + {content} + + )} + + + ) +} diff --git a/apps/cli/src/ui/components/tools/index.ts b/apps/cli/src/ui/components/tools/index.ts index e5f5527c2f2..c6284320029 100644 --- a/apps/cli/src/ui/components/tools/index.ts +++ b/apps/cli/src/ui/components/tools/index.ts @@ -15,6 +15,7 @@ import { FileReadTool } from "./FileReadTool.js" import { FileWriteTool } from "./FileWriteTool.js" import { SearchTool } from "./SearchTool.js" import { CommandTool } from "./CommandTool.js" +import { BrowserTool } from "./BrowserTool.js" import { ModeTool } from "./ModeTool.js" import { CompletionTool } from "./CompletionTool.js" import { GenericTool } from "./GenericTool.js" @@ -31,6 +32,7 @@ export { FileReadTool } from "./FileReadTool.js" export { FileWriteTool } from "./FileWriteTool.js" export { SearchTool } from "./SearchTool.js" export { CommandTool } from "./CommandTool.js" +export { BrowserTool } from "./BrowserTool.js" export { ModeTool } from "./ModeTool.js" export { CompletionTool } from "./CompletionTool.js" export { GenericTool } from "./GenericTool.js" @@ -43,6 +45,7 @@ const CATEGORY_RENDERERS: Record> = { "file-write": FileWriteTool, search: SearchTool, command: CommandTool, + browser: BrowserTool, mode: ModeTool, completion: CompletionTool, other: GenericTool, diff --git a/apps/cli/src/ui/components/tools/types.ts b/apps/cli/src/ui/components/tools/types.ts index 29c8444af1d..a16fbd60ea3 100644 --- a/apps/cli/src/ui/components/tools/types.ts +++ b/apps/cli/src/ui/components/tools/types.ts @@ -5,7 +5,15 @@ export interface ToolRendererProps { rawContent?: string } -export type ToolCategory = "file-read" | "file-write" | "search" | "command" | "mode" | "completion" | "other" +export type ToolCategory = + | "file-read" + | "file-write" + | "search" + | "command" + | "browser" + | "mode" + | "completion" + | "other" export function getToolCategory(toolName: string): ToolCategory { const fileReadTools = ["readFile", "read_file", "skill", "listFilesTopLevel", "listFilesRecursive", "list_files"] @@ -21,6 +29,7 @@ export function getToolCategory(toolName: string): ToolCategory { const searchTools = ["searchFiles", "search_files", "codebaseSearch", "codebase_search"] const commandTools = ["execute_command", "executeCommand"] + const browserTools = ["browser_action", "browserAction"] const modeTools = ["switchMode", "switch_mode", "newTask", "new_task", "finishTask"] const completionTools = ["attempt_completion", "attemptCompletion", "ask_followup_question", "askFollowupQuestion"] @@ -28,6 +37,7 @@ export function getToolCategory(toolName: string): ToolCategory { if (fileWriteTools.includes(toolName)) return "file-write" if (searchTools.includes(toolName)) return "search" if (commandTools.includes(toolName)) return "command" + if (browserTools.includes(toolName)) return "browser" if (modeTools.includes(toolName)) return "mode" if (completionTools.includes(toolName)) return "completion" return "other" diff --git a/apps/cli/src/ui/components/tools/utils.ts b/apps/cli/src/ui/components/tools/utils.ts index 484125dbb2e..31acf2cccbc 100644 --- a/apps/cli/src/ui/components/tools/utils.ts +++ b/apps/cli/src/ui/components/tools/utils.ts @@ -73,6 +73,10 @@ export function getToolDisplayName(toolName: string): string { execute_command: "Execute Command", executeCommand: "Execute Command", + // Browser operations + browser_action: "Browser Action", + browserAction: "Browser Action", + // Mode operations switchMode: "Switch Mode", switch_mode: "Switch Mode", @@ -125,6 +129,10 @@ export function getToolIconName(toolName: string): IconName { execute_command: "terminal", executeCommand: "terminal", + // Browser operations + browser_action: "browser", + browserAction: "browser", + // Mode operations switchMode: "switch", switch_mode: "switch", diff --git a/apps/cli/src/ui/types.ts b/apps/cli/src/ui/types.ts index 3c45377c675..c2187fb2b66 100644 --- a/apps/cli/src/ui/types.ts +++ b/apps/cli/src/ui/types.ts @@ -40,6 +40,14 @@ export interface ToolData { /** Command output */ output?: string + // Browser operation fields + /** Browser action type */ + action?: string + /** Browser URL */ + url?: string + /** Click/hover coordinates */ + coordinate?: string + // Batch operation fields /** Batch file reads */ batchFiles?: Array<{ diff --git a/apps/cli/src/ui/utils/tools.ts b/apps/cli/src/ui/utils/tools.ts index b79a506571d..be3ff9484db 100644 --- a/apps/cli/src/ui/utils/tools.ts +++ b/apps/cli/src/ui/utils/tools.ts @@ -57,6 +57,17 @@ export function extractToolData(toolInfo: Record): ToolData { toolData.output = toolInfo.output as string } + // Extract browser-related fields + if (toolInfo.action !== undefined) { + toolData.action = toolInfo.action as string + } + if (toolInfo.url !== undefined) { + toolData.url = toolInfo.url as string + } + if (toolInfo.coordinate !== undefined) { + toolData.coordinate = toolInfo.coordinate as string + } + // Extract batch file operations if (Array.isArray(toolInfo.files)) { toolData.batchFiles = (toolInfo.files as Array>).map((f) => ({ @@ -154,6 +165,12 @@ export function formatToolOutput(toolInfo: Record): string { return `📁 ${listPath || "."}${recursive ? " (recursive)" : ""}` } + case "browser_action": { + const action = toolInfo.action as string + const url = toolInfo.url as string + return `🌐 ${action || "action"}${url ? `: ${url}` : ""}` + } + case "attempt_completion": { const result = toolInfo.result as string if (result) { @@ -231,6 +248,12 @@ export function formatToolAskMessage(toolInfo: Record): string return `Apply changes to: ${diffPath || "(no path)"}` } + case "browser_action": { + const action = toolInfo.action as string + const url = toolInfo.url as string + return `Browser: ${action || "action"}${url ? ` - ${url}` : ""}` + } + default: { const params = Object.entries(toolInfo) .filter(([key]) => key !== "tool") diff --git a/apps/cli/tsup.config.ts b/apps/cli/tsup.config.ts index 3ad1234d995..eff2c14e2c9 100644 --- a/apps/cli/tsup.config.ts +++ b/apps/cli/tsup.config.ts @@ -16,6 +16,7 @@ export default defineConfig({ external: [ // Keep native modules external "@anthropic-ai/sdk", + "@anthropic-ai/bedrock-sdk", "@anthropic-ai/vertex-sdk", // Keep @vscode/ripgrep external - we bundle the binary separately "@vscode/ripgrep", diff --git a/apps/vscode-e2e/src/suite/tools/read-file.test.ts b/apps/vscode-e2e/src/suite/tools/read-file.test.ts index 6f3e28f60fc..00aca7f58ab 100644 --- a/apps/vscode-e2e/src/suite/tools/read-file.test.ts +++ b/apps/vscode-e2e/src/suite/tools/read-file.test.ts @@ -376,7 +376,7 @@ suite.skip("Roo Code read_file Tool", function () { } }) - test("Should read file with slice offset/limit", async function () { + test("Should read file with line range", async function () { const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false @@ -446,7 +446,7 @@ suite.skip("Roo Code read_file Tool", function () { alwaysAllowReadOnly: true, alwaysAllowReadOnlyOutsideWorkspace: true, }, - text: `Use the read_file tool to read the file "${fileName}" using slice mode with offset=2 and limit=3 (1-based offset). The file contains lines like "Line 1", "Line 2", etc. After reading, show me the three lines you read.`, + text: `Use the read_file tool to read the file "${fileName}" and show me what's on lines 2, 3, and 4. The file contains lines like "Line 1", "Line 2", etc. Assume the file exists and you can read it directly.`, }) // Wait for task completion @@ -455,8 +455,9 @@ suite.skip("Roo Code read_file Tool", function () { // Verify tool was executed assert.ok(toolExecuted, "The read_file tool should have been executed") - // Verify the tool returned the correct lines (offset=2, limit=3 -> lines 2-4) + // Verify the tool returned the correct lines (when line range is used) if (toolResult && (toolResult as string).includes(" | ")) { + // The result includes line numbers assert.ok( (toolResult as string).includes("2 | Line 2"), "Tool result should include line 2 with line number", diff --git a/apps/vscode-nightly/esbuild.mjs b/apps/vscode-nightly/esbuild.mjs index 92b80b50d4f..e45dbd3c3e8 100644 --- a/apps/vscode-nightly/esbuild.mjs +++ b/apps/vscode-nightly/esbuild.mjs @@ -57,22 +57,6 @@ async function main() { * @type {import('esbuild').Plugin[]} */ const plugins = [ - { - // Stub out @basetenlabs/performance-client which contains native .node - // binaries that esbuild cannot bundle. This module is only used by - // @ai-sdk/baseten for embedding models, not for chat completions. - name: "stub-baseten-native", - setup(build) { - build.onResolve({ filter: /^@basetenlabs\/performance-client/ }, (args) => ({ - path: args.path, - namespace: "stub-baseten-native", - })) - build.onLoad({ filter: /.*/, namespace: "stub-baseten-native" }, () => ({ - contents: "module.exports = { PerformanceClient: class PerformanceClient {} };", - loader: "js", - })) - }, - }, { name: "copyPaths", setup(build) { diff --git a/apps/web-evals/next-env.d.ts b/apps/web-evals/next-env.d.ts index 7506fe6afbc..1b3be0840f3 100644 --- a/apps/web-evals/next-env.d.ts +++ b/apps/web-evals/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -import "./.next/dev/types/routes.d.ts" // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/web-evals/next.config.ts b/apps/web-evals/next.config.ts index b5f54a87be8..08ed853fc38 100644 --- a/apps/web-evals/next.config.ts +++ b/apps/web-evals/next.config.ts @@ -1,7 +1,10 @@ import type { NextConfig } from "next" const nextConfig: NextConfig = { - turbopack: {}, + webpack: (config) => { + config.resolve.extensionAlias = { ".js": [".ts", ".tsx", ".js", ".jsx"] } + return config + }, } export default nextConfig diff --git a/apps/web-evals/package.json b/apps/web-evals/package.json index 83d69edd592..9ba2c98c2c9 100644 --- a/apps/web-evals/package.json +++ b/apps/web-evals/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "lint": "eslint src --ext=ts,tsx --max-warnings=0", + "lint": "next lint --max-warnings 0", "check-types": "tsc -b", "dev": "scripts/check-services.sh && next dev -p 3446", "format": "prettier --write src", @@ -35,7 +35,7 @@ "cmdk": "^1.1.0", "fuzzysort": "^3.1.0", "lucide-react": "^0.518.0", - "next": "^16.1.6", + "next": "~15.2.8", "next-themes": "^0.4.6", "p-map": "^7.0.3", "react": "^18.3.1", diff --git a/apps/web-evals/src/app/api/runs/[id]/logs/[taskId]/route.ts b/apps/web-evals/src/app/api/runs/[id]/logs/[taskId]/route.ts new file mode 100644 index 00000000000..e5ec8751ab0 --- /dev/null +++ b/apps/web-evals/src/app/api/runs/[id]/logs/[taskId]/route.ts @@ -0,0 +1,74 @@ +import { NextResponse } from "next/server" +import type { NextRequest } from "next/server" +import * as fs from "node:fs/promises" +import * as path from "node:path" + +import { findTask, findRun } from "@roo-code/evals" + +export const dynamic = "force-dynamic" + +const LOG_BASE_PATH = "/tmp/evals/runs" + +// Sanitize path components to prevent path traversal attacks +function sanitizePathComponent(component: string): string { + // Remove any path separators, null bytes, and other dangerous characters + return component.replace(/[/\\:\0*?"<>|]/g, "_") +} + +export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string; taskId: string }> }) { + const { id, taskId } = await params + + try { + const runId = Number(id) + const taskIdNum = Number(taskId) + + if (isNaN(runId) || isNaN(taskIdNum)) { + return NextResponse.json({ error: "Invalid run ID or task ID" }, { status: 400 }) + } + + // Verify the run exists + await findRun(runId) + + // Get the task to find its language and exercise + const task = await findTask(taskIdNum) + + // Verify the task belongs to this run + if (task.runId !== runId) { + return NextResponse.json({ error: "Task does not belong to this run" }, { status: 404 }) + } + + // Sanitize language and exercise to prevent path traversal + const safeLanguage = sanitizePathComponent(task.language) + const safeExercise = sanitizePathComponent(task.exercise) + + // Construct the log file path + const logFileName = `${safeLanguage}-${safeExercise}.log` + const logFilePath = path.join(LOG_BASE_PATH, String(runId), logFileName) + + // Verify the resolved path is within the expected directory (defense in depth) + const resolvedPath = path.resolve(logFilePath) + const expectedBase = path.resolve(LOG_BASE_PATH) + if (!resolvedPath.startsWith(expectedBase)) { + return NextResponse.json({ error: "Invalid log path" }, { status: 400 }) + } + + // Check if the log file exists and read it (async) + try { + const logContent = await fs.readFile(logFilePath, "utf-8") + return NextResponse.json({ logContent }) + } catch (err) { + if ((err as NodeJS.ErrnoException).code === "ENOENT") { + return NextResponse.json({ error: "Log file not found", logContent: null }, { status: 200 }) + } + throw err + } + } catch (error) { + console.error("Error reading task log:", error) + + if (error instanceof Error && error.name === "RecordNotFoundError") { + return NextResponse.json({ error: "Task or run not found" }, { status: 404 }) + } + + return NextResponse.json({ error: "Failed to read log file" }, { status: 500 }) + } +} diff --git a/apps/web-evals/src/app/api/runs/[id]/logs/failed/route.ts b/apps/web-evals/src/app/api/runs/[id]/logs/failed/route.ts new file mode 100644 index 00000000000..8b2760df987 --- /dev/null +++ b/apps/web-evals/src/app/api/runs/[id]/logs/failed/route.ts @@ -0,0 +1,147 @@ +import { NextResponse } from "next/server" +import type { NextRequest } from "next/server" +import * as fs from "node:fs" +import * as path from "node:path" +import archiver from "archiver" + +import { findRun, getTasks } from "@roo-code/evals" + +export const dynamic = "force-dynamic" + +const LOG_BASE_PATH = "/tmp/evals/runs" + +// Sanitize path components to prevent path traversal attacks +function sanitizePathComponent(component: string): string { + // Remove any path separators, null bytes, and other dangerous characters + return component.replace(/[/\\:\0*?"<>|]/g, "_") +} + +export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { + const { id } = await params + + try { + const runId = Number(id) + + if (isNaN(runId)) { + return NextResponse.json({ error: "Invalid run ID" }, { status: 400 }) + } + + // Verify the run exists + await findRun(runId) + + // Get all tasks for this run + const tasks = await getTasks(runId) + + // Filter for failed tasks only + const failedTasks = tasks.filter((task) => task.passed === false) + + if (failedTasks.length === 0) { + return NextResponse.json({ error: "No failed tasks to export" }, { status: 400 }) + } + + // Create a zip archive + const archive = archiver("zip", { zlib: { level: 9 } }) + + // Collect chunks to build the response + const chunks: Buffer[] = [] + + archive.on("data", (chunk: Buffer) => { + chunks.push(chunk) + }) + + // Track archive errors + let archiveError: Error | null = null + archive.on("error", (err: Error) => { + archiveError = err + }) + + // Set up the end promise before finalizing (proper event listener ordering) + const archiveEndPromise = new Promise((resolve, reject) => { + archive.on("end", resolve) + archive.on("error", reject) + }) + + // Add each failed task's log file and history files to the archive + const logDir = path.join(LOG_BASE_PATH, String(runId)) + let filesAdded = 0 + + for (const task of failedTasks) { + // Sanitize language and exercise to prevent path traversal + const safeLanguage = sanitizePathComponent(task.language) + const safeExercise = sanitizePathComponent(task.exercise) + const expectedBase = path.resolve(LOG_BASE_PATH) + + // Add the log file + const logFileName = `${safeLanguage}-${safeExercise}.log` + const logFilePath = path.join(logDir, logFileName) + + // Verify the resolved path is within the expected directory (defense in depth) + const resolvedLogPath = path.resolve(logFilePath) + if (resolvedLogPath.startsWith(expectedBase) && fs.existsSync(logFilePath)) { + archive.file(logFilePath, { name: logFileName }) + filesAdded++ + } + + // Add the API conversation history file + // Format: {language}-{exercise}.{iteration}_api_conversation_history.json + const apiHistoryFileName = `${safeLanguage}-${safeExercise}.${task.iteration}_api_conversation_history.json` + const apiHistoryFilePath = path.join(logDir, apiHistoryFileName) + const resolvedApiHistoryPath = path.resolve(apiHistoryFilePath) + if (resolvedApiHistoryPath.startsWith(expectedBase) && fs.existsSync(apiHistoryFilePath)) { + archive.file(apiHistoryFilePath, { name: apiHistoryFileName }) + filesAdded++ + } + + // Add the UI messages file + // Format: {language}-{exercise}.{iteration}_ui_messages.json + const uiMessagesFileName = `${safeLanguage}-${safeExercise}.${task.iteration}_ui_messages.json` + const uiMessagesFilePath = path.join(logDir, uiMessagesFileName) + const resolvedUiMessagesPath = path.resolve(uiMessagesFilePath) + if (resolvedUiMessagesPath.startsWith(expectedBase) && fs.existsSync(uiMessagesFilePath)) { + archive.file(uiMessagesFilePath, { name: uiMessagesFileName }) + filesAdded++ + } + } + + // Check if any files were actually added + if (filesAdded === 0) { + archive.abort() + return NextResponse.json( + { error: "No log files found - they may have been cleared from disk" }, + { status: 404 }, + ) + } + + // Finalize the archive + await archive.finalize() + + // Wait for all data to be collected + await archiveEndPromise + + // Check for archive errors + if (archiveError) { + throw archiveError + } + + // Combine all chunks into a single buffer + const zipBuffer = Buffer.concat(chunks) + + // Return the zip file + return new NextResponse(zipBuffer, { + status: 200, + headers: { + "Content-Type": "application/zip", + "Content-Disposition": `attachment; filename="run-${runId}-failed-logs.zip"`, + "Content-Length": String(zipBuffer.length), + }, + }) + } catch (error) { + console.error("Error exporting failed logs:", error) + + if (error instanceof Error && error.name === "RecordNotFoundError") { + return NextResponse.json({ error: "Run not found" }, { status: 404 }) + } + + return NextResponse.json({ error: "Failed to export logs" }, { status: 500 }) + } +} diff --git a/apps/web-roo-code/next.config.ts b/apps/web-roo-code/next.config.ts index 0aaf2849d55..a2591c1a30f 100644 --- a/apps/web-roo-code/next.config.ts +++ b/apps/web-roo-code/next.config.ts @@ -1,9 +1,9 @@ -import path from "path" import type { NextConfig } from "next" const nextConfig: NextConfig = { - turbopack: { - root: path.join(__dirname, "../.."), + webpack: (config) => { + config.resolve.extensionAlias = { ".js": [".ts", ".tsx", ".js", ".jsx"] } + return config }, async redirects() { return [ diff --git a/apps/web-roo-code/package.json b/apps/web-roo-code/package.json index 90b6e9e3069..d82cad56ab8 100644 --- a/apps/web-roo-code/package.json +++ b/apps/web-roo-code/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "lint": "eslint src --ext=ts,tsx --max-warnings=0", + "lint": "next lint --max-warnings 0", "check-types": "tsc --noEmit", "dev": "next dev", "build": "next build", @@ -12,23 +12,22 @@ "clean": "rimraf .next .turbo" }, "dependencies": { - "@radix-ui/react-dialog": "^1.1.15", - "@radix-ui/react-navigation-menu": "^1.2.14", - "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-slot": "^1.2.3", "@roo-code/evals": "workspace:^", - "@roo-code/types": "^1.108.0", - "@tanstack/react-query": "^5.90.20", - "@vercel/og": "^0.8.6", + "@roo-code/types": "workspace:^", + "@tanstack/react-query": "^5.79.0", + "@vercel/og": "^0.6.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "embla-carousel-auto-scroll": "^8.6.0", "embla-carousel-autoplay": "^8.6.0", "embla-carousel-react": "^8.6.0", - "framer-motion": "^12.29.2", - "lucide-react": "^0.563.0", - "next": "^16.1.6", + "framer-motion": "12.15.0", + "lucide-react": "^0.518.0", + "next": "~15.2.8", "next-themes": "^0.4.6", - "posthog-js": "^1.336.4", + "posthog-js": "^1.248.1", "react": "^18.3.1", "react-cookie-consent": "^9.0.0", "react-dom": "^18.3.1", @@ -37,7 +36,7 @@ "recharts": "^2.15.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", - "tailwind-merge": "^3.4.0", + "tailwind-merge": "^3.3.0", "tailwindcss-animate": "^1.0.7", "tldts": "^6.1.86", "zod": "^3.25.61" @@ -45,13 +44,13 @@ "devDependencies": { "@roo-code/config-eslint": "workspace:^", "@roo-code/config-typescript": "workspace:^", - "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/typography": "^0.5.16", "@types/node": "20.x", "@types/react": "^18.3.23", "@types/react-dom": "^18.3.7", - "autoprefixer": "^10.4.23", + "autoprefixer": "^10.4.21", "next-sitemap": "^4.2.3", - "postcss": "^8.5.6", + "postcss": "^8.5.4", "tailwindcss": "^3.4.17" } } diff --git a/apps/web-roo-code/src/app/cloud/page.tsx b/apps/web-roo-code/src/app/cloud/page.tsx index 51df0642eec..1da9cad2afb 100644 --- a/apps/web-roo-code/src/app/cloud/page.tsx +++ b/apps/web-roo-code/src/app/cloud/page.tsx @@ -5,9 +5,9 @@ import { ChartLine, Github, History, - ListChecks, LucideIcon, Pencil, + Router, Share2, Slack, Users, @@ -22,7 +22,7 @@ import { SEO } from "@/lib/seo" import { ogImageUrl } from "@/lib/og" import { EXTERNAL_LINKS } from "@/lib/constants" // Workaround for next/image choking on these for some reason -import screenshotDark from "../../../public/heroes/cloud-screen.png" +import screenshotDark from "/public/heroes/cloud-screen.png" const TITLE = "Roo Code Cloud" const DESCRIPTION = @@ -112,9 +112,9 @@ const features: Feature[] = [ description: "Start tasks, get updates, and collaborate with agents directly from your team's Slack channels.", }, { - icon: ListChecks, - title: "Linear Integration", - description: "Assign issues to Roo Code directly from Linear. Get PRs back without switching tools.", + icon: Router, + title: "Roomote Control", + description: "Connect to your local VS Code instance and control the extension remotely from the browser.", }, { icon: Users, diff --git a/apps/web-roo-code/src/app/linear/page.tsx b/apps/web-roo-code/src/app/linear/page.tsx deleted file mode 100644 index 40334e2698a..00000000000 --- a/apps/web-roo-code/src/app/linear/page.tsx +++ /dev/null @@ -1,413 +0,0 @@ -import { - ArrowRight, - CheckCircle, - CreditCard, - Eye, - GitBranch, - GitPullRequest, - Link2, - MessageSquare, - Settings, - Shield, -} from "lucide-react" -import type { LucideIcon } from "lucide-react" -import type { Metadata } from "next" - -import { AnimatedBackground } from "@/components/homepage" -import { LinearIssueDemo } from "@/components/linear/linear-issue-demo" -import { Button } from "@/components/ui" -import { EXTERNAL_LINKS } from "@/lib/constants" -import { SEO } from "@/lib/seo" -import { ogImageUrl } from "@/lib/og" - -const TITLE = "Roo Code for Linear" -const DESCRIPTION = "Assign development work to @Roo Code directly from Linear. Get PRs back without switching tools." -const OG_DESCRIPTION = "Turn Linear Issues into Pull Requests" -const PATH = "/linear" - -// Featured Workflow section is temporarily commented out until video is ready -// const LINEAR_DEMO_YOUTUBE_ID = "" - -export const metadata: Metadata = { - title: TITLE, - description: DESCRIPTION, - alternates: { - canonical: `${SEO.url}${PATH}`, - }, - openGraph: { - title: TITLE, - description: DESCRIPTION, - url: `${SEO.url}${PATH}`, - siteName: SEO.name, - images: [ - { - url: ogImageUrl(TITLE, OG_DESCRIPTION), - width: 1200, - height: 630, - alt: TITLE, - }, - ], - locale: SEO.locale, - type: "website", - }, - twitter: { - card: SEO.twitterCard, - title: TITLE, - description: DESCRIPTION, - images: [ogImageUrl(TITLE, OG_DESCRIPTION)], - }, - keywords: [ - ...SEO.keywords, - "linear integration", - "issue to PR", - "AI in Linear", - "engineering workflow automation", - "Roo Code Cloud", - ], -} - -// Invalidate cache when a request comes in, at most once every hour. -export const revalidate = 3600 - -type ValueProp = { - icon: LucideIcon - title: string - description: string -} - -const VALUE_PROPS: ValueProp[] = [ - { - icon: GitBranch, - title: "Work where you already work.", - description: - "Assign development work to @Roo Code directly from Linear. No new tools to learn, no context switching required.", - }, - { - icon: Eye, - title: "Progress is visible.", - description: - "Watch progress unfold in real-time. Roo Code posts updates as comments, so your whole team stays in the loop.", - }, - { - icon: MessageSquare, - title: "Mention for refinement.", - description: - 'Need changes? Just comment "@Roo Code also add dark mode support" and the agent picks up where it left off.', - }, - { - icon: Link2, - title: "Full traceability.", - description: - "Every PR links back to the originating issue. Every issue shows its linked PR. Your audit trail stays clean.", - }, - { - icon: Settings, - title: "Organization-level setup.", - description: - "Connect once, use everywhere. Your team members can assign issues to @Roo Code without individual configuration.", - }, - { - icon: Shield, - title: "Safe by design.", - description: - "Agents never touch main/master directly. They produce branches and PRs. You review and approve before merge.", - }, -] - -// type WorkflowStep = { -// step: number -// title: string -// description: string -// } - -// const WORKFLOW_STEPS: WorkflowStep[] = [ -// { -// step: 1, -// title: "Create an issue", -// description: "Write your issue with acceptance criteria. Be as detailed as you like.", -// }, -// { -// step: 2, -// title: "Call @Roo Code", -// description: "Mention @Roo Code in a comment to start. The agent begins working immediately.", -// }, -// { -// step: 3, -// title: "Watch progress", -// description: "Roo Code posts status updates as comments. Refine with @-mentions if needed.", -// }, -// { -// step: 4, -// title: "Review the PR", -// description: "When ready, the PR link appears in the issue. Review, iterate, and ship.", -// }, -// ] - -type OnboardingStep = { - icon: LucideIcon - title: string - description: string - link?: { - href: string - text: string - } -} - -const ONBOARDING_STEPS: OnboardingStep[] = [ - { - icon: CreditCard, - title: "1. Team Plan", - description: "Linear integration requires a Team plan.", - link: { - href: EXTERNAL_LINKS.CLOUD_APP_TEAM_TRIAL, - text: "Start a free trial", - }, - }, - { - icon: GitPullRequest, - title: "2. Connect GitHub", - description: "Link your repositories so Roo Code can open PRs on your behalf.", - }, - { - icon: Settings, - title: "3. Connect Linear", - description: "Authorize via OAuth. No API keys to manage or rotate.", - }, - { - icon: CheckCircle, - title: "4. Link & Start", - description: "Map your Linear project to a repo, then assign or mention @Roo Code.", - }, -] - -function LinearIcon({ className }: { className?: string }) { - return ( - - - - ) -} - -export default function LinearPage(): JSX.Element { - return ( - <> - {/* Hero Section */} -
- -
-
-
-
- - Powered by Roo Code Cloud -
-

- Turn Linear Issues into Pull Requests -

-

- Assign development work to @Roo Code directly from Linear. Get PRs back without - switching tools. -

- -
- -
- -
-
-
-
- - {/* Value Props Section */} -
-
-
-
-
-
-

- Why your team will love using Roo Code in Linear -

-

- AI agents that understand context, keep your team in the loop, and deliver PRs you can - review. -

-
-
- {VALUE_PROPS.map((prop, index) => { - const Icon = prop.icon - return ( -
-
- -
-

{prop.title}

-

{prop.description}

-
- ) - })} -
-
-
- - {/* Featured Workflow Section - temporarily commented out until video is ready -
-
-
-
-
- -
-
- - Featured Workflow -
-

Issue to Shipped Feature

-

- Stay in Linear from assignment to review. Roo Code keeps the issue updated and links the PR - when it's ready. -

-
- -
-
- {/* YouTube Video Embed or Placeholder */} - {/*
- {LINEAR_DEMO_YOUTUBE_ID ? ( -