@agent-native/core 0.207.1 → 0.207.2-nightly-20261013011333

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 (51) hide show
  1. package/dist/agent/production-agent.js +2 -0
  2. package/dist/cli/design-connect.d.ts +6 -0
  3. package/dist/cli/design-connect.js +880 -9
  4. package/dist/client/action-query-cache.d.ts +3 -1
  5. package/dist/client/action-query-cache.js +628 -161
  6. package/dist/client/action-query-cache.session-test-fixture.d.ts +49 -0
  7. package/dist/client/action-query-cache.session-test-fixture.js +151 -0
  8. package/dist/client/action-query-cache.test-fixtures.d.ts +2 -0
  9. package/dist/client/action-query-cache.test-fixtures.js +56 -0
  10. package/dist/client/motion-text.css +3 -0
  11. package/dist/client/motion-text.d.ts +38 -0
  12. package/dist/client/motion-text.js +551 -0
  13. package/dist/client/org/hooks.d.ts +3 -1
  14. package/dist/client/org/hooks.js +8 -2
  15. package/dist/client/route-chunk-recovery.d.ts +2 -0
  16. package/dist/client/route-chunk-recovery.js +11 -0
  17. package/dist/client/use-action.d.ts +10 -2
  18. package/dist/client/use-action.js +81 -12
  19. package/dist/client/use-settings-shortcut.js +8 -3
  20. package/dist/collab/awareness.d.ts +2 -2
  21. package/dist/collab/routes.d.ts +1 -1
  22. package/dist/collab/struct-routes.d.ts +1 -1
  23. package/dist/extensions/fetch-tool.js +8 -2
  24. package/dist/extensions/routes.js +7 -3
  25. package/dist/extensions/web-content.js +17 -2
  26. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  27. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  28. package/dist/mcp/build-server.js +5 -0
  29. package/dist/observability/routes.d.ts +4 -4
  30. package/dist/progress/routes.d.ts +1 -1
  31. package/dist/resources/handlers.d.ts +1 -1
  32. package/dist/secrets/routes.d.ts +5 -5
  33. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  34. package/dist/server/agent-engine-default-model-route.d.ts +2 -2
  35. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  36. package/dist/server/realtime-token.d.ts +1 -1
  37. package/dist/server/transcribe-voice.d.ts +1 -1
  38. package/dist/server/visual-edit-bridge-capability.d.ts +26 -0
  39. package/dist/server/visual-edit-bridge-capability.js +233 -0
  40. package/dist/shared/motion-easing.d.ts +6 -0
  41. package/dist/shared/motion-easing.js +109 -0
  42. package/dist/shared/motion-source-node-id.d.ts +3 -0
  43. package/dist/shared/motion-source-node-id.js +12 -0
  44. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  45. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +35 -36
  46. package/dist/triggers/actions/manage-automation.d.ts +5 -5
  47. package/dist/vite/client.js +2 -0
  48. package/dist/vite/motion-source-provenance-plugin.d.ts +3 -0
  49. package/dist/vite/motion-source-provenance-plugin.js +339 -0
  50. package/package.json +14 -5
  51. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +35 -36
