docs(plans): add opencc agent proxy poc plan
This commit is contained in:
parent
66d979e543
commit
ec6f993d95
217
.plans/opencc-agent-proxy-plan.md
Normal file
217
.plans/opencc-agent-proxy-plan.md
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
# Plan - PoC `cc-agent-proxy` + programme Lua `opencc`
|
||||||
|
|
||||||
|
> A executer ailleurs, pas sur cette machine. Deploiement HTTPS, reverse proxy, firewall et exposition publique geres separement par Guillaume.
|
||||||
|
|
||||||
|
## 1. Objectif
|
||||||
|
|
||||||
|
Piloter un agent OpenCode depuis une turtle ComputerCraft sur Minecraft / ATM10.
|
||||||
|
|
||||||
|
```text
|
||||||
|
Turtle --HTTP + token--> cc-agent-proxy --HTTP Basic Auth--> opencode serve
|
||||||
|
opencc.lua Node/TypeScript proxy OpenCode headless
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Faisabilite
|
||||||
|
|
||||||
|
`opencode serve` lance un serveur HTTP headless exposant une spec OpenAPI 3.1 sur `/doc`.
|
||||||
|
|
||||||
|
Routes utiles pour le PoC :
|
||||||
|
|
||||||
|
| Methode | Route | Usage |
|
||||||
|
|---|---|---|
|
||||||
|
| `GET` | `/global/health` | healthcheck amont |
|
||||||
|
| `POST` | `/session` | cree une session |
|
||||||
|
| `POST` | `/session/:id/message` | envoie un message et attend la reponse |
|
||||||
|
| `POST` | `/session/:id/prompt_async` | envoie en asynchrone |
|
||||||
|
| `GET` | `/session/:id/message` | liste les messages |
|
||||||
|
| `GET` | `/event` | flux SSE |
|
||||||
|
|
||||||
|
Conclusion : le proxy n'est pas strictement necessaire, mais il rend le client Lua beaucoup plus simple.
|
||||||
|
|
||||||
|
## 3. Pourquoi garder le proxy
|
||||||
|
|
||||||
|
- Expose une API turtle simple : `POST /ask { prompt, sessionId? }` vers `{ sessionId, reply }`.
|
||||||
|
- Gere le Basic Auth OpenCode cote Node.
|
||||||
|
- Garde cote turtle un token Bearer simple.
|
||||||
|
- Aplatit les reponses OpenCode pour limiter RAM et complexite Lua.
|
||||||
|
- Permet plus tard async, polling, logs, quotas ou allowlist sans changer le programme Lua.
|
||||||
|
|
||||||
|
## 4. Partie A - `cc-agent-proxy`
|
||||||
|
|
||||||
|
Creer un dossier `cc-agent-proxy/` dans le repo.
|
||||||
|
|
||||||
|
Stack :
|
||||||
|
|
||||||
|
- Node 20+.
|
||||||
|
- TypeScript strict.
|
||||||
|
- Fastify.
|
||||||
|
- Vitest.
|
||||||
|
- Zod.
|
||||||
|
- Config via env validee, avec `.env.example`.
|
||||||
|
|
||||||
|
Arborescence :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cc-agent-proxy/
|
||||||
|
package.json
|
||||||
|
tsconfig.json
|
||||||
|
.env.example
|
||||||
|
src/
|
||||||
|
config.ts
|
||||||
|
opencode.ts
|
||||||
|
auth.ts
|
||||||
|
server.ts
|
||||||
|
index.ts
|
||||||
|
test/
|
||||||
|
config.test.ts
|
||||||
|
opencode.test.ts
|
||||||
|
auth.test.ts
|
||||||
|
server.test.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Config :
|
||||||
|
|
||||||
|
| Variable | Defaut | Role |
|
||||||
|
|---|---|---|
|
||||||
|
| `PROXY_HOST` | `0.0.0.0` | interface d'ecoute |
|
||||||
|
| `PROXY_PORT` | `7070` | port du proxy |
|
||||||
|
| `PROXY_TOKEN` | requis | secret turtle <-> proxy |
|
||||||
|
| `OPENCODE_BASE_URL` | `http://127.0.0.1:4096` | URL OpenCode |
|
||||||
|
| `OPENCODE_USERNAME` | `opencode` | user Basic Auth |
|
||||||
|
| `OPENCODE_PASSWORD` | requis | password Basic Auth |
|
||||||
|
| `OPENCODE_MODEL` | optionnel | modele a passer a OpenCode |
|
||||||
|
|
||||||
|
Routes proxy :
|
||||||
|
|
||||||
|
| Methode | Route | Auth | Usage |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `GET` | `/health` | non | etat proxy + `opencode.health()` |
|
||||||
|
| `POST` | `/ask` | oui | cree/reutilise session, envoie prompt, retourne reponse |
|
||||||
|
| `POST` | `/session` | oui, optionnel | cree une session explicite |
|
||||||
|
|
||||||
|
Client OpenCode :
|
||||||
|
|
||||||
|
- `health()` appelle `GET /global/health`.
|
||||||
|
- `createSession(title?)` appelle `POST /session`.
|
||||||
|
- `sendMessage(sessionId, text)` appelle `POST /session/:id/message`.
|
||||||
|
- `Authorization: Basic base64(username:password)`.
|
||||||
|
- Body message : `{ parts: [{ type: "text", text }], model?: ... }`.
|
||||||
|
- Extraire les `parts` texte de la reponse.
|
||||||
|
- A valider au premier run reel : format exact des `parts`.
|
||||||
|
|
||||||
|
Auth proxy :
|
||||||
|
|
||||||
|
- Accepter `Authorization: Bearer <token>`.
|
||||||
|
- Accepter aussi `X-Proxy-Token` pour simplicite CC si besoin.
|
||||||
|
- Comparaison constant-time avec `crypto.timingSafeEqual`.
|
||||||
|
- Reponse `401` si absent ou invalide.
|
||||||
|
- Ne jamais logger le token.
|
||||||
|
|
||||||
|
Tests Node en scope du PoC :
|
||||||
|
|
||||||
|
- `config.test.ts` : valeurs par defaut, erreurs si secrets manquants.
|
||||||
|
- `opencode.test.ts` : `fetch` mocke pour health/session/message/parsing.
|
||||||
|
- `auth.test.ts` : token valide, invalide, absent.
|
||||||
|
- `server.test.ts` : `app.inject()` pour `/health`, `/ask`, `401` sans token.
|
||||||
|
|
||||||
|
## 5. Partie B - programme Lua `opencc`
|
||||||
|
|
||||||
|
Creer :
|
||||||
|
|
||||||
|
```text
|
||||||
|
apis/libopencc.lua
|
||||||
|
programs/opencc.lua
|
||||||
|
tests/opencc.lua
|
||||||
|
```
|
||||||
|
|
||||||
|
Programme :
|
||||||
|
|
||||||
|
- `opencc --help`.
|
||||||
|
- `opencc --version`.
|
||||||
|
- `opencc "prompt"` ou prompt interactif via `read()`.
|
||||||
|
- Appelle `http://<host>:<port>/ask`.
|
||||||
|
- Header `Content-Type: application/json`.
|
||||||
|
- Header `Authorization: Bearer <token>`.
|
||||||
|
- Body `textutils.serialiseJSON({ prompt = prompt, sessionId = sessionId })`.
|
||||||
|
- Parse la reponse JSON.
|
||||||
|
- Affiche `reply`.
|
||||||
|
- Memorise `sessionId` pour reutilisation si on choisit une session persistante.
|
||||||
|
|
||||||
|
Config Lua :
|
||||||
|
|
||||||
|
- Utiliser `settings` ComputerCraft en priorite :
|
||||||
|
- `opencc.proxy_url`.
|
||||||
|
- `opencc.proxy_token`.
|
||||||
|
- `opencc.session_id`.
|
||||||
|
- `opencc.timeout`, si applicable.
|
||||||
|
- Autoriser un fallback hardcode uniquement pour PoC local, mais ne pas committer de secret reel.
|
||||||
|
- Stockage session possible dans un petit fichier local, par exemple `/.opencc-session`, si plus simple que `settings`.
|
||||||
|
|
||||||
|
Tests Lua :
|
||||||
|
|
||||||
|
- En scope si simple : tester `libopencc` sans vraie requete HTTP via injection d'un faux client `http`.
|
||||||
|
- Tester construction URL, headers, body JSON, parsing succes, parsing erreur.
|
||||||
|
- Hors scope PoC si trop couteux : test end-to-end avec vrai proxy Node et vrai OpenCode.
|
||||||
|
- Le test reel HTTP se fera manuellement via CraftOS-PC puis en jeu.
|
||||||
|
|
||||||
|
Note repo :
|
||||||
|
|
||||||
|
- Le reseau existant `apis/net.lua` est oriente modem/rednet/router, pas HTTP sortant.
|
||||||
|
- Pour ce PoC, garder `http.post` direct cote Lua est le bon choix.
|
||||||
|
- Le packaging existant du repo est `ccpm` / `packages/*/ccpm.json`, pas `cube`.
|
||||||
|
- Ne pas integrer au packaging tant que le PoC n'est pas valide ; ajouter ensuite un package dedie type `tos-agent` si utile.
|
||||||
|
|
||||||
|
## 6. Pre-requis CC:Tweaked / ATM10
|
||||||
|
|
||||||
|
- API `http` activee.
|
||||||
|
- Hote/IP du proxy autorise dans les `http.rules` cote serveur ATM10.
|
||||||
|
- Pas de CORS, car ce n'est pas un navigateur.
|
||||||
|
- Prompts courts pour le PoC, car `POST /session/:id/message` peut etre long.
|
||||||
|
|
||||||
|
Evolution hors PoC :
|
||||||
|
|
||||||
|
- Proxy utilise `prompt_async`.
|
||||||
|
- Turtle appelle `POST /ask` puis poll `GET /ask/:id/status`.
|
||||||
|
- Le proxy ecoute eventuellement `/event` SSE cote OpenCode.
|
||||||
|
|
||||||
|
## 7. Ordre d'execution
|
||||||
|
|
||||||
|
1. Bootstrap `cc-agent-proxy`.
|
||||||
|
2. Implementer `config.ts` + tests.
|
||||||
|
3. Implementer `opencode.ts` + tests avec `fetch` mocke.
|
||||||
|
4. Implementer `auth.ts`, `server.ts`, `/health`, `/ask` + tests `app.inject()`.
|
||||||
|
5. Valider manuellement avec `opencode serve` + `curl`.
|
||||||
|
6. Implementer `apis/libopencc.lua` + `programs/opencc.lua`.
|
||||||
|
7. Ajouter `tests/opencc.lua` si l'injection HTTP reste simple.
|
||||||
|
8. Tester via CraftOS-PC.
|
||||||
|
9. Tester en jeu sur ATM10 apres configuration `http.rules`.
|
||||||
|
10. Documenter les commandes de lancement et les pre-requis.
|
||||||
|
|
||||||
|
## 8. Validation manuelle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OPENCODE_SERVER_PASSWORD=xxx opencode serve \
|
||||||
|
--hostname 127.0.0.1 \
|
||||||
|
--port 4096
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s http://localhost:7070/health
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST http://localhost:7070/ask \
|
||||||
|
-H "Authorization: Bearer $PROXY_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"prompt":"dis bonjour"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Points de vigilance
|
||||||
|
|
||||||
|
- Format reel des `parts` OpenCode a valider au premier run.
|
||||||
|
- OpenCode doit avoir un provider authentifie.
|
||||||
|
- Timeouts longs cote agent vs limites HTTP CC:Tweaked.
|
||||||
|
- `http.rules` cote serveur ATM10.
|
||||||
|
- `PROXY_TOKEN` jamais committe.
|
||||||
|
- `OPENCODE_PASSWORD` jamais committe.
|
||||||
|
- Le proxy doit rester minimal tant que le PoC n'a pas prouve la boucle complete.
|
||||||
Loading…
Reference in New Issue
Block a user