@agent-native/core 0.195.0 → 0.195.1-nightly-20260927210321
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/design/actions/generate-home-suggestions.ts +55 -7
- package/corpus/templates/design/app/components/design/design-canvas/LocalNetworkAccessPrompt.tsx +82 -18
- package/corpus/templates/design/app/i18n/en-US.ts +6 -1
- package/corpus/templates/design/changelog/2026-09-27-local-access-setup-shows-chrome-permission-screenshots-and-c.md +6 -0
- package/corpus/templates/design/changelog/2026-09-27-personalized-home-suggestions-work-when-responses-include-ex.md +6 -0
- package/corpus/templates/mail/app/components/email/EmailList.tsx +10 -0
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +78 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +9 -9
- package/corpus/templates/mail/app/components/layout/SearchBar.tsx +192 -175
- package/corpus/templates/mail/app/components/onboarding/AiInboxSetup.tsx +4 -0
- package/corpus/templates/mail/app/global.css +14 -0
- package/corpus/templates/mail/changelog/2026-09-27-inbox-priority-shows-each-email-s-score-with-quick-feedback-.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-27-mail-setup-waits-for-first-run-onboarding-and-empty-importan.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-27-mobile-inbox-toolbar-scrolls-together.md +6 -0
- package/corpus/templates/slides/actions/generate-home-suggestions.ts +55 -11
- package/corpus/templates/slides/changelog/2026-09-27-personalized-presentation-suggestions-work-when-responses-in.md +6 -0
- package/dist/client/onboarding/first-run-startup-gate.js +3 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/org/auth-policy.js +0 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/auth-plugin.js +2 -1
- package/dist/server/auth.js +22 -43
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/dist/vite/agent-native-config-loader.js +4 -2
- package/package.json +3 -3
- package/dist/server/session-email-cache.d.ts +0 -14
- package/dist/server/session-email-cache.js +0 -53
|
@@ -22,6 +22,11 @@ import {
|
|
|
22
22
|
DialogTitle,
|
|
23
23
|
} from "@/components/ui/dialog";
|
|
24
24
|
import { Input } from "@/components/ui/input";
|
|
25
|
+
import {
|
|
26
|
+
Popover,
|
|
27
|
+
PopoverAnchor,
|
|
28
|
+
PopoverContent,
|
|
29
|
+
} from "@/components/ui/popover";
|
|
25
30
|
import {
|
|
26
31
|
Tooltip,
|
|
27
32
|
TooltipContent,
|
|
@@ -294,192 +299,204 @@ export function SearchBar({
|
|
|
294
299
|
|
|
295
300
|
return (
|
|
296
301
|
<div className="relative flex items-center gap-1.5">
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
onKeyDown={handleKeyDown}
|
|
322
|
-
onFocus={() => {
|
|
323
|
-
if (blurCloseTimeoutRef.current !== null) {
|
|
324
|
-
clearTimeout(blurCloseTimeoutRef.current);
|
|
325
|
-
blurCloseTimeoutRef.current = null;
|
|
326
|
-
}
|
|
327
|
-
setIsFocused(true);
|
|
328
|
-
}}
|
|
329
|
-
onBlur={(e) => {
|
|
330
|
-
if (
|
|
331
|
-
e.relatedTarget &&
|
|
332
|
-
(e.relatedTarget as HTMLElement).closest("[data-search-dropdown]")
|
|
333
|
-
) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
setIsFocused(false);
|
|
337
|
-
if (hasActiveSearch || query.trim()) return;
|
|
338
|
-
blurCloseTimeoutRef.current = setTimeout(() => {
|
|
339
|
-
blurCloseTimeoutRef.current = null;
|
|
340
|
-
onClose();
|
|
341
|
-
}, 100);
|
|
342
|
-
}}
|
|
343
|
-
placeholder={t("mail.search.placeholder")}
|
|
344
|
-
className={cn(
|
|
345
|
-
"h-8 sm:h-7 flex-1 min-w-0 bg-transparent border-none px-2.5 text-[13px] text-foreground placeholder:text-muted-foreground/60 outline-none",
|
|
346
|
-
hasActiveSearch && "font-medium",
|
|
347
|
-
)}
|
|
348
|
-
/>
|
|
349
|
-
{hasActiveSearch && onSaveSearch && (
|
|
350
|
-
<Tooltip>
|
|
351
|
-
<TooltipTrigger asChild>
|
|
352
|
-
<button
|
|
353
|
-
type="button"
|
|
354
|
-
aria-label={t("mail.search.saveAsTab")}
|
|
355
|
-
onMouseDown={(e) => e.preventDefault()}
|
|
356
|
-
onClick={handleSaveSearch}
|
|
357
|
-
className="flex h-5 w-5 me-1 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
358
|
-
>
|
|
359
|
-
<IconPin className="h-3.5 w-3.5" />
|
|
360
|
-
</button>
|
|
361
|
-
</TooltipTrigger>
|
|
362
|
-
<TooltipContent>{t("mail.search.saveAsTab")}</TooltipContent>
|
|
363
|
-
</Tooltip>
|
|
364
|
-
)}
|
|
365
|
-
{(hasActiveSearch || query) && (
|
|
366
|
-
<Tooltip>
|
|
367
|
-
<TooltipTrigger asChild>
|
|
368
|
-
<button
|
|
369
|
-
type="button"
|
|
370
|
-
aria-label={t("mail.search.clear")}
|
|
371
|
-
onMouseDown={(e) => {
|
|
372
|
-
e.preventDefault();
|
|
373
|
-
handleClear();
|
|
374
|
-
}}
|
|
375
|
-
onClick={(e) => {
|
|
376
|
-
if (e.detail === 0) handleClear();
|
|
377
|
-
}}
|
|
378
|
-
className="flex h-5 w-5 me-1 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
379
|
-
>
|
|
380
|
-
<IconX className="h-3.5 w-3.5" />
|
|
381
|
-
</button>
|
|
382
|
-
</TooltipTrigger>
|
|
383
|
-
<TooltipContent>{t("mail.search.clear")}</TooltipContent>
|
|
384
|
-
</Tooltip>
|
|
385
|
-
)}
|
|
386
|
-
</div>
|
|
387
|
-
|
|
388
|
-
{/* Contact + instant local-match suggestions dropdown */}
|
|
389
|
-
{showDropdown && (
|
|
390
|
-
<div
|
|
391
|
-
data-search-dropdown
|
|
392
|
-
id="mail-search-suggestions"
|
|
393
|
-
role="listbox"
|
|
394
|
-
ref={listRef}
|
|
395
|
-
className="absolute end-0 top-full mt-1 w-72 rounded-lg border border-border bg-popover shadow-lg z-50 py-1 overflow-hidden"
|
|
396
|
-
>
|
|
397
|
-
{matchedContacts.map((contact, i) => (
|
|
398
|
-
<button
|
|
399
|
-
key={contact.email}
|
|
400
|
-
data-contact-item
|
|
401
|
-
data-search-item
|
|
402
|
-
id={`mail-search-suggestion-${i}`}
|
|
403
|
-
role="option"
|
|
404
|
-
aria-selected={i === selectedIndex}
|
|
405
|
-
type="button"
|
|
406
|
-
tabIndex={-1}
|
|
407
|
-
onMouseDown={(e) => {
|
|
408
|
-
e.preventDefault();
|
|
409
|
-
selectContact(contact);
|
|
410
|
-
}}
|
|
411
|
-
onMouseEnter={() => setSelectedIndex(i)}
|
|
412
|
-
className={cn(
|
|
413
|
-
"flex w-full items-center gap-3 px-3 py-2 text-start text-[13px]",
|
|
414
|
-
i === selectedIndex && "bg-accent",
|
|
415
|
-
)}
|
|
416
|
-
>
|
|
417
|
-
<span className="min-w-0 flex-1 truncate text-foreground/90">
|
|
418
|
-
{highlight(contact.name || contact.email, query.trim())}
|
|
419
|
-
</span>
|
|
420
|
-
{contact.name && (
|
|
421
|
-
<span className="shrink-0 text-muted-foreground text-xs">
|
|
422
|
-
{highlight(contact.email, query.trim())}
|
|
423
|
-
</span>
|
|
302
|
+
<Popover open={showDropdown}>
|
|
303
|
+
<PopoverAnchor asChild>
|
|
304
|
+
<div
|
|
305
|
+
className={cn(
|
|
306
|
+
"relative flex items-center rounded bg-accent/80 focus-within:ring-1 focus-within:ring-primary/40",
|
|
307
|
+
hasActiveSearch ? "w-56 sm:w-64" : "w-40 sm:w-48",
|
|
308
|
+
)}
|
|
309
|
+
>
|
|
310
|
+
<input
|
|
311
|
+
ref={inputRef}
|
|
312
|
+
id="mail-search"
|
|
313
|
+
data-mail-search
|
|
314
|
+
role="combobox"
|
|
315
|
+
aria-label={t("mail.search.label")}
|
|
316
|
+
aria-autocomplete="list"
|
|
317
|
+
aria-controls={
|
|
318
|
+
showDropdown ? "mail-search-suggestions" : undefined
|
|
319
|
+
}
|
|
320
|
+
aria-expanded={showDropdown}
|
|
321
|
+
aria-activedescendant={getActiveDescendantId(
|
|
322
|
+
"mail-search-suggestion-",
|
|
323
|
+
showDropdown,
|
|
324
|
+
selectedIndex,
|
|
325
|
+
combinedMatchCount,
|
|
424
326
|
)}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
327
|
+
autoFocus={autoFocus}
|
|
328
|
+
value={query}
|
|
329
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
330
|
+
onKeyDown={handleKeyDown}
|
|
331
|
+
onFocus={() => {
|
|
332
|
+
if (blurCloseTimeoutRef.current !== null) {
|
|
333
|
+
clearTimeout(blurCloseTimeoutRef.current);
|
|
334
|
+
blurCloseTimeoutRef.current = null;
|
|
335
|
+
}
|
|
336
|
+
setIsFocused(true);
|
|
337
|
+
}}
|
|
338
|
+
onBlur={(e) => {
|
|
339
|
+
if (
|
|
340
|
+
e.relatedTarget &&
|
|
341
|
+
(e.relatedTarget as HTMLElement).closest(
|
|
342
|
+
"[data-search-dropdown]",
|
|
343
|
+
)
|
|
344
|
+
) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
setIsFocused(false);
|
|
348
|
+
if (hasActiveSearch || query.trim()) return;
|
|
349
|
+
blurCloseTimeoutRef.current = setTimeout(() => {
|
|
350
|
+
blurCloseTimeoutRef.current = null;
|
|
351
|
+
onClose();
|
|
352
|
+
}, 100);
|
|
353
|
+
}}
|
|
354
|
+
placeholder={t("mail.search.placeholder")}
|
|
430
355
|
className={cn(
|
|
431
|
-
"border-
|
|
432
|
-
|
|
356
|
+
"h-8 sm:h-7 flex-1 min-w-0 bg-transparent border-none px-2.5 text-[13px] text-foreground placeholder:text-muted-foreground/60 outline-none",
|
|
357
|
+
hasActiveSearch && "font-medium",
|
|
433
358
|
)}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
{localMatches.map((thread, i) => {
|
|
439
|
-
const combinedIndex = matchedContacts.length + i;
|
|
440
|
-
const email = thread.latestMessage;
|
|
441
|
-
return (
|
|
359
|
+
/>
|
|
360
|
+
{hasActiveSearch && onSaveSearch && (
|
|
361
|
+
<Tooltip>
|
|
362
|
+
<TooltipTrigger asChild>
|
|
442
363
|
<button
|
|
443
|
-
key={email.threadId || email.id}
|
|
444
|
-
data-search-item
|
|
445
|
-
id={`mail-search-suggestion-${combinedIndex}`}
|
|
446
|
-
role="option"
|
|
447
|
-
aria-selected={combinedIndex === selectedIndex}
|
|
448
364
|
type="button"
|
|
449
|
-
|
|
365
|
+
aria-label={t("mail.search.saveAsTab")}
|
|
366
|
+
onMouseDown={(e) => e.preventDefault()}
|
|
367
|
+
onClick={handleSaveSearch}
|
|
368
|
+
className="flex h-5 w-5 me-1 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
369
|
+
>
|
|
370
|
+
<IconPin className="h-3.5 w-3.5" />
|
|
371
|
+
</button>
|
|
372
|
+
</TooltipTrigger>
|
|
373
|
+
<TooltipContent>{t("mail.search.saveAsTab")}</TooltipContent>
|
|
374
|
+
</Tooltip>
|
|
375
|
+
)}
|
|
376
|
+
{(hasActiveSearch || query) && (
|
|
377
|
+
<Tooltip>
|
|
378
|
+
<TooltipTrigger asChild>
|
|
379
|
+
<button
|
|
380
|
+
type="button"
|
|
381
|
+
aria-label={t("mail.search.clear")}
|
|
450
382
|
onMouseDown={(e) => {
|
|
451
383
|
e.preventDefault();
|
|
452
|
-
|
|
384
|
+
handleClear();
|
|
385
|
+
}}
|
|
386
|
+
onClick={(e) => {
|
|
387
|
+
if (e.detail === 0) handleClear();
|
|
453
388
|
}}
|
|
454
|
-
|
|
455
|
-
className={cn(
|
|
456
|
-
"flex w-full items-center gap-2 px-3 py-2 text-start text-[13px]",
|
|
457
|
-
combinedIndex === selectedIndex && "bg-accent",
|
|
458
|
-
)}
|
|
389
|
+
className="flex h-5 w-5 me-1 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
459
390
|
>
|
|
460
|
-
<
|
|
461
|
-
{highlight(
|
|
462
|
-
email.subject || email.from.name,
|
|
463
|
-
query.trim(),
|
|
464
|
-
)}
|
|
465
|
-
</span>
|
|
466
|
-
<span className="shrink-0 truncate max-w-[35%] text-muted-foreground text-xs">
|
|
467
|
-
{email.from.name || email.from.email}
|
|
468
|
-
</span>
|
|
391
|
+
<IconX className="h-3.5 w-3.5" />
|
|
469
392
|
</button>
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
393
|
+
</TooltipTrigger>
|
|
394
|
+
<TooltipContent>{t("mail.search.clear")}</TooltipContent>
|
|
395
|
+
</Tooltip>
|
|
396
|
+
)}
|
|
397
|
+
</div>
|
|
398
|
+
</PopoverAnchor>
|
|
474
399
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
400
|
+
{/* Contact + instant local-match suggestions dropdown */}
|
|
401
|
+
{showDropdown && (
|
|
402
|
+
<PopoverContent
|
|
403
|
+
align="end"
|
|
404
|
+
data-search-dropdown
|
|
405
|
+
id="mail-search-suggestions"
|
|
406
|
+
role="listbox"
|
|
407
|
+
ref={listRef}
|
|
408
|
+
side="bottom"
|
|
409
|
+
sideOffset={4}
|
|
410
|
+
onOpenAutoFocus={(event) => event.preventDefault()}
|
|
411
|
+
className="w-72 max-w-[calc(100vw-1rem)] overflow-hidden rounded-lg p-0"
|
|
412
|
+
>
|
|
413
|
+
{matchedContacts.map((contact, i) => (
|
|
414
|
+
<button
|
|
415
|
+
key={contact.email}
|
|
416
|
+
data-contact-item
|
|
417
|
+
data-search-item
|
|
418
|
+
id={`mail-search-suggestion-${i}`}
|
|
419
|
+
role="option"
|
|
420
|
+
aria-selected={i === selectedIndex}
|
|
421
|
+
type="button"
|
|
422
|
+
tabIndex={-1}
|
|
423
|
+
onMouseDown={(e) => {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
selectContact(contact);
|
|
426
|
+
}}
|
|
427
|
+
onMouseEnter={() => setSelectedIndex(i)}
|
|
428
|
+
className={cn(
|
|
429
|
+
"flex w-full items-center gap-3 px-3 py-2 text-start text-[13px]",
|
|
430
|
+
i === selectedIndex && "bg-accent",
|
|
431
|
+
)}
|
|
432
|
+
>
|
|
433
|
+
<span className="min-w-0 flex-1 truncate text-foreground/90">
|
|
434
|
+
{highlight(contact.name || contact.email, query.trim())}
|
|
435
|
+
</span>
|
|
436
|
+
{contact.name && (
|
|
437
|
+
<span className="shrink-0 text-muted-foreground text-xs">
|
|
438
|
+
{highlight(contact.email, query.trim())}
|
|
439
|
+
</span>
|
|
440
|
+
)}
|
|
441
|
+
</button>
|
|
442
|
+
))}
|
|
443
|
+
|
|
444
|
+
{showLocalResults && localMatches.length > 0 && (
|
|
445
|
+
<div
|
|
446
|
+
className={cn(
|
|
447
|
+
"border-border/60",
|
|
448
|
+
matchedContacts.length > 0 && "border-t",
|
|
449
|
+
)}
|
|
450
|
+
>
|
|
451
|
+
<div className="px-3 pt-2 pb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70">
|
|
452
|
+
{t("mail.search.localResults")}
|
|
453
|
+
</div>
|
|
454
|
+
{localMatches.map((thread, i) => {
|
|
455
|
+
const combinedIndex = matchedContacts.length + i;
|
|
456
|
+
const email = thread.latestMessage;
|
|
457
|
+
return (
|
|
458
|
+
<button
|
|
459
|
+
key={email.threadId || email.id}
|
|
460
|
+
data-search-item
|
|
461
|
+
id={`mail-search-suggestion-${combinedIndex}`}
|
|
462
|
+
role="option"
|
|
463
|
+
aria-selected={combinedIndex === selectedIndex}
|
|
464
|
+
type="button"
|
|
465
|
+
tabIndex={-1}
|
|
466
|
+
onMouseDown={(e) => {
|
|
467
|
+
e.preventDefault();
|
|
468
|
+
selectThread(thread);
|
|
469
|
+
}}
|
|
470
|
+
onMouseEnter={() => setSelectedIndex(combinedIndex)}
|
|
471
|
+
className={cn(
|
|
472
|
+
"flex w-full items-center gap-2 px-3 py-2 text-start text-[13px]",
|
|
473
|
+
combinedIndex === selectedIndex && "bg-accent",
|
|
474
|
+
)}
|
|
475
|
+
>
|
|
476
|
+
<span className="min-w-0 flex-1 truncate text-foreground/90">
|
|
477
|
+
{highlight(
|
|
478
|
+
email.subject || email.from.name,
|
|
479
|
+
query.trim(),
|
|
480
|
+
)}
|
|
481
|
+
</span>
|
|
482
|
+
<span className="shrink-0 truncate max-w-[35%] text-muted-foreground text-xs">
|
|
483
|
+
{email.from.name || email.from.email}
|
|
484
|
+
</span>
|
|
485
|
+
</button>
|
|
486
|
+
);
|
|
487
|
+
})}
|
|
488
|
+
</div>
|
|
489
|
+
)}
|
|
490
|
+
|
|
491
|
+
{showLocalResults && remoteSearchPending && (
|
|
492
|
+
<div className="flex items-center gap-2 border-t border-border/60 px-3 py-2 text-[12px] text-muted-foreground">
|
|
493
|
+
<IconLoader2 className="h-3 w-3 animate-spin" />
|
|
494
|
+
{t("mail.search.searchingGmail")}
|
|
495
|
+
</div>
|
|
496
|
+
)}
|
|
497
|
+
</PopoverContent>
|
|
498
|
+
)}
|
|
499
|
+
</Popover>
|
|
483
500
|
|
|
484
501
|
<Dialog
|
|
485
502
|
open={saveDialogOpen}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sendToAgentChat } from "@agent-native/core/client/agent-chat";
|
|
2
2
|
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
3
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
|
+
import { useFirstRunOnboardingGateOwnsSurface } from "@agent-native/core/client/onboarding";
|
|
4
5
|
import { AI_FILTER_LABEL } from "@shared/ai-filter";
|
|
5
6
|
import type { AiFilterBackfillStatus } from "@shared/ai-filter-backfill";
|
|
6
7
|
import {
|
|
@@ -402,6 +403,7 @@ export function AiInboxSetup({
|
|
|
402
403
|
onSkipSetup?: () => void;
|
|
403
404
|
}) {
|
|
404
405
|
const t = useT();
|
|
406
|
+
const firstRunOnboardingOwnsSurface = useFirstRunOnboardingGateOwnsSurface();
|
|
405
407
|
const { data: settings } = useSettings();
|
|
406
408
|
const { data: rules = [], isLoading: rulesLoading } = useAutomations();
|
|
407
409
|
const googleStatus = useGoogleAuthStatus();
|
|
@@ -467,6 +469,7 @@ export function AiInboxSetup({
|
|
|
467
469
|
[rules],
|
|
468
470
|
);
|
|
469
471
|
const visible =
|
|
472
|
+
!firstRunOnboardingOwnsSurface &&
|
|
470
473
|
connected &&
|
|
471
474
|
!googleStatus.isLoading &&
|
|
472
475
|
!jevAvailability.isLoading &&
|
|
@@ -960,6 +963,7 @@ export function AiInboxSetup({
|
|
|
960
963
|
step < 3 &&
|
|
961
964
|
(saving ||
|
|
962
965
|
customTagIncomplete ||
|
|
966
|
+
(step === 1 && !importantPrompt.trim()) ||
|
|
963
967
|
(step === 2 && (!jevConfigured || rulesLoading)))
|
|
964
968
|
}
|
|
965
969
|
aria-busy={saving || (step === 2 && rulesLoading)}
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
--mail-label-finance-text: 163 94% 24%;
|
|
57
57
|
--mail-label-travel-bg: 187 85% 53% / 0.2;
|
|
58
58
|
--mail-label-travel-text: 192 91% 36%;
|
|
59
|
+
--mail-importance-low: oklch(56% 0.17 25);
|
|
60
|
+
--mail-importance-high: oklch(50% 0.15 145);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
.dark {
|
|
@@ -101,6 +103,8 @@
|
|
|
101
103
|
--mail-label-forums-text: 199 95% 74%;
|
|
102
104
|
--mail-label-finance-text: 152 76% 70%;
|
|
103
105
|
--mail-label-travel-text: 188 86% 74%;
|
|
106
|
+
--mail-importance-low: oklch(78% 0.13 25);
|
|
107
|
+
--mail-importance-high: oklch(78% 0.13 145);
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
@layer base {
|
|
@@ -260,6 +264,16 @@
|
|
|
260
264
|
z-index: 3;
|
|
261
265
|
flex: none;
|
|
262
266
|
}
|
|
267
|
+
.email-importance-score {
|
|
268
|
+
position: relative;
|
|
269
|
+
z-index: 3;
|
|
270
|
+
color: hsl(var(--foreground));
|
|
271
|
+
color: color-mix(
|
|
272
|
+
in oklch,
|
|
273
|
+
var(--mail-importance-low) calc(100% - var(--mail-importance-weight)),
|
|
274
|
+
var(--mail-importance-high) var(--mail-importance-weight)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
263
277
|
.email-list-row.focused .hover-actions,
|
|
264
278
|
.email-list-row:hover .hover-actions {
|
|
265
279
|
opacity: 1;
|
|
@@ -49,26 +49,70 @@ function roleContext(value: string | null | undefined): string {
|
|
|
49
49
|
return `The user's selected onboarding role is ${JSON.stringify(role)}. Tailor suggestions to that role's typical work and goals.`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function findArrayEnd(text: string, start: number): number | undefined {
|
|
53
|
+
let depth = 0;
|
|
54
|
+
let inString = false;
|
|
55
|
+
let escaped = false;
|
|
56
|
+
|
|
57
|
+
for (let index = start; index < text.length; index++) {
|
|
58
|
+
const char = text[index];
|
|
59
|
+
if (inString) {
|
|
60
|
+
if (escaped) escaped = false;
|
|
61
|
+
else if (char === "\\") escaped = true;
|
|
62
|
+
else if (char === '"') inString = false;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (char === '"') inString = true;
|
|
66
|
+
else if (char === "[") depth++;
|
|
67
|
+
else if (char === "]" && --depth === 0) return index;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
52
71
|
function parseSuggestions(text: string) {
|
|
53
72
|
const unwrapped = text
|
|
54
73
|
.trim()
|
|
55
74
|
.replace(/^```(?:json)?\s*/i, "")
|
|
56
75
|
.replace(/\s*```$/i, "");
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const json =
|
|
60
|
-
start >= 0 && end > start ? unwrapped.slice(start, end + 1) : unwrapped;
|
|
61
|
-
let parsed: unknown;
|
|
76
|
+
let parsedJson: unknown;
|
|
77
|
+
let hasTopLevelJson = false;
|
|
62
78
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
parsedJson = JSON.parse(unwrapped);
|
|
80
|
+
hasTopLevelJson = true;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
83
|
+
}
|
|
84
|
+
if (hasTopLevelJson) {
|
|
85
|
+
const result = suggestionsSchema.safeParse(parsedJson);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
throw new Error("Home suggestions returned an invalid shape.");
|
|
88
|
+
}
|
|
89
|
+
return result.data;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let parsedCandidateJson = false;
|
|
93
|
+
for (
|
|
94
|
+
let start = unwrapped.indexOf("[");
|
|
95
|
+
start >= 0;
|
|
96
|
+
start = unwrapped.indexOf("[", start + 1)
|
|
97
|
+
) {
|
|
98
|
+
const end = findArrayEnd(unwrapped, start);
|
|
99
|
+
if (end === undefined) continue;
|
|
100
|
+
|
|
101
|
+
let parsed: unknown;
|
|
102
|
+
try {
|
|
103
|
+
parsed = JSON.parse(unwrapped.slice(start, end + 1));
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
parsedCandidateJson = true;
|
|
109
|
+
const result = suggestionsSchema.safeParse(parsed);
|
|
110
|
+
if (result.success) return result.data;
|
|
66
111
|
}
|
|
67
|
-
|
|
68
|
-
if (!result.success) {
|
|
112
|
+
if (parsedCandidateJson) {
|
|
69
113
|
throw new Error("Home suggestions returned an invalid shape.");
|
|
70
114
|
}
|
|
71
|
-
|
|
115
|
+
throw new Error("Home suggestions returned invalid JSON.");
|
|
72
116
|
}
|
|
73
117
|
|
|
74
118
|
export default defineAction({
|
|
@@ -71,12 +71,13 @@ export function FirstRunOnboardingStartupGate({ children, fallback = _jsx(AppShe
|
|
|
71
71
|
};
|
|
72
72
|
}, [shouldResolve]);
|
|
73
73
|
const ownsSurface = decision === "eligible";
|
|
74
|
-
const
|
|
74
|
+
const gateOwnsSurface = decision !== "ineligible";
|
|
75
|
+
const hideApp = gateOwnsSurface;
|
|
75
76
|
const app = shouldResolve ? (_jsx("div", { "aria-hidden": hideApp ? "true" : undefined, "data-first-run-app-hidden": hideApp ? "true" : undefined, style: {
|
|
76
77
|
display: "contents",
|
|
77
78
|
...(hideApp ? { visibility: "hidden" } : {}),
|
|
78
79
|
}, children: children })) : (children);
|
|
79
|
-
return (_jsxs(FirstRunOnboardingGateContext.Provider, { value:
|
|
80
|
+
return (_jsxs(FirstRunOnboardingGateContext.Provider, { value: gateOwnsSurface, children: [app, decision === "pending" && (_jsx(FirstRunOnboardingStartupLoading, { fallback: fallback })), ownsSurface && (_jsx(Suspense, { fallback: _jsx(FirstRunOnboardingStartupLoading, { fallback: fallback }), children: _jsx(FirstRunOnboarding, { initialFirstRun: true }) }))] }));
|
|
80
81
|
}
|
|
81
82
|
function FirstRunOnboardingStartupLoading({ fallback, }) {
|
|
82
83
|
return (_jsx("div", { role: "status", "aria-label": "Loading application", "data-first-run-startup-loading": "true", className: "fixed inset-0 z-[110] bg-background", children: _jsx("div", { inert: true, children: fallback }) }));
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -16,8 +16,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
16
16
|
}>>;
|
|
17
17
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
18
18
|
ok?: undefined;
|
|
19
|
-
text?: undefined;
|
|
20
19
|
error: string;
|
|
20
|
+
text?: undefined;
|
|
21
21
|
} | {
|
|
22
22
|
error?: undefined;
|
|
23
23
|
ok: boolean;
|
|
@@ -20,27 +20,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
20
20
|
thumbsUpRate: number;
|
|
21
21
|
avgEvalScore: number;
|
|
22
22
|
} | {
|
|
23
|
+
error?: undefined;
|
|
24
|
+
ok?: undefined;
|
|
23
25
|
summary: import("./types.js").TraceSummary;
|
|
24
26
|
spans: import("./types.js").TraceSpan[];
|
|
25
27
|
id?: undefined;
|
|
28
|
+
} | {
|
|
26
29
|
error?: undefined;
|
|
27
30
|
ok?: undefined;
|
|
28
|
-
} | {
|
|
29
31
|
summary?: undefined;
|
|
30
32
|
spans?: undefined;
|
|
31
33
|
id: string;
|
|
32
|
-
error?: undefined;
|
|
33
|
-
ok?: undefined;
|
|
34
34
|
} | {
|
|
35
|
+
ok?: undefined;
|
|
35
36
|
summary?: undefined;
|
|
36
37
|
spans?: undefined;
|
|
37
38
|
id?: undefined;
|
|
38
39
|
error: any;
|
|
39
|
-
ok?: undefined;
|
|
40
40
|
} | {
|
|
41
|
+
error?: undefined;
|
|
41
42
|
summary?: undefined;
|
|
42
43
|
spans?: undefined;
|
|
43
44
|
id?: undefined;
|
|
44
|
-
error?: undefined;
|
|
45
45
|
ok: boolean;
|
|
46
46
|
}>>;
|
package/dist/org/auth-policy.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getCurrentAdapter } from "better-auth";
|
|
2
2
|
import { getAppConfig } from "../app-config/index.js";
|
|
3
3
|
import { getDbExec } from "../db/client.js";
|
|
4
|
-
import { invalidateSessionEmailCache } from "../server/session-email-cache.js";
|
|
5
4
|
export const GOOGLE_AUTH_REQUIRED_MESSAGE = "This organization requires Google sign-in.";
|
|
6
5
|
export const SSO_AUTH_REQUIRED_MESSAGE = "This organization requires single sign-on.";
|
|
7
6
|
export function authProviderRequiredMessage(provider) {
|
|
@@ -184,7 +183,6 @@ export async function setRequiredAuthProvider(orgId, provider) {
|
|
|
184
183
|
if (!isMissingLegacySessionTable(error))
|
|
185
184
|
throw error;
|
|
186
185
|
}
|
|
187
|
-
invalidateSessionEmailCache();
|
|
188
186
|
return {
|
|
189
187
|
revokedBetterAuthSessions: Number(betterAuthResult.rowsAffected ?? 0),
|
|
190
188
|
revokedLegacySessions: Number(legacyResult.rowsAffected ?? 0),
|