feat(model-server): frontend modèles locaux — badge de statut & CRUD serveurs (#35) et wizard multi-profils OpenCode (#36)
Sprint « Modeles locaux », couche frontend. #35 : - F35.1 badge de statut de lancement du serveur local (ModelServerLaunchBadge + useAgentsModelServer). - F35.2 feature model-servers : CRUD (ModelServersPanel / useModelServers / gateway modelServer) et ModelServerSelect. #36 : - Liste multi-profils OpenCode dans le wizard de premier lancement, gateway de clonage (clone_opencode_profile_from_seed). Tests verts (exécution réelle) : tsc propre, vitest 608/608. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -13,11 +13,92 @@ export interface HealthReport {
|
||||
note: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle status of a local model server during an agent launch (F35, mirror
|
||||
* of the backend `ModelServerStatusDto`, tagged on `state`, camelCase wire).
|
||||
*
|
||||
* Contract note — the backend event carries the `serverId` on the *envelope*
|
||||
* ({@link DomainEvent} `modelServerStatusChanged`), not inside the status, and it
|
||||
* does NOT emit `baseURL`/`model` in the status payload: the UI reads what the
|
||||
* backend actually sends. `reused` (on `ready`) tells apart a freshly-started
|
||||
* server from a reused running one.
|
||||
*/
|
||||
export type ModelServerStatus =
|
||||
| { state: "notConfigured" }
|
||||
| { state: "probing" }
|
||||
| { state: "starting" }
|
||||
| { state: "ready"; reused: boolean }
|
||||
| { state: "failed"; code: string; message: string };
|
||||
|
||||
/**
|
||||
* Stop policy of a managed local model server (mirror of the backend
|
||||
* `StopPolicyDto`, camelCase wire):
|
||||
* - `keepAlive`: leave the process running,
|
||||
* - `stopOnAppExit`: stop when IdeA exits (the effective default),
|
||||
* - `stopWhenUnused`: stop when no profile references it.
|
||||
*/
|
||||
export type StopPolicy = "keepAlive" | "stopOnAppExit" | "stopWhenUnused";
|
||||
|
||||
/**
|
||||
* A declared local model server (F35, mirror of the backend flat
|
||||
* `LocalModelServerConfigDto`, camelCase wire). Global to IdeA (not project
|
||||
* scoped). Referenced by an OpenCode profile through
|
||||
* `OpenCodeConfig.localModelServerId` (= this `id`).
|
||||
*
|
||||
* Contract notes:
|
||||
* - `id` is a UUID **minted client-side** on create (the backend requires a valid
|
||||
* UUID; it does not generate the server id, only an internal model id it hides).
|
||||
* - `servedModelName` is what the user configures and what is sent to OpenCode as
|
||||
* the `model` — the backend's internal `model.id`/`model.label` are not exposed.
|
||||
* - `modelPath` is required by the backend when `autoStart` is `true`.
|
||||
*/
|
||||
export interface LocalModelServerConfig {
|
||||
id: string;
|
||||
/** Only `llamaCpp` is supported today (camelCase, not "llamacpp"). */
|
||||
kind: "llamaCpp";
|
||||
name: string;
|
||||
/** OpenAI-compatible base URL served by `llama-server` (normalised to `/v1`). */
|
||||
baseURL: string;
|
||||
port: number;
|
||||
/** Absolute `.gguf` path. Required when `autoStart` is `true`. */
|
||||
modelPath?: string;
|
||||
/** Model name exposed by the server and sent to OpenCode as `model`. */
|
||||
servedModelName: string;
|
||||
/** Explicit `llama-server` executable path/command (optional). */
|
||||
binaryPath?: string;
|
||||
args: string[];
|
||||
autoStart: boolean;
|
||||
stopPolicy: StopPolicy;
|
||||
}
|
||||
|
||||
/** A domain event relayed from the backend (tagged union on `type`). */
|
||||
export type DomainEvent =
|
||||
| { type: "projectCreated"; projectId: string }
|
||||
| { type: "agentLaunched"; agentId: string; sessionId: string }
|
||||
| { type: "agentExited"; agentId: string; code: number }
|
||||
| {
|
||||
/**
|
||||
* A local model server changed lifecycle state while (re)launching an
|
||||
* agent whose OpenCode profile binds `localModelServerId` (F35). Keyed by
|
||||
* `serverId`; the frontend correlates it back to the agent through the
|
||||
* profile's `opencode.localModelServerId`.
|
||||
*/
|
||||
type: "modelServerStatusChanged";
|
||||
serverId: string;
|
||||
status: ModelServerStatus;
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* An agent launch failed before a runtime session was created (F35). Unlike
|
||||
* a generic "agent failed", this carries an actionable `message` and a
|
||||
* stable `code`; `cause` namespaces the failure (e.g. `"model_server"`).
|
||||
*/
|
||||
type: "agentLaunchFailed";
|
||||
agentId: string;
|
||||
cause: string;
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
| { type: "agentProfileChanged"; agentId: string; profileId: string }
|
||||
| { type: "agentBusyChanged"; agentId: string; busy: boolean }
|
||||
| {
|
||||
@ -687,6 +768,13 @@ export interface OpenCodeConfig {
|
||||
reasoning?: boolean;
|
||||
/** Enables attachments. Effective default: `false`. */
|
||||
attachment?: boolean;
|
||||
/**
|
||||
* Optional id of a managed local model server (F35) this profile binds to.
|
||||
* When set, IdeA can start/stop the referenced `llama-server` for the profile;
|
||||
* omitted when the profile points at an externally-managed endpoint (mirrors
|
||||
* the backend `skip_serializing_if`). Opaque string id on the wire.
|
||||
*/
|
||||
localModelServerId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user