@qontinui/ui-bridge-native 0.5.1 → 0.6.2

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.
@@ -139,6 +139,31 @@ var UI_BRIDGE_NATIVE_ROUTES = {
139
139
  path: "/ui-bridge/ai/fill-form",
140
140
  description: "Fill multiple input elements in a single call"
141
141
  },
142
+ // AI helpers (NOT_SUPPORTED stubs) — these endpoints exist on the runner-side
143
+ // UI Bridge surface but have no analog on mobile React Native. The mobile
144
+ // bridge registers explicit stubs so callers get a structured NOT_SUPPORTED
145
+ // envelope instead of a confusing HTTP 404. The mobile bridge's snapshot +
146
+ // `/control/find` already cover what an operator would reach for these for.
147
+ AI_FORMS: {
148
+ method: "GET",
149
+ path: "/ui-bridge/ai/forms",
150
+ description: "Discover forms (runner-only; mobile returns NOT_SUPPORTED)"
151
+ },
152
+ AI_IDLE_STATUS: {
153
+ method: "GET",
154
+ path: "/ui-bridge/ai/idle-status",
155
+ description: "Get page-idle signal (runner-only; mobile returns NOT_SUPPORTED)"
156
+ },
157
+ AI_CHANGE_BUFFER_ENABLE: {
158
+ method: "POST",
159
+ path: "/ui-bridge/ai/change-buffer/enable",
160
+ description: "Enable DOM change buffer (runner-only; mobile returns NOT_SUPPORTED)"
161
+ },
162
+ AI_WAIT_FOR_ELEMENT: {
163
+ method: "POST",
164
+ path: "/ui-bridge/ai/wait-for-element",
165
+ description: "Wait for element predicate via HTTP (runner-only; mobile returns NOT_SUPPORTED \u2014 use WS waitForElement instead)"
166
+ },
142
167
  // Test hooks — drive ModalDetector state from outside the React tree
143
168
  // (gated by `features.testHooks`). Mirrors `pushModal` / `dismissModal`
144
169
  // calls that components normally make in-process.
