@agent-native/core 0.209.2 → 0.209.3-nightly-20261016212700

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 (79) hide show
  1. package/dist/a2a-claims.js +5 -5
  2. package/dist/agent/context-xray/plugin.js +2 -6
  3. package/dist/agent/context-xray/schema-store.d.ts +1 -0
  4. package/dist/agent/context-xray/schema-store.js +7 -0
  5. package/dist/agent/harness/store.js +3 -0
  6. package/dist/agent/observational-memory/plugin.js +2 -6
  7. package/dist/agent/observational-memory/store.js +3 -0
  8. package/dist/agent/run-store.js +3 -0
  9. package/dist/agent/tool-approval-store.js +4 -0
  10. package/dist/automation/index.d.ts +1 -1
  11. package/dist/chat-threads/store.js +3 -0
  12. package/dist/client/action-query-cache-context.d.ts +1 -0
  13. package/dist/client/action-query-cache-context.js +2 -0
  14. package/dist/client/action-query-cache.d.ts +1 -1
  15. package/dist/client/action-query-cache.js +34 -15
  16. package/dist/client/motion-text.css +8 -0
  17. package/dist/client/motion-text.d.ts +6 -0
  18. package/dist/client/motion-text.js +154 -29
  19. package/dist/client/use-action.js +18 -1
  20. package/dist/collab/routes.d.ts +1 -1
  21. package/dist/db/migrations.d.ts +1 -0
  22. package/dist/db/migrations.js +1 -1
  23. package/dist/db/runtime-facts.d.ts +7 -0
  24. package/dist/db/runtime-facts.js +18 -0
  25. package/dist/db/schema-catalog.js +4 -1
  26. package/dist/db/store-ledger.test-helpers.d.ts +5 -0
  27. package/dist/db/store-ledger.test-helpers.js +19 -0
  28. package/dist/db/store-registry.d.ts +34 -0
  29. package/dist/db/store-registry.generated.js +13 -0
  30. package/dist/db/store-registry.js +288 -46
  31. package/dist/db/versioned-store-migrations.d.ts +14 -0
  32. package/dist/db/versioned-store-migrations.js +37 -0
  33. package/dist/db/widen-columns.js +5 -2
  34. package/dist/extensions/html-shell.js +67 -0
  35. package/dist/integrations/remote-devices-store.js +3 -0
  36. package/dist/jobs/run-history.d.ts +3 -2
  37. package/dist/jobs/run-history.js +5 -5
  38. package/dist/jobs/scheduler-health.d.ts +3 -2
  39. package/dist/jobs/scheduler-health.js +5 -5
  40. package/dist/mcp/build-server.d.ts +3 -0
  41. package/dist/mcp/build-server.js +24 -7
  42. package/dist/mcp/server.js +40 -9
  43. package/dist/notifications/routes.d.ts +1 -1
  44. package/dist/oauth-tokens/store.js +3 -0
  45. package/dist/observability/routes.d.ts +4 -4
  46. package/dist/observability/store.js +4 -0
  47. package/dist/org/auto-join-domain.js +23 -15
  48. package/dist/org/context.d.ts +12 -0
  49. package/dist/org/context.js +27 -19
  50. package/dist/org/handlers.js +31 -13
  51. package/dist/org/index.d.ts +2 -1
  52. package/dist/org/index.js +1 -0
  53. package/dist/org/plugin.js +2 -4
  54. package/dist/org/schema-store.d.ts +1 -0
  55. package/dist/org/schema-store.js +13 -0
  56. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  57. package/dist/provider-api/actions/provider-api.d.ts +9 -9
  58. package/dist/resources/store.js +5 -2
  59. package/dist/server/agent-access.js +2 -6
  60. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  61. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  62. package/dist/server/auth-plugin.js +2 -6
  63. package/dist/server/auth.js +22 -2
  64. package/dist/server/better-auth-migrations.d.ts +4 -2
  65. package/dist/server/better-auth-migrations.js +18 -6
  66. package/dist/server/identity-sso-store.js +3 -0
  67. package/dist/server/realtime-token.d.ts +1 -1
  68. package/dist/server/release-migrations.d.ts +1 -1
  69. package/dist/server/release-migrations.js +3 -65
  70. package/dist/server/release-schema.js +10 -2
  71. package/dist/server/short-lived-token.d.ts +3 -2
  72. package/dist/server/short-lived-token.js +3 -2
  73. package/dist/triggers/actions/manage-automation.d.ts +3 -3
  74. package/dist/triggers/event-queue.d.ts +4 -2
  75. package/dist/triggers/event-queue.js +38 -38
  76. package/dist/usage/alerts-store.js +3 -0
  77. package/dist/workspace-connections/groups.js +4 -0
  78. package/dist/workspace-connections/store.js +3 -0
  79. package/package.json +3 -3
