wu-framework 2.1.2 → 2.5.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 (72) hide show
  1. package/README.md +6 -1
  2. package/dist/adapters/alpine/index.d.ts +1 -1
  3. package/dist/adapters/angular/index.d.ts +1 -1
  4. package/dist/adapters/htmx/index.d.ts +1 -1
  5. package/dist/adapters/lit/index.d.ts +1 -1
  6. package/dist/adapters/lit/index.js +2 -2
  7. package/dist/adapters/lit/index.js.map +1 -1
  8. package/dist/adapters/preact/index.d.ts +1 -1
  9. package/dist/adapters/preact/index.js +1 -1
  10. package/dist/adapters/preact/index.js.map +1 -1
  11. package/dist/adapters/qwik/index.d.ts +3 -10
  12. package/dist/adapters/qwik/index.js +1 -1
  13. package/dist/adapters/qwik/index.js.map +1 -1
  14. package/dist/adapters/react/index.js +1 -1
  15. package/dist/adapters/react/index.js.map +1 -1
  16. package/dist/adapters/shared.d.ts +44 -0
  17. package/dist/adapters/shared.js +1 -1
  18. package/dist/adapters/shared.js.map +1 -1
  19. package/dist/adapters/solid/index.d.ts +1 -1
  20. package/dist/adapters/solid/index.js +1 -1
  21. package/dist/adapters/solid/index.js.map +1 -1
  22. package/dist/adapters/stencil/index.d.ts +1 -1
  23. package/dist/adapters/stimulus/index.d.ts +1 -1
  24. package/dist/adapters/svelte/index.d.ts +1 -1
  25. package/dist/adapters/svelte/index.js +1 -1
  26. package/dist/adapters/svelte/index.js.map +1 -1
  27. package/dist/adapters/vanilla/index.d.ts +1 -1
  28. package/dist/adapters/vanilla/index.js +1 -1
  29. package/dist/adapters/vanilla/index.js.map +1 -1
  30. package/dist/adapters/vue/index.js +1 -1
  31. package/dist/adapters/vue/index.js.map +1 -1
  32. package/dist/ai/wu-ai.js +1 -1
  33. package/dist/ai/wu-ai.js.map +1 -1
  34. package/dist/core/wu-devtools.js +2 -0
  35. package/dist/core/wu-devtools.js.map +1 -0
  36. package/dist/core/wu-html-parser.js +1 -1
  37. package/dist/core/wu-html-parser.js.map +1 -1
  38. package/dist/core/wu-iframe-sandbox.js +1 -1
  39. package/dist/core/wu-iframe-sandbox.js.map +1 -1
  40. package/dist/core/wu-loader.js +1 -1
  41. package/dist/core/wu-loader.js.map +1 -1
  42. package/dist/core/wu-logger.js +2 -0
  43. package/dist/core/wu-logger.js.map +1 -0
  44. package/dist/core/wu-mcp-bridge.js +1 -1
  45. package/dist/core/wu-mcp-bridge.js.map +1 -1
  46. package/dist/core/wu-script-executor.js +1 -1
  47. package/dist/core/wu-script-executor.js.map +1 -1
  48. package/dist/core/wu-store-sync.js +2 -0
  49. package/dist/core/wu-store-sync.js.map +1 -0
  50. package/dist/core/wu-timeline.js +2 -0
  51. package/dist/core/wu-timeline.js.map +1 -0
  52. package/dist/index.d.cts +739 -0
  53. package/dist/index.d.ts +295 -1
  54. package/dist/wu-ai-browser-primitives-CaUCk1Xl.js +2 -0
  55. package/dist/wu-ai-browser-primitives-CaUCk1Xl.js.map +1 -0
  56. package/dist/wu-framework.cjs +3 -0
  57. package/dist/wu-framework.cjs.map +1 -0
  58. package/dist/wu-framework.dev.js +1207 -275
  59. package/dist/wu-framework.dev.js.map +1 -1
  60. package/dist/wu-framework.esm.js +2 -2
  61. package/dist/wu-framework.esm.js.map +1 -1
  62. package/dist/wu-framework.umd.js +2 -2
  63. package/dist/wu-framework.umd.js.map +1 -1
  64. package/integrations/astro/WuApp.astro +16 -11
  65. package/integrations/astro/WuShell.astro +11 -3
  66. package/package.json +14 -6
  67. package/dist/wu-ai-browser-primitives-BDKXJlwc.js +0 -2
  68. package/dist/wu-ai-browser-primitives-BDKXJlwc.js.map +0 -1
  69. package/dist/wu-framework.cjs.js +0 -3
  70. package/dist/wu-framework.cjs.js.map +0 -1
  71. package/dist/wu-logger-fJfUHBGA.js +0 -2
  72. package/dist/wu-logger-fJfUHBGA.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -52,6 +52,200 @@ export interface WuLifecycle {
52
52
  unmount?: (container: HTMLElement) => void | Promise<void>;
53
53
  activate?: (container: HTMLElement) => void | Promise<void>;
54
54
  deactivate?: (container: HTMLElement) => void | Promise<void>;
55
+ /**
56
+ * Live-props slot (v2.2+). Called by `wu.update(appName, props)` to push new
57
+ * props into a mounted app without remounting. Adapters built on
58
+ * `createWuAdapter` expose this when their framework can re-render in place.
59
+ */
60
+ update?: (container: HTMLElement, props: Record<string, any>) => void | Promise<void>;
61
+ }
62
+
63
+ /** Full-page diagnostic snapshot returned by `wu.inspect()` (v2.2+). */
64
+ export interface WuInspectSnapshot {
65
+ version: string | null;
66
+ timestamp: number;
67
+ summary: { registered: number; defined: number; mounted: number; hidden: number };
68
+ apps: Array<{
69
+ name: string;
70
+ status: 'mounted' | 'hidden';
71
+ framework: string | null;
72
+ containerSelector: string | null;
73
+ mountedAt: number | null;
74
+ liveProps: boolean;
75
+ props: Record<string, any> | null;
76
+ sandbox: WuSandboxInfo | null;
77
+ }>;
78
+ defined: string[];
79
+ registered: string[];
80
+ /** Registered capability contracts (v2.5+). */
81
+ capabilities: Array<{ name: string; version: string; app: string | null }>;
82
+ events: { recent: Array<{ type: string; appName?: string; timestamp?: number }>; stats: any };
83
+ store: { snapshot: any; metrics: any };
84
+ }
85
+
86
+ /** Options for `wu.provide()` (v2.5+). */
87
+ export interface WuProvideOptions {
88
+ /** Semver version the implementation satisfies (default '0.0.0'). */
89
+ version?: string;
90
+ /** Required keys (array) or key→typeof map; verified at provide() time. */
91
+ shape?: string[] | Record<string, string>;
92
+ /** Providing app — the capability auto-revokes when this app unmounts. */
93
+ app?: string;
94
+ }
95
+
96
+ /** Options for `wu.consume()` (v2.5+). */
97
+ export interface WuConsumeOptions {
98
+ /** Return a Promise that resolves once a satisfying provider appears. */
99
+ wait?: boolean;
100
+ /** ms; rejects the wait promise if exceeded. */
101
+ timeout?: number;
102
+ }
103
+
104
+ /** Handle returned by `wu.provide()` (v2.5+). */
105
+ export interface WuCapabilityHandle {
106
+ revoke(): void;
107
+ }
108
+
109
+ /**
110
+ * Typed, versioned, runtime-verified capability contracts (v2.5+). Apps
111
+ * declare what they provide and consume; the runtime negotiates semver and
112
+ * verifies shape — replacing Module Federation's fragile shared singletons.
113
+ */
114
+ export class WuContracts {
115
+ constructor(core: WuCore);
116
+ provide<T extends object>(name: string, impl: T, opts?: WuProvideOptions): WuCapabilityHandle;
117
+ consume<T = any>(name: string, range?: string, opts?: { wait?: false; timeout?: number }): T;
118
+ consume<T = any>(name: string, range: string, opts: { wait: true; timeout?: number }): Promise<T>;
119
+ has(name: string, range?: string): boolean;
120
+ revoke(name: string): boolean;
121
+ list(): Array<{ name: string; version: string; app: string | null }>;
122
+ cleanup(): void;
123
+ }
124
+
125
+ /** A single journal entry recorded by WuTimeline (v2.3+). */
126
+ export interface WuTimelineEntry {
127
+ /** Lamport clock — the (l, site) pair is the CRDT total order. */
128
+ l: number;
129
+ /** Originating site id. */
130
+ site: string;
131
+ /** Wall-clock timestamp (ms). */
132
+ t: number;
133
+ kind: 'store' | 'event';
134
+ /** store: ring-buffer sequence number */
135
+ seq?: number;
136
+ /** store: dot-path written ('' = full-state replace) */
137
+ path?: string;
138
+ /** store: written value (deep-cloned) */
139
+ value?: any;
140
+ /** event: event name */
141
+ name?: string;
142
+ /** event: source app */
143
+ appName?: string;
144
+ /** event (app:mounted): container selector */
145
+ container?: string | null;
146
+ /** event (app:updated): live props pushed */
147
+ props?: Record<string, any> | null;
148
+ }
149
+
150
+ /** Status of the time-travel recorder (v2.3+). */
151
+ export interface WuTimelineStatus {
152
+ loaded: boolean;
153
+ recording: boolean;
154
+ /** true when positioned at the journal end (the present) */
155
+ live: boolean;
156
+ /** number of journal entries applied */
157
+ position: number;
158
+ /** total journal length */
159
+ length: number;
160
+ site: string | null;
161
+ lamport: number;
162
+ snapshots: number;
163
+ }
164
+
165
+ /** Serializable journal — the reproducible bug report (v2.3+). */
166
+ export interface WuTimelineExport {
167
+ format: string;
168
+ wu: string | null;
169
+ site: string;
170
+ exportedAt: number;
171
+ baselineApps: Array<{ name: string; container: string | null; props: Record<string, any> | null }>;
172
+ entries: WuTimelineEntry[];
173
+ snapshots: Array<{ at: number; state: any }>;
174
+ }
175
+
176
+ /**
177
+ * The `wu.timeline` facade (v2.3+) — cross-framework time travel. Records every
178
+ * store write, event-bus emit, and app lifecycle change into one journal;
179
+ * seek() rewinds the whole multi-framework page in lockstep (store hydrate +
180
+ * live-props replay + app diff). Synchronous + chainable for the fire-and-forget
181
+ * controls (record/stop/clear); the seek family returns Promises. The recorder
182
+ * chunk is lazy-loaded on first use — `await wu.timelineReady()` to force it.
183
+ * See ROADMAP.md.
184
+ */
185
+ export interface WuTimelineFacade {
186
+ record(opts?: { snapshotEvery?: number; maxEntries?: number }): WuTimelineFacade;
187
+ stop(): WuTimelineFacade;
188
+ clear(): WuTimelineFacade;
189
+ /** Rewind/forward to a journal position (0..length). */
190
+ seek(pos: number, opts?: { store?: boolean; apps?: boolean; props?: boolean }): Promise<WuTimelineStatus>;
191
+ /** Return to the present (seek to journal end). */
192
+ live(): Promise<WuTimelineStatus>;
193
+ stepBack(): Promise<WuTimelineStatus>;
194
+ stepForward(): Promise<WuTimelineStatus>;
195
+ export(): Promise<WuTimelineExport>;
196
+ import(data: WuTimelineExport): Promise<WuTimelineStatus>;
197
+ /** Merge remote journal entries (CRDT seed for multiplayer sync, #2). */
198
+ ingest(remoteEntries: WuTimelineEntry[]): Promise<WuTimelineStatus>;
199
+ entries(): WuTimelineEntry[];
200
+ status(): WuTimelineStatus;
201
+ readonly loaded: boolean;
202
+ /** The underlying WuTimeline instance once loaded (lazy), else null. */
203
+ readonly instance: any;
204
+ }
205
+
206
+ /** A duck-typed sync transport (v2.4+). Bring your own, or use 'broadcast' / a WebSocket. */
207
+ export interface WuSyncTransport {
208
+ send(message: any): void;
209
+ onMessage(cb: (message: any) => void): void;
210
+ close(): void;
211
+ }
212
+
213
+ /** Options for `wu.store.sync()` (v2.4+). */
214
+ export interface WuSyncOptions {
215
+ /** 'broadcast' (cross-tab), a WebSocket / ws(s):// URL, or a custom transport. Default 'broadcast'. */
216
+ transport?: 'broadcast' | WuSyncTransport | WebSocket | string;
217
+ /** Channel name for the broadcast transport. Default 'default'. */
218
+ room?: string;
219
+ }
220
+
221
+ /** Live status of a store-sync session (v2.4+). */
222
+ export interface WuSyncStatus {
223
+ connected: boolean;
224
+ site: string | null;
225
+ lamport: number;
226
+ peers: number;
227
+ tracked?: number;
228
+ sent?: number;
229
+ received?: number;
230
+ applied?: number;
231
+ ignored?: number;
232
+ /** Local writes skipped because the value wasn't serializable. */
233
+ dropped?: number;
234
+ loading?: boolean;
235
+ stopped?: boolean;
236
+ /** Set if the connection failed (e.g. unknown transport). */
237
+ error?: string | null;
238
+ }
239
+
240
+ /** Handle returned by `wu.store.sync()` (v2.4+). */
241
+ export interface WuSyncHandle {
242
+ /** Stop syncing — detaches the store tap and closes the transport. */
243
+ stop(): void;
244
+ status(): WuSyncStatus;
245
+ /** Resolves once the sync chunk has loaded and the transport is connected. */
246
+ ready(): Promise<any>;
247
+ readonly connected: boolean;
248
+ readonly instance: any;
55
249
  }
