@agent-native/core 0.157.0 → 0.157.1

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 (111) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +19 -4
  3. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +7 -2
  4. package/corpus/templates/assets/app/global.css +4 -0
  5. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +1 -2
  6. package/corpus/templates/brain/app/routes/sources.tsx +1 -2
  7. package/corpus/templates/calendar/app/hooks/use-bookings.ts +12 -2
  8. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +64 -2
  9. package/corpus/templates/calendar/server/handlers/bookings.ts +219 -93
  10. package/corpus/templates/calendar/server/plugins/auth.ts +0 -2
  11. package/corpus/templates/clips/actions/create-folder.ts +7 -1
  12. package/corpus/templates/clips/actions/create-meeting.ts +6 -2
  13. package/corpus/templates/clips/actions/create-recording.ts +5 -3
  14. package/corpus/templates/clips/actions/finalize-recording.ts +97 -65
  15. package/corpus/templates/clips/actions/import-loom-recording.ts +5 -3
  16. package/corpus/templates/clips/actions/request-recording-access.ts +272 -0
  17. package/corpus/templates/clips/actions/stitch-recordings.ts +5 -3
  18. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +38 -63
  19. package/corpus/templates/clips/app/components/player/share-dialog.tsx +75 -75
  20. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -21
  21. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +13 -30
  22. package/corpus/templates/clips/app/i18n/en-US.ts +10 -0
  23. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -5
  24. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -16
  25. package/corpus/templates/clips/app/routes/share.$shareId.tsx +135 -18
  26. package/corpus/templates/clips/changelog/2026-08-14-long-resumable-uploads-now-abort-cleanly-and-show-errors.md +6 -0
  27. package/corpus/templates/clips/changelog/2026-08-14-standardized-share-popovers.md +6 -0
  28. package/corpus/templates/clips/chrome-extension/public/manifest.json +11 -3
  29. package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +37 -8
  30. package/corpus/templates/clips/chrome-extension/src/github-preview.ts +3 -3
  31. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -25
  32. package/corpus/templates/clips/desktop/src/app.tsx +24 -0
  33. package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +42 -13
  34. package/corpus/templates/clips/desktop/src/lib/recorder.ts +11 -18
  35. package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +1 -0
  36. package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
  37. package/corpus/templates/clips/desktop/src/styles.css +24 -9
  38. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -0
  39. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +8 -0
  40. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +154 -176
  41. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +115 -31
  42. package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +7 -0
  43. package/corpus/templates/clips/server/db/index.ts +1 -0
  44. package/corpus/templates/clips/server/db/schema.ts +1 -0
  45. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +6 -1
  46. package/corpus/templates/clips/server/lib/emails.ts +23 -0
  47. package/corpus/templates/clips/server/lib/public-agent-context.ts +55 -0
  48. package/corpus/templates/clips/server/lib/recordings.ts +2 -1
  49. package/corpus/templates/clips/server/lib/resumable-upload-cleanup.ts +49 -0
  50. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +34 -7
  51. package/corpus/templates/clips/server/lib/upload-interruption.ts +15 -1
  52. package/corpus/templates/clips/server/lib/upload-lease.ts +94 -9
  53. package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +82 -7
  54. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
  55. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +71 -12
  56. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -3
  57. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +19 -0
  58. package/corpus/templates/clips/server/routes/api/uploads/reap.post.ts +8 -1
  59. package/corpus/templates/clips/shared/recording-link.ts +4 -0
  60. package/corpus/templates/clips/shared/share-loader-response.ts +2 -1
  61. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +7 -16
  62. package/corpus/templates/factory/AGENTS.md +5 -1
  63. package/corpus/templates/factory/README.md +6 -2
  64. package/corpus/templates/factory/actions/view-screen.ts +15 -0
  65. package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +58 -189
  66. package/corpus/templates/factory/app/components/layout/Header.tsx +1 -0
  67. package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
  68. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +7 -0
  69. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -0
  70. package/corpus/templates/factory/app/i18n/en-US.ts +3 -1
  71. package/corpus/templates/factory/app/routes/agents.tsx +9 -0
  72. package/corpus/templates/mail/server/plugins/auth.ts +0 -2
  73. package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +50 -14
  74. package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -19
  75. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +7 -1
  76. package/corpus/templates/slides/app/context/DeckContext.tsx +71 -22
  77. package/corpus/templates/slides/app/lib/editor-shortcuts.ts +46 -0
  78. package/corpus/templates/slides/app/pages/DeckEditor.tsx +13 -0
  79. package/dist/client/AgentPanel.d.ts +13 -1
  80. package/dist/client/AgentPanel.js +12 -10
  81. package/dist/client/AssistantChat.js +25 -5
  82. package/dist/client/HighlightedCodeBlock.js +12 -2
  83. package/dist/client/agent-chat/index.d.ts +1 -0
  84. package/dist/client/agent-chat/index.js +1 -0
  85. package/dist/client/chat/markdown-renderer.js +16 -3
  86. package/dist/client/chat-first/apps-rail.js +1 -1
  87. package/dist/client/components/ui/message-scroller.js +1 -1
  88. package/dist/client/settings/AccountSettingsCard.js +48 -19
  89. package/dist/client/sharing/ShareButton.d.ts +1 -2
  90. package/dist/client/sharing/ShareButton.js +5 -41
  91. package/dist/client/sharing/ShareDialog.js +5 -4
  92. package/dist/client/use-chat-threads.js +10 -14
  93. package/dist/collab/struct-routes.d.ts +1 -1
  94. package/dist/localization/default-messages.d.ts +1 -0
  95. package/dist/localization/default-messages.js +1 -0
  96. package/dist/progress/routes.d.ts +1 -1
  97. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  98. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  99. package/dist/server/auth-marketing.d.ts +1 -0
  100. package/dist/server/auth-marketing.js +0 -2
  101. package/dist/server/auth.d.ts +1 -0
  102. package/dist/server/auth.js +18 -0
  103. package/dist/server/onboarding-html.d.ts +1 -0
  104. package/dist/server/onboarding-html.js +2 -88
  105. package/dist/server/realtime-token.d.ts +1 -1
  106. package/dist/shared/markdown-block-split.d.ts +16 -0
  107. package/dist/shared/markdown-block-split.js +81 -5
  108. package/dist/styles/agent-native.css +13 -0
  109. package/dist/voice/voice-cleanup-prompt.js +1 -0
  110. package/package.json +2 -2
  111. package/corpus/templates/clips/shared/mic-audio-cleanup.ts +0 -350
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 8236
34
+ - template files: 8241
@@ -265,7 +265,18 @@ export async function getFirstPartyAnalyticsBigQueryBackfillJob(
265
265
  async function getNextFirstPartyAnalyticsBigQueryBackfillJob(
266
266
  db: Executor,
267
267
  now: string,
268
+ scope?: FirstPartyAnalyticsScope,
268
269
  ): Promise<BigQueryBackfillJob | null> {
270
+ const scopeClauses: string[] = [];
271
+ const args: unknown[] = [now, now];
272
+ if (scope?.orgId) {
273
+ scopeClauses.push("AND org_id = ?");
274
+ args.push(scope.orgId);
275
+ }
276
+ if (scope?.userEmail) {
277
+ scopeClauses.push("AND owner_email = ?");
278
+ args.push(scope.userEmail);
279
+ }
269
280
  const result = await db.execute({
270
281
  sql: `SELECT id, org_id, owner_email, table_ref, batch_size,
271
282
  backfill_cursor, status, copied_count, lease_token,
@@ -278,9 +289,10 @@ async function getNextFirstPartyAnalyticsBigQueryBackfillJob(
278
289
  OR (status = 'running' AND lease_expires_at IS NOT NULL
279
290
  AND lease_expires_at <= ?)
280
291
  )
292
+ ${scopeClauses.join("\n ")}
281
293
  ORDER BY updated_at ASC
282
294
  LIMIT 1`,
283
- args: [now, now],
295
+ args,
284
296
  timeoutMs: 3_000,
285
297
  maxAttempts: 1,
286
298
  });
@@ -820,8 +832,8 @@ async function pressureSnapshot(
820
832
  sql: `SELECT
821
833
  COUNT(*) AS total_sessions,
822
834
  SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) AS active_sessions,
823
- SUM(CASE WHEN wait_event_type IS NOT NULL THEN 1 ELSE 0 END) AS waiting_sessions,
824
- SUM(CASE WHEN wait_event_type = 'Lock' THEN 1 ELSE 0 END) AS lock_waiters
835
+ SUM(CASE WHEN state = 'active' AND wait_event_type IS NOT NULL THEN 1 ELSE 0 END) AS waiting_sessions,
836
+ SUM(CASE WHEN state = 'active' AND wait_event_type = 'Lock' THEN 1 ELSE 0 END) AS lock_waiters
825
837
  FROM pg_stat_activity
826
838
  WHERE pid <> pg_backend_pid()`,
827
839
  timeoutMs: 2_000,
@@ -870,7 +882,9 @@ async function recordPressurePause(
870
882
  });
871
883
  }
872
884
 
873
- export async function runFirstPartyAnalyticsBigQueryBackfillOnce(): Promise<BigQueryBackfillSweepResult> {
885
+ export async function runFirstPartyAnalyticsBigQueryBackfillOnce(
886
+ scope?: FirstPartyAnalyticsScope,
887
+ ): Promise<BigQueryBackfillSweepResult> {
874
888
  if (process.env.ANALYTICS_BIGQUERY_BACKFILL_JOBS?.trim() === "0") {
875
889
  return { status: "disabled", batches: 0, copied: 0, remaining: 0 };
876
890
  }
@@ -879,6 +893,7 @@ export async function runFirstPartyAnalyticsBigQueryBackfillOnce(): Promise<BigQ
879
893
  const coordinator = await getNextFirstPartyAnalyticsBigQueryBackfillJob(
880
894
  db,
881
895
  new Date().toISOString(),
896
+ scope,
882
897
  );
883
898
  if (!coordinator) {
884
899
  return { status: "idle", batches: 0, copied: 0, remaining: 0 };
@@ -913,7 +913,8 @@ function addPartitionPrunedEventDeduplication(
913
913
  }
914
914
  result +=
915
915
  sql.slice(cursor, predicateEnd) +
916
- " QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY received_at DESC) = 1";
916
+ " QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY received_at DESC) = 1" +
917
+ (predicateEnd < sql.length ? " " : "");
917
918
  cursor = predicateEnd;
918
919
  }
919
920
  return result;
@@ -1405,7 +1406,11 @@ export async function backfillFirstPartyAnalyticsBatch(
1405
1406
  const selectedRows = rows.slice(0, boundedLimit);
1406
1407
  if (!selectedRows.length) {
1407
1408
  return {
1408
- nextCursor: serializeBackfillCursor(parsedCursor),
1409
+ // An empty shard has no tuple cursor. Returning the sentinel empty
1410
+ // cursor makes the shard worker reject an otherwise successful drain.
1411
+ nextCursor: parsedCursor.receivedAt
1412
+ ? serializeBackfillCursor(parsedCursor)
1413
+ : null,
1409
1414
  copied: 0,
1410
1415
  complete: true,
1411
1416
  };
@@ -107,6 +107,10 @@
107
107
  text-align: center;
108
108
  }
109
109
 
110
+ .assets-create-chat-panel [data-agent-empty-state="centered"] {
111
+ justify-content: safe center;
112
+ }
113
+
110
114
  .assets-create-chat-intro h1 {
111
115
  margin: 0;
112
116
  color: hsl(var(--foreground));
@@ -1217,12 +1217,11 @@ export function BrandKitDetailRoute({
1217
1217
  );
1218
1218
  const shareAction = (
1219
1219
  <ShareButton
1220
- trigger="label-icon"
1221
1220
  resourceType="asset-library"
1222
1221
  resourceId={library.id}
1223
1222
  allowedRoles={["viewer", "editor", "admin"]}
1224
1223
  resourceTitle={library.title}
1225
- triggerClassName="h-10 gap-2 px-4 border-input bg-background hover:bg-accent hover:text-accent-foreground"
1224
+ triggerClassName="h-10 px-4 border-input bg-background hover:bg-accent hover:text-accent-foreground"
1226
1225
  />
1227
1226
  );
1228
1227
  const headerActions = (
@@ -1875,8 +1875,7 @@ function SourceListItem({
1875
1875
  resourceId={source.id}
1876
1876
  allowedRoles={["viewer", "editor", "admin"]}
1877
1877
  resourceTitle={sourceName(source)}
1878
- trigger="icon"
1879
- triggerClassName="size-8"
1878
+ triggerClassName="h-8 px-2"
1880
1879
  />
1881
1880
 
1882
1881
  <DropdownMenu>
@@ -1,5 +1,5 @@
1
1
  import { useActionQuery } from "@agent-native/core/client/hooks";
2
- import type { Booking } from "@shared/api";
2
+ import type { Booking, BookingHost } from "@shared/api";
3
3
  import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
4
4
 
5
5
  import { appApiPath } from "@/lib/api-path";
@@ -17,16 +17,26 @@ export function useBookings() {
17
17
  return useActionQuery<Booking[]>("list-bookings");
18
18
  }
19
19
 
20
+ export type BookingAvailabilityPreview = {
21
+ slug: string;
22
+ durations: number[];
23
+ hosts: BookingHost[];
24
+ };
25
+
20
26
  export function useAvailableSlots(
21
27
  date: string,
22
28
  duration: number,
23
29
  slug?: string,
30
+ draft?: BookingAvailabilityPreview,
24
31
  ) {
32
+ const draftParam = draft ? JSON.stringify(draft) : undefined;
33
+
25
34
  return useQuery<{ start: string; end: string }[]>({
26
- queryKey: ["available-slots", date, duration, slug],
35
+ queryKey: ["available-slots", date, duration, slug, draftParam],
27
36
  queryFn: async () => {
28
37
  const params = new URLSearchParams({ date, duration: String(duration) });
29
38
  if (slug) params.set("slug", slug);
39
+ if (draftParam) params.set("draft", draftParam);
30
40
  const res = await fetch(
31
41
  appApiPath(`/api/bookings/available-slots?${params}`),
32
42
  );
@@ -46,6 +46,7 @@ import {
46
46
  addMonths,
47
47
  subMonths,
48
48
  format,
49
+ parseISO,
49
50
  startOfDay,
50
51
  getDay,
51
52
  } from "date-fns";
@@ -113,6 +114,10 @@ import {
113
114
  useUpdateBookingLink,
114
115
  OPTIMISTIC_PREFIX,
115
116
  } from "@/hooks/use-booking-links";
117
+ import {
118
+ useAvailableSlots,
119
+ type BookingAvailabilityPreview,
120
+ } from "@/hooks/use-bookings";
116
121
  import { useGoogleAuthStatus } from "@/hooks/use-google-auth";
117
122
  import { useSettings } from "@/hooks/use-settings";
118
123
  import { useZoomStatus, useConnectZoom } from "@/hooks/use-zoom-auth";
@@ -826,6 +831,14 @@ export default function BookingLinksPage({
826
831
  !!selectedLink &&
827
832
  savedDraftSignature !== null &&
828
833
  draftSignature !== savedDraftSignature;
834
+ const availabilityPreview =
835
+ selectedLink && !selectedLink.id.startsWith(OPTIMISTIC_PREFIX)
836
+ ? ({
837
+ slug: slugify(draft.slug),
838
+ durations: draft.durations,
839
+ hosts: draft.hosts,
840
+ } satisfies BookingAvailabilityPreview)
841
+ : undefined;
829
842
 
830
843
  function handleCreate() {
831
844
  setCreateDialogOpen(true);
@@ -1535,6 +1548,13 @@ export default function BookingLinksPage({
1535
1548
  customFields={draft.customFields}
1536
1549
  isActive={draft.isActive}
1537
1550
  availability={availability ?? undefined}
1551
+ bookingSourceSlug={
1552
+ selectedLink.id?.startsWith(OPTIMISTIC_PREFIX) ||
1553
+ !availabilityPreview
1554
+ ? undefined
1555
+ : selectedLink.slug
1556
+ }
1557
+ availabilityPreview={availabilityPreview}
1538
1558
  bookingUrl={previewUrl}
1539
1559
  onCopy={() => void copyPreviewUrl(draft.slug)}
1540
1560
  openHref={bookingPreviewPath(draft.slug)}
@@ -2022,6 +2042,8 @@ function BookingPreview({
2022
2042
  customFields = [],
2023
2043
  isActive,
2024
2044
  availability,
2045
+ bookingSourceSlug,
2046
+ availabilityPreview,
2025
2047
  bookingUrl,
2026
2048
  onCopy,
2027
2049
  openHref,
@@ -2034,6 +2056,8 @@ function BookingPreview({
2034
2056
  customFields?: CustomField[];
2035
2057
  isActive: boolean;
2036
2058
  availability?: AvailabilityConfig;
2059
+ bookingSourceSlug?: string;
2060
+ availabilityPreview?: BookingAvailabilityPreview;
2037
2061
  bookingUrl?: string;
2038
2062
  onCopy?: () => void;
2039
2063
  openHref?: string;
@@ -2062,6 +2086,24 @@ function BookingPreview({
2062
2086
  fieldResponses: {},
2063
2087
  });
2064
2088
 
2089
+ const liveAvailabilityDate =
2090
+ bookingSourceSlug && selectedDate ? format(selectedDate, "yyyy-MM-dd") : "";
2091
+ const liveAvailabilityDuration =
2092
+ selectedDuration !== null && durations.includes(selectedDuration)
2093
+ ? selectedDuration
2094
+ : primaryDuration;
2095
+ const {
2096
+ data: liveSlots = [],
2097
+ isLoading: liveSlotsLoading,
2098
+ isError: liveSlotsError,
2099
+ } = useAvailableSlots(
2100
+ liveAvailabilityDate,
2101
+ liveAvailabilityDuration,
2102
+ bookingSourceSlug,
2103
+ availabilityPreview,
2104
+ );
2105
+ const hasLiveAvailability = Boolean(bookingSourceSlug && selectedDate);
2106
+
2065
2107
  // Reset selections when durations change
2066
2108
  useEffect(() => {
2067
2109
  setSelectedDuration(null);
@@ -2092,6 +2134,9 @@ function BookingPreview({
2092
2134
 
2093
2135
  // Generate realistic time slots based on availability
2094
2136
  const timeSlots = useMemo(() => {
2137
+ if (hasLiveAvailability) {
2138
+ return liveSlots.map((slot) => format(parseISO(slot.start), "h:mm a"));
2139
+ }
2095
2140
  if (!selectedDate || !availability) {
2096
2141
  return ["9:00 AM", "9:30 AM", "10:00 AM", "10:30 AM", "11:00 AM"];
2097
2142
  }
@@ -2122,7 +2167,14 @@ function BookingPreview({
2122
2167
  }
2123
2168
  }
2124
2169
  return slots;
2125
- }, [selectedDate, selectedDuration, primaryDuration, availability]);
2170
+ }, [
2171
+ selectedDate,
2172
+ selectedDuration,
2173
+ primaryDuration,
2174
+ availability,
2175
+ hasLiveAvailability,
2176
+ liveSlots,
2177
+ ]);
2126
2178
 
2127
2179
  // Determine which step to show
2128
2180
  const [forcedStep, setForcedStep] = useState<BookingPreviewStep | null>(null);
@@ -2458,7 +2510,17 @@ function BookingPreview({
2458
2510
  {t("bookingLinks.availableTimes")}
2459
2511
  </p>
2460
2512
  )}
2461
- {timeSlots.length > 0 ? (
2513
+ {liveSlotsLoading ? (
2514
+ <div className="grid grid-cols-3 gap-1.5">
2515
+ {Array.from({ length: 6 }).map((_, index) => (
2516
+ <Skeleton key={index} className="h-8 rounded-md" />
2517
+ ))}
2518
+ </div>
2519
+ ) : liveSlotsError ? (
2520
+ <p className="rounded-md border border-destructive/30 bg-destructive/[0.06] px-2.5 py-2 text-center text-xs text-destructive">
2521
+ {t("bookingLinks.availabilityUnavailable")}
2522
+ </p>
2523
+ ) : timeSlots.length > 0 ? (
2462
2524
  <div className="grid grid-cols-3 gap-1.5">
2463
2525
  {timeSlots.map((slot) => (
2464
2526
  <button