135 lines
6.0 KiB
Markdown
135 lines
6.0 KiB
Markdown
# OpenCode-Adapter für TensorX
|
|
|
|
Diese Referenz gilt für Modell-IDs mit `z-ai/`, `qwen/` oder `moonshotai/`. Der Skill ruft
|
|
TensorX nicht selbst auf, sondern startet OpenCode über `opencode-tensorx-adapter.py`.
|
|
|
|
## Voraussetzungen und Authentifizierung
|
|
|
|
1. OpenCode installieren und die Version protokollieren:
|
|
|
|
```powershell
|
|
npm install -g opencode-ai
|
|
opencode --version
|
|
```
|
|
|
|
2. TensorX einmal im OpenCode-Credential-Store anmelden:
|
|
|
|
```powershell
|
|
opencode auth login
|
|
opencode auth list
|
|
```
|
|
|
|
Die statische Datei `opencode-tensorx.json` enthält Provider, Basis-URL, Modelle und
|
|
Effort-Varianten, aber keinen API-Key. Der Adapter liest weder Cline-Dateien noch einen
|
|
Cline-Credential-Store. OpenCode löst das Credential selbst auf. Keys niemals in
|
|
Laufartefakte, Prompts oder die Konfigurationsvorlage schreiben.
|
|
|
|
## Modell- und Effort-Mapping
|
|
|
|
Der Adapter ergänzt intern das Providerpräfix `tensorx/`. Aus
|
|
`qwen/qwen3.8-flash-next` wird daher für OpenCode
|
|
`tensorx/qwen/qwen3.8-flash-next`; im Messprotokoll bleibt die ursprüngliche TensorX-ID.
|
|
|
|
Die Stufen `low`, `medium`, `high`, `xhigh` und `max` werden als OpenCode-Varianten aus
|
|
`opencode-tensorx.json` übergeben. Für Qwen und GLM enthält die Variante
|
|
`thinking: {type: enabled, level: ...}`; `max` wird auf `xhigh` abgebildet, falls der Provider
|
|
keine eigene `max`-Stufe kennt. Nur in der Vorlage vorhandene Varianten werden per
|
|
`--variant` gesetzt.
|
|
|
|
## Isolierte Laufkonfiguration
|
|
|
|
Für jeden Lauf schreibt der Adapter `_meta/opencode-config.json` und setzt nur für den
|
|
Kindprozess `OPENCODE_CONFIG` auf diese Datei. Der Aufruf verwendet `opencode run --pure`,
|
|
damit keine interaktive Oberfläche benötigt wird. Der Prompt wird über stdin übergeben.
|
|
|
|
Die Berechtigungen beginnen mit `deny` und erlauben gezielt:
|
|
|
|
- Lesen, Suchen, Auflisten sowie eine kleine Read-only-Shell-Allowlist;
|
|
- Schreiben und externe Verzeichnisse ausschließlich für das angegebene Ergebnisverzeichnis;
|
|
- im Modus `solo` keine Tasks;
|
|
- im Modus `builtin` nur OpenCodes `general`- und `explore`-Subagenten;
|
|
- im Modus `custom` nur Rollen aus der mit `--agents` übergebenen JSON-Datei.
|
|
|
|
Für das Ergebnisziel erzeugt der Wrapper kanonische sowie zum aktiven OpenCode-Root und zur
|
|
Git-Worktree-Wurzel relative Allow-Patterns. Das ist unter Windows notwendig, wenn Root und
|
|
Laufverzeichnis im selben Git-Worktree liegen, das Laufverzeichnis aber außerhalb des
|
|
Root-Unterordners liegt.
|
|
|
|
Webzugriff, Skills, Rückfragen und Weiterdelegation durch Subagenten bleiben gesperrt. Bei
|
|
`custom` übersetzt der Adapter `description` und `prompt` jeder Rolle in eine explizite
|
|
OpenCode-Subagentenkonfiguration mit demselben Modell wie der Hauptagent.
|
|
|
|
## Aufruf
|
|
|
|
```powershell
|
|
$skillDir = "<Verzeichnis des Skills>"
|
|
$lauf = "<absoluter Pfad zum Laufverzeichnis>"
|
|
$root = "<Root-Verzeichnis der Codebasis>"
|
|
$modell = "<TensorX-Modell-ID>"
|
|
$effort = "<low|medium|high|xhigh|max>"
|
|
$modus = "<solo|builtin|custom>"
|
|
$agents = "<Agenten-JSON; nur bei custom>"
|
|
|
|
python "$skillDir\opencode-tensorx-adapter.py" `
|
|
--prompt "$lauf\_meta\combined_prompt.md" `
|
|
--root $root `
|
|
--output "$lauf\Ergebnisse" `
|
|
--model $modell `
|
|
--effort $effort `
|
|
--mode $modus `
|
|
--agents $agents `
|
|
--stall-timeout 600 `
|
|
--max-runtime 0 `
|
|
--result-dir $lauf `
|
|
--title "run-experiment $modell $modus $effort"
|
|
```
|
|
|
|
`--agents` bei `solo` und `builtin` weglassen. `--stall-timeout 600` beendet den gesamten
|
|
OpenCode-Prozessbaum, wenn zehn Minuten lang weder stdout noch stderr Aktivität zeigen.
|
|
`--stall-timeout 0` deaktiviert diese Sicherung. `--max-runtime 0` setzt kein absolutes
|
|
Laufzeitlimit. `Ctrl+C` beendet ebenfalls den Prozessbaum und persistiert soweit möglich das
|
|
Teilergebnis. Ein leeres `Ergebnisse`-Verzeichnis macht den Lauf standardmäßig zu einem Fehler.
|
|
Nur ein bewusst textueller Smoke-Test darf diese Prüfung mit `--allow-empty-output` abschalten.
|
|
|
|
## Laufartefakte und Messfelder
|
|
|
|
| Datei | Inhalt |
|
|
|---|---|
|
|
| `OpenCodeEvents.jsonl` | unveränderter, inkrementell geschriebener JSON-Ereignisstrom |
|
|
| `OpenCode.log` | OpenCode-stderr, inkrementell geschrieben |
|
|
| `Adapter.log` | Start, Lebenszyklus, Abbruchgrund und Abschluss des Wrappers |
|
|
| `_meta/opencode-config.json` | tatsächlich verwendete, keyfreie Laufkonfiguration |
|
|
| `_meta/opencode-session.json` | exportierte Session, soweit eine Session-ID vorliegt |
|
|
| `RawResult.json` | normalisierte Metriken für das gemeinsame Messprotokoll |
|
|
|
|
Aus `RawResult.json` verwenden:
|
|
|
|
| Messgröße | Feld |
|
|
|---|---|
|
|
| Erfolg/Abbruch | `is_error`, `subtype`, `timed_out`, `interrupted`, `exit_code`, `errors` |
|
|
| Modellkontrolle | `provider`, `model`, `model_requested` |
|
|
| Zeit | `duration_ms`, `start_time`, `end_time` |
|
|
| Tokens | `usage.prompt_tokens`, `completion_tokens`, `reasoning_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `total_tokens` |
|
|
| Turns und Ende | `num_turns`, `finish_reason` |
|
|
| Tools | `tool_call_count`, `tool_call_types`, `tool_calls` |
|
|
| Subagenten | `subagent_stats`, `subagent_details` |
|
|
| Ergebnisdateien | `written_files` |
|
|
| Abschlusstext | `result` |
|
|
| Reproduzierbarkeit | `adapter_version`, `opencode_version`, `config_path`, `session_id` |
|
|
|
|
`usage.total_tokens` übernimmt nach Möglichkeit OpenCodes Gesamtwert. Fehlt dieser, addiert
|
|
der Adapter Input, Output, Reasoning, Cache-Read und Cache-Write aus den gelieferten
|
|
OpenCode-Feldern. Kosten werden nur protokolliert, wenn OpenCode sie liefert; nicht schätzen.
|
|
|
|
## Pflichtprüfung
|
|
|
|
1. `RawResult.json` existiert und `is_error` ist `false`.
|
|
2. `timed_out` und `interrupted` sind `false`; `exit_code` ist `0`.
|
|
3. `OpenCode.log` und `errors` enthalten keinen Provider- oder Permissionfehler.
|
|
4. Für Analyseversuche ist `Ergebnisse/` nicht leer und `tool_call_count` größer null.
|
|
5. `model_requested` entspricht der angeforderten TensorX-ID; Provider ist `tensorx`.
|
|
6. Bei `custom` sind die erwarteten Rollen in `subagent_stats.by_type` nachweisbar.
|
|
|
|
Ein absichtlich textueller Smoke-Test darf von den Prüfungen 4 und 6 abweichen, muss aber
|
|
Antwort, Exitcode, Modell, Sessionexport und Tokenmetriken bestätigen.
|