4.8 KiB
Plan: Full AI CLI Integration Through Real Opencode
Goal
Run the real ComputerCraft ai CLI against a real opencode serve process through the WebSocket bridge proxy, while using the fake provider/model fixture proven by opencode-fake-provider-direct-plan.md.
This test should cover the actual runtime chain used in-game.
Dependency
Do not implement this plan until .plans/opencode-fake-provider-direct-plan.md has produced a working fake provider fixture.
Update this plan first with the concrete results from plan 1:
- Working fake provider plugin code shape.
- Working opencode startup command/env.
- Working readiness endpoint.
- Any internal prompt behavior discovered.
Desired Boundary
Real:
- CraftOS-PC harness
/programs/ai.lua/apis/libai.lua/apis/libhttpws.luatools/mcp-bridgeopencode proxyopencode serve- opencode sessions/messages/agents/model selection
Fake:
- The provider/model response behavior only, through the reusable fake provider fixture from plan 1
Runtime Chain
CraftOS /programs/ai.lua
-> libai.lua
-> libhttpws.lua
-> mcp-bridge opencode proxy
-> real opencode serve
-> fake provider/model
Test Fixture
Reuse the fake provider workspace generator from plan 1.
Response mappings needed for the CLI cases:
[
{ "match": "reply with exactly: pong", "reply": "pong" },
{ "match": "fresh start", "reply": "new reply" },
{ "match": "continue please", "reply": "plain reply" }
]
Keep the mapping fixture easy to extend so future CLI cases can add entries without changing provider code.
CraftOS Wrapper
Create or update a Lua wrapper under:
tools/mcp-bridge/test-integration/lua/ai-cli-check.lua
The wrapper should:
- Accept the WebSocket proxy URL as its first argument.
- Clear stale settings:
opencc.server_urlopencc.session_id
- Set:
opencc.bridge_urlopencc.request_timeout_seconds
- Run:
ai sessionsai pingai new fresh startai continue please
- Print markers around each command.
- Print persisted session markers after commands.
- Call
os.shutdown().
Expected marker examples:
print('--- sessions ---');
shell.run('/programs/ai.lua', 'sessions');
print('--- ping ---');
shell.run('/programs/ai.lua', 'ping');
print('SESSION_AFTER_PING=' .. tostring(settings.get('opencc.session_id')));
print('--- new ---');
shell.run('/programs/ai.lua', 'new', 'fresh', 'start');
print('SESSION_AFTER_NEW=' .. tostring(settings.get('opencc.session_id')));
print('--- ask ---');
shell.run('/programs/ai.lua', 'continue', 'please');
print('SESSION_AFTER_ASK=' .. tostring(settings.get('opencc.session_id')));
Node Test Implementation
Add or replace the current CLI integration test under:
tools/mcp-bridge/test-integration/ai-cli.test.ts
Test steps:
- Create temp fake-provider opencode workspace using the plan 1 fixture.
- Start
opencode serveon a random local port. - Poll until opencode is ready.
- Start
startOpencodeProxy({ opencodeUrl }). - Start CraftOS with:
mountRepo: trueshellArgs: [proxyUrl]- a generous timeout, likely
30_000or higher depending on measured opencode startup time
- Assert CLI output includes:
pongnew replyplain reply- session markers proving
ai newreplaces the session and plainai ...reuses it
- Stop CraftOS, proxy, and opencode in
finally.
Useful Assertions
ai sessionsexits without an opencode transport/config error.ai pingprintspong.ai new fresh startprintsnew reply.- Plain
ai continue pleaseprintsplain reply. SESSION_AFTER_NEWis non-empty.SESSION_AFTER_ASKequalsSESSION_AFTER_NEW.- If
SESSION_AFTER_PINGis printed, decide whether ping should persist a session or whetherai pingshould become non-persistent in a separate behavior change.
Current Open Questions
- Should
ai pingpersistopencc.session_id? Currentprograms/ai.luacallsai.ping(askOptions()), andlibai.pingbehavior must be checked before asserting this too tightly. - Should
ai sessionsbe expected to show no sessions, one session, or just avoid failing before messages are created? Real opencode behavior may differ from the old fake HTTP server. - Does opencode generate a title/summary for each message during the synchronous
/messagecall? If yes, the fake provider fallback must make that harmless. - What is the most stable way to choose a free opencode port in CI?
Verification
After implementation, run:
npx tsx --test test-integration/opencode-fake-provider.test.ts
npx tsx --test test-integration/ai-cli.test.ts
npm run check
just check
If the full test is too slow for the default integration suite, keep it as a separately named test command or document why it is excluded from npm run test:integration.