@agent-native/core 0.194.0 → 0.195.0-nightly-20260927130129

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 (95) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/brain/actions/check-builder-embeddings.ts +71 -0
  3. package/corpus/templates/brain/app/i18n-data.ts +90 -0
  4. package/corpus/templates/brain/app/routes/sources.tsx +95 -0
  5. package/corpus/templates/calendar/actions/create-event.ts +264 -32
  6. package/corpus/templates/calendar/app/i18n/en-US.ts +3 -6
  7. package/corpus/templates/calendar/app/root.tsx +0 -1
  8. package/corpus/templates/calendar/changelog/2026-09-27-agent-created-events-show-details-and-open-links.md +6 -0
  9. package/corpus/templates/calendar/changelog/2026-09-27-calendar-event-cards-retain-meet-and-zoom-links-show-confere.md +6 -0
  10. package/corpus/templates/calendar/changelog/2026-09-27-calendar-event-cards-show-times-in-the-supplied-offset-or-ca.md +6 -0
  11. package/corpus/templates/calendar/shared/zoom-add-failed-messages.ts +13 -0
  12. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +144 -13
  13. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +226 -12
  14. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +191 -18
  15. package/corpus/templates/design/app/pages/DesignEditor.tsx +24 -4
  16. package/corpus/templates/design/changelog/2026-09-26-live-previews-keep-canvas-keyboard-shortcuts-available-when-.md +6 -0
  17. package/corpus/templates/design/changelog/2026-09-27-canvas-shortcuts-keep-working-when-a-connected-app-focuses-a.md +6 -0
  18. package/corpus/templates/design/changelog/2026-09-27-drops-into-plain-frames-now-stack-above-existing-content-whi.md +6 -0
  19. package/corpus/templates/design/changelog/2026-09-27-layers-dragged-out-of-a-frame-now-stay-above-the-frame.md +6 -0
  20. package/corpus/templates/design/changelog/2026-09-27-live-previews-keep-canvas-shortcuts-available-after-autofocu.md +6 -0
  21. package/corpus/templates/mail/actions/apply-ai-filter.ts +8 -20
  22. package/corpus/templates/mail/actions/create-scheduled-send.ts +16 -3
  23. package/corpus/templates/mail/actions/manage-automations.ts +54 -3
  24. package/corpus/templates/mail/actions/manage-draft.ts +11 -23
  25. package/corpus/templates/mail/actions/manage-gmail-filters.ts +25 -42
  26. package/corpus/templates/mail/actions/send-email.ts +52 -2
  27. package/corpus/templates/mail/app/root.tsx +0 -3
  28. package/corpus/templates/mail/changelog/2026-09-27-scheduled-sends-reject-timestamps-outside-the-supported-date.md +6 -0
  29. package/corpus/templates/mail/changelog/2026-09-27-show-successful-mail-changes-in-chat.md +6 -0
  30. package/dist/action-ui.d.ts +19 -0
  31. package/dist/action-ui.js +68 -0
  32. package/dist/agent/production-agent.js +9 -1
  33. package/dist/client/agentkit-chat/action-widget.d.ts +1 -1
  34. package/dist/client/agentkit-chat/action-widget.js +25 -0
  35. package/dist/client/agentkit-chat/approval-card.d.ts +7 -0
  36. package/dist/client/agentkit-chat/approval-card.js +56 -0
  37. package/dist/client/agentkit-chat/root.js +2 -0
  38. package/dist/client/chat/action-chat-ui-surface.js +5 -2
  39. package/dist/client/chat/agent-approval-card.js +4 -3
  40. package/dist/client/chat/index.d.ts +2 -1
  41. package/dist/client/chat/index.js +2 -1
  42. package/dist/client/chat/tool-call-display.js +3 -0
  43. package/dist/client/chat/tool-render-registry.d.ts +5 -0
  44. package/dist/client/chat/widgets/ActionCard.d.ts +9 -0
  45. package/dist/client/chat/widgets/ActionCard.js +5 -0
  46. package/dist/client/chat/widgets/RecordChangeWidget.d.ts +10 -0
  47. package/dist/client/chat/widgets/RecordChangeWidget.js +126 -0
  48. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts +1 -0
  49. package/dist/client/chat/widgets/builtin-tool-renderers.js +160 -2
  50. package/dist/client/components/ui/button-classes.d.ts +1 -0
  51. package/dist/client/components/ui/button-classes.js +1 -0
  52. package/dist/client/observability/ObservabilityDashboard.js +113 -12
  53. package/dist/client/observability/ObservabilityReviewSummaryButton.d.ts +1 -1
  54. package/dist/client/observability/ObservabilityReviewSummaryButton.js +13 -8
  55. package/dist/client/sse-event-processor.d.ts +1 -0
  56. package/dist/client/sse-event-processor.js +3 -0
  57. package/dist/collab/routes.d.ts +2 -2
  58. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  59. package/dist/index.browser.d.ts +1 -1
  60. package/dist/index.browser.js +1 -1
  61. package/dist/index.d.ts +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/localization/core-messages/ar-SA.js +34 -0
  64. package/dist/localization/core-messages/de-DE.js +30 -0
  65. package/dist/localization/core-messages/en-US.d.ts +30 -0
  66. package/dist/localization/core-messages/en-US.js +30 -0
  67. package/dist/localization/core-messages/es-ES.js +31 -0
  68. package/dist/localization/core-messages/fr-FR.js +31 -0
  69. package/dist/localization/core-messages/hi-IN.js +30 -0
  70. package/dist/localization/core-messages/ja-JP.js +30 -0
  71. package/dist/localization/core-messages/ko-KR.js +30 -0
  72. package/dist/localization/core-messages/pt-BR.js +31 -0
  73. package/dist/localization/core-messages/zh-CN.js +30 -0
  74. package/dist/localization/core-messages/zh-TW.js +30 -0
  75. package/dist/localization/core-messages.d.ts +30 -0
  76. package/dist/localization/core-messages.js +14 -0
  77. package/dist/localization/default-messages.d.ts +4 -1
  78. package/dist/localization/default-messages.js +6 -3
  79. package/dist/notifications/routes.d.ts +2 -2
  80. package/dist/observability/reviews.js +26 -14
  81. package/dist/observability/routes.d.ts +8 -8
  82. package/dist/observability/store.d.ts +4 -1
  83. package/dist/observability/store.js +27 -6
  84. package/dist/observability/types.d.ts +2 -0
  85. package/dist/progress/routes.d.ts +1 -1
  86. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  87. package/dist/server/prompts/framework-core-compact.js +1 -1
  88. package/dist/server/prompts/framework-core.js +1 -1
  89. package/dist/server/transcribe-voice.d.ts +1 -1
  90. package/dist/triggers/actions/manage-automation.d.ts +2 -2
  91. package/package.json +1 -1
  92. package/corpus/templates/calendar/app/lib/register-chat-renderers.tsx +0 -295
  93. package/corpus/templates/mail/app/lib/mail-gmail-filter-confirmation.tsx +0 -77
  94. package/corpus/templates/mail/app/lib/register-chat-renderers.tsx +0 -54
  95. package/corpus/templates/mail/app/lib/register-mail-draft-card.tsx +0 -91
