# Contributing to Mysti Thank you for your interest in contributing to Mysti! We welcome contributions from the community. ## Ways to Contribute - **Bug Reports**: Found a bug? [Open an issue](https://github.com/DeepMyst/Mysti/issues/new) - **Feature Requests**: Have an idea? [Start a discussion](https://github.com/DeepMyst/Mysti/issues/new) - **Code Contributions**: Fix bugs or add features via pull requests - **Documentation**: Improve README, add examples, or fix typos - **Testing**: Try new features and report feedback ## Getting Started ### Prerequisites - Node.js from `.nvmrc` (`nvm install && nvm use` if using nvm). The supported engine range is declared in `package.json`. - VS Code satisfying `engines.vscode` in `package.json`. - A provider CLI/account is needed for live provider testing. Unit tests do not require credentials. For example: - `npm install -g @anthropic-ai/claude-code` - `npm install -g @google/gemini-cli` - `npm install -g @github/copilot` ### Development Setup 1. **Fork and clone the repository** ```bash git clone https://github.com/YOUR_USERNAME/Mysti.git cd Mysti ``` 2. **Install dependencies** ```bash npm ci ``` 3. **Start development build** ```bash npm run watch ``` 4. **Launch Extension Development Host** - Leave `npm run watch` from step 3 **running** — F5 does not build for you, and it will happily launch against a stale or absent `dist/extension.js` with no error explaining why your change is missing. - Press `F5` in VS Code - A new VS Code window opens with Mysti loaded - Set breakpoints and debug in the original window; filter the Debug Console by `[Mysti]` for the extension's own logs Install the browser used by the webview suites with `npx playwright install chromium`. Run `npm run typecheck`, `npm run lint`, `npm test`, and `npm run compile:release` before requesting review. CI requires Chromium and blocks on lint, test, build and package-shape failures. See [maintenance and releases](docs/MAINTENANCE.md) for the complete verification workflow and [architecture](docs/ARCHITECTURE.md) for module boundaries. ### Project Structure ``` Mysti/ ├── src/ │ ├── extension.ts # Entry point │ ├── providers/ # AI provider implementations │ │ ├── base/ # BaseCliProvider, IProvider interface │ │ ├── claude/ # Claude Code provider │ │ ├── codex/ # OpenAI Codex provider │ │ ├── copilot/ # GitHub Copilot provider │ │ └── gemini/ # Google Gemini provider │ ├── managers/ # Business logic managers │ ├── chat/ # Panel identity and interaction ownership │ ├── services/ # Transport, storage and integration services │ ├── canvas/ # Document model, operations and typed protocol │ ├── webview/ # HTML loaders and Canvas browser source │ └── types.ts # TypeScript type definitions ├── media/chat/ # Chat browser scripts and styles ├── tests/ # Vitest and Chromium suites ├── tests-vscode/ # Real extension-host integration tests ├── resources/ # Icons, logos, agent definitions └── package.json # Extension manifest ``` ## Pull Request Process 1. **Create a feature branch** ```bash git checkout -b feature/your-feature-name ``` 2. **Make your changes** - Follow existing code style - Add comments for complex logic - Use `[Mysti]` prefix for console logs 3. **Test your changes** - Run `npm run typecheck`, `npm run lint`, `npm test`, and `npm run compile:release`. Treat every failing check as a failure to resolve; do not retry until green or lower rule severity. - Press `F5` to launch Extension Development Host - Test with multiple providers if applicable - Add regression tests for behavioral changes: malformed inputs, cancellation, isolation between panels, and cleanup matter more than implementation details. - For packaged/runtime changes, run `npm run package` and check the resulting VSIX with `node scripts/check-package-shape.js mysti-.vsix`. - Check the Debug Console for errors 4. **Commit with clear messages** ```bash git commit -m "feat: add support for new feature" ``` Use conventional commits: - `feat:` - New feature - `fix:` - Bug fix - `docs:` - Documentation - `refactor:` - Code refactoring - `test:` - Tests 5. **Push and create PR** ```bash git push origin feature/your-feature-name ``` Then open a Pull Request on GitHub. ## Code Style - **TypeScript**: Use strict types, avoid `any` - **Naming**: Private members use `_` prefix (`_currentProcess`) - **Logging**: Use `console.log('[Mysti] ProviderName: message')` - **Error handling**: Handle errors at the boundary that can recover or report them. Preserve cancellation, release owned resources, and avoid logging secrets. - **External data**: Parse as `unknown` and validate fields before using them. - **Modularity**: Keep new stateful behavior behind a small API with explicit ownership and disposal. Do not add unrelated behavior to the main chat controller. - **Dependencies**: Commit manifest and lockfile updates together; use `npm ci` to verify the new lock. See the maintenance guide before changing engine ranges. ## Adding a New Provider Ten steps, not six. Steps 6 and 9 are enforced — miss them and `tsc` or `npm run lint` fails — but the rest are silent, so work down the list. 1. Create the class in `src/providers//`, extending `BaseCliProvider`. 2. Implement the abstract methods: `discoverCli()`, `getCliPath()`, `buildCliArgs()`, `parseStreamLine()`, `getAuthConfig()`, `checkAuthentication()`, `getAuthCommand()`, `getInstallCommand()`. 3. Implement `_createSession(panelId)` returning your provider's session state. Per-panel state lives there — never as an instance field on the provider. 4. Declare `capabilities` **truthfully**. The UI is capability-driven, so a flag that lies produces a control that does nothing. In particular `supportsPromptEnhancement` must be `true` only if you implement `enhancePrompt()` — `tests/providers/promptEnhancement.test.ts` fails if the flag and the method disagree. 5. Register it in `_registerBuiltInProviders()` in `src/providers/ProviderRegistry.ts`. 6. Add the id to **both** the `ProviderType` **and** `AgentType` unions in `src/types.ts`, then to the four TS-enforced maps — `PROVIDER_DISPLAY_META` and `PROVIDER_CUSTOM_MODEL_SETTING_KEYS` in `src/providers/base/ProviderManifest.ts` (both `Record`), and `AGENT_BRAINSTORM_ICONS` and `agentKeyMap` in `src/managers/BrainstormManager.ts` (both `Record` — the same 15 ids; `agentKeyMap` is a local inside the method, so grep for it rather than expecting an export). All four are exhaustive `Record`s over a union, so a miss is a compile error, not a silent gap. 7. Add the settings in `package.json`: the `defaultProvider` enum plus its enumDescription, `Path`, `Model`, the `brainstorm.synthesisAgent` and `brainstorm.agents` enums, and `agents.Persona` / `agents.CustomPrompt`. Paths and API keys are `"scope": "machine"` — `tests/utils/settingsScopeParity.test.ts` enforces that by key shape. 8. Webview: logo in `resources/icons/`, boot URI in `src/webview/webviewContent.ts`, `LOGO_BY_ICON_PATH` in `media/chat/chat.js`, and the agent-menu item plus setup-wizard card in `media/chat/index.html`, inside the provider-literals allowlist markers. (The chat UI is **static assets under `media/chat/`**, not a template string in `webviewContent.ts` — that extraction landed in Plan 03.) 9. Add the id to `PROVIDER_IDS` in `scripts/check-provider-literals.js` (the lint guard, which runs first in `npm run lint`) and to `_getProviderDisplayName` in `src/managers/SlashCommandManager.ts`. 10. Tests: a `TestableXProvider` in `tests/helpers/providerFactory.ts`, a `createXSession` in `tests/helpers/sessionFactory.ts`, a `tests/providers//` suite, and the provider-id enumerations in `tests/providers/providerManifest.test.ts`, `tests/integration/chatViewDebranding.test.ts` and `tests/webview/mentionParsing.test.ts`. `GeminiProvider` is the cleanest reference for a stream-json CLI backend; `HermesProvider` for an ACP/persistent-process one. ## Good First Issues Look for issues labeled [`good first issue`](https://github.com/DeepMyst/Mysti/labels/good%20first%20issue) - these are great starting points for new contributors. ## Questions? - [Open an issue](https://github.com/DeepMyst/Mysti/issues) for bugs or features - Check existing issues before creating new ones ## License By contributing to Mysti, you agree that your contributions will be licensed under the Apache License 2.0. --- Thank you for helping make Mysti better! ## Mysti 2.0 BETA contributions Read [Getting started](docs/GETTING-STARTED.md), [assignment semantics](docs/MENTIONS.md), and [architecture](docs/ARCHITECTURE.md) before changing routing. An explicit tag is a user assignment: a model must not drop it, substitute a different provider, or invent another agent's answer. For routing changes, test selected-provider inclusion, simultaneous independent starts, dependencies, unavailable/auth-failed providers, write serialization, native approval, Stop, superseding sends, and distinct repeated roles. Use deterministic barriers to prove concurrency rather than timing thresholds. Exercise the actual webview when changing progress or attribution; a host event with no renderer is not a complete feature. Useful focused checks: ```sh npm test -- tests/managers/explicitMentions.test.ts tests/managers/collaborationManager.test.ts npm test -- tests/services/collaboratorPoolNativeApproval.test.ts tests/integration/chatViewMessagePersistence.test.ts npm test -- tests/webview/collaborationBrowser.test.ts npm run typecheck npm run lint ``` For release presentation, update the README, feature-specific guide, CHANGELOG and versioned release notes together. Keep account requirements and beta limitations visible. Do not claim platform or live-provider validation from mocked tests. Community translations should link the current canonical guide until updated. Record new visual changes with `npm run demo:record` after installing Chromium and FFmpeg. Review every frame for secrets, clipping, and unsupported claims. Preserve the sample-data label on fixture captures. See the [media kit](docs/releases/2.0-beta/README.md) for reproducibility and the [maintenance guide](docs/MAINTENANCE.md) for packaging and exact-commit release checks.