@@ -845,22 +870,25 @@ function createServerHandlers(registry, executor, config) {
845
870
  getElements: async (ctx) => {
846
871
  const visibleOnly = ctx.query?.visibleOnly === "true" || ctx.body?.visibleOnly === true;
847
872
  const forRoute = ctx.query?.route || ctx.body?.route;
848
- let allElements = visibleOnly ? registry.getVisibleElements() : registry.getAllElements();
873
+ let allElements = visibleOnly ? registry.getMountedVisibleElements() : registry.getAllElements();
849
874
  if (forRoute) {
850
875
  allElements = allElements.filter((e) => e.registrationRoute === forRoute);
851
876
  }
852
877
  const elements = allElements.map((e) => {
853
878
  const handlers = extractHandlerNames(e.props);
879
+ const state = e.getState();
880
+ const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
854
881
  return {
855
882
  id: e.id,
856
883
  type: e.type,
857
884
  label: e.label,
858
885
  identifier: e.getIdentifier(),
859
- state: e.getState(),
886
+ state,
860
887
  actions: e.actions,
861
888
  customActions: e.customActions ? Object.keys(e.customActions) : void 0,
862
889
  registeredHandlers: handlers.length > 0 ? handlers : void 0,
863
- registrationRoute: e.registrationRoute
890
+ registrationRoute: e.registrationRoute,
891
+ visibility
864
892
  };
865
893
  });
866
894
  return success2({ elements });
@@ -1123,6 +1151,37 @@ function createServerHandlers(registry, executor, config) {
1123
1151
  "NOT_SUPPORTED"
1124
1152
  );
1125
1153
  },
1154
+ // AI helpers — runner-only endpoints that have no React Native analog.
1155
+ //
1156
+ // The mobile bridge mounts explicit NOT_SUPPORTED stubs at the runner's
1157
+ // cheatsheet paths so callers (and the /manual-test skill in particular)
1158
+ // get a structured envelope explaining the gap rather than a confusing
1159
+ // HTTP 404. Each error message names an in-tree mobile replacement so
1160
+ // operators aren't left guessing what to use instead.
1161
+ aiForms: async () => {
1162
+ return error2(
1163
+ 'ai/forms (form discovery) is runner-only; mobile React Native has no DOM to walk. Use GET /ui-bridge/control/snapshot and filter for type === "input" instead.',
1164
+ "NOT_SUPPORTED"
1165
+ );
1166
+ },
1167
+ aiIdleStatus: async () => {
1168
+ return error2(
1169
+ 'ai/idle-status (page-idle signal) is runner-only; mobile React Native has no DOM-mutation / network-idle signals. Use the registry event stream (WS subscribe to "element:registered"/"element:stateChanged") or poll /control/snapshot for stability.',
1170
+ "NOT_SUPPORTED"
1171
+ );
1172
+ },
1173
+ aiChangeBufferEnable: async () => {
1174
+ return error2(
1175
+ 'ai/change-buffer (DOM mutation diff buffer) is runner-only; mobile React Native has no DOM. Use the WS event bridge (subscribe to "element:registered"/"element:unregistered"/"element:stateChanged") for change notifications.',
1176
+ "NOT_SUPPORTED"
1177
+ );
1178
+ },
1179
+ aiWaitForElement: async () => {
1180
+ return error2(
1181
+ 'POST /ai/wait-for-element is runner-only on mobile. Use the WS "waitForElement" JSON-RPC method or "waitForCondition" instead \u2014 same semantics, no HTTP polling overhead.',
1182
+ "NOT_SUPPORTED"
1183
+ );
1184
+ },
1126
1185
  // Meta / Introspection (stub — server constructor overrides with real route table)
1127
1186
  getMethods: async () => {
1128
1187
  return error2("Methods introspection not configured", "NOT_SUPPORTED");
@@ -1778,6 +1837,24 @@ var WS_ROUTES = [
1778
1837
  { pattern: "meta/methods", handler: "getMethods", httpMethods: ["GET"] },
1779
1838
  // AI helpers — mobile parity with the runner's `/ui-bridge/ai/*` family.
1780
1839
  { pattern: "ai/fill-form", handler: "fillForm", httpMethods: ["POST"] },
1840
+ // AI helpers — NOT_SUPPORTED stubs. These endpoints exist on the runner-side
1841
+ // UI Bridge surface (and the /manual-test skill's cheatsheet documents them
1842
+ // as if they're universally available). Mobile React Native has no DOM, so
1843
+ // the mobile bridge mounts explicit stubs so callers get a structured
1844
+ // NOT_SUPPORTED envelope (with a hint pointing at the mobile-native
1845
+ // replacement) instead of a confusing HTTP 404.
1846
+ { pattern: "ai/forms", handler: "aiForms", httpMethods: ["GET"] },
1847
+ { pattern: "ai/idle-status", handler: "aiIdleStatus", httpMethods: ["GET"] },
1848
+ {
1849
+ pattern: "ai/change-buffer/enable",
1850
+ handler: "aiChangeBufferEnable",
1851
+ httpMethods: ["POST"]
1852
+ },
1853
+ {
1854
+ pattern: "ai/wait-for-element",
1855
+ handler: "aiWaitForElement",
1856
+ httpMethods: ["POST"]
1857
+ },
1781
1858
  // Coord-based tap — synthesizes a press at the given screen coords by
1782
1859
  // matching against registered elements' layout rects.
1783
1860
  { pattern: "control/tap", handler: "tapAt", httpMethods: ["POST"] },
@@ -1850,6 +1927,10 @@ var HANDLER_DESCRIPTIONS = {
1850
1927
  diffBaseline: "Diff current UI against a saved baseline",
1851
1928
  getMethods: "List every handler name (legacy introspection)",
1852
1929
  fillForm: "Fill multiple inputs in one call: body { fields: [{elementId, value}] } \u2014 each field dispatches `type` + `clear:true`",
1930
+ aiForms: 'STUB \u2014 runner-only; mobile returns NOT_SUPPORTED. Use /control/snapshot + filter type==="input" instead.',
1931
+ aiIdleStatus: "STUB \u2014 runner-only; mobile returns NOT_SUPPORTED. Subscribe to registry events over WS for change signals.",
1932
+ aiChangeBufferEnable: "STUB \u2014 runner-only; mobile returns NOT_SUPPORTED. Use WS event subscriptions for change notifications.",
1933
+ aiWaitForElement: "STUB \u2014 runner-only; mobile returns NOT_SUPPORTED. Use the WS waitForElement / waitForCondition JSON-RPC methods.",
1853
1934
  tapAt: "Synthesize a press at given screen coords by matching registered element layout rects: body { x, y, action? }",
1854
1935
  getConsoleErrors: "TEST HOOK \u2014 last-N console.error/console.warn entries; ?since=<ms>&limit=<n>",
1855
1936
  getNetworkRequests: "TEST HOOK \u2014 last-N fetch/XHR entries with status + duration; ?since=<ms>&limit=<n>",