wu-framework 1.2.1 → 2.1.0

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 (155) hide show
  1. package/README.md +99 -18
  2. package/dist/adapters/alpine/index.js +2 -0
  3. package/dist/adapters/alpine/index.js.map +1 -0
  4. package/dist/adapters/angular/index.js +2 -0
  5. package/dist/adapters/angular/index.js.map +1 -0
  6. package/dist/adapters/htmx/index.js +2 -0
  7. package/dist/adapters/htmx/index.js.map +1 -0
  8. package/dist/adapters/index.js +2 -0
  9. package/dist/adapters/index.js.map +1 -0
  10. package/dist/adapters/lit/index.js +44 -0
  11. package/dist/adapters/lit/index.js.map +1 -0
  12. package/dist/adapters/preact/index.js +2 -0
  13. package/dist/adapters/preact/index.js.map +1 -0
  14. package/dist/adapters/qwik/index.js +2 -0
  15. package/dist/adapters/qwik/index.js.map +1 -0
  16. package/dist/adapters/react/index.js +2 -0
  17. package/dist/adapters/react/index.js.map +1 -0
  18. package/dist/adapters/shared.js +2 -0
  19. package/dist/adapters/shared.js.map +1 -0
  20. package/dist/adapters/solid/index.js +2 -0
  21. package/dist/adapters/solid/index.js.map +1 -0
  22. package/dist/adapters/stencil/index.js +2 -0
  23. package/dist/adapters/stencil/index.js.map +1 -0
  24. package/dist/adapters/stimulus/index.js +2 -0
  25. package/dist/adapters/stimulus/index.js.map +1 -0
  26. package/dist/adapters/svelte/index.js +2 -0
  27. package/dist/adapters/svelte/index.js.map +1 -0
  28. package/dist/adapters/vanilla/index.js +2 -0
  29. package/dist/adapters/vanilla/index.js.map +1 -0
  30. package/dist/adapters/vue/index.js +2 -0
  31. package/dist/adapters/vue/index.js.map +1 -0
  32. package/dist/ai/wu-ai.js +2 -0
  33. package/dist/ai/wu-ai.js.map +1 -0
  34. package/dist/core/wu-mcp-bridge.js +2 -0
  35. package/dist/core/wu-mcp-bridge.js.map +1 -0
  36. package/{src → dist}/index.d.ts +445 -317
  37. package/dist/wu-ai-browser-primitives-BDKXJlwc.js +2 -0
  38. package/dist/wu-ai-browser-primitives-BDKXJlwc.js.map +1 -0
  39. package/dist/wu-framework.cjs.js +2 -2
  40. package/dist/wu-framework.cjs.js.map +1 -1
  41. package/dist/wu-framework.dev.js +2640 -9197
  42. package/dist/wu-framework.dev.js.map +1 -1
  43. package/dist/wu-framework.esm.js +2 -2
  44. package/dist/wu-framework.esm.js.map +1 -1
  45. package/dist/wu-framework.umd.js +2 -2
  46. package/dist/wu-framework.umd.js.map +1 -1
  47. package/dist/wu-html-parser.js +2 -0
  48. package/dist/wu-html-parser.js.map +1 -0
  49. package/dist/wu-iframe-sandbox.js +2 -0
  50. package/dist/wu-iframe-sandbox.js.map +1 -0
  51. package/dist/wu-logger-fJfUHBGA.js +2 -0
  52. package/dist/wu-logger-fJfUHBGA.js.map +1 -0
  53. package/dist/wu-script-executor.js +2 -0
  54. package/dist/wu-script-executor.js.map +1 -0
  55. package/package.json +43 -34
  56. package/src/adapters/alpine/index.js +0 -231
  57. package/src/adapters/alpine.js +0 -3
  58. package/src/adapters/angular/ai.js +0 -30
  59. package/src/adapters/angular/index.js +0 -932
  60. package/src/adapters/angular.js +0 -3
  61. package/src/adapters/htmx/index.js +0 -242
  62. package/src/adapters/htmx.js +0 -3
  63. package/src/adapters/index.js +0 -225
  64. package/src/adapters/lit/ai.js +0 -20
  65. package/src/adapters/lit/index.js +0 -721
  66. package/src/adapters/lit.js +0 -3
  67. package/src/adapters/preact/ai.js +0 -33
  68. package/src/adapters/preact/index.js +0 -661
  69. package/src/adapters/preact.js +0 -3
  70. package/src/adapters/qwik/index.js +0 -108
  71. package/src/adapters/qwik.js +0 -3
  72. package/src/adapters/react/ai.js +0 -135
  73. package/src/adapters/react/index.js +0 -695
  74. package/src/adapters/react.js +0 -3
  75. package/src/adapters/shared.js +0 -64
  76. package/src/adapters/solid/ai.js +0 -32
  77. package/src/adapters/solid/index.js +0 -586
  78. package/src/adapters/solid.js +0 -3
  79. package/src/adapters/stencil/index.js +0 -228
  80. package/src/adapters/stencil.js +0 -3
  81. package/src/adapters/stimulus/index.js +0 -255
  82. package/src/adapters/stimulus.js +0 -3
  83. package/src/adapters/svelte/ai.js +0 -31
  84. package/src/adapters/svelte/index.js +0 -798
  85. package/src/adapters/svelte.js +0 -3
  86. package/src/adapters/vanilla/ai.js +0 -30
  87. package/src/adapters/vanilla/index.js +0 -785
  88. package/src/adapters/vanilla.js +0 -3
  89. package/src/adapters/vue/ai.js +0 -52
  90. package/src/adapters/vue/index.js +0 -618
  91. package/src/adapters/vue.js +0 -3
  92. package/src/ai/wu-ai-actions.js +0 -261
  93. package/src/ai/wu-ai-agent.js +0 -546
  94. package/src/ai/wu-ai-browser-primitives.js +0 -354
  95. package/src/ai/wu-ai-browser.js +0 -380
  96. package/src/ai/wu-ai-context.js +0 -332
  97. package/src/ai/wu-ai-conversation.js +0 -613
  98. package/src/ai/wu-ai-orchestrate.js +0 -1021
  99. package/src/ai/wu-ai-permissions.js +0 -381
  100. package/src/ai/wu-ai-provider.js +0 -700
  101. package/src/ai/wu-ai-schema.js +0 -225
  102. package/src/ai/wu-ai-triggers.js +0 -396
  103. package/src/ai/wu-ai.js +0 -804
  104. package/src/core/wu-app.js +0 -236
  105. package/src/core/wu-cache.js +0 -498
  106. package/src/core/wu-core.js +0 -1412
  107. package/src/core/wu-error-boundary.js +0 -396
  108. package/src/core/wu-event-bus.js +0 -390
  109. package/src/core/wu-hooks.js +0 -350
  110. package/src/core/wu-html-parser.js +0 -199
  111. package/src/core/wu-iframe-sandbox.js +0 -328
  112. package/src/core/wu-loader.js +0 -450
  113. package/src/core/wu-logger.js +0 -143
  114. package/src/core/wu-manifest.js +0 -533
  115. package/src/core/wu-mcp-bridge.js +0 -432
  116. package/src/core/wu-overrides.js +0 -510
  117. package/src/core/wu-performance.js +0 -228
  118. package/src/core/wu-plugin.js +0 -401
  119. package/src/core/wu-prefetch.js +0 -414
  120. package/src/core/wu-proxy-sandbox.js +0 -477
  121. package/src/core/wu-sandbox.js +0 -779
  122. package/src/core/wu-script-executor.js +0 -161
  123. package/src/core/wu-sentinel-client.js +0 -311
  124. package/src/core/wu-snapshot-sandbox.js +0 -227
  125. package/src/core/wu-store.js +0 -307
  126. package/src/core/wu-strategies.js +0 -256
  127. package/src/core/wu-style-bridge.js +0 -477
  128. package/src/index.js +0 -234
  129. package/src/utils/dependency-resolver.js +0 -328
  130. /package/{src → dist}/adapters/alpine/index.d.ts +0 -0
  131. /package/{src → dist}/adapters/alpine.d.ts +0 -0
  132. /package/{src → dist}/adapters/angular/index.d.ts +0 -0
  133. /package/{src → dist}/adapters/angular.d.ts +0 -0
  134. /package/{src → dist}/adapters/htmx/index.d.ts +0 -0
  135. /package/{src → dist}/adapters/htmx.d.ts +0 -0
  136. /package/{src → dist}/adapters/lit/index.d.ts +0 -0
  137. /package/{src → dist}/adapters/lit.d.ts +0 -0
  138. /package/{src → dist}/adapters/preact/index.d.ts +0 -0
  139. /package/{src → dist}/adapters/preact.d.ts +0 -0
  140. /package/{src → dist}/adapters/qwik/index.d.ts +0 -0
  141. /package/{src → dist}/adapters/qwik.d.ts +0 -0
  142. /package/{src → dist}/adapters/react/index.d.ts +0 -0
  143. /package/{src → dist}/adapters/react.d.ts +0 -0
  144. /package/{src → dist}/adapters/solid/index.d.ts +0 -0
  145. /package/{src → dist}/adapters/solid.d.ts +0 -0
  146. /package/{src → dist}/adapters/stencil/index.d.ts +0 -0
  147. /package/{src → dist}/adapters/stencil.d.ts +0 -0
  148. /package/{src → dist}/adapters/stimulus/index.d.ts +0 -0
  149. /package/{src → dist}/adapters/stimulus.d.ts +0 -0
  150. /package/{src → dist}/adapters/svelte/index.d.ts +0 -0
  151. /package/{src → dist}/adapters/svelte.d.ts +0 -0
  152. /package/{src → dist}/adapters/vanilla/index.d.ts +0 -0
  153. /package/{src → dist}/adapters/vanilla.d.ts +0 -0
  154. /package/{src → dist}/adapters/vue/index.d.ts +0 -0
  155. /package/{src → dist}/adapters/vue.d.ts +0 -0