@@ -8,6 +8,18 @@ const MOTION_TEXT_UNITS = new Set([
8
8
  "line",
9
9
  "paragraph",
10
10
  ]);
11
+ const MOTION_TEXT_ORDERS = new Set([
12
+ "left-to-right",
13
+ "right-to-left",
14
+ "center-out",
15
+ "random",
16
+ "top-to-bottom",
17
+ "bottom-to-top",
18
+ ]);
19
+ const MOTION_TEXT_ANIMATION_DIRECTIONS = new Set([
20
+ "in",
21
+ "out",
22
+ ]);
11
23
  const MOTION_TEXT_PROPERTIES = new Set([
12
24
  "opacity",
13
25
  "translate",
@@ -61,6 +73,7 @@ const INLINE_TEXT_TAGS = new Set([
61
73
  ]);
62
74
  const MAX_TEXT_UNITS = 512;
63
75
  const PREVIEW_MESSAGE_TYPES = new Set([
76
+ "motion-preview-duration-request",
64
77
  "motion-preview",
65
78
  "motion-preview-clear",
66
79
  ]);
@@ -137,30 +150,50 @@ export function AgentNativeMotionText({ animation, animations: animationList, pl
137
150
  if (groupCount > MAX_TEXT_UNITS) {
138
151
  throw new Error(`AgentNativeMotionText supports at most ${MAX_TEXT_UNITS} animated units.`);
139
152
  }
140
- if ((groupCount - 1) * primaryAnimation.staggerMs > 120_000) {
141
- throw new Error("AgentNativeMotionText stagger exceeds the 120000ms runtime limit.");
142
- }
153
+ const animationSchedules = animations.map((track) => {
154
+ const overlap = track.overlapPercent;
155
+ const durationMs = overlap === undefined
156
+ ? track.durationMs
157
+ : track.durationMs /
158
+ (1 + Math.max(0, groupCount - 1) * (1 - overlap / 100));
159
+ const staggerMs = overlap === undefined
160
+ ? track.staggerMs
161
+ : durationMs * (1 - overlap / 100);
162
+ const spanMs = (track.delayMs ?? 0) + (groupCount - 1) * staggerMs + durationMs;
163
+ if (!Number.isFinite(spanMs) || spanMs > 120_000) {
164
+ throw new Error("AgentNativeMotionText animation span exceeds the 120000ms runtime limit.");
165
+ }
166
+ return { track, durationMs, staggerMs };
167
+ });
168
+ const orderRanks = textOrderRanks(groupCount, motionTextOrder(primaryAnimation), `${primaryAnimation.targetNodeId}|${hostElement.textContent ?? ""}`);
143
169
  const previewAnimations = [];
144
170
  try {
145
- for (const track of animations) {
171
+ for (const { track, durationMs, staggerMs } of animationSchedules) {
146
172
  for (const entry of elements) {
147
173
  if (typeof entry.element.animate !== "function") {
148
174
  throw new Error("AgentNativeMotionText requires the Web Animations API.");
149
175
  }
150
- const delayIndex = track.direction === "reverse"
151
- ? groupCount - 1 - entry.index
152
- : entry.index;
176
+ const delayIndex = orderRanks[entry.index] ?? entry.index;
153
177
  const easingStyle = track.keyframes.some((keyframe) => isMotionEaseVariableReference(keyframe.ease ?? ""))
154
178
  ? window.getComputedStyle(entry.element)
155
179
  : 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;
180
+ const animationDirection = motionTextAnimationDirection(track);
181
+ const keyframes = (animationDirection === "out"
182
+ ? [...track.keyframes].reverse()
183
+ : track.keyframes).map((keyframe, keyframeIndex) => {
184
+ const easingKeyframe = animationDirection === "out" &&
185
+ keyframeIndex < track.keyframes.length - 1
186
+ ? track.keyframes[track.keyframes.length - 2 - keyframeIndex]
187
+ : keyframe;
188
+ return {
189
+ offset: animationDirection === "out" ? 1 - keyframe.t : keyframe.t,
190
+ easing: resolveMotionEaseForWebAnimations(easingKeyframe.ease ?? "ease", (name) => easingStyle?.getPropertyValue(name) ?? ""),
191
+ [track.property]: keyframe.value,
192
+ };
193
+ });
194
+ const delay = (track.delayMs ?? 0) + delayIndex * staggerMs;
162
195
  const runningAnimation = entry.element.animate(keyframes, {
163
- duration: track.durationMs,
196
+ duration: durationMs,
164
197
  delay,
165
198
  iterations: playbackMode === "once" ? 1 : Infinity,
166
199
  direction: playbackMode === "ping-pong" ? "alternate" : "normal",
@@ -169,7 +202,7 @@ export function AgentNativeMotionText({ animation, animations: animationList, pl
169
202
  previewAnimations.push({
170
203
  animation: runningAnimation,
171
204
  delay,
172
- durationMs: track.durationMs,
205
+ durationMs,
173
206
  });
174
207
  }
175
208
  }
@@ -180,12 +213,21 @@ export function AgentNativeMotionText({ animation, animations: animationList, pl
180
213
  }
181
214
  throw error;
182
215
  }
216
+ const textTimelineDurationMs = previewAnimations.reduce((duration, entry) => Math.max(duration, entry.delay + entry.durationMs), 0);
217
+ const previewSpanKey = `react:${primaryAnimation.targetNodeId}`;
218
+ const reportPreviewSpanDuration = (durationMs) => {
219
+ window.parent.postMessage({ type: "motion-preview-span", key: previewSpanKey, durationMs }, "*");
220
+ };
183
221
  let isPreviewing = false;
184
222
  const handlePreviewMessage = (event) => {
185
223
  if (event.source !== window.parent ||
186
224
  !isMotionPreviewMessage(event.data)) {
187
225
  return;
188
226
  }
227
+ if (event.data.type === "motion-preview-duration-request") {
228
+ reportPreviewSpanDuration(textTimelineDurationMs);
229
+ return;
230
+ }
189
231
  if (event.data.type === "motion-preview-clear") {
190
232
  if (!isPreviewing)
191
233
  return;
@@ -197,28 +239,33 @@ export function AgentNativeMotionText({ animation, animations: animationList, pl
197
239
  return;
198
240
  }
199
241
  const t = Number(event.data.t);
200
- const timelineDuration = Number(event.data.durationMs);
201
- if (!Number.isFinite(t) || !Number.isFinite(timelineDuration))
242
+ const requestedTimelineDuration = Number(event.data.durationMs);
243
+ if (!Number.isFinite(t) || !Number.isFinite(requestedTimelineDuration)) {
202
244
  return;
203
- if (timelineDuration <= 0)
245
+ }
246
+ if (requestedTimelineDuration <= 0)
204
247
  return;
248
+ if (textTimelineDurationMs > requestedTimelineDuration) {
249
+ reportPreviewSpanDuration(textTimelineDurationMs);
250
+ }
205
251
  if (!isPreviewing) {
206
252
  isPreviewing = true;
207
253
  for (const entry of previewAnimations)
208
254
  entry.animation.pause();
209
255
  }
210
- const timelineTime = Math.max(0, Math.min(1, t)) * timelineDuration;
256
+ const timelineTime = Math.max(0, Math.min(1, t)) * requestedTimelineDuration;
211
257
  for (const entry of previewAnimations) {
212
- const elapsed = Math.max(0, timelineTime - entry.delay);
213
258
  entry.animation.currentTime =
214
259
  playbackMode === "once"
215
- ? Math.min(entry.durationMs, elapsed)
216
- : elapsed;
260
+ ? Math.min(entry.delay + entry.durationMs, timelineTime)
261
+ : timelineTime;
217
262
  }
218
263
  };
219
264
  window.addEventListener("message", handlePreviewMessage);
265
+ reportPreviewSpanDuration(textTimelineDurationMs);
220
266
  return () => {
221
267
  window.removeEventListener("message", handlePreviewMessage);
268
+ reportPreviewSpanDuration(0);
222
269
  for (const entry of previewAnimations) {
223
270
  entry.animation.cancel();
224
271
  }
@@ -242,14 +289,23 @@ function validateAnimations(animations) {
242
289
  throw new Error("AgentNativeMotionText requires at least one animation.");
243
290
  }
244
291
  const first = animations[0];
292
+ const firstOrder = motionTextOrder(first);
293
+ const firstAnimationDirection = motionTextAnimationDirection(first);
294
+ const firstIgnoreSpaces = motionTextIgnoreSpaces(first);
245
295
  const properties = new Set();
246
296
  for (const animation of animations) {
247
297
  validateAnimation(animation);
248
298
  if (animation.targetNodeId !== first.targetNodeId ||
249
299
  animation.unit !== first.unit ||
250
300
  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.");
301
+ motionTextAnimationDirection(animation) !== firstAnimationDirection ||
302
+ motionTextOrder(animation) !== firstOrder ||
303
+ animation.overlapPercent !== first.overlapPercent ||
304
+ (animation.unit === "character" &&
305
+ motionTextIgnoreSpaces(animation) !== firstIgnoreSpaces) ||
306
+ (animation.overlapPercent === undefined &&
307
+ animation.staggerMs !== first.staggerMs)) {
308
+ throw new Error("AgentNativeMotionText animations for one target must share target, unit, direction, animation direction, order, overlap, character whitespace, and fixed stagger settings.");
253
309
  }
254
310
  if (properties.has(animation.property)) {
255
311
  throw new Error(`AgentNativeMotionText property "${animation.property}" is duplicated.`);
@@ -271,12 +327,36 @@ function validateAnimation(animation) {
271
327
  if (animation.direction !== "forward" && animation.direction !== "reverse") {
272
328
  throw new Error("AgentNativeMotionText direction is unsupported.");
273
329
  }
330
+ if (animation.animationDirection !== undefined &&
331
+ !MOTION_TEXT_ANIMATION_DIRECTIONS.has(animation.animationDirection)) {
332
+ throw new Error("AgentNativeMotionText animationDirection is unsupported.");
333
+ }
334
+ if (animation.order !== undefined &&
335
+ !MOTION_TEXT_ORDERS.has(animation.order)) {
336
+ throw new Error("AgentNativeMotionText order is unsupported.");
337
+ }
338
+ if ((animation.order === "top-to-bottom" ||
339
+ animation.order === "bottom-to-top") &&
340
+ animation.unit !== "line" &&
341
+ animation.unit !== "paragraph") {
342
+ throw new Error("AgentNativeMotionText vertical order requires line or paragraph units.");
343
+ }
344
+ if (animation.overlapPercent !== undefined &&
345
+ (!Number.isFinite(animation.overlapPercent) ||
346
+ animation.overlapPercent < 0 ||
347
+ animation.overlapPercent > 100)) {
348
+ throw new Error("AgentNativeMotionText overlapPercent must be between 0 and 100.");
349
+ }
350
+ if (animation.ignoreSpaces !== undefined &&
351
+ typeof animation.ignoreSpaces !== "boolean") {
352
+ throw new Error("AgentNativeMotionText ignoreSpaces must be a boolean.");
353
+ }
274
354
  if (!MOTION_TEXT_PROPERTIES.has(animation.property)) {
275
355
  throw new Error("AgentNativeMotionText property is unsupported.");
276
356
  }
277
357
  if (!Number.isFinite(animation.staggerMs) ||
278
358
  animation.staggerMs < 0 ||
279
- animation.staggerMs > 5000) {
359
+ animation.staggerMs > 120_000) {
280
360
  throw new Error("AgentNativeMotionText staggerMs is invalid.");
281
361
  }
282
362
  if (animation.delayMs !== undefined &&
@@ -321,7 +401,46 @@ function assignRef(ref, value) {
321
401
  else if (ref)
322
402
  ref.current = value;
323
403
  }
324
- function textTokens(text, unit) {
404
+ function motionTextAnimationDirection(animation) {
405
+ return animation.animationDirection ?? "in";
406
+ }
407
+ function motionTextOrder(animation) {
408
+ return (animation.order ??
409
+ (animation.direction === "reverse" ? "right-to-left" : "left-to-right"));
410
+ }
411
+ function motionTextIgnoreSpaces(animation) {
412
+ return animation.ignoreSpaces ?? true;
413
+ }
414
+ function textOrderRanks(count, order, seed) {
415
+ const indexes = Array.from({ length: count }, (_, index) => index);
416
+ if (order === "right-to-left" || order === "bottom-to-top") {
417
+ indexes.reverse();
418
+ }
419
+ else if (order === "center-out") {
420
+ const center = (count - 1) / 2;
421
+ indexes.sort((left, right) => Math.abs(left - center) - Math.abs(right - center) || left - right);
422
+ }
423
+ else if (order === "random") {
424
+ let state = 2_166_136_261;
425
+ for (let index = 0; index < seed.length; index += 1) {
426
+ state = Math.imul(state ^ seed.charCodeAt(index), 16_777_619);
427
+ }
428
+ for (let index = indexes.length - 1; index > 0; index -= 1) {
429
+ state = (Math.imul(state, 1_664_525) + 1_013_904_223) >>> 0;
430
+ const swapIndex = state % (index + 1);
431
+ [indexes[index], indexes[swapIndex]] = [
432
+ indexes[swapIndex],
433
+ indexes[index],
434
+ ];
435
+ }
436
+ }
437
+ const ranks = [];
438
+ indexes.forEach((index, rank) => {
439
+ ranks[index] = rank;
440
+ });
441
+ return ranks;
442
+ }
443
+ function textTokens(text, unit, ignoreSpaces) {
325
444
  if (unit === "character") {
326
445
  const Segmenter = Intl.Segmenter;
327
446
  const parts = Segmenter
@@ -329,7 +448,7 @@ function textTokens(text, unit) {
329
448
  : Array.from(text);
330
449
  return parts.map((part) => ({
331
450
  text: part,
332
- animated: !/^\s+$/u.test(part),
451
+ animated: !ignoreSpaces || !/^\s+$/u.test(part),
333
452
  }));
334
453
  }
335
454
  const Segmenter = Intl.Segmenter;
@@ -346,7 +465,7 @@ function textTokens(text, unit) {
346
465
  for (let index = 0; index < chunks.length; index += 1) {
347
466
  const chunk = chunks[index];
348
467
  if (/^\s+$/u.test(chunk.text)) {
349
- tokens.push({ text: chunk.text, animated: false });
468
+ tokens.push({ text: chunk.text, animated: !ignoreSpaces });
350
469
  }
351
470
  else if (chunk.word) {
352
471
  tokens.push({ text: chunk.text, animated: true });
@@ -379,7 +498,8 @@ function renderTextNodes(node, animation, nextUnitIndex) {
379
498
  collectTextLeaves(node, textLeaves, { current: 0 });
380
499
  const text = textLeaves.map((leaf) => leaf.text).join("");
381
500
  const unit = animation.unit === "character" ? "character" : "word";
382
- const tokenValues = textTokens(text, unit);
501
+ const ignoreSpaces = animation.unit === "character" ? motionTextIgnoreSpaces(animation) : true;
502
+ const tokenValues = textTokens(text, unit, ignoreSpaces);
383
503
  const tokens = [];
384
504
  let tokenOffset = 0;
385
505
  for (const token of tokenValues) {
@@ -455,6 +575,11 @@ function renderTextLeaf(leaf, tokens) {
455
575
  parts.push(text);
456
576
  continue;
457
577
  }
578
+ if (/^\s+$/u.test(token.text)) {
579
+ parts.push(text);
580
+ parts.push(_jsx("span", { "aria-hidden": "true", className: "agent-native-motion-text-unit agent-native-motion-text-space-unit", "data-agent-native-motion-text-unit": token.index }, `${token.index}-${start}-space`));
581
+ continue;
582
+ }
458
583
  parts.push(_jsx("span", { className: "agent-native-motion-text-unit", "data-agent-native-motion-text-unit": token.index, children: text }, `${token.index}-${start}`));
459
584
  }
460
585
  return parts;
@@ -1,4 +1,5 @@
1
1
  import { hashKey, useQuery, useMutation, useQueryClient, } from "@tanstack/react-query";
2
+ import { useContext } from "react";
2
3
  import { ACTION_BATCH_ACTION_NAME } from "../shared/action-batch.js";
3
4
  import { ACTION_BROWSER_PERSIST_ALLOW, ACTION_BROWSER_PERSIST_HEADER, } from "../shared/action-browser-persist.js";
4
5
  import { ACTION_CHANGE_MARKER_FAILED, ACTION_CHANGE_MARKER_HEADER, } from "../shared/action-change-marker-header.js";
@@ -6,6 +7,7 @@ import { SLOW_ACTION_RESPONSE_MS } from "../shared/analytics-events.js";
6
7
  import { ANALYTICS_CLIENT_PLATFORM_HEADER } from "../shared/analytics-platform.js";
7
8
  import { actionCircuitRemainingMs, actionErrorCode, actionErrorRetryAfterMs, actionErrorStatus, assertActionCircuitClosed, endsActionPolling, isActionCircuitOpenError, isTerminalActionError, recordActionFailure, resetActionFailureCircuit, resetActionFailureCircuits, } from "./action-failure-circuit.js";
8
9
  import { fetchActionGet } from "./action-get-batch.js";
10
+ import { trustedActionQueryCacheBindingPendingContext } from "./action-query-cache-context.js";
9
11
  import { ACTION_RESOURCES_META_KEY, actionQueryAffectedByResources, } from "./action-query-scope.js";
10
12
  import { getAnalyticsClientPlatform } from "./analytics-platform.js";
11
13
  import { getOrCreateAnalyticsSessionId } from "./analytics-session.js";
@@ -867,8 +869,16 @@ function canBatchActionQueryFetch(query) {
867
869
  }
868
870
  export function useActionQuery(actionName, params, options) {
869
871
  const apiDisabled = Boolean(agentNativeApiDisabledReason());
870
- const { refetchInterval, retry: callerRetry, queryKeyScope, resources, batchRefetches, ...restOptions } = options ?? {};
872
+ const { refetchInterval, retry: callerRetry, enabled: callerEnabled, queryKeyScope, resources, batchRefetches, ...restOptions } = options ?? {};
871
873
  const queryKey = ["action", actionName, params, ...(queryKeyScope ?? [])];
874
+ const trustedBindingPending = useContext(trustedActionQueryCacheBindingPendingContext);
875
+ const queryClient = useQueryClient();
876
+ const existingQuery = trustedBindingPending
877
+ ? queryClient.getQueryCache().find({ queryKey, exact: true })
878
+ : undefined;
879
+ const deferFetchUntilBound = trustedBindingPending &&
880
+ existingQuery?.state.fetchStatus !== "fetching" &&
881
+ existingQuery?.state.data === undefined;
872
882
  const circuitKey = () => hashKey(queryKey);
873
883
  return useQuery({
874
884
  queryKey,
@@ -935,6 +945,13 @@ export function useActionQuery(actionName, params, options) {
935
945
  },
936
946
  retryDelay: defaultActionQueryRetryDelay,
937
947
  ...restOptions,
948
+ enabled: (query) => {
949
+ if (deferFetchUntilBound)
950
+ return false;
951
+ return typeof callerEnabled === "function"
952
+ ? callerEnabled(query)
953
+ : callerEnabled !== false;
954
+ },
938
955
  ...(resources || batchRefetches === false
939
956
  ? {
940
957
  meta: {
@@ -13,8 +13,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
13
13
  };
14
14
  }>>;
15
15
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- ok?: undefined;
17
16
  error: string;
17
+ ok?: undefined;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -3,6 +3,7 @@ type NitroPluginDef = (nitroApp: any) => void | Promise<void>;
3
3
  export declare function isDuplicateColumnError(err: unknown): boolean;
4
4
  /** True when the connected Postgres role cannot apply the migration. */
5
5
  export declare function isPermissionError(err: unknown): boolean;
6
+ export declare function splitSqlStatements(sql: string): string[];
6
7
  export interface RunMigrationsOptions {
7
8
  runInServerlessRequest?: boolean;
8
9
  table: string;
@@ -80,7 +80,7 @@ function isMissingRelationError(err) {
80
80
  const e = err;
81
81
  return (e?.code === "42P01" || /relation .* does not exist/i.test(e?.message ?? ""));
82
82
  }
83
- function splitSqlStatements(sql) {
83
+ export function splitSqlStatements(sql) {
84
84
  const out = [];
85
85
  let buf = "";
86
86
  let i = 0;
@@ -9,3 +9,10 @@ export declare function retryOnDdlRace<T>(fn: () => Promise<T>): Promise<T>;
9
9
  * client, so modules that mock `./client.js` keep working.
10
10
  */
11
11
  export declare function dbClientGeneration(): number;
12
+ /**
13
+ * True while a store migration runs that the ledger will record once it
14
+ * resolves. Helpers that swallow failures elsewhere must rethrow here, or the
15
+ * ledger records a step that never happened and never retries it.
16
+ */
17
+ export declare function isRecordingStoreMigration(): boolean;
18
+ export declare function runRecordingStoreMigration<T>(run: () => Promise<T>): Promise<T>;
@@ -1,3 +1,4 @@
1
+ import { getAsyncLocalStorageCtor } from "../shared/optional-node-builtins.js";
1
2
  /**
2
3
  * Dependency-free database runtime facts. Kept out of `./client.js` so the
3
4
  * store runner does not require every `vi.mock("../db/client.js")` to stub them.
@@ -39,3 +40,20 @@ export function dbClientGeneration() {
39
40
  const proc = globalThis.process;
40
41
  return proc?.__agentNativePgliteClientGeneration ?? 0;
41
42
  }
43
+ const AsyncLocalStorageCtor = getAsyncLocalStorageCtor();
44
+ const recordingStoreMigration = AsyncLocalStorageCtor
45
+ ? new AsyncLocalStorageCtor()
46
+ : undefined;
47
+ /**
48
+ * True while a store migration runs that the ledger will record once it
49
+ * resolves. Helpers that swallow failures elsewhere must rethrow here, or the
50
+ * ledger records a step that never happened and never retries it.
51
+ */
52
+ export function isRecordingStoreMigration() {
53
+ return recordingStoreMigration?.getStore() === true;
54
+ }
55
+ export function runRecordingStoreMigration(run) {
56
+ return recordingStoreMigration
57
+ ? recordingStoreMigration.run(true, run)
58
+ : run();
59
+ }
@@ -6,7 +6,7 @@
6
6
  * has no `pg_dump`.
7
7
  */
8
8
  /** Tables whose rows are migration bookkeeping, dumped with their data. */
9
- const BOOKKEEPING_TABLE = /(?:^_.*migrations?$|_migrations$|^_an_store_migrations$)/;
9
+ const BOOKKEEPING_TABLE = /^_[a-z0-9_]*migrations(?:_named)?$/;
10
10
  async function rows(exec, sql) {
11
11
  return (await exec.execute(sql)).rows;
12
12
  }
@@ -21,6 +21,9 @@ function literal(value) {
21
21
  }
22
22
  if (typeof value === "boolean")
23
23
  return value ? "TRUE" : "FALSE";
24
+ // Locale-formatted dates do not parse back; ISO 8601 does, in any time zone.
25
+ if (value instanceof Date)
26
+ return `'${value.toISOString()}'`;
24
27
  return `'${String(value).replace(/'/g, "''")}'`;
25
28
  }
26
29
  const COLUMNS_SQL = `
@@ -0,0 +1,5 @@
1
+ export declare function isStoreLedgerStatement(sql: string): boolean;
2
+ export declare function storeLedgerResult(sql: string): {
3
+ rows: Array<Record<string, unknown>>;
4
+ rowsAffected: number;
5
+ } | undefined;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * For specs that mock `getDbExec()` with a hand-written executor. Outside
3
+ * hosted runtimes a store records its migrations in `_an_store_migrations`
4
+ * (see `store-registry.ts`), so a strict mock sees those statements too.
5
+ * Answer them as an empty ledger: every store then applies its migrations
6
+ * against the mock once per executor, as it did before the ledger.
7
+ */
8
+ const STORE_LEDGER_STATEMENT = /\b_an_store_migration(?:s|_lock)\b/;
9
+ export function isStoreLedgerStatement(sql) {
10
+ return STORE_LEDGER_STATEMENT.test(sql);
11
+ }
12
+ export function storeLedgerResult(sql) {
13
+ if (!isStoreLedgerStatement(sql))
14
+ return undefined;
15
+ return {
16
+ rows: [],
17
+ rowsAffected: /^\s*(?:INSERT|UPDATE|DELETE)\b/i.test(sql) ? 1 : 0,
18
+ };
19
+ }
@@ -13,6 +13,7 @@
13
13
  * kept only for that.
14
14
  */
15
15
  import { type DbExec } from "./client.js";
16
+ import { type MigrationEntry } from "./migrations.js";
16
17
  export declare const STORE_MIGRATIONS_TABLE = "_an_store_migrations";
17
18
  export interface StoreMigration {
18
19
  /** Stable, never renamed: the ledger records it. */
@@ -24,9 +25,37 @@ export interface StoreMigration {
24
25
  readonly kind?: "schema" | "data";
25
26
  readonly sql?: string | readonly string[];
26
27
  readonly run?: (exec: DbExec) => Promise<void>;
28
+ /**
29
+ * The versioned `runMigrations` entry this migration replaces. A database
30
+ * whose old bookkeeping table already records that entry gets a ledger row
31
+ * (`source = 'legacy'`) instead of running it again.
32
+ */
33
+ readonly legacy?: LegacyMigrationRef;
34
+ }
35
+ export interface LegacyMigrationRef {
36
+ /** The `runMigrations` table, e.g. `_chat_thread_schema_migrations`. */
37
+ readonly table: string;
38
+ readonly version: number;
39
+ /** Set for named entries, which were gated by name, not version. */
40
+ readonly name?: string;
41
+ /**
42
+ * Where the list ran on main. A release-only list (the default) keeps
43
+ * running only in the release step. A list that also ran at plugin boot
44
+ * runs everywhere: local runtimes import its history once, and hosted apps
45
+ * without release migrations keep running it through `runMigrations` and
46
+ * its old table, exactly as before.
47
+ */
48
+ readonly ranAtBoot?: boolean;
49
+ /** The original entry, for that hosted `runMigrations` path. */
50
+ readonly entry?: MigrationEntry;
27
51
  }
28
52
  export interface StoreDefinition {
29
53
  readonly id: string;
54
+ /**
55
+ * Stores whose migrations must run first at release, for a migration that
56
+ * reads or alters another store's tables. Registry order is otherwise by id.
57
+ */
58
+ readonly after?: readonly string[];
30
59
  /**
31
60
  * Never provision from a request, even for hosted apps that do not migrate
32
61
  * at release: the release step (or a versioned list) is the only creator.
@@ -58,6 +87,11 @@ export declare class SchemaNotMigratedError extends Error {
58
87
  export declare function schemaIsReleaseOwned(): boolean;
59
88
  /** Stable across bundlers; `run` bodies are not hashed because minifiers rewrite them. */
60
89
  export declare function migrationChecksum(migration: StoreMigration): string | null;
90
+ /**
91
+ * Registry order with each store's `after` dependencies first. Fails on an
92
+ * unknown id or a cycle rather than guessing an order.
93
+ */
94
+ export declare function orderStoresForRelease<T extends StoreDefinition>(stores: readonly T[]): T[];
61
95
  /**
62
96
  * Every registered store's migrations that the ledger does not list. The
63
97
  * release step calls this after applying, so a deploy whose ledger disagrees
@@ -48,6 +48,10 @@ export const FRAMEWORK_STORES = [
48
48
  "automation_run_history",
49
49
  () => import("../jobs/run-history.js").then((m) => m.automationRunHistoryStore),
50
50
  ],
51
+ [
52
+ "automation_trigger_events",
53
+ () => import("../triggers/event-queue.js").then((m) => m.automationTriggerEventsStore),
54
+ ],
51
55
  [
52
56
  "automation_webhook_tokens",
53
57
  () => import("../triggers/webhook-store.js").then((m) => m.automationWebhookTokensStore),
@@ -56,6 +60,10 @@ export const FRAMEWORK_STORES = [
56
60
  "awaiting_inputs",
57
61
  () => import("../integrations/awaiting-input-store.js").then((m) => m.awaitingInputsStore),
58
62
  ],
63
+ [
64
+ "better_auth",
65
+ () => import("../server/better-auth-migrations.js").then((m) => m.betterAuthStore),
66
+ ],
59
67
  [
60
68
  "browser_sessions",
61
69
  () => import("../browser-sessions/store.js").then((m) => m.browserSessionsStore),
@@ -80,6 +88,10 @@ export const FRAMEWORK_STORES = [
80
88
  "computer_approvals",
81
89
  () => import("../integrations/computer-supervision-store.js").then((m) => m.computerApprovalsStore),
82
90
  ],
91
+ [
92
+ "context_xray",
93
+ () => import("../agent/context-xray/schema-store.js").then((m) => m.contextXrayStore),
94
+ ],
83
95
  [
84
96
  "conversation_scopes",
85
97
  () => import("../integrations/scope-store.js").then((m) => m.conversationScopesStore),
@@ -164,6 +176,7 @@ export const FRAMEWORK_STORES = [
164
176
  "observational_memory",
165
177
  () => import("../agent/observational-memory/store.js").then((m) => m.observationalMemoryStore),
166
178
  ],
179
+ ["org", () => import("../org/schema-store.js").then((m) => m.orgStore)],
167
180
  [
168
181
  "pending_tasks",
169
182
  () => import("../integrations/pending-tasks-store.js").then((m) => m.pendingTasksStore),