@agent-native/core 0.196.0-nightly-20260928172902 → 0.196.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +17 -0
  3. package/corpus/templates/assets/CHANGELOG.md +18 -0
  4. package/corpus/templates/brain/CHANGELOG.md +6 -0
  5. package/corpus/templates/calendar/CHANGELOG.md +4 -0
  6. package/corpus/templates/clips/CHANGELOG.md +19 -0
  7. package/corpus/templates/clips/actions/create-recording-agent-link.ts +8 -2
  8. package/corpus/templates/clips/actions/update-recording.ts +5 -1
  9. package/corpus/templates/clips/app/routes/share.$shareId.tsx +10 -3
  10. package/corpus/templates/clips/changelog/2026-09-28-agent-links-stay-valid-when-clip-details-change.md +6 -0
  11. package/corpus/templates/clips/changelog/2026-09-28-password-changes-immediately-invalidate-old-recording-links.md +6 -0
  12. package/corpus/templates/clips/changelog/2026-09-28-password-protected-recording-links-stop-working-when-the-pas.md +6 -0
  13. package/corpus/templates/clips/server/db/schema.ts +3 -0
  14. package/corpus/templates/clips/server/lib/player-video-url.ts +9 -1
  15. package/corpus/templates/clips/server/lib/public-agent-context.ts +12 -4
  16. package/corpus/templates/clips/server/lib/share-password.ts +25 -0
  17. package/corpus/templates/clips/server/plugins/db.ts +36 -0
  18. package/corpus/templates/clips/server/routes/[...page].get.ts +8 -1
  19. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +33 -6
  20. package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +34 -6
  21. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +26 -5
  22. package/corpus/templates/content/CHANGELOG.md +1 -0
  23. package/corpus/templates/crm/CHANGELOG.md +12 -0
  24. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +265 -3
  25. package/corpus/templates/design/CHANGELOG.md +21 -0
  26. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +463 -6
  27. package/corpus/templates/design/app/pages/Index.tsx +1 -1
  28. package/corpus/templates/design/changelog/2026-09-27-auto-focused-app-fields-no-longer-interrupt-canvas-shortcuts.md +6 -0
  29. package/corpus/templates/design/changelog/2026-09-28-model-picker-loads-available-models.md +6 -0
  30. package/corpus/templates/design/changelog/2026-09-28-template-menus-stay-available-on-hover.md +6 -0
  31. package/corpus/templates/dispatch/CHANGELOG.md +18 -0
  32. package/corpus/templates/forms/CHANGELOG.md +6 -0
  33. package/corpus/templates/mail/.env.example +1 -1
  34. package/corpus/templates/mail/CHANGELOG.md +33 -0
  35. package/corpus/templates/mail/changelog/2026-09-28-fixed-inbox-loading-stalls-and-showed-progress-during-google-2.md +6 -0
  36. package/corpus/templates/mail/changelog/2026-09-28-fixed-inbox-loading-stalls-and-showed-progress-during-google.md +6 -0
  37. package/corpus/templates/mail/server/db/schema.ts +7 -0
  38. package/corpus/templates/mail/server/lib/ai-filter-backfill.ts +4 -0
  39. package/corpus/templates/mail/server/lib/jobs.ts +5 -2
  40. package/corpus/templates/mail/server/plugins/db.ts +16 -0
  41. package/corpus/templates/mail/server/plugins/mail-jobs.ts +355 -44
  42. package/corpus/templates/slides/CHANGELOG.md +28 -0
  43. package/corpus/templates/slides/app/pages/Index.tsx +1 -1
  44. package/corpus/templates/slides/changelog/2026-09-28-model-picker-loads-available-models.md +6 -0
  45. package/corpus/templates/slides/changelog/2026-09-28-template-menus-stay-available-on-hover.md +6 -0
  46. package/dist/automation/index.d.ts +1 -1
  47. package/dist/client/auth/AuthPage.js +3 -2
  48. package/dist/client/org/OrgSwitcher.js +31 -19
  49. package/dist/client/settings/UsageSection.js +3 -3
  50. package/dist/client/use-action.js +1 -1
  51. package/dist/collab/awareness.d.ts +2 -2
  52. package/dist/collab/routes.d.ts +1 -1
  53. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  54. package/dist/jobs/background-automation-runner.d.ts +2 -0
  55. package/dist/jobs/background-automation-runner.js +20 -1
  56. package/dist/jobs/sweep-hooks.d.ts +6 -2
  57. package/dist/jobs/sweep-hooks.js +17 -9
  58. package/dist/localization/core-messages/ar-SA.js +2 -2
  59. package/dist/localization/core-messages/de-DE.js +2 -2
  60. package/dist/localization/core-messages/en-US.d.ts +2 -2
  61. package/dist/localization/core-messages/en-US.js +2 -2
  62. package/dist/localization/core-messages/es-ES.js +2 -2
  63. package/dist/localization/core-messages/fr-FR.js +2 -2
  64. package/dist/localization/core-messages/hi-IN.js +2 -2
  65. package/dist/localization/core-messages/ja-JP.js +2 -2
  66. package/dist/localization/core-messages/ko-KR.js +2 -2
  67. package/dist/localization/core-messages/pt-BR.js +2 -2
  68. package/dist/localization/core-messages/zh-CN.js +2 -2
  69. package/dist/localization/core-messages/zh-TW.js +2 -2
  70. package/dist/localization/core-messages.d.ts +2 -2
  71. package/dist/notifications/routes.d.ts +5 -5
  72. package/dist/observability/routes.d.ts +6 -6
  73. package/dist/progress/routes.d.ts +1 -1
  74. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  75. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  76. package/dist/resources/handlers.d.ts +1 -1
  77. package/dist/secrets/routes.d.ts +4 -4
  78. package/dist/server/agent-chat-plugin.js +6 -2
  79. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  80. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  81. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  82. package/dist/server/index.d.ts +1 -1
  83. package/dist/triggers/dispatcher.js +167 -36
  84. package/dist/triggers/event-queue.d.ts +18 -1
  85. package/dist/triggers/event-queue.js +143 -10
  86. package/package.json +4 -4
