@agent-native/core 0.102.1 → 0.102.2

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 (113) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +9 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/client/AgentPanel.tsx +7 -0
  5. package/corpus/core/src/client/AssistantChat.tsx +7 -0
  6. package/corpus/core/src/client/agent-chat-adapter.ts +7 -1
  7. package/corpus/core/src/client/chat/message-components.tsx +17 -3
  8. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +96 -6
  9. package/corpus/core/src/client/composer/asset-picker-url.ts +80 -0
  10. package/corpus/core/src/client/error-format.ts +24 -0
  11. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +8 -1
  12. package/corpus/templates/assets/app/routes/library.tsx +69 -0
  13. package/corpus/templates/assets/changelog/2026-07-15-fixed-top-level-image-picker-selections-returning-to-the-com.md +6 -0
  14. package/corpus/templates/clips/actions/disconnect-calendar.ts +57 -9
  15. package/corpus/templates/clips/actions/generate-workflow.ts +102 -59
  16. package/corpus/templates/clips/actions/get-recording-player-data.ts +64 -1
  17. package/corpus/templates/clips/actions/regenerate-summary.ts +7 -0
  18. package/corpus/templates/clips/actions/regenerate-title.ts +29 -11
  19. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +22 -11
  20. package/corpus/templates/clips/app/components/editor/thumbnail-picker.tsx +87 -9
  21. package/corpus/templates/clips/app/components/editor/trim-handles.tsx +15 -0
  22. package/corpus/templates/clips/app/components/editor/waveform.tsx +21 -8
  23. package/corpus/templates/clips/app/components/library/folder-tree.tsx +52 -0
  24. package/corpus/templates/clips/app/components/player/settings-panel.tsx +86 -46
  25. package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -37
  26. package/corpus/templates/clips/app/components/player/video-player.tsx +45 -1
  27. package/corpus/templates/clips/app/i18n/ar-SA.ts +2 -0
  28. package/corpus/templates/clips/app/i18n/de-DE.ts +2 -0
  29. package/corpus/templates/clips/app/i18n/en-US.ts +2 -0
  30. package/corpus/templates/clips/app/i18n/es-ES.ts +2 -0
  31. package/corpus/templates/clips/app/i18n/fr-FR.ts +2 -0
  32. package/corpus/templates/clips/app/i18n/hi-IN.ts +2 -0
  33. package/corpus/templates/clips/app/i18n/ja-JP.ts +2 -0
  34. package/corpus/templates/clips/app/i18n/ko-KR.ts +2 -0
  35. package/corpus/templates/clips/app/i18n/pt-BR.ts +2 -0
  36. package/corpus/templates/clips/app/i18n/zh-CN.ts +2 -0
  37. package/corpus/templates/clips/app/i18n/zh-TW.ts +2 -0
  38. package/corpus/templates/clips/app/lib/timestamp-mapping.ts +14 -0
  39. package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -2
  40. package/corpus/templates/clips/app/routes/_index.tsx +1 -2
  41. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +71 -31
  42. package/corpus/templates/clips/app/routes/share.$shareId.tsx +4 -1
  43. package/corpus/templates/clips/changelog/2026-07-15-ai-workflow-generation-now-stays-visible-avoids-duplicate-re.md +6 -0
  44. package/corpus/templates/clips/changelog/2026-07-15-clip-playback-and-cta-controls-remain-interactive-through-ed.md +6 -0
  45. package/corpus/templates/clips/changelog/2026-07-15-clip-titles-no-longer-describe-the-product-as-a-loom-alterna.md +6 -0
  46. package/corpus/templates/clips/changelog/2026-07-15-description-regeneration-now-opens-the-agent-chat-so-progres.md +6 -0
  47. package/corpus/templates/clips/changelog/2026-07-15-direct-recording-urls-now-respect-share-link-and-password-ac.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-15-disconnecting-a-calendar-now-clears-unrecorded-synced-meetin.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-15-folders-now-expose-rename-and-delete-actions-directly-in-the.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-07-15-recording-pages-now-explain-sign-in-access-and-avoid-showing.md +6 -0
  51. package/corpus/templates/clips/changelog/2026-07-15-the-clips-extension-quick-actions-toolbar-can-be-moved-out-o.md +6 -0
  52. package/corpus/templates/clips/changelog/2026-07-15-the-editor-now-skips-cut-sections-during-preview-and-keeps-t.md +6 -0
  53. package/corpus/templates/clips/changelog/2026-07-15-thumbnail-capture-now-updates-previews-while-scrubbing-and-l.md +6 -0
  54. package/corpus/templates/clips/changelog/2026-07-15-windows-permission-links-open-the-matching-settings-page.md +6 -0
  55. package/corpus/templates/clips/chrome-extension/src/content-script.ts +117 -2
  56. package/corpus/templates/clips/chrome-extension/src/overlay.ts +27 -0
  57. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  58. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +139 -101
  59. package/corpus/templates/clips/server/lib/recording-page-access.ts +35 -0
  60. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +7 -3
  61. package/corpus/templates/design/changelog/2026-07-15-prototype-print-and-download-buttons-now-work-in-preview.md +6 -0
  62. package/corpus/templates/slides/actions/extract-pdf.ts +1 -1
  63. package/corpus/templates/slides/actions/import-file.ts +4 -1
  64. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
  65. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +9 -12
  66. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +29 -21
  67. package/corpus/templates/slides/app/i18n/ar-SA.ts +1 -0
  68. package/corpus/templates/slides/app/i18n/de-DE.ts +1 -0
  69. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  70. package/corpus/templates/slides/app/i18n/es-ES.ts +1 -0
  71. package/corpus/templates/slides/app/i18n/fr-FR.ts +1 -0
  72. package/corpus/templates/slides/app/i18n/hi-IN.ts +1 -0
  73. package/corpus/templates/slides/app/i18n/ja-JP.ts +1 -0
  74. package/corpus/templates/slides/app/i18n/ko-KR.ts +1 -0
  75. package/corpus/templates/slides/app/i18n/pt-BR.ts +1 -0
  76. package/corpus/templates/slides/app/i18n/zh-CN.ts +1 -0
  77. package/corpus/templates/slides/app/i18n/zh-TW.ts +1 -0
  78. package/corpus/templates/slides/changelog/2026-07-15-image-search-and-generation-controls-now-use-the-registered-.md +6 -0
  79. package/corpus/templates/slides/changelog/2026-07-15-pdf-deck-references-can-be-imported-for-slide-inspiration-ag.md +6 -0
  80. package/corpus/templates/slides/changelog/2026-07-15-stable-style-inspector-dock.md +6 -0
  81. package/dist/client/AgentPanel.d.ts.map +1 -1
  82. package/dist/client/AgentPanel.js +5 -0
  83. package/dist/client/AgentPanel.js.map +1 -1
  84. package/dist/client/AssistantChat.d.ts.map +1 -1
  85. package/dist/client/AssistantChat.js +7 -0
  86. package/dist/client/AssistantChat.js.map +1 -1
  87. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  88. package/dist/client/agent-chat-adapter.js +8 -1
  89. package/dist/client/agent-chat-adapter.js.map +1 -1
  90. package/dist/client/chat/message-components.d.ts +4 -0
  91. package/dist/client/chat/message-components.d.ts.map +1 -1
  92. package/dist/client/chat/message-components.js +10 -3
  93. package/dist/client/chat/message-components.js.map +1 -1
  94. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  95. package/dist/client/composer/ComposerPlusMenu.js +58 -6
  96. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  97. package/dist/client/composer/asset-picker-url.d.ts +16 -0
  98. package/dist/client/composer/asset-picker-url.d.ts.map +1 -0
  99. package/dist/client/composer/asset-picker-url.js +64 -0
  100. package/dist/client/composer/asset-picker-url.js.map +1 -0
  101. package/dist/client/error-format.d.ts.map +1 -1
  102. package/dist/client/error-format.js +17 -0
  103. package/dist/client/error-format.js.map +1 -1
  104. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  105. package/dist/client/resources/McpIntegrationDialog.js +6 -1
  106. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  107. package/dist/observability/routes.d.ts +5 -5
  108. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  109. package/dist/resources/handlers.d.ts +2 -2
  110. package/dist/secrets/routes.d.ts +9 -9
  111. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  112. package/dist/server/transcribe-voice.d.ts +1 -1
  113. package/package.json +1 -1
