# Plan: Direct Fake Provider Integration ## Goal Prove that a real `opencode serve` process can run with a deterministic fake provider/model and answer HTTP API requests without calling an external LLM. This plan deliberately stops before CraftOS, the WebSocket bridge, or `/programs/ai.lua`. It validates only the opencode-side fixture that the full integration test will reuse. ## Desired Boundary Real: - `opencode serve` - opencode config validation and loading - opencode session/message HTTP endpoints - opencode model/provider selection - opencode agent/title/summary plumbing as far as it is triggered by simple messages Fake: - The provider/model response behavior only ## Proposed Test Fixture Create a test-only temporary opencode workspace during the test. Do not modify the project `.opencode/opencode.json` for this. Files generated under a temp directory: - `opencode.json` - `fake-provider.ts` or `fake-provider.js` - `fake-responses.json` Example response mapping: ```json [ { "match": "reply with exactly: pong", "reply": "pong" }, { "match": "fresh start", "reply": "new reply" }, { "match": "continue please", "reply": "plain reply" } ] ``` The fake provider should return the first response whose `match` appears in the final model prompt. Unknown prompts should return a deterministic fallback such as `ok` or `unhandled fake prompt`, not fail immediately, because opencode may issue title/summary/internal prompts. ## Config Shape To Validate Use the published schema as the source of truth before finalizing fields. Candidate config: ```json { "$schema": "https://opencode.ai/config.json", "model": "traptest/fake", "small_model": "traptest/fake", "enabled_providers": ["traptest"], "plugin": ["./fake-provider.ts"], "provider": { "traptest": { "name": "Trap Test", "models": { "fake": { "id": "fake", "name": "Trap Test Fake Model", "limit": { "context": 100000, "output": 10000 }, "cost": { "input": 0, "output": 0 }, "status": "active" } } } }, "agent": { "build": { "model": "traptest/fake" }, "title": { "model": "traptest/fake" }, "summary": { "model": "traptest/fake" } } } ``` Open question: the exact plugin provider hook shape must be verified against opencode's runtime/plugin API. Do not guess this implementation from the config schema alone. ## Test Implementation Add a Node integration test, likely under: - `tools/mcp-bridge/test-integration/opencode-fake-provider.test.ts` Test steps: 1. Create a temp directory. 2. Write the test `opencode.json`. 3. Write `fake-responses.json`. 4. Write the fake provider plugin. 5. Start `opencode serve` on `127.0.0.1` with a random free port. 6. Wait for readiness by polling an HTTP endpoint such as `GET /session`. 7. Call opencode HTTP directly: - `POST /session` - `POST /session/:id/message` with `reply with exactly: pong` - `POST /session/:id/message` with `fresh start` 8. Assert the responses contain `pong` and `new reply`. 9. Stop the opencode process and clean up the temp directory. ## Useful Assertions - `opencode serve` starts successfully with the generated config. - `POST /session` returns a usable session ID. - `POST /session/:id/message` returns text from the fake mapping. - Unknown/internal prompts do not break the test fixture. - No external provider credentials are required. ## Result To Capture For Plan 2 After this plan is run, record: - Exact working fake provider plugin API shape. - Exact command/env used to start `opencode serve` reliably. - Confirmed readiness endpoint and polling logic. - Whether title/summary/internal model calls happen during simple message requests. - Any required config fields not listed above. Plan 2 should be updated with these facts before implementation.