UNPKG

consortium

Version:

Remote control and session sharing CLI for AI coding agents

1,414 lines (1,404 loc) 61.7 kB
import { z } from 'zod'; import { EventEmitter } from 'node:events'; import { Socket } from 'socket.io-client'; import { ExpoPushMessage } from 'expo-server-sdk'; /** * Simplified schema that only validates fields actually used in the codebase * while preserving all other fields through passthrough() */ declare const UsageSchema: z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>; declare const RawJSONLinesSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{ type: z.ZodLiteral<"user">; isSidechain: z.ZodOptional<z.ZodBoolean>; isMeta: z.ZodOptional<z.ZodBoolean>; uuid: z.ZodString; message: z.ZodObject<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ type: z.ZodLiteral<"user">; isSidechain: z.ZodOptional<z.ZodBoolean>; isMeta: z.ZodOptional<z.ZodBoolean>; uuid: z.ZodString; message: z.ZodObject<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ type: z.ZodLiteral<"user">; isSidechain: z.ZodOptional<z.ZodBoolean>; isMeta: z.ZodOptional<z.ZodBoolean>; uuid: z.ZodString; message: z.ZodObject<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ content: z.ZodUnion<[z.ZodString, z.ZodAny]>; }, z.ZodTypeAny, "passthrough">>; }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{ uuid: z.ZodString; type: z.ZodLiteral<"assistant">; message: z.ZodOptional<z.ZodObject<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ uuid: z.ZodString; type: z.ZodLiteral<"assistant">; message: z.ZodOptional<z.ZodObject<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ uuid: z.ZodString; type: z.ZodLiteral<"assistant">; message: z.ZodOptional<z.ZodObject<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional<z.ZodObject<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>; cache_read_input_tokens: z.ZodOptional<z.ZodNumber>; output_tokens: z.ZodNumber; service_tier: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; model: z.ZodOptional<z.ZodString>; }, z.ZodTypeAny, "passthrough">>>; }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{ type: z.ZodLiteral<"summary">; summary: z.ZodString; leafUuid: z.ZodString; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ type: z.ZodLiteral<"summary">; summary: z.ZodString; leafUuid: z.ZodString; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ type: z.ZodLiteral<"summary">; summary: z.ZodString; leafUuid: z.ZodString; }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{ type: z.ZodLiteral<"system">; uuid: z.ZodString; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ type: z.ZodLiteral<"system">; uuid: z.ZodString; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ type: z.ZodLiteral<"system">; uuid: z.ZodString; }, z.ZodTypeAny, "passthrough">>]>; type RawJSONLines = z.infer<typeof RawJSONLinesSchema>; /** * Permission mode type - includes both Claude and Codex modes * Must match MessageMetaSchema.permissionMode enum values * * Claude modes: default, acceptEdits, bypassPermissions, plan * Codex modes: read-only, safe-yolo, yolo * * When calling Claude SDK, Codex modes are mapped at the SDK boundary: * - yolo → bypassPermissions * - safe-yolo → default * - read-only → default */ type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'read-only' | 'safe-yolo' | 'yolo'; /** * Usage data type from Claude */ type Usage = z.infer<typeof UsageSchema>; /** * Update event from server */ declare const UpdateSchema: z.ZodObject<{ id: z.ZodString; seq: z.ZodNumber; body: z.ZodUnion<[z.ZodObject<{ message: z.ZodObject<{ id: z.ZodString; seq: z.ZodNumber; content: z.ZodObject<{ c: z.ZodString; t: z.ZodLiteral<"encrypted">; }, "strip", z.ZodTypeAny, { c: string; t: "encrypted"; }, { c: string; t: "encrypted"; }>; }, "strip", z.ZodTypeAny, { content: { c: string; t: "encrypted"; }; id: string; seq: number; }, { content: { c: string; t: "encrypted"; }; id: string; seq: number; }>; sid: z.ZodString; t: z.ZodLiteral<"new-message">; }, "strip", z.ZodTypeAny, { message: { content: { c: string; t: "encrypted"; }; id: string; seq: number; }; t: "new-message"; sid: string; }, { message: { content: { c: string; t: "encrypted"; }; id: string; seq: number; }; t: "new-message"; sid: string; }>, z.ZodObject<{ t: z.ZodLiteral<"update-session">; sid: z.ZodString; metadata: z.ZodOptional<z.ZodNullable<z.ZodObject<{ version: z.ZodNumber; value: z.ZodString; }, "strip", z.ZodTypeAny, { value: string; version: number; }, { value: string; version: number; }>>>; agentState: z.ZodOptional<z.ZodNullable<z.ZodObject<{ version: z.ZodNumber; value: z.ZodString; }, "strip", z.ZodTypeAny, { value: string; version: number; }, { value: string; version: number; }>>>; }, "strip", z.ZodTypeAny, { t: "update-session"; sid: string; metadata?: { value: string; version: number; } | null | undefined; agentState?: { value: string; version: number; } | null | undefined; }, { t: "update-session"; sid: string; metadata?: { value: string; version: number; } | null | undefined; agentState?: { value: string; version: number; } | null | undefined; }>, z.ZodObject<{ t: z.ZodLiteral<"update-machine">; machineId: z.ZodString; metadata: z.ZodOptional<z.ZodNullable<z.ZodObject<{ version: z.ZodNumber; value: z.ZodString; }, "strip", z.ZodTypeAny, { value: string; version: number; }, { value: string; version: number; }>>>; daemonState: z.ZodOptional<z.ZodNullable<z.ZodObject<{ version: z.ZodNumber; value: z.ZodString; }, "strip", z.ZodTypeAny, { value: string; version: number; }, { value: string; version: number; }>>>; }, "strip", z.ZodTypeAny, { t: "update-machine"; machineId: string; metadata?: { value: string; version: number; } | null | undefined; daemonState?: { value: string; version: number; } | null | undefined; }, { t: "update-machine"; machineId: string; metadata?: { value: string; version: number; } | null | undefined; daemonState?: { value: string; version: number; } | null | undefined; }>]>; createdAt: z.ZodNumber; }, "strip", z.ZodTypeAny, { id: string; seq: number; body: { message: { content: { c: string; t: "encrypted"; }; id: string; seq: number; }; t: "new-message"; sid: string; } | { t: "update-session"; sid: string; metadata?: { value: string; version: number; } | null | undefined; agentState?: { value: string; version: number; } | null | undefined; } | { t: "update-machine"; machineId: string; metadata?: { value: string; version: number; } | null | undefined; daemonState?: { value: string; version: number; } | null | undefined; }; createdAt: number; }, { id: string; seq: number; body: { message: { content: { c: string; t: "encrypted"; }; id: string; seq: number; }; t: "new-message"; sid: string; } | { t: "update-session"; sid: string; metadata?: { value: string; version: number; } | null | undefined; agentState?: { value: string; version: number; } | null | undefined; } | { t: "update-machine"; machineId: string; metadata?: { value: string; version: number; } | null | undefined; daemonState?: { value: string; version: number; } | null | undefined; }; createdAt: number; }>; type Update = z.infer<typeof UpdateSchema>; /** * Session information */ type Session = { id: string; /** * Server-side idempotency tag for this session. Two `getOrCreateSession` * calls with the same `tag` return the same row, so callers who want * to resume an existing session (e.g. `consortium code --resume <id>`) * must pass the original tag — not a fresh random one. Surfacing it * here so the TUI wizard can hand it to the spawned agent process. */ tag: string; seq: number; encryptionKey: Uint8Array; encryptionVariant: 'legacy' | 'dataKey'; metadata: Metadata; metadataVersion: number; agentState: AgentState | null; agentStateVersion: number; }; /** * Machine metadata - static information (rarely changes) */ declare const MachineMetadataSchema: z.ZodObject<{ host: z.ZodString; platform: z.ZodString; consortiumCliVersion: z.ZodString; homeDir: z.ZodString; consortiumHomeDir: z.ZodString; consortiumLibDir: z.ZodString; cpuCount: z.ZodOptional<z.ZodNumber>; memoryTotalMb: z.ZodOptional<z.ZodNumber>; openclawInstalled: z.ZodOptional<z.ZodBoolean>; openclawVersion: z.ZodOptional<z.ZodNullable<z.ZodString>>; openclawWorkspaceExists: z.ZodOptional<z.ZodBoolean>; openclawGatewayRunning: z.ZodOptional<z.ZodBoolean>; openclawGatewayPort: z.ZodOptional<z.ZodNumber>; openclawChannels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; openclawAgentCount: z.ZodOptional<z.ZodNumber>; openclawAgents: z.ZodOptional<z.ZodArray<z.ZodObject<{ name: z.ZodString; workspace: z.ZodString; agentDir: z.ZodString; model: z.ZodString; routingRules: z.ZodNumber; isDefault: z.ZodBoolean; }, "strip", z.ZodTypeAny, { model: string; name: string; workspace: string; agentDir: string; routingRules: number; isDefault: boolean; }, { model: string; name: string; workspace: string; agentDir: string; routingRules: number; isDefault: boolean; }>, "many">>; terminalCapabilities: z.ZodOptional<z.ZodObject<{ tmux: z.ZodBoolean; zellij: z.ZodBoolean; }, "strip", z.ZodTypeAny, { tmux: boolean; zellij: boolean; }, { tmux: boolean; zellij: boolean; }>>; }, "strip", z.ZodTypeAny, { host: string; platform: string; consortiumCliVersion: string; homeDir: string; consortiumHomeDir: string; consortiumLibDir: string; cpuCount?: number | undefined; memoryTotalMb?: number | undefined; openclawInstalled?: boolean | undefined; openclawVersion?: string | null | undefined; openclawWorkspaceExists?: boolean | undefined; openclawGatewayRunning?: boolean | undefined; openclawGatewayPort?: number | undefined; openclawChannels?: string[] | undefined; openclawAgentCount?: number | undefined; openclawAgents?: { model: string; name: string; workspace: string; agentDir: string; routingRules: number; isDefault: boolean; }[] | undefined; terminalCapabilities?: { tmux: boolean; zellij: boolean; } | undefined; }, { host: string; platform: string; consortiumCliVersion: string; homeDir: string; consortiumHomeDir: string; consortiumLibDir: string; cpuCount?: number | undefined; memoryTotalMb?: number | undefined; openclawInstalled?: boolean | undefined; openclawVersion?: string | null | undefined; openclawWorkspaceExists?: boolean | undefined; openclawGatewayRunning?: boolean | undefined; openclawGatewayPort?: number | undefined; openclawChannels?: string[] | undefined; openclawAgentCount?: number | undefined; openclawAgents?: { model: string; name: string; workspace: string; agentDir: string; routingRules: number; isDefault: boolean; }[] | undefined; terminalCapabilities?: { tmux: boolean; zellij: boolean; } | undefined; }>; type MachineMetadata = z.infer<typeof MachineMetadataSchema>; /** * Daemon state - dynamic runtime information (frequently updated) */ declare const DaemonStateSchema: z.ZodObject<{ status: z.ZodUnion<[z.ZodEnum<["running", "shutting-down"]>, z.ZodString]>; pid: z.ZodOptional<z.ZodNumber>; httpPort: z.ZodOptional<z.ZodNumber>; startedAt: z.ZodOptional<z.ZodNumber>; shutdownRequestedAt: z.ZodOptional<z.ZodNumber>; shutdownSource: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["mobile-app", "cli", "os-signal", "unknown"]>, z.ZodString]>>; }, "strip", z.ZodTypeAny, { status: string; pid?: number | undefined; httpPort?: number | undefined; startedAt?: number | undefined; shutdownRequestedAt?: number | undefined; shutdownSource?: string | undefined; }, { status: string; pid?: number | undefined; httpPort?: number | undefined; startedAt?: number | undefined; shutdownRequestedAt?: number | undefined; shutdownSource?: string | undefined; }>; type DaemonState = z.infer<typeof DaemonStateSchema>; type Machine = { id: string; encryptionKey: Uint8Array; encryptionVariant: 'legacy' | 'dataKey'; metadata: MachineMetadata; metadataVersion: number; daemonState: DaemonState | null; daemonStateVersion: number; }; declare const UserMessageSchema: z.ZodObject<{ role: z.ZodLiteral<"user">; content: z.ZodObject<{ type: z.ZodLiteral<"text">; text: z.ZodString; attachmentIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; localId: z.ZodOptional<z.ZodString>; driveId: z.ZodOptional<z.ZodString>; driveNodeIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; driveDek: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { type: "text"; text: string; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveNodeIds?: string[] | undefined; driveDek?: string | undefined; }, { type: "text"; text: string; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveNodeIds?: string[] | undefined; driveDek?: string | undefined; }>; localKey: z.ZodOptional<z.ZodString>; meta: z.ZodOptional<z.ZodObject<{ sentFrom: z.ZodOptional<z.ZodString>; permissionMode: z.ZodOptional<z.ZodEnum<["default", "acceptEdits", "bypassPermissions", "plan", "read-only", "safe-yolo", "yolo"]>>; model: z.ZodOptional<z.ZodNullable<z.ZodString>>; fallbackModel: z.ZodOptional<z.ZodNullable<z.ZodString>>; customSystemPrompt: z.ZodOptional<z.ZodNullable<z.ZodString>>; appendSystemPrompt: z.ZodOptional<z.ZodNullable<z.ZodString>>; allowedTools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>; disallowedTools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>; }, "strip", z.ZodTypeAny, { model?: string | null | undefined; sentFrom?: string | undefined; permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "read-only" | "safe-yolo" | "yolo" | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; }, { model?: string | null | undefined; sentFrom?: string | undefined; permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "read-only" | "safe-yolo" | "yolo" | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; }>>; attachmentIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; localId: z.ZodOptional<z.ZodString>; driveId: z.ZodOptional<z.ZodString>; driveDek: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { content: { type: "text"; text: string; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveNodeIds?: string[] | undefined; driveDek?: string | undefined; }; role: "user"; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveDek?: string | undefined; localKey?: string | undefined; meta?: { model?: string | null | undefined; sentFrom?: string | undefined; permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "read-only" | "safe-yolo" | "yolo" | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; } | undefined; }, { content: { type: "text"; text: string; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveNodeIds?: string[] | undefined; driveDek?: string | undefined; }; role: "user"; attachmentIds?: string[] | undefined; localId?: string | undefined; driveId?: string | undefined; driveDek?: string | undefined; localKey?: string | undefined; meta?: { model?: string | null | undefined; sentFrom?: string | undefined; permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "read-only" | "safe-yolo" | "yolo" | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; } | undefined; }>; type UserMessage = z.infer<typeof UserMessageSchema>; type Metadata = { path: string; host: string; version?: string; name?: string; os?: string; summary?: { text: string; updatedAt: number; }; machineId?: string; claudeSessionId?: string; agentSessionId?: string; codexRolloutPath?: string; tools?: string[]; slashCommands?: string[]; homeDir: string; consortiumHomeDir: string; consortiumLibDir: string; consortiumToolsDir: string; startedFromDaemon?: boolean; hostPid?: number; startedBy?: 'daemon' | 'terminal'; lifecycleState?: 'running' | 'archiveRequested' | 'archived' | string; lifecycleStateSince?: number; archivedBy?: string; archiveReason?: string; flavor?: string; firstMessage?: string; /** Resolved model id (cli-set; Pi updates per message_start). */ model?: string; /** Resolved provider id (cli-set alongside `model`). */ provider?: string; }; type AgentState = { controlledByUser?: boolean | null | undefined; requests?: { [id: string]: { tool: string; arguments: any; createdAt: number; }; }; completedRequests?: { [id: string]: { tool: string; arguments: any; createdAt: number; completedAt: number; status: 'canceled' | 'denied' | 'approved'; reason?: string; mode?: PermissionMode; decision?: 'approved' | 'approved_for_session' | 'denied' | 'abort'; allowTools?: string[]; }; }; }; /** * Common RPC types and interfaces for both session and machine clients */ /** * Generic RPC handler function type * @template TRequest - The request data type * @template TResponse - The response data type */ type RpcHandler<TRequest = any, TResponse = any> = (data: TRequest) => TResponse | Promise<TResponse>; /** * RPC request data from server */ interface RpcRequest { method: string; params: string; } /** * Configuration for RPC handler manager */ interface RpcHandlerConfig { scopePrefix: string; encryptionKey: Uint8Array; encryptionVariant: 'legacy' | 'dataKey'; logger?: (message: string, data?: any) => void; } /** * Generic RPC handler manager for session and machine clients * Manages RPC method registration, encryption/decryption, and handler execution */ declare class RpcHandlerManager { private handlers; private readonly scopePrefix; private readonly encryptionKey; private readonly encryptionVariant; private readonly logger; private socket; constructor(config: RpcHandlerConfig); /** * Register an RPC handler for a specific method * @param method - The method name (without prefix) * @param handler - The handler function */ registerHandler<TRequest = any, TResponse = any>(method: string, handler: RpcHandler<TRequest, TResponse>): void; /** * Handle an incoming RPC request * @param request - The RPC request data * @param callback - The response callback */ handleRequest(request: RpcRequest): Promise<any>; onSocketConnect(socket: Socket): Promise<void>; onSocketDisconnect(): void; /** * Get the number of registered handlers */ getHandlerCount(): number; /** * Check if a handler is registered * @param method - The method name (without prefix) */ hasHandler(method: string): boolean; /** * Invoke a registered handler in-process with already-decrypted params. * Used by the generic harness dispatcher to fall through to a legacy * per-harness RPC (e.g. `openclaw-agent-add`) when the harness provider * doesn't expose the dispatcher-facing method directly. */ callLocal<TRequest = any, TResponse = any>(method: string, params: TRequest): Promise<TResponse | undefined>; /** * Clear all handlers */ clearHandlers(): void; /** * Get the prefixed method name * @param method - The method name */ private getPrefixedMethod; } /** * ACP (Agent Communication Protocol) message data types. * This is the unified format for all agent messages - CLI adapts each provider's format to ACP. */ type ACPMessageData = { type: 'message'; message: string; } | { type: 'reasoning'; message: string; } | { type: 'thinking'; text: string; } | { type: 'tool-call'; callId: string; name: string; input: unknown; id: string; } | { type: 'tool-result'; callId: string; output: unknown; id: string; isError?: boolean; } | { type: 'file-edit'; description: string; filePath: string; diff?: string; oldContent?: string; newContent?: string; id: string; } | { type: 'terminal-output'; data: string; callId: string; } | { type: 'task_started'; id: string; } | { type: 'task_complete'; id: string; } | { type: 'turn_aborted'; id: string; } | { type: 'permission-request'; permissionId: string; toolName: string; description: string; options?: unknown; } | { type: 'artifact'; artifactId: string; mime: string; name?: string; sizeBytes?: number; } | { type: 'token_count'; [key: string]: unknown; }; type ACPProvider = 'gemini' | 'grok' | 'pi' | 'codex' | 'claude' | 'consortium-code'; declare class ApiSessionClient extends EventEmitter { private readonly token; readonly sessionId: string; private metadata; private metadataVersion; private agentState; private agentStateVersion; private socket; private pendingMessages; private pendingMessageCallback; readonly rpcHandlerManager: RpcHandlerManager; private agentStateLock; private metadataLock; private encryptionKey; private encryptionVariant; private lastClaudeModel; private pendingEmits; private static readonly MAX_PENDING_EMITS; private reconnectTimer; private manualReconnectAttempts; private destroyed; private flushWatchdog; private static readonly FLUSH_WATCHDOG_MS; /** Get encryption details for passing to child processes. */ getEncryptionDetails(): { key: Uint8Array; variant: 'legacy' | 'dataKey'; }; /** * Upload an agent-produced media blob to the server as a SessionArtifact. * * Phase 1: bytes are POSTed as base64 *plaintext*. The S3 path is in a * `private/` prefix, served only via short-lived presigned URLs to * authenticated session owners — same security model as * SupportTicketAttachment. Phase 1.5 will layer client-side encryption * with libsodium secretbox under the session data key (the primitive is * already used by Drive content, so it's cross-platform on both sides). * * Returns the artifact id and metadata so the caller can immediately * reference it in an outgoing agent message * (`{ type: 'artifact', artifactId, mime }`). */ uploadArtifact(args: { bytes: Uint8Array; mime: string; }): Promise<{ id: string; mime: string; sizeBytes: number; }>; constructor(token: string, session: Session); onUserMessage(callback: (data: UserMessage) => void): void; /** * Emit a 'message' payload, buffering it if the socket is currently * disconnected. Drained on the next 'connect' event. */ private reliableEmitMessage; private flushPendingEmits; /** * Send message to session * @param body - Message body (can be MessageContent or raw content for agent messages) */ sendClaudeSessionMessage(body: RawJSONLines): void; sendCodexMessage(body: any): void; /** * Send a generic agent message to the session using ACP (Agent Communication Protocol) format. * Works for any agent type (Gemini, Codex, Claude, etc.) - CLI normalizes to unified ACP format. * * @param provider - The agent provider sending the message (e.g., 'gemini', 'codex', 'claude') * @param body - The message payload (type: 'message' | 'reasoning' | 'tool-call' | 'tool-result') */ /** * Send a user message to the session, rendered as a chat bubble on the web client. * Used to mirror terminal TUI input to the web session. */ sendUserChatMessage(text: string): void; sendAgentMessage(provider: ACPProvider, body: ACPMessageData): void; sendSessionEvent(event: { type: 'switch'; mode: 'local' | 'remote'; } | { type: 'message'; message: string; } | { type: 'permission-mode-changed'; mode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'; } | { type: 'ready'; }, id?: string): void; /** * Send a ping message to keep the connection alive */ keepAlive(thinking: boolean, mode: 'local' | 'remote'): void; /** * Send session death message */ sendSessionDeath(): void; /** * Infers the LLM provider ID from a model name string. */ private inferProvider; /** * Detects the usage mode based on environment variables. * If base URL points to the consortium proxy, it's managed mode. * Otherwise defaults to wrapped (backward-compatible). */ private detectUsageMode; /** * Send usage data to the server */ sendUsageData(usage: Usage, model?: string): void; /** * Update session metadata * @param handler - Handler function that returns the updated metadata */ updateMetadata(handler: (metadata: Metadata) => Metadata): void; /** * Update session agent state * @param handler - Handler function that returns the updated agent state */ updateAgentState(handler: (metadata: AgentState) => AgentState): void; /** * Wait for socket buffer to flush */ flush(): Promise<void>; close(): Promise<void>; /** * Schedule a manual reconnect after a connect_error. Mirrors * ApiMachineClient.scheduleManualReconnect; see comment there for the * Socket.IO middleware-rejection rationale. Session sockets don't * carry their own refresh path — the session token comes from the * parent process, so the only thing we can do here is retry with * the existing token until it works (or until close() is called). */ private scheduleManualReconnect; } /** * Shared types for the persistent terminal multiplexer subsystem. * * TerminalBackend is the common interface implemented by tmux, zellij, and * the fallback ephemeral (node-pty) backend. TerminalManager owns backend * instances and dispatches I/O through them. */ type TerminalMode = 'tmux' | 'zellij' | 'ephemeral'; type TerminalStatus = 'running' | 'exited'; interface TerminalDescriptor { id: string; mode: TerminalMode; status: TerminalStatus; /** Epoch ms; best-effort, may be 0 if unknown post-restart */ createdAt: number; } interface SpawnSessionOptions { machineId?: string; directory: string; sessionId?: string; approvedNewDirectoryCreation?: boolean; agent?: 'claude' | 'codex' | 'gemini' | 'grok' | 'pi' | 'consortium-code'; token?: string; /** Start as Project Manager agent with session orchestration tools */ pmMode?: boolean; /** When true, create a worktree before spawning the agent process */ worktreeMode?: boolean; /** Card ID for worktree branch naming */ cardId?: string; /** Card slug for worktree directory naming */ cardSlug?: string; /** Base branch for worktree (defaults to 'main') */ repoBaseBranch?: string; /** * Legacy: Claude session ID to resume (uses `claude --resume <id>`). * Still honored for claude agents when `resume` is not set. Prefer `resume` * below for all new callers — it carries agent-specific resume data. */ resumeSessionId?: string; /** * Agent-specific resume hint. Only one of these is consulted, based on * `agent`: * - claude → uses `sessionId` as `--resume <id>` * - codex → uses `rolloutPath` via `experimental_resume` * config (daemon writes it to a --config arg) * and passes `sessionId` for logging. * - consortium-code → uses `--continue` (no id). `sessionId` carried * for logging only; actual resume is last-session. * - gemini → resume not supported; daemon rejects with a * user-visible error if this is set. */ resume?: { sessionId?: string; rolloutPath?: string; }; environmentVariables?: { ANTHROPIC_BASE_URL?: string; ANTHROPIC_AUTH_TOKEN?: string; ANTHROPIC_MODEL?: string; TMUX_SESSION_NAME?: string; TMUX_TMPDIR?: string; }; /** Per-provider key mode from profile: managed, byok, or none */ profileKeyMode?: Record<string, 'managed' | 'byok' | 'none'>; /** * How auth credentials should be sourced for this session. Mirrors * `AuthSource` in `src/auth/types.ts` — duplicated as a string-literal * union here to avoid a circular import between the common RPC layer * and the auth module. Defaults to `'auto'` server-side: prefer * machine creds if the probe finds them, else fall back to managed * proxy if the user has credits, else error. */ authSource?: 'machine' | 'managed' | 'byok' | 'auto'; /** * Optional expectation about the resolved identity. When supplied, * the daemon verifies the probe's identity matches before spawning; * a mismatch surfaces a clear error rather than silently using the * wrong account. */ authIdentity?: { agent: 'claude' | 'codex' | 'gemini' | 'consortium'; email?: string; }; /** * Provider id picked in the mobile Provider button (W3A). When set and * non-`consortium`, the daemon injects this provider's keyEnvVar from * the encrypted BYOK keystore so the agent CLI talks directly to the * native upstream instead of routing through the Consortium proxy. * Higher precedence than `profileKeyMode` for choosing the BYOK * provider id. */ providerId?: string; /** * Selected model id (W3A). Currently advisory — the agent CLI reads * the model from its own per-agent flags or environment. Carried so * future telemetry / provider-routing decisions can avoid re-parsing * provider:model strings. */ modelId?: string; /** * Explicit environment variable name to bind the BYOK key under when * the daemon can't infer it from its catalogs (custom providers). * Mobile supplies this for `customProviders` entries; the daemon uses * it verbatim instead of looking up via AGENT_PROVIDERS or * OPENCODE_PROVIDERS. Ignored when the daemon already knows the * provider. */ byokEnvVar?: string; /** * Optional OpenAI-compatible base URL for the custom provider. When * present the daemon exports `OPENCODE_CUSTOM_BASE_URL` so users can * reference it from their opencode.json provider config. */ byokBaseURL?: string; } type SpawnSessionResult = { type: 'success'; sessionId: string; } | { type: 'requestToApproveDirectoryCreation'; directory: string; } | { type: 'error'; errorMessage: string; } /** * Proxy-token mint failed for a required scope. Distinct from the * generic 'error' so the app can route to billing/upgrade UI instead * of a generic "Failed to spawn" alert. `errorCode` mirrors the * structured server response (`spending_cap_required`, * `subscription_canceled`, `daily_limit_hit`, `insufficient_credits`, * etc.). The CLI never silently downgrades to direct upstream — a * failed mint is a hard spawn refusal. */ | { type: 'mint_failed'; errorCode: string; message: string; scope: 'consortium' | 'anthropic' | 'openai' | 'google' | 'zai'; }; interface ServerToDaemonEvents { update: (data: Update) => void; 'rpc-request': (data: { method: string; params: string; }, callback: (response: string) => void) => void; 'rpc-registered': (data: { method: string; }) => void; 'rpc-unregistered': (data: { method: string; }) => void; 'rpc-error': (data: { type: string; error: string; }) => void; auth: (data: { success: boolean; user: string; }) => void; error: (data: { message: string; }) => void; 'pty:open': (data: { terminalId: string; cols: number; rows: number; persistentTerminalId?: string; }, callback: (response: { ok: boolean; error?: string; }) => void) => void; 'pty:data': (data: { terminalId: string; data: string; }) => void; 'pty:resize': (data: { terminalId: string; cols: number; rows: number; }) => void; 'pty:close': (data: { terminalId: string; }) => void; 'terminal:create': (data: { terminalId: string; persistenceMode?: string; cols?: number; rows?: number; cwd?: string; shell?: string; }, callback: (response: { ok: boolean; mode: string; error?: string; }) => void) => void; 'terminal:list': (data: unknown, callback: (response: { ok: boolean; terminals: TerminalDescriptor[]; }) => void) => void; 'terminal:destroy': (data: { terminalId: string; }, callback: (response: { ok: boolean; error?: string; }) => void) => void; 'server-shutting-down': (data: { reason: string; timestamp: number; }) => void; 'machine:fs-readdir': (data: { machineId: string; path: string; requestId: string; }) => void; 'machine:fs-stat': (data: { machineId: string; path: string; requestId: string; }) => void; } interface DaemonToServerEvents { 'machine-alive': (data: { machineId: string; time: number; }) => void; 'machine-update-metadata': (data: { machineId: string; metadata: string; expectedVersion: number; }, cb: (answer: { result: 'error'; } | { result: 'version-mismatch'; version: number; metadata: string; } | { result: 'success'; version: number; metadata: string; }) => void) => void; 'machine-update-state': (data: { machineId: string; daemonState: string; expectedVersion: number; }, cb: (answer: { result: 'error'; } | { result: 'version-mismatch'; version: number; daemonState: string; } | { result: 'success'; version: number; daemonState: string; }) => void) => void; 'openclaw:activity': (data: { machineId: string; eventType: s