feat(electrobun): wire PTY daemon into terminal tabs via Electrobun RPC

- Bun process connects to agor-ptyd via PtyClient (5 retries, exponential backoff)
- RPC bridge: 5 request handlers (create/write/resize/unsubscribe/close)
- Daemon output forwarded to WebView as pty.output messages (base64 passthrough)
- Terminal.svelte: real PTY sessions via RPC instead of echo mode
- Shared RPC schema at src/shared/pty-rpc-schema.ts
- Fixed pty-client.ts protocol: base64 string for data (was number array)
- TerminalTabs passes sessionId to Terminal component
This commit is contained in:
Hibryda 2026-03-20 03:20:13 +01:00
parent f3456bd09d
commit 4676fc2c94
6 changed files with 343 additions and 86 deletions

View file

@ -0,0 +1,62 @@
/**
* Shared RPC schema for PTY bridge between Bun process and WebView.
*
* Bun holds the Unix socket connection to agor-ptyd; the WebView calls
* into Bun via requests, and Bun pushes output/close events via messages.
*/
// ── Requests (WebView → Bun, expects a response) ─────────────────────────────
export type PtyRPCRequests = {
/** Create a PTY session and subscribe to its output. */
"pty.create": {
params: {
sessionId: string;
cols: number;
rows: number;
/** Working directory for the shell process. */
cwd?: string;
};
response: { ok: boolean; error?: string };
};
/** Write raw input bytes (base64-encoded) to a PTY session. */
"pty.write": {
params: {
sessionId: string;
/** UTF-8 text typed by the user (xterm onData delivers this). */
data: string;
};
response: { ok: boolean };
};
/** Notify the daemon that the terminal dimensions changed. */
"pty.resize": {
params: { sessionId: string; cols: number; rows: number };
response: { ok: boolean };
};
/** Unsubscribe from a session's output (session stays alive). */
"pty.unsubscribe": {
params: { sessionId: string };
response: { ok: boolean };
};
/** Kill a PTY session. */
"pty.close": {
params: { sessionId: string };
response: { ok: boolean };
};
};
// ── Messages (Bun → WebView, fire-and-forget) ────────────────────────────────
export type PtyRPCMessages = {
/** PTY output chunk. data is base64-encoded raw bytes from the daemon. */
"pty.output": { sessionId: string; data: string };
/** PTY session exited. */
"pty.closed": { sessionId: string; exitCode: number | null };
};
// ── Combined schema ───────────────────────────────────────────────────────────
export type PtyRPCSchema = {
requests: PtyRPCRequests;
messages: PtyRPCMessages;
};