@agent-native/core 0.202.0-nightly-20261006153106 → 0.202.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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Core Web Vitals per page view, measured with the browser's own
3
+ * PerformanceObserver. A page view is one visible stretch of one route: it
4
+ * ends when the route changes through `pushState`/`popstate` or the page is
5
+ * hidden, and a page that becomes visible again starts a new one. TTFB and
6
+ * LCP belong to the document load only; INP and CLS are measured within each
7
+ * page view. A metric the browser cannot measure is left out, never zero, and
8
+ * a page view the manifest has no route for carries no route. No report
9
+ * carries the page's path, which can hold slugs and emails; `pageview` has it.
10
+ */
11
+ export type WebVitalsNavigationType = "load" | "client" | "resume";
12
+ export interface PageViewVitals {
13
+ route?: string;
14
+ navigationType: WebVitalsNavigationType;
15
+ ttfbMs?: number;
16
+ lcpMs?: number;
17
+ inpMs?: number;
18
+ cls?: number;
19
+ }
20
+ export interface WebVitalsLocation {
21
+ route: string | null;
22
+ pathname: string;
23
+ }
24
+ interface LayoutShiftLike {
25
+ startTime: number;
26
+ value: number;
27
+ hadRecentInput: boolean;
28
+ }
29
+ interface InteractionLike {
30
+ interactionId?: number;
31
+ duration: number;
32
+ }
33
+ export interface WebVitalsTrackerOptions {
34
+ /** Read when a page view ends: whether layout shifts are being observed. */
35
+ measuresLayoutShift: () => boolean;
36
+ report: (vitals: PageViewVitals) => void;
37
+ interactionCount?: () => number | undefined;
38
+ }
39
+ /**
40
+ * The page-view state machine, separate from the observers that feed it so
41
+ * the metric rules can be exercised without a browser.
42
+ */
43
+ export declare function createWebVitalsTracker(options: WebVitalsTrackerOptions): {
44
+ startLoad(location: WebVitalsLocation, ttfbMs: number | undefined): void;
45
+ /**
46
+ * `replace` keeps the page view and moves it to the new route, since
47
+ * redirects and URL canonicalization replace the entry the person landed
48
+ * on. Any other change of path is a new page view.
49
+ */
50
+ navigate(location: WebVitalsLocation, kind: "push" | "replace"): void;
51
+ hidden(): void;
52
+ /** Drops the current page view without reporting it. */
53
+ discard(): void;
54
+ visible(location: WebVitalsLocation): void;
55
+ largestContentfulPaint(startTimeMs: number): void;
56
+ finalizeLargestContentfulPaint(): void;
57
+ layoutShift(entry: LayoutShiftLike): void;
58
+ interaction(entry: InteractionLike): void;
59
+ };
60
+ export type WebVitalsTracker = ReturnType<typeof createWebVitalsTracker>;
61
+ export interface WebVitalsController {
62
+ navigate(kind: "push" | "replace"): void;
63
+ }
64
+ /**
65
+ * Starts measuring the current document. Returns null where the browser has
66
+ * no PerformanceObserver, so no page view is reported as measured.
67
+ */
68
+ export declare function installWebVitals(locate: () => WebVitalsLocation, report: (vitals: PageViewVitals) => void): WebVitalsController | null;
69
+ export {};
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Core Web Vitals per page view, measured with the browser's own
3
+ * PerformanceObserver. A page view is one visible stretch of one route: it
4
+ * ends when the route changes through `pushState`/`popstate` or the page is
5
+ * hidden, and a page that becomes visible again starts a new one. TTFB and
6
+ * LCP belong to the document load only; INP and CLS are measured within each
7
+ * page view. A metric the browser cannot measure is left out, never zero, and
8
+ * a page view the manifest has no route for carries no route. No report
9
+ * carries the page's path, which can hold slugs and emails; `pageview` has it.
10
+ */
11
+ const CLS_WINDOW_GAP_MS = 1_000;
12
+ const CLS_WINDOW_MAX_MS = 5_000;
13
+ const LONGEST_INTERACTIONS_KEPT = 10;
14
+ const INTERACTIONS_PER_INP_STEP = 50;
15
+ function roundMs(value) {
16
+ return Math.round(value);
17
+ }
18
+ /**
19
+ * The page-view state machine, separate from the observers that feed it so
20
+ * the metric rules can be exercised without a browser.
21
+ */
22
+ export function createWebVitalsTracker(options) {
23
+ let current = null;
24
+ function begin(location, navigationType) {
25
+ current = {
26
+ location,
27
+ navigationType,
28
+ lcpFinal: navigationType !== "load",
29
+ cls: 0,
30
+ windowValue: 0,
31
+ windowStart: 0,
32
+ windowLast: 0,
33
+ shifted: false,
34
+ longestInteractions: [],
35
+ interactionIds: new Set(),
36
+ interactionCountAtStart: options.interactionCount?.(),
37
+ };
38
+ }
39
+ function inp(view) {
40
+ const longest = view.longestInteractions;
41
+ if (!longest.length)
42
+ return undefined;
43
+ const browserCount = view.interactionCountAtStart === undefined
44
+ ? undefined
45
+ : (options.interactionCount?.() ?? 0) - view.interactionCountAtStart;
46
+ const count = Math.max(browserCount ?? 0, view.interactionIds.size);
47
+ // The 98th percentile: skip one of the longest per 50 interactions.
48
+ const index = Math.min(longest.length - 1, Math.floor(count / INTERACTIONS_PER_INP_STEP));
49
+ return roundMs(longest[index].duration);
50
+ }
51
+ function end() {
52
+ const view = current;
53
+ current = null;
54
+ if (!view)
55
+ return;
56
+ // Switching back to a tab and away again measured nothing a person
57
+ // experienced; reporting its CLS of 0 would only dilute the percentiles.
58
+ if (view.navigationType === "resume" &&
59
+ !view.shifted &&
60
+ !view.interactionIds.size) {
61
+ return;
62
+ }
63
+ const vitals = { navigationType: view.navigationType };
64
+ if (view.location.route)
65
+ vitals.route = view.location.route;
66
+ if (view.ttfbMs !== undefined)
67
+ vitals.ttfbMs = view.ttfbMs;
68
+ if (view.lcpMs !== undefined)
69
+ vitals.lcpMs = view.lcpMs;
70
+ const inpMs = inp(view);
71
+ if (inpMs !== undefined)
72
+ vitals.inpMs = inpMs;
73
+ if (options.measuresLayoutShift()) {
74
+ vitals.cls = Math.round(view.cls * 10_000) / 10_000;
75
+ }
76
+ if (vitals.ttfbMs === undefined &&
77
+ vitals.lcpMs === undefined &&
78
+ vitals.inpMs === undefined &&
79
+ vitals.cls === undefined) {
80
+ return;
81
+ }
82
+ options.report(vitals);
83
+ }
84
+ return {
85
+ startLoad(location, ttfbMs) {
86
+ begin(location, "load");
87
+ if (current && ttfbMs !== undefined)
88
+ current.ttfbMs = roundMs(ttfbMs);
89
+ },
90
+ /**
91
+ * `replace` keeps the page view and moves it to the new route, since
92
+ * redirects and URL canonicalization replace the entry the person landed
93
+ * on. Any other change of path is a new page view.
94
+ */
95
+ navigate(location, kind) {
96
+ if (!current)
97
+ return;
98
+ if (current.location.pathname === location.pathname)
99
+ return;
100
+ if (kind === "replace") {
101
+ current.location = location;
102
+ return;
103
+ }
104
+ end();
105
+ begin(location, "client");
106
+ },
107
+ hidden() {
108
+ end();
109
+ },
110
+ /** Drops the current page view without reporting it. */
111
+ discard() {
112
+ current = null;
113
+ },
114
+ visible(location) {
115
+ if (!current)
116
+ begin(location, "resume");
117
+ },
118
+ largestContentfulPaint(startTimeMs) {
119
+ if (!current || current.lcpFinal)
120
+ return;
121
+ current.lcpMs = roundMs(Math.max(0, startTimeMs));
122
+ },
123
+ finalizeLargestContentfulPaint() {
124
+ if (current)
125
+ current.lcpFinal = true;
126
+ },
127
+ layoutShift(entry) {
128
+ const view = current;
129
+ if (!view || entry.hadRecentInput)
130
+ return;
131
+ if (view.windowValue > 0 &&
132
+ entry.startTime - view.windowLast < CLS_WINDOW_GAP_MS &&
133
+ entry.startTime - view.windowStart < CLS_WINDOW_MAX_MS) {
134
+ view.windowValue += entry.value;
135
+ }
136
+ else {
137
+ view.windowValue = entry.value;
138
+ view.windowStart = entry.startTime;
139
+ }
140
+ view.windowLast = entry.startTime;
141
+ view.cls = Math.max(view.cls, view.windowValue);
142
+ view.shifted = true;
143
+ },
144
+ interaction(entry) {
145
+ const view = current;
146
+ const id = entry.interactionId;
147
+ if (!view || !id)
148
+ return;
149
+ view.interactionIds.add(id);
150
+ const longest = view.longestInteractions;
151
+ const existing = longest.find((item) => item.id === id);
152
+ if (existing) {
153
+ existing.duration = Math.max(existing.duration, entry.duration);
154
+ }
155
+ else if (longest.length < LONGEST_INTERACTIONS_KEPT ||
156
+ entry.duration > longest[longest.length - 1].duration) {
157
+ longest.push({ id, duration: entry.duration });
158
+ }
159
+ else {
160
+ return;
161
+ }
162
+ longest.sort((a, b) => b.duration - a.duration);
163
+ longest.length = Math.min(longest.length, LONGEST_INTERACTIONS_KEPT);
164
+ },
165
+ };
166
+ }
167
+ function supportedEntryTypes() {
168
+ return typeof PerformanceObserver !== "undefined"
169
+ ? (PerformanceObserver.supportedEntryTypes ?? [])
170
+ : [];
171
+ }
172
+ function activationStart() {
173
+ const navigation = performance.getEntriesByType("navigation")[0];
174
+ return navigation?.activationStart ?? 0;
175
+ }
176
+ function timeToFirstByte() {
177
+ const navigation = performance.getEntriesByType("navigation")[0];
178
+ if (!navigation || navigation.responseStart <= 0)
179
+ return undefined;
180
+ if (navigation.responseStart > performance.now())
181
+ return undefined;
182
+ return Math.max(0, navigation.responseStart - activationStart());
183
+ }
184
+ /**
185
+ * Starts measuring the current document. Returns null where the browser has
186
+ * no PerformanceObserver, so no page view is reported as measured.
187
+ */
188
+ export function installWebVitals(locate, report) {
189
+ if (typeof window === "undefined" || typeof document === "undefined") {
190
+ return null;
191
+ }
192
+ const types = supportedEntryTypes();
193
+ if (!types.length)
194
+ return null;
195
+ const performanceWithCount = performance;
196
+ let measuresLayoutShift = false;
197
+ const tracker = createWebVitalsTracker({
198
+ measuresLayoutShift: () => measuresLayoutShift,
199
+ report,
200
+ interactionCount: () => performanceWithCount.interactionCount,
201
+ });
202
+ const prerendering = document
203
+ .prerendering;
204
+ let firstHiddenAt = document.visibilityState === "hidden" && !prerendering ? 0 : Infinity;
205
+ const observers = new Map();
206
+ /** False when the browser cannot observe `type`, so its metric stays absent. */
207
+ const observe = (type, handle, init = {}) => {
208
+ if (!types.includes(type))
209
+ return false;
210
+ try {
211
+ const observer = new PerformanceObserver((list) => handle(list.getEntries()));
212
+ observer.observe({ type, buffered: true, ...init });
213
+ observers.set(observer, handle);
214
+ return true;
215
+ }
216
+ catch {
217
+ // coercion-ok: false tells the caller the type is unobserved.
218
+ return false;
219
+ }
220
+ };
221
+ const flush = () => {
222
+ for (const [observer, handle] of observers) {
223
+ const records = observer.takeRecords();
224
+ if (records.length)
225
+ handle(records);
226
+ }
227
+ };
228
+ tracker.startLoad(locate(), timeToFirstByte());
229
+ // A page loaded in a background tab: nobody saw its load, so it is not a
230
+ // page view, and what happens once someone switches to it is a resume like
231
+ // any other. Ending it instead would report its TTFB as a load.
232
+ if (firstHiddenAt === 0)
233
+ tracker.discard();
234
+ const handleLcp = (entries) => {
235
+ const start = activationStart();
236
+ for (const entry of entries) {
237
+ if (entry.startTime < firstHiddenAt) {
238
+ tracker.largestContentfulPaint(entry.startTime - start);
239
+ }
240
+ }
241
+ };
242
+ const handleShifts = (entries) => {
243
+ for (const entry of entries) {
244
+ tracker.layoutShift(entry);
245
+ }
246
+ };
247
+ const handleInteractions = (entries) => {
248
+ for (const entry of entries) {
249
+ tracker.interaction(entry);
250
+ }
251
+ };
252
+ observe("largest-contentful-paint", handleLcp);
253
+ measuresLayoutShift = observe("layout-shift", handleShifts);
254
+ observe("event", handleInteractions, { durationThreshold: 16 });
255
+ observe("first-input", handleInteractions);
256
+ const finalizeLcp = () => {
257
+ flush();
258
+ tracker.finalizeLargestContentfulPaint();
259
+ };
260
+ for (const type of ["keydown", "click"]) {
261
+ window.addEventListener(type, finalizeLcp, { capture: true, once: true });
262
+ }
263
+ const pageHidden = () => {
264
+ flush();
265
+ tracker.finalizeLargestContentfulPaint();
266
+ tracker.hidden();
267
+ };
268
+ document.addEventListener("visibilitychange", (event) => {
269
+ if (document.visibilityState === "hidden") {
270
+ firstHiddenAt = Math.min(firstHiddenAt, event.timeStamp);
271
+ pageHidden();
272
+ }
273
+ else {
274
+ tracker.visible(locate());
275
+ }
276
+ }, { capture: true });
277
+ window.addEventListener("pagehide", pageHidden, { capture: true });
278
+ window.addEventListener("pageshow", (event) => {
279
+ if (event.persisted)
280
+ tracker.visible(locate());
281
+ }, { capture: true });
282
+ return {
283
+ navigate(kind) {
284
+ flush();
285
+ tracker.navigate(locate(), kind);
286
+ },
287
+ };
288
+ }
@@ -8,8 +8,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
8
8
  state: string;
9
9
  }>>;
10
10
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
11
- error: string;
12
11
  ok?: undefined;
12
+ error: string;
13
13
  } | {
14
14
  error?: undefined;
15
15
  ok: boolean;
@@ -42,8 +42,8 @@ declare const _default: import("../../action.js").ActionDefinition<{
42
42
  url: string;
43
43
  id: string;
44
44
  provider: string;
45
- configured?: undefined;
46
45
  error?: undefined;
46
+ configured?: undefined;
47
47
  } | {
48
48
  url?: undefined;
49
49
  id?: undefined;
@@ -49,6 +49,8 @@ export interface MCPConfig {
49
49
  connectorCatalog: string[];
50
50
  instructions?: string;
51
51
  widgets?: boolean;
52
+ widgetDomain?: string;
53
+ widgetDiagnostic?: "tiny-html" | "no-frame-domains";
52
54
  keyToolNames?: readonly string[];
53
55
  toolDescriptions?: Record<string, string>;
54
56
  toolParameterDescriptions?: Record<string, Record<string, string>>;