@@ -104,9 +104,15 @@ declare var __INITIAL_SOURCE_HEAD__: string;
104
104
  var userFocusedElement: Element | null = null;
105
105
  var trustedFocusIntent: {
106
106
  target: Element | null;
107
- kind: "pointer" | "tab" | "activation";
107
+ kind: "pointer" | "tab" | "activation" | "navigation";
108
+ key?: string;
109
+ rovingGroup?: Element | null;
110
+ activeDescendantBefore?: string | null;
111
+ tabIndexesBefore?: Array<{ element: Element; value: string | null }>;
108
112
  expiresAt: number;
109
113
  } | null = null;
114
+ var rovingGroupSelector =
115
+ '[role="grid"], [role="listbox"], [role="menu"], [role="menubar"], [role="radiogroup"], [role="tablist"], [role="toolbar"], [role="tree"], [role="treegrid"]';
110
116
  var focusTargetSelector =
111
117
  'a[href], area[href], button, input:not([type="hidden"]), select, textarea, summary, iframe, audio[controls], video[controls], [tabindex], [contenteditable]:not([contenteditable="false"]), [role="button"], [role="link"], [role="switch"], [role="checkbox"], [role="radio"], [role="slider"], [role="spinbutton"], [role="menuitem"], [role="textbox"], [role="combobox"], [role="searchbox"]';
112
118
 
@@ -134,23 +140,472 @@ declare var __INITIAL_SOURCE_HEAD__: string;
134
140
 
135
141
  function armTrustedFocusIntent(
136
142
  target: Element | null,
137
- kind: "pointer" | "tab" | "activation",
143
+ kind: "pointer" | "tab" | "activation" | "navigation",
144
+ key?: string,
138
145
  ): void {
146
+ var rovingGroup =
147
+ kind === "navigation" && target
148
+ ? target.closest(rovingGroupSelector)
149
+ : null;
139
150
  trustedFocusIntent = {
140
151
  target: target,
141
152
  kind: kind,
153
+ ...(key ? { key: key } : {}),
154
+ ...(rovingGroup
155
+ ? {
156
+ rovingGroup: rovingGroup,
157
+ activeDescendantBefore: rovingGroup.getAttribute(
158
+ "aria-activedescendant",
159
+ ),
160
+ tabIndexesBefore: Array.from(
161
+ rovingGroup.querySelectorAll("[tabindex]"),
162
+ ).map(function (element) {
163
+ return {
164
+ element: element,
165
+ value: element.getAttribute("tabindex"),
166
+ };
167
+ }),
168
+ }
169
+ : {}),
142
170
  expiresAt: Date.now() + 1000,
143
171
  };
144
172
  }
