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; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>; declare const RawJSONLinesSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{ type: z.ZodLiteral<"user">; isSidechain: z.ZodOptional; isMeta: z.ZodOptional; 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; isMeta: z.ZodOptional; 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; isMeta: z.ZodOptional; 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.ZodObject<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, z.ZodTypeAny, "passthrough">>; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ uuid: z.ZodString; type: z.ZodLiteral<"assistant">; message: z.ZodObject<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, z.ZodTypeAny, "passthrough">>; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ uuid: z.ZodString; type: z.ZodLiteral<"assistant">; message: z.ZodObject<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ usage: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ input_tokens: z.ZodNumber; cache_creation_input_tokens: z.ZodOptional; cache_read_input_tokens: z.ZodOptional; output_tokens: z.ZodNumber; service_tier: z.ZodOptional; }, z.ZodTypeAny, "passthrough">>>; content: z.ZodAny; }, 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; /** * Common RPC types and interfaces for both session and machine clients */ /** * Session context for RPC handlers * Contains environment and path information for the current session */ interface RpcSessionContext { /** Working directory path for the session */ path: string; /** Environment variables (includes direnv if available) */ env: Record; } /** * Generic RPC handler function type * @template TRequest - The request data type * @template TResponse - The response data type */ type RpcHandler = (data: TRequest) => TResponse | Promise; /** * 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; private sessionContext; constructor(config: RpcHandlerConfig); /** * Set the session context (path and environment) * This should be called after direnv environment is loaded * @param context - The session context with path and environment */ setSessionContext(context: RpcSessionContext): void; /** * Get the current session context * @returns The session context or null if not set */ getSessionContext(): RpcSessionContext | null; /** * Register an RPC handler for a specific method * @param method - The method name (without prefix) * @param handler - The handler function */ registerHandler(method: string, handler: RpcHandler): void; /** * Handle an incoming RPC request * @param request - The RPC request data * @param callback - The response callback */ handleRequest(request: RpcRequest): Promise; onSocketConnect(socket: Socket): 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; /** * Clear all handlers */ clearHandlers(): void; /** * Get the prefixed method name * @param method - The method name */ private getPrefixedMethod; } 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; constructor(token: string, session: Session); onUserMessage(callback: (data: UserMessage) => void): void; /** * 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; 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; /** * Send usage data to the server */ sendUsageData(usage: Usage): void; /** * Get the current session summary/title * @returns The summary text or undefined if not set */ getSummary(): string | undefined; /** * 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; close(): Promise; /** * Download and decrypt a blob from the server * @param blobId - The blob ID to download * @returns The decrypted binary data and metadata, or null if download/decryption fails */ downloadBlob(blobId: string): Promise<{ data: Uint8Array; mimeType: string; size: number; } | null>; /** * Convert an image_ref content block to a Claude API image content block * Downloads, decrypts, and base64 encodes the image * @param imageRef - The image reference content block * @returns Claude API image content block, or null if conversion fails */ resolveImageRef(imageRef: ImageRefContent): Promise<{ type: 'image'; source: { type: 'base64'; media_type: string; data: string; }; } | null>; } type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'; /** * Usage data type from Claude */ type Usage = z.infer; /** * Session information */ type Session = { id: 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; happyCliVersion: z.ZodString; homeDir: z.ZodString; happyHomeDir: z.ZodString; happyLibDir: z.ZodString; }, "strip", z.ZodTypeAny, { host: string; platform: string; happyCliVersion: string; homeDir: string; happyHomeDir: string; happyLibDir: string; }, { host: string; platform: string; happyCliVersion: string; homeDir: string; happyHomeDir: string; happyLibDir: string; }>; type MachineMetadata = z.infer; /** * 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; httpPort: z.ZodOptional; startedAt: z.ZodOptional; shutdownRequestedAt: z.ZodOptional; shutdownSource: z.ZodOptional, 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; type Machine = { id: string; encryptionKey: Uint8Array; encryptionVariant: 'legacy' | 'dataKey'; metadata: MachineMetadata; metadataVersion: number; daemonState: DaemonState | null; daemonStateVersion: number; }; /** * Image reference content block for user messages (E2E encrypted images) */ declare const ImageRefContentSchema: z.ZodObject<{ type: z.ZodLiteral<"image_ref">; blobId: z.ZodString; mimeType: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/webp"]>; width: z.ZodOptional; height: z.ZodOptional; }, "strip", z.ZodTypeAny, { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; }, { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; }>; type ImageRefContent = z.infer; declare const UserMessageSchema: z.ZodObject<{ role: z.ZodLiteral<"user">; content: z.ZodUnion<[z.ZodObject<{ type: z.ZodLiteral<"text">; text: z.ZodString; }, "strip", z.ZodTypeAny, { type: "text"; text: string; }, { type: "text"; text: string; }>, z.ZodArray; text: z.ZodString; }, "strip", z.ZodTypeAny, { type: "text"; text: string; }, { type: "text"; text: string; }>, z.ZodObject<{ type: z.ZodLiteral<"image_ref">; blobId: z.ZodString; mimeType: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/webp"]>; width: z.ZodOptional; height: z.ZodOptional; }, "strip", z.ZodTypeAny, { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; }, { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; }>]>, "many">]>; localKey: z.ZodOptional; meta: z.ZodOptional; permissionMode: z.ZodOptional; model: z.ZodOptional>; fallbackModel: z.ZodOptional>; customSystemPrompt: z.ZodOptional>; appendSystemPrompt: z.ZodOptional>; allowedTools: z.ZodOptional>>; disallowedTools: z.ZodOptional>>; }, "strip", z.ZodTypeAny, { sentFrom?: string | undefined; permissionMode?: string | undefined; model?: string | null | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; }, { sentFrom?: string | undefined; permissionMode?: string | undefined; model?: string | null | undefined; fallbackModel?: string | null | undefined; customSystemPrompt?: string | null | undefined; appendSystemPrompt?: string | null | undefined; allowedTools?: string[] | null | undefined; disallowedTools?: string[] | null | undefined; }>>; }, "strip", z.ZodTypeAny, { content: { type: "text"; text: string; } | ({ type: "text"; text: string; } | { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; })[]; role: "user"; localKey?: string | undefined; meta?: { sentFrom?: string | undefined; permissionMode?: string | undefined; model?: string | null | 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; } | ({ type: "text"; text: string; } | { type: "image_ref"; blobId: string; mimeType: "image/jpeg" | "image/png" | "image/gif" | "image/webp"; width?: number | undefined; height?: number | undefined; })[]; role: "user"; localKey?: string | undefined; meta?: { sentFrom?: string | undefined; permissionMode?: string | undefined; model?: string | null | 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; type Metadata = { path: string; host: string; version?: string; name?: string; os?: string; summary?: { text: string; updatedAt: number; }; machineId?: string; claudeSessionId?: string; tools?: string[]; slashCommands?: string[]; customCommands?: Array<{ name: string; description?: string; argumentHint?: string; scope: 'project' | 'personal'; namespace?: string; }>; homeDir: string; happyHomeDir: string; happyLibDir: string; happyToolsDir: string; startedFromDaemon?: boolean; hostPid?: number; startedBy?: 'daemon' | 'terminal'; lifecycleState?: 'running' | 'archiveRequested' | 'archived' | string; lifecycleStateSince?: number; archivedBy?: string; archiveReason?: string; flavor?: string; permissionMode?: PermissionMode; }; 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[]; }; }; }; interface SpawnSessionOptions { machineId?: string; directory: string; sessionId?: string; approvedNewDirectoryCreation?: boolean; agent?: 'claude' | 'codex'; token?: string; resumeClaudeSessionId?: string; /** When resuming, create a new session ID instead of reusing the original */ forkSession?: boolean; /** Environment variables to pass to the spawned session */ environmentVariables?: Record; } type SpawnSessionResult = { type: 'success'; sessionId: string; } | { type: 'requestToApproveDirectoryCreation'; directory: string; } | { type: 'error'; errorMessage: string; }; /** * WebSocket client for machine/daemon communication with Happy server * Similar to ApiSessionClient but for machine-scoped connections */ type MachineRpcHandlers = { spawnSession: (options: SpawnSessionOptions) => Promise; stopSession: (sessionId: string) => boolean; requestShutdown: () => void; }; declare class ApiMachineClient { private token; private machine; private socket; private keepAliveInterval; private rpcHandlerManager; constructor(token: string, machine: Machine); setRPCHandlers({ spawnSession, stopSession, requestShutdown }: MachineRpcHandlers): void; /** * Update machine metadata * Currently unused, changes from the mobile client are more likely * for example to set a custom name. */ updateMachineMetadata(handler: (metadata: MachineMetadata | null) => MachineMetadata): Promise; /** * Update daemon state (runtime info) - similar to session updateAgentState * Simplified without lock - relies on backoff for retry */ updateDaemonState(handler: (state: DaemonState | null) => DaemonState): Promise; connect(): void; private startKeepAlive; private stopKeepAlive; shutdown(): void; } interface PushToken { id: string; token: string; createdAt: number; updatedAt: number; } declare class PushNotificationClient { private readonly token; private readonly baseUrl; private readonly expo; constructor(token: string, baseUrl?: string); /** * Fetch all push tokens for the authenticated user */ fetchPushTokens(): Promise; /** * Send push notification via Expo Push API with retry * @param messages - Array of push messages to send */ sendPushNotifications(messages: ExpoPushMessage[]): Promise; /** * Send a push notification to all registered devices for the user * @param title - Notification title * @param body - Notification body * @param data - Additional data to send with the notification */ sendToAllDevices(title: string, body: string, data?: Record): void; } /** * Minimal persistence functions for happy CLI * * Handles settings and private key storage in ~/.happy/ or local .happy/ */ type Credentials = { token: string; encryption: { type: 'legacy'; secret: Uint8Array; } | { type: 'dataKey'; dataKeySeed: Uint8Array; machineKey: Uint8Array; }; }; declare class ApiClient { static create(credential: Credentials): Promise; private readonly credential; private readonly pushClient; private constructor(); /** * Create a new session or load existing one with the given tag */ getOrCreateSession(opts: { tag: string; metadata: Metadata; state: AgentState | null; }): Promise; /** * Register or update machine with the server * Returns the current machine state from the server with decrypted metadata and daemonState */ getOrCreateMachine(opts: { machineId: string; metadata: MachineMetadata; daemonState?: DaemonState; }): Promise; sessionSyncClient(session: Session): ApiSessionClient; machineSyncClient(machine: Machine): ApiMachineClient; push(): PushNotificationClient; /** * Register a vendor API token with the server * The token is sent as a JSON string - server handles encryption */ registerVendorToken(vendor: 'openai' | 'anthropic' | 'gemini', apiKey: any): Promise; } /** * Design decisions: * - Logging should be done only through file for debugging, otherwise we might disturb the claude session when in interactive mode * - Use info for logs that are useful to the user - this is our UI * - File output location: ~/.handy/logs/.log */ declare class Logger { readonly logFilePath: string; private dangerouslyUnencryptedServerLoggingUrl; constructor(logFilePath?: string); localTimezoneTimestamp(): string; debug(message: string, ...args: unknown[]): void; debugLargeJson(message: string, object: unknown, maxStringLength?: number, maxArrayLength?: number): void; info(message: string, ...args: unknown[]): void; infoDeveloper(message: string, ...args: unknown[]): void; warn(message: string, ...args: unknown[]): void; getLogPath(): string; private logToConsole; private sendToRemoteServer; private logToFile; } declare let logger: Logger; /** * Global configuration for happy CLI * * Centralizes all configuration including environment variables and paths * Environment files should be loaded using Node's --env-file flag */ declare class Configuration { readonly serverUrl: string; readonly webappUrl: string; readonly isDaemonProcess: boolean; readonly happyHomeDir: string; readonly logsDir: string; readonly settingsFile: string; readonly privateKeyFile: string; readonly daemonStateFile: string; readonly daemonLockFile: string; readonly currentCliVersion: string; readonly isExperimentalEnabled: boolean; readonly disableCaffeinate: boolean; constructor(); } declare const configuration: Configuration; export { ApiClient, ApiSessionClient, RawJSONLinesSchema, configuration, logger }; export type { RawJSONLines };