@@ -0,0 +1,551 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Children, cloneElement, isValidElement, useCallback, useEffect, useRef, useState, } from "react";
3
+ import "./motion-text.css";
4
+ import { isMotionEaseVariableReference, isValidMotionEase, resolveMotionEaseForWebAnimations, } from "../shared/motion-easing.js";
5
+ const MOTION_TEXT_UNITS = new Set([
6
+ "character",
7
+ "word",
8
+ "line",
9
+ "paragraph",
10
+ ]);
11
+ const MOTION_TEXT_PROPERTIES = new Set([
12
+ "opacity",
13
+ "translate",
14
+ "scale",
15
+ "rotate",
16
+ "filter",
17
+ ]);
18
+ const MOTION_TEXT_PLAYBACK_MODES = new Set([
19
+ "loop",
20
+ "once",
21
+ "ping-pong",
22
+ ]);
23
+ const PARAGRAPH_TAGS = new Set([
24
+ "blockquote",
25
+ "h1",
26
+ "h2",
27
+ "h3",
28
+ "h4",
29
+ "h5",
30
+ "h6",
31
+ "li",
32
+ "p",
33
+ ]);
34
+ const INLINE_TEXT_TAGS = new Set([
35
+ "a",
36
+ "abbr",
37
+ "b",
38
+ "bdi",
39
+ "bdo",
40
+ "cite",
41
+ "code",
42
+ "data",
43
+ "del",
44
+ "dfn",
45
+ "em",
46
+ "i",
47
+ "ins",
48
+ "kbd",
49
+ "mark",
50
+ "q",
51
+ "s",
52
+ "samp",
53
+ "small",
54
+ "span",
55
+ "strong",
56
+ "sub",
57
+ "sup",
58
+ "time",
59
+ "u",
60
+ "var",
61
+ ]);
62
+ const MAX_TEXT_UNITS = 512;
63
+ const PREVIEW_MESSAGE_TYPES = new Set([
64
+ "motion-preview",
65
+ "motion-preview-clear",
66
+ ]);
67
+ /**
68
+ * Applies static text property animations to a single intrinsic JSX host element.
69
+ * Importing this entry includes the package stylesheet; the same asset is
70
+ * available as `@agent-native/core/client/motion-text.css` for CSS-only setups.
71
+ */
72
+ export function AgentNativeMotionText({ animation, animations: animationList, playbackMode = "once", children, }) {
73
+ if (animation && animationList) {
74
+ throw new Error("AgentNativeMotionText accepts animation or animations, not both.");
75
+ }
76
+ const animations = animationList ?? (animation ? [animation] : []);
77
+ validateAnimations(animations);
78
+ const primaryAnimation = animations[0];
79
+ validatePlaybackMode(playbackMode);
80
+ const child = Children.only(children);
81
+ if (!isValidElement(child) || typeof child.type !== "string") {
82
+ throw new Error("AgentNativeMotionText requires exactly one intrinsic host JSX child.");
83
+ }
84
+ const host = child;
85
+ if (host.props["data-agent-native-node-id"] !== primaryAnimation.targetNodeId) {
86
+ throw new Error("AgentNativeMotionText animation.targetNodeId must match the child’s static data-agent-native-node-id.");
87
+ }
88
+ const [motionAllowed, setMotionAllowed] = useState(false);
89
+ const hostRef = useRef(null);
90
+ const childRef = host.props.ref;
91
+ const setHostRef = useCallback((element) => {
92
+ hostRef.current = element;
93
+ if (typeof childRef === "function") {
94
+ if (!element) {
95
+ childRef(null);
96
+ return;
97
+ }
98
+ const cleanup = childRef(element);
99
+ return () => {
100
+ hostRef.current = null;
101
+ if (typeof cleanup === "function")
102
+ cleanup();
103
+ else
104
+ childRef(null);
105
+ };
106
+ }
107
+ assignRef(childRef, element);
108
+ if (element) {
109
+ return () => {
110
+ hostRef.current = null;
111
+ assignRef(childRef, null);
112
+ };
113
+ }
114
+ }, [childRef]);
115
+ useEffect(() => {
116
+ if (typeof window.matchMedia !== "function") {
117
+ setMotionAllowed(true);
118
+ return;
119
+ }
120
+ const preference = window.matchMedia("(prefers-reduced-motion: reduce)");
121
+ const updatePreference = () => setMotionAllowed(!preference.matches);
122
+ updatePreference();
123
+ preference.addEventListener?.("change", updatePreference);
124
+ return () => preference.removeEventListener?.("change", updatePreference);
125
+ }, []);
126
+ useEffect(() => {
127
+ if (!motionAllowed)
128
+ return;
129
+ const hostElement = hostRef.current;
130
+ if (!hostElement)
131
+ return;
132
+ const elements = resolveMotionUnits(hostElement, primaryAnimation);
133
+ if (elements.length === 0) {
134
+ throw new Error("AgentNativeMotionText found no animatable text units.");
135
+ }
136
+ const groupCount = elements.reduce((count, entry) => Math.max(count, entry.index + 1), 0);
137
+ if (groupCount > MAX_TEXT_UNITS) {
138
+ throw new Error(`AgentNativeMotionText supports at most ${MAX_TEXT_UNITS} animated units.`);
139
+ }
140
+ if ((groupCount - 1) * primaryAnimation.staggerMs > 120_000) {
141
+ throw new Error("AgentNativeMotionText stagger exceeds the 120000ms runtime limit.");
142
+ }
143
+ const previewAnimations = [];
144
+ try {
145
+ for (const track of animations) {
146
+ for (const entry of elements) {
147
+ if (typeof entry.element.animate !== "function") {
148
+ throw new Error("AgentNativeMotionText requires the Web Animations API.");
149
+ }
150
+ const delayIndex = track.direction === "reverse"
151
+ ? groupCount - 1 - entry.index
152
+ : entry.index;
153
+ const easingStyle = track.keyframes.some((keyframe) => isMotionEaseVariableReference(keyframe.ease ?? ""))
154
+ ? window.getComputedStyle(entry.element)
155
+ : null;
156
+ const keyframes = track.keyframes.map((keyframe) => ({
157
+ offset: keyframe.t,
158
+ easing: resolveMotionEaseForWebAnimations(keyframe.ease ?? "ease", (name) => easingStyle?.getPropertyValue(name) ?? ""),
159
+ [track.property]: keyframe.value,
160
+ }));
161
+ const delay = (track.delayMs ?? 0) + delayIndex * track.staggerMs;
162
+ const runningAnimation = entry.element.animate(keyframes, {
163
+ duration: track.durationMs,
164
+ delay,
165
+ iterations: playbackMode === "once" ? 1 : Infinity,
166
+ direction: playbackMode === "ping-pong" ? "alternate" : "normal",
167
+ fill: "both",
168
+ });
169
+ previewAnimations.push({
170
+ animation: runningAnimation,
171
+ delay,
172
+ durationMs: track.durationMs,
173
+ });
174
+ }
175
+ }
176
+ }
177
+ catch (error) {
178
+ for (const entry of previewAnimations) {
179
+ entry.animation.cancel();
180
+ }
181
+ throw error;
182
+ }
183
+ let isPreviewing = false;
184
+ const handlePreviewMessage = (event) => {
185
+ if (event.source !== window.parent ||
186
+ !isMotionPreviewMessage(event.data)) {
187
+ return;
188
+ }
189
+ if (event.data.type === "motion-preview-clear") {
190
+ if (!isPreviewing)
191
+ return;
192
+ isPreviewing = false;
193
+ for (const entry of previewAnimations) {
194
+ entry.animation.currentTime = 0;
195
+ entry.animation.play();
196
+ }
197
+ return;
198
+ }
199
+ const t = Number(event.data.t);
200
+ const timelineDuration = Number(event.data.durationMs);
201
+ if (!Number.isFinite(t) || !Number.isFinite(timelineDuration))
202
+ return;
203
+ if (timelineDuration <= 0)
204
+ return;
205
+ if (!isPreviewing) {
206
+ isPreviewing = true;
207
+ for (const entry of previewAnimations)
208
+ entry.animation.pause();
209
+ }
210
+ const timelineTime = Math.max(0, Math.min(1, t)) * timelineDuration;
211
+ for (const entry of previewAnimations) {
212
+ const elapsed = Math.max(0, timelineTime - entry.delay);
213
+ entry.animation.currentTime =
214
+ playbackMode === "once"
215
+ ? Math.min(entry.durationMs, elapsed)
216
+ : elapsed;
217
+ }
218
+ };
219
+ window.addEventListener("message", handlePreviewMessage);
220
+ return () => {
221
+ window.removeEventListener("message", handlePreviewMessage);
222
+ for (const entry of previewAnimations) {
223
+ entry.animation.cancel();
224
+ }
225
+ };
226
+ }, [animations, motionAllowed, playbackMode, primaryAnimation]);
227
+ const nextUnitIndex = { current: 0 };
228
+ const outputChildren = motionAllowed
229
+ ? primaryAnimation.unit === "paragraph"
230
+ ? renderParagraphs(host.props.children, nextUnitIndex)
231
+ : renderTextNodes(host.props.children, primaryAnimation, nextUnitIndex)
232
+ : host.props.children;
233
+ return cloneElement(host, { ref: setHostRef, children: outputChildren });
234
+ }
235
+ function validatePlaybackMode(mode) {
236
+ if (!MOTION_TEXT_PLAYBACK_MODES.has(mode)) {
237
+ throw new Error("AgentNativeMotionText playbackMode is unsupported.");
238
+ }
239
+ }
240
+ function validateAnimations(animations) {
241
+ if (!Array.isArray(animations) || animations.length === 0) {
242
+ throw new Error("AgentNativeMotionText requires at least one animation.");
243
+ }
244
+ const first = animations[0];
245
+ const properties = new Set();
246
+ for (const animation of animations) {
247
+ validateAnimation(animation);
248
+ if (animation.targetNodeId !== first.targetNodeId ||
249
+ animation.unit !== first.unit ||
250
+ animation.direction !== first.direction ||
251
+ animation.staggerMs !== first.staggerMs) {
252
+ throw new Error("AgentNativeMotionText animations for one target must share target, unit, direction, and stagger.");
253
+ }
254
+ if (properties.has(animation.property)) {
255
+ throw new Error(`AgentNativeMotionText property "${animation.property}" is duplicated.`);
256
+ }
257
+ properties.add(animation.property);
258
+ }
259
+ }
260
+ function validateAnimation(animation) {
261
+ if (!animation || typeof animation !== "object") {
262
+ throw new Error("AgentNativeMotionText animation must be a static object.");
263
+ }
264
+ if (typeof animation.targetNodeId !== "string" ||
265
+ !/^[A-Za-z0-9_-]+$/.test(animation.targetNodeId)) {
266
+ throw new Error("AgentNativeMotionText targetNodeId is invalid.");
267
+ }
268
+ if (!MOTION_TEXT_UNITS.has(animation.unit)) {
269
+ throw new Error("AgentNativeMotionText unit is unsupported.");
270
+ }
271
+ if (animation.direction !== "forward" && animation.direction !== "reverse") {
272
+ throw new Error("AgentNativeMotionText direction is unsupported.");
273
+ }
274
+ if (!MOTION_TEXT_PROPERTIES.has(animation.property)) {
275
+ throw new Error("AgentNativeMotionText property is unsupported.");
276
+ }
277
+ if (!Number.isFinite(animation.staggerMs) ||
278
+ animation.staggerMs < 0 ||
279
+ animation.staggerMs > 5000) {
280
+ throw new Error("AgentNativeMotionText staggerMs is invalid.");
281
+ }
282
+ if (animation.delayMs !== undefined &&
283
+ (!Number.isFinite(animation.delayMs) ||
284
+ animation.delayMs < 0 ||
285
+ animation.delayMs > 120_000)) {
286
+ throw new Error("AgentNativeMotionText delayMs is invalid.");
287
+ }
288
+ if (!Number.isFinite(animation.durationMs) ||
289
+ animation.durationMs <= 0 ||
290
+ animation.durationMs > 120_000) {
291
+ throw new Error("AgentNativeMotionText durationMs is invalid.");
292
+ }
293
+ if (!Array.isArray(animation.keyframes) ||
294
+ animation.keyframes.length < 2 ||
295
+ animation.keyframes.length > 128) {
296
+ throw new Error("AgentNativeMotionText keyframes are invalid.");
297
+ }
298
+ let previousT = -1;
299
+ for (const keyframe of animation.keyframes) {
300
+ if (!Number.isFinite(keyframe.t) ||
301
+ keyframe.t < 0 ||
302
+ keyframe.t > 1 ||
303
+ keyframe.t <= previousT ||
304
+ typeof keyframe.value !== "string" ||
305
+ keyframe.value.trim().length === 0 ||
306
+ (keyframe.ease !== undefined &&
307
+ (typeof keyframe.ease !== "string" ||
308
+ !isValidMotionEase(keyframe.ease)))) {
309
+ throw new Error("AgentNativeMotionText keyframes are invalid.");
310
+ }
311
+ previousT = keyframe.t;
312
+ }
313
+ if (animation.keyframes[0]?.t !== 0 ||
314
+ animation.keyframes[animation.keyframes.length - 1]?.t !== 1) {
315
+ throw new Error("AgentNativeMotionText keyframes must span [0, 1].");
316
+ }
317
+ }
318
+ function assignRef(ref, value) {
319
+ if (typeof ref === "function")
320
+ ref(value);
321
+ else if (ref)
322
+ ref.current = value;
323
+ }
324
+ function textTokens(text, unit) {
325
+ if (unit === "character") {
326
+ const Segmenter = Intl.Segmenter;
327
+ const parts = Segmenter
328
+ ? Array.from(new Segmenter(undefined, { granularity: "grapheme" }).segment(text), (part) => part.segment)
329
+ : Array.from(text);
330
+ return parts.map((part) => ({
331
+ text: part,
332
+ animated: !/^\s+$/u.test(part),
333
+ }));
334
+ }
335
+ const Segmenter = Intl.Segmenter;
336
+ const chunks = Segmenter
337
+ ? Array.from(new Segmenter(undefined, { granularity: "word" }).segment(text), (part) => ({
338
+ text: part.segment,
339
+ word: part.isWordLike,
340
+ }))
341
+ : (text.match(/\s+|[^\s]+/gu) ?? []).map((part) => ({
342
+ text: part,
343
+ word: !/^\s+$/u.test(part),
344
+ }));
345
+ const tokens = [];
346
+ for (let index = 0; index < chunks.length; index += 1) {
347
+ const chunk = chunks[index];
348
+ if (/^\s+$/u.test(chunk.text)) {
349
+ tokens.push({ text: chunk.text, animated: false });
350
+ }
351
+ else if (chunk.word) {
352
+ tokens.push({ text: chunk.text, animated: true });
353
+ }
354
+ else if (tokens.length && tokens[tokens.length - 1].animated) {
355
+ tokens[tokens.length - 1].text += chunk.text;
356
+ }
357
+ else {
358
+ const nextWord = chunks
359
+ .slice(index + 1)
360
+ .findIndex((candidate) => candidate.word);
361
+ if (nextWord >= 0) {
362
+ let punctuation = chunk.text;
363
+ while (index + 1 < chunks.length &&
364
+ !chunks[index + 1].word &&
365
+ !/^\s+$/u.test(chunks[index + 1].text)) {
366
+ punctuation += chunks[++index].text;
367
+ }
368
+ tokens.push({ text: punctuation, animated: true });
369
+ }
370
+ else {
371
+ tokens.push({ text: chunk.text, animated: false });
372
+ }
373
+ }
374
+ }
375
+ return tokens;
376
+ }
377
+ function renderTextNodes(node, animation, nextUnitIndex) {
378
+ const textLeaves = [];
379
+ collectTextLeaves(node, textLeaves, { current: 0 });
380
+ const text = textLeaves.map((leaf) => leaf.text).join("");
381
+ const unit = animation.unit === "character" ? "character" : "word";
382
+ const tokenValues = textTokens(text, unit);
383
+ const tokens = [];
384
+ let tokenOffset = 0;
385
+ for (const token of tokenValues) {
386
+ const start = tokenOffset;
387
+ const end = start + token.text.length;
388
+ tokenOffset = end;
389
+ tokens.push({ ...token, start, end, index: -1 });
390
+ }
391
+ for (const token of tokens) {
392
+ if (token.animated)
393
+ token.index = nextUnitIndex.current++;
394
+ }
395
+ if (nextUnitIndex.current > MAX_TEXT_UNITS) {
396
+ throw new Error(`AgentNativeMotionText supports at most ${MAX_TEXT_UNITS} animated units.`);
397
+ }
398
+ return mapTextLeaves(node, 0, textLeaves, tokens);
399
+ }
400
+ function collectTextLeaves(node, leaves, offset) {
401
+ if (typeof node === "string" || typeof node === "number") {
402
+ const text = String(node);
403
+ const start = offset.current;
404
+ leaves.push({ text, start, end: start + text.length });
405
+ offset.current += text.length;
406
+ return;
407
+ }
408
+ if (Array.isArray(node)) {
409
+ for (const child of node)
410
+ collectTextLeaves(child, leaves, offset);
411
+ return;
412
+ }
413
+ if (isValidElement(node)) {
414
+ if (typeof node.type !== "string" || !INLINE_TEXT_TAGS.has(node.type)) {
415
+ throw new Error("Character, word, and line Motion text supports only static inline host elements.");
416
+ }
417
+ collectTextLeaves(asMotionTextNode(node).props.children, leaves, offset);
418
+ }
419
+ }
420
+ function mapTextLeaves(node, leafIndex, leaves, tokens) {
421
+ if (typeof node === "string" || typeof node === "number") {
422
+ const leaf = leaves[leafIndex];
423
+ return renderTextLeaf(leaf, tokens);
424
+ }
425
+ if (Array.isArray(node)) {
426
+ let nextLeafIndex = leafIndex;
427
+ const mapped = node.map((child) => {
428
+ const mappedChild = mapTextLeaves(child, nextLeafIndex, leaves, tokens);
429
+ nextLeafIndex += countTextLeaves(child);
430
+ return mappedChild;
431
+ });
432
+ return mapped;
433
+ }
434
+ if (isValidElement(node)) {
435
+ if (typeof node.type !== "string")
436
+ return node;
437
+ const element = asMotionTextNode(node);
438
+ const children = element.props.children;
439
+ const mappedChildren = mapTextLeaves(children, leafIndex, leaves, tokens);
440
+ return cloneElement(element, { children: mappedChildren });
441
+ }
442
+ return node;
443
+ }
444
+ function renderTextLeaf(leaf, tokens) {
445
+ if (!leaf)
446
+ return null;
447
+ const parts = [];
448
+ for (const token of tokens) {
449
+ const start = Math.max(leaf.start, token.start);
450
+ const end = Math.min(leaf.end, token.end);
451
+ if (start >= end)
452
+ continue;
453
+ const text = leaf.text.slice(start - leaf.start, end - leaf.start);
454
+ if (!token.animated) {
455
+ parts.push(text);
456
+ continue;
457
+ }
458
+ parts.push(_jsx("span", { className: "agent-native-motion-text-unit", "data-agent-native-motion-text-unit": token.index, children: text }, `${token.index}-${start}`));
459
+ }
460
+ return parts;
461
+ }
462
+ function countTextLeaves(node) {
463
+ if (typeof node === "string" || typeof node === "number")
464
+ return 1;
465
+ if (Array.isArray(node))
466
+ return node.reduce((sum, child) => sum + countTextLeaves(child), 0);
467
+ if (isValidElement(node)) {
468
+ return countTextLeaves(asMotionTextNode(node).props.children);
469
+ }
470
+ return 0;
471
+ }
472
+ function renderParagraphs(node, nextUnitIndex) {
473
+ if (isValidElement(node) && typeof node.type === "string") {
474
+ const element = asMotionTextNode(node);
475
+ if (PARAGRAPH_TAGS.has(node.type)) {
476
+ const index = nextUnitIndex.current++;
477
+ return cloneElement(element, {
478
+ "data-agent-native-motion-text-unit": index,
479
+ });
480
+ }
481
+ if (Array.isArray(element.props.children)) {
482
+ let foundElement = false;
483
+ const children = element.props.children.map((child) => {
484
+ if (isValidElement(child) &&
485
+ typeof child.type === "string" &&
486
+ PARAGRAPH_TAGS.has(child.type)) {
487
+ foundElement = true;
488
+ return renderParagraphs(child, nextUnitIndex);
489
+ }
490
+ return child;
491
+ });
492
+ if (foundElement)
493
+ return cloneElement(element, { children });
494
+ }
495
+ if (isValidElement(element.props.children) &&
496
+ typeof element.props.children.type === "string" &&
497
+ PARAGRAPH_TAGS.has(element.props.children.type)) {
498
+ return cloneElement(element, {
499
+ children: renderParagraphs(element.props.children, nextUnitIndex),
500
+ });
501
+ }
502
+ if (typeof element.props.children === "string" &&
503
+ element.props.children.length > 0) {
504
+ const index = nextUnitIndex.current++;
505
+ return cloneElement(element, {
506
+ "data-agent-native-motion-text-unit": index,
507
+ });
508
+ }
509
+ }
510
+ return node;
511
+ }
512
+ function asMotionTextNode(node) {
513
+ return node;
514
+ }
515
+ function resolveMotionUnits(host, animation) {
516
+ if (animation.unit === "paragraph") {
517
+ const hostTag = host.tagName.toLowerCase();
518
+ if (PARAGRAPH_TAGS.has(hostTag))
519
+ return [{ element: host, index: 0 }];
520
+ const children = Array.from(host.children);
521
+ if (children.length &&
522
+ children.every((child) => PARAGRAPH_TAGS.has(child.tagName.toLowerCase()))) {
523
+ return children.map((element, index) => ({ element, index }));
524
+ }
525
+ return [{ element: host, index: 0 }];
526
+ }
527
+ const units = Array.from(host.querySelectorAll("[data-agent-native-motion-text-unit]"));
528
+ if (animation.unit === "line") {
529
+ const lineTops = [];
530
+ return units.map((element) => {
531
+ const top = element.getBoundingClientRect().top;
532
+ let index = lineTops.findIndex((existing) => Math.abs(existing - top) < 0.5);
533
+ if (index < 0) {
534
+ index = lineTops.length;
535
+ lineTops.push(top);
536
+ }
537
+ return { element, index };
538
+ });
539
+ }
540
+ return units.map((element) => ({
541
+ element,
542
+ index: Number(element.getAttribute("data-agent-native-motion-text-unit")),
543
+ }));
544
+ }
545
+ function isMotionPreviewMessage(value) {
546
+ if (!value || typeof value !== "object")
547
+ return false;
548
+ const message = value;
549
+ return (typeof message.type === "string" &&
550
+ PREVIEW_MESSAGE_TYPES.has(message.type));
551
+ }
@@ -88,7 +88,9 @@ export declare function useSetOrgVisualIdentity(): import("@tanstack/react-query
88
88
  } | null, {
89
89
  previous: OrgInfo | undefined;
90
90
  }>;