145
173
 
174
+ function clearNavigationFocusIntentAfterAppTasks(): void {
175
+ var navigationIntent = trustedFocusIntent;
176
+ // Let app key handlers enqueue their roving-focus task before clearing intent.
177
+ window.setTimeout(function () {
178
+ window.setTimeout(function () {
179
+ if (trustedFocusIntent === navigationIntent) {
180
+ trustedFocusIntent = null;
181
+ }
182
+ }, 0);
183
+ }, 0);
184
+ }
185
+
186
+ function isRovingFocusSibling(
187
+ current: Element | null,
188
+ next: Element,
189
+ key: string | undefined,
190
+ intent: {
191
+ rovingGroup?: Element | null;
192
+ activeDescendantBefore?: string | null;
193
+ tabIndexesBefore?: Array<{ element: Element; value: string | null }>;
194
+ },
195
+ ): boolean {
196
+ if (!current) return false;
197
+
198
+ function isNativeRadio(element: Element): element is HTMLInputElement {
199
+ return (
200
+ element.tagName === "INPUT" &&
201
+ (element as HTMLInputElement).type === "radio"
202
+ );
203
+ }
204
+
205
+ if (isNativeRadio(current) && isNativeRadio(next)) {
206
+ var radioName = current.name;
207
+ var radioForm = current.form || current.closest("form");
208
+ var radios = Array.from(
209
+ (current.getRootNode() as ParentNode).querySelectorAll(
210
+ 'input[type="radio"]',
211
+ ),
212
+ ).filter(function (candidate) {
213
+ var radio = candidate as HTMLInputElement;
214
+ return (
215
+ radioName !== "" &&
216
+ radio.name === radioName &&
217
+ (radio.form || radio.closest("form")) === radioForm
218
+ );
219
+ });
220
+ var currentRadioIndex = radios.indexOf(current);
221
+ var nextRadioIndex = radios.indexOf(next);
222
+ var delta =
223
+ key === "ArrowRight" || key === "ArrowDown"
224
+ ? 1
225
+ : key === "ArrowLeft" || key === "ArrowUp"
226
+ ? -1
227
+ : 0;
228
+ if (key === "ArrowLeft" || key === "ArrowRight") {
229
+ if (window.getComputedStyle(current).direction === "rtl") {
230
+ delta *= -1;
231
+ }
232
+ }
233
+ if (
234
+ radios.length > 1 &&
235
+ currentRadioIndex !== -1 &&
236
+ nextRadioIndex !== -1 &&
237
+ delta !== 0
238
+ ) {
239
+ return (
240
+ nextRadioIndex ===
241
+ (currentRadioIndex + delta + radios.length) % radios.length
242
+ );
243
+ }
244
+ }
245
+
246
+ var currentGroup = current.closest(rovingGroupSelector);
247
+ if (
248
+ !currentGroup ||
249
+ currentGroup !== next.closest(rovingGroupSelector) ||
250
+ intent.rovingGroup !== currentGroup
251
+ ) {
252
+ return false;
253
+ }
254
+ var role = currentGroup.getAttribute("role");
255
+ var itemSelector: string | null = null;
256
+ switch (role) {
257
+ case "grid":
258
+ case "treegrid":
259
+ itemSelector =
260
+ '[role="row"], [role="gridcell"], [role="columnheader"], [role="rowheader"], tr, td, th';
261
+ break;
262
+ case "listbox":
263
+ itemSelector = '[role="option"]';
264
+ break;
265
+ case "menu":
266
+ case "menubar":
267
+ itemSelector =
268
+ '[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]';
269
+ break;
270
+ case "radiogroup":
271
+ itemSelector = '[role="radio"], input[type="radio"]';
272
+ break;
273
+ case "tablist":
274
+ itemSelector = '[role="tab"]';
275
+ break;
276
+ case "toolbar":
277
+ itemSelector = 'button, a[href], [role="button"], [role="link"]';
278
+ break;
279
+ case "tree":
280
+ itemSelector = '[role="treeitem"]';
281
+ break;
282
+ }
283
+ if (!itemSelector) return false;
284
+ var currentItem = current.closest(itemSelector);
285
+ var nextItem = next.closest(itemSelector);
286
+ if (!currentItem || !nextItem || currentItem === nextItem) return false;
287
+
288
+ function belongsToGroup(item: Element): boolean {
289
+ if (item.closest(rovingGroupSelector) !== currentGroup) return false;
290
+ if (item.getAttribute("role")) return true;
291
+ if (
292
+ item.tagName !== "TR" &&
293
+ item.tagName !== "TD" &&
294
+ item.tagName !== "TH"
295
+ ) {
296
+ return true;
297
+ }
298
+ return (
299
+ item.closest('table[role="grid"], table[role="treegrid"]') ===
300
+ currentGroup
301
+ );
302
+ }
303
+
304
+ function isGridRow(item: Element): boolean {
305
+ return (
306
+ item.getAttribute("role") === "row" ||
307
+ (item.tagName === "TR" && belongsToGroup(item))
308
+ );
309
+ }
310
+
311
+ function gridRows(): Element[] {
312
+ return Array.from(
313
+ currentGroup.querySelectorAll('[role="row"], tr'),
314
+ ).filter(function (row) {
315
+ return belongsToGroup(row) && isGridRow(row);
316
+ });
317
+ }
318
+
319
+ function gridCells(row: Element): Element[] {
320
+ return Array.from(
321
+ row.querySelectorAll(
322
+ '[role="gridcell"], [role="columnheader"], [role="rowheader"], td, th',
323
+ ),
324
+ ).filter(function (cell) {
325
+ if (!belongsToGroup(cell)) return false;
326
+ if (cell.getAttribute("role")) {
327
+ return cell.closest('[role="row"]') === row;
328
+ }
329
+ if (cell.tagName === "TD" || cell.tagName === "TH") {
330
+ return (
331
+ cell.closest("tr") === row &&
332
+ cell.closest('table[role="grid"], table[role="treegrid"]') ===
333
+ currentGroup
334
+ );
335
+ }
336
+ return cell.closest('[role="row"]') === row;
337
+ });
338
+ }
339
+
340
+ function ariaIndex(
341
+ element: Element,
342
+ name: string,
343
+ fallback: number,
344
+ ): number {
345
+ var value = Number(element.getAttribute(name));
346
+ return Number.isInteger(value) && value > 0 ? value - 1 : fallback;
347
+ }
348
+
349
+ function hasRovingFocusTransition(
350
+ currentRovingItem: Element,
351
+ nextRovingItem: Element,
352
+ ): boolean {
353
+ var activeDescendant = currentGroup.getAttribute("aria-activedescendant");
354
+ var previousActiveDescendant = intent.activeDescendantBefore || null;
355
+ if (
356
+ activeDescendant &&
357
+ activeDescendant !== previousActiveDescendant &&
358
+ (activeDescendant === (nextRovingItem as HTMLElement).id ||
359
+ activeDescendant === (next as HTMLElement).id)
360
+ ) {
361
+ return true;
362
+ }
363
+ var previousTabIndex = intent.tabIndexesBefore?.find(function (entry) {
364
+ return entry.element === currentRovingItem;
365
+ });
366
+ var nextTabIndex = intent.tabIndexesBefore?.find(function (entry) {
367
+ return entry.element === nextRovingItem;
368
+ });
369
+ if (
370
+ previousTabIndex?.value === "0" &&
371
+ currentRovingItem.getAttribute("tabindex") !== "0" &&
372
+ nextTabIndex !== undefined &&
373
+ nextTabIndex.value !== "0" &&
374
+ nextRovingItem.getAttribute("tabindex") === "0"
375
+ ) {
376
+ return true;
377
+ }
378
+
379
+ function isGridCell(item: Element): boolean {
380
+ return (
381
+ item.getAttribute("role") === "gridcell" ||
382
+ item.getAttribute("role") === "columnheader" ||
383
+ item.getAttribute("role") === "rowheader" ||
384
+ item.tagName === "TD" ||
385
+ item.tagName === "TH"
386
+ );
387
+ }
388
+
389
+ return (
390
+ (role === "grid" || role === "treegrid") &&
391
+ isGridCell(currentRovingItem) &&
392
+ isGridCell(nextRovingItem) &&
393
+ current !== currentRovingItem &&
394
+ next !== nextRovingItem &&
395
+ current.matches(focusTargetSelector) &&
396
+ next.matches(focusTargetSelector)
397
+ );
398
+ }
399
+
400
+ if (role === "grid" || role === "treegrid") {
401
+ var currentRow = currentItem.closest('[role="row"], tr');
402
+ var nextRow = nextItem.closest('[role="row"], tr');
403
+ if (
404
+ !currentRow ||
405
+ !nextRow ||
406
+ !belongsToGroup(currentRow) ||
407
+ !belongsToGroup(nextRow)
408
+ ) {
409
+ return false;
410
+ }
411
+ var rows = gridRows();
412
+ var currentRowIndex = ariaIndex(
413
+ currentRow,
414
+ "aria-rowindex",
415
+ rows.indexOf(currentRow),
416
+ );
417
+ var nextRowIndex = ariaIndex(
418
+ nextRow,
419
+ "aria-rowindex",
420
+ rows.indexOf(nextRow),
421
+ );
422
+ var verticalDelta = key === "ArrowDown" ? 1 : key === "ArrowUp" ? -1 : 0;
423
+ if (isGridRow(currentItem) && isGridRow(nextItem)) {
424
+ return (
425
+ verticalDelta !== 0 &&
426
+ nextRowIndex === currentRowIndex + verticalDelta &&
427
+ hasRovingFocusTransition(currentItem, nextItem)
428
+ );
429
+ }
430
+ if (isGridRow(currentItem) || isGridRow(nextItem)) {
431
+ if (role !== "treegrid" || currentRow !== nextRow) return false;
432
+ var currentIsRow = isGridRow(currentItem);
433
+ var cells = gridCells(currentRow);
434
+ if (currentIsRow && key === "ArrowRight") {
435
+ return (
436
+ cells[0] === nextItem &&
437
+ hasRovingFocusTransition(currentItem, nextItem)
438
+ );
439
+ }
440
+ if (!currentIsRow && key === "ArrowLeft") {
441
+ return (
442
+ cells[0] === currentItem &&
443
+ hasRovingFocusTransition(currentItem, nextItem)
444
+ );
445
+ }
446
+ return false;
447
+ }
448
+ var currentColumnIndex = ariaIndex(
449
+ currentItem,
450
+ "aria-colindex",
451
+ gridCells(currentRow).indexOf(currentItem),
452
+ );
453
+ var nextColumnIndex = ariaIndex(
454
+ nextItem,
455
+ "aria-colindex",
456
+ gridCells(nextRow).indexOf(nextItem),
457
+ );
458
+ if (key === "ArrowLeft" || key === "ArrowRight") {
459
+ var columnDelta = key === "ArrowRight" ? 1 : -1;
460
+ if (window.getComputedStyle(currentGroup).direction === "rtl") {
461
+ columnDelta *= -1;
462
+ }
463
+ return (
464
+ currentRow === nextRow &&
465
+ nextColumnIndex === currentColumnIndex + columnDelta &&
466
+ hasRovingFocusTransition(currentItem, nextItem)
467
+ );
468
+ }
469
+ return (
470
+ verticalDelta !== 0 &&
471
+ nextRowIndex === currentRowIndex + verticalDelta &&
472
+ nextColumnIndex === currentColumnIndex &&
473
+ hasRovingFocusTransition(currentItem, nextItem)
474
+ );
475
+ }
476
+
477
+ function itemFor(target: Element): Element | null {
478
+ if (role === "tree") return target.closest('[role="treeitem"]');
479
+ return target.closest(itemSelector!);
480
+ }
481
+
482
+ function isNavigableTreeItem(item: Element): boolean {
483
+ var currentItem: Element | null = item;
484
+ while (currentItem && currentItem !== currentGroup) {
485
+ if (
486
+ currentItem.getAttribute("hidden") !== null ||
487
+ currentItem.getAttribute("inert") !== null ||
488
+ currentItem.getAttribute("aria-hidden") === "true"
489
+ ) {
490
+ return false;
491
+ }
492
+ if (
493
+ currentItem !== item &&
494
+ currentItem.getAttribute("role") === "treeitem" &&
495
+ currentItem.getAttribute("aria-expanded") === "false"
496
+ ) {
497
+ return false;
498
+ }
499
+ currentItem = currentItem.parentElement;
500
+ }
501
+ return true;
502
+ }
503
+
504
+ var currentRovingItem = itemFor(current);
505
+ var nextRovingItem = itemFor(next);
506
+ if (
507
+ !currentRovingItem ||
508
+ !nextRovingItem ||
509
+ !belongsToGroup(currentRovingItem) ||
510
+ !belongsToGroup(nextRovingItem)
511
+ ) {
512
+ return false;
513
+ }
514
+
515
+ var isRtl = window.getComputedStyle(currentGroup).direction === "rtl";
516
+ var childKey = isRtl ? "ArrowLeft" : "ArrowRight";
517
+ var parentKey = isRtl ? "ArrowRight" : "ArrowLeft";
518
+ if (role === "tree" && key === childKey) {
519
+ return (
520
+ isNavigableTreeItem(currentRovingItem) &&
521
+ isNavigableTreeItem(nextRovingItem) &&
522
+ nextRovingItem.parentElement?.closest('[role="treeitem"]') ===
523
+ currentRovingItem &&
524
+ hasRovingFocusTransition(currentRovingItem, nextRovingItem)
525
+ );
526
+ }
527
+ if (role === "tree" && key === parentKey) {
528
+ return (
529
+ isNavigableTreeItem(currentRovingItem) &&
530
+ isNavigableTreeItem(nextRovingItem) &&
531
+ currentRovingItem.parentElement?.closest('[role="treeitem"]') ===
532
+ nextRovingItem &&
533
+ hasRovingFocusTransition(currentRovingItem, nextRovingItem)
534
+ );
535
+ }
536
+
537
+ var items = Array.from(currentGroup.querySelectorAll(itemSelector)).filter(
538
+ function (item) {
539
+ return (
540
+ belongsToGroup(item) &&
541
+ itemFor(item) === item &&
542
+ (role !== "tree" || isNavigableTreeItem(item))
543
+ );
544
+ },
545
+ );
546
+ var currentIndex = items.indexOf(currentRovingItem);
547
+ var nextIndex = items.indexOf(nextRovingItem);
548
+ if (currentIndex === -1 || nextIndex === -1) return false;
549
+
550
+ var orientation = currentGroup.getAttribute("aria-orientation");
551
+ if (!orientation) {
552
+ orientation =
553
+ role === "toolbar" ||
554
+ role === "menubar" ||
555
+ role === "tablist" ||
556
+ role === "radiogroup"
557
+ ? "horizontal"
558
+ : "vertical";
559
+ }
560
+ var delta =
561
+ key === "ArrowRight"
562
+ ? 1
563
+ : key === "ArrowLeft"
564
+ ? -1
565
+ : key === "ArrowDown"
566
+ ? 1
567
+ : key === "ArrowUp"
568
+ ? -1
569
+ : 0;
570
+ if (!delta) return false;
571
+ if (orientation === "horizontal") {
572
+ if (key !== "ArrowLeft" && key !== "ArrowRight") return false;
573
+ if (window.getComputedStyle(currentGroup).direction === "rtl")
574
+ delta *= -1;
575
+ } else if (key !== "ArrowUp" && key !== "ArrowDown") {
576
+ return false;
577
+ }
578
+ var expectedIndex = currentIndex + delta;
579
+ if (
580
+ role === "radiogroup" ||
581
+ role === "tablist" ||
582
+ role === "menu" ||
583
+ role === "menubar" ||
584
+ role === "toolbar"
585
+ ) {
586
+ expectedIndex = (expectedIndex + items.length) % items.length;
587
+ }
588
+ return (
589
+ nextIndex === expectedIndex &&
590
+ hasRovingFocusTransition(currentRovingItem, nextRovingItem)
591
+ );
592
+ }
593
+
146
594
  function rememberUserFocusedElement(event: FocusEvent): void {
147
595
  var intent = trustedFocusIntent;
148
596
  var target = getCanvasFocusTarget(event);
597
+ var navigationTargetMatches =
598
+ intent?.kind !== "navigation" ||
599
+ target === intent.target ||
600
+ (target !== null &&
601
+ isRovingFocusSibling(intent.target, target, intent.key, intent));
149
602
  if (
150
603
  !intent ||
151
604
  Date.now() > intent.expiresAt ||
152
605
  !target ||
153
- (intent.kind === "pointer" &&
606
+ !navigationTargetMatches ||
607
+ (intent.kind !== "tab" &&
608
+ intent.kind !== "navigation" &&
154
609
  (intent.target === null ||
155
610
  (intent.target !== target &&
156
611
  !event.composedPath().includes(intent.target) &&
@@ -213,11 +668,13 @@ declare var __INITIAL_SOURCE_HEAD__: string;
213
668
  var active = document.activeElement;
214
669
  if (active instanceof Element && isCanvasFocusTarget(active)) {
215
670
  userFocusedElement = active;
216
- if (
671
+ if (keyEvent.key.startsWith("Arrow")) {
672
+ armTrustedFocusIntent(active, "navigation", keyEvent.key);
673
+ clearNavigationFocusIntentAfterAppTasks();
674
+ } else if (
217
675
  keyEvent.key === "Enter" ||
218
676
  keyEvent.key === " " ||
219
- keyEvent.key === "Escape" ||
220
- keyEvent.key.startsWith("Arrow")
677
+ keyEvent.key === "Escape"
221
678
  ) {
222
679
  armTrustedFocusIntent(active, "activation");
223
680
  }
@@ -1108,7 +1108,7 @@ export default function Index() {
1108
1108
  disabled={!agentEngineConfigured}
1109
1109
  submissionDisabled={!agentEngineConfigured}
1110
1110
  showModelSelector={agentEngineConfigured}
1111
- modelStatusChecksEnabled={false}
1111
+ modelStatusChecksEnabled={agentEngineConfigured}
1112
1112
  title={t("home.newDesignLower")}
1113
1113
  draftScope="design:new:0"
1114
1114
  placeholder={
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Auto-focused app fields no longer interrupt canvas shortcuts while editing live screens
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-28
4
+ ---
5
+
6
+ The model picker shows available models when AI is configured.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-28
4
+ ---
5
+
6
+ Template menus stay available when you hover over a card.
@@ -3,6 +3,24 @@
3
3
  All notable user-facing changes to Agent-Native Dispatch are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-09-28
7
+
8
+ ### Fixed
9
+
10
+ - Desktop sign-in now carries over to Mail and other eligible apps.
11
+
12
+ ## 2026-09-27
13
+
14
+ ### Improved
15
+
16
+ - Workspace connection changes now show clear confirmations in chat.
17
+
18
+ ## 2026-09-25
19
+
20
+ ### Improved
21
+
22
+ - Dispatch settings now live on Dispatch › General (Chat-first workspace, Resources, and Connect apps), and Members keeps the Dispatch access column.
23
+
6
24
  ## 2026-09-23
7
25
 
8
26
  ### Fixed
@@ -3,6 +3,12 @@
3
3
  All notable user-facing changes to Agent-Native Forms are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-09-27
7
+
8
+ ### Improved
9
+
10
+ - Forms keeps newly added follow-up questions and actionable response signals visible in chat.
11
+
6
12
  ## 2026-09-15
7
13
 
8
14
  ### Fixed
@@ -18,7 +18,7 @@
18
18
  # GMAIL_WATCH_TOPIC=projects/<project>/topics/<topic>
19
19
  # GMAIL_PUSH_AUDIENCE=https://<your-domain>/api/gmail/push
20
20
  # GMAIL_PUSH_SIGNER_EMAIL=<pubsub-signer>@<project>.iam.gserviceaccount.com
21
- # GMAIL_WATCH_RENEW_AUDIENCE=https://<your-domain>/api/gmail/renew
21
+ # GMAIL_WATCH_RENEW_AUDIENCE=https://<your-domain>/api/gmail/watch/renew
22
22
 
23
23
  # Inbound email webhooks (Resend / SendGrid)
24
24
  # REQUIRED in prod when inbound email is enabled — webhooks fail-closed without it
@@ -3,16 +3,46 @@
3
3
  All notable user-facing changes to Agent-Native Mail are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-09-28
7
+
8
+ ### Improved
9
+
10
+ - Builder credit notices appear above sidebar actions in a full-width layout.
11
+ - Mail automation rules use a consistent neutral color treatment.
12
+ - Open the current agent conversation in a full-page view
13
+
14
+ ### Fixed
15
+
16
+ - Avoid automatic retries after Gmail quota cooldowns
17
+
6
18
  ## 2026-09-27
7
19
 
20
+ ### Added
21
+
22
+ - Mail can mark prompt-matched messages Important and show browser notifications while Mail is open; mobile app notifications are coming soon.
23
+
8
24
  ### Improved
9
25
 
26
+ - AI triage links open the relevant rule group.
27
+ - Inbox Priority shows each email's score with quick feedback and rule settings.
28
+ - Mail rule changes in chat now link to the matching Settings section
29
+ - Updated drafts now include a review link in chat
10
30
  - Add AI inbox triage to Mail's first-run onboarding.
11
31
  - Scheduled-send cards show the subject and local send time
12
32
  - Successful draft, filter, and inbox rule changes now appear as concise action cards in chat.
13
33
 
14
34
  ### Fixed
15
35
 
36
+ - Failed queued draft sends now report an error instead of appearing successful.
37
+ - Gmail cooldown messages now show when to try again.
38
+ - Inbox sorting recovers automatically when background processing is interrupted
39
+ - Mail resumes inbox organization after temporary Gmail limits
40
+ - Mail retries inbox rules after temporary Google token refresh failures
41
+ - Mail setup stays visible while triage availability loads
42
+ - Mail setup waits for first-run onboarding, and empty importance prompts require an explicit skip.
43
+ - Inbox tabs are visible on mobile, and the full toolbar scrolls together horizontally.
44
+ - Triage examples stay placeholders until you choose them
45
+ - Undo resumes safely after an interrupted mail restore
16
46
  - Fixed the inbox crash when the sidebar is pinned
17
47
  - Inbox navigation stays in a hamburger drawer, and filter tabs use available toolbar space before scrolling.
18
48
  - Inbox sorting finishes reliably across larger mailboxes
@@ -32,6 +62,7 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
32
62
 
33
63
  ### Fixed
34
64
 
65
+ - Removing a member from your organization now completes instead of failing with a pending cleanup error
35
66
  - Chat-created inbox rules appear immediately while recent mail is processed in the background.
36
67
  - Chat-created Mail rules save and queue recent-mail processing before background model checks run.
37
68
  - Fixed AI rule setup progress and chat updates
@@ -51,6 +82,8 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
51
82
 
52
83
  ### Improved
53
84
 
85
+ - Mail settings now live in tabs on Mail > General (Drafting, Snippets, Rules, AI filter, Gmail filters, Aliases, Tracking), and Slack draft requests sit on Channels > Slack.
86
+ - Settings now opens from your name at the bottom of the sidebar, or with ⌘,.
54
87
  - Mail now guides users to connect Jev before setting up triage and lets them remove existing rules if Jev becomes unavailable.
55
88
  - Tune inbox priorities with Jev, label messages clearly, and teach importance with feedback.
56
89
 
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-28
4
+ ---
5
+
6
+ Google sign-in shows progress while authentication finishes.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-28
4
+ ---
5
+
6
+ Your inbox now loads without getting stuck on loading placeholders.
@@ -166,6 +166,13 @@ export const mailSyncAccounts = table(
166
166
  .default(0),
167
167
  syncClaimId: text("sync_claim_id"),
168
168
  syncClaimedAt: integer("sync_claimed_at"),
169
+ lastWatchRenewedAt: bigint("last_watch_renewed_at", { mode: "number" }),
170
+ lastWatchAttemptedAt: bigint("last_watch_attempted_at", { mode: "number" }),
171
+ lastAutomationAttemptedAt: bigint("last_automation_attempted_at", {
172
+ mode: "number",
173
+ }),
174
+ watchRenewClaimId: text("watch_renew_claim_id"),
175
+ watchRenewClaimedAt: bigint("watch_renew_claimed_at", { mode: "number" }),
169
176
  labelsJson: text("labels_json"),
170
177
  labelsUpdatedAt: integer("labels_updated_at"),
171
178
  createdAt: integer("created_at").notNull(),