chore: save the grilled plan for the opencc agent oproxy
This commit is contained in:
parent
ec6f993d95
commit
b87dafc666
808
.plans/opencc-agent-proxy-GRILLED_PLAN.md
Normal file
808
.plans/opencc-agent-proxy-GRILLED_PLAN.md
Normal file
@ -0,0 +1,808 @@
|
||||
# GRILLED_PLAN - `cc-agent-proxy` + programme Lua `opencc`
|
||||
|
||||
> Compagnon de `.plans/opencc-agent-proxy-plan.md`. Chaque question a une
|
||||
> recommandation par defaut et un bloc `TODO: answer` que tu remplis. Un
|
||||
> prochain `/grill-me` lira ce fichier et le condensera en plan v2 pret a
|
||||
> executer.
|
||||
>
|
||||
> Convention :
|
||||
> - Remplace `TODO: answer` par ta reponse (1-3 lignes suffisent).
|
||||
> - Si tu choisis une option listee, ecris `Option N` + raison breve.
|
||||
> - Si tu inventes une 5e option, ecris-la in extenso.
|
||||
> - Si une question devient sans objet apres une reponse majeure, ecris
|
||||
> `N/A - voir Q<n>`.
|
||||
> - Laisse `TODO: answer (optionnel)` tel quel si pas d'avis.
|
||||
|
||||
## Regles de base du PoC
|
||||
|
||||
- Une turtle, un OpenCode, un proxy, une reponse utilisable. Rien de plus.
|
||||
- Contraintes explicites > design generique.
|
||||
- Pas de packaging tant que la boucle n'a pas tourne in-game.
|
||||
- Aucun secret commit.
|
||||
- La forme des reponses OpenCode est suspecte tant qu'on ne l'a pas vue en vrai.
|
||||
|
||||
---
|
||||
|
||||
## A. Les 8 questions determinantes
|
||||
|
||||
A repondre en premier. Le reste devient souvent trivial une fois ces choix
|
||||
trances.
|
||||
|
||||
### A1. Critere d'acceptation du PoC
|
||||
|
||||
Quand dit-on "c'est fini" ?
|
||||
|
||||
- **Option 1 - curl roundtrip** : `curl /ask` retourne une vraie reponse
|
||||
OpenCode. Pas d'in-game.
|
||||
- **Option 2 - CraftOS-PC roundtrip** : `opencc "salut"` repond dans
|
||||
l'emulateur, en pointant sur le proxy local.
|
||||
- **Option 3 - in-game ATM10** : `opencc` marche sur une vraie turtle apres
|
||||
config `http.rules`.
|
||||
- **Option 4 - conversation in-game** : Option 3 + verifier que la session
|
||||
persistante garde le contexte sur plusieurs prompts.
|
||||
|
||||
Recommandation : **Option 4**. C'est ce qui prouve que le pipeline tient bout
|
||||
en bout. 1-3 sont des jalons intermediaires. Premier prompt anodin (`dis
|
||||
bonjour`) avant prompts libres.
|
||||
|
||||
Pourquoi ca compte : decide si async, multi-turtle, logs riches, quotas,
|
||||
packaging et UX terminale sont hors scope.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A2. Autorite et workspace d'OpenCode
|
||||
|
||||
Le proxy parle a un `opencode serve` qui a, potentiellement, acces complet a
|
||||
des fichiers et a un shell. Une turtle qui prompt = un acteur exterieur qui
|
||||
peut indirectement declencher des actions cote hote.
|
||||
|
||||
- **Option 1 - workspace dedie jetable** : `opencode serve` lance dans un dir
|
||||
temporaire (`/tmp/opencc-poc`) sans secrets, sans repo perso.
|
||||
- **Option 2 - workspace projet dedie** : un dossier `~/opencc-workspace/`
|
||||
vide ou minimal, persistant entre runs.
|
||||
- **Option 3 - repo perso** : non, trop risque.
|
||||
- **Option 4 - sandbox container** : OpenCode dans Docker avec mount limite.
|
||||
Plus de cout pour le PoC.
|
||||
|
||||
Recommandation : **Option 1**. Workspace jetable, recree a chaque session de
|
||||
test. Documenter le dir exact dans `.env`.
|
||||
|
||||
Pourquoi ca compte : c'est la vraie frontiere de confiance, plus que le
|
||||
token Lua.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A3. Cycle de vie de la session
|
||||
|
||||
- **Option 1 - session unique partagee** : le proxy cree une session au boot,
|
||||
toutes les turtles tapent dedans. Conflits de memoire conversationnelle.
|
||||
- **Option 2 - session par turtle, persistee cote turtle** : la turtle stocke
|
||||
`sessionId` dans `settings` ; le proxy se contente de relayer.
|
||||
- **Option 3 - session ephemere par prompt** : chaque `/ask` cree+detruit. Pas
|
||||
de continuite. Plus simple, perd le contexte.
|
||||
- **Option 4 - session par turtle, mappee cote proxy** : table
|
||||
`turtleId -> sessionId` cote proxy. Necessite d'identifier la turtle.
|
||||
|
||||
Recommandation : **Option 2**. Le proxy reste sans etat ; la turtle envoie
|
||||
`sessionId` optionnel, le proxy en cree une si absent et le renvoie dans la
|
||||
reponse.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A4. Sync vs async pour `/ask`
|
||||
|
||||
`POST /session/:id/message` peut bloquer longtemps. CC:Tweaked a des
|
||||
timeouts HTTP (~30s typiques, depend du serveur).
|
||||
|
||||
- **Option 1 - sync stricte** : le proxy attend la fin et renvoie. Risque de
|
||||
timeout cote turtle.
|
||||
- **Option 2 - async + polling** : `POST /ask` -> `jobId`, `GET /ask/:jobId`
|
||||
pour poll. Plus robuste, plus complexe.
|
||||
- **Option 3 - keepalive / chunked** : inutile en HTTP CC standard.
|
||||
- **Option 4 - sync now, async later** : on commence en sync (prompts courts
|
||||
pour PoC), on documente la limite, on bascule async si on l'atteint. API
|
||||
`/ask` reste compatible.
|
||||
|
||||
Recommandation : **Option 4**.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A5. Topologie de deploiement
|
||||
|
||||
Le plan source dit "deploiement HTTPS, RP, firewall, exposition publique
|
||||
geres separement par Guillaume".
|
||||
|
||||
- **Option 1 - tout sur ta machine perso** : `opencode serve` +
|
||||
`cc-agent-proxy` en localhost, expose via tunnel (Cloudflare, ngrok).
|
||||
- **Option 2 - VPS dedie** : meme hote distant, HTTPS via Caddy/nginx.
|
||||
- **Option 3 - homelab** : Option 2 mais chez toi, derriere ton RP existant.
|
||||
- **Option 4 - deux hotes separes** : OpenCode sur GPU dedie, proxy ailleurs.
|
||||
|
||||
Conditionne : auth (A6), `OPENCODE_BASE_URL`, qui termine TLS.
|
||||
|
||||
Recommandation : **Option 3** si tu as un homelab, sinon Option 1. Proxy +
|
||||
opencode sur le meme hote, loopback entre les deux, proxy expose en HTTPS.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A6. Modele d'authentification turtle <-> proxy
|
||||
|
||||
- **Option 1 - token unique partage** : un seul `PROXY_TOKEN`, meme valeur
|
||||
sur toutes les turtles via `settings`. Pas de revocation granulaire.
|
||||
- **Option 2 - token par turtle** : table de tokens cote proxy. Permet
|
||||
revocation par turtle.
|
||||
- **Option 3 - HMAC signe** : turtle envoie `os.getComputerID()` + HMAC.
|
||||
Plus complexe, peu de gain sans rotation.
|
||||
- **Option 4 - allowlist IP** : impossible, la turtle sort via le proxy HTTP
|
||||
du serveur Minecraft.
|
||||
|
||||
Recommandation : **Option 1**. Helper `isTokenValid(token)` pour permettre
|
||||
une table plus tard sans refactor.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A7. Forme de la reponse renvoyee a la turtle
|
||||
|
||||
OpenCode retourne `parts`, tool calls, code blocks. La turtle a peu de RAM.
|
||||
|
||||
- **Option 1 - texte plat** : `{ reply }`. Tout ce qui n'est pas texte est
|
||||
jete.
|
||||
- **Option 2 - texte + meta** : `{ reply, model, tokens, sessionId }`.
|
||||
- **Option 3 - parts brutes** : la turtle parse. Trop couteux.
|
||||
- **Option 4 - texte plat + troncature** : `{ reply, sessionId, truncated }`
|
||||
avec `MAX_REPLY_CHARS` (ex. 4 KiB). Logs proxy gardent le complet.
|
||||
|
||||
Recommandation : **Option 4**.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### A8. Scope minimal v1 (in et out)
|
||||
|
||||
- **Option 1 - hello world** : turtle envoie "ping", recoit "pong". Une seule
|
||||
route, sync, pas de session persistante.
|
||||
- **Option 2 - conversation 1 turtle / 1 session** : echange sur plusieurs
|
||||
prompts, sessionId persistante.
|
||||
- **Option 3 - + outils OpenCode** : agent peut lire/ecrire un fichier dans le
|
||||
workspace.
|
||||
- **Option 4 - + multi-turtle** : deux turtles en parallele sans collision.
|
||||
|
||||
Recommandation : **Option 2**.
|
||||
|
||||
Hors-scope explicite du PoC : async, multi-turtles, package ccpm, deploiement
|
||||
auto, Docker, quotas, UI terminale riche, streaming OpenCode (`/event`).
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## B. Scope, contraintes de temps, cleanup
|
||||
|
||||
### B1. Limite de temps et plan de bascule
|
||||
|
||||
Si la forme de l'API OpenCode bloque, qu'est-ce qu'on fait ?
|
||||
|
||||
Recommandation : **une seule passe d'implementation**. Si l'API OpenCode bloque,
|
||||
on arrete d'abstraire et on capture le contrat reel via curl avant de coder.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### B2. Rollback / cleanup post-PoC
|
||||
|
||||
Comment on nettoie une fois la demo faite ?
|
||||
|
||||
Recommandation : stop proxy, stop `opencode serve`, supprimer sessions de
|
||||
test, rotation du `PROXY_TOKEN` et du `OPENCODE_PASSWORD` utilises.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## C. OpenCode upstream : contrat et comportement
|
||||
|
||||
### C1. Version OpenCode et Basic Auth verifies au premier run
|
||||
|
||||
OpenCode evolue. Le plan suppose Basic Auth active. A valider.
|
||||
|
||||
Recommandation : enregistrer `opencode --version` utilise lors de la
|
||||
validation ; pinger `/global/health` avec Basic Auth via curl avant de coder
|
||||
le client.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C2. Spec exacte de `POST /session/:id/message`
|
||||
|
||||
Plan : `{ parts: [{ type: "text", text }], model? }`. Marque comme inconnu.
|
||||
|
||||
Recommandation : `curl http://localhost:4096/doc` une fois OpenCode lance,
|
||||
capturer un sample reel de reponse, le commiter sanitize dans
|
||||
`cc-agent-proxy/test/fixtures/`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C3. Provider et modele LLM
|
||||
|
||||
`OPENCODE_MODEL` optionnel. Quel provider Guillaume utilise (anthropic,
|
||||
openai, ollama local) ?
|
||||
|
||||
Recommandation : laisser defaut OpenCode, ne passer `model` que si
|
||||
`OPENCODE_MODEL` est defini dans `.env`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C4. Timeout amont vers OpenCode
|
||||
|
||||
Recommandation : `REQUEST_TIMEOUT_MS` configurable, defaut 60s. Au dela ->
|
||||
504 cote proxy.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C5. Exposition des erreurs OpenCode au turtle
|
||||
|
||||
Recommandation : pas de stack trace ni secret. Renvoyer
|
||||
`{ error: "...", code: "..." }` avec message public court ; detail dans les
|
||||
logs proxy uniquement.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C6. SessionId auto-creation et recovery si stale
|
||||
|
||||
Deux comportements distincts :
|
||||
- `sessionId` absent dans la requete -> proxy en cree un (recommande **oui**).
|
||||
- `sessionId` fourni mais 404 amont -> ?
|
||||
- **Option A** : recreer silencieusement.
|
||||
- **Option B** : renvoyer `{ error: "session_expired" }`, laisser la
|
||||
turtle decider (`opencc --new`).
|
||||
|
||||
Recommandation : **Option B**. Auto-recreation cacherait une perte de
|
||||
contexte deroutante.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C7. Comportement quand OpenCode est down
|
||||
|
||||
- 502/503 brutal ?
|
||||
- Retry interne avec backoff ?
|
||||
- `/health` reflete-t-il l'etat upstream ?
|
||||
|
||||
Recommandation : pas de retry auto, **502** + JSON `{ error: "upstream_down" }`.
|
||||
`/health` inclut un champ `opencode: "up"/"down"`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### C8. Gestion des parts non-textuelles (tools, code blocks)
|
||||
|
||||
Recommandation : concatener les parts texte, ignorer les non-textuelles dans
|
||||
la `reply`, mais logger un compteur cote proxy (`parts_text`, `parts_tool`,
|
||||
`parts_other`).
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## D. Proxy API shape
|
||||
|
||||
### D1. Routes minimales du proxy
|
||||
|
||||
Plan : `/health`, `/ask`, `/session`.
|
||||
|
||||
- `/session` obligatoire ou implicite via `/ask` ?
|
||||
- `/health` inclut upstream ?
|
||||
|
||||
Recommandation :
|
||||
- `GET /health` -> `{ proxy: "ok", opencode: "up"/"down" }`.
|
||||
- `POST /ask` -> obligatoire, body `{ prompt, sessionId? }`,
|
||||
response `{ sessionId, reply, truncated }`.
|
||||
- `POST /session` -> garder, retourne `{ sessionId }`. Pratique pour
|
||||
initialiser ou nommer une session ; ne casse pas le PoC si on ne l'expose
|
||||
pas a la turtle.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### D2. Codes HTTP stables pour la turtle
|
||||
|
||||
Recommandation :
|
||||
- `200` succes
|
||||
- `400` requete invalide (prompt vide, body malforme)
|
||||
- `401` token absent/invalide
|
||||
- `413` prompt trop long
|
||||
- `502` OpenCode down
|
||||
- `504` OpenCode timeout
|
||||
- `500` erreur proxy inattendue
|
||||
|
||||
TODO: answer
|
||||
|
||||
### D3. Limites taille de requete
|
||||
|
||||
- Max prompt length ?
|
||||
- Max body size HTTP ?
|
||||
|
||||
Recommandation : prompt max **8 KiB** (`MAX_PROMPT_CHARS` env), body max
|
||||
**32 KiB** cote Fastify. Pas de rate-limit dans le PoC.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### D4. Request IDs / correlation
|
||||
|
||||
Recommandation : `requestId` auto-genere cote proxy, present dans tous les
|
||||
logs, non expose dans la reponse JSON (juste dans header `x-request-id` pour
|
||||
debug optionnel).
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## E. Stack Node / TypeScript
|
||||
|
||||
### E1. Runtime et gestionnaire de paquets
|
||||
|
||||
Recommandation : **Node 20+**, **pnpm**. Sinon **npm** si tu prefers vanilla.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E2. Strictness TypeScript
|
||||
|
||||
Recommandation : `"strict": true` + `noUncheckedIndexedAccess`.
|
||||
`exactOptionalPropertyTypes` evite (bruit pour peu de valeur en PoC).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E3. Framework HTTP et validation
|
||||
|
||||
Plan : Fastify + Zod.
|
||||
|
||||
Recommandation : **Fastify** + **Zod** + `fastify-type-provider-zod` pour
|
||||
validation automatique des routes. Confirme ou propose autre.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E4. Logging
|
||||
|
||||
Recommandation : **Pino** (default Fastify). `LOG_LEVEL=info` par defaut,
|
||||
`debug` en dev. Flag `LOG_BODIES=true` pour inclure prompt/reply ; **off
|
||||
par defaut**. Jamais logger token ni `OPENCODE_PASSWORD`. Logs : status,
|
||||
duree, `sessionId` (12 premiers chars), `requestId`, longueurs prompt/reply.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E5. Process / lancement / deploiement
|
||||
|
||||
- `tsx` en dev, `node dist/index.js` apres `tsc` en prod ?
|
||||
- Dockerfile ? systemd ? pm2 ?
|
||||
- Bind `0.0.0.0` ? Shutdown gracieux ?
|
||||
|
||||
Recommandation : tsx en dev, node dist en prod, **pas de Docker**, pas de
|
||||
systemd dans le repo (tu deploies a la main). `0.0.0.0` car expose derriere
|
||||
RP. Shutdown : `app.close()` sur SIGTERM, rien de plus.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E6. Tests Node
|
||||
|
||||
Plan : vitest, fetch mocke, `app.inject()`. Pas d'objectif de couverture %.
|
||||
|
||||
Recommandation : couvrir `/ask` happy path, `401`, OpenCode 5xx mock,
|
||||
prompt vide, prompt trop long, sessionId 404 amont. Fixture OpenCode reelle
|
||||
(cf C2) utilisee dans `opencode.test.ts`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E7. Variables d'env (en plus du tableau du plan)
|
||||
|
||||
A ajouter :
|
||||
- `LOG_LEVEL` (info/debug)
|
||||
- `LOG_BODIES` (true/false)
|
||||
- `MAX_REPLY_CHARS` (defaut 4096)
|
||||
- `MAX_PROMPT_CHARS` (defaut 8192)
|
||||
- `REQUEST_TIMEOUT_MS` (defaut 60000)
|
||||
- `OPENCODE_WORKSPACE` (info uniquement, documente le dir A2)
|
||||
|
||||
Recommandation : oui, ajouter les six. `.env.example` les liste, jamais de
|
||||
secret reel.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### E8. CORS, body parsing, etat en memoire
|
||||
|
||||
- CORS : non, ce n'est pas un navigateur.
|
||||
- Body : JSON only.
|
||||
- Etat : stateless (cf A3 Option 2).
|
||||
|
||||
Recommandation : **garder tel quel**. Confirme ou contredit.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## F. Auth, secrets, exposition publique
|
||||
|
||||
### F1. Generation du `PROXY_TOKEN`
|
||||
|
||||
Recommandation : genere a la main (`openssl rand -hex 32`), ecrit dans
|
||||
`.env`. Si absent au boot, le proxy refuse de demarrer (fail-fast).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F2. HTTPS vs HTTP cote turtle
|
||||
|
||||
ATM10 accepte les deux si dans `http.rules`. Token nu en HTTP = leak.
|
||||
|
||||
Recommandation : **HTTPS uniquement**, meme en homelab, via le RP existant.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F3. Saisie du token sur la turtle
|
||||
|
||||
Le secret ne doit jamais etre dans un fichier Lua commit.
|
||||
|
||||
Recommandation : `settings set opencc.proxy_token <token>` + `settings.save()`
|
||||
manuellement dans l'environnement de chaque turtle. Documenter dans le
|
||||
quickstart.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F4. Token en query string ?
|
||||
|
||||
Recommandation : **non**, header uniquement. Les query strings se retrouvent
|
||||
dans les logs RP/proxy.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F5. Headers acceptes : Bearer et X-Proxy-Token
|
||||
|
||||
Plan : les deux pour simplicite CC.
|
||||
|
||||
Recommandation : accepter `Authorization: Bearer <token>` ET `X-Proxy-Token`,
|
||||
documenter Bearer comme prefere. `X-Proxy-Token` reste seulement si CC pose
|
||||
souci avec `Authorization` (a tester).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F6. Comparaison constant-time
|
||||
|
||||
Recommandation : `crypto.timingSafeEqual` apres normalisation (longueur
|
||||
egalisee) pour eviter le throw sur taille differente.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F7. Rotation du token
|
||||
|
||||
Recommandation : **hors scope PoC**. Redemarrer proxy + reconfigurer
|
||||
turtles = acceptable.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F8. Rate-limit et allowlist IP
|
||||
|
||||
Recommandation : ni l'un ni l'autre dans l'app. Si exposition publique le
|
||||
demande, c'est au RP / firewall de gerer (donc en dehors du repo).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### F9. Basic Auth OpenCode
|
||||
|
||||
Recommandation : credentials uniquement via env (`OPENCODE_USERNAME`,
|
||||
`OPENCODE_PASSWORD`), valides au boot, sinon fail-fast.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## G. Programme Lua `opencc`
|
||||
|
||||
### G1. Emplacement et packaging
|
||||
|
||||
Plan : `apis/libopencc.lua`, `programs/opencc.lua`, `tests/opencc.lua`.
|
||||
|
||||
Recommandation : pas de `packages/tos-agent/ccpm.json` avant validation
|
||||
in-game (cf I3). Fichiers nus dans `apis/` et `programs/` pendant le PoC.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G2. Source de config (settings vs fichier vs CLI)
|
||||
|
||||
Clefs `settings` :
|
||||
- `opencc.proxy_url` (URL complete HTTPS recommandee)
|
||||
- `opencc.proxy_token`
|
||||
- `opencc.session_id` (auto-remplie)
|
||||
- `opencc.timeout` (optionnel)
|
||||
|
||||
Recommandation : **`settings` uniquement** + flags CLI (`--url`, `--token`)
|
||||
qui overrident pour le debug. Si `proxy_url` ou `proxy_token` manque,
|
||||
message clair + exit non-zero. Pas de host/port separes.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G3. Format CLI
|
||||
|
||||
- `opencc --help`, `--version`
|
||||
- `opencc "prompt"` (argv) ou interactif via `read()` si pas d'arg
|
||||
- REPL multi-tour ?
|
||||
|
||||
Recommandation : pas de REPL. Un prompt par invocation. Le contexte vient
|
||||
de la `session_id` persistante.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G4. Persistance et reset de la session
|
||||
|
||||
- Persistance : `settings.set('opencc.session_id', id); settings.save()` ou
|
||||
fichier dedie ?
|
||||
- Reset : `opencc --new` ? `--reset-session` ?
|
||||
|
||||
Recommandation : **`settings`** (coherence G2) ; flag **`opencc --new`** qui
|
||||
efface `opencc.session_id` et cree une nouvelle session via le prochain
|
||||
`/ask`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G5. Affichage de la reponse
|
||||
|
||||
- Print brut ?
|
||||
- Word-wrap manuel ?
|
||||
- Pagination ?
|
||||
- Print metadata (sessionId, model) ?
|
||||
|
||||
Recommandation : print + word-wrap simple sur largeur terminal. Pas de
|
||||
pagination. Pas de metadata sauf en mode `--verbose` (a ajouter plus tard).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G6. Erreurs reseau et `http.rules`
|
||||
|
||||
`http.post` peut renvoyer `nil` (handshake ko, host bloque par `http.rules`)
|
||||
ou un response status != 200.
|
||||
|
||||
Recommandation :
|
||||
- `nil` -> "proxy injoignable. Verifie `opencc.proxy_url` et que l'hote
|
||||
est autorise dans `http.rules`".
|
||||
- `401` -> "token invalide".
|
||||
- `413` -> "prompt trop long".
|
||||
- `502/504` -> "agent indisponible / trop lent".
|
||||
- Autre -> message generique + status code.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G7. Timeout HTTP CC
|
||||
|
||||
`http.post` n'a pas de parametre timeout standard. CC:Tweaked >= 1.97 a
|
||||
`http.request` avec timeout ; a verifier sur ATM10.
|
||||
|
||||
Recommandation : exposer `opencc.timeout`. Si CC l'accepte, on l'utilise ;
|
||||
sinon documenter la limite et compter sur A4 Option 4 pour la suite.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G8. Pattern factory et JSON
|
||||
|
||||
Repo : `apis/libccpm.lua` est une factory avec `opts.http` injectable. Meme
|
||||
chose pour `libopencc` ? Encodage JSON via `textutils.serialiseJSON` ?
|
||||
|
||||
Recommandation : **factory** : `local createOpencc = require('/apis/libopencc'); local opencc = createOpencc({ http = http, settings = settings, computerCraftTimeout = ... })`. JSON via `textutils.serialiseJSON` / `unserialiseJSON`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G9. Trim / multiline / vide
|
||||
|
||||
Recommandation : trim final, refus si prompt vide apres trim. Multiline
|
||||
preserve.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### G10. Tests Lua
|
||||
|
||||
Plan : injection d'un faux `http` via `libtest`.
|
||||
|
||||
Recommandation : `tests/opencc.lua` avec `libtest`, faux `http` qui verifie
|
||||
URL, headers (Bearer + Content-Type), body JSON, parsing succes, parsing
|
||||
erreur. Hors-scope : E2E reel avec vrai proxy.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## H. Tests et validation
|
||||
|
||||
### H1. Fixture OpenCode capturee
|
||||
|
||||
Recommandation : oui (cf C2). Sanitize, store dans
|
||||
`cc-agent-proxy/test/fixtures/session-message.json`. Sert de reference pour
|
||||
`opencode.test.ts`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H2. E2E manuel vs automatise
|
||||
|
||||
Recommandation : **manuel** pour le PoC. Documenter les commandes (cf H7).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H3. CraftOS-PC headless avant l'in-game
|
||||
|
||||
Recommandation : oui si `just craftos --headless` peut faire `http.post`.
|
||||
Premier roundtrip en local avant ATM10.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H4. Pre-requis ATM10 a documenter
|
||||
|
||||
A documenter :
|
||||
- `http` enable cote serveur.
|
||||
- Hote du proxy autorise dans `http.rules` (allow `*.tondomaine.tld:443` ou
|
||||
IP).
|
||||
- DNS / IP joignable depuis le serveur Minecraft.
|
||||
- Token + URL definis dans les settings de la turtle.
|
||||
- Provider LLM authentifie cote OpenCode.
|
||||
|
||||
Recommandation : checklist dans `docs/opencc-quickstart.md` ecrite **apres**
|
||||
la premiere validation reelle.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H5. Hooks `just check` et `just test`
|
||||
|
||||
`pre-commit` = `just check test` (Lua + luacheck). Faut-il y mettre les
|
||||
tests Node ?
|
||||
|
||||
Recommandation : **non**. Recipe separee `just node-check` (eslint+prettier)
|
||||
et `just node-test` (vitest) dans un sous-Justfile de `cc-agent-proxy/`.
|
||||
Eviter une dependance implicite Node pour les commits Lua.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H6. CI
|
||||
|
||||
Repo : pas de CI publique declaree, juste hooks locaux.
|
||||
|
||||
Recommandation : pas de CI pour le PoC. Plus tard, eventuellement un workflow
|
||||
GH Actions `node-test` + `lua-check`.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### H7. Transcript de validation manuelle
|
||||
|
||||
Recommandation : apres premier roundtrip reussi, enregistrer les commandes
|
||||
exactes et outputs sanitize dans `docs/opencc-quickstart.md`, incluant un
|
||||
deuxieme `/ask` avec le meme `sessionId` pour prouver la persistance.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## I. Architecture / coherence repo
|
||||
|
||||
### I1. Reuse de `apis/net.lua`
|
||||
|
||||
Recommandation : **non**. `net.lua` est modem/rednet. `http.post` direct
|
||||
cote Lua est le bon choix.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### I2. Reuse de `apis/eventloop.lua`
|
||||
|
||||
Recommandation : **non**. Le PoC est request/response synchrone. Re-evaluer
|
||||
si A4 passe en async (G1 post-PoC).
|
||||
|
||||
TODO: answer
|
||||
|
||||
### I3. Packaging ccpm
|
||||
|
||||
Recommandation : **post-PoC**. Apres validation in-game, creer
|
||||
`packages/tos-agent/ccpm.json` :
|
||||
- `files` : `apis/libopencc.lua`, `programs/opencc.lua`
|
||||
- `dependencies` : `tos-core`
|
||||
- `autostart` : aucun
|
||||
- Ajouter dans `packages/index.json`.
|
||||
|
||||
Declencheur : PoC reussi + au moins une raison de reinstaller/partager.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### I4. ADR
|
||||
|
||||
Recommandation : ADR-0012 "external agent bridge via HTTPS proxy" ecrit
|
||||
apres validation. Justifie la presence d'un sous-dossier Node dans un repo
|
||||
Lua.
|
||||
|
||||
TODO: answer
|
||||
|
||||
### I5. Conformite CLAUDE.md
|
||||
|
||||
- Bump `_VERSION` sur chaque module Lua modifie.
|
||||
- `--version` / `--help` sur `opencc`.
|
||||
- Lua : 2-space indent, `;`, `local function`.
|
||||
- Node : suit Prettier default.
|
||||
|
||||
Recommandation : appliquer tel quel.
|
||||
|
||||
TODO: answer
|
||||
|
||||
---
|
||||
|
||||
## J. Post-PoC (evolutions, hors scope mais a ne pas peindre dans un coin)
|
||||
|
||||
Reponds seulement si avis fort.
|
||||
|
||||
### J1. Mode async
|
||||
|
||||
Trigger : reponses LLM frequemment > timeout CC/proxy.
|
||||
|
||||
Recommandation : ajouter `POST /ask?async=1` + `GET /ask/:jobId/status`.
|
||||
Backward-compatible. `opencc` apprend a poll.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
### J2. SSE / WebSocket pour streaming
|
||||
|
||||
Pas de SSE en CC:Tweaked, mais `http.websocket` existe.
|
||||
|
||||
Recommandation : proxy WS dedie si streaming devient utile. Hors-scope PoC.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
### J3. Multi-turtle isolation et identite
|
||||
|
||||
Trigger : > 1 turtle/utilisateur sur le meme proxy.
|
||||
|
||||
Recommandation : avec A3 Option 2 c'est deja gratuit niveau sessions. Pour
|
||||
quotas, ajouter `turtleId` (= `os.getComputerID()`) au body et a la table de
|
||||
tokens.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
### J4. Outils OpenCode (lecture/ecriture fichiers)
|
||||
|
||||
Recommandation : sandbox stricte (mount lecture-seule + un dir scratch).
|
||||
Hors-scope PoC.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
### J5. Replacement de `http.post` par `apis/net.lua`
|
||||
|
||||
Recommandation : probablement jamais. `net.lua` est routeur/rednet, pas
|
||||
sortie HTTP.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
### J6. Observabilite (metrics, traces)
|
||||
|
||||
Recommandation : ignorer en PoC. Pino logs suffisent. Prometheus exporter
|
||||
plus tard si quotas.
|
||||
|
||||
TODO: answer (optionnel)
|
||||
|
||||
---
|
||||
|
||||
## K. Inconnues a valider au premier run
|
||||
|
||||
Pas de reponse texte ; coche au fur et a mesure.
|
||||
|
||||
- [ ] Version exacte d'OpenCode utilisee (`opencode --version`).
|
||||
- [ ] Format reel des `parts` retournees par `POST /session/:id/message`.
|
||||
- [ ] Comportement OpenCode si `model` est passe vs absent.
|
||||
- [ ] Basic Auth vraiment necessaire dans la config de Guillaume.
|
||||
- [ ] Timeout effectif `http.post` cote CC sur ATM10 (et si CC:Tweaked
|
||||
version supporte un parametre timeout).
|
||||
- [ ] Reaction OpenCode si on hammer une session morte (404 ? autre ?).
|
||||
- [ ] Limite de longueur d'un message accepte par OpenCode.
|
||||
- [ ] Cas ou le provider LLM est down : OpenCode renvoie quoi ?
|
||||
- [ ] CraftOS-PC headless peut-il faire `http.post` HTTPS vers le proxy en
|
||||
local ?
|
||||
|
||||
---
|
||||
|
||||
## L. Quoi repondre en priorite
|
||||
|
||||
Si tu veux aller vite, reponds dans cet ordre. Le reste decoule.
|
||||
|
||||
1. A1 - critere d'acceptation
|
||||
2. A2 - workspace OpenCode (frontiere de confiance)
|
||||
3. A3 - cycle session
|
||||
4. A4 - sync vs async
|
||||
5. A5 - topologie deploiement
|
||||
6. A6 - auth turtle <-> proxy
|
||||
7. A7 - forme de la reponse
|
||||
8. A8 - scope v1
|
||||
|
||||
Une fois ces 8 trances, on peut souvent ignorer les sections B-J pour le
|
||||
"go/no-go" et juste valider les recommandations par defaut. Les detailler
|
||||
n'apporte de la valeur que si tu veux devier d'une recommandation precise.
|
||||
Loading…
Reference in New Issue
Block a user