Files
comun/docs/opencode_agenti_orchestrare.md
2026-09-28 16:01:35 +03:00

6.0 KiB

Agenti opencode (DeepSeek V4.1 Flash) orchestrati din Claude Code

Verificat live 15.09.2026, opencode 1.18.31. Docs: https://opencode.ai/docs/server/

Model

opencode-go/deepseek-v4.1-flash (abonament opencode go). In API: {"providerID":"opencode-go","modelID":"deepseek-v4.1-flash"}.

Varianta 1: one-shot (fara comunicare pe parcurs)

opencode run -m opencode-go/deepseek-v4.1-flash --title <lane> "<sarcina>"
opencode run -s <sessionID> "<mesaj urmator>"     # continua aceeasi sesiune dupa ce s-a oprit

Varianta 2: server + HTTP (mesaje in timpul lucrului) — recomandat

Pornire (un server per proiect, pentru toate lane-urile lui, in directorul proiectului):

opencode serve --port <port proiect>        # 127.0.0.1, fundal

Serverele lungi (opencode serve, archon serve) se pornesc cu Start-Process (proces propriu), nu ca task de fundal al sesiunii Claude Code: acela e omorat cand memoria e putina. Port fix per proiect. Proiectele ROA ruleaza in paralel; pe acelasi port, oprirea serverului dintr-un proiect opreste lane-urile celuilalt si le poate muta directorul de lucru (verificat 15.09.2026: lane ROACONT ajuns in ROAFACTURARE).

Proiect Port
ROAFACTURARE 4096
ROACONT 4196
ROAIMOB 4296

Proiect nou: urmatorul port liber din tabel (+100), trecut aici inainte de pornire. In API trimite si ?directory=<radacina proiectului>.

Actiune Apel
Sesiune noua POST /session {title} → id
Sarcina (nu asteapta) POST /session/:id/prompt_async {model, parts:[{type:"text",text}]}
Mesaj in timpul lucrului acelasi prompt_async pe sesiunea ocupata
Stare GET /session/status → {id:{type:"busy"}}; sesiunea lipseste cand e libera
Rezultat GET /session/:id/message (parts cu type=text)
Oprire POST /session/:id/abort
Evenimente live GET /event (SSE)
Interfata vizuala opencode attach http://127.0.0.1:<port proiect> (Marius poate urmari sesiunile)

Comportament verificat: mesajul trimis cat agentul e busy intra in coada si e preluat la pasul urmator (dupa apelul de tool curent), in aceeasi sesiune; agentul l-a respectat. Nu intrerupe un tool aflat in executie. Pentru oprire imediata: abort, apoi mesaj nou.

Prompt initial (obligatoriu)

opencode incarca singur CLAUDE.md din proiect si ~/.claude/CLAUDE.md, dar acolo scrie cum sa orchestreze Claude (delegare, gstack), nu cum sa execute. De aceea fiecare sesiune primeste COMUN\docs\opencode_prompt_initial.md in campul system (verificat: agentul il respecta):

$sys = [IO.File]::ReadAllText('D:\ROA\<PROIECT>\COMUN\docs\opencode_prompt_initial.md')
$b = @{model=$m; system=$sys; parts=@(@{type='text';text="Lane: <nume>. <sarcina>"})} | ConvertTo-Json -Depth 5
Invoke-RestMethod -Method Post "$u/session/$sid/prompt_async" -ContentType 'application/json; charset=utf-8' -Body ([Text.Encoding]::UTF8.GetBytes($b))

Cu opencode run, fara server: pui promptul ca fisier atasat, -f COMUN\docs\opencode_prompt_initial.md. Promptul impune: rol de executant, citirea reguli_lucru.md, interdictiile (commit, write-back, binare, sed -i), censul cp1250 + CRLF, raportul docs\raport_<lane>.md si ultimul mesaj GATA <lane> / BLOCAT <lane>: motiv.

Permisiuni

Fara configurare, agentul se opreste la fiecare acces in afara proiectului (scratchpad, D:\ROA\UTIL) si asteapta aprobare. Configurarea e globala, pentru toate proiectele, in %USERPROFILE%\.config\opencode\opencode.jsonc:

"permission": { "edit": "allow", "bash": "allow", "webfetch": "allow", "external_directory": "allow" }

Se aplica la pornirea serverului (opencode serve); un server deja pornit trebuie repornit. O cerere ramasa in asteptare se aproba prin API: GET /permission → POST /session/:id/permissions/:permissionID {"response":"always"}.

Flux standard pe o lucrare (plan -> executie -> review -> aprobare)

  1. Plan (orchestratorul, Opus): docs\plan_<subiect>.md exact - pasii, codul de inserat, locul (fisier:linie), pasul 0 = baseline curat (*.pre_runda1.bak == svn cat), testul cu cazurile lui, verificarile da/nu, livrarea. Executantul nu redeseneaza; un brief vag produce cod in plus.
  2. Executie: sesiune opencode noua, Lane: <x>. Executa EXACT planul din .... Livreaza patch + raport + GATA.
  3. Verificare orchestrator (asserturi, nu citire): 0 x EF BF BD, CRLF pe toate liniile (numarat cu perl -ne '$c++ if /\r\n$/'; grep -c $'\r$' din Git Bash numara gresit), liniile cu octeti

    0x7F identice cu baseline, git diff --no-index citit o data fata de plan, testul trecut.

  4. Review: sesiune opencode NOUA (nu executantul), rol de reviewer, nu modifica cod. Brief docs\brief_review_<subiect>.md cu: intrarile (plan, patch, cod, test), cele 5 verificari - fidelitate fata de plan, corectitudine pe fluxul real (apelanti, alias selectat, cursoare inchise, NULL, ramurile neatinse raman identice), conventii (reguli_lucru.md 2-3), octeti/CRLF, testul rulat de el -, livrare docs\review_<subiect>.md cu BLOCANT/MAJOR/MINOR + fisier:linie + dovada; ce nu poate dovedi marcheaza "ipoteza". Ultimul mesaj REVIEW GATA: <n> BLOCANT, <n> MAJOR, <n> MINOR.
  5. BLOCANT/MAJOR -> corectie in sesiunea executantului (sau una noua cu handoff), apoi review din nou. BLOCANT de doua ori sau verificarea de la 3 pica de doua ori -> escaladare Opus.
  6. Aprobare Marius pe patch; abia apoi commit.

Prag context per sesiune opencode: ca la subagenti (~200-250k); peste -> abort, handoff pe disc, sesiune noua. Contextul curent: input + cache.read din info.tokens al ultimului mesaj (GET /session/:id/message).

Reguli pentru lane-uri

  • Sarcina contine numele lane-ului, fisierele exacte si criteriul de terminare.
  • Orchestratorul verifica dupa fiecare lane: diff, octeti cp1252, CRLF, teste.
  • Dupa lucru: opreste serverul (PID-ul real e cel care asculta pe port, nu cel din Start-Process): Stop-Process -Id (Get-NetTCPConnection -LocalPort <port proiect> -State Listen).OwningProcess - doar portul propriu.