@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.
- package/corpus/README.md +1 -1
- package/corpus/templates/brain/actions/check-builder-embeddings.ts +71 -0
- package/corpus/templates/brain/app/i18n-data.ts +90 -0
- package/corpus/templates/brain/app/routes/sources.tsx +95 -0
- package/corpus/templates/calendar/actions/create-event.ts +264 -32
- package/corpus/templates/calendar/app/i18n/en-US.ts +3 -6
- package/corpus/templates/calendar/app/root.tsx +0 -1
- package/corpus/templates/calendar/changelog/2026-09-27-agent-created-events-show-details-and-open-links.md +6 -0
- package/corpus/templates/calendar/changelog/2026-09-27-calendar-event-cards-retain-meet-and-zoom-links-show-confere.md +6 -0
- package/corpus/templates/calendar/changelog/2026-09-27-calendar-event-cards-show-times-in-the-supplied-offset-or-ca.md +6 -0
- package/corpus/templates/calendar/shared/zoom-add-failed-messages.ts +13 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +144 -13
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +226 -12
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +191 -18
- package/corpus/templates/design/app/pages/DesignEditor.tsx +24 -4
- package/corpus/templates/design/changelog/2026-09-26-live-previews-keep-canvas-keyboard-shortcuts-available-when-.md +6 -0
- package/corpus/templates/design/changelog/2026-09-27-canvas-shortcuts-keep-working-when-a-connected-app-focuses-a.md +6 -0
- package/corpus/templates/design/changelog/2026-09-27-drops-into-plain-frames-now-stack-above-existing-content-whi.md +6 -0
- package/corpus/templates/design/changelog/2026-09-27-layers-dragged-out-of-a-frame-now-stay-above-the-frame.md +6 -0
- package/corpus/templates/design/changelog/2026-09-27-live-previews-keep-canvas-shortcuts-available-after-autofocu.md +6 -0
- package/corpus/templates/mail/actions/apply-ai-filter.ts +8 -20
- package/corpus/templates/mail/actions/create-scheduled-send.ts +16 -3
- package/corpus/templates/mail/actions/manage-automations.ts +54 -3
- package/corpus/templates/mail/actions/manage-draft.ts +11 -23
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +25 -42
- package/corpus/templates/mail/actions/send-email.ts +52 -2
- package/corpus/templates/mail/app/root.tsx +0 -3
- package/corpus/templates/mail/changelog/2026-09-27-scheduled-sends-reject-timestamps-outside-the-supported-date.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-27-show-successful-mail-changes-in-chat.md +6 -0
- package/dist/action-ui.d.ts +19 -0
- package/dist/action-ui.js +68 -0
- package/dist/agent/production-agent.js +9 -1
- package/dist/client/agentkit-chat/action-widget.d.ts +1 -1
- package/dist/client/agentkit-chat/action-widget.js +25 -0
- package/dist/client/agentkit-chat/approval-card.d.ts +7 -0
- package/dist/client/agentkit-chat/approval-card.js +56 -0
- package/dist/client/agentkit-chat/root.js +2 -0
- package/dist/client/chat/action-chat-ui-surface.js +5 -2
- package/dist/client/chat/agent-approval-card.js +4 -3
- package/dist/client/chat/index.d.ts +2 -1
- package/dist/client/chat/index.js +2 -1
- package/dist/client/chat/tool-call-display.js +3 -0
- package/dist/client/chat/tool-render-registry.d.ts +5 -0
- package/dist/client/chat/widgets/ActionCard.d.ts +9 -0
- package/dist/client/chat/widgets/ActionCard.js +5 -0
- package/dist/client/chat/widgets/RecordChangeWidget.d.ts +10 -0
- package/dist/client/chat/widgets/RecordChangeWidget.js +126 -0
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts +1 -0
- package/dist/client/chat/widgets/builtin-tool-renderers.js +160 -2
- package/dist/client/components/ui/button-classes.d.ts +1 -0
- package/dist/client/components/ui/button-classes.js +1 -0
- package/dist/client/observability/ObservabilityDashboard.js +113 -12
- package/dist/client/observability/ObservabilityReviewSummaryButton.d.ts +1 -1
- package/dist/client/observability/ObservabilityReviewSummaryButton.js +13 -8
- package/dist/client/sse-event-processor.d.ts +1 -0
- package/dist/client/sse-event-processor.js +3 -0
- package/dist/collab/routes.d.ts +2 -2
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/localization/core-messages/ar-SA.js +34 -0
- package/dist/localization/core-messages/de-DE.js +30 -0
- package/dist/localization/core-messages/en-US.d.ts +30 -0
- package/dist/localization/core-messages/en-US.js +30 -0
- package/dist/localization/core-messages/es-ES.js +31 -0
- package/dist/localization/core-messages/fr-FR.js +31 -0
- package/dist/localization/core-messages/hi-IN.js +30 -0
- package/dist/localization/core-messages/ja-JP.js +30 -0
- package/dist/localization/core-messages/ko-KR.js +30 -0
- package/dist/localization/core-messages/pt-BR.js +31 -0
- package/dist/localization/core-messages/zh-CN.js +30 -0
- package/dist/localization/core-messages/zh-TW.js +30 -0
- package/dist/localization/core-messages.d.ts +30 -0
- package/dist/localization/core-messages.js +14 -0
- package/dist/localization/default-messages.d.ts +4 -1
- package/dist/localization/default-messages.js +6 -3
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/reviews.js +26 -14
- package/dist/observability/routes.d.ts +8 -8
- package/dist/observability/store.d.ts +4 -1
- package/dist/observability/store.js +27 -6
- package/dist/observability/types.d.ts +2 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/prompts/framework-core-compact.js +1 -1
- package/dist/server/prompts/framework-core.js +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/package.json +1 -1
- package/corpus/templates/calendar/app/lib/register-chat-renderers.tsx +0 -295
- package/corpus/templates/mail/app/lib/mail-gmail-filter-confirmation.tsx +0 -77
- package/corpus/templates/mail/app/lib/register-chat-renderers.tsx +0 -54
- 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
|
-
|
|
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 {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
|
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: "
|
|
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,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 (
|
|
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)
|
|
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) &&
|
|
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(
|
|
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
|
-
|
|
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;
|