/** * Cross-extension RPC handlers for the subagents extension. * * Exposes ping, spawn, and stop RPCs over the pi.events event bus, * using per-request scoped reply channels. * * Reply envelope follows pi-mono convention: * success → { success: true, data?: T } * error → { success: false, error: string } */ export type RpcErrorCode = "RATE_LIMITED" | "UNAUTHORIZED" | "INVALID_PARAMS" | "ERROR"; export declare class RpcError extends Error { readonly code: RpcErrorCode; constructor(code: RpcErrorCode, message: string); } /** Minimal event bus interface needed by the RPC handlers. */ export interface EventBus { on(event: string, handler: (data: unknown) => void): () => void; emit(event: string, data: unknown): void; } /** RPC reply envelope — matches pi-mono's RpcResponse shape. */ export type RpcReply = { success: true; data?: T; } | { success: false; error: string; }; /** RPC protocol version — bumped when the envelope or method contracts change. */ export declare const PROTOCOL_VERSION = 2; export interface SpawnCapable { spawn(pi: unknown, ctx: unknown, type: string, prompt: string, options: any): string; abort(id: string): boolean; } export interface SessionCapable extends SpawnCapable { getSessionUsage(): { spawnedAgents: number; totalTurns: number; }; getSessionMaxSpawns(): number; getSessionMaxTurns(): number; } export interface SwarmCapable { listSwarms(): Array<{ swarmId: string; name: string; agentCount: number; strategy: string; leaderId?: string; }>; getSwarmMetrics(swarmId?: string): { totalDeliveries: number; totalRecordsDelivered: number; partialDeliveries: number; timedOutDeliveries: number; averageLatencyMs?: number; bySwarm: Record; }; } export interface AuthContext { extensionId: string; extensionName?: string; } export interface SpawnRpcRequest { type: string; prompt: string; options?: Record; } export interface StopRpcRequest { agentId: string; } export interface SessionUsageRpcReply { usage: { spawnedAgents: number; totalTurns: number; }; limits: { maxAgents: number; maxTurns: number; }; } export interface PingRpcReply { version: number; } export interface SubagentsRpcClient { ping(): Promise; spawn(request: SpawnRpcRequest): Promise<{ id: string; }>; stop(request: StopRpcRequest): Promise; sessionUsage(): Promise; } /** Tunables for the per-extension rate limiter. */ export interface RateLimitConfig { /** Sliding window size in milliseconds (default 60 000 — one minute). */ windowMs?: number; /** Maximum calls per window per extension+operation (default 10). */ maxPerWindow?: number; } /** Apply rate-limit configuration. Safe to call multiple times. */ export declare function configureRateLimit(config: RateLimitConfig): void; export declare function resetRpcRateLimitsForTests(): void; /** Return current effective rate-limit settings (useful in tests & diagnostics). */ export declare function getRateLimitConfig(): Required; export interface RpcDeps { events: EventBus; pi: unknown; getCtx: () => unknown | undefined; manager: SpawnCapable; authProvider?: (requestId: string, payload: any) => AuthContext | undefined; /** Optional rate-limit tunables applied at registration time. */ rateLimit?: RateLimitConfig; /** Optional session-capable manager for session usage RPC. */ sessionManager?: SessionCapable; /** Optional swarm coordinator for swarm health RPC. */ swarmCoordinator?: SwarmCapable; } export interface RpcHandle { unsubPing: () => void; unsubSpawn: () => void; unsubStop: () => void; unsubSessionUsage: () => void; /** No-op when swarmCoordinator was not provided to registerRpcHandlers. */ unsubSwarmHealth?: () => void; } export declare function createSubagentsRpcClient(events: EventBus, options?: { timeoutMs?: number; extensionId?: string; }): SubagentsRpcClient; /** * Register ping, spawn, stop, and sessionUsage RPC handlers on the event bus. * Returns unsub functions for cleanup. * * **Global rate-limit state:** Calling this function with `deps.rateLimit` will * mutate module-level globals (`rateLimitWindow`, `rateLimitMax`) via * {@link configureRateLimit}. Multiple registrations in the same process share * and override these settings — the last registration wins. This is intentional * for the expected single-registration pattern; callers registering multiple * times should be aware of the side effect. */ export declare function registerRpcHandlers(deps: RpcDeps): RpcHandle;