@@ -1,16 +1,31 @@
1
1
  import { defineAction } from "@agent-native/core/action";
2
2
  import type { ActionRunContext } from "@agent-native/core/action";
3
3
  import { emit } from "@agent-native/core/event-bus";
4
+ import {
5
+ DEFAULT_LOCALE,
6
+ LOCALIZATION_SETTING_KEY,
7
+ normalizeLocalizationPreference,
8
+ resolveLocaleFromRequest,
9
+ type LocaleCode,
10
+ } from "@agent-native/core/localization";
4
11
  import { buildDeepLink, getRequestUserEmail } from "@agent-native/core/server";
12
+ import { getUserSetting } from "@agent-native/core/settings";
5
13
  import { track } from "@agent-native/core/tracking";
6
14
  import { z } from "zod";
7
15
 
16
+ import { getCalendarTimezone } from "../server/lib/calendar-settings.js";
8
17
  import {
9
18
  prepareZoomMeetingPatch,
10
19
  shouldAutoAddGoogleMeet,
11
20
  } from "../server/lib/event-video-conferencing.js";
12
21
  import * as googleCalendar from "../server/lib/google-calendar.js";
13
22
  import type { CalendarEvent } from "../shared/api.js";
23
+ import {
24
+ addDaysToDateKey,
25
+ dateKeyInTimezone,
26
+ isCalendarTimezone,
27
+ } from "../shared/timezone.js";
28
+ import { zoomAddFailedMessages } from "../shared/zoom-add-failed-messages.js";
14
29
  import {
15
30
  availabilityInput,
16
31
  autoDeclineModeInput,
@@ -19,6 +34,7 @@ import {
19
34
  buildReminderOverrides,
20
35
  buildStatusEventFields,
21
36
  cliBoolean,
37
+ extractVideoLink,
22
38
  eventTypeInput,
23
39
  googleColorIdInput,
24
40
  ensureOrganizerInAttendees,
@@ -34,6 +50,193 @@ import {
34
50
  workingLocationTypeInput,
35
51
  } from "./event-action-helpers.js";
36
52
 
53
+ const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
54
+ const ACTION_CHANGE_TITLE_LIMIT = 180;
55
+
56
+ function eventTimezone(
57
+ value: string | undefined,
58
+ input: string,
59
+ fallback?: string,
60
+ ): string | null {
61
+ if (isCalendarTimezone(value)) return value;
62
+ const inputOffset = input.match(/(?:Z|[+-]\d{2}:\d{2})$/i)?.[0];
63
+ if (inputOffset) {
64
+ return inputOffset.toUpperCase() === "Z" ? "UTC" : inputOffset;
65
+ }
66
+ return isCalendarTimezone(fallback) ? fallback : null;
67
+ }
68
+
69
+ function eventDate(value: string, timezone: string | null): string | undefined {
70
+ if (DATE_ONLY_PATTERN.test(value)) return value;
71
+ const instant = new Date(value);
72
+ return timezone && !Number.isNaN(instant.getTime())
73
+ ? dateKeyInTimezone(instant, timezone)
74
+ : undefined;
75
+ }
76
+
77
+ function eventTime(
78
+ value: string,
79
+ timezone: string,
80
+ locale: string,
81
+ ): string | undefined {
82
+ const instant = new Date(value);
83
+ return Number.isNaN(instant.getTime())
84
+ ? undefined
85
+ : new Intl.DateTimeFormat(locale, {
86
+ timeZone: timezone,
87
+ hour: "numeric",
88
+ minute: "2-digit",
89
+ }).format(instant);
90
+ }
91
+
92
+ function eventTimezoneLabel(timezone: string): string {
93
+ return /^[+-]\d{2}:\d{2}$/.test(timezone) ? `UTC${timezone}` : timezone;
94
+ }
95
+
96
+ function localizedDate(value: string, locale: string): string | undefined {
97
+ if (!DATE_ONLY_PATTERN.test(value)) return undefined;
98
+ const instant = new Date(`${value}T12:00:00.000Z`);
99
+ return Number.isNaN(instant.getTime())
100
+ ? undefined
101
+ : new Intl.DateTimeFormat(locale, {
102
+ dateStyle: "medium",
103
+ timeZone: "UTC",
104
+ }).format(instant);
105
+ }
106
+
107
+ async function getActionLocale(
108
+ email: string,
109
+ requestHeaders: Headers | undefined,
110
+ ): Promise<LocaleCode> {
111
+ let preference:
112
+ | ReturnType<typeof normalizeLocalizationPreference>
113
+ | undefined;
114
+ try {
115
+ preference = normalizeLocalizationPreference(
116
+ await getUserSetting(email, LOCALIZATION_SETTING_KEY),
117
+ );
118
+ } catch {
119
+ // coercion-ok: the saved locale only formats the result card; it cannot block event creation.
120
+ }
121
+ return resolveLocaleFromRequest({
122
+ preference,
123
+ request: requestHeaders ? { headers: requestHeaders } : undefined,
124
+ fallback: DEFAULT_LOCALE,
125
+ }).locale;
126
+ }
127
+
128
+ function getZoomFailureMessage(locale: LocaleCode): string {
129
+ return (
130
+ zoomAddFailedMessages[locale as keyof typeof zoomAddFailedMessages] ??
131
+ zoomAddFailedMessages[DEFAULT_LOCALE]
132
+ );
133
+ }
134
+
135
+ function eventChangeTitle(event: CalendarEvent): string {
136
+ const location = event.workingLocationProperties;
137
+ let fallback = "Event";
138
+ if (location?.type === "homeOffice") fallback = "Home";
139
+ if (location?.type === "officeLocation") {
140
+ fallback = location.officeLocation?.label || "Office";
141
+ }
142
+ if (location?.type === "customLocation") {
143
+ fallback = location.customLocation?.label || "Working location";
144
+ }
145
+ return (event.title.trim() || fallback.trim() || "Event").slice(
146
+ 0,
147
+ ACTION_CHANGE_TITLE_LIMIT,
148
+ );
149
+ }
150
+
151
+ function eventChangeDetail(
152
+ event: CalendarEvent,
153
+ args: { eventType?: string; fullDay?: boolean; start: string; end: string },
154
+ locale: string,
155
+ additions: Array<string | undefined> = [],
156
+ timezoneFallback?: string,
157
+ ): string | undefined {
158
+ const startTimezone = eventTimezone(
159
+ event.startTimeZone,
160
+ args.start,
161
+ timezoneFallback,
162
+ );
163
+ const endTimezone = eventTimezone(
164
+ event.endTimeZone ?? event.startTimeZone,
165
+ args.end,
166
+ startTimezone ?? timezoneFallback,
167
+ );
168
+ const fullDayOutOfOffice =
169
+ args.eventType === "outOfOffice" && args.fullDay === true;
170
+ let when: string | undefined;
171
+
172
+ if (
173
+ fullDayOutOfOffice &&
174
+ DATE_ONLY_PATTERN.test(args.start) &&
175
+ DATE_ONLY_PATTERN.test(args.end)
176
+ ) {
177
+ const start = localizedDate(args.start, locale);
178
+ const end = localizedDate(args.end, locale);
179
+ if (start && end && startTimezone) {
180
+ when = `${start}${start === end ? "" : `–${end}`} ${eventTimezoneLabel(startTimezone)}`;
181
+ }
182
+ } else if (
183
+ event.allDay ||
184
+ (DATE_ONLY_PATTERN.test(event.start) && DATE_ONLY_PATTERN.test(event.end))
185
+ ) {
186
+ const start = eventDate(event.start, startTimezone);
187
+ const endExclusive = eventDate(event.end, endTimezone);
188
+ if (start && endExclusive) {
189
+ const end = addDaysToDateKey(endExclusive, -1);
190
+ const localizedStart = localizedDate(start, locale);
191
+ const localizedEnd = localizedDate(end, locale);
192
+ if (localizedStart && localizedEnd) {
193
+ when =
194
+ start === end ? localizedStart : `${localizedStart}–${localizedEnd}`;
195
+ }
196
+ }
197
+ } else if (startTimezone && endTimezone) {
198
+ const startDate = eventDate(event.start, startTimezone);
199
+ const endDate = eventDate(event.end, endTimezone);
200
+ const startTime = eventTime(event.start, startTimezone, locale);
201
+ const endTime = eventTime(event.end, endTimezone, locale);
202
+ if (startDate && endDate && startTime && endTime) {
203
+ const localizedStart = localizedDate(startDate, locale);
204
+ const localizedEnd = localizedDate(endDate, locale);
205
+ if (localizedStart && localizedEnd) {
206
+ when =
207
+ startDate === endDate && startTimezone === endTimezone
208
+ ? `${localizedStart} · ${startTime}–${endTime} ${eventTimezoneLabel(startTimezone)}`
209
+ : `${localizedStart} ${startTime} ${eventTimezoneLabel(startTimezone)}–${localizedEnd} ${endTime} ${eventTimezoneLabel(endTimezone)}`;
210
+ }
211
+ }
212
+ }
213
+
214
+ const detail = [when, ...additions, event.location?.trim()]
215
+ .filter((value): value is string => Boolean(value))
216
+ .join(" · ")
217
+ .slice(0, 500);
218
+ return detail || undefined;
219
+ }
220
+
221
+ function eventDeepLink(
222
+ event: Pick<CalendarEvent, "id" | "start" | "startTimeZone">,
223
+ timezoneFallback?: string | null,
224
+ ): string | undefined {
225
+ if (!event.id) return undefined;
226
+ const timezone =
227
+ timezoneFallback === undefined
228
+ ? eventTimezone(event.startTimeZone, event.start)
229
+ : timezoneFallback;
230
+ return buildDeepLink({
231
+ app: "calendar",
232
+ view: "calendar",
233
+ params: {
234
+ eventId: event.id,
235
+ date: eventDate(event.start, timezone),
236
+ },
237
+ });
238
+ }
239
+
37
240
  export default defineAction({
38
241
  description: "Create a calendar event on Google Calendar",
39
242
  schema: z.object({
@@ -148,26 +351,6 @@ export default defineAction({
148
351
  "Connected Google account email whose primary calendar receives the event. Required when multiple accounts are connected.",
149
352
  ),
150
353
  }),
151
- chatUI: {
152
- renderer: "calendar.event-created",
153
- projectResult: (_args, result) => {
154
- const event = result as Record<string, unknown>;
155
- return {
156
- id: event.id,
157
- title: event.title,
158
- start: event.start,
159
- end: event.end,
160
- startTimeZone: event.startTimeZone,
161
- endTimeZone: event.endTimeZone,
162
- allDay: event.allDay,
163
- location: event.location,
164
- hangoutLink: event.hangoutLink,
165
- meetingLink: event.meetingLink,
166
- conferenceData: event.conferenceData,
167
- videoConferenceError: event.videoConferenceError,
168
- };
169
- },
170
- },
171
354
  run: async (args, actionContext?: ActionRunContext) => {
172
355
  const email = getRequestUserEmail();
173
356
  if (!email) throw new Error("no authenticated user");
@@ -195,6 +378,7 @@ export default defineAction({
195
378
  normalizeAttendees(args.attendees),
196
379
  acctEmail,
197
380
  );
381
+ const locale = await getActionLocale(email, actionContext?.requestHeaders);
198
382
  const reminderFields = buildReminderOverrides({
199
383
  reminders: args.reminders,
200
384
  reminderMinutes: args.reminderMinutes,
@@ -239,6 +423,7 @@ export default defineAction({
239
423
 
240
424
  let zoomMeetingLink: string | undefined;
241
425
  let videoConferenceError: CalendarEvent["videoConferenceError"];
426
+ let videoConferenceWarning: string | undefined;
242
427
  if (args.addZoom) {
243
428
  try {
244
429
  const zoom = await prepareZoomMeetingPatch(email, calEvent);
@@ -246,6 +431,7 @@ export default defineAction({
246
431
  Object.assign(calEvent, zoom.patch);
247
432
  } catch (error) {
248
433
  videoConferenceError = "zoom";
434
+ videoConferenceWarning = getZoomFailureMessage(locale);
249
435
  console.error("[create-event] Zoom meeting provisioning failed", error);
250
436
  }
251
437
  }
@@ -269,6 +455,19 @@ export default defineAction({
269
455
  if (videoConferenceError)
270
456
  calEvent.videoConferenceError = videoConferenceError;
271
457
 
458
+ let timezoneFallback: string | undefined;
459
+ if (
460
+ !calEvent.startTimeZone &&
461
+ !/(?:Z|[+-]\d{2}:\d{2})$/i.test(args.start) &&
462
+ !DATE_ONLY_PATTERN.test(args.start)
463
+ ) {
464
+ try {
465
+ timezoneFallback = await getCalendarTimezone(email);
466
+ } catch {
467
+ // coercion-ok: this timezone only formats the result card after event creation.
468
+ }
469
+ }
470
+
272
471
  try {
273
472
  emit(
274
473
  "calendar.event.created",
@@ -304,22 +503,55 @@ export default defineAction({
304
503
  actionContext,
305
504
  );
306
505
 
307
- return calEvent;
506
+ const startTimezone = eventTimezone(
507
+ calEvent.startTimeZone,
508
+ args.start,
509
+ timezoneFallback,
510
+ );
511
+ const url = eventDeepLink(calEvent, startTimezone);
512
+ const conferenceLink = calEvent.meetingLink ?? extractVideoLink(calEvent);
513
+ const detail = eventChangeDetail(
514
+ calEvent,
515
+ args,
516
+ locale,
517
+ [
518
+ conferenceLink && !calEvent.location?.includes(conferenceLink)
519
+ ? conferenceLink
520
+ : undefined,
521
+ videoConferenceWarning,
522
+ ],
523
+ timezoneFallback,
524
+ );
525
+ return {
526
+ ...calEvent,
527
+ change: {
528
+ verb: "created",
529
+ kind: "calendar-event",
530
+ title: eventChangeTitle(calEvent),
531
+ ...(detail ? { detail } : {}),
532
+ ...(url ? { url } : {}),
533
+ },
534
+ };
308
535
  },
309
536
  link: ({ result }) => {
310
537
  if (!result || typeof result !== "object") return null;
311
- const evt = result as { id?: string; start?: string };
312
- if (!evt.id) return null;
313
- const date =
314
- typeof evt.start === "string" && evt.start
315
- ? evt.start.slice(0, 10)
316
- : undefined;
538
+ const evt = result as {
539
+ id?: string;
540
+ start?: string;
541
+ startTimeZone?: string;
542
+ change?: { url?: string };
543
+ };
544
+ if (!evt.id || !evt.start) return null;
545
+ const url =
546
+ evt.change?.url ??
547
+ eventDeepLink({
548
+ id: evt.id,
549
+ start: evt.start,
550
+ startTimeZone: evt.startTimeZone,
551
+ });
552
+ if (!url) return null;
317
553
  return {
318
- url: buildDeepLink({
319
- app: "calendar",
320
- view: "calendar",
321
- params: { eventId: evt.id, date },
322
- }),
554
+ url,
323
555
  label: "Open event in Calendar",
324
556
  view: "calendar",
325
557
  };
@@ -1,3 +1,5 @@
1
+ import { zoomAddFailedMessages } from "../../shared/zoom-add-failed-messages.js";
2
+
1
3
  export default {
2
4
  common: {
3
5
  connect: "Connect",
@@ -47,11 +49,6 @@ export default {
47
49
  noEventId: "No event id provided. Add ?id=<eventId> to the URL.",
48
50
  openCalendar: "Open calendar",
49
51
  },
50
- eventCreation: {
51
- created: "Event created",
52
- zoomNotAdded: "The event was created, but Zoom could not be added.",
53
- openInCalendar: "Open event in Calendar",
54
- },
55
52
  agentSidebar: {
56
53
  emptyState: "Ask me anything about your calendar",
57
54
  suggestions: {
@@ -1013,7 +1010,7 @@ export default {
1013
1010
  year: "year",
1014
1011
  zoom: "Zoom",
1015
1012
  zoomAdded: "Zoom added",
1016
- zoomAddFailed: "Failed to add Zoom",
1013
+ zoomAddFailed: zoomAddFailedMessages["en-US"],
1017
1014
  zoomConnectFailed: "Could not connect Zoom",
1018
1015
  zoomConnectionOpened: "Zoom connection opened",
1019
1016
  zoomNotConfigured: "Zoom OAuth is not configured.",
@@ -42,7 +42,6 @@ import { AppToolkitProvider } from "@/components/ui/toolkit-provider";
42
42
 
43
43
  import changelog from "../CHANGELOG.md?raw";
44
44
  import { i18nCatalog } from "./i18n";
45
- import "@/lib/register-chat-renderers";
46
45
 
47
46
  import stylesheet from "./global.css?url";
48
47
  configureTracking({
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Events created by the agent now show their date and time with a direct link to Calendar.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Calendar event cards retain Meet and Zoom links, show conferencing warnings, and format event times in your selected locale.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Calendar event cards show times in the supplied offset or Calendar timezone and keep long working-location labels readable.
@@ -0,0 +1,13 @@
1
+ export const zoomAddFailedMessages = {
2
+ "en-US": "Failed to add Zoom",
3
+ "es-ES": "No se pudo agregar Zoom",
4
+ "fr-FR": "Échec de l'ajout du Zoom",
5
+ "de-DE": "Zoom konnte nicht hinzugefügt werden",
6
+ "pt-BR": "Falha ao adicionar Zoom",
7
+ "zh-CN": "添加Zoom失败",
8
+ "zh-TW": "新增Zoom失敗",
9
+ "ja-JP": "Zoomの追加に失敗しました",
10
+ "ko-KR": "Zoom를 추가하지 못했습니다.",
11
+ "hi-IN": "Zoom जोड़ने में विफल",
12
+ "ar-SA": "فشلت إضافة Zoom",
13
+ } as const;
@@ -943,14 +943,106 @@ export const editorChromeBridgeScript: string = `"use strict";
943
943
  var editorChromeDocumentObserver = null;
944
944
  var editorChromeRootObserver = null;
945
945
  var repairingEditorChromeHost = false;
946
+ var userFocusedElement = null;
947
+ var trustedFocusIntent = null;
948
+ var focusTargetSelector = '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"]';
949
+ function isCanvasFocusTarget(target) {
950
+ return !!(target && (isEditorTypingTarget(target) || target.matches(focusTargetSelector)));
951
+ }
952
+ function getCanvasFocusTarget(event) {
953
+ var path = event.composedPath();
954
+ for (var i = 0; i < path.length; i += 1) {
955
+ var node = path[i];
956
+ if (!(node instanceof Element)) continue;
957
+ if (node instanceof HTMLLabelElement && node.control) {
958
+ return node.control;
959
+ }
960
+ if (isCanvasFocusTarget(node)) return node;
961
+ var closest = node.closest(focusTargetSelector);
962
+ if (closest) return closest;
963
+ }
964
+ return null;
965
+ }
966
+ function armTrustedFocusIntent(target, kind) {
967
+ trustedFocusIntent = {
968
+ target,
969
+ kind,
970
+ expiresAt: Date.now() + 1e3
971
+ };
972
+ }
973
+ function rememberUserFocusedElement(event) {
974
+ var intent = trustedFocusIntent;
975
+ var target = getCanvasFocusTarget(event);
976
+ if (!intent || Date.now() > intent.expiresAt || !target || intent.kind === "pointer" && (intent.target === null || intent.target !== target && !event.composedPath().includes(intent.target) && !intent.target.contains(target) && !target.contains(intent.target))) {
977
+ trustedFocusIntent = null;
978
+ userFocusedElement = null;
979
+ return;
980
+ }
981
+ userFocusedElement = target;
982
+ trustedFocusIntent = null;
983
+ }
984
+ function rememberTrustedCanvasInput(event) {
985
+ if (readOnly || interactionMode || !event.isTrusted) return;
986
+ var target = event.target;
987
+ if (target instanceof Node && editorChromeHost?.contains(target)) return;
988
+ if (event.type === "pointerdown") {
989
+ var pointerFocusTarget = getCanvasFocusTarget(event);
990
+ userFocusedElement = null;
991
+ if (pointerFocusTarget) {
992
+ var active = document.activeElement;
993
+ var visited = /* @__PURE__ */ new Set();
994
+ while (active && !visited.has(active)) {
995
+ visited.add(active);
996
+ if (active === pointerFocusTarget || pointerFocusTarget.contains(active)) {
997
+ userFocusedElement = pointerFocusTarget;
998
+ break;
999
+ }
1000
+ active = active.shadowRoot?.activeElement || null;
1001
+ }
1002
+ }
1003
+ trustedFocusIntent = pointerFocusTarget ? {
1004
+ target: pointerFocusTarget,
1005
+ kind: "pointer",
1006
+ expiresAt: Date.now() + 1e3
1007
+ } : null;
1008
+ return;
1009
+ }
1010
+ if (event.type === "keydown") {
1011
+ var keyEvent = event;
1012
+ if (keyEvent.key === "Tab") {
1013
+ armTrustedFocusIntent(null, "tab");
1014
+ var tabIntent = trustedFocusIntent;
1015
+ window.setTimeout(function() {
1016
+ if (trustedFocusIntent === tabIntent) trustedFocusIntent = null;
1017
+ }, 0);
1018
+ window.parent.postMessage(
1019
+ { type: "agent-native:canvas-tab-navigation" },
1020
+ "*"
1021
+ );
1022
+ return;
1023
+ }
1024
+ var active = document.activeElement;
1025
+ if (active instanceof Element && isCanvasFocusTarget(active)) {
1026
+ userFocusedElement = active;
1027
+ if (keyEvent.key === "Enter" || keyEvent.key === " " || keyEvent.key === "Escape" || keyEvent.key.startsWith("Arrow")) {
1028
+ armTrustedFocusIntent(active, "activation");
1029
+ }
1030
+ }
1031
+ }
1032
+ }
946
1033
  function isCanvasFocusTransferSafe() {
1034
+ if (trustedFocusIntent && Date.now() > trustedFocusIntent.expiresAt) {
1035
+ if (trustedFocusIntent.target === userFocusedElement) {
1036
+ userFocusedElement = null;
1037
+ }
1038
+ trustedFocusIntent = null;
1039
+ }
947
1040
  if (activeTextEditEl) return false;
948
1041
  var active = document.activeElement;
949
1042
  var visited = /* @__PURE__ */ new Set();
950
- var focusTargetSelector = '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"]';
951
1043
  while (active && !visited.has(active)) {
952
1044
  visited.add(active);
953
- if (isEditorTypingTarget(active) || active.closest?.(focusTargetSelector)) {
1045
+ if (userFocusedElement?.isConnected && (active === userFocusedElement || userFocusedElement.contains(active))) {
954
1046
  return false;
955
1047
  }
956
1048
  var shadowActive = active.shadowRoot?.activeElement;
@@ -958,19 +1050,17 @@ export const editorChromeBridgeScript: string = `"use strict";
958
1050
  active = shadowActive;
959
1051
  continue;
960
1052
  }
961
- if (active !== document.body && active !== document.documentElement && active.matches?.(":focus-within")) {
962
- return false;
963
- }
964
1053
  return true;
965
1054
  }
966
1055
  return true;
967
1056
  }
968
- function reportCanvasFocusState() {
1057
+ function reportCanvasFocusState(reason) {
969
1058
  if (readOnly || interactionMode) return;
970
1059
  window.parent.postMessage(
971
1060
  {
972
1061
  type: "agent-native:canvas-focus-state",
973
- focusSafe: isCanvasFocusTransferSafe()
1062
+ focusSafe: isCanvasFocusTransferSafe(),
1063
+ ...reason ? { reason } : {}
974
1064
  },
975
1065
  "*"
976
1066
  );
@@ -12451,7 +12541,9 @@ export const editorChromeBridgeScript: string = `"use strict";
12451
12541
  clientY,
12452
12542
  dragged
12453
12543
  );
12454
- if (betweenChildren) return betweenChildren;
12544
+ if (betweenChildren && (hit === el.parentElement || isAutoLayoutElement(hit))) {
12545
+ return betweenChildren;
12546
+ }
12455
12547
  return {
12456
12548
  anchor: hit,
12457
12549
  placement: "inside",
@@ -12638,7 +12730,7 @@ export const editorChromeBridgeScript: string = `"use strict";
12638
12730
  var exitedContainer = el.parentElement;
12639
12731
  var receivingContainer = exitedContainer && exitedContainer.parentElement;
12640
12732
  var targetContainer = dropContainerForTarget(target);
12641
- if (!ignoreTargetAutoLayout && target && exitedContainer && receivingContainer && isContainerDropTarget(exitedContainer) && !isAutoLayoutElement(receivingContainer) && target.anchor?.parentElement !== document.body && (targetContainer === receivingContainer || target?.anchor === receivingContainer) && (pointHit === receivingContainer || !pointHit || pointHit === document.body || pointHit === document.documentElement)) {
12733
+ if (!ignoreTargetAutoLayout && target && exitedContainer && receivingContainer && isContainerDropTarget(exitedContainer) && !isAutoLayoutElement(receivingContainer) && !unnestPromotedBoardRootTarget && (targetContainer === receivingContainer || target?.anchor === receivingContainer) && (pointHit === receivingContainer || !pointHit || pointHit === document.body || pointHit === document.documentElement)) {
12642
12734
  target = {
12643
12735
  ...target,
12644
12736
  anchor: exitedContainer,
@@ -17630,11 +17722,35 @@ export const editorChromeBridgeScript: string = `"use strict";
17630
17722
  ].forEach(function(type) {
17631
17723
  document.addEventListener(type, stopBlockedLayerInteraction, true);
17632
17724
  });
17633
- document.addEventListener("focusin", reportCanvasFocusState, true);
17725
+ document.addEventListener(
17726
+ "focusin",
17727
+ function(event) {
17728
+ rememberUserFocusedElement(event);
17729
+ reportCanvasFocusState();
17730
+ },
17731
+ true
17732
+ );
17733
+ document.addEventListener("pointerdown", rememberTrustedCanvasInput, true);
17734
+ document.addEventListener("keydown", rememberTrustedCanvasInput, true);
17634
17735
  document.addEventListener(
17635
17736
  "focusout",
17636
- function() {
17637
- window.setTimeout(reportCanvasFocusState, 0);
17737
+ function(event) {
17738
+ var blurred = event.target instanceof Element ? event.target : null;
17739
+ window.setTimeout(function() {
17740
+ if (blurred && userFocusedElement && (blurred === userFocusedElement || userFocusedElement.contains(blurred))) {
17741
+ var active = document.activeElement;
17742
+ var visited = /* @__PURE__ */ new Set();
17743
+ while (active && !visited.has(active)) {
17744
+ visited.add(active);
17745
+ if (active === userFocusedElement || userFocusedElement.contains(active)) {
17746
+ break;
17747
+ }
17748
+ active = active.shadowRoot?.activeElement || null;
17749
+ }
17750
+ if (!active || !visited.has(active)) userFocusedElement = null;
17751
+ }
17752
+ reportCanvasFocusState();
17753
+ }, 0);
17638
17754
  },
17639
17755
  true
17640
17756
  );
@@ -18756,7 +18872,14 @@ export const editorChromeBridgeScript: string = `"use strict";
18756
18872
  return;
18757
18873
  }
18758
18874
  if (e.data.type === "agent-native:canvas-focus-state-probe") {
18759
- reportCanvasFocusState();
18875
+ reportCanvasFocusState(
18876
+ e.data.reason === "route-change" ? "route-change" : void 0
18877
+ );
18878
+ return;
18879
+ }
18880
+ if (e.data.type === "agent-native:canvas-focus-claimed") {
18881
+ userFocusedElement = null;
18882
+ trustedFocusIntent = null;
18760
18883
  return;
18761
18884
  }
18762
18885
  if (e.data.type === "resume-text-edit") {
@@ -18816,6 +18939,10 @@ export const editorChromeBridgeScript: string = `"use strict";
18816
18939
  }
18817
18940
  if (e.data.type === "set-read-only") {
18818
18941
  var nextReadOnly = !!e.data.readOnly;
18942
+ if (nextReadOnly !== readOnly) {
18943
+ userFocusedElement = null;
18944
+ trustedFocusIntent = null;
18945
+ }
18819
18946
  readOnly = nextReadOnly;
18820
18947
  textEditingEnabled = !readOnly && !interactionMode && textEditingEnabledFlag;
18821
18948
  if (readOnly) {
@@ -18837,6 +18964,10 @@ export const editorChromeBridgeScript: string = `"use strict";
18837
18964
  }
18838
18965
  if (e.data.type === "set-interaction-mode") {
18839
18966
  var nextInteractionMode = e.data.interact === true;
18967
+ if (nextInteractionMode !== interactionMode) {
18968
+ userFocusedElement = null;
18969
+ trustedFocusIntent = null;
18970
+ }
18840
18971
  interactionMode = nextInteractionMode;
18841
18972
  if (interactionMode) {
18842
18973
  var releaseSpacePan = bridgeSpaceKeyPressed;