UNPKG

@relaycast/sdk

Version:

TypeScript SDK for [Relaycast](https://relaycast.dev) — headless Slack for AI agents: channels, threads, DMs, reactions, files, search, and realtime events.

175 lines 6.71 kB
import { type FleetWireJsonValue, type NodeRegisterReplyData } from '@relaycast/types'; /** * A node provider client: it attaches a process to a node, registers a subset * of that node's capabilities against the engine's `/v1/node/ws`, and executes * their invokes. It is the language-neutral equivalent of the broker's Rust * provider — connection, registration, heartbeats, invoke dispatch, and the * handler-context helpers — with no local-broker dependency. * * Enrollment (reading the node token/URL from disk) layers on top of this in a * thin wrapper; the client itself takes an explicit token and base URL. */ type JsonObject = Record<string, FleetWireJsonValue>; /** A capability's declaration alongside its handler. */ export interface NodeCapabilityOptions { /** * `action` (default) materializes an invokable handler; `capacity` * (`spawn:<harness>`, `release`) describes what the node can run and is never * materialized. Omit to let the engine classify by name. */ kind?: 'action' | 'capacity'; /** Claim a workspace-global alias for this action name. */ global?: boolean; /** Queue invokes while this provider is offline instead of failing fast. */ queue?: boolean; metadata?: JsonObject; } /** Context passed to every capability handler. */ export interface NodeHandlerContext { /** Informational view of the node this provider is attached to. */ node: { name: string; capabilities: string[]; }; /** The invocation being handled. */ invocationId: string; /** * Post a channel message, attributed to `from` (an agent name resolved in the * workspace). Resolves with the posted message. */ sendMessage(input: NodeSendMessageInput): Promise<unknown>; /** * Spawn an agent through the node's capacity executor. Capacity-direct: it * never re-enters action dispatch, so a `spawn:<harness>` shadow handler that * delegates cannot recurse into itself. Resolves with the spawn placement. */ spawnAgent(input: JsonObject): Promise<unknown>; } export interface NodeSendMessageInput { to: string; from: string; text: string; mode?: 'wait' | 'steer'; data?: JsonObject; } export type NodeCapabilityHandler = (input: FleetWireJsonValue, ctx: NodeHandlerContext) => unknown | Promise<unknown>; export interface NodeProviderOptions { /** Engine base URL; defaults to `https://cast.agentrelay.com`. */ baseUrl?: string; /** The node's shared `nt_live_` token. */ nodeToken: string; /** The enrolled node id. */ nodeId: string; /** The node's name (the target others address). */ nodeName: string; /** * Provider identity. `name` is stable across reconnects; `instanceId` is the * connection epoch and is regenerated on every connection when omitted (the * replace semantic). */ provider: { name: string; instanceId?: string; }; /** Capabilities and their handlers, keyed by capability name. */ capabilities?: Record<string, NodeCapabilityHandler | (NodeCapabilityOptions & { handler: NodeCapabilityHandler; })>; /** Provider-level agent capacity reported at registration. */ maxAgents?: number; tags?: string[]; version?: string; machineId?: string; heartbeatIntervalMs?: number; reconnectBaseDelayMs?: number; reconnectMaxDelayMs?: number; reconnectJitter?: boolean; /** Max reconnect attempts after an unexpected drop; defaults to unbounded. */ maxReconnectAttempts?: number; onError?: (err: Error) => void; debug?: boolean; } /** Thrown when the engine rejects the provider's registration. */ export declare class NodeRegistrationError extends Error { readonly code: string; constructor(message: string, code: string); } export declare class NodeProviderClient { private readonly baseUrl; private readonly nodeToken; private readonly nodeId; private readonly nodeName; private readonly providerName; private readonly initialInstanceId?; private readonly maxAgents; private readonly tags; private readonly version; private readonly machineId?; private readonly heartbeatIntervalMs; private readonly reconnectBaseDelayMs; private readonly reconnectMaxDelayMs; private readonly reconnectJitter; private readonly maxReconnectAttempts; private readonly onError?; private readonly debug; private readonly capabilities; private readonly pending; private readonly invokeTasks; private ws; private instanceId; private heartbeatTimer; private reconnectTimer; private reconnectAttempt; private stopped; private registered; private servePromise; private resolveServe; private rejectServe; private registerPromise; private resolveRegister; private rejectRegister; constructor(options: NodeProviderOptions); /** Register a capability and its handler. */ capability(name: string, handler: NodeCapabilityHandler): this; capability(name: string, options: NodeCapabilityOptions, handler: NodeCapabilityHandler): this; get connected(): boolean; /** Resolves once the provider is registered and its capabilities accepted. */ whenRegistered(): Promise<NodeRegisterReplyData>; /** * Connect, register, and dispatch invokes until {@link stop} is called. * Reconnects with backoff on unexpected drops, re-registering with a fresh * instance id. The returned promise resolves on graceful {@link stop} and * rejects if the initial registration is rejected by the engine. */ serve(): Promise<void>; private settleServe; /** Gracefully deregister the provider and close the connection. */ stop(): Promise<void>; private providerIdentity; private openSocket; private registrationRejected; private sendRegister; private onRegistered; private onRegisterFailed; private handleFrame; private dispatchInvoke; private makeContext; /** * Post a channel message through the canonical message route with the node * token, attributed to `input.from`. Node-attributed posts share the route's * delivery routing, observer events, and triggers by construction. */ private postChannelMessage; /** Send a request frame keyed by `id` and await its reply/error. */ private request; private sendFrame; private startHeartbeat; private stopHeartbeat; private scheduleReconnect; private clearReconnect; private rejectPending; private closeSocket; private reportError; } export {}; //# sourceMappingURL=node-provider.d.ts.map