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>
This commit is contained in:
2026-06-20 10:57:20 +02:00
parent befff76de8
commit 018eb1a25e
8 changed files with 352 additions and 23 deletions

View File

@ -28,15 +28,27 @@ export class TauriInputGateway implements InputGateway {
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> {

View File

@ -64,11 +64,13 @@ export function makeTerminalHandle(
return {
sessionId,
write(data: Uint8Array): Promise<void> {
const run = chain.then(() =>
invoke<void>("write_terminal", {
const run = chain.then(async () => {
logTerminalWrite("start", sessionId, data);
await invoke<void>("write_terminal", {
request: { sessionId, data: Array.from(data) },
}),
);
});
logTerminalWrite("ok", sessionId, data);
});
// Keep the chain alive even if this write rejects: the next write must
// still run. Swallow the error on the *chain* copy only — `run` keeps the
// rejection so the caller can observe it.
@ -91,6 +93,35 @@ export function makeTerminalHandle(
};
}
function logTerminalWrite(phase: "start" | "ok", sessionId: string, data: Uint8Array): void {
if (data.length === 1 && data[0] >= 0x20 && data[0] !== 0x7f) return;
console.info("[terminal-write]", phase, {
sessionId,
bytes: data.length,
control: describeBytes(data),
});
}
function describeBytes(data: Uint8Array): string {
if (data.length === 0) return "<empty>";
if (data.length > 16) return "<bulk>";
return Array.from(data)
.map((byte) => {
switch (byte) {
case 0x0d:
return "\\r";
case 0x0a:
return "\\n";
case 0x7f:
return "\\x7f";
default:
if (byte < 0x20) return `\\x${byte.toString(16).padStart(2, "0")}`;
return String.fromCharCode(byte);
}
})
.join("");
}
export class TauriTerminalGateway implements TerminalGateway {
async openTerminal(
options: OpenTerminalOptions,