161 lines
6.9 KiB
Plaintext
161 lines
6.9 KiB
Plaintext
{
|
|
// OpenCode configuration for this repo's CI agents.
|
|
// - e2e-ci-* agents: used by .github/workflows/e2e-council.yml for CI test-generation, on DeepSeek.
|
|
// - ai-review-* agents: used by scripts/ai-review/run-review.mjs (dispatched via `opencode serve`)
|
|
// for PR code review. ONE shared set, run once per provider by the matrix in
|
|
// .github/workflows/ai-code-review.yml (DeepSeek-V4-Pro). The model is
|
|
// supplied per-call by the runner, so the agents themselves are provider-agnostic.
|
|
// Docs: https://opencode.ai/docs/ — verify provider shape against current docs at build time.
|
|
"$schema": "https://opencode.ai/config.json",
|
|
|
|
"provider": {
|
|
"deepseek": {
|
|
"npm": "@ai-sdk/openai-compatible",
|
|
"name": "DeepSeek",
|
|
"options": {
|
|
"baseURL": "https://api.deepseek.com",
|
|
"apiKey": "{env:DEEPSEEK_API_KEY_E2E}"
|
|
},
|
|
"models": {
|
|
"deepseek-v4-pro": {
|
|
"name": "DeepSeek-V4-Pro",
|
|
"limit": { "context": 1048576, "output": 262144 }
|
|
}
|
|
}
|
|
},
|
|
// Separate DeepSeek provider for PR review — distinct from the `deepseek` provider above so
|
|
// review usage/billing (DEEPSEEK_API_KEY) is isolated from the e2e council (DEEPSEEK_API_KEY_E2E).
|
|
"deepseek-review": {
|
|
"npm": "@ai-sdk/openai-compatible",
|
|
"name": "DeepSeek (review)",
|
|
"options": {
|
|
"baseURL": "https://api.deepseek.com",
|
|
"apiKey": "{env:DEEPSEEK_API_KEY}"
|
|
},
|
|
"models": {
|
|
"deepseek-v4-pro": {
|
|
"name": "DeepSeek-V4-Pro",
|
|
"limit": { "context": 1048576, "output": 262144 }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// Default model for runs that don't pass --model explicitly.
|
|
// The workflow passes --model deepseek/deepseek-v4-pro per agent invocation.
|
|
"model": "deepseek/deepseek-v4-pro",
|
|
|
|
// Register the CI agents explicitly so `--agent e2e-ci-*` resolves deterministically.
|
|
// OpenCode does NOT auto-discover agents nested in .opencode/agents/<subdir>/ (the first CI
|
|
// run fell back to the default agent), so we point each name at its prompt file here.
|
|
"agent": {
|
|
"e2e-ci-triage": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-triage.md}"
|
|
},
|
|
"e2e-ci-analyst": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-analyst.md}"
|
|
},
|
|
"e2e-ci-architect": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-architect.md}"
|
|
},
|
|
"e2e-ci-engineer": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-engineer.md}"
|
|
},
|
|
"e2e-ci-sentinel": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-sentinel.md}"
|
|
},
|
|
"e2e-ci-healer": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-healer.md}"
|
|
},
|
|
"e2e-ci-refiner": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-refiner.md}"
|
|
},
|
|
"e2e-ci-responder": {
|
|
"mode": "primary",
|
|
"prompt": "{file:./.opencode/agents/e2e_ci_council_of_agents/e2e-ci-responder.md}"
|
|
},
|
|
|
|
// PR review agents. Prompts are assembled at call time in run-review.mjs
|
|
// (shared-rules.md + agents/<key>.md) and sent via the `system` override on
|
|
// session.prompt, so no `prompt` is registered here.
|
|
//
|
|
// ONE shared agent set drives every provider. run-review.mjs sends an explicit
|
|
// `model: {providerID, modelID}` (and `variant` when REVIEW_MODEL_VARIANT is set) on each
|
|
// session.prompt call, which overrides whatever is declared here — so the `model` below is
|
|
// only a default for local/manual `opencode` runs. Do NOT fork these into per-provider
|
|
// copies: identical agents are exactly what makes a model-vs-model comparison meaningful,
|
|
// and duplicated blocks drift.
|
|
//
|
|
// Tool policy is an ALLOWLIST-by-negation, not just "no write/edit/bash": PR diff
|
|
// content is untrusted (any external contributor can put prompt-injection text in a
|
|
// diff) and is fed directly into these agents' prompts, with output auto-posted to the
|
|
// PR. Only read/glob/grep are needed to inspect real repo context around the diff.
|
|
// Everything else — especially webfetch/websearch (SSRF / exfiltration via injected
|
|
// instructions) and task (spawning subagents that may not inherit these restrictions)
|
|
// — is explicitly denied. Deny the full known opencode tool-id set (see
|
|
// `opencode serve` + `GET /experimental/tool/ids`) rather than only the obvious ones,
|
|
// so a newly added tool doesn't silently become available by omission.
|
|
"ai-review-security": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
},
|
|
"ai-review-code-quality": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
},
|
|
"ai-review-performance": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
},
|
|
"ai-review-documentation": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
},
|
|
"ai-review-release": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
},
|
|
"ai-review-coordinator": {
|
|
"mode": "primary",
|
|
"model": "deepseek-review/deepseek-v4-pro",
|
|
"tools": {
|
|
"read": true, "glob": true, "grep": true,
|
|
"write": false, "edit": false, "bash": false, "patch": false, "apply_patch": false,
|
|
"webfetch": false, "websearch": false, "task": false, "todowrite": false, "skill": false
|
|
}
|
|
}
|
|
}
|
|
}
|