cc-libs/.plans/opencode-fake-provider-direct-plan.md
2026-06-12 00:20:57 +02:00

122 lines
3.8 KiB
Markdown

# 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.