Skip to content

Latest commit

 

History

History
222 lines (172 loc) · 10.7 KB

File metadata and controls

222 lines (172 loc) · 10.7 KB

copilot-instructions.md

<ai_meta> <parsing_rules> - Process development patterns in sequential order - Use exact patterns and templates provided - Follow MUST/ALWAYS/REQUIRED directives strictly - Never deviate from established architectural patterns </parsing_rules> <file_conventions> - encoding: UTF-8 - line_endings: LF - indent: 4 spaces (Python, TypeScript, Kotlin) - package_structure: packages/ for Python, vscode-client/ for TypeScript, intellij-client/ for Kotlin </file_conventions> </ai_meta>

RobotCode is a comprehensive Robot Framework toolkit that provides IDE extensions (VS Code, IntelliJ), CLI tools, and Language Server Protocol implementation. It uses Robot Framework's native parser for full compatibility while extending it with modern development tools like DAP debugging, test discovery, and multi-workspace support.

Quick Start for Agents

Key Commands

Task Command
Lint all (style + types) hatch run lint:all
Auto-fix lint hatch run lint:fix
Run tests pytest .
Run tests (specific matrix) hatch run test.rf70.py311:test
Update snapshots pytest --regtest2-reset
Coverage hatch run cov
Build VS Code extension npm run compile && npm run package
Build IntelliJ plugin cd intellij-client && gradle buildPlugin
Bump version hatch run build:bump

Key Files

File Purpose
pyproject.toml Root project config, ruff/mypy/pytest settings
hatch.toml Hatch environments, scripts, test matrix
package.json VS Code extension manifest (commands, activation, config)
robot.toml Robot Framework project configuration
src/robotcode/cli/ CLI entry point (robotcode command)
packages/plugin/ Plugin system (pluggy-based hook specs)

Common Pitfalls

  • Namespace packages: All Python packages live under the robotcode.* namespace. The __init__.py files in robotcode/ directories are empty — never add imports to them.
  • Plugin registration: New CLI commands or tools must be registered via [project.entry-points.robotcode] in the package's pyproject.toml and use @hookimpl from robotcode.plugin.
  • Snapshot tests: If test output changes intentionally, reset snapshots with pytest --regtest2-reset. Failing to do so causes false negatives.
  • Python environment: Always ask your tools which Python interpreter is selected for the workspace before running commands.
  • VS Code build: The extension uses esbuild (not webpack). Run npm run compile for development, npm run package for production.
  • Version files: Never edit __version__.py or version strings manually — use hatch run build:bump and scripts/update_git_versions.py to keep all 12+ packages in sync.
  • Bundled libs: Never edit bundled/libs/ manually — it's regenerated by build scripts. Add new runtime deps to bundled_requirements.txt.

Agent Communication Guidelines

Core Rules

  • REVIEW/ANALYZE/CHECK/EXAMINE: READ-ONLY operations. Provide analysis and feedback, NEVER make changes.
  • IMPLEMENT/ADD/CREATE/FIX/CHANGE: Implementation required. ALWAYS ask for confirmation and wait for explicit user choice before proceeding.
  • IMPROVE/OPTIMIZE/REFACTOR: Always ask for specific approach before implementing.
  • MANDATORY WAIT: When presenting implementation options, ALWAYS wait for explicit user choice before proceeding.

Communication Flow

  1. Recognize Intent: Review request vs. Implementation request?
  2. For Reviews: Analyze and suggest, but don't change anything.
  3. For Implementation:
    • ALWAYS ask for confirmation before implementing.
    • If multiple approaches exist, present numbered options A), B), C), D), ...).
    • ALWAYS end with "Other approach".
    • WAIT for user response before proceeding.
    • NEVER start implementation until user explicitly chooses an option.
  4. Critical Rule: When presenting options, STOP and wait for user input. Do not continue with any implementation.

Tech Stack

  • Language Server: Python 3.10–3.14 with asyncio
  • Protocol: LSP + DAP
  • Parser: Robot Framework native parser
  • Build: Hatch (Python), esbuild (VS Code), Gradle (IntelliJ)
  • Linting: ruff (format + lint) + mypy (type checking)
  • Testing: pytest + regtest2 snapshots, matrix across Python 3.10–3.14 × Robot Framework 5.0–7.4
  • VS Code extension: TypeScript, manager-based lifecycle
  • IntelliJ plugin: Kotlin via LSP4IJ

Architecture

Repository Layout

src/robotcode/cli/          # CLI entry point (Click-based, plugin-loaded commands)
packages/
├── core/                   # Base utilities (documents, workspace, URI, async tools)
├── plugin/                 # Plugin system (pluggy hookspecs + manager singleton)
├── jsonrpc2/               # JSON-RPC communication layer
├── robot/                  # Robot Framework integration (config, diagnostics, project)
├── language_server/        # LSP implementation
├── debugger/               # DAP implementation
├── runner/                 # Enhanced RF execution tools
├── analyze/                # Static code analysis
├── repl/                   # Interactive RF shell
├── repl_server/            # REPL server for remote connections
└── modifiers/              # Code transformation tools

