feat(opencode): remplace le provider Ollama par llama.cpp

Le tool-calling local ne fonctionnait jamais via Ollama. Refonte du
support local d'OpenCode autour de llama.cpp: profil, catalogue,
matérialisation de la config OpenCode et surface first-run alignés sur
llama-server (backend + frontend).

QA vert (commandes réelles): domain 244, application 81+64, infra 263
(10 échecs = bind-port sandbox identiques sur develop, non-régression),
frontend 574, tsc propre. Réserve E2E live non bloquante faute de
llama-server joignable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 00:41:19 +02:00
parent eaba05d27d
commit 4e70631c40
12 changed files with 478 additions and 140 deletions

View File

@ -1160,20 +1160,18 @@ export const MOCK_REFERENCE_PROFILES: AgentProfile[] = [
cwdTemplate: "{projectRoot}",
},
{
id: "mock-ollama",
name: "Ollama / OpenAI-compatible local model",
command: "openai-compatible",
id: "mock-opencode",
name: "OpenCode + llama.cpp",
command: "opencode",
args: [],
contextInjection: { strategy: "conventionFile", target: "AGENTS.md" },
detect: null,
detect: "opencode --version",
cwdTemplate: "{projectRoot}",
structuredAdapter: "openAiCompatible",
chatHttp: {
endpoint: "http://localhost:11434/v1",
model: "qwen2.5-coder",
requestTimeoutMs: 120_000,
connectTimeoutMs: 5_000,
maxToolIterations: 16,
structuredAdapter: "openCode",
opencode: {
baseURL: "http://localhost:8080/v1",
apiKey: "sk-no-key",
model: "qwen3-coder-30b",
},
},
];

View File

@ -23,15 +23,15 @@ function customProfile(id: string, command: string): AgentProfile {
describe("MockProfileGateway", () => {
it("firstRunState is first-run with only the selectable reference profiles", async () => {
// §17.3/D7: only structured-drivable profiles are offered (Claude/Codex CLIs
// + the OpenAI-compatible local/LAN adapter, ticket #14); Gemini/Aider are
// filtered out of the selection path server-side.
// + the OpenCode + llama.cpp local adapter); Gemini/Aider are filtered out of
// the selection path server-side.
const gw = new MockProfileGateway();
const state = await gw.firstRunState();
expect(state.isFirstRun).toBe(true);
expect(state.referenceProfiles.map((p) => p.command)).toEqual([
"claude",
"codex",
"openai-compatible",
"opencode",
]);
});
@ -53,7 +53,7 @@ describe("MockProfileGateway", () => {
expect(byCommand).toEqual({
claude: true,
codex: false,
"openai-compatible": false,
opencode: false,
});
});