Skip to content

Commit a282067

Browse files
authored
Plugin api (#164)
1 parent e234e8f commit a282067

127 files changed

Lines changed: 8348 additions & 5017 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/nightly.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,6 @@ jobs:
176176
with:
177177
components: rustfmt, clippy
178178

179-
- name: Add WASI target
180-
run: rustup target add wasm32-wasip1
181-
182179
- name: Setup sccache
183180
uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9
184181

.github/workflows/opencode-review.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,40 @@ jobs:
1111
permissions:
1212
id-token: write
1313
contents: read
14-
pull-requests: read
15-
issues: read
14+
pull-requests: write
15+
issues: write
16+
1617
steps:
1718
- uses: actions/checkout@v6
1819
with:
1920
persist-credentials: false
20-
- uses: anomalyco/opencode/github@latest
21+
22+
- name: primary
23+
id: review_primary
24+
continue-on-error: true
25+
uses: anomalyco/opencode/github@2410593023d2c61f05123c9b0faf189a28dfbeee
26+
env:
27+
OPENCODE_API_KEY: ${{ secrets.ZEN_API_KEY }}
28+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
with:
31+
model: ${{ vars.OPENCODE_REVIEW_MODEL }}
32+
use_github_token: true
33+
prompt: |
34+
Review this pull request:
35+
- Check for code quality issues
36+
- Look for potential bugs
37+
- Suggest improvements
38+
39+
- name: fallback
40+
if: steps.review_primary.outcome == 'failure'
41+
uses: anomalyco/opencode/github@2410593023d2c61f05123c9b0faf189a28dfbeee
2142
env:
43+
OPENCODE_API_KEY: ${{ secrets.ZEN_API_KEY }}
2244
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
2345
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2446
with:
25-
model: openai/gpt-5.1-codex-mini
47+
model: ${{ vars.OPENCODE_REVIEW_MODEL_FALLBACK }}
2648
use_github_token: true
2749
prompt: |
2850
Review this pull request:

.github/workflows/opencode.yml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,34 @@ jobs:
1919
permissions:
2020
id-token: write
2121
contents: read
22-
pull-requests: read
23-
issues: read
22+
pull-requests: write
23+
issues: write
24+
2425
steps:
2526
- name: Checkout repository
2627
uses: actions/checkout@v6
2728
with:
2829
persist-credentials: false
2930

30-
- name: Run opencode
31-
uses: anomalyco/opencode/github@latest
31+
- name: primary
32+
id: opencode_primary
33+
continue-on-error: true
34+
# Pinned to an immutable commit for CodeQL (tag: github-v1.2.17)
35+
uses: anomalyco/opencode/github@2410593023d2c61f05123c9b0faf189a28dfbeee
36+
env:
37+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
38+
OPENCODE_API_KEY: ${{ secrets.ZEN_API_KEY }}
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
with:
41+
model: ${{ vars.OPENCODE_DEFAULT_MODEL }}
42+
43+
- name: fallback
44+
if: steps.opencode_primary.outcome == 'failure'
45+
# Pinned to an immutable commit for CodeQL (tag: github-v1.2.17)
46+
uses: anomalyco/opencode/github@2410593023d2c61f05123c9b0faf189a28dfbeee
3247
env:
3348
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
49+
OPENCODE_API_KEY: ${{ secrets.ZEN_API_KEY }}
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3451
with:
35-
model: openai/gpt-5.1-codex-mini
52+
model: ${{ vars.OPENCODE_DEFAULT_MODEL_FALLBACK }}

.github/workflows/publish-stable.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ jobs:
6666
with:
6767
components: rustfmt, clippy
6868

69-
- name: Add WASI target
70-
run: rustup target add wasm32-wasip1
71-
7269
- name: Setup sccache
7370
uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9
7471

AGENTS.md

Lines changed: 179 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,181 @@
11
# Repository Guidelines
22

3-
## Project Structure & Module Organization
4-
- `Backend/`: Rust + Tauri application code (`src/`), commands (`src/tauri_commands/`), and plugin runtime.
5-
- `Backend/built-in-plugins/`: git submodules for bundled plugins; initialize/update with `git submodule update --init --recursive`.
6-
- `Frontend/`: TypeScript + Vite UI (`src/scripts/`, `src/styles/`, `src/modals/`), with Vitest tests colocated as `*.test.ts`.
7-
- `docs/`: architecture and plugin docs plus UI assets.
8-
- `packaging/flatpak/`: Flatpak manifests and packaging notes.
9-
- Root files: workspace `Cargo.toml`, `Justfile`, and project docs (`README.md`, `ARCHITECTURE.md`, `SECURITY.md`).
10-
11-
## Build, Test, and Development Commands
12-
- `just build` (or `just build client|plugins`): build frontend, backend, and plugin bundles.
13-
- `git submodule update --init --recursive`: fetch submodule content (required before plugin builds/tests).
14-
- `just test`: workspace Rust tests + frontend TypeScript check + Vitest run.
15-
- `just fix`: run `cargo fmt`, `cargo clippy --fix`, and frontend typecheck.
16-
- `cargo tauri dev`: run the desktop app in development mode.
17-
- `npm --prefix Frontend run dev`: run frontend-only Vite dev server.
18-
- `just tauri-build`: production Tauri build wrapper.
19-
20-
## Coding Style & Naming Conventions
21-
- Rust: format with `cargo fmt --all`; keep clippy-clean (`cargo clippy --all-targets -- -D warnings`).
22-
- TypeScript: 2-space indentation, ES modules, and small feature-focused files under `Frontend/src/scripts/features/`.
23-
- Tests: name frontend tests `*.test.ts` near the implementation (example: `Frontend/src/scripts/lib/dom.test.ts`).
24-
- Naming: use `snake_case` for Rust modules/functions and `camelCase` for TypeScript variables/functions.
25-
26-
# ExecPlans
27-
28-
When writing complex features or significant refactors, use an ExecPlan (as described in .agent/PLANS.md) from design to implementation.
29-
30-
## Testing Guidelines
31-
- Run full checks before opening a PR: `just test`.
32-
- For frontend-only work, run `cd Frontend && npm test` and `npm exec tsc -- -p tsconfig.json --noEmit`.
33-
- Add or update tests for behavior changes; prefer focused unit tests over broad snapshots.
34-
35-
## Commit & Pull Request Guidelines
36-
- Follow existing commit style: short imperative subject, optional scope prefix (examples: `backend: fix tauri precommands`, `ci: add wasm32-wasip1 target`, `chore(deps): bump @types/node`).
37-
- Keep commits logically scoped; avoid mixing frontend/backend refactors unless required.
38-
- Do not directly modify plugin code under `Backend/built-in-plugins/`; only update submodule pointers in this repository when explicitly requested.
39-
- PRs should include: summary of behavior changes, linked issue(s), test evidence (command output), and screenshots for UI changes.
40-
- Target the `Dev` branch for normal development work.
41-
42-
## Security & Configuration Tips
43-
- Review `SECURITY.md` before changing update, plugin, or network-related code paths.
44-
- Do not commit secrets; keep local overrides in files like `.env.tauri.local`.
45-
- Do not directly edit code inside git submodules (including `Backend/built-in-plugins/*`) unless the task explicitly requires a submodule update; treat submodule changes as pointer-only updates in this repo.
3+
## Project structure & module organization
4+
5+
- `Backend/`: Rust + Tauri backend (`src/`), commands (`src/tauri_commands/`), plugin runtime (`src/plugin_runtime/`), and bundled plugin support (`src/plugin_runtime`, `scripts/`).
6+
- `Backend/built-in-plugins/`: local copies of bundled plugins (do not edit their code unless explicitly requested; update submodule pointers instead).
7+
- `Frontend/`: TypeScript + Vite UI code (`src/scripts/`, `src/styles/`, `src/modals/`), with Vitest tests colocated as `*.test.ts` files.
8+
- `docs/`: UX docs, plugin architecture notes, and plugin/theme packaging guides referenced by contributors.
9+
- `packaging/flatpak/`: Flatpak manifests and Flatpak-specific build notes.
10+
- Supporting files at the repo root include the workspace `Cargo.toml`, `Justfile`, `README.md`, `ARCHITECTURE.md`, `SECURITY.md`, and installer scripts.
11+
12+
## Build, test, and development commands
13+
14+
### Full builds
15+
- `just build` (or `just build client|plugins`): builds the backend, frontend, and plugin bundles from the workspace Justfile.
16+
- `just tauri-build`: production Tauri build wrapper (AppImage/Flatpak). `git submodule update --init --recursive` is required before building bundled plugins.
17+
18+
### Running tests
19+
20+
**All tests:**
21+
- `just test`: runs workspace Rust tests plus frontend type-check + Vitest via the Justfile.
22+
23+
**Frontend (Vitest):**
24+
- `npm --prefix Frontend test`: run all tests
25+
- `npm --prefix Frontend test run`: run tests once (non-watch mode)
26+
- `npm --prefix Frontend test -- --run`: explicit non-watch mode
27+
- `npm --prefix Frontend test -- src/scripts/lib/dom.test.ts`: run single test file
28+
- `npm --prefix Frontend test -- --run -t "qs and qsa"`: run single test by name pattern
29+
- `npm --prefix Frontend test -- --watch`: watch mode for development
30+
31+
**Backend (Rust):**
32+
- `cargo test --workspace`: run all Rust tests
33+
- `cargo test`: run tests for current crate
34+
- `cargo test --package openvcs_lib`: test specific crate
35+
- `cargo test --lib`: run only library tests (not integration tests)
36+
- `cargo test --lib -- branch`: run tests matching "branch" in name
37+
- `cargo test --lib -- --test-threads=1`: run tests sequentially (for flaky tests)
38+
39+
### Linting and formatting
40+
41+
- `just fix`: formatter/lint quick fixes (runs `cargo fmt`, `cargo clippy --fix`, and frontend type-check).
42+
- `cargo fmt --all`: format Rust code
43+
- `cargo clippy --all-targets -- -D warnings`: check Rust for issues
44+
- `cargo clippy --fix --all-targets --allow-dirty`: auto-fix clippy issues
45+
- `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit`: TypeScript type-check
46+
47+
### Development servers
48+
49+
- `cargo tauri dev`: run the desktop app in dev mode (`Backend/` directory).
50+
- `npm --prefix Frontend run dev`: run the frontend-only Vite dev server.
51+
52+
## Plugin runtime & host expectations
53+
54+
- Plugin components live under `Backend/built-in-plugins/` and follow the manifest format in `openvcs.plugin.json`. Built-in bundles ship with the AppImage/Flatpak and are also built by the SDK (`openvcs build` + `openvcs dist`).
55+
- The backend loads plugin modules as Node.js runtime scripts (`*.mjs|*.js|*.cjs`) via `Backend/src/plugin_runtime/node_instance.rs`.
56+
- The canonical host/plugin contract is JSON-RPC over stdio with method names in `Backend/src/plugin_runtime/protocol.rs`.
57+
- When changing host APIs or runtime behavior, update protocol constants and runtime logic in `Backend/src/plugin_runtime`.
58+
59+
## Coding style & conventions
60+
61+
### Rust
62+
63+
**Formatting:**
64+
- Run `cargo fmt --all` before committing
65+
- Use default Rust formatting (4-space indentation, etc.)
66+
- Keep lines under ~100 characters when reasonable
67+
68+
**Naming:**
69+
- `snake_case` for modules, functions, and variables
70+
- `PascalCase` for structs, enums, and trait names
71+
- Prefix private fields with underscore (e.g., `self._field`)
72+
- Use descriptive names; avoid single letters except in tight loops
73+
74+
**Imports:**
75+
- Group imports: std library first, then external crates, then local modules
76+
- Use `use` statements for frequently used items
77+
- Prefer absolute paths from crate root (`crate::module::Item`)
78+
79+
**Error handling:**
80+
- Use `Result<T, E>` for fallible operations; avoid `panic!` in library code
81+
- Use `?` operator for propagating errors
82+
- Include context in error messages: `some_func().context("failed to load config")?`
83+
- Log warnings for recoverable errors with `log::warn`
84+
- Use `anyhow` for application code (commands, main) when context is needed
85+
86+
**Types & patterns:**
87+
- Prefer `Arc<T>` for shared ownership across threads
88+
- Use `tokio` async runtime for I/O-bound async operations
89+
- Use `parking_lot` mutexes (faster than std)
90+
- Derive `Clone`, `Debug`, `Serialize`, `Deserialize` as needed
91+
92+
### Documentation
93+
94+
- **ALL code must be documented**, not just public APIs. This includes:
95+
- Rust: Use doc comments (`///` for items, `//!` for modules) for all functions, structs, enums, traits, and fields.
96+
- TypeScript: Use JSDoc comments (`/** ... */`) for all functions, classes, interfaces, and types.
97+
- All functions must include documentation comments.
98+
- All code files MUST be no more than 1000 lines; split files before they exceed this limit.
99+
- When you change behavior, workflows, commands, paths, config, or plugin/runtime expectations, ALWAYS update the relevant documentation in the same change, even if the user does not explicitly ask.
100+
- Include usage examples for complex functions.
101+
- Keep README files in sync with code changes.
102+
- Document configuration options and environment variables.
103+
- All new files must include the following copyright header:
104+
105+
```rust
106+
// Copyright © 2025-2026 OpenVCS Contributors
107+
// SPDX-License-Identifier: GPL-3.0-or-later
108+
```
109+
110+
```typescript
111+
// Copyright © 2025-2026 OpenVCS Contributors
112+
// SPDX-License-Identifier: GPL-3.0-or-later
113+
```
114+
115+
### TypeScript
116+
117+
**Formatting:**
118+
- 2-space indentation (no tabs)
119+
- Use ES modules (`import`/`export`)
120+
- Keep lines under ~100 characters when reasonable
121+
- Use semicolons at statement ends
122+
123+
**Naming:**
124+
- `camelCase` for variables, functions, and methods
125+
- `PascalCase` for classes, types, and interfaces
126+
- Prefix private class members with underscore (e.g., `this._field`)
127+
- Use descriptive names; avoid abbreviations except common ones (e.g., `btn`, `cfg`)
128+
129+
**Imports:**
130+
- Use absolute imports from project root when possible
131+
- Group imports: external libs, then relative `./` paths, then `../` paths
132+
- Prefer named imports: `import { foo, bar } from './module'`
133+
- Use type-only imports (`import type { Foo }`) when only using types
134+
135+
**Types:**
136+
- Use explicit types for function parameters and return values
137+
- Prefer interfaces for object shapes, types for unions/intersections
138+
- Use `null` for "intentionally empty", `undefined` for "not yet set"
139+
- Avoid `any`; use `unknown` when type is truly unknown
140+
141+
**Error handling:**
142+
- Use try/catch for async operations; always handle or re-throw
143+
- Use `Promise.catch(() => {})` for fire-and-forget async calls
144+
- Show user-facing errors via `notify()` from `lib/notify`
145+
- Log internal errors with console for debugging
146+
147+
**UI patterns:**
148+
- Use `qs<T>('#id')` for single element queries from `lib/dom`
149+
- Use `qsa('.class')` for multiple elements
150+
- Use event delegation for list items
151+
- Keep feature modules focused and small (<200 lines when possible)
152+
- Colocate tests as `*.test.ts` next to the source file
153+
154+
### Testing
155+
156+
- Run `just test` before PRs
157+
- Frontend-only work: run `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit` and `npm --prefix Frontend test`
158+
- Use Vitest's `describe`/`it`/`expect` for frontend tests
159+
- Use descriptive test names: `it('finds elements by selector')`
160+
- Use `beforeEach` to reset DOM state in DOM tests
161+
162+
## ExecPlans
163+
164+
- For multi-component features or refactors, create/update an ExecPlan (`Client/PLANS.md`). Outline design, component impacts, and how the plugin runtime is exercised.
165+
166+
## Testing guidelines
167+
168+
- Run `just test` before PRs; frontend-only work should at least cover `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit` and `npm --prefix Frontend test`.
169+
- Use `cargo tauri dev` to verify runtime plugin interactions (especially when touching `Backend/src/plugin_runtime/`), and make sure `docs/plugin architecture.md` stays aligned with behavior.
170+
171+
## Commit & PR guidelines
172+
173+
- Use short, imperative commit subjects (optionally scoped, e.g., `backend: refresh plugin runtime config`). Keep changelist focused; avoid mixing UI and backend refactors unless necessary.
174+
- PRs should target the `Dev` branch, include a summary, issue links, commands/tests run, and highlight architecture implications (host API/protocol changes and security decisions).
175+
- Do not modify plugin code inside submodules unless explicitly asked; treat submodule updates as pointer bumps after upstream changes.
176+
- Keep this AGENTS (and other module-level copies you rely on) current whenever workflows, tooling, or responsibilities change so future contributors can find accurate guidance.
177+
178+
## Security & configuration notes
179+
180+
- Review `SECURITY.md` before making plugin, plugin-install, or network-related changes.
181+
- Keep secrets out of the repo; use `.env.tauri.local` for local overrides and do not check them in. If new config flags are introduced, document them in `docs/` and update relevant settings screens/logs.

ARCHITECTURE.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Primary flow:
2222
Frontend:
2323
- `Frontend/src/scripts/main.ts`: UI bootstrap and feature wiring.
2424
- `Frontend/src/scripts/lib/tauri.ts`: minimal bridge wrapper for `invoke`/`listen`.
25-
- `Frontend/src/scripts/plugins.ts`: UI plugin runtime and plugin-contributed UI hooks.
2625
- `Frontend/src/scripts/features/`: feature modules grouped by domain.
2726
- `Frontend/src/styles/`: tokens, layout, modal, and component styles.
2827

@@ -32,8 +31,8 @@ Backend:
3231
- `Backend/src/state.rs`: app config, repo state, recents, output log.
3332
- `Backend/src/repo.rs`: repository handle wrapper around `Arc<dyn Vcs>`.
3433
- `Backend/src/plugin_vcs_backends.rs`: backend discovery and open logic.
35-
- `Backend/src/plugin_bundles.rs`: `.ovcsp` install/index/component resolution.
36-
- `Backend/src/plugin_runtime/stdio_rpc.rs`: plugin process spawn, RPC transport, restarts/timeouts.
34+
- `Backend/src/plugin_bundles.rs`: `.ovcsp` install/index/runtime resolution.
35+
- `Backend/src/plugin_runtime/node_instance.rs`: plugin process lifecycle and JSON-RPC calls.
3736
- `Backend/src/plugin_runtime/vcs_proxy.rs`: `Vcs` trait proxy over plugin RPC.
3837
- `Backend/src/plugins.rs`: plugin discovery/manifest summarization for UI.
3938

@@ -44,23 +43,22 @@ Backend:
4443
- Command boundary:
4544
Feature-facing backend API lives under `Backend/src/tauri_commands/`.
4645
- Backend/plugin boundary:
47-
Backend communicates with plugin components over stdio JSON-RPC, not in-process APIs.
46+
Backend communicates with plugin processes over JSON-RPC over stdio.
4847
- Settings boundary:
4948
Backend persists/loads app configuration and mediates environment application.
5049

5150
## Architecture Invariants
5251

5352
- Active repo backend is treated as dynamic availability; stale handles are rejected when backend disappears.
54-
- Plugin components that request capabilities require approval before execution.
55-
- Frontend plugin scripts can extend UI, but repository operations still route through backend commands.
53+
- Plugin modules require approval before execution.
5654
- Output/log/progress signaling is centralized through backend event emission.
5755

5856
## Cross-Cutting Concerns
5957

6058
- State lifecycle:
6159
Startup config load, optional reopen-last-repo, runtime config updates.
6260
- Plugin lifecycle:
63-
Built-in/user plugin discovery, install/uninstall, capability approvals.
61+
Built-in/user plugin discovery, install/uninstall, and approval gating.
6462
- Reliability:
6563
RPC timeout handling, respawn backoff, and auto-disable after repeated crashes.
6664
- UX:

0 commit comments

Comments
 (0)