vscode-client/
├── extension/              # VS Code extension (TypeScript, manager pattern)
└── rendererLog/            # Notebook log renderer

intellij-client/
├── src/main/kotlin/        # IntelliJ plugin (Kotlin, LSP4IJ bridge)
└── build.gradle.kts        # Gradle config

Namespace Package Pattern

All Python packages share the robotcode namespace. Each package lives at:

packages/{name}/src/robotcode/{name}/

Each package has its own pyproject.toml with version, dependencies, and entry points. The __init__.py files in robotcode/ directories are empty — exports are defined in submodules.

Plugin System

The CLI (robotcode command) discovers features via pluggy:

  1. Hook specs in packages/plugin/src/robotcode/plugin/specs.py define register_cli_commands() and register_tool_config_classes()
  2. Packages register via [project.entry-points.robotcode] in their pyproject.toml:
    [project.entry-points.robotcode]
    langserver = "robotcode.language_server.hooks"
  3. Hook implementations use @hookimpl to return Click commands or config classes
  4. PluginManager (PluginManager.instance()) loads all entry points at startup

Package Dependency Graph

core ──────────────┐
plugin ─────────┐  │
                ▼  ▼
jsonrpc2 ──► robot ◄── analyze
                │         │
                ▼         │
          language_server ◄┘
                │
debugger ◄── runner
repl ◄── repl_server
modifiers (standalone)
  • core and plugin are leaf dependencies — most packages depend on them
  • language_server depends on jsonrpc2, robot, analyze, and the root robotcode CLI
  • debugger depends on jsonrpc2 and runner

Version Management

All 12 Python packages + VS Code extension + IntelliJ plugin share a single synchronized version. Each package has its own __version__.py, but versions are never edited manually. Instead:

  1. hatch run build:bump (commitizen) bumps the version
  2. scripts/update_git_versions.py propagates the version to all __version__.py files, cross-package pyproject.toml dependencies, package.json, and gradle.properties
  3. CI triggers on git tags (v*) and uses get_release_version to derive the version from git history

All inter-package dependencies are pinned to the same version — packages are never independently versioned.

Bundled Dependencies

bundled/libs/ is an isolated, offline-capable Python runtime for the VS Code extension. The language server runs from this directory without requiring pip install.

  • bundled_requirements.txt lists external runtime deps (click, pluggy, tomli, platformdirs, colorama, typing-extensions)
  • scripts/install_bundled_editable.py installs all deps + all packages/*/ into bundled/libs/
  • .pth files in bundled/libs/ manage sys.path injection
  • Never edit bundled/libs/ manually — it's regenerated by the build scripts

LSP Protocol Parts Pattern

LSP features are implemented as modular *ProtocolPart classes in packages/language_server/:

  1. Each part inherits from LanguageServerProtocolPart (→ GenericJsonRPCProtocolPart)
  2. Methods are annotated with @rpc_method(name, param_type=..., cancelable=..., threaded=...) from packages/jsonrpc2/
  3. Parts register themselves via constructor: parent.registry.add_class_part_instance(self)
  4. The RpcRegistry descriptor auto-discovers all @rpc_method methods via introspection; lazy-initializes on first access

To add a new LSP feature: create a new *ProtocolPart class, decorate handlers with @rpc_method, and register the part in the protocol's __init__.

Configuration

  • robot.toml (project root): Robot Framework project settings — python paths, suite paths, profiles, analyze options
  • pyproject.toml: Ruff, mypy, pytest, and coverage configuration
  • hatch.toml: Development environments, test matrix, build scripts
  • Environment variable prefix: ROBOTCODE (auto-detected by CLI)

Project-Wide Standards

Language Requirement

English for all code and docs (REQUIRED): Documentation, comments, docstrings, identifiers, and commit messages must use English regardless of contributor's native language.

Commit Messages

Conventional Commits (REQUIRED): <type>(<scope>): <short description>

Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert

Example: feat(cli): add --dry-run flag to publish command

Breaking changes: add BREAKING CHANGE: <description> in footer.

Code Quality Principles

  • Readability over cleverness; meaningful names; single responsibility
  • Small functions (under 20 lines when possible); early returns over deep nesting
  • Type annotations required for all APIs (Python type hints, TypeScript types)
  • Explicit error handling with proper exception hierarchies; fail fast
  • Async patterns where applicable; lazy loading; appropriate caching
  • Inline comments explain why, not what

Testing

  • pytest with regtest2 for snapshot testing
  • Matrix: Python 3.10–3.14 × Robot Framework 5.0–7.4
  • Tests in tests/robotcode/ mirror package structure
  • asyncio_mode = "auto" — async tests run automatically
  • Each test must be independently runnable