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.
- package/README.md +6 -1
- package/dist/adapters/alpine/index.d.ts +1 -1
- package/dist/adapters/angular/index.d.ts +1 -1
- package/dist/adapters/htmx/index.d.ts +1 -1
- package/dist/adapters/lit/index.d.ts +1 -1
- package/dist/adapters/lit/index.js +2 -2
- package/dist/adapters/lit/index.js.map +1 -1
- package/dist/adapters/preact/index.d.ts +1 -1
- package/dist/adapters/preact/index.js +1 -1
- package/dist/adapters/preact/index.js.map +1 -1
- package/dist/adapters/qwik/index.d.ts +3 -10
- package/dist/adapters/qwik/index.js +1 -1
- package/dist/adapters/qwik/index.js.map +1 -1
- package/dist/adapters/react/index.js +1 -1
- package/dist/adapters/react/index.js.map +1 -1
- package/dist/adapters/shared.d.ts +44 -0
- package/dist/adapters/shared.js +1 -1
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/solid/index.d.ts +1 -1
- package/dist/adapters/solid/index.js +1 -1
- package/dist/adapters/solid/index.js.map +1 -1
- package/dist/adapters/stencil/index.d.ts +1 -1
- package/dist/adapters/stimulus/index.d.ts +1 -1
- package/dist/adapters/svelte/index.d.ts +1 -1
- package/dist/adapters/svelte/index.js +1 -1
- package/dist/adapters/svelte/index.js.map +1 -1
- package/dist/adapters/vanilla/index.d.ts +1 -1
- package/dist/adapters/vanilla/index.js +1 -1
- package/dist/adapters/vanilla/index.js.map +1 -1
- package/dist/adapters/vue/index.js +1 -1
- package/dist/adapters/vue/index.js.map +1 -1
- package/dist/ai/wu-ai.js +1 -1
- package/dist/ai/wu-ai.js.map +1 -1
- package/dist/core/wu-devtools.js +2 -0
- package/dist/core/wu-devtools.js.map +1 -0
- package/dist/core/wu-html-parser.js +1 -1
- package/dist/core/wu-html-parser.js.map +1 -1
- package/dist/core/wu-iframe-sandbox.js +1 -1
- package/dist/core/wu-iframe-sandbox.js.map +1 -1
- package/dist/core/wu-loader.js +1 -1
- package/dist/core/wu-loader.js.map +1 -1
- package/dist/core/wu-logger.js +2 -0
- package/dist/core/wu-logger.js.map +1 -0
- package/dist/core/wu-mcp-bridge.js +1 -1
- package/dist/core/wu-mcp-bridge.js.map +1 -1
- package/dist/core/wu-script-executor.js +1 -1
- package/dist/core/wu-script-executor.js.map +1 -1
- package/dist/core/wu-store-sync.js +2 -0
- package/dist/core/wu-store-sync.js.map +1 -0
- package/dist/core/wu-timeline.js +2 -0
- package/dist/core/wu-timeline.js.map +1 -0
- package/dist/index.d.cts +739 -0
- package/dist/index.d.ts +295 -1
- package/dist/wu-ai-browser-primitives-CaUCk1Xl.js +2 -0
- package/dist/wu-ai-browser-primitives-CaUCk1Xl.js.map +1 -0
- package/dist/wu-framework.cjs +3 -0
- package/dist/wu-framework.cjs.map +1 -0
- package/dist/wu-framework.dev.js +1207 -275
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +2 -2
- package/dist/wu-framework.esm.js.map +1 -1
- package/dist/wu-framework.umd.js +2 -2
- package/dist/wu-framework.umd.js.map +1 -1
- package/integrations/astro/WuApp.astro +16 -11
- package/integrations/astro/WuShell.astro +11 -3
- package/package.json +14 -6
- package/dist/wu-ai-browser-primitives-BDKXJlwc.js +0 -2
- package/dist/wu-ai-browser-primitives-BDKXJlwc.js.map +0 -1
- package/dist/wu-framework.cjs.js +0 -3
- package/dist/wu-framework.cjs.js.map +0 -1
- package/dist/wu-logger-fJfUHBGA.js +0 -2
- 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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"}
|