Files
IdeA/frontend/src/adapters/input.ts
Blomios 018eb1a25e fix(input): fiabilise la livraison de délégation et journalise le submit
Durcit le portail d'écriture de délégation et son acheminement bout-en-bout
(commande Tauri → orchestrateur → file d'entrée infrastructure → portail
frontend), avec une journalisation du submit pour diagnostiquer les cas où la
délégation n'était pas remise. Couvre le portail d'écriture côté front
(useWritePortal) avec ses tests.

QA : checks application/front/infrastructure/app-tauri verts. Les tests loopback
socket Unix réels ne sont pas exécutables en sandbox (UnixListener::bind →
PermissionDenied) ; alternatives avec skips vertes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 10:57:20 +02:00

66 lines
2.3 KiB
TypeScript

/**
* Tauri adapter for {@link InputGateway} (ARCHITECTURE §20.3).
*
* `interrupt` → `interrupt_agent` (preempt). `delegationDelivered` →
* `delegation_delivered` (the native write-portal's ack that a delegation's
* text was effectively written into the PTY). The former `submit` →
* `submit_agent_input` path is gone: the agent cell is a native terminal, so
* human keystrokes reach the PTY directly (no mediated-input strip).
*
* 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 { invoke } from "@tauri-apps/api/core";
import type { InputGateway } from "@/ports";
export class TauriInputGateway implements InputGateway {
async interrupt(projectId: string, agentId: string): Promise<void> {
await invoke("interrupt_agent", {
request: { projectId, agentId },
});
}
async delegationDelivered(
projectId: string,
agentId: string,
ticket: string,
): Promise<void> {
console.info("[input-gateway] delegationDelivered:start", {
projectId,
agentId,
ticket,
});
await invoke("delegation_delivered", {
request: { projectId, agentId, ticket },
});
console.info("[input-gateway] delegationDelivered:ok", {
projectId,
agentId,
ticket,
});
}
async setFrontAttached(agentId: string, attached: boolean): Promise<void> {
console.info("[input-gateway] setFrontAttached:start", { agentId, attached });
await invoke("set_front_attached", {
request: { agentId, attached },
});
console.info("[input-gateway] setFrontAttached:ok", { agentId, attached });
}
async cancelResume(agentId: string): Promise<boolean> {
// `cancel_resume` takes a bare `agent_id` (camelCase `agentId`), not a
// `request` envelope, and returns whether a pending resume was disarmed.
return invoke<boolean>("cancel_resume", { agentId });
}
async setResumeAt(agentId: string, resetsAtMs: number): Promise<void> {
// `set_resume_at` takes bare `agent_id` + `resets_at_ms` (camelCase), like
// `cancel_resume`; arms the cancellable resume at the chosen instant.
await invoke("set_resume_at", { agentId, resetsAtMs });
}
}