@qontinui/ui-bridge-native 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/control/{index.d.mts → action-executor.d.ts} +6 -10
  2. package/dist/control/action-executor.d.ts.map +1 -0
  3. package/dist/control/index.d.ts +5 -91
  4. package/dist/control/index.d.ts.map +1 -0
  5. package/dist/control/index.js +1 -1
  6. package/dist/control/index.js.map +1 -1
  7. package/dist/control/index.mjs +1 -1
  8. package/dist/control/index.mjs.map +1 -1
  9. package/dist/{types-BCYWwyVy.d.ts → control/types.d.ts} +17 -18
  10. package/dist/control/types.d.ts.map +1 -0
  11. package/dist/core/element-identifier.d.ts +41 -0
  12. package/dist/core/element-identifier.d.ts.map +1 -0
  13. package/dist/core/index.d.ts +6 -43
  14. package/dist/core/index.d.ts.map +1 -0
  15. package/dist/{registry-B8A_EoxS.d.ts → core/registry.d.ts} +10 -13
  16. package/dist/core/registry.d.ts.map +1 -0
  17. package/dist/{types-BPNuYxDx.d.ts → core/types.d.ts} +30 -30
  18. package/dist/core/types.d.ts.map +1 -0
  19. package/dist/debug/index.d.ts +4 -44
  20. package/dist/debug/index.d.ts.map +1 -0
  21. package/dist/debug/index.js.map +1 -1
  22. package/dist/debug/index.mjs.map +1 -1
  23. package/dist/debug/{index.d.mts → inspector.d.ts} +3 -6
  24. package/dist/debug/inspector.d.ts.map +1 -0
  25. package/dist/design/{index.d.mts → design-inspector-native.d.ts} +7 -11
  26. package/dist/design/design-inspector-native.d.ts.map +1 -0
  27. package/dist/{design-types-BHr6Q1FX.d.ts → design/design-types.d.ts} +10 -11
  28. package/dist/design/design-types.d.ts.map +1 -0
  29. package/dist/design/index.d.ts +5 -60
  30. package/dist/design/index.d.ts.map +1 -0
  31. package/dist/index.d.ts +28 -73
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +129 -23
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +129 -23
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/react/UIBridgeNativeProvider.d.ts +147 -0
  38. package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -0
  39. package/dist/react/index.d.ts +8 -69
  40. package/dist/react/index.d.ts.map +1 -0
  41. package/dist/react/index.js +138 -23
  42. package/dist/react/index.js.map +1 -1
  43. package/dist/react/index.mjs +138 -23
  44. package/dist/react/index.mjs.map +1 -1
  45. package/dist/react/{index.d.mts → useAutoRegister.d.ts} +7 -15
  46. package/dist/react/useAutoRegister.d.ts.map +1 -0
  47. package/dist/react/useUIBridge.d.ts +103 -0
  48. package/dist/react/useUIBridge.d.ts.map +1 -0
  49. package/dist/react/useUIComponent.d.ts +112 -0
  50. package/dist/react/useUIComponent.d.ts.map +1 -0
  51. package/dist/react/useUIElement.d.ts +162 -0
  52. package/dist/react/useUIElement.d.ts.map +1 -0
  53. package/dist/server/design-handlers.d.ts +47 -0
  54. package/dist/server/design-handlers.d.ts.map +1 -0
  55. package/dist/server/handlers.d.ts +20 -0
  56. package/dist/server/handlers.d.ts.map +1 -0
  57. package/dist/server/http-server.d.ts +247 -0
  58. package/dist/server/http-server.d.ts.map +1 -0
  59. package/dist/server/index.d.ts +13 -117
  60. package/dist/server/index.d.ts.map +1 -0
  61. package/dist/server/index.js +102 -1
  62. package/dist/server/index.js.map +1 -1
  63. package/dist/server/index.mjs +102 -1
  64. package/dist/server/index.mjs.map +1 -1
  65. package/dist/server/types.d.ts +200 -0
  66. package/dist/server/types.d.ts.map +1 -0
  67. package/dist/server/ws-connection.d.ts +48 -0
  68. package/dist/server/ws-connection.d.ts.map +1 -0
  69. package/dist/server/ws-event-bridge.d.ts +113 -0
  70. package/dist/server/ws-event-bridge.d.ts.map +1 -0
  71. package/dist/server/ws-protocol.d.ts +48 -0
  72. package/dist/server/ws-protocol.d.ts.map +1 -0
  73. package/dist/server/ws-types.d.ts +65 -0
  74. package/dist/server/ws-types.d.ts.map +1 -0
  75. package/dist/transport/CloudRelayClient.d.ts +51 -0
  76. package/dist/transport/CloudRelayClient.d.ts.map +1 -0
  77. package/dist/transport/DeviceAnnouncer.d.ts +75 -0
  78. package/dist/transport/DeviceAnnouncer.d.ts.map +1 -0
  79. package/dist/transport/index.d.ts +3 -0
  80. package/dist/transport/index.d.ts.map +1 -0
  81. package/package.json +1 -1
  82. package/dist/core/index.d.mts +0 -46
  83. package/dist/design-types-BHr6Q1FX.d.mts +0 -205
  84. package/dist/http-server-B7KudcYJ.d.ts +0 -622
  85. package/dist/http-server-D7uVANBU.d.mts +0 -622
  86. package/dist/index.d.mts +0 -76
  87. package/dist/registry-DhbGbl9c.d.mts +0 -215
  88. package/dist/server/index.d.mts +0 -119
  89. package/dist/types-BPNuYxDx.d.mts +0 -383
  90. package/dist/types-Bcj7ji97.d.mts +0 -177
  91. package/dist/useUIBridge-CDZbWxII.d.ts +0 -571
  92. package/dist/useUIBridge-DfIEq9EQ.d.mts +0 -571