56
250
 
57
251
  export interface WuPlugin {
@@ -152,6 +346,8 @@ export class WuCore {
152
346
  errorBoundary: WuErrorBoundary;
153
347
  sandbox: WuSandbox;
154
348
  cache: WuCache;
349
+ /** Capability-contract registry (v2.5+). */
350
+ contracts: WuContracts;
155
351
 
156
352
  /**
157
353
  * Lazy AI proxy. Auto-loads the AI chunk on first method call.
@@ -177,6 +373,13 @@ export class WuCore {
177
373
  }): Promise<void>;
178
374
  mount(appName: string, containerSelector: string): Promise<void>;
179
375
  unmount(appName: string, options?: { force?: boolean; keepAlive?: boolean }): Promise<void>;
376
+ /**
377
+ * Push new props into an already-mounted app without remounting (v2.2+).
378
+ * Resolves `true` if the app's adapter supports live props; resolves `false`
379
+ * (an honest no-op, never throws) when the app is not mounted or its adapter
380
+ * has no `update` slot.
381
+ */
382
+ update(appName: string, props: Record<string, any>): Promise<boolean>;
180
383
  define(appName: string, lifecycle: WuLifecycle): void;
181
384
  app(name: string, config: Partial<WuAppConfig>): WuApp;
182
385
  hide(appName: string): Promise<void>;
@@ -192,6 +395,44 @@ export class WuCore {
192
395
  */
193
396
  getSandboxInfo(appName: string): WuSandboxInfo | null;
194
397
 
398
+ /**
399
+ * Register a capability another app can consume (typed/versioned contract, v2.5+).
400
+ */
401
+ provide<T extends object>(name: string, impl: T, opts?: WuProvideOptions): WuCapabilityHandle;
402
+ /**
403
+ * Consume a capability from another app (v2.5+). Returns a live proxy that
404
+ * fails loudly on access if unsatisfied, or a Promise with { wait: true }.
405
+ */
406
+ consume<T = any>(name: string, range?: string, opts?: { wait?: false; timeout?: number }): T;
407
+ consume<T = any>(name: string, range: string, opts: { wait: true; timeout?: number }): Promise<T>;
408
+
409
+ /**
410
+ * Full-page diagnostic snapshot — every mounted app, its sandbox mode and
411
+ * live-props capability, recent events, and a store snapshot in one object
412
+ * (v2.2+). Backs `wu.showInspector()` and `window.__WU_DEVTOOLS__`.
413
+ */
414
+ inspect(opts?: { events?: number }): WuInspectSnapshot;
415
+
416
+ /** Open the lazy, Shadow-DOM-isolated inspector overlay (v2.2+). */
417
+ showInspector(): Promise<{ close: () => void } | null>;
418
+ /** Close the inspector overlay if open (v2.2+). */
419
+ hideInspector(): Promise<void>;
420
+
421
+ /**
422
+ * Cross-framework time travel (v2.3+). Record store/event/lifecycle
423
+ * mutations and scrub the whole multi-framework page back and forth. The
424
+ * recorder is a lazy chunk loaded on first `wu.timeline.*` call — zero
425
+ * overhead until used. See ROADMAP.md.
426
+ */
427
+ timeline: WuTimelineFacade;
428
+
429
+ /**
430
+ * Force-load the timeline chunk and resolve the real WuTimeline (v2.3+).
431
+ * `await wu.timelineReady()` before the first write you want captured — after
432
+ * it resolves, `wu.timeline.record()` arms synchronously. Mirrors aiReady().
433
+ */
434
+ timelineReady(): Promise<any>;
435
+
195
436
  /**
196
437
  * Tag a <style> or <link> element as belonging to a specific app (v2.1+).
197
438
  * Makes `fully-isolated` / `own-only` styleMode detect the style regardless
@@ -225,7 +466,7 @@ export class WuEventBus {
225
466
  trustedApps: Set<string>;
226
467
  history: WuEvent[];
227
468
 
228
- emit(eventName: string, data?: any, options?: { appName?: string; token?: string; meta?: any }): boolean;
469
+ emit(eventName: string, data?: any, options?: { appName?: string; token?: string; meta?: any; history?: boolean }): boolean;
229
470
  on(eventName: string, callback: (event: WuEvent) => void): () => void;
230
471
  once(eventName: string, callback: (event: WuEvent) => void): () => void;
231
472
  off(eventName: string, callback: (event: WuEvent) => void): void;
@@ -234,6 +475,12 @@ export class WuEventBus {
234
475
  replay(eventNameOrPattern: string, callback: (event: WuEvent) => void): void;
235
476
  clearHistory(eventNameOrPattern?: string): void;
236
477
  matchesWildcard(eventName: string, pattern: string): boolean;
478
+ /**
479
+ * Low-level emit tap (v2.3+). Fires for every emitted event (after history,
480
+ * before listeners), bypassing wildcard matching and authorization — the
481
+ * internal firehose WuTimeline journals from. Returns an unsubscribe fn.
482
+ */
483
+ tap(fn: (event: WuEvent) => void): () => void;
237
484
  enableStrictMode(): void;
238
485
  disableStrictMode(): void;
239
486
  removeAll(): void;
@@ -248,6 +495,23 @@ export class WuStore {
248
495
  set(path: string, value: any): number;
249
496
  on(pattern: string, callback: (value: any, path?: string) => void): () => void;
250
497
  batch(updates: Record<string, any>): number[];
498
+ /**
499
+ * Low-level write tap (v2.3+). Fires synchronously inside set() for every
500
+ * write with the ring-buffer sequence — the substrate WuTimeline journals
501
+ * from. Returns an unsubscribe function.
502
+ */
503
+ tap(fn: (sequence: number, path: string, value: any) => void): () => void;
504
+ /**
505
+ * Replace the whole state and re-notify listeners (v2.3+) — the seek
506
+ * primitive for WuTimeline. Does not touch the ring buffer or taps.
507
+ */
508
+ hydrate(newState: any, opts?: { notifyPaths?: string[] }): void;
509
+ /**
510
+ * Start real-time collaborative sync across replicas (tabs/workers/clients)
511
+ * via a per-path Last-Writer-Wins CRDT (v2.4+). Lazy-loads the sync chunk.
512
+ * See ROADMAP.md (#2).
513
+ */
514
+ sync(opts?: WuSyncOptions): WuSyncHandle;
251
515
  clear(): void;
252
516
  getMetrics(): {
253
517
  reads: number;
@@ -417,6 +681,11 @@ export function off(event: string, cb: (event: WuEvent) => void): void;
417
681
  export function getState(path?: string): any;
418
682
  export function setState(path: string, value: any): number;
419
683
  export function onStateChange(pattern: string, cb: (value: any) => void): () => void;
684
+ export function syncStore(opts?: WuSyncOptions): WuSyncHandle;
685
+
686
+ export function provide<T extends object>(name: string, impl: T, opts?: WuProvideOptions): WuCapabilityHandle;
687
+ export function consume<T = any>(name: string, range?: string, opts?: { wait?: false; timeout?: number }): T;
688
+ export function consume<T = any>(name: string, range: string, opts: { wait: true; timeout?: number }): Promise<T>;
420
689
 
421
690
  export function startMeasure(name: string, app?: string): void;
422
691
  export function endMeasure(name: string, app?: string): number;
@@ -436,6 +705,11 @@ export function useHook(phase: string, middleware: Function, opts?: any): void;
436
705
  export function silenceAllLogs(): void;
437
706
  export function enableAllLogs(): void;
438
707
 
708
+ // --- Semver (capability-contract range matching, v2.5+) ---
709
+ export function satisfies(version: string, range: string): boolean;
710
+ export function parseVersion(v: string): [number, number, number];
711
+ export function compareVersions(a: string | number[], b: string | number[]): number;
712
+
439
713
  /**
440
714
  * Canonicalize styleMode aliases (v2.1+).
441
715
  * - `'none'` → `'isolated'`
@@ -443,3 +717,23 @@ export function enableAllLogs(): void;
443
717
  * - Other inputs pass through unchanged.
444
718
  */
445
719
  export function normalizeStyleMode(mode: string | undefined): string | undefined;
720
+
721
+ /**
722
+ * DevTools bridge (v2.2+). A tiny always-present global so external inspectors
723
+ * and the built-in overlay can detect Wu and pull a full-page snapshot.
724
+ */
725
+ export interface WuDevtoolsBridge {
726
+ version: string;
727
+ isWu: true;
728
+ inspect(opts?: { events?: number }): WuInspectSnapshot;
729
+ show(): Promise<{ close: () => void } | null>;
730
+ hide(): Promise<void>;
731
+ subscribe(cb: (event: WuEvent) => void): () => void;
732
+ }
733
+
734
+ declare global {
735
+ interface Window {
736
+ wu?: WuCore;
737
+ __WU_DEVTOOLS__?: WuDevtoolsBridge;
738
+ }
739
+ }
@@ -0,0 +1,2 @@
1
+ const t=[],e=300,n=[];let o=!1;function r(){o||(!function(){const n=window.fetch;window.fetch=async function(...o){const r=Date.now(),i=o[0],s="string"==typeof i?i:i?.url||"",a=(o[1]?.method||i?.method||"GET").toUpperCase();try{const i=await n.apply(window,o),l=parseInt(i.headers?.get("content-length")||"0",10);return t.push({type:"fetch",method:a,url:s,status:i.status,statusText:i.statusText,duration:Date.now()-r,size:l,timestamp:r}),t.length>e&&t.shift(),i}catch(n){throw t.push({type:"fetch",method:a,url:s,status:0,error:n.message,duration:Date.now()-r,timestamp:r}),t.length>e&&t.shift(),n}};const o=XMLHttpRequest.prototype.open,r=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(t,e,...n){return this._wuAi={method:(t||"GET").toUpperCase(),url:String(e)},o.call(this,t,e,...n)},XMLHttpRequest.prototype.send=function(...n){return this._wuAi&&(this._wuAi.start=Date.now(),this.addEventListener("loadend",()=>{t.push({type:"xhr",method:this._wuAi.method,url:this._wuAi.url,status:this.status,statusText:this.statusText,duration:Date.now()-this._wuAi.start,size:parseInt(this.getResponseHeader("content-length")||"0",10),timestamp:this._wuAi.start}),t.length>e&&t.shift()})),r.apply(this,n)}}(),function(){const t=["log","warn","error"];for(const e of t){const t=console[e];console[e]=(...o)=>{n.push({level:e,message:o.map(t=>{if("object"!=typeof t)return String(t);try{return JSON.stringify(t)}catch(e){return String(t)}}).join(" "),timestamp:Date.now()}),n.length>500&&n.shift(),t.apply(console,o)}}}(),o=!0)}function i(t,e=0,n=5){if(e>n||!t)return"";const o=" ".repeat(e),r=t.tagName?.toLowerCase()||"",s=t.getAttribute?.("role")||"",a=t.getAttribute?.("aria-label")||"",l=1===t.childNodes?.length&&3===t.childNodes[0].nodeType?t.textContent?.trim().slice(0,80):"";let c=`${o}<${r}`;if(t.id&&(c+=` id="${t.id}"`),s&&(c+=` role="${s}"`),a&&(c+=` aria-label="${a}"`),t.className&&"string"==typeof t.className){const e=t.className.trim().slice(0,60);e&&(c+=` class="${e}"`)}c+=">",l&&(c+=` "${l}"`);let u=c+"\n";const h=(t.shadowRoot||t).children||[];for(let t=0;t<h.length&&t<50;t++)u+=i(h[t],e+1,n);return u}function s(t,e){const n=["color","background","background-color","font-family","font-size","font-weight","border","border-radius","padding","margin","display","flex-direction","align-items","justify-content","gap","width","height","max-width","max-height","overflow","opacity","box-shadow","text-align","line-height","position","top","left","right","bottom","z-index","transform","visibility"];try{const o=window.getComputedStyle(t);for(const t of n){const n=o.getPropertyValue(t);n&&e.style?.setProperty(t,n)}}catch(t){}const o=t.children||[],r=e.children||[],i=Math.min(o.length,r.length,200);for(let t=0;t<i;t++)s(o[t],r[t])}async function a(t,e=.8){const n=t?document.querySelector(t):document.documentElement;if(!n)return{error:`Element not found: ${t}`};const o=n.getBoundingClientRect(),r=Math.ceil(Math.min(o.width||window.innerWidth,1920)),i=Math.ceil(Math.min(o.height||window.innerHeight,1080)),a=n.cloneNode(!0);s(n,a);const l=(new XMLSerializer).serializeToString(a),c=[`<svg xmlns="http://www.w3.org/2000/svg" width="${r}" height="${i}">`,'<foreignObject width="100%" height="100%">',`<div xmlns="http://www.w3.org/1999/xhtml" style="width:${r}px;height:${i}px;overflow:hidden;">`,l,"</div>","</foreignObject>","</svg>"].join(""),u=new Blob([c],{type:"image/svg+xml;charset=utf-8"}),h=URL.createObjectURL(u),d=await new Promise(t=>{const n=new Image;n.onload=()=>{try{const o=document.createElement("canvas");o.width=r,o.height=i;o.getContext("2d").drawImage(n,0,0),t(o.toDataURL("image/png",e))}catch(e){t(null)}finally{URL.revokeObjectURL(h)}},n.onerror=()=>{URL.revokeObjectURL(h),t(null)},n.src=h});if(!d)return{error:"Canvas rendering failed"};const p=d.split(",")[1];return{width:r,height:i,format:"png",base64:p,sizeKB:Math.round(3*p.length/4/1024)}}function l(t,e){let n=null;if(t&&(n=document.querySelector(t)),!n&&e){const t=document.querySelectorAll('button, a, [role="button"], input[type="submit"], input[type="button"], [data-click], label, [onclick]'),o=e.toLowerCase();for(const e of t)if(e.textContent?.trim().toLowerCase().includes(o)){n=e;break}}if(!n)return{error:`Element not found: ${t||`text="${e}"`}`};n.scrollIntoView({behavior:"instant",block:"center"}),n.click();const o=n.tagName?.toLowerCase();return{clicked:`${o}${n.id?`#${n.id}`:""}`,text:n.textContent?.trim().slice(0,100)||"",rect:n.getBoundingClientRect().toJSON?.()||null}}function c(t,e,{clear:n=!1,submit:o=!1}={}){if(!t)return{error:"selector is required"};if(void 0===e)return{error:"text is required"};const r=document.querySelector(t);if(!r)return{error:`Element not found: ${t}`};r.focus(),n&&(r.value="",r.dispatchEvent(new Event("input",{bubbles:!0})));const i=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value")?.set||Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype,"value")?.set,s=n?e:(r.value||"")+e;if(i?i.call(r,s):r.value=s,r.dispatchEvent(new Event("input",{bubbles:!0})),r.dispatchEvent(new Event("change",{bubbles:!0})),o){const t=r.closest("form");t?t.dispatchEvent(new Event("submit",{bubbles:!0,cancelable:!0})):r.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter",code:"Enter",bubbles:!0}))}return{selector:t,typed:e,currentValue:r.value?.slice(0,200),submitted:!!o}}function u(e,n,o=30){let r=t;return e&&(r=r.filter(t=>t.method===e.toUpperCase())),n&&(r="error"===n?r.filter(t=>0===t.status||t.status>=400):r.filter(t=>String(t.status).startsWith(String(n)))),{requests:r.slice(-o),total:t.length,showing:Math.min(r.length,o)}}function h(t,e=30){const o=t&&"all"!==t?n.filter(e=>e.level===t):n;return{messages:o.slice(-e),total:n.length,showing:Math.min(o.length,e)}}export{a,i as b,l as c,h as d,r as e,n as f,u as g,t as n,c as t};
2
+ //# sourceMappingURL=wu-ai-browser-primitives-CaUCk1Xl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wu-ai-browser-primitives-CaUCk1Xl.js","sources":["../src/ai/wu-ai-browser-primitives.js"],"sourcesContent":["/**\n * WU-AI Browser Primitives\n *\n * Shared browser capabilities used by both wu-ai-browser.js (Paradigm 1/2)\n * and wu-mcp-bridge.js (Paradigm 3). Single source of truth to avoid\n * duplicating interceptors, DOM traversal, and Canvas rendering.\n */\n\n// ── Shared capture buffers (singleton) ──\n\nexport const networkLog = [];\nexport const MAX_NETWORK_LOG = 300;\nexport const consoleLog = [];\nexport const MAX_CONSOLE_LOG = 500;\n\nlet _interceptorsInstalled = false;\n\n/**\n * Install network + console interceptors (idempotent — only runs once).\n */\nexport function ensureInterceptors() {\n if (_interceptorsInstalled) return;\n _installNetworkInterceptor();\n _installConsoleInterceptor();\n _interceptorsInstalled = true;\n}\n\n/**\n * Build an accessibility tree representation of a DOM element.\n * Traverses into Shadow DOM if present.\n */\nexport function buildA11yTree(el, depth = 0, maxDepth = 5) {\n if (depth > maxDepth || !el) return '';\n\n const indent = ' '.repeat(depth);\n const tag = el.tagName?.toLowerCase() || '';\n const role = el.getAttribute?.('role') || '';\n const ariaLabel = el.getAttribute?.('aria-label') || '';\n const text = el.childNodes?.length === 1 && el.childNodes[0].nodeType === 3\n ? el.textContent?.trim().slice(0, 80) : '';\n\n let line = `${indent}<${tag}`;\n if (el.id) line += ` id=\"${el.id}\"`;\n if (role) line += ` role=\"${role}\"`;\n if (ariaLabel) line += ` aria-label=\"${ariaLabel}\"`;\n if (el.className && typeof el.className === 'string') {\n const cls = el.className.trim().slice(0, 60);\n if (cls) line += ` class=\"${cls}\"`;\n }\n line += '>';\n if (text) line += ` \"${text}\"`;\n\n let result = line + '\\n';\n const root = el.shadowRoot || el;\n const children = root.children || [];\n\n for (let i = 0; i < children.length && i < 50; i++) {\n result += buildA11yTree(children[i], depth + 1, maxDepth);\n }\n return result;\n}\n\n/**\n * Recursively inline computed styles from source to clone for Canvas rendering.\n */\nexport function inlineComputedStyles(source, clone) {\n const props = ['color', 'background', 'background-color', 'font-family',\n 'font-size', 'font-weight', 'border', 'border-radius', 'padding', 'margin',\n 'display', 'flex-direction', 'align-items', 'justify-content', 'gap',\n 'width', 'height', 'max-width', 'max-height', 'overflow', 'opacity',\n 'box-shadow', 'text-align', 'line-height', 'position', 'top', 'left',\n 'right', 'bottom', 'z-index', 'transform', 'visibility'];\n\n try {\n const style = window.getComputedStyle(source);\n for (const prop of props) {\n const val = style.getPropertyValue(prop);\n if (val) clone.style?.setProperty(prop, val);\n }\n } catch (_) { /* skip */ }\n\n const srcKids = source.children || [];\n const cloneKids = clone.children || [];\n const max = Math.min(srcKids.length, cloneKids.length, 200);\n for (let i = 0; i < max; i++) {\n inlineComputedStyles(srcKids[i], cloneKids[i]);\n }\n}\n\n/**\n * Capture a screenshot of a DOM element via Canvas API (SVG foreignObject).\n * @returns {Promise<{ width, height, format, base64, sizeKB } | { error: string }>}\n */\nexport async function captureScreenshot(selector, quality = 0.8) {\n const target = selector\n ? document.querySelector(selector)\n : document.documentElement;\n\n if (!target) return { error: `Element not found: ${selector}` };\n\n const rect = target.getBoundingClientRect();\n const w = Math.ceil(Math.min(rect.width || window.innerWidth, 1920));\n const h = Math.ceil(Math.min(rect.height || window.innerHeight, 1080));\n\n const clone = target.cloneNode(true);\n inlineComputedStyles(target, clone);\n\n const serializer = new XMLSerializer();\n const xhtml = serializer.serializeToString(clone);\n\n const svgStr = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\">`,\n '<foreignObject width=\"100%\" height=\"100%\">',\n `<div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:${w}px;height:${h}px;overflow:hidden;\">`,\n xhtml,\n '</div>',\n '</foreignObject>',\n '</svg>',\n ].join('');\n\n const svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n const dataUrl = await new Promise((resolve) => {\n const img = new Image();\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas');\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext('2d');\n ctx.drawImage(img, 0, 0);\n resolve(canvas.toDataURL('image/png', quality));\n } catch (_) {\n // toDataURL throws SecurityError on tainted canvases — fail gracefully\n resolve(null);\n } finally {\n URL.revokeObjectURL(url);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(null);\n };\n img.src = url;\n });\n\n if (!dataUrl) return { error: 'Canvas rendering failed' };\n\n const base64 = dataUrl.split(',')[1];\n return {\n width: w,\n height: h,\n format: 'png',\n base64,\n sizeKB: Math.round((base64.length * 3) / 4 / 1024),\n };\n}\n\n/**\n * Click an element by CSS selector or visible text content.\n * @returns {{ clicked, text } | { error }}\n */\nexport function clickElement(selector, text) {\n let el = null;\n\n if (selector) {\n el = document.querySelector(selector);\n }\n\n if (!el && text) {\n const candidates = document.querySelectorAll(\n 'button, a, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"], [data-click], label, [onclick]'\n );\n const searchText = text.toLowerCase();\n for (const candidate of candidates) {\n if (candidate.textContent?.trim().toLowerCase().includes(searchText)) {\n el = candidate;\n break;\n }\n }\n }\n\n if (!el) return { error: `Element not found: ${selector || `text=\"${text}\"`}` };\n\n el.scrollIntoView({ behavior: 'instant', block: 'center' });\n el.click();\n\n const tag = el.tagName?.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n return {\n clicked: `${tag}${id}`,\n text: el.textContent?.trim().slice(0, 100) || '',\n rect: el.getBoundingClientRect().toJSON?.() || null,\n };\n}\n\n/**\n * Type into an input, textarea, or contenteditable element.\n * Works with React, Vue, Angular, and other frameworks.\n * @returns {{ selector, typed, currentValue, submitted } | { error }}\n */\nexport function typeIntoElement(selector, text, { clear = false, submit = false } = {}) {\n if (!selector) return { error: 'selector is required' };\n if (text === undefined) return { error: 'text is required' };\n\n const el = document.querySelector(selector);\n if (!el) return { error: `Element not found: ${selector}` };\n\n el.focus();\n\n if (clear) {\n el.value = '';\n el.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n // Use native setter to trigger framework reactivity (React, Vue, etc.)\n const nativeSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype, 'value'\n )?.set || Object.getOwnPropertyDescriptor(\n window.HTMLTextAreaElement.prototype, 'value'\n )?.set;\n\n const newValue = clear ? text : (el.value || '') + text;\n if (nativeSetter) {\n nativeSetter.call(el, newValue);\n } else {\n el.value = newValue;\n }\n\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n\n if (submit) {\n const form = el.closest('form');\n if (form) {\n form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));\n } else {\n el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', bubbles: true }));\n }\n }\n\n return {\n selector,\n typed: text,\n currentValue: el.value?.slice(0, 200),\n submitted: !!submit,\n };\n}\n\n/**\n * Filter and return network log entries.\n */\nexport function getFilteredNetwork(method, status, limit = 30) {\n let filtered = networkLog;\n if (method) {\n filtered = filtered.filter((r) => r.method === method.toUpperCase());\n }\n if (status) {\n if (status === 'error') {\n filtered = filtered.filter((r) => r.status === 0 || r.status >= 400);\n } else {\n filtered = filtered.filter((r) => String(r.status).startsWith(String(status)));\n }\n }\n return {\n requests: filtered.slice(-limit),\n total: networkLog.length,\n showing: Math.min(filtered.length, limit),\n };\n}\n\n/**\n * Filter and return console log entries.\n */\nexport function getFilteredConsole(level, limit = 30) {\n const filtered = level && level !== 'all'\n ? consoleLog.filter((m) => m.level === level)\n : consoleLog;\n return {\n messages: filtered.slice(-limit),\n total: consoleLog.length,\n showing: Math.min(filtered.length, limit),\n };\n}\n\n// ── Private: Interceptors ──\n\nfunction _installNetworkInterceptor() {\n // Intercept fetch\n const originalFetch = window.fetch;\n window.fetch = async function (...args) {\n const start = Date.now();\n const req = args[0];\n const url = typeof req === 'string' ? req : req?.url || '';\n const method = (args[1]?.method || req?.method || 'GET').toUpperCase();\n\n try {\n const response = await originalFetch.apply(window, args);\n const size = parseInt(response.headers?.get('content-length') || '0', 10);\n networkLog.push({\n type: 'fetch', method, url,\n status: response.status, statusText: response.statusText,\n duration: Date.now() - start, size, timestamp: start,\n });\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\n return response;\n } catch (err) {\n networkLog.push({\n type: 'fetch', method, url,\n status: 0, error: err.message,\n duration: Date.now() - start, timestamp: start,\n });\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\n throw err;\n }\n };\n\n // Intercept XMLHttpRequest\n const origOpen = XMLHttpRequest.prototype.open;\n const origSend = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (method, url, ...rest) {\n this._wuAi = { method: (method || 'GET').toUpperCase(), url: String(url) };\n return origOpen.call(this, method, url, ...rest);\n };\n\n XMLHttpRequest.prototype.send = function (...args) {\n if (this._wuAi) {\n this._wuAi.start = Date.now();\n this.addEventListener('loadend', () => {\n networkLog.push({\n type: 'xhr', method: this._wuAi.method, url: this._wuAi.url,\n status: this.status, statusText: this.statusText,\n duration: Date.now() - this._wuAi.start,\n size: parseInt(this.getResponseHeader('content-length') || '0', 10),\n timestamp: this._wuAi.start,\n });\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\n });\n }\n return origSend.apply(this, args);\n };\n}\n\nfunction _installConsoleInterceptor() {\n const levels = ['log', 'warn', 'error'];\n for (const level of levels) {\n const original = console[level];\n console[level] = (...args) => {\n consoleLog.push({\n level,\n message: args.map((a) => {\n if (typeof a !== 'object') return String(a);\n try { return JSON.stringify(a); } catch (_) { return String(a); }\n }).join(' '),\n timestamp: Date.now(),\n });\n if (consoleLog.length > MAX_CONSOLE_LOG) consoleLog.shift();\n original.apply(console, args);\n };\n }\n}\n"],"names":["networkLog","MAX_NETWORK_LOG","consoleLog","_interceptorsInstalled","ensureInterceptors","originalFetch","window","fetch","async","args","start","Date","now","req","url","method","toUpperCase","response","apply","size","parseInt","headers","get","push","type","status","statusText","duration","timestamp","length","shift","err","error","message","origOpen","XMLHttpRequest","prototype","open","origSend","send","rest","this","_wuAi","String","call","addEventListener","getResponseHeader","_installNetworkInterceptor","levels","level","original","console","map","a","JSON","stringify","_","join","_installConsoleInterceptor","buildA11yTree","el","depth","maxDepth","indent","repeat","tag","tagName","toLowerCase","role","getAttribute","ariaLabel","text","childNodes","nodeType","textContent","trim","slice","line","id","className","cls","result","children","shadowRoot","i","inlineComputedStyles","source","clone","props","style","getComputedStyle","prop","val","getPropertyValue","setProperty","srcKids","cloneKids","max","Math","min","captureScreenshot","selector","quality","target","document","querySelector","documentElement","rect","getBoundingClientRect","w","ceil","width","innerWidth","h","height","innerHeight","cloneNode","xhtml","XMLSerializer","serializeToString","svgStr","svgBlob","Blob","URL","createObjectURL","dataUrl","Promise","resolve","img","Image","onload","canvas","createElement","getContext","drawImage","toDataURL","revokeObjectURL","onerror","src","base64","split","format","sizeKB","round","clickElement","candidates","querySelectorAll","searchText","candidate","includes","scrollIntoView","behavior","block","click","clicked","toJSON","typeIntoElement","clear","submit","undefined","focus","value","dispatchEvent","Event","bubbles","nativeSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","set","HTMLTextAreaElement","newValue","form","closest","cancelable","KeyboardEvent","key","code","typed","currentValue","submitted","getFilteredNetwork","limit","filtered","filter","r","startsWith","requests","total","showing","getFilteredConsole","m","messages"],"mappings":"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"}