@@ -0,0 +1,2 @@
1
+ import{e,t,c as r,g as n,a as o,d as i,b as a}from"../wu-ai-browser-primitives-BDKXJlwc.js";import{l as s}from"../wu-logger-fJfUHBGA.js";function u(u){let c=null,d=null,m=0,l=!1,p=null;const f=u.eventBus?.getInternalToken?.("wu-mcp-bridge")||null,g=(e,t)=>u.eventBus?.emit(e,t,{appName:"wu-mcp-bridge",token:f}),w=[];function v(e){if(u.ai&&u.ai.permissions)return u.ai.permissions.check(e);return["readStore","executeActions"].includes(e)}function h(e,t,r){u.eventBus&&u.eventBus.emit("mcp:bridge:operation",{operation:e,params:t,result:r?.error?{error:r.error}:{success:!0},timestamp:Date.now()},{appName:"wu-mcp-bridge"})}u.eventBus&&u.eventBus.on("*",e=>{w.push({name:e.name,data:e.data,timestamp:e.timestamp||Date.now(),source:e.source||"unknown"}),w.length>200&&w.shift()}),e();const b={status:()=>({connected:!0,framework:"wu-framework",apps:N(),storeKeys:u.store?Object.keys(u.store.get("")||{}):[],actionsCount:u.ai?u.ai.tools().length:0,eventLogSize:w.length}),list_apps:()=>N(),list_events:({limit:e=20})=>w.slice(-e),list_actions(){if(!u.ai)return{actions:[],note:"wu.ai not initialized"};const e=u.ai.tools();return{actions:e,count:e.length}},snapshot({appName:e}){try{const t=e?document.querySelector(`[data-wu-app="${e}"]`)||document.querySelector(`#wu-app-${e}`):document.body;return t?{app:e||"(page)",snapshot:a(t,0,5),timestamp:Date.now()}:{error:`App "${e}" not found in DOM`}}catch(e){return{error:e.message}}},console:({level:e="all",limit:t=50})=>i(e,t),async screenshot({selector:e,quality:t=.8}){const r=await o(e,t);return r.error||(r.timestamp=Date.now()),r},network:({method:e,status:t,limit:r=50})=>n(e,t,r),get_state({path:e}){if(!u.store)return{error:"wu.store not available"};if(!v("readStore"))return{error:"Permission denied: readStore is disabled"};return{path:e||"(root)",value:u.store.get(e||"")}},set_state:({path:e,value:t})=>u.store?e?v("writeStore")?(u.store.set(e,t),h("set_state",{path:e,value:t},{}),{path:e,value:t,updated:!0}):(h("set_state",{path:e},{error:"Permission denied"}),{error:"Permission denied: writeStore is disabled"}):{error:"path is required"}:{error:"wu.store not available"},emit_event:({event:e,data:t})=>u.eventBus?e?v("emitEvents")?(g(e,t),h("emit_event",{event:e,data:t},{}),{emitted:e,data:t}):(h("emit_event",{event:e},{error:"Permission denied"}),{error:"Permission denied: emitEvents is disabled"}):{error:"event name is required"}:{error:"wu.eventBus not available"},navigate:({route:e})=>e?v("emitEvents")?(g("shell:navigate",{route:e}),u.store&&v("writeStore")&&u.store.set("currentPath",e),h("navigate",{route:e},{}),{navigated:e}):(h("navigate",{route:e},{error:"Permission denied: emitEvents"}),{error:"Permission denied: emitEvents is disabled"}):{error:"Route is required"},mount_app({appName:e,container:t}){if(!e)return{error:"appName is required"};if(!v("modifyDOM"))return h("mount_app",{appName:e},{error:"Permission denied"}),{error:"Permission denied: modifyDOM is disabled"};try{return u.mount?(u.mount(e,t),h("mount_app",{appName:e,container:t},{success:!0}),{mounted:e,container:t}):{error:"wu.mount not available"}}catch(e){return{error:e.message}}},unmount_app({appName:e}){if(!e)return{error:"appName is required"};if(!v("modifyDOM"))return h("unmount_app",{appName:e},{error:"Permission denied"}),{error:"Permission denied: modifyDOM is disabled"};try{return u.unmount?(u.unmount(e),h("unmount_app",{appName:e},{success:!0}),{unmounted:e}):{error:"wu.unmount not available"}}catch(e){return{error:e.message}}},click({selector:e,text:t}){if(!v("modifyDOM"))return{error:"Permission denied: modifyDOM is disabled"};const n=r(e,t);return h("click",{selector:e,text:t},n),n},type({selector:e,text:r,clear:n=!1,submit:o=!1}){if(!v("modifyDOM"))return{error:"Permission denied: modifyDOM is disabled"};const i=t(e,r,{clear:n,submit:o});return h("type",{selector:e,textLength:r?.length},i),i},async execute_action({action:e,params:t}){if(!u.ai)return{error:"wu.ai not available"};if(!e)return{error:"action name is required"};try{return{action:e,...await u.ai.execute(e,t||{})}}catch(e){return{error:e.message}}}};function y(e="ws://localhost:19100",t={}){if(c&&c.readyState<=1)s.warn("[wu-mcp-bridge] Already connected or connecting");else{p=t.token||null,l=!p;try{c=new WebSocket(e),c.onopen=()=>{s.debug("[wu-mcp-bridge] Connected to wu-mcp-server"),m=0,p&&c.send(JSON.stringify({type:"auth",token:p}))},c.onmessage=async e=>{try{const t=JSON.parse(e.data);if("auth_result"===t.type)return l=!0===t.success,void(l?s.debug("[wu-mcp-bridge] Authenticated successfully"):(console.error("[wu-mcp-bridge] Authentication failed:",t.reason||"Invalid token"),_()));if(!l)return void(t.id&&S(t.id,null,"Not authenticated. Send auth token first."));const{id:r,command:n,params:o}=t;if(!r||!n)return void s.warn("[wu-mcp-bridge] Invalid message:",t);const i=b[n];if(!i)return void S(r,null,`Unknown command: ${n}`);try{S(r,await i(o||{}))}catch(e){S(r,null,e.message)}}catch(e){console.error("[wu-mcp-bridge] Failed to handle message:",e)}},c.onclose=()=>{s.debug("[wu-mcp-bridge] Disconnected"),c=null,l=!1,k(e,t)},c.onerror=()=>{}}catch(r){console.error("[wu-mcp-bridge] Connection failed:",r.message),k(e,t)}}}function _(){d&&(clearTimeout(d),d=null),m=10,c&&(c.close(),c=null),l=!1}function S(e,t,r){if(!c||1!==c.readyState)return;const n=r?{id:e,error:r}:{id:e,result:t};c.send(JSON.stringify(n))}function k(e,t){if(m>=10)return;m++;const r=2e3*Math.min(m,5);d=setTimeout(()=>y(e,t),r)}function N(){const e=[];if(u._apps)for(const[t,r]of Object.entries(u._apps))e.push({name:t,mounted:r.mounted||r.isMounted||!1,url:r.url||r.info?.url||"",status:r.status||r.info?.status||"unknown"});return 0===e.length&&document.querySelectorAll("[data-wu-app]").forEach(t=>{e.push({name:t.getAttribute("data-wu-app"),mounted:!0,container:`#${t.id||"(no-id)"}`})}),e}return{connect:y,disconnect:_,isConnected:function(){return null!==c&&1===c.readyState&&l}}}export{u as createMcpBridge};
2
+ //# sourceMappingURL=wu-mcp-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wu-mcp-bridge.js","sources":["../../src/core/wu-mcp-bridge.js"],"sourcesContent":["/**\r\n * WU-MCP Bridge (Browser Side)\r\n *\r\n * Connects to the wu-mcp-server via WebSocket and executes\r\n * commands using wu.* APIs. This is the \"eyes and hands\" of\r\n * the MCP server inside the browser.\r\n *\r\n * Security:\r\n * - Optional auth token sent on first message (handshake)\r\n * - All state/event/mount operations check wu.ai permissions\r\n * - Mutating operations emit audit events\r\n * - Read-only operations (status, list_apps, snapshot, console, network) are unrestricted\r\n *\r\n * @example\r\n * // Connect with auth token\r\n * wu.mcp.connect('ws://localhost:19100', { token: 'my-secret' });\r\n *\r\n * // Connect without auth (development only)\r\n * wu.mcp.connect();\r\n */\r\n\r\nimport {\r\n ensureInterceptors,\r\n networkLog,\r\n consoleLog,\r\n captureScreenshot,\r\n buildA11yTree,\r\n clickElement,\r\n typeIntoElement,\r\n getFilteredNetwork,\r\n getFilteredConsole,\r\n} from '../ai/wu-ai-browser-primitives.js';\r\nimport { logger } from './wu-logger.js';\r\n\r\n/**\r\n * Create the MCP bridge for a Wu instance.\r\n *\r\n * @param {object} wu - The Wu Framework instance (window.wu)\r\n * @returns {object} Bridge API: { connect, disconnect, isConnected }\r\n */\r\nexport function createMcpBridge(wu) {\r\n let ws = null;\r\n let reconnectTimer = null;\r\n let reconnectAttempts = 0;\r\n let authenticated = false;\r\n let authToken = null;\r\n const MAX_RECONNECT_ATTEMPTS = 10;\r\n const RECONNECT_DELAY = 2000;\r\n\r\n // Closure-capture our internal token. Required so strictMode accepts\r\n // emits as appName='wu-mcp-bridge' (and rejects spoofers under the same name).\r\n const _bridgeToken = wu.eventBus?.getInternalToken?.('wu-mcp-bridge') || null;\r\n const _emitInternal = (event, data) =>\r\n wu.eventBus?.emit(event, data, { appName: 'wu-mcp-bridge', token: _bridgeToken });\r\n\r\n // Event log for wu_list_events\r\n const eventLog = [];\r\n const MAX_EVENT_LOG = 200;\r\n\r\n // Capture events for history\r\n if (wu.eventBus) {\r\n wu.eventBus.on('*', (event) => {\r\n eventLog.push({\r\n name: event.name,\r\n data: event.data,\r\n timestamp: event.timestamp || Date.now(),\r\n source: event.source || 'unknown',\r\n });\r\n if (eventLog.length > MAX_EVENT_LOG) eventLog.shift();\r\n });\r\n }\r\n\r\n // Install shared interceptors (idempotent — safe if wu-ai-browser already did it)\r\n ensureInterceptors();\r\n\r\n // ── Permission helpers ──\r\n\r\n /**\r\n * Check a permission flag via wu.ai.permissions if available.\r\n * Falls back to deny if wu.ai is not initialized.\r\n */\r\n function _checkPermission(perm) {\r\n if (wu.ai && wu.ai.permissions) {\r\n return wu.ai.permissions.check(perm);\r\n }\r\n // If AI module not initialized, deny write operations, allow reads\r\n const readPerms = ['readStore', 'executeActions'];\r\n return readPerms.includes(perm);\r\n }\r\n\r\n /**\r\n * Emit an audit event for bridge operations.\r\n */\r\n function _audit(operation, params, result) {\r\n if (wu.eventBus) {\r\n wu.eventBus.emit('mcp:bridge:operation', {\r\n operation,\r\n params,\r\n result: result?.error ? { error: result.error } : { success: true },\r\n timestamp: Date.now(),\r\n }, { appName: 'wu-mcp-bridge' });\r\n }\r\n }\r\n\r\n // ── Command handlers ──\r\n\r\n const handlers = {\r\n // ── Read-only operations (no permission gates) ──\r\n\r\n status() {\r\n return {\r\n connected: true,\r\n framework: 'wu-framework',\r\n apps: _getAppList(),\r\n storeKeys: wu.store ? Object.keys(wu.store.get('') || {}) : [],\r\n actionsCount: wu.ai ? wu.ai.tools().length : 0,\r\n eventLogSize: eventLog.length,\r\n };\r\n },\r\n\r\n list_apps() {\r\n return _getAppList();\r\n },\r\n\r\n list_events({ limit = 20 }) {\r\n return eventLog.slice(-limit);\r\n },\r\n\r\n list_actions() {\r\n if (!wu.ai) return { actions: [], note: 'wu.ai not initialized' };\r\n const tools = wu.ai.tools();\r\n return { actions: tools, count: tools.length };\r\n },\r\n\r\n snapshot({ appName }) {\r\n try {\r\n const target = appName\r\n ? document.querySelector(`[data-wu-app=\"${appName}\"]`) || document.querySelector(`#wu-app-${appName}`)\r\n : document.body;\r\n\r\n if (!target) return { error: `App \"${appName}\" not found in DOM` };\r\n\r\n return {\r\n app: appName || '(page)',\r\n snapshot: buildA11yTree(target, 0, 5),\r\n timestamp: Date.now(),\r\n };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n console({ level = 'all', limit = 50 }) {\r\n return getFilteredConsole(level, limit);\r\n },\r\n\r\n async screenshot({ selector, quality = 0.8 }) {\r\n const result = await captureScreenshot(selector, quality);\r\n if (!result.error) result.timestamp = Date.now();\r\n return result;\r\n },\r\n\r\n network({ method, status, limit = 50 }) {\r\n return getFilteredNetwork(method, status, limit);\r\n },\r\n\r\n // ── Permission-gated operations ──\r\n\r\n get_state({ path }) {\r\n if (!wu.store) return { error: 'wu.store not available' };\r\n if (!_checkPermission('readStore')) {\r\n return { error: 'Permission denied: readStore is disabled' };\r\n }\r\n const value = wu.store.get(path || '');\r\n return { path: path || '(root)', value };\r\n },\r\n\r\n set_state({ path, value }) {\r\n if (!wu.store) return { error: 'wu.store not available' };\r\n if (!path) return { error: 'path is required' };\r\n if (!_checkPermission('writeStore')) {\r\n _audit('set_state', { path }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: writeStore is disabled' };\r\n }\r\n wu.store.set(path, value);\r\n _audit('set_state', { path, value }, { success: true });\r\n return { path, value, updated: true };\r\n },\r\n\r\n emit_event({ event, data }) {\r\n if (!wu.eventBus) return { error: 'wu.eventBus not available' };\r\n if (!event) return { error: 'event name is required' };\r\n if (!_checkPermission('emitEvents')) {\r\n _audit('emit_event', { event }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: emitEvents is disabled' };\r\n }\r\n _emitInternal(event, data);\r\n _audit('emit_event', { event, data }, { success: true });\r\n return { emitted: event, data };\r\n },\r\n\r\n navigate({ route }) {\r\n if (!route) return { error: 'Route is required' };\r\n if (!_checkPermission('emitEvents')) {\r\n _audit('navigate', { route }, { error: 'Permission denied: emitEvents' });\r\n return { error: 'Permission denied: emitEvents is disabled' };\r\n }\r\n _emitInternal('shell:navigate', { route });\r\n if (wu.store && _checkPermission('writeStore')) {\r\n wu.store.set('currentPath', route);\r\n }\r\n _audit('navigate', { route }, { success: true });\r\n return { navigated: route };\r\n },\r\n\r\n mount_app({ appName, container }) {\r\n if (!appName) return { error: 'appName is required' };\r\n if (!_checkPermission('modifyDOM')) {\r\n _audit('mount_app', { appName }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n try {\r\n if (wu.mount) {\r\n wu.mount(appName, container);\r\n _audit('mount_app', { appName, container }, { success: true });\r\n return { mounted: appName, container };\r\n }\r\n return { error: 'wu.mount not available' };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n unmount_app({ appName }) {\r\n if (!appName) return { error: 'appName is required' };\r\n if (!_checkPermission('modifyDOM')) {\r\n _audit('unmount_app', { appName }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n try {\r\n if (wu.unmount) {\r\n wu.unmount(appName);\r\n _audit('unmount_app', { appName }, { success: true });\r\n return { unmounted: appName };\r\n }\r\n return { error: 'wu.unmount not available' };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n click({ selector, text }) {\r\n if (!_checkPermission('modifyDOM')) {\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n const result = clickElement(selector, text);\r\n _audit('click', { selector, text }, result);\r\n return result;\r\n },\r\n\r\n type({ selector, text, clear = false, submit = false }) {\r\n if (!_checkPermission('modifyDOM')) {\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n const result = typeIntoElement(selector, text, { clear, submit });\r\n _audit('type', { selector, textLength: text?.length }, result);\r\n return result;\r\n },\r\n\r\n async execute_action({ action, params }) {\r\n if (!wu.ai) return { error: 'wu.ai not available' };\r\n if (!action) return { error: 'action name is required' };\r\n\r\n try {\r\n // Execute through public API (respects permissions, validation, audit)\r\n const result = await wu.ai.execute(action, params || {});\r\n return { action, ...result };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n };\r\n\r\n // ── WebSocket connection ──\r\n\r\n function connect(url = 'ws://localhost:19100', options = {}) {\r\n if (ws && ws.readyState <= 1) {\r\n logger.warn('[wu-mcp-bridge] Already connected or connecting');\r\n return;\r\n }\r\n\r\n authToken = options.token || null;\r\n authenticated = !authToken; // No token = auto-authenticated (dev mode)\r\n\r\n try {\r\n ws = new WebSocket(url);\r\n\r\n ws.onopen = () => {\r\n logger.debug('[wu-mcp-bridge] Connected to wu-mcp-server');\r\n reconnectAttempts = 0;\r\n\r\n // Send auth handshake if token provided\r\n if (authToken) {\r\n ws.send(JSON.stringify({\r\n type: 'auth',\r\n token: authToken,\r\n }));\r\n }\r\n };\r\n\r\n ws.onmessage = async (event) => {\r\n try {\r\n const msg = JSON.parse(event.data);\r\n\r\n // Handle auth response\r\n if (msg.type === 'auth_result') {\r\n authenticated = msg.success === true;\r\n if (!authenticated) {\r\n console.error('[wu-mcp-bridge] Authentication failed:', msg.reason || 'Invalid token');\r\n disconnect();\r\n } else {\r\n logger.debug('[wu-mcp-bridge] Authenticated successfully');\r\n }\r\n return;\r\n }\r\n\r\n // Reject commands if not authenticated\r\n if (!authenticated) {\r\n if (msg.id) {\r\n _respond(msg.id, null, 'Not authenticated. Send auth token first.');\r\n }\r\n return;\r\n }\r\n\r\n const { id, command, params } = msg;\r\n\r\n if (!id || !command) {\r\n logger.warn('[wu-mcp-bridge] Invalid message:', msg);\r\n return;\r\n }\r\n\r\n const handler = handlers[command];\r\n if (!handler) {\r\n _respond(id, null, `Unknown command: ${command}`);\r\n return;\r\n }\r\n\r\n try {\r\n const result = await handler(params || {});\r\n _respond(id, result);\r\n } catch (err) {\r\n _respond(id, null, err.message);\r\n }\r\n } catch (err) {\r\n console.error('[wu-mcp-bridge] Failed to handle message:', err);\r\n }\r\n };\r\n\r\n ws.onclose = () => {\r\n logger.debug('[wu-mcp-bridge] Disconnected');\r\n ws = null;\r\n authenticated = false;\r\n _scheduleReconnect(url, options);\r\n };\r\n\r\n ws.onerror = () => {\r\n // onclose will fire after this\r\n };\r\n } catch (err) {\r\n console.error('[wu-mcp-bridge] Connection failed:', err.message);\r\n _scheduleReconnect(url, options);\r\n }\r\n }\r\n\r\n function disconnect() {\r\n if (reconnectTimer) {\r\n clearTimeout(reconnectTimer);\r\n reconnectTimer = null;\r\n }\r\n reconnectAttempts = MAX_RECONNECT_ATTEMPTS; // prevent reconnect\r\n if (ws) {\r\n ws.close();\r\n ws = null;\r\n }\r\n authenticated = false;\r\n }\r\n\r\n function isConnected() {\r\n return ws !== null && ws.readyState === 1 && authenticated;\r\n }\r\n\r\n // ── Private helpers ──\r\n\r\n function _respond(id, result, error) {\r\n if (!ws || ws.readyState !== 1) return;\r\n const msg = error ? { id, error } : { id, result };\r\n ws.send(JSON.stringify(msg));\r\n }\r\n\r\n function _scheduleReconnect(url, options) {\r\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) return;\r\n reconnectAttempts++;\r\n const delay = RECONNECT_DELAY * Math.min(reconnectAttempts, 5);\r\n reconnectTimer = setTimeout(() => connect(url, options), delay);\r\n }\r\n\r\n function _getAppList() {\r\n const apps = [];\r\n\r\n if (wu._apps) {\r\n for (const [name, app] of Object.entries(wu._apps)) {\r\n apps.push({\r\n name,\r\n mounted: app.mounted || app.isMounted || false,\r\n url: app.url || app.info?.url || '',\r\n status: app.status || app.info?.status || 'unknown',\r\n });\r\n }\r\n }\r\n\r\n // Fallback: scan DOM for wu-app elements\r\n if (apps.length === 0) {\r\n document.querySelectorAll('[data-wu-app]').forEach((el) => {\r\n apps.push({\r\n name: el.getAttribute('data-wu-app'),\r\n mounted: true,\r\n container: `#${el.id || '(no-id)'}`,\r\n });\r\n });\r\n }\r\n\r\n return apps;\r\n }\r\n\r\n return { connect, disconnect, isConnected };\r\n}\r\n"],"names":["createMcpBridge","wu","ws","reconnectTimer","reconnectAttempts","authenticated","authToken","_bridgeToken","eventBus","getInternalToken","_emitInternal","event","data","emit","appName","token","eventLog","_checkPermission","perm","ai","permissions","check","includes","_audit","operation","params","result","error","success","timestamp","Date","now","on","push","name","source","length","shift","ensureInterceptors","handlers","status","connected","framework","apps","_getAppList","storeKeys","store","Object","keys","get","actionsCount","tools","eventLogSize","list_apps","list_events","limit","slice","list_actions","actions","note","count","snapshot","target","document","querySelector","body","app","buildA11yTree","err","message","console","level","getFilteredConsole","screenshot","selector","quality","captureScreenshot","network","method","getFilteredNetwork","get_state","path","value","set_state","set","updated","emit_event","emitted","navigate","route","navigated","mount_app","container","mount","mounted","unmount_app","unmount","unmounted","click","text","clickElement","type","clear","submit","typeIntoElement","textLength","execute_action","action","execute","connect","url","options","readyState","logger","warn","WebSocket","onopen","debug","send","JSON","stringify","onmessage","async","msg","parse","reason","disconnect","id","_respond","command","handler","onclose","_scheduleReconnect","onerror","clearTimeout","close","delay","Math","min","setTimeout","_apps","entries","isMounted","info","querySelectorAll","forEach","el","getAttribute","isConnected"],"mappings":"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"}