Files
desktop/sidecar/protocol.ts
T
pastilhasandClaude Opus 5 b91d4df21d desktop, extracted from the platform
x11vnc against display :0 — the session the owner is actually logged into, not a second one Officer
installs. sidecar/, api/, web/ and the host setup script, moved out of src/ whole.

Dormant when it moved: the websocket was commented out in server.tsx and the router in hono.ts since
2026-08-13, and no officer-vnc process was running on any machine. Nothing regressed and nothing was
restored — this took switched-off code out of the platform.

The point of the move is what the platform stopped knowing. Its sidecar/protocol.ts carried a VNC
section — vnc:start, vnc:ensure-password, vnc:stop, four reply variants, VncStartParams,
VncSessionInfo — and sidecar-registry.ts carried startVnc, ensureVncPassword, stopVnc and
isVncConnected. That is the platform speaking a plugin's vocabulary, which CLAUDE.md names as a rule
and this was the clearest breach of. All of it is in sidecar/protocol.ts here now.

The permission made a round trip worth recording. It was kind: 'execution' — "runs as the server owner
and cannot be shared" — and a plugin permission has no kind, deliberately, because a permission nobody
can delegate is a contradiction. So the property is expressed as ownerOnly: ['/'] instead: every path
under this plugin refused to anyone but the owner. Same answer, reached from the paths rather than
from a kind, and the first real use of a mechanism that landed the same day. The property is real —
there is one physical screen and it is the owner's.

Not finished, and BLOCKERS.md says so rather than the commit implying otherwise: the websocket is
dormant because a plugin cannot claim a WebSocket provider, host setup needs a reboot and no manifest
can express that, and there is no artwork.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 00:41:24 +00:00

45 lines
1.8 KiB
TypeScript

// The desktop sidecar's own vocabulary.
//
// These types lived in the PLATFORM's `sidecar/protocol.ts` until the extraction, alongside `vnc:start`
// and `vnc:password` variants in its command and event unions. That is the thing CLAUDE.md warns about
// most plainly — "the platform must not know what your plugin is about. Not just its code, its
// VOCABULARY" — and it is why the platform grew a generic `sendSidecarCommand` instead: it knows a
// command has a type and an id, and nothing else.
export type VncStartParams = {
email: string;
username: string;
resolution?: string;
};
export type VncSessionInfo = {
email: string;
display: number;
port: number;
pid: number;
alive: boolean;
};
/** What this plugin sends to its sidecar. `id` is what the reply is matched on. */
export type DesktopCommand =
// Every sidecar answers this; the connector uses it as a liveness check.
| { type: 'ping'; id: string }
| { type: 'vnc:start'; id: string; params: VncStartParams }
// Provision the password WITHOUT starting a server — the UI needs it before it can open the socket
// that would start one, so asking `vnc:start` here would be circular.
| { type: 'vnc:ensure-password'; id: string; email: string }
| { type: 'vnc:stop'; id: string; email: string };
/** What the sidecar sends back. */
export type DesktopEvent =
| { type: 'pong'; id: string }
// The generic failure, for a command this sidecar does not recognise.
| { type: 'error'; id: string; error: string }
| { type: 'vnc:started'; id: string; port: number; display: number }
| { type: 'vnc:password'; id: string; password: string }
| { type: 'vnc:stopped'; id: string }
| { type: 'vnc:error'; id: string; error: string };
/** The `handles` key this sidecar registers under, and the one the api addresses it by. */
export const DESKTOP_SIDECAR_KIND = 'vnc';