@@ -274,6 +274,27 @@ export function calendarEventToMeetingView(args: {
274
274
  };
275
275
  }
276
276
 
277
+ /**
278
+ * Acquire the calendar account's write lock inside a caller-owned transaction.
279
+ * Disconnect and materialization both take this lock before touching the
280
+ * account's calendar events, so cleanup cannot race a meeting insert.
281
+ */
282
+ export async function lockCalendarAccount(
283
+ db: any,
284
+ accountId: string,
285
+ ownerEmail?: string | null,
286
+ ): Promise<boolean> {
287
+ const ownerFilter = ownerEmail
288
+ ? eq(schema.calendarAccounts.ownerEmail, ownerEmail)
289
+ : isNull(schema.calendarAccounts.ownerEmail);
290
+ const locked = await db
291
+ .update(schema.calendarAccounts)
292
+ .set({ updatedAt: new Date().toISOString() })
293
+ .where(and(eq(schema.calendarAccounts.id, accountId), ownerFilter))
294
+ .returning({ id: schema.calendarAccounts.id });
295
+ return locked.length > 0;
296
+ }
297
+
277
298
  export async function fetchLiveCalendarEventFromId(virtualId: string) {
278
299
  const parsed = parseCalendarMeetingId(virtualId);
279
300
  if (!parsed) return null;
@@ -317,11 +338,14 @@ export async function fetchLiveCalendarEventFromId(virtualId: string) {
317
338
  }
318
339
  }
