From 5231c659c0dbce9eebb7cca6180c9ce2ae7c4d39 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Sat, 7 Mar 2026 11:25:11 -0500 Subject: [PATCH] Add repo agent guidance and sync test config --- AGENTS.md | 83 +++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + test/stubs/opencode-plugin.ts | 24 ++++++++++ tsconfig.json | 2 + vitest.config.ts | 3 +- 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md create mode 100644 test/stubs/opencode-plugin.ts diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ea5e7de --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,83 @@ +# AGENTS.md + +Guidance for coding agents working in this repository. + +## Purpose + +This repo contains small, self-contained [glance.sh](https://glance.sh) integrations for different coding agents. Each plugin should be easy to read, easy to install, and easy to test locally. + +## Repository shape + +- Each agent integration lives in its own top-level directory such as `pi/` or `opencode/`. +- Each plugin directory should contain: + - `glance.ts`: the plugin implementation + - `glance.test.ts`: the Vitest suite for that plugin + - `README.md`: install and usage instructions for that plugin +- Shared test-only helpers and runtime stubs belong under `test/`. + +## Plugin expectations + +- Keep plugins self-contained inside their own directory. +- Prefer platform-native APIs such as `fetch`, `AbortController`, and `ReadableStream` over adding new dependencies. +- Preserve the style already used in the plugin you are editing instead of forcing a repo-wide formatting style. +- Match the repo's writing style: concise, direct, and low on filler in code comments, README copy, and PR text. +- Keep runtime-specific code minimal and explicit. Document runtime assumptions in the plugin `README.md`. +- Update the plugin `README.md` whenever install steps, behavior, supported commands/tools, or runtime requirements change. +- If a plugin has internal async/session logic that is hard to verify from the public API alone, expose a small `__testing` surface rather than making production code more coupled. + +## Behavior requirements + +Every plugin should cover the same core lifecycle: + +- create a glance session +- surface the session URL to the agent or user +- listen for image events over SSE +- handle reconnects, timeouts, expiry, and cancellation +- return or inject the received image URL in the host agent's expected format + +If you fix a behavior bug in one plugin, check the other plugins for the same pattern before stopping. + +## Testing requirements + +- Every plugin must have a Vitest suite in the same directory as the plugin file. +- Tests should cover both the happy path and failure modes, not just basic registration. +- At minimum, cover: + - session creation + - reuse or refresh of persistent sessions + - SSE image delivery + - timeout or expiry handling + - cancellation or shutdown behavior + - user-facing command/tool responses +- Prefer deterministic tests with mocked `fetch`, streams, timers, and runtime APIs. +- Keep tests local to the plugin. Put only reusable stubs or fixtures in `test/`. + +## Tooling and config + +When adding a new plugin directory or new test-only runtime stub, update the root tooling so it stays in sync: + +- `vitest.config.ts` +- `tsconfig.json` +- `package.json` if new scripts are genuinely needed +- `.github/workflows/test.yml` if CI inputs change + +Do not add a build step unless the repository actually needs one. + +## Validation + +Before opening or updating a PR, run: + +```bash +npm test +npm run test:coverage +npm exec -- tsc --noEmit +``` + +If a command cannot be run, say so explicitly and explain why. + +## PR checklist + +- The plugin implementation, tests, and README are all updated together. +- New behavior is covered by tests. +- Root test/typecheck config includes any new plugin or stub paths. +- CI still runs the repo validation commands on pull requests. +- The PR description calls out user-visible behavior changes and any runtime-specific caveats in concise language. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/test/stubs/opencode-plugin.ts b/test/stubs/opencode-plugin.ts new file mode 100644 index 0000000..076952a --- /dev/null +++ b/test/stubs/opencode-plugin.ts @@ -0,0 +1,24 @@ +export interface ToolContext { + abort?: AbortSignal; + metadata(input: { + metadata: Record; + title: string; + }): void; +} + +export interface ToolDefinition { + args: Record; + description: string; + execute(...args: any[]): Promise | string; +} + +export type Plugin = (input: { + client: unknown; +}) => Promise<{ + event?: (input: { event: { type: string } }) => Promise | void; + tool: Record; +}>; + +export function tool(definition: T): T { + return definition; +} diff --git a/tsconfig.json b/tsconfig.json index 0f8b427..800ac36 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,12 +10,14 @@ "noEmit": true, "baseUrl": ".", "paths": { + "@opencode-ai/plugin": ["test/stubs/opencode-plugin.ts"], "@mariozechner/pi-ai": ["test/stubs/pi-ai.ts"], "@mariozechner/pi-coding-agent": ["test/stubs/pi-coding-agent.ts"], "@mariozechner/pi-tui": ["test/stubs/pi-tui.ts"] } }, "include": [ + "opencode/**/*.ts", "pi/**/*.ts", "test/**/*.ts", "vitest.config.ts" diff --git a/vitest.config.ts b/vitest.config.ts index bb3322a..24ef279 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,6 +7,7 @@ const resolveFromRoot = (path: string) => export default defineConfig({ resolve: { alias: { + "@opencode-ai/plugin": resolveFromRoot("./test/stubs/opencode-plugin.ts"), "@mariozechner/pi-ai": resolveFromRoot("./test/stubs/pi-ai.ts"), "@mariozechner/pi-coding-agent": resolveFromRoot( "./test/stubs/pi-coding-agent.ts", @@ -18,7 +19,7 @@ export default defineConfig({ clearMocks: true, coverage: { all: true, - include: ["pi/**/*.ts"], + include: ["opencode/**/*.ts", "pi/**/*.ts"], provider: "v8", reporter: ["text", "lcov"], },