@@ -0,0 +1,247 @@
1
+ /**
2
+ * UI Bridge Native HTTP Server
3
+ *
4
+ * Abstract HTTP server implementation for React Native.
5
+ * This provides a framework-agnostic server interface that can be
6
+ * implemented using various React Native HTTP server libraries.
7
+ *
8
+ * Supported libraries:
9
+ * - react-native-http-bridge (recommended)
10
+ * - @aspect/react-native-http-server
11
+ * - Custom implementations
12
+ */
13
+ import type { NativeUIBridgeRegistry } from '../core/registry';
14
+ import type { NativeActionExecutor } from '../control/types';
15
+ import type { NativeServerConfig, NavigationProvider, RouteProvider, ScreenshotProvider } from './types';
16
+ import type { WebSocketEventBridge } from './ws-event-bridge';
17
+ import type { JsonRpcRequest, JsonRpcResponse } from './ws-types';
18
+ /**
19
+ * HTTP Request interface (library-agnostic)
20
+ */
21
+ export interface HTTPRequest {
22
+ method: string;
23
+ path: string;
24
+ headers: Record<string, string>;
25
+ query: Record<string, string>;
26
+ body?: unknown;
27
+ }
28
+ /**
29
+ * HTTP Response interface (library-agnostic)
30
+ */
31
+ export interface HTTPResponse {
32
+ status: number;
33
+ headers: Record<string, string>;
34
+ body: string;
35
+ }
36
+ /**
37
+ * Request handler type
38
+ */
39
+ export type RequestHandler = (request: HTTPRequest) => Promise<HTTPResponse>;
40
+ /**
41
+ * Server adapter interface
42
+ *
43
+ * Implement this interface to integrate with your chosen HTTP server library.
44
+ */
45
+ export interface ServerAdapter {
46
+ /** Start the server */
47
+ start(port: number, handler: RequestHandler): Promise<void>;
48
+ /** Stop the server */
49
+ stop(): Promise<void>;
50
+ /** Check if server is running */
51
+ isRunning(): boolean;
52
+ }
53
+ /**
54
+ * WebSocket-aware server adapter interface.
55
+ *
56
+ * Extends ServerAdapter with callbacks for WebSocket connections.
57
+ * The adapter manages the raw TCP/WS layer; these callbacks let the
58
+ * UI Bridge server handle message routing and event broadcasting.
59
+ */
60
+ export interface WebSocketServerAdapter extends ServerAdapter {
61
+ /** Called when a JSON text frame is received from a WS client. Returns response string or null. */
62
+ onWebSocketMessage?: (connId: string, message: string) => Promise<string | null>;
63
+ /** Called when a new WS connection is established after the HTTP 101 upgrade. */
64
+ onWebSocketConnect?: (connId: string) => void;
65
+ /** Called when a WS connection is closed or drops. */
66
+ onWebSocketDisconnect?: (connId: string) => void;
67
+ /** Send a message to a specific WS connection by ID. */
68
+ sendToConnection?: (connId: string, message: string) => void;
69
+ /** Send a message to all connected WS clients. */
70
+ broadcast?: (message: string) => void;
71
+ }
72
+ /**
73
+ * Native UI Bridge HTTP Server
74
+ */
75
+ export declare class NativeUIBridgeServer {
76
+ private registry;
77
+ private executor;
78
+ private config;
79
+ private handlers;
80
+ private adapter?;
81
+ private running;
82
+ /**
83
+ * Per-connection cleanup thunks for in-flight waiters (waitForElement,
84
+ * waitForCondition, ...). Aborted when a client disconnects so the
85
+ * underlying timers/listeners don't leak.
86
+ */
87
+ private pendingWaiters;
88
+ constructor(registry: NativeUIBridgeRegistry, executor: NativeActionExecutor, config?: NativeServerConfig);
89
+ /**
90
+ * Set the server adapter
91
+ */
92
+ setAdapter(adapter: ServerAdapter): void;
93
+ /**
94
+ * Set a navigation provider for programmatic route navigation.
95
+ * This enables `control/page/navigate` and `control/page/back` on native.
96
+ */
97
+ setNavigationProvider(provider: NavigationProvider): void;
98
+ /**
99
+ * Set a route provider for reporting the current navigation route.
100
+ * When set, `control/snapshot` responses include `currentRoute` and `segments`.
101
+ */
102
+ setRouteProvider(provider: RouteProvider): void;
103
+ /**
104
+ * Set a screenshot provider for native screen capture.
105
+ * This enables `control/screenshot` on native.
106
+ */
107
+ setScreenshotProvider(provider: ScreenshotProvider): void;
108
+ /**
109
+ * Start the HTTP server
110
+ */
111
+ start(): Promise<void>;
112
+ /**
113
+ * Stop the HTTP server
114
+ */
115
+ stop(): Promise<void>;
116
+ /**
117
+ * Check if server is running
118
+ */
119
+ isRunning(): boolean;
120
+ private eventBridge?;
121
+ /**
122
+ * Set the event bridge for WebSocket event broadcasting and subscriptions.
123
+ */
124
+ setEventBridge(bridge: WebSocketEventBridge): void;
125
+ /**
126
+ * Handle a JSON-RPC message from a WebSocket client.
127
+ * Parses the message, routes to the appropriate handler, and returns
128
+ * a JSON string response (or null for events that need no response).
129
+ */
130
+ handleWebSocketMessage(connId: string, rawMessage: string): Promise<string | null>;
131
+ /**
132
+ * Execute a batch of JSON-RPC requests concurrently.
133
+ */
134
+ handleBatchRequest(batch: JsonRpcRequest[]): Promise<JsonRpcResponse[]>;
135
+ /**
136
+ * Register an in-flight waiter's cleanup thunk under the given connection.
137
+ * Returns an `unregister` thunk that the natural-resolution path should
138
+ * call so the cleanup isn't re-invoked on disconnect.
139
+ */
140
+ private registerWaiter;
141
+ /**
142
+ * Abort all pending waiters associated with a connection. Called by the
143
+ * provider's WS disconnect handler so timers/listeners don't leak after
144
+ * the client goes away.
145
+ */
146
+ abortWaitersForConnection(connId: string): void;
147
+ /**
148
+ * Wait for an element to be registered, or resolve immediately if it already exists.
149
+ * Returns a JsonRpcResponse JSON string.
150
+ */
151
+ private handleWaitForElement;
152
+ /**
153
+ * Wait for an arbitrary element-state predicate to become true.
154
+ *
155
+ * Supported `condition` shapes:
156
+ * {field: "mounted"|"visible"|"enabled"|"focused", equals: boolean}
157
+ * {field: "layout", exists: true}
158
+ * {field: string, equals: unknown} // generic: state[field] === equals
159
+ *
160
+ * Resolves immediately with `waited:false` if the predicate already
161
+ * holds. Otherwise subscribes to `element:registered` and
162
+ * `element:stateChanged` until the predicate matches or timeout fires.
163
+ */
164
+ private handleWaitForCondition;
165
+ /**
166
+ * Execute a sequence of JSON-RPC steps in order, stopping on first failure.
167
+ * Returns a JsonRpcResponse JSON string with per-step results.
168
+ */
169
+ private handleSequence;
170
+ /**
171
+ * Route a JSON-RPC method string to the appropriate handler using path-style matching.
172
+ *
173
+ * Method strings mirror HTTP routes but without the /ui-bridge/ prefix.
174
+ * Path params are extracted from :name placeholders in the route pattern.
175
+ *
176
+ * Examples:
177
+ * "health" → handlers.health
178
+ * "control/snapshot" → handlers.getSnapshot
179
+ * "control/element/tab-runs/action" → handlers.executeAction ({id:'tab-runs'})
180
+ * "control/component/my-comp/action/submit" → handlers.executeComponentAction
181
+ */
182
+ private routeMethodToHandler;
183
+ /**
184
+ * Handle incoming HTTP request
185
+ *
186
+ * Exposed as public so that CloudRelayClient can call it directly (without
187
+ * loopback TCP overhead) when processing tunneled requests.
188
+ */
189
+ handleRequest(request: HTTPRequest): Promise<HTTPResponse>;
190
+ /**
191
+ * Route an HTTP request to the appropriate handler using WS_ROUTES.
192
+ *
193
+ * Strips the `/ui-bridge/` prefix from the path, then iterates the shared
194
+ * WS_ROUTES table. Each route's `pattern` is matched against the stripped
195
+ * path via the module-level `parsePath` helper; path params are merged
196
+ * with the request body into a HandlerContext.
197
+ *
198
+ * `httpMethods` disambiguates routes that share a pattern but differ
199
+ * by verb (e.g. GET vs DELETE on `design/style-guide`). A route without
200
+ * `httpMethods` is WS-only and will not be matched on HTTP.
201
+ */
202
+ private routeRequest;
203
+ }
204
+ /**
205
+ * Create a UI Bridge Native server
206
+ */
207
+ export declare function createNativeServer(registry: NativeUIBridgeRegistry, executor: NativeActionExecutor, config?: NativeServerConfig): NativeUIBridgeServer;
208
+ /**
209
+ * Example adapter using react-native-http-bridge
210
+ *
211
+ * To use this adapter:
212
+ * 1. Install: npm install react-native-http-bridge
213
+ * 2. Link native modules
214
+ * 3. Create adapter and pass to server
215
+ *
216
+ * ```tsx
217
+ * import httpBridge from 'react-native-http-bridge';
218
+ *
219
+ * const adapter: ServerAdapter = {
220
+ * start: async (port, handler) => {
221
+ * httpBridge.start(port, 'ui-bridge', async (request) => {
222
+ * const response = await handler({
223
+ * method: request.type,
224
+ * path: request.url,
225
+ * headers: request.headers || {},
226
+ * query: parseQuery(request.url),
227
+ * body: request.postData ? JSON.parse(request.postData) : undefined,
228
+ * });
229
+ * httpBridge.respond(
230
+ * request.requestId,
231
+ * response.status,
232
+ * response.headers['Content-Type'],
233
+ * response.body
234
+ * );
235
+ * });
236
+ * },
237
+ * stop: async () => {
238
+ * httpBridge.stop();
239
+ * },
240
+ * isRunning: () => true,
241
+ * };
242
+ *
243
+ * server.setAdapter(adapter);
244
+ * await server.start();
245
+ * ```
246
+ */
247
+ //# sourceMappingURL=http-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/server/http-server.ts"],"names":[],"mappings":"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"}
@@ -1,119 +1,15 @@
1
- import { h as NativeServerHandlers, b as HandlerContext, A as APIResponse } from '../http-server-B7KudcYJ.js';
2
- export { H as HTTPRequest, a as HTTPResponse, c as HandlerFunction, J as JsonRpcBatchRequest, d as JsonRpcBatchResponse, r as JsonRpcClientMessage, e as JsonRpcEvent, f as JsonRpcRequest, g as JsonRpcResponse, s as JsonRpcServerMessage, t as JsonRpcSubscribe, u as JsonRpcUnsubscribe, N as NativeServerConfig, i as NativeUIBridgeServer, j as NavigationProvider, R as RequestHandler, k as RouteDefinition, l as RouteProvider, S as ScreenshotProvider, m as ServerAdapter, U as UI_BRIDGE_NATIVE_ROUTES, W as WebSocketConnection, n as WebSocketEventBridge, o as WebSocketMessageHandler, p as WebSocketServerAdapter, q as createNativeServer, v as isBatchRequest, w as isSubscribe, x as isUnsubscribe } from '../http-server-B7KudcYJ.js';
3
- import { a as NativeUIBridgeRegistry } from '../registry-B8A_EoxS.js';
4
- import { N as NativeActionExecutor } from '../types-BCYWwyVy.js';
5
- import { E as ElementDesignData, S as StateStyles, R as ResponsiveSnapshot } from '../design-types-BHr6Q1FX.js';
6
- import '../types-BPNuYxDx.js';
7
-
8
1
  /**
9
- * UI Bridge Native Server Handlers
2
+ * UI Bridge Native - Server
10
3
  *
11
- * Request handlers for the HTTP API endpoints.
12
- */
13
-
14
- /**
15
- * Create server handlers
16
- */
17
- declare function createServerHandlers(registry: NativeUIBridgeRegistry, executor: NativeActionExecutor, config?: {
18
- appInfo?: {
19
- appId: string;
20
- appName: string;
21
- appType: string;
22
- framework?: string;
23
- };
24
- }): NativeServerHandlers;
25
-
26
- /**
27
- * Pure-JS RFC 6455 WebSocket protocol implementation.
28
- *
29
- * Provides frame encoding/decoding and handshake utilities for running
30
- * a WebSocket server on react-native-tcp-socket without native crypto deps.
31
- */
32
- declare const OPCODE_CONTINUATION = 0;
33
- declare const OPCODE_TEXT = 1;
34
- declare const OPCODE_BINARY = 2;
35
- declare const OPCODE_CLOSE = 8;
36
- declare const OPCODE_PING = 9;
37
- declare const OPCODE_PONG = 10;
38
- interface DecodedFrame {
39
- opcode: number;
40
- fin: boolean;
41
- payload: Uint8Array;
42
- masked: boolean;
43
- }
44
- interface DecodeResult {
45
- frames: DecodedFrame[];
46
- remainder: Uint8Array<any>;
47
- }
48
- /**
49
- * Compute the Sec-WebSocket-Accept value from the client's Sec-WebSocket-Key.
50
- */
51
- declare function computeAcceptKey(clientKey: string): string;
52
- /**
53
- * Build the HTTP 101 Switching Protocols response for a WebSocket upgrade.
54
- */
55
- declare function buildUpgradeResponse(clientKey: string): string;
56
- /** Encode a text message as a WebSocket frame. */
57
- declare function encodeTextFrame(text: string): Uint8Array;
58
- /** Encode a PING frame with optional payload. */
59
- declare function encodePingFrame(payload?: Uint8Array): Uint8Array;
60
- /** Encode a PONG frame with the payload from the PING. */
61
- declare function encodePongFrame(payload: Uint8Array): Uint8Array;
62
- /** Encode a CLOSE frame with optional status code and reason. */
63
- declare function encodeCloseFrame(code?: number, reason?: string): Uint8Array;
64
- /**
65
- * Decode one or more WebSocket frames from a byte buffer.
66
- * Returns decoded frames and any unconsumed bytes (for partial frames).
67
- */
68
- declare function decodeFrames(buffer: Uint8Array): DecodeResult;
69
- /**
70
- * Decode a text payload from a Uint8Array.
71
- */
72
- declare function decodeTextPayload(payload: Uint8Array): string;
73
-
74
- /**
75
- * UI Bridge Native Design Review Handlers
76
- *
77
- * HTTP handlers for the 8 design review endpoints.
78
- * Maps registered element styles to the web SDK's design data format.
79
- */
80
-
81
- /**
82
- * Design handler interface (subset of NativeServerHandlers)
83
- */
84
- interface NativeDesignHandlers {
85
- getElementStyles: (ctx: HandlerContext) => Promise<APIResponse<ElementDesignData>>;
86
- getElementStateStyles: (ctx: HandlerContext) => Promise<APIResponse<{
87
- elementId: string;
88
- stateStyles: StateStyles[];
89
- }>>;
90
- getDesignSnapshot: (ctx: HandlerContext) => Promise<APIResponse<{
91
- elements: ElementDesignData[];
92
- timestamp: number;
93
- }>>;
94
- getResponsiveSnapshots: (ctx: HandlerContext) => Promise<APIResponse<ResponsiveSnapshot[]>>;
95
- runDesignAudit: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;
96
- loadStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{
97
- loaded: boolean;
98
- }>>;
99
- getStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;
100
- clearStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{
101
- cleared: boolean;
102
- }>>;
103
- evaluateQuality: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;
104
- getQualityContexts: (ctx: HandlerContext) => Promise<APIResponse<Array<{
105
- name: string;
106
- description: string;
107
- }>>>;
108
- saveBaseline: (ctx: HandlerContext) => Promise<APIResponse<{
109
- saved: boolean;
110
- elementCount: number;
111
- }>>;
112
- diffBaseline: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;
113
- }
114
- /**
115
- * Create design review handlers.
116
- */
117
- declare function createDesignHandlers(registry: NativeUIBridgeRegistry): NativeDesignHandlers;
118
-
119
- export { APIResponse, type DecodeResult, type DecodedFrame, HandlerContext, type NativeDesignHandlers, NativeServerHandlers, OPCODE_BINARY, OPCODE_CLOSE, OPCODE_CONTINUATION, OPCODE_PING, OPCODE_PONG, OPCODE_TEXT, buildUpgradeResponse, computeAcceptKey, createDesignHandlers, createServerHandlers, decodeFrames, decodeTextPayload, encodeCloseFrame, encodePingFrame, encodePongFrame, encodeTextFrame };
4
+ * HTTP and WebSocket server for external control of native apps.
5
+ */
6
+ export * from './types';
7
+ export * from './handlers';
8
+ export * from './design-handlers';
9
+ export * from './http-server';
10
+ export * from './ws-protocol';
11
+ export * from './ws-types';
12
+ export { WebSocketConnection } from './ws-connection';
13
+ export type { WebSocketMessageHandler } from './ws-connection';
14
+ export { WebSocketEventBridge } from './ws-event-bridge';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1104,6 +1104,10 @@ var WS_ROUTES = [
1104
1104
  { pattern: "health", handler: "health", httpMethods: ["GET"] },
1105
1105
  // Elements
1106
1106
  { pattern: "control/elements", handler: "getElements", httpMethods: ["GET"] },
1107
+ // Flat alias — matches the runner UI Bridge's `/ui-bridge/elements` path so
1108
+ // agents can use the same URL across runner + mobile without remembering
1109
+ // the `control/` prefix. Delegates to the same handler.
1110
+ { pattern: "elements", handler: "getElements", httpMethods: ["GET"] },
1107
1111
  { pattern: "control/element/:id", handler: "getElement", httpMethods: ["GET"] },
1108
1112
  { pattern: "control/element/:id/state", handler: "getElementState", httpMethods: ["GET"] },
1109
1113
  { pattern: "control/element/:id/action", handler: "executeAction", httpMethods: ["POST"] },
@@ -1154,6 +1158,87 @@ var WS_ROUTES = [
1154
1158
  // Meta / Introspection
1155
1159
  { pattern: "meta/methods", handler: "getMethods", httpMethods: ["GET"] }
1156
1160
  ];
1161
+ var HANDLER_DESCRIPTIONS = {
1162
+ health: "Liveness probe; returns app metadata + element count",
1163
+ getElements: "Flat list of registered UI elements",
1164
+ getElement: "Single element by id",
1165
+ getElementState: "Dynamic state (value, focused, checked) for one element",
1166
+ executeAction: 'Run an action on an element (see "actions" below for names)',
1167
+ getComponents: "Higher-level components with action schemas",
1168
+ getComponent: "Component detail + per-action paramSchema",
1169
+ executeComponentAction: "Invoke a component action directly (preferred over button clicks)",
1170
+ find: "AI-powered element search by natural-language query",
1171
+ getSnapshot: "Full snapshot: elements + route + state. Supports ?visibleOnly=true and ?currentRouteOnly=true",
1172
+ getWorkflows: "List registered workflows",
1173
+ runWorkflow: "Trigger a workflow by id",
1174
+ pageRefresh: "Reload the current route",
1175
+ pageNavigate: "Imperative router.push(url) \u2014 preferred over tapping tab buttons",
1176
+ pageReplace: "router.replace(url)",
1177
+ pageGoBack: "router.back()",
1178
+ pageGoForward: "router.forward()",
1179
+ getScreenshot: "PNG screenshot of the current screen",
1180
+ getElementStyles: "Computed styles for an element (design review)",
1181
+ getElementStateStyles: "Computed styles per interaction state (hover/focus/disabled)",
1182
+ getDesignSnapshot: "Visual + style snapshot for design review",
1183
+ getResponsiveSnapshots: "Screenshots at multiple viewport widths",
1184
+ runDesignAudit: "Accessibility + visual audit",
1185
+ loadStyleGuide: "Load a design system style guide",
1186
+ getStyleGuide: "Fetch the currently loaded style guide",
1187
+ clearStyleGuide: "Unload the style guide",
1188
+ evaluateQuality: "Score the current UI against a quality context",
1189
+ getQualityContexts: "List available quality evaluation contexts",
1190
+ saveBaseline: "Save a quality baseline snapshot",
1191
+ diffBaseline: "Diff current UI against a saved baseline",
1192
+ getMethods: "List every handler name (legacy introspection)"
1193
+ };
1194
+ var ACTION_REFERENCE = [
1195
+ { name: "press", aliases: ["click"], params: "PressActionParams (optional position)" },
1196
+ { name: "longPress", params: "PressActionParams (optional position)" },
1197
+ { name: "doubleTap", params: "none" },
1198
+ {
1199
+ name: "type",
1200
+ params: "TypeActionParams { text, delay?, clear? | clearFirst? } \u2014 `clear:true` replaces content atomically"
1201
+ },
1202
+ { name: "clear", params: "none \u2014 empties the input" },
1203
+ { name: "focus", params: "none" },
1204
+ { name: "blur", params: "none" },
1205
+ { name: "scroll", params: "ScrollActionParams { offset? {x,y}, to? }" },
1206
+ { name: "swipe", params: "SwipeActionParams { direction, distance }" },
1207
+ { name: "toggle", params: "none \u2014 flips boolean controls" }
1208
+ ];
1209
+ function buildRoutesPayload() {
1210
+ const entries = [];
1211
+ for (const r of WS_ROUTES) {
1212
+ if (!r.httpMethods) continue;
1213
+ for (const m of r.httpMethods) {
1214
+ entries.push({ method: m, path: `/ui-bridge/${r.pattern}` });
1215
+ }
1216
+ }
1217
+ entries.push({ method: "GET", path: "/ui-bridge/_help" });
1218
+ entries.push({ method: "GET", path: "/ui-bridge/_routes" });
1219
+ entries.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
1220
+ return { routes: entries, count: entries.length };
1221
+ }
1222
+ function buildHelpPayload() {
1223
+ return {
1224
+ version: 1,
1225
+ description: "UI Bridge Native HTTP surface. Prefix every path with /ui-bridge/.",
1226
+ routes: WS_ROUTES.map((r) => ({
1227
+ pattern: r.pattern,
1228
+ httpMethods: r.httpMethods ?? [],
1229
+ wsOnly: !r.httpMethods,
1230
+ handler: r.handler,
1231
+ description: HANDLER_DESCRIPTIONS[r.handler] ?? ""
1232
+ })),
1233
+ actions: ACTION_REFERENCE,
1234
+ tips: [
1235
+ "Start with `GET /ui-bridge/control/snapshot?visibleOnly=true` to see what the user actually sees.",
1236
+ "Prefer `control/component/:id/action/:actionId` over button presses \u2014 typed paramSchema, no button-id guessing.",
1237
+ "Use `pageNavigate` for tab switches instead of pressing tab buttons; gesture state often swallows clicks.",
1238
+ "The `type` action supports `clear:true` to replace existing text atomically in one call."
1239
+ ]
1240
+ };
1241
+ }
1157
1242
  var NativeUIBridgeServer = class {
1158
1243
  constructor(registry, executor, config = {}) {
1159
1244
  this.registry = registry;
@@ -1170,7 +1255,9 @@ var NativeUIBridgeServer = class {
1170
1255
  cors: true,
1171
1256
  ...config
1172
1257
  };
1173
- this.handlers = createServerHandlers(registry, executor);
1258
+ this.handlers = createServerHandlers(registry, executor, {
1259
+ appInfo: this.config.appInfo
1260
+ });
1174
1261
  this.handlers.getMethods = async () => {
1175
1262
  const methods = WS_ROUTES.map((r) => ({
1176
1263
  method: r.pattern,
@@ -1974,6 +2061,20 @@ var NativeUIBridgeServer = class {
1974
2061
  };
1975
2062
  }
1976
2063
  const stripped = path.slice(PREFIX.length);
2064
+ if (method === "GET" && stripped === "_help") {
2065
+ return {
2066
+ success: true,
2067
+ data: buildHelpPayload(),
2068
+ timestamp: Date.now()
2069
+ };
2070
+ }
2071
+ if (method === "GET" && stripped === "_routes") {
2072
+ return {
2073
+ success: true,
2074
+ data: buildRoutesPayload(),
2075
+ timestamp: Date.now()
2076
+ };
2077
+ }
1977
2078
  let patternMatchedButWrongVerb = false;
1978
2079
  for (const route of WS_ROUTES) {
1979
2080
  const pathParams = parsePath(route.pattern, stripped);