319
340
 
320
- export async function upsertCalendarEventSnapshot(args: {
321
- account: CalendarAccountForEvents;
322
- event: CalendarEvent;
323
- }) {
324
- const db = getDb();
341
+ export async function upsertCalendarEventSnapshot(
342
+ args: {
343
+ account: CalendarAccountForEvents;
344
+ event: CalendarEvent;
345
+ },
346
+ database: any = getDb(),
347
+ ) {
348
+ const db = database;
325
349
  const startIso = eventStartIso(args.event);
326
350
  const endIso = eventEndIso(args.event);
327
351
  if (!args.event.id || !startIso || !endIso) {
@@ -397,120 +421,134 @@ export async function materializeCalendarMeetingFromVirtualId(
397
421
  const live = await fetchLiveCalendarEventFromId(virtualId);
398
422
  if (!live) return null;
399
423
  const db = getDb();
400
- const snapshot = await upsertCalendarEventSnapshot(live);
401
-
402
- if (snapshot.meetingId) {
403
- const [existingMeeting] = await db
404
- .select()
405
- .from(schema.meetings)
406
- .where(eq(schema.meetings.id, snapshot.meetingId))
407
- .limit(1);
408
- if (existingMeeting) return { meeting: existingMeeting, created: false };
409
- }
410
-
411
424
  const ownerEmail = getCurrentOwnerEmail();
412
425
  const orgId = (await getActiveOrganizationId().catch(() => null)) ?? null;
413
426
  const joinUrl = pickJoinUrl(live.event);
414
427
  const meetingId = nanoid();
415
428
  const nowIso = new Date().toISOString();
416
429
 
417
- // Claim the calendar_events row atomically before inserting the meeting
418
- // row, so two concurrent materialize calls for the same event can't both
419
- // insert a `meetings` row (check-then-act TOCTOU). Only the caller whose
420
- // UPDATE actually matched a row (meetingId still NULL) proceeds to insert;
421
- // the loser re-reads and returns the winner's meeting instead.
422
- const claimed = await db
423
- .update(schema.calendarEvents)
424
- .set({ meetingId, updatedAt: nowIso })
425
- .where(
426
- and(
427
- eq(schema.calendarEvents.id, snapshot.id),
428
- isNull(schema.calendarEvents.meetingId),
429
- ),
430
+ return db.transaction(async (tx: any) => {
431
+ // Disconnect takes this same account-row write lock before it snapshots
432
+ // and deletes events. If disconnect wins, the account is gone by the time
433
+ // this transaction reaches the lock and materialization becomes a no-op.
434
+ if (
435
+ !(await lockCalendarAccount(tx, live.account.id, live.account.ownerEmail))
430
436
  )
431
- .returning({ id: schema.calendarEvents.id });
432
-
433
- if (!claimed.length) {
434
- // Someone else claimed it first — re-read and return their meeting.
435
- const [winnerEvent] = await db
436
- .select({ meetingId: schema.calendarEvents.meetingId })
437
- .from(schema.calendarEvents)
438
- .where(eq(schema.calendarEvents.id, snapshot.id))
439
- .limit(1);
440
- if (winnerEvent?.meetingId) {
441
- const [winnerMeeting] = await db
437
+ return null;
438
+
439
+ const snapshot = await upsertCalendarEventSnapshot(live, tx);
440
+
441
+ if (snapshot.meetingId) {
442
+ const [existingMeeting] = await tx
442
443
  .select()
443
444
  .from(schema.meetings)
444
- .where(eq(schema.meetings.id, winnerEvent.meetingId))
445
+ .where(eq(schema.meetings.id, snapshot.meetingId))
445
446
  .limit(1);
446
- if (winnerMeeting) return { meeting: winnerMeeting, created: false };
447
+ if (existingMeeting) {
448
+ return { meeting: existingMeeting, created: false };
449
+ }
447
450
  }
448
- return null;
449
- }
450
451
 
451
- try {
452
- await db.insert(schema.meetings).values({
453
- id: meetingId,
454
- organizationId: orgId ?? live.account.orgId ?? null,
455
- title: live.event.summary || "Untitled meeting",
456
- scheduledStart: eventStartIso(live.event),
457
- scheduledEnd: eventEndIso(live.event),
458
- actualStart: null,
459
- actualEnd: null,
460
- platform: detectPlatform(joinUrl),
461
- joinUrl: joinUrl ?? null,
462
- calendarEventId: snapshot.id,
463
- recordingId: null,
464
- transcriptStatus: "idle",
465
- summaryMd: "",
466
- bulletsJson: "[]",
467
- actionItemsJson: "[]",
468
- source: "calendar",
469
- reminderFiredAt: null,
470
- createdAt: nowIso,
471
- updatedAt: nowIso,
472
- ownerEmail,
473
- orgId,
474
- visibility: "private",
475
- } as any);
476
-
477
- const participants = calendarEventParticipants(live.event).filter(
478
- (p) => p.email,
479
- );
480
- if (participants.length) {
481
- await db.insert(schema.meetingParticipants).values(
482
- participants.map((p) => ({
483
- id: nanoid(),
484
- meetingId,
485
- email: p.email,
486
- name: p.name ?? null,
487
- isOrganizer: !!p.isOrganizer,
488
- attendedAt: null,
489
- createdAt: nowIso,
490
- })) as any,
491
- );
492
- }
493
- } catch (err) {
494
- // Roll back the claim so a future call can retry — but only if it still
495
- // points at our own meetingId (don't clobber a legitimate later claim).
496
- await db
452
+ // Claim the calendar_events row atomically before inserting the meeting
453
+ // row, so two concurrent materialize calls for the same event can't both
454
+ // insert a `meetings` row (check-then-act TOCTOU). Only the caller whose
455
+ // UPDATE actually matched a row (meetingId still NULL) proceeds to insert;
456
+ // the loser re-reads and returns the winner's meeting instead.
457
+ const claimed = await tx
497
458
  .update(schema.calendarEvents)
498
- .set({ meetingId: null, updatedAt: new Date().toISOString() })
459
+ .set({ meetingId, updatedAt: nowIso })
499
460
  .where(
500
461
  and(
501
462
  eq(schema.calendarEvents.id, snapshot.id),
502
- eq(schema.calendarEvents.meetingId, meetingId),
463
+ isNull(schema.calendarEvents.meetingId),
503
464
  ),
504
465
  )
505
- .catch(() => {});
506
- throw err;
507
- }
466
+ .returning({ id: schema.calendarEvents.id });
467
+
468
+ if (!claimed.length) {
469
+ // Someone else claimed it first — re-read and return the winner.
470
+ const [winnerEvent] = await tx
471
+ .select({ meetingId: schema.calendarEvents.meetingId })
472
+ .from(schema.calendarEvents)
473
+ .where(eq(schema.calendarEvents.id, snapshot.id))
474
+ .limit(1);
475
+ if (winnerEvent?.meetingId) {
476
+ const [winnerMeeting] = await tx
477
+ .select()
478
+ .from(schema.meetings)
479
+ .where(eq(schema.meetings.id, winnerEvent.meetingId))
480
+ .limit(1);
481
+ if (winnerMeeting) {
482
+ return { meeting: winnerMeeting, created: false };
483
+ }
484
+ }
485
+ return null;
486
+ }
508
487
 
509
- const [meeting] = await db
510
- .select()
511
- .from(schema.meetings)
512
- .where(eq(schema.meetings.id, meetingId))
513
- .limit(1);
488
+ try {
489
+ await tx.insert(schema.meetings).values({
490
+ id: meetingId,
491
+ organizationId: orgId ?? live.account.orgId ?? null,
492
+ title: live.event.summary || "Untitled meeting",
493
+ scheduledStart: eventStartIso(live.event),
494
+ scheduledEnd: eventEndIso(live.event),
495
+ actualStart: null,
496
+ actualEnd: null,
497
+ platform: detectPlatform(joinUrl),
498
+ joinUrl: joinUrl ?? null,
499
+ calendarEventId: snapshot.id,
500
+ recordingId: null,
501
+ transcriptStatus: "idle",
502
+ summaryMd: "",
503
+ bulletsJson: "[]",
504
+ actionItemsJson: "[]",
505
+ source: "calendar",
506
+ reminderFiredAt: null,
507
+ createdAt: nowIso,
508
+ updatedAt: nowIso,
509
+ ownerEmail,
510
+ orgId,
511
+ visibility: "private",
512
+ } as any);
513
+
514
+ const participants = calendarEventParticipants(live.event).filter(
515
+ (p) => p.email,
516
+ );
517
+ if (participants.length) {
518
+ await tx.insert(schema.meetingParticipants).values(
519
+ participants.map((p) => ({
520
+ id: nanoid(),
521
+ meetingId,
522
+ email: p.email,
523
+ name: p.name ?? null,
524
+ isOrganizer: !!p.isOrganizer,
525
+ attendedAt: null,
526
+ createdAt: nowIso,
527
+ })) as any,
528
+ );
529
+ }
530
+ } catch (err) {
531
+ // Roll back the claim so a future call can retry — but only if it still
532
+ // points at our own meetingId (don't clobber a legitimate later claim).
533
+ await tx
534
+ .update(schema.calendarEvents)
535
+ .set({ meetingId: null, updatedAt: new Date().toISOString() })
536
+ .where(
537
+ and(
538
+ eq(schema.calendarEvents.id, snapshot.id),
539
+ eq(schema.calendarEvents.meetingId, meetingId),
540
+ ),
541
+ )
542
+ .catch(() => {});
543
+ throw err;
544
+ }
514
545
 
515
- return { meeting, created: true };
546
+ const [meeting] = await tx
547
+ .select()
548
+ .from(schema.meetings)
549
+ .where(eq(schema.meetings.id, meetingId))
550
+ .limit(1);
551
+
552
+ return { meeting, created: true };
553
+ });
516
554
  }
@@ -0,0 +1,35 @@
1
+ export type RecordingPageAccessRole = "owner" | "admin" | "editor" | "viewer";
2
+
3
+ /**
4
+ * Match the public recording and video routes: only a finite expiry date can
5
+ * expire a recording, and the expiry is strict so the exact instant remains
6
+ * valid until time advances past it.
7
+ */
8
+ export function isRecordingExpired(
9
+ expiresAt: string | null | undefined,
10
+ now = Date.now(),
11
+ ): boolean {
12
+ if (!expiresAt) return false;
13
+
14
+ const expires = new Date(expiresAt).getTime();
15
+ return Number.isFinite(expires) && expires < now;
16
+ }
17
+
18
+ /**
19
+ * Decide whether an authenticated request may use the editor/player route.
20
+ * Public visibility is intentionally a share-link concern; a direct `/r/*`
21
+ * request must either be the owner or have an explicit share grant.
22
+ * Password-protected recordings stay on the password-aware share flow for
23
+ * every non-owner so the authenticated action cannot mint a bypass token.
24
+ */
25
+ export function canOpenDirectRecordingPage(input: {
26
+ role: RecordingPageAccessRole;
27
+ visibility: "private" | "org" | "public";
28
+ hasPassword: boolean;
29
+ hasExplicitShare: boolean;
30
+ }): boolean {
31
+ if (input.role === "owner") return true;
32
+ if (input.hasPassword) return false;
33
+ if (input.visibility === "public") return input.hasExplicitShare;
34
+ return true;
35
+ }
@@ -110,12 +110,16 @@ export function sanitizeLocalhostSourceSnapshotHtml(html: string): string {
110
110
  );
111
111
  }
112
112
 
113
+ // Prototypes are still sandboxed, but user-initiated print/download controls
114
+ // need the browser permissions that make `window.print()` and download links
115
+ // work inside an iframe. Without these tokens the browser silently ignores
116
+ // the common "Download / Print PDF" pattern.
113
117
  const EXTERNAL_PREVIEW_IFRAME_SANDBOX =
114
- "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin";
118
+ "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads allow-modals allow-same-origin";
115
119
  const EDITABLE_INLINE_IFRAME_SANDBOX =
116
- "allow-scripts allow-popups allow-popups-to-escape-sandbox allow-same-origin";
120
+ "allow-scripts allow-popups allow-popups-to-escape-sandbox allow-downloads allow-modals allow-same-origin";
117
121
  const READ_ONLY_INLINE_IFRAME_SANDBOX =
118
- "allow-scripts allow-popups allow-popups-to-escape-sandbox";
122
+ "allow-scripts allow-popups allow-popups-to-escape-sandbox allow-downloads allow-modals";
119
123
 
120
124
  export function getDesignCanvasIframeSandbox(args: {
121
125
  externalPreview: boolean;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Prototype print and download buttons now work in preview
@@ -11,7 +11,7 @@ export default async function (args: string[]) {
11
11
  }
12
12
 
13
13
  const buf = fs.readFileSync(pdfPath);
14
- const pdf = new PDFParse(new Uint8Array(buf));
14
+ const pdf = new PDFParse({ data: new Uint8Array(buf) });
15
15
  const result = await pdf.getText();
16
16
  const pages = result.pages || [];
17
17
  console.log("Total pages:", pages.length);
@@ -214,7 +214,10 @@ export default defineAction({
214
214
  const { PDFParse } = await import("pdf-parse");
215
215
  const { convertSectionsToSlides } =
216
216
  await import("../server/handlers/import/html-converter.js");
217
- const pdf = new PDFParse(new Uint8Array(fileBuffer));
217
+ // pdf-parse v2 expects a LoadParameters object. Passing the byte array
218
+ // directly uses the old v1 shape and can fail while pdf.js initializes
219
+ // in production (the reported DOMMatrix error).
220
+ const pdf = new PDFParse({ data: new Uint8Array(fileBuffer) });
218
221
  const result = await pdf.getText();
219
222
  const pages = normalizePdfPages(result);
220
223
  const textPages = pages.filter((p) => p.text.trim());
@@ -69,7 +69,7 @@ export default function ImageGenPanel({
69
69
  const contextParts: string[] = [];
70
70
 
71
71
  contextParts.push(
72
- "Generate 3 image variations using our image generation action (`pnpm action generate-image`).",
72
+ "Generate 3 image variations by calling the registered `generate-image-api` action three times with the same prompt.",
73
73
  );
74
74
  contextParts.push(
75
75
  "The deliverables must be actual generated image assets from the action. Do not create placeholder HTML/CSS, oversized icon compositions, inline SVGs, or text-only mockups.",
@@ -1,4 +1,4 @@
1
- import { appBasePath, useT } from "@agent-native/core/client";
1
+ import { callAction, useT } from "@agent-native/core/client";
2
2
  import { IconX, IconSearch, IconLoader2 } from "@tabler/icons-react";
3
3
  import { useState, useEffect, useRef } from "react";
4
4
  import { createPortal } from "react-dom";
@@ -61,18 +61,15 @@ export default function ImageSearchPanel({
61
61
  setLoading(true);
62
62
  setError(null);
63
63
  try {
64
- const res = await fetch(
65
- `${appBasePath()}/api/image-search?q=${encodeURIComponent(query)}`,
64
+ const data = await callAction<SearchResult[]>(
65
+ "search-images",
66
+ { q: query.trim() },
67
+ { method: "GET" },
66
68
  );
67
- if (!res.ok) {
68
- const data = await res.json();
69
- setError(data.error || "Search failed");
70
- setResults([]);
71
- } else {
72
- setResults(await res.json());
73
- }
74
- } catch {
75
- setError("Search failed");
69
+ setResults(data);
70
+ } catch (error) {
71
+ setError(error instanceof Error ? error.message : t("raw.searchFailed"));
72
+ setResults([]);
76
73
  } finally {
77
74
  setLoading(false);
78
75
  }
@@ -1141,7 +1141,10 @@ export default function SlideEditor({
1141
1141
  const selector = getBuilderSelector(el);
1142
1142
  el.contentEditable = "true";
1143
1143
  el.setAttribute("data-editing-block", "true");
1144
- clearSelectedElement();
1144
+ // Keep the inspector selection mounted while text is being edited. The
1145
+ // inspector is a stable dock, so clearing it here would make the canvas
1146
+ // resize and auto-fit again on the second click.
1147
+ setSelectedElementRect(null);
1145
1148
  captureInlineEditDraft(slide.id);
1146
1149
  // Mark the deck dirty immediately so SSE/poll refreshes do not replace
1147
1150
  // the deck under an active contentEditable edit, even before the user
@@ -1167,13 +1170,7 @@ export default function SlideEditor({
1167
1170
  );
1168
1171
  }
1169
1172
  },
1170
- [
1171
- buildSelectionState,
1172
- captureInlineEditDraft,
1173
- clearSelectedElement,
1174
- onInlineEditStart,
1175
- slide.id,
1176
- ],
1173
+ [buildSelectionState, captureInlineEditDraft, onInlineEditStart, slide.id],
1177
1174
  );
1178
1175
 
1179
1176
  // Exit edit mode when switching slides — save pending content first so
@@ -2053,18 +2050,29 @@ export default function SlideEditor({
2053
2050
  )}
2054
2051
  </div>
2055
2052
 
2056
- {selectedStyleSnapshot && !readOnly && (
2057
- <div className="relative z-[70] hidden h-full w-[17rem] shrink-0 border-l border-border/70 bg-background/95 lg:block">
2058
- <SlideStyleInspector
2059
- snapshot={selectedStyleSnapshot}
2060
- designSystem={designSystem}
2061
- className="h-full w-full rounded-none border-0 bg-transparent shadow-none"
2062
- onChange={applySelectedStylePatch}
2063
- onClose={() => {
2064
- clearSelectedElement();
2065
- syncSelectionToAppState(null);
2066
- }}
2067
- />
2053
+ {!readOnly && (
2054
+ <div
2055
+ className="relative z-[70] hidden h-full w-[17rem] shrink-0 border-l border-border/70 bg-background/95 lg:block"
2056
+ data-slide-style-dock="true"
2057
+ >
2058
+ {selectedStyleSnapshot ? (
2059
+ <SlideStyleInspector
2060
+ snapshot={selectedStyleSnapshot}
2061
+ designSystem={designSystem}
2062
+ className="h-full w-full rounded-none border-0 bg-transparent shadow-none"
2063
+ onChange={applySelectedStylePatch}
2064
+ onClose={() => {
2065
+ clearSelectedElement();
2066
+ syncSelectionToAppState(null);
2067
+ }}
2068
+ />
2069
+ ) : (
2070
+ <div className="flex h-11 items-center border-b border-border/70 px-3">
2071
+ <span className="text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground/70">
2072
+ {t("styleInspector.title")}
2073
+ </span>
2074
+ </div>
2075
+ )}
2068
2076
  </div>
2069
2077
  )}
2070
2078
  </div>
@@ -2082,7 +2090,7 @@ export default function SlideEditor({
2082
2090
  viewportRect={selectionViewportRect}
2083
2091
  />
2084
2092
  )}
2085
- {selectedElementRect && (
2093
+ {selectedElementRect && !editingEl && (
2086
2094
  <ElementSelectionOutline
2087
2095
  rect={selectedElementRect}
2088
2096
  viewportRect={selectionViewportRect}
@@ -103,6 +103,7 @@ const messages = {
103
103
  searchImagesPlaceholder: "Buscar imagens...",
104
104
  searchForLogosImagesIcons: "Buscar logos, imagens, ícones...",
105
105
  search: "بحث",
106
+ searchFailed: "فشل البحث",
106
107
  logoSearchTitle: "بحث عن الشعار",
107
108
  searchCompanyLogo: "Busque uma empresa para encontrar seu logo",
108
109
  searchCompanyPlaceholder: "Buscar nome da empresa (ex.: Intuit)",
@@ -106,6 +106,7 @@ const messages = {
106
106
  searchImagesPlaceholder: "Nach Bildern suchen...",
107
107
  searchForLogosImagesIcons: "Nach Logos, Bildern, Icons suchen...",
108
108
  search: "Suchen",
109
+ searchFailed: "Suche fehlgeschlagen",
109
110
  logoSearchTitle: "Logo-Suche",
110
111
  searchCompanyLogo: "Suche nach einem Unternehmen, um sein Logo zu finden",
111
112
  searchCompanyPlaceholder: "Unternehmensname suchen (z. B. Intuit)",
@@ -104,6 +104,7 @@ const messages = {
104
104
  searchImagesPlaceholder: "Search for images...",
105
105
  searchForLogosImagesIcons: "Search for logos, images, icons...",
106
106
  search: "Search",
107
+ searchFailed: "Search failed",
107
108
  logoSearchTitle: "Logo Search",
108
109
  searchCompanyLogo: "Search for a company to find their logo",
109
110
  searchCompanyPlaceholder: "Search company name (e.g. Intuit)",
@@ -105,6 +105,7 @@ const messages = {
105
105
  searchImagesPlaceholder: "Buscar imágenes...",
106
106
  searchForLogosImagesIcons: "Buscar logos, imágenes, iconos...",
107
107
  search: "Buscar",
108
+ searchFailed: "Error al buscar",
108
109
  logoSearchTitle: "Búsqueda de logos",
109
110
  searchCompanyLogo: "Busca una empresa para encontrar su logo",
110
111
  searchCompanyPlaceholder: "Buscar nombre de empresa (p. ej. Intuit)",
@@ -106,6 +106,7 @@ const messages = {
106
106
  searchImagesPlaceholder: "Rechercher des images...",
107
107
  searchForLogosImagesIcons: "Rechercher des logos, images, icônes...",
108
108
  search: "Rechercher",
109
+ searchFailed: "Échec de la recherche",
109
110
  logoSearchTitle: "Recherche de logo",
110
111
  searchCompanyLogo: "Recherchez une entreprise pour trouver son logo",
111
112
  searchCompanyPlaceholder: "Rechercher un nom d’entreprise (ex. Intuit)",
@@ -103,6 +103,7 @@ const messages = {
103
103
  searchImagesPlaceholder: "Buscar imagens...",
104
104
  searchForLogosImagesIcons: "Buscar logos, imagens, ícones...",
105
105
  search: "खोजें",
106
+ searchFailed: "खोज विफल",
106
107
  logoSearchTitle: "लोगो खोज",
107
108
  searchCompanyLogo: "Busque uma empresa para encontrar seu logo",
108
109
  searchCompanyPlaceholder: "Buscar nome da empresa (ex.: Intuit)",
@@ -104,6 +104,7 @@ const messages = {
104
104
  searchImagesPlaceholder: "画像を検索...",
105
105
  searchForLogosImagesIcons: "ロゴ、画像、アイコンを検索...",
106
106
  search: "検索",
107
+ searchFailed: "検索に失敗しました",
107
108
  logoSearchTitle: "ロゴ検索",
108
109
  searchCompanyLogo: "会社を検索してロゴを見つける",
109
110
  searchCompanyPlaceholder: "会社名を検索(例: Intuit)",
@@ -104,6 +104,7 @@ const messages = {
104
104
  searchImagesPlaceholder: "画像を検索...",
105
105
  searchForLogosImagesIcons: "ロゴ、画像、アイコンを検索...",
106
106
  search: "검색",
107
+ searchFailed: "검색 실패",
107
108
  logoSearchTitle: "로고 검색",
108
109
  searchCompanyLogo: "会社を検索してロゴを見つける",
109
110
  searchCompanyPlaceholder: "会社名を検索(例: Intuit)",
@@ -104,6 +104,7 @@ const messages = {
104
104
  searchImagesPlaceholder: "Buscar imagens...",
105
105
  searchForLogosImagesIcons: "Buscar logos, imagens, ícones...",
106
106
  search: "Buscar",
107
+ searchFailed: "Falha na pesquisa",
107
108
  logoSearchTitle: "Busca de logo",
108
109
  searchCompanyLogo: "Busque uma empresa para encontrar seu logo",
109
110
  searchCompanyPlaceholder: "Buscar nome da empresa (ex.: Intuit)",
@@ -102,6 +102,7 @@ const messages = {
102
102
  searchImagesPlaceholder: "画像を検索...",
103
103
  searchForLogosImagesIcons: "ロゴ、画像、アイコンを検索...",
104
104
  search: "搜索",
105
+ searchFailed: "搜索失败",
105
106
  logoSearchTitle: "徽标搜索",
106
107
  searchCompanyLogo: "会社を検索してロゴを見つける",
107
108
  searchCompanyPlaceholder: "会社名を検索(例: Intuit)",
@@ -100,6 +100,7 @@ const messages = {
100
100
  searchImagesPlaceholder: "搜尋圖片...",
101
101
  searchForLogosImagesIcons: "搜尋徽標、圖片、圖示...",
102
102
  search: "搜尋",
103
+ searchFailed: "搜尋失敗",
103
104
  logoSearchTitle: "徽標搜尋",
104
105
  searchCompanyLogo: "搜尋公司以尋找徽標",
105
106
  searchCompanyPlaceholder: "搜尋公司名稱(例如:Intuit)",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Image search and generation controls now use the registered Slides actions
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ PDF deck references can be imported for slide inspiration again
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ The slide Style inspector now stays in a stable dock while selecting and editing elements, so the canvas no longer jumps or changes zoom.
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}