91
- export declare function useSwitchOrg(): import("@tanstack/react-query").UseMutationResult<any, Error, string | null, unknown>;
91
+ export declare function useSwitchOrg(options?: {
92
+ onPersisted?: (orgId: string | null) => void;
93
+ }): import("@tanstack/react-query").UseMutationResult<any, Error, string | null, unknown>;
92
94
  export declare function useDeleteOrg(): import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
93
95
  export declare function useJoinByDomain(): import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
94
96
  export declare function useSetOrgDomain(): import("@tanstack/react-query").UseMutationResult<any, Error, string | null, unknown>;
@@ -230,14 +230,20 @@ export function useSetOrgVisualIdentity() {
230
230
  },
231
231
  });
232
232
  }
233
- export function useSwitchOrg() {
233
+ export function useSwitchOrg(options = {}) {
234
234
  const qc = useQueryClient();
235
235
  return useMutation({
236
236
  mutationFn: (orgId) => apiFetch(`${orgBasePath()}/switch`, {
237
237
  method: "PUT",
238
238
  body: JSON.stringify({ orgId }),
239
239
  }),
240
- onSuccess: async () => {
240
+ onSuccess: async (_data, orgId) => {
241
+ try {
242
+ options.onPersisted?.(orgId);
243
+ }
244
+ catch {
245
+ console.error("The organization persistence callback failed.");
246
+ }
241
247
  // The persisted-results scope follows the session's org; re-read it before
242
248
  // refetching, or this org's results are saved under the old one. Loaded here,
243
249
  // not at import: use-session pulls in frame.ts, which touches window on load.
@@ -20,6 +20,8 @@ export declare function createRouteChunkRecoveryState(): RouteChunkRecoveryState
20
20
  export declare function isRouteModuleReloadMessage(value: unknown): boolean;
21
21
  export declare function isDynamicImportFailureMessage(value: unknown): boolean;
22
22
  export declare function rememberIntendedNavigation(state: RouteChunkRecoveryState, href: string, now?: number): void;
23
+ /** Preserve router-driven targets whose route module fails before history commits. */
24
+ export declare function rememberRouteChunkRecoveryNavigation(href: string, win?: Window | undefined): void;
23
25
  export declare function getFreshIntendedNavigation(state: RouteChunkRecoveryState, currentHref: string, now?: number): string | null;
24
26
  export declare function intendedHrefFromClick(win: Window, event: MouseEvent): string | null;
25
27
  /** The recorded exhaustion for this page session, if recovery ever gave up. */
@@ -2,6 +2,7 @@ import { CHUNK_RECOVERY_CACHE_BUSTER_PARAM, CHUNK_RECOVERY_ORIGINAL_HASH_PARAM,
2
2
  const INSTALL_KEY = "__agentNativeRouteChunkRecoveryInstalled";
3
3
  const INTENDED_NAV_MAX_AGE_MS = 15_000;
4
4
  const STALE_CHUNK_EXHAUSTED_KEY = "__agentNativeStaleChunkRecoveryExhausted";
5
+ const recoveryStates = new WeakMap();
5
6
  /**
6
7
  * Fired on `window` the first time a stale chunk could not be recovered by a
7
8
  * reload. The shared noise rules drop the raw dynamic-import failure because
@@ -35,6 +36,15 @@ export function rememberIntendedNavigation(state, href, now = Date.now()) {
35
36
  state.intendedHref = href;
36
37
  state.intendedAt = now;
37
38
  }
39
+ /** Preserve router-driven targets whose route module fails before history commits. */
40
+ export function rememberRouteChunkRecoveryNavigation(href, win = typeof window === "undefined" ? undefined : window) {
41
+ if (!win)
42
+ return;
43
+ const state = recoveryStates.get(win);
44
+ const sameOrigin = sameOriginHref(win, href);
45
+ if (state && sameOrigin)
46
+ rememberIntendedNavigation(state, sameOrigin);
47
+ }
38
48
  export function getFreshIntendedNavigation(state, currentHref, now = Date.now()) {
39
49
  if (!state.intendedHref)
40
50
  return null;
@@ -374,6 +384,7 @@ export function installRouteChunkRecovery(win = typeof window === "undefined" ?
374
384
  installedTarget[INSTALL_KEY] = true;
375
385
  clearChunkRecoveryCacheBuster(win);
376
386
  const state = createRouteChunkRecoveryState();
387
+ recoveryStates.set(win, state);
377
388
  win.document.addEventListener("click", (event) => {
378
389
  const href = intendedHrefFromClick(win, event);
379
390
  if (href)
@@ -1,4 +1,4 @@
1
- import type { Query, UseQueryOptions, UseMutationOptions } from "@tanstack/react-query";
1
+ import type { Query, QueryClient, UseQueryOptions, UseMutationOptions } from "@tanstack/react-query";
2
2
  /** @internal exported for tests */
3
3
  export declare function defaultActionQueryRetry(failureCount: number, error: unknown): boolean;
4
4
  /** @internal alias kept for existing specs. */
@@ -105,10 +105,18 @@ export declare function guardActionQueryRefetchInterval<TData = unknown>(refetch
105
105
  export declare function resolveActionQueryRetry(retry: unknown, failureCount: number, error: unknown): boolean;
106
106
  /** @internal exported for tests */
107
107
  export declare function resetActionCircuitTripEventsForTests(): void;
108
+ export declare function registerActionQueryCacheRevoker(client: QueryClient, revoke: () => void, bindingToken?: object): void;
109
+ /** @internal set only by the scoped action-query cache binder. */
110
+ export declare function setActionQueryCacheBindingToken(token: object | undefined): void;
111
+ export declare function setAccessDeniedActionQueryBinding(query: Query, token: object | undefined): void;
112
+ export declare function getAccessDeniedActionQueryBinding(query: Query): object | undefined;
113
+ export declare function clearAccessDeniedActionQueryBinding(query: Query): void;
108
114
  /** @internal read by the persisted query cache. */
109
115
  export declare function isBrowserPersistableActionQuery(query: Query): boolean;
116
+ /** @internal a response is persistable only in the binding active at fetch start. */
117
+ export declare function isBrowserPersistableActionQueryForBinding(query: Query, token: object): boolean;
110
118
  /** @internal used only after a persisted action result is accepted and hydrated. */
111
- export declare function markRestoredBrowserPersistableActionQuery(query: Query): void;
119
+ export declare function markRestoredBrowserPersistableActionQuery(query: Query, token?: object): void;
112
120
  export declare function revokeBrowserPersistableActionQuery(query: Query): void;
113
121
  export declare function useActionQuery<TResult = undefined, TName extends ActionName = ActionName>(actionName: TName, params?: ActionParams<TName>, options?: Omit<UseQueryOptions<TResult extends undefined ? ActionResult<TName> : TResult>, "queryKey" | "queryFn"> & {
114
122
  queryKeyScope?: readonly unknown[];