diff --git a/README.md b/README.md index 0d7364d..087a502 100644 --- a/README.md +++ b/README.md @@ -1190,7 +1190,7 @@ Methods: - `system.capabilities` returns gateway protocol and node policy snapshot. Companion runtime helper: -- `src/companion/runtimeClient.ts` provides a typed Node/WebSocket client for companion runtimes (macOS/iOS/Android workers) with wrappers for `node.register`, `node.capabilities.get`, `node.location.set/get`, `node.status.set`, `node.push_token.set`, `system.capabilities`, `system.nodes`, and canvas artifact RPCs (`canvas.put/get/list/delete/clear`), plus optional `autoConnect` mode and event helpers (`subscribeEvents()`, `subscribeEvent()`, `waitForEvent()`). +- `src/companion/runtimeClient.ts` provides a typed Node/WebSocket client for companion runtimes (macOS/iOS/Android workers) with wrappers for `node.register`, `node.capabilities.get`, `node.location.set/get`, `node.status.set`, `node.push_token.set`, `system.capabilities`, `system.nodes`, and canvas artifact RPCs (`canvas.put/get/list/delete/clear`), plus convenience helpers (`bootstrapNode`, optional `autoConnect`) and event helpers (`subscribeEvents()`, `subscribeEvent()`, `waitForEvent()`). - `src/companion/platformClients.ts` provides platform-focused wrappers: - `MacOSCompanionClient` (`platform: "macos"`, APNs push registration) - `IOSCompanionClient` (`platform: "ios"`, APNs push registration) diff --git a/docs/plans/state.json b/docs/plans/state.json index b341c5f..4155c9d 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -341,6 +341,20 @@ ], "test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/platformClients.integration.test.ts src/companion/heartbeatLoop.test.ts + pnpm typecheck passing" }, + "companion-runtime-bootstrap-helper": { + "status": "completed", + "date": "2026-02-17", + "updated": "2026-02-17", + "summary": "Added `bootstrapNode()` to `CompanionRuntimeClient` to perform register + capability negotiation in one call with optional `system.capabilities` inclusion.", + "files_modified": [ + "src/companion/runtimeClient.ts", + "src/companion/runtimeClient.test.ts", + "src/companion/index.ts", + "README.md", + "docs/plans/state.json" + ], + "test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/platformClients.integration.test.ts src/companion/heartbeatLoop.test.ts + pnpm typecheck passing" + }, "browser-tools-activation-clarity": { "status": "completed", "date": "2026-02-17", diff --git a/src/companion/index.ts b/src/companion/index.ts index 4ef8de5..ce884cd 100644 --- a/src/companion/index.ts +++ b/src/companion/index.ts @@ -23,6 +23,7 @@ export type { GetCanvasArtifactInput, DeleteCanvasArtifactInput, NodeRegisterResult, + NodeBootstrapResult, NodeCapabilitiesResult, NodeStatusSetResult, NodeLocationSetResult, diff --git a/src/companion/runtimeClient.test.ts b/src/companion/runtimeClient.test.ts index dd45910..f8a44b2 100644 --- a/src/companion/runtimeClient.test.ts +++ b/src/companion/runtimeClient.test.ts @@ -267,6 +267,36 @@ describe('CompanionRuntimeClient', () => { } }); + it('bootstraps node registration and capabilities in one call', async () => { + if (!LISTEN_ALLOWED) { + return; + } + + const client = new CompanionRuntimeClient({ + url: `ws://127.0.0.1:${TEST_PORT}`, + token: TEST_TOKEN, + }); + await client.connect(); + + try { + const boot = await client.bootstrapNode( + { + nodeId: 'bootstrap-runtime-node', + role: 'companion', + capabilities: ['ui.canvas'], + }, + { includeSystemCapabilities: true }, + ); + + expect(boot.register.registered).toBe(true); + expect(boot.capabilities.node.id).toBe('bootstrap-runtime-node'); + expect(boot.systemCapabilities?.nodes.enabled).toBe(true); + expect(boot.systemCapabilities?.nodes.registered).toBe(true); + } finally { + client.disconnect(); + } + }); + it('updates status/location/push and exposes them through system.nodes', async () => { if (!LISTEN_ALLOWED) { return; diff --git a/src/companion/runtimeClient.ts b/src/companion/runtimeClient.ts index 72b8408..321dec7 100644 --- a/src/companion/runtimeClient.ts +++ b/src/companion/runtimeClient.ts @@ -89,6 +89,12 @@ export interface NodeCapabilitiesResult { }; } +export interface NodeBootstrapResult { + register: NodeRegisterResult; + capabilities: NodeCapabilitiesResult; + systemCapabilities?: SystemCapabilitiesResult; +} + export interface NodeStatus { platform: 'macos' | 'ios' | 'android' | 'linux' | 'windows' | 'unknown'; appVersion?: string; @@ -459,6 +465,26 @@ export class CompanionRuntimeClient { }); } + async bootstrapNode( + input: RegisterNodeInput, + options?: { includeSystemCapabilities?: boolean }, + ): Promise { + const register = await this.registerNode(input); + const capabilities = await this.getNodeCapabilities(); + if (options?.includeSystemCapabilities) { + const systemCapabilities = await this.getSystemCapabilities(); + return { + register, + capabilities, + systemCapabilities, + }; + } + return { + register, + capabilities, + }; + } + getNodeCapabilities(): Promise { return this.call('node.capabilities.get'); }