@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.
Files changed (31) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/design/actions/generate-home-suggestions.ts +55 -7
  3. package/corpus/templates/design/app/components/design/design-canvas/LocalNetworkAccessPrompt.tsx +82 -18
  4. package/corpus/templates/design/app/i18n/en-US.ts +6 -1
  5. package/corpus/templates/design/changelog/2026-09-27-local-access-setup-shows-chrome-permission-screenshots-and-c.md +6 -0
  6. package/corpus/templates/design/changelog/2026-09-27-personalized-home-suggestions-work-when-responses-include-ex.md +6 -0
  7. package/corpus/templates/mail/app/components/email/EmailList.tsx +10 -0
  8. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +78 -1
  9. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +9 -9
  10. package/corpus/templates/mail/app/components/layout/SearchBar.tsx +192 -175
  11. package/corpus/templates/mail/app/components/onboarding/AiInboxSetup.tsx +4 -0
  12. package/corpus/templates/mail/app/global.css +14 -0
  13. package/corpus/templates/mail/changelog/2026-09-27-inbox-priority-shows-each-email-s-score-with-quick-feedback-.md +6 -0
  14. package/corpus/templates/mail/changelog/2026-09-27-mail-setup-waits-for-first-run-onboarding-and-empty-importan.md +6 -0
  15. package/corpus/templates/mail/changelog/2026-09-27-mobile-inbox-toolbar-scrolls-together.md +6 -0
  16. package/corpus/templates/slides/actions/generate-home-suggestions.ts +55 -11
  17. package/corpus/templates/slides/changelog/2026-09-27-personalized-presentation-suggestions-work-when-responses-in.md +6 -0
  18. package/dist/client/onboarding/first-run-startup-gate.js +3 -2
  19. package/dist/collab/routes.d.ts +1 -1
  20. package/dist/observability/routes.d.ts +5 -5
  21. package/dist/org/auth-policy.js +0 -2
  22. package/dist/progress/routes.d.ts +1 -1
  23. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  24. package/dist/secrets/routes.d.ts +6 -6
  25. package/dist/server/auth-plugin.js +2 -1
  26. package/dist/server/auth.js +22 -43
  27. package/dist/triggers/actions/manage-automation.d.ts +2 -2
  28. package/dist/vite/agent-native-config-loader.js +4 -2
  29. package/package.json +3 -3
  30. package/dist/server/session-email-cache.d.ts +0 -14
  31. 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
- <div
298
- className={cn(
299
- "relative flex items-center rounded bg-accent/80 focus-within:ring-1 focus-within:ring-primary/40",
300
- hasActiveSearch ? "w-56 sm:w-64" : "w-40 sm:w-48",
301
- )}
302
- >
303
- <input
304
- ref={inputRef}
305
- id="mail-search"
306
- data-mail-search
307
- role="combobox"
308
- aria-label={t("mail.search.label")}
309
- aria-autocomplete="list"
310
- aria-controls={showDropdown ? "mail-search-suggestions" : undefined}
311
- aria-expanded={showDropdown}
312
- aria-activedescendant={getActiveDescendantId(
313
- "mail-search-suggestion-",
314
- showDropdown,
315
- selectedIndex,
316
- combinedMatchCount,
317
- )}
318
- autoFocus={autoFocus}
319
- value={query}
320
- onChange={(e) => setQuery(e.target.value)}
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
- </button>
426
- ))}
427
-
428
- {showLocalResults && localMatches.length > 0 && (
429
- <div
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-border/60",
432
- matchedContacts.length > 0 && "border-t",
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
- <div className="px-3 pt-2 pb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70">
436
- {t("mail.search.localResults")}
437
- </div>
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
- tabIndex={-1}
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
- selectThread(thread);
384
+ handleClear();
385
+ }}
386
+ onClick={(e) => {
387
+ if (e.detail === 0) handleClear();
453
388
  }}
454
- onMouseEnter={() => setSelectedIndex(combinedIndex)}
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
- <span className="min-w-0 flex-1 truncate text-foreground/90">
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
- </div>
473
- )}
393
+ </TooltipTrigger>
394
+ <TooltipContent>{t("mail.search.clear")}</TooltipContent>
395
+ </Tooltip>
396
+ )}
397
+ </div>
398
+ </PopoverAnchor>
474
399
 
475
- {showLocalResults && remoteSearchPending && (
476
- <div className="flex items-center gap-2 border-t border-border/60 px-3 py-2 text-[12px] text-muted-foreground">
477
- <IconLoader2 className="h-3 w-3 animate-spin" />
478
- {t("mail.search.searchingGmail")}
479
- </div>
480
- )}
481
- </div>
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;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Inbox Priority shows each email's score with quick feedback and rule settings.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Mail setup waits for first-run onboarding, and empty importance prompts require an explicit skip.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Inbox tabs are visible on mobile, and the full toolbar scrolls together horizontally.
@@ -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
- const start = unwrapped.indexOf("[");
58
- const end = unwrapped.lastIndexOf("]");
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
- parsed = JSON.parse(json);
64
- } catch {
65
- throw new Error("Home suggestions returned invalid JSON.");
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
- const result = suggestionsSchema.safeParse(parsed);
68
- if (!result.success) {
112
+ if (parsedCandidateJson) {
69
113
  throw new Error("Home suggestions returned an invalid shape.");
70
114
  }
71
- return result.data;
115
+ throw new Error("Home suggestions returned invalid JSON.");
72
116
  }
73
117
 
74
118
  export default defineAction({
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-27
4
+ ---
5
+
6
+ Personalized presentation suggestions work when responses include extra text
@@ -71,12 +71,13 @@ export function FirstRunOnboardingStartupGate({ children, fallback = _jsx(AppShe
71
71
  };
72
72
  }, [shouldResolve]);
73
73
  const ownsSurface = decision === "eligible";
74
- const hideApp = decision !== "ineligible";
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: ownsSurface, children: [app, decision === "pending" && (_jsx(FirstRunOnboardingStartupLoading, { fallback: fallback })), ownsSurface && (_jsx(Suspense, { fallback: _jsx(FirstRunOnboardingStartupLoading, { fallback: fallback }), children: _jsx(FirstRunOnboarding, { initialFirstRun: true }) }))] }));
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 }) }));
@@ -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
  }>>;
@@ -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),
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- ok: boolean;
6
5
  error?: undefined;
6
+ ok: boolean;
7
7
  }>>;