From 1f22c3e578efeaef7a2408e1bc35dfc6c29e99ac Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:40:09 +0800 Subject: [PATCH] feat(hub): register RPC handlers for hub, agent, and gateway operations Add 5 new RPC methods (getHubInfo, listAgents, createAgent, deleteAgent, updateGateway) mirroring the existing Console HTTP API, enabling pure WebSocket communication from the frontend. Co-Authored-By: Claude Opus 4.5 --- docs/rpc.md | 130 +++++++++++++++++++++++++ packages/sdk/src/actions/index.ts | 8 ++ packages/sdk/src/actions/rpc.ts | 44 +++++++++ src/hub/hub.ts | 10 ++ src/hub/rpc/handlers/create-agent.ts | 13 +++ src/hub/rpc/handlers/delete-agent.ts | 19 ++++ src/hub/rpc/handlers/get-hub-info.ts | 17 ++++ src/hub/rpc/handlers/list-agents.ts | 16 +++ src/hub/rpc/handlers/update-gateway.ts | 21 ++++ src/hub/rpc/index.ts | 5 + 10 files changed, 283 insertions(+) create mode 100644 src/hub/rpc/handlers/create-agent.ts create mode 100644 src/hub/rpc/handlers/delete-agent.ts create mode 100644 src/hub/rpc/handlers/get-hub-info.ts create mode 100644 src/hub/rpc/handlers/list-agents.ts create mode 100644 src/hub/rpc/handlers/update-gateway.ts diff --git a/docs/rpc.md b/docs/rpc.md index 535a8078..d3ce36dc 100644 --- a/docs/rpc.md +++ b/docs/rpc.md @@ -207,6 +207,136 @@ const result = await client.request( } ``` +### `getHubInfo` + +Returns Hub status information. No parameters required. + +**Response:** + +```ts +interface GetHubInfoResult { + hubId: string; // Hub device ID + url: string; // Current Gateway URL + connectionState: string; // "disconnected" | "connecting" | "connected" | "registered" + agentCount: number; // Number of active agents +} +``` + +**Example:** + +```ts +const info = await client.request(hubDeviceId, "getHubInfo"); +``` + +--- + +### `listAgents` + +Lists all active agents. No parameters required. + +**Response:** + +```ts +interface ListAgentsResult { + agents: { id: string; closed: boolean }[]; +} +``` + +**Example:** + +```ts +const result = await client.request(hubDeviceId, "listAgents"); +``` + +--- + +### `createAgent` + +Creates a new agent or restores an existing one. + +**Parameters:** + +```ts +interface CreateAgentParams { + id?: string; // optional - reuse existing session ID +} +``` + +**Response:** + +```ts +interface CreateAgentResult { + id: string; // the created/restored agent session ID +} +``` + +**Example:** + +```ts +const result = await client.request(hubDeviceId, "createAgent"); +// or with specific ID: +const result = await client.request(hubDeviceId, "createAgent", { id: "existing-id" }); +``` + +--- + +### `deleteAgent` + +Closes and removes an agent. + +**Parameters:** + +```ts +interface DeleteAgentParams { + id: string; // required - agent ID to delete +} +``` + +**Response:** + +```ts +interface DeleteAgentResult { + ok: boolean; // true if agent was found and deleted +} +``` + +**Example:** + +```ts +const result = await client.request(hubDeviceId, "deleteAgent", { id: "019abc12-..." }); +``` + +--- + +### `updateGateway` + +Reconnects the Hub to a different Gateway URL. + +**Parameters:** + +```ts +interface UpdateGatewayParams { + url: string; // required - new Gateway URL +} +``` + +**Response:** + +```ts +interface UpdateGatewayResult { + url: string; // the new URL + connectionState: string; // connection state after reconnect +} +``` + +**Example:** + +```ts +const result = await client.request(hubDeviceId, "updateGateway", { url: "http://localhost:4000" }); +``` + +--- + ## Adding New RPC Methods 1. Create a handler file in `src/hub/rpc/handlers/`: diff --git a/packages/sdk/src/actions/index.ts b/packages/sdk/src/actions/index.ts index d60637ee..0c673bbd 100644 --- a/packages/sdk/src/actions/index.ts +++ b/packages/sdk/src/actions/index.ts @@ -16,6 +16,14 @@ export { isResponseError, type GetAgentMessagesParams, type GetAgentMessagesResult, + type GetHubInfoResult, + type ListAgentsResult, + type CreateAgentParams, + type CreateAgentResult, + type DeleteAgentParams, + type DeleteAgentResult, + type UpdateGatewayParams, + type UpdateGatewayResult, } from "./rpc.js"; export { StreamAction, type StreamPayload } from "./stream.js"; diff --git a/packages/sdk/src/actions/rpc.ts b/packages/sdk/src/actions/rpc.ts index 0cdc3200..11c0e665 100644 --- a/packages/sdk/src/actions/rpc.ts +++ b/packages/sdk/src/actions/rpc.ts @@ -72,3 +72,47 @@ export interface GetAgentMessagesResult { offset: number; limit: number; } + +/** getHubInfo - no params needed */ +export interface GetHubInfoResult { + hubId: string; + url: string; + connectionState: string; + agentCount: number; +} + +/** listAgents - no params needed */ +export interface ListAgentsResult { + agents: { id: string; closed: boolean }[]; +} + +/** createAgent - request params */ +export interface CreateAgentParams { + id?: string; +} + +/** createAgent - response payload */ +export interface CreateAgentResult { + id: string; +} + +/** deleteAgent - request params */ +export interface DeleteAgentParams { + id: string; +} + +/** deleteAgent - response payload */ +export interface DeleteAgentResult { + ok: boolean; +} + +/** updateGateway - request params */ +export interface UpdateGatewayParams { + url: string; +} + +/** updateGateway - response payload */ +export interface UpdateGatewayResult { + url: string; + connectionState: string; +} diff --git a/src/hub/hub.ts b/src/hub/hub.ts index 5765cef1..c456d8a7 100644 --- a/src/hub/hub.ts +++ b/src/hub/hub.ts @@ -12,6 +12,11 @@ import { getHubId } from "./hub-identity.js"; import { loadAgentRecords, addAgentRecord, removeAgentRecord } from "./agent-store.js"; import { RpcDispatcher, RpcError } from "./rpc/dispatcher.js"; import { createGetAgentMessagesHandler } from "./rpc/handlers/get-agent-messages.js"; +import { createGetHubInfoHandler } from "./rpc/handlers/get-hub-info.js"; +import { createListAgentsHandler } from "./rpc/handlers/list-agents.js"; +import { createCreateAgentHandler } from "./rpc/handlers/create-agent.js"; +import { createDeleteAgentHandler } from "./rpc/handlers/delete-agent.js"; +import { createUpdateGatewayHandler } from "./rpc/handlers/update-gateway.js"; export class Hub { private readonly agents = new Map(); @@ -34,6 +39,11 @@ export class Hub { this.rpc = new RpcDispatcher(); this.rpc.register("getAgentMessages", createGetAgentMessagesHandler()); + this.rpc.register("getHubInfo", createGetHubInfoHandler(this)); + this.rpc.register("listAgents", createListAgentsHandler(this)); + this.rpc.register("createAgent", createCreateAgentHandler(this)); + this.rpc.register("deleteAgent", createDeleteAgentHandler(this)); + this.rpc.register("updateGateway", createUpdateGatewayHandler(this)); this.client = this.createClient(this.url); this.client.connect(); diff --git a/src/hub/rpc/handlers/create-agent.ts b/src/hub/rpc/handlers/create-agent.ts new file mode 100644 index 00000000..c0ab1186 --- /dev/null +++ b/src/hub/rpc/handlers/create-agent.ts @@ -0,0 +1,13 @@ +import type { RpcHandler } from "../dispatcher.js"; + +interface HubLike { + createAgent(id?: string): { sessionId: string }; +} + +export function createCreateAgentHandler(hub: HubLike): RpcHandler { + return (params: unknown) => { + const { id } = (params ?? {}) as { id?: string }; + const agent = hub.createAgent(id); + return { id: agent.sessionId }; + }; +} diff --git a/src/hub/rpc/handlers/delete-agent.ts b/src/hub/rpc/handlers/delete-agent.ts new file mode 100644 index 00000000..72207f24 --- /dev/null +++ b/src/hub/rpc/handlers/delete-agent.ts @@ -0,0 +1,19 @@ +import { RpcError, type RpcHandler } from "../dispatcher.js"; + +interface HubLike { + closeAgent(id: string): boolean; +} + +export function createDeleteAgentHandler(hub: HubLike): RpcHandler { + return (params: unknown) => { + if (!params || typeof params !== "object") { + throw new RpcError("INVALID_PARAMS", "params must be an object"); + } + const { id } = params as { id?: string }; + if (!id) { + throw new RpcError("INVALID_PARAMS", "Missing required param: id"); + } + const ok = hub.closeAgent(id); + return { ok }; + }; +} diff --git a/src/hub/rpc/handlers/get-hub-info.ts b/src/hub/rpc/handlers/get-hub-info.ts new file mode 100644 index 00000000..46da8784 --- /dev/null +++ b/src/hub/rpc/handlers/get-hub-info.ts @@ -0,0 +1,17 @@ +import type { RpcHandler } from "../dispatcher.js"; + +interface HubLike { + hubId: string; + url: string; + connectionState: string; + listAgents(): string[]; +} + +export function createGetHubInfoHandler(hub: HubLike): RpcHandler { + return () => ({ + hubId: hub.hubId, + url: hub.url, + connectionState: hub.connectionState, + agentCount: hub.listAgents().length, + }); +} diff --git a/src/hub/rpc/handlers/list-agents.ts b/src/hub/rpc/handlers/list-agents.ts new file mode 100644 index 00000000..ccd5c3e2 --- /dev/null +++ b/src/hub/rpc/handlers/list-agents.ts @@ -0,0 +1,16 @@ +import type { RpcHandler } from "../dispatcher.js"; + +interface HubLike { + listAgents(): string[]; + getAgent(id: string): { closed: boolean } | undefined; +} + +export function createListAgentsHandler(hub: HubLike): RpcHandler { + return () => { + const agents = hub.listAgents().map((id) => { + const agent = hub.getAgent(id); + return { id, closed: agent?.closed ?? true }; + }); + return { agents }; + }; +} diff --git a/src/hub/rpc/handlers/update-gateway.ts b/src/hub/rpc/handlers/update-gateway.ts new file mode 100644 index 00000000..acc4c9ce --- /dev/null +++ b/src/hub/rpc/handlers/update-gateway.ts @@ -0,0 +1,21 @@ +import { RpcError, type RpcHandler } from "../dispatcher.js"; + +interface HubLike { + url: string; + connectionState: string; + reconnect(url: string): void; +} + +export function createUpdateGatewayHandler(hub: HubLike): RpcHandler { + return (params: unknown) => { + if (!params || typeof params !== "object") { + throw new RpcError("INVALID_PARAMS", "params must be an object"); + } + const { url } = params as { url?: string }; + if (!url) { + throw new RpcError("INVALID_PARAMS", "Missing required param: url"); + } + hub.reconnect(url); + return { url: hub.url, connectionState: hub.connectionState }; + }; +} diff --git a/src/hub/rpc/index.ts b/src/hub/rpc/index.ts index c482999a..7bd88565 100644 --- a/src/hub/rpc/index.ts +++ b/src/hub/rpc/index.ts @@ -1,2 +1,7 @@ export { RpcDispatcher, RpcError, type RpcHandler } from "./dispatcher.js"; export { createGetAgentMessagesHandler } from "./handlers/get-agent-messages.js"; +export { createGetHubInfoHandler } from "./handlers/get-hub-info.js"; +export { createListAgentsHandler } from "./handlers/list-agents.js"; +export { createCreateAgentHandler } from "./handlers/create-agent.js"; +export { createDeleteAgentHandler } from "./handlers/delete-agent.js"; +export { createUpdateGatewayHandler } from "./handlers/update-gateway.js";