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:
@ -9,6 +9,7 @@ import type {
|
||||
ContextInjection,
|
||||
HttpChatConfig,
|
||||
InjectionStrategy,
|
||||
OpenCodeConfig,
|
||||
} from "@/domain";
|
||||
|
||||
/** A field-keyed validation error map (empty ⇒ valid). */
|
||||
@ -20,6 +21,7 @@ export type ProfileErrors = Partial<
|
||||
| "flag"
|
||||
| "var"
|
||||
| "endpoint"
|
||||
| "baseURL"
|
||||
| "model"
|
||||
| "apiKeyEnv"
|
||||
| "requestTimeoutMs"
|
||||
@ -95,6 +97,23 @@ export function validateHttpChatConfig(c: HttpChatConfig): ProfileErrors {
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an {@link OpenCodeConfig} draft the way the backend
|
||||
* `OpenCodeConfig::new` would (base URL http/https + non-empty, model non-empty;
|
||||
* the API key is a free-form, optional secret). Returns an empty object when the
|
||||
* draft is valid.
|
||||
*/
|
||||
export function validateOpenCodeConfig(c: OpenCodeConfig): ProfileErrors {
|
||||
const errors: ProfileErrors = {};
|
||||
if (!isValidHttpUrl(c.baseURL)) {
|
||||
errors.baseURL = "Base URL must start with http:// or https://.";
|
||||
}
|
||||
if (c.model.trim().length === 0) {
|
||||
errors.model = "Model is required.";
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a profile draft the way the backend would, so the wizard can surface
|
||||
* errors before any `invoke`. Returns an empty object when the draft is valid.
|
||||
@ -125,8 +144,15 @@ export function validateProfile(p: AgentProfile): ProfileErrors {
|
||||
Object.assign(errors, validateHttpChatConfig(p.chatHttp));
|
||||
}
|
||||
}
|
||||
if (p.structuredAdapter === "openCode" && p.opencode?.model !== undefined) {
|
||||
if (p.opencode.model.trim().length === 0) errors.model = "Model is required.";
|
||||
// An OpenCode profile carries its own llama.cpp endpoint config; the backend
|
||||
// refuses to persist it unless base URL + model are well-formed, so mirror that.
|
||||
if (p.structuredAdapter === "openCode") {
|
||||
if (!p.opencode) {
|
||||
errors.baseURL = "Base URL must start with http:// or https://.";
|
||||
errors.model = "Model is required.";
|
||||
} else {
|
||||
Object.assign(errors, validateOpenCodeConfig(p.opencode));
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
@ -168,6 +194,19 @@ export function defaultHttpChatConfig(): HttpChatConfig {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A sensible default {@link OpenCodeConfig} for a fresh OpenCode profile draft —
|
||||
* pre-fills a local `llama-server` endpoint so the form starts valid. Mirrors the
|
||||
* backend reference profile (`http://localhost:8080/v1`, `qwen3-coder-30b`).
|
||||
*/
|
||||
export function defaultOpenCodeConfig(): OpenCodeConfig {
|
||||
return {
|
||||
baseURL: "http://localhost:8080/v1",
|
||||
apiKey: "sk-no-key",
|
||||
model: "qwen3-coder-30b",
|
||||
};
|
||||
}
|
||||
|
||||
/** A fresh, empty custom-profile draft (id minted client-side). */
|
||||
export function emptyCustomProfile(): AgentProfile {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user