Sauvegarde de l'arbre de travail en cours (persistance P8, conversations C-series, write-portal frontend, médiation d'entrée) avant d'attaquer le support de la délégation inter-agents pour les profils Codex. Le round-trip inter-agent question/réponse est couvert sans tokens par les tests loopback existants (state::mcp_e2e_loopback_tests). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
492 lines
16 KiB
TypeScript
492 lines
16 KiB
TypeScript
/**
|
|
* Pure UI-domain types — TS mirrors of the backend DTOs (camelCase wire format,
|
|
* ARCHITECTURE §1.3). No React, no Tauri here: these are plain data shapes the
|
|
* ports speak in, so view logic and gateways stay testable in isolation.
|
|
*/
|
|
|
|
/** Health report returned by the `health` gateway/command. */
|
|
export interface HealthReport {
|
|
version: string;
|
|
alive: boolean;
|
|
timeMillis: number;
|
|
correlationId: string;
|
|
note: string | null;
|
|
}
|
|
|
|
/** 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 }
|
|
| { type: "agentProfileChanged"; agentId: string; profileId: string }
|
|
| { type: "agentBusyChanged"; agentId: string; busy: boolean }
|
|
| {
|
|
/**
|
|
* A delegation is ready to be injected into the agent's native terminal
|
|
* (ARCHITECTURE §20). The backend is the queue/busy authority but no longer
|
|
* PTY-writes the turn: the frontend write-portal runs the handshake (b→e)
|
|
* and writes `text` + `submitSequence`. `submitSequence`/`submitDelayMs`
|
|
* come from the target's profile; absent ⇒ the portal applies its defaults
|
|
* (`"\r"`, ~60 ms).
|
|
*/
|
|
type: "delegationReady";
|
|
agentId: string;
|
|
ticket: string;
|
|
text: string;
|
|
submitSequence?: string;
|
|
submitDelayMs?: number;
|
|
}
|
|
| { type: "templateUpdated"; templateId: string; version: number }
|
|
| { type: "agentDriftDetected"; agentId: string; from: number; to: number }
|
|
| { type: "agentSynced"; agentId: string; to: number }
|
|
| { type: "layoutChanged"; projectId: string }
|
|
| { type: "remoteConnected"; projectId: string }
|
|
| { type: "gitStateChanged"; projectId: string }
|
|
| {
|
|
type: "orchestratorRequestProcessed";
|
|
requesterId: string;
|
|
action: string;
|
|
ok: boolean;
|
|
/**
|
|
* Which entry door the delegation arrived through: `"mcp"` (MCP server) or
|
|
* `"file"` (`.ideai/requests` watcher). Optional for backward-compatibility:
|
|
* an event relayed without it simply yields no source badge.
|
|
*/
|
|
source?: "mcp" | "file";
|
|
}
|
|
| { type: "ptyOutput"; sessionId: string; bytes: number[] };
|
|
|
|
/** Where a project physically lives (mirror of the backend `RemoteRef`). */
|
|
export type RemoteRef =
|
|
| { kind: "local" }
|
|
| {
|
|
kind: "ssh";
|
|
host: string;
|
|
port: number;
|
|
user: string;
|
|
auth: unknown;
|
|
remoteRoot: string;
|
|
}
|
|
| { kind: "wsl"; distro: string };
|
|
|
|
/** A project as returned by the `project` gateway (mirror of `ProjectDto`). */
|
|
export interface Project {
|
|
id: string;
|
|
name: string;
|
|
root: string;
|
|
remote: RemoteRef;
|
|
createdAt: number;
|
|
}
|
|
|
|
/** Stable error shape mirrored from the backend `ErrorDto`. */
|
|
export interface GatewayError {
|
|
code: string;
|
|
message: string;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Layout (L4) — mirror of the domain `LayoutTree` (ARCHITECTURE §3, §7).
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** Split direction: `row` = columns (left→right), `column` = rows (top→bottom). */
|
|
export type Direction = "row" | "column";
|
|
|
|
/** A terminal-hosting leaf cell. `session` is the hosted SessionId, if any.
|
|
* `agent` is the agent id if an agent is pinned to this cell (absent = plain terminal).
|
|
* `conversationId` is the persistent CLI conversation id (survives PTY close/reopen,
|
|
* lets the agent resume); omitted when absent (mirrors the backend `skip_serializing_if`).
|
|
* `agentWasRunning` records whether the cell's agent process was running at close time;
|
|
* omitted when `false`. */
|
|
export interface LeafCell {
|
|
id: string;
|
|
session?: string | null;
|
|
agent?: string;
|
|
conversationId?: string;
|
|
agentWasRunning?: boolean;
|
|
}
|
|
|
|
/** A weighted child of a split. `weight` is a relative (`> 0`) share. */
|
|
export interface WeightedChild {
|
|
node: LayoutNode;
|
|
weight: number;
|
|
}
|
|
|
|
/** A weighted n-ary split (rows or columns). */
|
|
export interface SplitContainer {
|
|
id: string;
|
|
direction: Direction;
|
|
children: WeightedChild[];
|
|
}
|
|
|
|
/** A spreadsheet grid cell placement with spans. */
|
|
export interface GridCell {
|
|
node: LayoutNode;
|
|
row: number;
|
|
col: number;
|
|
rowSpan: number;
|
|
colSpan: number;
|
|
}
|
|
|
|
/** A spreadsheet-style grid with per-row/col weights and span-based merging. */
|
|
export interface GridContainer {
|
|
id: string;
|
|
colWeights: number[];
|
|
rowWeights: number[];
|
|
cells: GridCell[];
|
|
}
|
|
|
|
/**
|
|
* A node in the layout tree. Tagged on `type` with the payload under `node`,
|
|
* matching the backend `#[serde(tag = "type", content = "node")]`.
|
|
*/
|
|
export type LayoutNode =
|
|
| { type: "leaf"; node: LeafCell }
|
|
| { type: "split"; node: SplitContainer }
|
|
| { type: "grid"; node: GridContainer };
|
|
|
|
/** The root of a tab's terminal layout. */
|
|
export interface LayoutTree {
|
|
root: LayoutNode;
|
|
}
|
|
|
|
/**
|
|
* A layout mutation (mirror of the backend `LayoutOperationDto`, tagged on
|
|
* `type`). Node/session ids are UUID strings.
|
|
*/
|
|
export type LayoutOperation =
|
|
| {
|
|
type: "split";
|
|
target: string;
|
|
direction: Direction;
|
|
newLeaf: string;
|
|
container: string;
|
|
}
|
|
| { type: "merge"; container: string; keepIndex: number }
|
|
| { type: "resize"; container: string; weights: number[] }
|
|
| { type: "move"; from: string; to: string }
|
|
| { type: "setSession"; target: string; session?: string | null }
|
|
| { type: "setCellAgent"; target: string; agent: string | null }
|
|
| { type: "setCellConversation"; target: string; conversationId: string | null }
|
|
| { type: "setAgentRunning"; target: string; running: boolean };
|
|
|
|
/** The kind of a named layout. */
|
|
export type LayoutKind = "terminal" | "gitGraph";
|
|
|
|
/** Named layout entry returned by `listLayouts`. */
|
|
export interface LayoutInfo {
|
|
id: string;
|
|
name: string;
|
|
kind: LayoutKind;
|
|
}
|
|
|
|
/**
|
|
* A commit node in the full git graph (DAG). `refs` carries short branch/tag
|
|
* names (e.g. `"main"`, `"tag: v1.0"`). `timestamp` is seconds since Unix epoch.
|
|
*/
|
|
export interface GraphCommit {
|
|
hash: string;
|
|
summary: string;
|
|
parents: string[];
|
|
refs: string[];
|
|
author: string;
|
|
timestamp: number;
|
|
}
|
|
|
|
/** Response of `listLayouts`. */
|
|
export interface LayoutList {
|
|
layouts: LayoutInfo[];
|
|
activeId: string;
|
|
}
|
|
|
|
/** Unsubscribe handle returned by event subscriptions. */
|
|
export type Unsubscribe = () => void;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// AI profiles & first-run (L5) — mirror of the domain `AgentProfile` /
|
|
// `ContextInjection` (CONTEXT §9, ARCHITECTURE §3).
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Context-injection strategy (tagged on `strategy`, mirror of the backend
|
|
* `ContextInjection`):
|
|
* - `conventionFile`: write the `.md` to a conventional file (e.g. `CLAUDE.md`),
|
|
* - `flag`: pass the context path through a CLI flag,
|
|
* - `stdin`: pipe the content on stdin,
|
|
* - `env`: pass the context via an environment variable.
|
|
*/
|
|
export type ContextInjection =
|
|
| { strategy: "conventionFile"; target: string }
|
|
| { strategy: "flag"; flag: string }
|
|
| { strategy: "stdin" }
|
|
| { strategy: "env"; var: string };
|
|
|
|
/** The four injection strategy discriminants. */
|
|
export type InjectionStrategy = ContextInjection["strategy"];
|
|
|
|
/**
|
|
* A declarative AI-CLI profile (mirror of the backend `AgentProfile`). `id` is a
|
|
* UUID string; `detect` is the optional detection command line.
|
|
*/
|
|
export interface AgentProfile {
|
|
id: string;
|
|
name: string;
|
|
command: string;
|
|
args: string[];
|
|
contextInjection: ContextInjection;
|
|
detect: string | null;
|
|
cwdTemplate: string;
|
|
/** Optional CLI flags for agent-session continuity: `assignFlag` to bind a
|
|
* conversation id at launch, `resumeFlag` to resume an existing conversation. */
|
|
session?: { assignFlag?: string; resumeFlag: string };
|
|
}
|
|
|
|
/** Availability of a candidate profile after detection (mirror of the DTO). */
|
|
export interface ProfileAvailability {
|
|
profile: AgentProfile;
|
|
available: boolean;
|
|
}
|
|
|
|
/** First-run state (mirror of `FirstRunStateDto`). */
|
|
export interface FirstRunState {
|
|
isFirstRun: boolean;
|
|
referenceProfiles: AgentProfile[];
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Agents (L6) — mirror of the domain `Agent` / `AgentOrigin` (ARCHITECTURE §6).
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Origin of an agent (tagged on `type`, mirror of the backend `AgentOrigin`):
|
|
* - `scratch`: created from scratch, no template link,
|
|
* - `fromTemplate`: derived from a template, tracking the last synced version.
|
|
*/
|
|
export type AgentOrigin =
|
|
| { type: "scratch" }
|
|
| { type: "fromTemplate"; templateId: string; syncedTemplateVersion: number };
|
|
|
|
/**
|
|
* A project-scoped agent (mirror of the backend `Agent` DTO, camelCase wire
|
|
* format). `contextPath` is the relative path of the agent's `.md` within
|
|
* `.ideai/` (e.g. `agents/foo.md`).
|
|
*/
|
|
export interface Agent {
|
|
id: string;
|
|
name: string;
|
|
contextPath: string;
|
|
profileId: string;
|
|
origin: AgentOrigin;
|
|
synchronized: boolean;
|
|
/** Skills assigned to this agent (injected into its convention file). */
|
|
skills: SkillRef[];
|
|
}
|
|
|
|
/**
|
|
* A terminal/PTY session as returned by the backend (mirror of
|
|
* `TerminalSessionDto`, camelCase wire format). Surfaced by `changeAgentProfile`
|
|
* as the freshly relaunched session when a live agent was hot-swapped.
|
|
*/
|
|
export interface TerminalSession {
|
|
/** Stable session id (UUID) — used for write/resize/close + the output channel. */
|
|
sessionId: string;
|
|
/** Working directory the shell runs in. */
|
|
cwd: string;
|
|
/** Current rows. */
|
|
rows: number;
|
|
/** Current cols. */
|
|
cols: number;
|
|
/**
|
|
* Conversation id assigned by this (re)launch, when the profile supports
|
|
* session assignment and the hosting cell had none yet; absent otherwise.
|
|
*/
|
|
assignedConversationId?: string;
|
|
}
|
|
|
|
/**
|
|
* An agent that can be resumed when its project is (re)opened (mirror of the
|
|
* backend `ResumableAgentDto`, camelCase wire format; ARCHITECTURE §15.2). It is
|
|
* a read-only inventory entry computed at open time — never a spawn:
|
|
* - `nodeId` is the layout leaf hosting the agent (where to relaunch),
|
|
* - `conversationId` is the persisted CLI conversation id; absent ⇒ relaunch fresh,
|
|
* - `wasRunning` is `agentWasRunning` frozen at close time (drives the status label),
|
|
* - `resumeSupported` reflects whether the agent's profile exposes a usable
|
|
* session strategy; when `false`, "Reprendre" relaunches fresh ("relance à neuf").
|
|
*/
|
|
export interface ResumableAgent {
|
|
agentId: string;
|
|
name: string;
|
|
nodeId: string;
|
|
conversationId?: string;
|
|
wasRunning: boolean;
|
|
resumeSupported: boolean;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Skills (L12) — mirror of the domain `Skill` / `SkillRef`.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Where a skill lives (selects its backing store): `global` skills are reusable
|
|
* across projects; `project` skills are specific to one project's `.ideai/`.
|
|
*/
|
|
export type SkillScope = "global" | "project";
|
|
|
|
/**
|
|
* A reusable, model-agnostic workflow assignable to agents (mirror of the
|
|
* backend `Skill` DTO, camelCase wire format).
|
|
*/
|
|
export interface Skill {
|
|
id: string;
|
|
name: string;
|
|
contentMd: string;
|
|
scope: SkillScope;
|
|
}
|
|
|
|
/** A reference from an agent to one assigned skill (mirror of `SkillRef`). */
|
|
export interface SkillRef {
|
|
skillId: string;
|
|
scope: SkillScope;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Memory (L14) — mirror of the backend `MemoryDto` / `MemoryIndexEntryDto`.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* The category of a memory note (selects how it is recalled/injected). Mirrors
|
|
* the backend `type` field; identity of a note is its **slug** (kebab-case).
|
|
*/
|
|
export type MemoryType = "user" | "feedback" | "project" | "reference";
|
|
|
|
/**
|
|
* A memory note (mirror of the backend `Memory` DTO, camelCase wire format).
|
|
* `name` doubles as the human title and the source of the slug identity.
|
|
*/
|
|
export interface Memory {
|
|
name: string;
|
|
description: string;
|
|
type: MemoryType;
|
|
content: string;
|
|
}
|
|
|
|
/**
|
|
* One entry of the memory index (mirror of the backend `MemoryIndexEntry`):
|
|
* a lightweight, recall-oriented projection of a note.
|
|
*/
|
|
export interface MemoryIndexEntry {
|
|
slug: string;
|
|
title: string;
|
|
hook: string;
|
|
type: MemoryType;
|
|
}
|
|
|
|
/** A resolved `[[wikilink]]` target — the slug of another note. */
|
|
export type MemoryLink = string;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Embedder (L14 / lot C2) — mirror of the backend `EmbedderProfileDto` and
|
|
// `EmbedderEnginesDto`. Drives the memory/embedder settings panel. Identity of
|
|
// a profile is its `id`; changing the active embedder takes effect at the next
|
|
// app start (the UI says so explicitly).
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Embedding strategy of an embedder profile (mirror of the backend `strategy`).
|
|
* `none` ⇒ no vector tier (naïve recall); the other strategies select where the
|
|
* embeddings come from.
|
|
*/
|
|
export type EmbedderStrategy = "localOnnx" | "localServer" | "api" | "none";
|
|
|
|
/**
|
|
* A declarative embedder profile (mirror of the backend `EmbedderProfile` DTO,
|
|
* camelCase wire format). Transparent by design: secrets are never stored here —
|
|
* `apiKeyEnv` is the *name* of an environment variable, never the key itself.
|
|
*/
|
|
export interface EmbedderProfile {
|
|
id: string;
|
|
name: string;
|
|
strategy: EmbedderStrategy;
|
|
/** Model id/name (ONNX model, server/api model). Omitted for `none`. */
|
|
model?: string;
|
|
/** Server/API endpoint URL. Omitted for `localOnnx` / `none`. */
|
|
endpoint?: string;
|
|
/** Name of the env var holding the API key (api strategy). Never the key. */
|
|
apiKeyEnv?: string;
|
|
/** Embedding vector dimension. */
|
|
dimension: number;
|
|
}
|
|
|
|
/**
|
|
* A recommended local ONNX engine (mirror of the backend `recommendedOnnx`
|
|
* entry). `e5-small` is the curated default (`recommended: true`).
|
|
*/
|
|
export interface RecommendedOnnxEngine {
|
|
id: string;
|
|
displayName: string;
|
|
dimension: number;
|
|
approxSizeMb: number;
|
|
recommended: boolean;
|
|
}
|
|
|
|
/**
|
|
* Capabilities/availability snapshot of the embedder engines on this build
|
|
* (mirror of the backend `describe_embedder_engines`). The `vector*Enabled`
|
|
* flags reflect Cargo feature flags compiled into the build: a strategy whose
|
|
* flag is `false` is shown disabled ("not available in this build").
|
|
*/
|
|
export interface EmbedderEngines {
|
|
recommendedOnnx: RecommendedOnnxEngine[];
|
|
ollamaDetected: boolean;
|
|
onnxCachedModels: string[];
|
|
vectorHttpEnabled: boolean;
|
|
vectorOnnxEnabled: boolean;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Templates (L7) — mirror of the domain `Template` / `AgentDrift`.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* A reusable agent template (mirror of the backend `Template` DTO).
|
|
* `version` is incremented on each `updateTemplate` call.
|
|
*/
|
|
export interface Template {
|
|
id: string;
|
|
name: string;
|
|
contentMd: string;
|
|
version: number;
|
|
defaultProfileId: string;
|
|
}
|
|
|
|
/**
|
|
* Drift between a synchronized agent's last-synced template version and the
|
|
* template's current version (mirror of `AgentDrift` backend DTO).
|
|
*/
|
|
export interface AgentDrift {
|
|
agentId: string;
|
|
from: number;
|
|
to: number;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Git (L8) — UI-domain types for the git feature.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** A file in the working tree with its staging state. */
|
|
export interface GitFileStatus {
|
|
path: string;
|
|
staged: boolean;
|
|
}
|
|
|
|
/** A git commit summary (short representation). */
|
|
export interface GitCommit {
|
|
hash: string;
|
|
summary: string;
|
|
}
|
|
|
|
/** The list of branches and the currently checked-out branch. */
|
|
export interface GitBranches {
|
|
branches: string[];
|
|
current: string | null;
|
|
}
|