/** * Frontend mirror of the Rust typed RPC contract in * `server/src/crdt_sync/rpc_contract.rs`. * * Every typed write method declared on the backend has matching TypeScript * params/result types here. The `CONTRACT_FIXTURES` table also exposes the * same canonical example payloads as the Rust `CONTRACT_METHODS` slice — the * `rpcContract.test.ts` test compares them against the committed * `rpcContract.snapshot.json` that the Rust test regenerates. If the Rust * shapes drift from the TS shapes, the snapshot drifts and one side fails in * CI — surfacing the mismatch as a compile / test error instead of a runtime * one. * * When adding a method on the backend: * 1. Add the params + result type here. * 2. Add the entry to `CONTRACT_FIXTURES` with a canonical example. * 3. Re-run `UPDATE_RPC_CONTRACT_SNAPSHOT=1 cargo test` to refresh * `rpcContract.snapshot.json`. */ // ── Params types ──────────────────────────────────────────────────────────── /** Params for `model.set_preference`. */ export interface SetModelPreferenceParams { model: string; } /** Params for `anthropic.set_api_key`. */ export interface SetAnthropicApiKeyParams { api_key: string; } /** Params for `settings.put_editor`. */ export interface PutEditorParams { editor_command: string | null; } /** Params for `settings.open_file`. */ export interface OpenFileParams { path: string; line: number | null; } /** Params for `project.open`. */ export interface OpenProjectParams { path: string; } /** Params for `project.forget`. */ export interface ForgetProjectParams { path: string; } /** Payload for `bot_config.save` (and result of `bot_config.get`). */ export interface BotConfigPayload { transport: string | null; enabled: boolean | null; homeserver: string | null; username: string | null; password: string | null; room_ids: string[] | null; slack_bot_token: string | null; slack_signing_secret: string | null; slack_channel_ids: string[] | null; } /** Payload for `settings.put_project` (also returned by `settings.get_project`). */ export interface ProjectSettingsPayload { default_qa: string; default_coder_model: string | null; max_coders: number | null; max_retries: number; base_branch: string | null; rate_limit_notifications: boolean; timezone: string | null; rendezvous: string | null; watcher_sweep_interval_secs: number; watcher_done_retention_secs: number; } // ── Result types ──────────────────────────────────────────────────────────── /** Result envelope for write methods that simply succeed or fail. */ export interface OkResult { ok: boolean; } /** Result for `settings.put_editor`. */ export interface EditorSettingsResult { editor_command: string | null; } /** Result for `project.open`. */ export interface OpenProjectResult { path: string; } // ── Method → params/result mapping ────────────────────────────────────────── /** * Compile-time mapping from typed RPC method name to its params + result * shapes. Used by `callTypedRpc` to enforce that callers pass the right * params and receive the right return type for a method. */ export interface TypedRpcMethods { "model.set_preference": { params: SetModelPreferenceParams; result: OkResult; }; "anthropic.set_api_key": { params: SetAnthropicApiKeyParams; result: OkResult; }; "settings.put_editor": { params: PutEditorParams; result: EditorSettingsResult; }; "settings.open_file": { params: OpenFileParams; result: OkResult; }; "settings.put_project": { params: ProjectSettingsPayload; result: ProjectSettingsPayload; }; "project.open": { params: OpenProjectParams; result: OpenProjectResult; }; "project.close": { params: Record; result: OkResult; }; "project.forget": { params: ForgetProjectParams; result: OkResult; }; "bot_config.save": { params: BotConfigPayload; result: BotConfigPayload; }; "chat.cancel": { params: Record; result: OkResult; }; } /** Union of all typed RPC method names declared in the contract. */ export type TypedRpcMethodName = keyof TypedRpcMethods; // ── Canonical fixtures (mirror of Rust `CONTRACT_METHODS`) ────────────────── /** * One canonical example payload per typed RPC method. The shape *must* * match the corresponding Rust `CONTRACT_METHODS` entry. Drift between this * table and `rpcContract.snapshot.json` (regenerated by the Rust side) fails * the `rpcContract.test.ts` snapshot check. */ export const CONTRACT_FIXTURES: { [K in TypedRpcMethodName]: { params: TypedRpcMethods[K]["params"]; result: TypedRpcMethods[K]["result"]; }; } = { "model.set_preference": { params: { model: "claude-sonnet-4-6" }, result: { ok: true }, }, "anthropic.set_api_key": { params: { api_key: "sk-ant-..." }, result: { ok: true }, }, "settings.put_editor": { params: { editor_command: "zed" }, result: { editor_command: "zed" }, }, "settings.open_file": { params: { path: "src/main.rs", line: 42 }, result: { ok: true }, }, "settings.put_project": { params: { default_qa: "server", default_coder_model: null, max_coders: null, max_retries: 2, base_branch: null, rate_limit_notifications: true, timezone: null, rendezvous: null, watcher_sweep_interval_secs: 60, watcher_done_retention_secs: 86_400, }, result: { default_qa: "server", default_coder_model: null, max_coders: null, max_retries: 2, base_branch: null, rate_limit_notifications: true, timezone: null, rendezvous: null, watcher_sweep_interval_secs: 60, watcher_done_retention_secs: 86_400, }, }, "project.open": { params: { path: "/path/to/project" }, result: { path: "/path/to/project" }, }, "project.close": { params: {}, result: { ok: true }, }, "project.forget": { params: { path: "/path/to/project" }, result: { ok: true }, }, "bot_config.save": { params: { transport: "matrix", enabled: true, homeserver: "https://matrix.example", username: "bot", password: "secret", room_ids: ["!room:example"], slack_bot_token: null, slack_signing_secret: null, slack_channel_ids: null, }, result: { transport: "matrix", enabled: true, homeserver: "https://matrix.example", username: "bot", password: "secret", room_ids: ["!room:example"], slack_bot_token: null, slack_signing_secret: null, slack_channel_ids: null, }, }, "chat.cancel": { params: {}, result: { ok: true }, }, };