feat: add main features
Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
108
frontend/src/adapters/agent.ts
Normal file
108
frontend/src/adapters/agent.ts
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Tauri adapter for {@link AgentGateway} (L6).
|
||||
*
|
||||
* NOTE: The Tauri commands wired here (`list_agents`, `create_agent`, …) are
|
||||
* defined in the backend `app-tauri` crate and will be registered in a
|
||||
* subsequent lot. This adapter is complete on the frontend side; the mock
|
||||
* gateway covers tests and offline dev today. The real mode will work
|
||||
* transparently once the commands are registered.
|
||||
*
|
||||
* Commands use snake_case (Tauri convention); payload keys are camelCase
|
||||
* (matching the backend DTO `#[serde(rename_all = "camelCase")]`), consistent
|
||||
* with the other adapters in this directory.
|
||||
*/
|
||||
|
||||
import { Channel, invoke } from "@tauri-apps/api/core";
|
||||
|
||||
import type { Agent } from "@/domain";
|
||||
import type {
|
||||
AgentGateway,
|
||||
CreateAgentInput,
|
||||
OpenTerminalOptions,
|
||||
TerminalHandle,
|
||||
} from "@/ports";
|
||||
|
||||
/** Wire shape returned by the `launch_agent` command (mirrors `open_terminal`). */
|
||||
interface LaunchAgentResponse {
|
||||
sessionId: string;
|
||||
cwd: string;
|
||||
rows: number;
|
||||
cols: number;
|
||||
}
|
||||
|
||||
export class TauriAgentGateway implements AgentGateway {
|
||||
listAgents(projectId: string): Promise<Agent[]> {
|
||||
return invoke<Agent[]>("list_agents", { projectId });
|
||||
}
|
||||
|
||||
createAgent(projectId: string, input: CreateAgentInput): Promise<Agent> {
|
||||
// The `create_agent` command takes a single `request` DTO; `projectId` must
|
||||
// live *inside* it (camelCase), not at the top level.
|
||||
return invoke<Agent>("create_agent", {
|
||||
request: {
|
||||
projectId,
|
||||
name: input.name,
|
||||
profileId: input.profileId,
|
||||
initialContent: input.initialContent ?? null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
readContext(projectId: string, agentId: string): Promise<string> {
|
||||
return invoke<string>("read_agent_context", { projectId, agentId });
|
||||
}
|
||||
|
||||
async updateContext(
|
||||
projectId: string,
|
||||
agentId: string,
|
||||
content: string,
|
||||
): Promise<void> {
|
||||
// `update_agent_context` takes a single `request` DTO.
|
||||
await invoke("update_agent_context", {
|
||||
request: { projectId, agentId, content },
|
||||
});
|
||||
}
|
||||
|
||||
async deleteAgent(projectId: string, agentId: string): Promise<void> {
|
||||
await invoke("delete_agent", { projectId, agentId });
|
||||
}
|
||||
|
||||
async launchAgent(
|
||||
projectId: string,
|
||||
agentId: string,
|
||||
options: OpenTerminalOptions,
|
||||
onData: (bytes: Uint8Array) => void,
|
||||
): Promise<TerminalHandle> {
|
||||
// Per-session output channel. The backend serialises chunks as byte arrays.
|
||||
const channel = new Channel<number[]>();
|
||||
channel.onmessage = (chunk) => onData(Uint8Array.from(chunk));
|
||||
|
||||
const res = await invoke<LaunchAgentResponse>("launch_agent", {
|
||||
request: {
|
||||
projectId,
|
||||
agentId,
|
||||
rows: options.rows,
|
||||
cols: options.cols,
|
||||
},
|
||||
onOutput: channel,
|
||||
});
|
||||
|
||||
const sessionId = res.sessionId;
|
||||
return {
|
||||
sessionId,
|
||||
async write(data: Uint8Array): Promise<void> {
|
||||
await invoke("write_terminal", {
|
||||
request: { sessionId, data: Array.from(data) },
|
||||
});
|
||||
},
|
||||
async resize(rows: number, cols: number): Promise<void> {
|
||||
await invoke("resize_terminal", {
|
||||
request: { sessionId, rows, cols },
|
||||
});
|
||||
},
|
||||
async close(): Promise<void> {
|
||||
await invoke("close_terminal", { sessionId });
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user