@pitcher/js-api 1.29.0 → 1.31.0

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 (158) hide show
  1. package/js-api.esm.js +488 -56
  2. package/js-api.esm.js.map +1 -1
  3. package/js-api.umd.min.js +32 -11
  4. package/js-api.umd.min.js.map +1 -1
  5. package/lib/ai-tasks/__tests__/weekly-focus.spec.d.ts +1 -0
  6. package/lib/ai-tasks/weekly-focus.d.ts +241 -0
  7. package/lib/apps/browser/appTypes.d.ts +28 -0
  8. package/lib/apps/browser/components/ContextMenu/TranslateFileButton.test.d.ts +1 -0
  9. package/lib/apps/browser/stores/api.d.ts +6 -1
  10. package/lib/apps/browser/stores/api.filesFoldersDeleter.test.d.ts +1 -0
  11. package/lib/apps/browser/stores/app.d.ts +5 -0
  12. package/lib/apps/browser/stores/app.selectionPruneScope.test.d.ts +1 -0
  13. package/lib/apps/browser/stores/upload.d.ts +26 -1
  14. package/lib/apps/browser/stores/upload.types.d.ts +9 -0
  15. package/lib/apps/browser/util/lifecycle.d.ts +57 -0
  16. package/lib/apps/browser/util/lifecycle.test.d.ts +1 -0
  17. package/lib/apps/canvas-builder/components/container/PopupApps/PopupAppModal.spec.d.ts +1 -0
  18. package/lib/apps/canvas-builder/components/container/PresentationTools/PresentationToolsButtons.spec.d.ts +1 -0
  19. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.integration.spec.d.ts +1 -0
  20. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.spec.d.ts +1 -0
  21. package/lib/apps/canvas-builder/components/ui/DynamicContent/section-component-bindings.util.d.ts +32 -0
  22. package/lib/apps/canvas-builder/components/ui/DynamicContent/useDynamicContent.d.ts +6 -0
  23. package/lib/apps/canvas-builder/components/ui/Link/Link.util.d.ts +8 -1
  24. package/lib/apps/canvas-builder/components/ui/Link/Link.util.test.d.ts +1 -0
  25. package/lib/apps/canvas-builder/components/ui/Multimedia/Multimedia.ldAsset.spec.d.ts +1 -0
  26. package/lib/apps/canvas-builder/components/ui/SectionList/SectionItemModal.spec.d.ts +1 -0
  27. package/lib/apps/canvas-builder/composables/useCanvas.d.ts +286 -10
  28. package/lib/apps/canvas-builder/composables/useCanvas.saveEcho.spec.d.ts +1 -0
  29. package/lib/apps/canvas-builder/composables/useCanvasBlocks.d.ts +40 -2
  30. package/lib/apps/canvas-builder/composables/useCanvasExit.d.ts +1 -0
  31. package/lib/apps/canvas-builder/composables/useCanvasHistory.d.ts +38 -2
  32. package/lib/apps/canvas-builder/composables/useCanvasTheme.d.ts +4 -2
  33. package/lib/apps/canvas-builder/composables/useContentSelector.d.ts +8 -1
  34. package/lib/apps/canvas-builder/composables/useInstalledEmbeddables.d.ts +1 -1
  35. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.d.ts +27 -0
  36. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.spec.d.ts +1 -0
  37. package/lib/apps/canvas-builder/composables/usePopupApps.d.ts +43 -4
  38. package/lib/apps/canvas-builder/composables/usePopupApps.spec.d.ts +1 -0
  39. package/lib/apps/canvas-builder/composables/usePresentationTools.d.ts +112 -0
  40. package/lib/apps/canvas-builder/composables/usePresentationTools.spec.d.ts +1 -0
  41. package/lib/apps/canvas-builder/types/canvas.d.ts +66 -3
  42. package/lib/apps/canvas-builder/util/canvas.util.d.ts +12 -0
  43. package/lib/apps/canvas-builder/util/completionWizard.util.d.ts +347 -0
  44. package/lib/apps/canvas-builder/util/completionWizard.util.test.d.ts +1 -0
  45. package/lib/apps/canvas-builder/util/fullscreenMode.util.d.ts +7 -0
  46. package/lib/apps/canvas-builder/util/fullscreenMode.util.test.d.ts +1 -0
  47. package/lib/apps/canvas-builder/util/iframe.util.d.ts +24 -2
  48. package/lib/apps/canvas-builder/util/iframe.util.test.d.ts +1 -0
  49. package/lib/apps/canvas-builder/util/lazySections.util.d.ts +35 -0
  50. package/lib/apps/canvas-builder/util/lazySections.util.test.d.ts +1 -0
  51. package/lib/apps/canvas-selector/stores/app.d.ts +14 -0
  52. package/lib/apps/collection-player/components/AppHeader.spec.d.ts +1 -0
  53. package/lib/apps/collection-player/composables/collection-navigation.util.d.ts +27 -0
  54. package/lib/apps/collection-player/composables/collection-navigation.util.spec.d.ts +1 -0
  55. package/lib/apps/collection-player/composables/speaker-notes.use.d.ts +14 -0
  56. package/lib/apps/collection-player/composables/speaker-notes.use.spec.d.ts +1 -0
  57. package/lib/apps/collection-player/stores/app.store.d.ts +8 -1
  58. package/lib/apps/collection-player/stores/showNotesToggle.spec.d.ts +1 -0
  59. package/lib/apps/content-selector/appTypes.d.ts +16 -0
  60. package/lib/apps/content-selector/components/Assets.uploaderRefresh.spec.d.ts +1 -0
  61. package/lib/apps/content-selector/components/Content/AllContent/List/expandFileGuard.spec.d.ts +1 -0
  62. package/lib/apps/content-selector/stores/app.d.ts +1 -1
  63. package/lib/apps/notes/NotesApp.accountNotes.spec.d.ts +1 -0
  64. package/lib/apps/notes/NotesApp.speakerNotes.spec.d.ts +1 -0
  65. package/lib/apps/notes/composables/useAccountNotes.d.ts +14 -0
  66. package/lib/apps/notes/composables/useAccountNotes.spec.d.ts +1 -0
  67. package/lib/apps/notes/composables/useAccountOnlyNotesGate.d.ts +21 -0
  68. package/lib/apps/notes/composables/useAccountOnlyNotesGate.spec.d.ts +1 -0
  69. package/lib/apps/notes/composables/useActiveSlideNotes.d.ts +42 -0
  70. package/lib/apps/notes/composables/useActiveSlideNotes.spec.d.ts +1 -0
  71. package/lib/components/CFileAccessManagement/collaborationApi.d.ts +2 -0
  72. package/lib/components/CFilePanel/Details.spec.d.ts +1 -0
  73. package/lib/components/CFilePanel/KeyMessages.spec.d.ts +1 -0
  74. package/lib/components/CFilePanel/Summary.spec.d.ts +1 -0
  75. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.annotations.use.d.ts +5 -1
  76. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.formFields.use.d.ts +8 -0
  77. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.link.use.d.ts +1 -1
  78. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.overlayItems.use.d.ts +1 -1
  79. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.use.d.ts +4 -9
  80. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.util.d.ts +53 -1
  81. package/lib/components/CFileViewer/pdf/CFileViewerFullscreen.pdf.use.d.ts +1 -1
  82. package/lib/components/CFileViewer/pdf/__tests__/CFileViewer.pdf.annotations.text.test.d.ts +1 -0
  83. package/lib/components/CGlobalLoader/CGlobalLoaderMark.spec.d.ts +1 -0
  84. package/lib/components/CGlobalLoader/globalLoader.paths.d.ts +2 -0
  85. package/lib/components/CGlobalSearch/globalSearchTarget.util.d.ts +31 -0
  86. package/lib/components/CGlobalSearch/globalSearchTarget.util.test.d.ts +1 -0
  87. package/lib/components/CRichTextEditor/extensions/paragraphExtended.d.ts +7 -1
  88. package/lib/components/CRichTextEditor/extensions/paragraphExtended.test.d.ts +1 -0
  89. package/lib/components/canvases/CanvasesManagementBulk.use.d.ts +12 -2
  90. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.d.ts +86 -0
  91. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.spec.d.ts +1 -0
  92. package/lib/components/masterCanvases/CMasterCanvasesPendingShareCell.spec.d.ts +1 -0
  93. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.d.ts +39 -0
  94. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.spec.d.ts +1 -0
  95. package/lib/components/masterCanvases/createFromMaster.use.d.ts +255 -0
  96. package/lib/components/masterCanvases/createFromMaster.use.spec.d.ts +1 -0
  97. package/lib/components/masterCanvases/masterCanvasDocuments.use.d.ts +56 -0
  98. package/lib/components/masterCanvases/masterCanvasDocuments.use.spec.d.ts +1 -0
  99. package/lib/components/masterCanvases/masterCanvasShares.use.d.ts +103 -0
  100. package/lib/components/masterCanvases/masterCanvasShares.use.spec.d.ts +1 -0
  101. package/lib/components/masterCanvases/masterFromCanvas.use.d.ts +122 -0
  102. package/lib/components/masterCanvases/masterFromCanvas.use.spec.d.ts +1 -0
  103. package/lib/components/masterCanvases/masterFromTemplate.use.d.ts +50 -0
  104. package/lib/components/masterCanvases/masterFromTemplate.use.spec.d.ts +1 -0
  105. package/lib/components/savedCanvases/CSavedCanvasesManagement.use.d.ts +204 -0
  106. package/lib/components/savedCanvases/savedCanvasDocuments.use.d.ts +111 -0
  107. package/lib/components/savedCanvases/savedCanvasDocuments.use.spec.d.ts +1 -0
  108. package/lib/components/savedCanvases/smartFolders/SmartFolders.use.d.ts +4 -0
  109. package/lib/composables/useCourseOnlyApps.d.ts +1 -1
  110. package/lib/composables/usePdfInterpolation.d.ts +2 -2
  111. package/lib/composables/useWindowEvents.d.ts +1 -1
  112. package/lib/constants/cdp.const.d.ts +2 -0
  113. package/lib/constants/translationLanguages.const.d.ts +150 -0
  114. package/lib/constants/translationLanguages.const.spec.d.ts +1 -0
  115. package/lib/main.lib.d.ts +7 -0
  116. package/lib/sdk/api/HighLevelApi.d.ts +19 -6
  117. package/lib/sdk/api/modules/ai.d.ts +43 -1
  118. package/lib/sdk/api/modules/ai.spec.d.ts +1 -0
  119. package/lib/sdk/api/modules/appsDb.d.ts +4 -4
  120. package/lib/sdk/api/modules/canvas.d.ts +20 -0
  121. package/lib/sdk/api/modules/ui/types.ui.d.ts +25 -0
  122. package/lib/sdk/interfaces.d.ts +31 -1
  123. package/lib/sdk/main.d.ts +46 -0
  124. package/lib/sdk/payload.types.d.ts +149 -0
  125. package/lib/sdk/platform.d.ts +27 -0
  126. package/lib/sdk/platform.spec.d.ts +1 -0
  127. package/lib/sdk/singleton-scope.spec.d.ts +1 -0
  128. package/lib/sdk/utils/httpFetch.spec.d.ts +1 -0
  129. package/lib/theme/canvasUiUnoPreset.test.d.ts +1 -0
  130. package/lib/types/ai-tasks.const.d.ts +39 -1
  131. package/lib/types/app.d.ts +55 -1
  132. package/lib/types/call.d.ts +14 -0
  133. package/lib/types/canvases.d.ts +15 -0
  134. package/lib/types/launchDarkly.types.d.ts +8 -3
  135. package/lib/types/organizationSettings.types.d.ts +39 -0
  136. package/lib/util/aiSummary.d.ts +30 -0
  137. package/lib/util/aiSummary.spec.d.ts +1 -0
  138. package/lib/util/network.d.ts +35 -0
  139. package/lib/util/user.d.ts +18 -0
  140. package/lib/util/user.test.d.ts +1 -0
  141. package/package.json +1 -1
  142. package/types/openapi/models/Canvas.d.ts +1 -0
  143. package/types/openapi/models/CanvasCreate.d.ts +1 -0
  144. package/types/openapi/models/CanvasCreateRequest.d.ts +1 -0
  145. package/types/openapi/models/CanvasRecommendedFile.d.ts +1 -1
  146. package/types/openapi/models/CanvasRetrieve.d.ts +1 -0
  147. package/types/openapi/models/CanvasUpdate.d.ts +1 -0
  148. package/types/openapi/models/CanvasUpdateRequest.d.ts +1 -0
  149. package/types/openapi/models/DeletedCanvas.d.ts +1 -0
  150. package/types/openapi/models/DeletedEnvironment.d.ts +0 -1
  151. package/types/openapi/models/Environment.d.ts +0 -1
  152. package/types/openapi/models/EnvironmentRequest.d.ts +0 -1
  153. package/types/openapi/models/File.d.ts +3 -1
  154. package/types/openapi/models/FileRetrieve.d.ts +2 -0
  155. package/types/openapi/models/PatchedCanvasUpdateRequest.d.ts +1 -0
  156. package/types/openapi/models/PatchedEnvironmentRequest.d.ts +0 -1
  157. package/types/openapi/models/SharedLink.d.ts +6 -0
  158. package/types/openapi/models/SharedLinkCreateRequest.d.ts +5 -0
package/js-api.esm.js CHANGED
@@ -2385,6 +2385,261 @@ function resolvePiaSearchMode(config) {
2385
2385
  return "off";
2386
2386
  }
2387
2387
 
2388
+ const WINDOW_DAYS = 6;
2389
+ const MAX_RANK_MEETINGS = 12;
2390
+ const HERO_MAX_CHARS = 400;
2391
+ const REASON_MAX_CHARS = 140;
2392
+ const DEFAULT_MAX_PICKS = 5;
2393
+ const TITLE_MAX_CHARS = 70;
2394
+ const ACCOUNT_NAME_MAX_CHARS = 60;
2395
+ const SECTION_LABEL_MAX_CHARS = 40;
2396
+ const FIELD_LABEL_MAX_CHARS = 30;
2397
+ const FIELD_VALUE_MAX_CHARS = 60;
2398
+ const WEEKLY_FOCUS_RANKING_RULES = `You rank a sales rep's upcoming meetings by how much they need preparation.
2399
+
2400
+ Below are {{meeting_count}} numbered meetings, each with its account's CRM context (deals, tasks, recent calls).
2401
+
2402
+ Pick the {{max_picks}} most important. Pick fewer only if the list has fewer meetings.
2403
+
2404
+ Rules:
2405
+ - Highest priority first; ties go to the earlier meeting.
2406
+ - Strongest signals: an overdue or due-soon high-priority task, a poorly rated recent interaction, a deal closing within days. Routine meetings on healthy accounts rank last.
2407
+ - {{account_rule}}
2408
+ - Each "reason": ONE sentence, max {{reason_max_chars}} characters, only facts from the data — name the deal, task, rating, or date that makes it matter.
2409
+ - "hero": 1-2 sentences, max {{hero_max_chars}} characters, summarizing the week in plain business language.
2410
+ - Never invent facts. Never repeat field names, codes, or IDs.`;
2411
+ const ONE_PER_ACCOUNT_RULE = "Pick at most ONE meeting per account: when an account has several meetings, pick only its most important one.";
2412
+ const MULTI_PER_ACCOUNT_RULE = "Prefer spreading picks across different accounts, but you may pick two meetings on the same account when each is genuinely high priority on its own.";
2413
+ function effectiveMaxPicks(maxPicks) {
2414
+ if (typeof maxPicks !== "number" || !Number.isFinite(maxPicks)) return DEFAULT_MAX_PICKS;
2415
+ return Math.min(8, Math.max(1, Math.floor(maxPicks)));
2416
+ }
2417
+ function clamp(value, max) {
2418
+ const trimmed = value.trim();
2419
+ return trimmed.length > max ? trimmed.slice(0, max - 1).trimEnd() + "…" : trimmed;
2420
+ }
2421
+ function fill(template2, tokens) {
2422
+ return template2.replace(
2423
+ /\{\{(\w+)\}\}/g,
2424
+ (match, key) => Object.prototype.hasOwnProperty.call(tokens, key) ? tokens[key] : match
2425
+ );
2426
+ }
2427
+ const DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
2428
+ function startOfDayUtcMs(date, timeZone) {
2429
+ if (!timeZone) return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
2430
+ const parts = new Intl.DateTimeFormat("en-US", {
2431
+ timeZone,
2432
+ year: "numeric",
2433
+ month: "2-digit",
2434
+ day: "2-digit"
2435
+ }).formatToParts(date);
2436
+ const get = (type) => Number(parts.find((p) => p.type === type)?.value);
2437
+ return Date.UTC(get("year"), get("month") - 1, get("day"));
2438
+ }
2439
+ function daysAgo(iso, options) {
2440
+ const now = options?.now ?? /* @__PURE__ */ new Date();
2441
+ const todayMs = startOfDayUtcMs(now, options?.timeZone);
2442
+ const dateOnly = DATE_ONLY.exec(iso);
2443
+ if (dateOnly) {
2444
+ const [y, m, d] = [+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]];
2445
+ const thenMs = Date.UTC(y, m, d);
2446
+ const back = new Date(thenMs);
2447
+ if (back.getUTCFullYear() !== y || back.getUTCMonth() !== m || back.getUTCDate() !== d) return null;
2448
+ return Math.round((todayMs - thenMs) / 864e5);
2449
+ }
2450
+ const then = new Date(iso);
2451
+ if (Number.isNaN(then.getTime())) return null;
2452
+ return Math.round((todayMs - startOfDayUtcMs(then, options?.timeZone)) / 864e5);
2453
+ }
2454
+ function weeklyWindowMeetings(meetings, options) {
2455
+ const now = options?.now ?? /* @__PURE__ */ new Date();
2456
+ const nowMs = now.getTime();
2457
+ return meetings.filter((meeting) => {
2458
+ const days = daysAgo(meeting.meeting_time, { now, timeZone: options?.timeZone });
2459
+ if (days === null) return false;
2460
+ if (!DATE_ONLY.test(meeting.meeting_time)) {
2461
+ const t = new Date(meeting.meeting_time).getTime();
2462
+ if (Number.isNaN(t) || t <= nowMs) return false;
2463
+ }
2464
+ const offset = -days;
2465
+ return offset >= 0 && offset <= WINDOW_DAYS;
2466
+ }).sort((a, b) => sortableTime(a.meeting_time) - sortableTime(b.meeting_time));
2467
+ }
2468
+ function sortableTime(iso) {
2469
+ const t = Date.parse(iso);
2470
+ return Number.isNaN(t) ? Number.POSITIVE_INFINITY : t;
2471
+ }
2472
+ function relativeDays(days) {
2473
+ if (days === 0) return "today";
2474
+ if (days === 1) return "yesterday";
2475
+ if (days < 0) return days === -1 ? "tomorrow" : `in ${-days} days`;
2476
+ return `${days} days ago`;
2477
+ }
2478
+ function formatWhen(iso, timeZone) {
2479
+ if (DATE_ONLY.test(iso)) return iso;
2480
+ const date = new Date(iso);
2481
+ if (Number.isNaN(date.getTime())) return iso;
2482
+ const day = date.toLocaleDateString("en-US", {
2483
+ weekday: "short",
2484
+ month: "short",
2485
+ day: "numeric",
2486
+ ...timeZone && { timeZone }
2487
+ });
2488
+ const time = date.toLocaleTimeString("en-US", {
2489
+ hour: "numeric",
2490
+ minute: "2-digit",
2491
+ ...timeZone && { timeZone }
2492
+ });
2493
+ return `${day} ${time}`.trim();
2494
+ }
2495
+ function meetingBlock(index, meeting, context, options) {
2496
+ const when = formatWhen(meeting.meeting_time, options.timeZone);
2497
+ const offset = -(daysAgo(meeting.meeting_time, options) ?? 0);
2498
+ const day = offset === 0 ? "today" : offset === 1 ? "tomorrow" : `in ${offset} days`;
2499
+ const attendees = meeting.attendee_count ?? 0;
2500
+ const head = `${index}. "${clamp(meeting.meeting_subject, TITLE_MAX_CHARS)}" — ${clamp(meeting.account_name, ACCOUNT_NAME_MAX_CHARS)} — ${when} (${day})` + (attendees > 0 ? ` — ${attendees} attendee${attendees === 1 ? "" : "s"}` : "");
2501
+ const lines = [head];
2502
+ for (const section of context?.sections ?? []) {
2503
+ if (section.items.length === 0) continue;
2504
+ const first = section.items[0];
2505
+ const fieldList = first.fields ?? [];
2506
+ const fields = section.fields_curated && fieldList.length > 0 ? " · " + fieldList.slice(0, 3).map((f) => `${clamp(f.label, FIELD_LABEL_MAX_CHARS)}: ${clamp(f.value, FIELD_VALUE_MAX_CHARS)}`).join(" · ") : "";
2507
+ const age = first.days_ago != null ? ` (${relativeDays(first.days_ago)})` : "";
2508
+ const count = section.items.length > 1 ? `${section.items.length} records; key: ` : "";
2509
+ lines.push(
2510
+ ` ${clamp(section.label, SECTION_LABEL_MAX_CHARS)}: ${count}${clamp(first.title, TITLE_MAX_CHARS)}${fields}${age}`
2511
+ );
2512
+ }
2513
+ return lines.join("\n");
2514
+ }
2515
+ function template(variables) {
2516
+ const meetings = variables.meetings;
2517
+ const context = variables.context ?? {};
2518
+ const maxPicks = effectiveMaxPicks(variables.max_picks);
2519
+ const onePerAccount = variables.one_per_account !== false;
2520
+ const options = { now: variables.now, timeZone: variables.time_zone };
2521
+ const blocks = meetings.map((m, i) => meetingBlock(i + 1, m, context[m.account_id], options)).join("\n");
2522
+ const rules = fill(variables.ranking_rules || WEEKLY_FOCUS_RANKING_RULES, {
2523
+ meeting_count: String(meetings.length),
2524
+ max_picks: String(maxPicks),
2525
+ reason_max_chars: String(REASON_MAX_CHARS),
2526
+ hero_max_chars: String(HERO_MAX_CHARS),
2527
+ account_rule: onePerAccount ? ONE_PER_ACCOUNT_RULE : MULTI_PER_ACCOUNT_RULE
2528
+ });
2529
+ return `${rules}
2530
+
2531
+ Answer with JSON ONLY — no other text. The object has exactly two keys:
2532
+ "hero": the summary as one string.
2533
+ "top": an array with one entry per picked meeting, highest priority first. Each entry is an object with "m" (the picked meeting's number from the list below, as an integer) and "reason" (one sentence as a string).
2534
+
2535
+ MEETINGS:
2536
+ ${blocks}`;
2537
+ }
2538
+ function tryParse(slice) {
2539
+ try {
2540
+ return JSON.parse(slice);
2541
+ } catch {
2542
+ const repaired = slice.replace(/[“”]/g, '"').replace(/[‘’]/g, "'").replace(/,\s*([}\]])/g, "$1");
2543
+ try {
2544
+ return JSON.parse(repaired);
2545
+ } catch {
2546
+ return null;
2547
+ }
2548
+ }
2549
+ }
2550
+ function looksLikeResponse(o) {
2551
+ return Array.isArray(o.top);
2552
+ }
2553
+ function extractJson(raw) {
2554
+ let fallback = null;
2555
+ for (let start = raw.indexOf("{"); start !== -1; start = raw.indexOf("{", start + 1)) {
2556
+ let depth = 0;
2557
+ let inString = false;
2558
+ let escaped = false;
2559
+ for (let i = start; i < raw.length; i++) {
2560
+ const ch = raw[i];
2561
+ if (inString) {
2562
+ if (escaped) escaped = false;
2563
+ else if (ch === "\\") escaped = true;
2564
+ else if (ch === '"') inString = false;
2565
+ } else if (ch === '"') {
2566
+ inString = true;
2567
+ } else if (ch === "{") {
2568
+ depth += 1;
2569
+ } else if (ch === "}") {
2570
+ depth -= 1;
2571
+ if (depth === 0) {
2572
+ const parsed = tryParse(raw.slice(start, i + 1));
2573
+ if (parsed) {
2574
+ if (looksLikeResponse(parsed)) return parsed;
2575
+ if (!fallback) fallback = parsed;
2576
+ }
2577
+ break;
2578
+ }
2579
+ }
2580
+ }
2581
+ }
2582
+ return fallback;
2583
+ }
2584
+ function normalizeWeeklyFocus(parsed) {
2585
+ const raw = parsed ?? {};
2586
+ const top = [];
2587
+ if (Array.isArray(raw.top)) {
2588
+ for (const pick of raw.top) {
2589
+ const m = typeof pick?.m === "number" ? pick.m : Number(pick?.m);
2590
+ const reason = typeof pick?.reason === "string" ? pick.reason.trim() : "";
2591
+ if (!Number.isInteger(m) || !reason) continue;
2592
+ top.push({ m, reason: clamp(reason, REASON_MAX_CHARS) });
2593
+ }
2594
+ }
2595
+ const hero = typeof raw.hero === "string" ? clamp(raw.hero, HERO_MAX_CHARS) : "";
2596
+ return { hero, top };
2597
+ }
2598
+ function extractWeeklyFocus(rawText) {
2599
+ const parsed = extractJson(rawText ?? "");
2600
+ if (!parsed) return { hero: "", top: [] };
2601
+ return normalizeWeeklyFocus(parsed);
2602
+ }
2603
+ function resolveWeeklyFocusPicks(output, rankedMeetings, options = {}) {
2604
+ const maxPicks = effectiveMaxPicks(options.maxPicks);
2605
+ const onePerAccount = options.onePerAccount !== false;
2606
+ const windowCount = options.windowCount ?? rankedMeetings.length;
2607
+ const seen = /* @__PURE__ */ new Set();
2608
+ const pickedAccounts = /* @__PURE__ */ new Set();
2609
+ const top = [];
2610
+ let dropped = 0;
2611
+ for (const pick of output.top ?? []) {
2612
+ const meeting = Number.isInteger(pick.m) ? rankedMeetings[pick.m - 1] : void 0;
2613
+ const reason = typeof pick.reason === "string" ? pick.reason.trim() : "";
2614
+ if (!meeting || !reason || seen.has(meeting.event_id)) {
2615
+ dropped += 1;
2616
+ continue;
2617
+ }
2618
+ if (onePerAccount && pickedAccounts.has(meeting.account_id)) {
2619
+ dropped += 1;
2620
+ continue;
2621
+ }
2622
+ seen.add(meeting.event_id);
2623
+ pickedAccounts.add(meeting.account_id);
2624
+ top.push({ event_id: meeting.event_id, rank: top.length + 1, reason: clamp(reason, REASON_MAX_CHARS) });
2625
+ if (top.length >= maxPicks) break;
2626
+ }
2627
+ return { top, collapsed_count: Math.max(0, windowCount - top.length), dropped };
2628
+ }
2629
+ function weeklyFocusTarget(rankedMeetings, options = {}) {
2630
+ const onePerAccount = options.onePerAccount !== false;
2631
+ const ceiling = onePerAccount ? new Set(rankedMeetings.map((m) => m.account_id)).size : rankedMeetings.length;
2632
+ return Math.min(effectiveMaxPicks(options.maxPicks), ceiling);
2633
+ }
2634
+ function prepareWeeklyFocusMeetings(meetings, options) {
2635
+ const windowMeetings = weeklyWindowMeetings(meetings, options);
2636
+ return {
2637
+ windowMeetings,
2638
+ rankedMeetings: windowMeetings.slice(0, MAX_RANK_MEETINGS),
2639
+ windowCount: windowMeetings.length
2640
+ };
2641
+ }
2642
+
2388
2643
  const PIA_SEARCH_ROUTE = "/core/api/protected/pia-prepare/pia-search";
2389
2644
  const CAPABILITIES_TIMEOUT_MS = 3e3;
2390
2645
  const ON_DEVICE_MAX_TOKENS = 512;
@@ -2419,6 +2674,32 @@ function apiOriginFromEnv(env) {
2419
2674
  if (typeof orgDomain === "string" && orgDomain.length > 0) return normalizeOrigin(orgDomain);
2420
2675
  throw new Error("piaSearchAnswer: no customer domain found in env (token_claims / organization metadata)");
2421
2676
  }
2677
+ async function postJsonWithTimeout(url, body, accessToken, timeoutMs, label) {
2678
+ const controller = new AbortController();
2679
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
2680
+ try {
2681
+ const response = await fetch(url, {
2682
+ method: "POST",
2683
+ signal: controller.signal,
2684
+ headers: {
2685
+ "Content-Type": "application/json",
2686
+ Authorization: `Bearer ${accessToken}`
2687
+ },
2688
+ body: JSON.stringify(body)
2689
+ });
2690
+ if (!response.ok) {
2691
+ throw new Error(`${label} ${response.status}`);
2692
+ }
2693
+ return await response.json();
2694
+ } catch (error) {
2695
+ if (error?.name === "AbortError") {
2696
+ throw new Error(`${label} online request timed out after ${timeoutMs}ms`);
2697
+ }
2698
+ throw error;
2699
+ } finally {
2700
+ clearTimeout(timer);
2701
+ }
2702
+ }
2422
2703
  function buildOnDevicePrompt(query, contextText) {
2423
2704
  const context = typeof contextText === "string" && contextText.trim().length > 0 ? contextText.trim() : "No content context was provided.";
2424
2705
  return `You are PIA, a sales content assistant. Answer the rep's question using ONLY the CONTEXT below — do not invent content that is not in it.
@@ -2428,7 +2709,7 @@ ${context}
2428
2709
 
2429
2710
  QUESTION: ${query}
2430
2711
 
2431
- Answer concisely in plain text. If the context does not contain the answer, say you could not find it in the available content.`;
2712
+ Answer concisely in plain text. If the context does not contain the answer, say you could not find it in the available content. Refer to content by its name only — do not include any file ids or codes in your answer.`;
2432
2713
  }
2433
2714
  async function aiGetCapabilities() {
2434
2715
  const env = await highLevelApi.API.request("get_env");
@@ -2443,6 +2724,17 @@ function aiComplete(payload) {
2443
2724
  }
2444
2725
  return highLevelApi.API.request("ai.complete", payload);
2445
2726
  }
2727
+ function asCitations(value) {
2728
+ if (!Array.isArray(value)) return void 0;
2729
+ const citations = value.flatMap((entry) => {
2730
+ if (!entry || typeof entry !== "object") return [];
2731
+ const { file_id: fileId, page_indices: pageIndices } = entry;
2732
+ if (typeof fileId !== "string" || fileId === "" || !Array.isArray(pageIndices)) return [];
2733
+ const pages = pageIndices.filter((page) => Number.isInteger(page) && page >= 0);
2734
+ return pages.length > 0 ? [{ file_id: fileId, page_indices: pages }] : [];
2735
+ });
2736
+ return citations.length > 0 ? citations : void 0;
2737
+ }
2446
2738
  async function piaSearchAnswer(payload) {
2447
2739
  if (!payload || typeof payload.query !== "string" || payload.query.trim() === "") {
2448
2740
  return Promise.reject(new Error("query is required and must be a non-empty string"));
@@ -2474,41 +2766,152 @@ async function piaSearchAnswer(payload) {
2474
2766
  if (!instanceId) {
2475
2767
  throw new Error("piaSearchAnswer: instance_id could not be resolved from the payload or env");
2476
2768
  }
2477
- const controller = new AbortController();
2478
- const timer = setTimeout(() => controller.abort(), ONLINE_TIMEOUT_MS);
2479
- try {
2480
- const response = await fetch(`${apiOriginFromEnv(env)}${PIA_SEARCH_ROUTE}`, {
2481
- method: "POST",
2482
- signal: controller.signal,
2483
- headers: {
2484
- "Content-Type": "application/json",
2485
- Authorization: `Bearer ${env.pitcher.access_token}`
2486
- },
2487
- body: JSON.stringify({
2488
- query: payload.query,
2489
- instance_id: instanceId,
2490
- ...Array.isArray(payload.file_ids) && payload.file_ids.length > 0 && { file_ids: payload.file_ids }
2491
- })
2492
- });
2493
- if (!response.ok) {
2494
- throw new Error(`pia_search ${response.status}`);
2495
- }
2496
- const data = await response.json();
2497
- const output = data?.pia_search ?? {};
2498
- return {
2499
- answer: typeof output.answer === "string" ? output.answer : "",
2500
- cited_file_ids: Array.isArray(output.cited_file_ids) ? output.cited_file_ids : [],
2501
- ...output.confidence && { confidence: output.confidence },
2502
- source: "online"
2503
- };
2504
- } catch (error) {
2505
- if (error?.name === "AbortError") {
2506
- throw new Error(`pia_search online request timed out after ${ONLINE_TIMEOUT_MS}ms`);
2769
+ const data = await postJsonWithTimeout(
2770
+ `${apiOriginFromEnv(env)}${PIA_SEARCH_ROUTE}`,
2771
+ {
2772
+ query: payload.query,
2773
+ instance_id: instanceId,
2774
+ ...Array.isArray(payload.file_ids) && payload.file_ids.length > 0 && { file_ids: payload.file_ids },
2775
+ ...payload.include_document_text === true && { include_document_text: true },
2776
+ ...Array.isArray(payload.expansion_terms) && payload.expansion_terms.length > 0 && { expansion_terms: payload.expansion_terms }
2777
+ },
2778
+ env.pitcher.access_token,
2779
+ ONLINE_TIMEOUT_MS,
2780
+ "pia_search"
2781
+ );
2782
+ const output = data?.pia_search ?? {};
2783
+ const citations = asCitations(output.citations);
2784
+ return {
2785
+ answer: typeof output.answer === "string" ? output.answer : "",
2786
+ cited_file_ids: Array.isArray(output.cited_file_ids) ? output.cited_file_ids : [],
2787
+ ...citations && { citations },
2788
+ ...output.confidence && { confidence: output.confidence },
2789
+ source: "online"
2790
+ };
2791
+ }
2792
+ const WEEKLY_FOCUS_ROUTE = "/core/api/protected/pia-prepare/weekly-focus";
2793
+ const weeklyFocusOutputReserve = (maxPicks) => 220 + 60 * maxPicks;
2794
+ const ON_DEVICE_COMPLETE_TIMEOUT_MS = 12e4;
2795
+ async function weeklyFocusRank(payload) {
2796
+ if (!payload || !Array.isArray(payload.meetings)) {
2797
+ return Promise.reject(new Error("meetings is required and must be an array"));
2798
+ }
2799
+ const env = await highLevelApi.API.request("get_env");
2800
+ const timeZone = payload.time_zone || Intl.DateTimeFormat().resolvedOptions().timeZone;
2801
+ const { windowMeetings, rankedMeetings, windowCount } = prepareWeeklyFocusMeetings(payload.meetings, { timeZone });
2802
+ if (rankedMeetings.length === 0) {
2803
+ return { hero: "", top: [], collapsed_count: 0, source: env?.mode === "IOS" ? "on_device" : "online" };
2804
+ }
2805
+ const maxPicks = effectiveMaxPicks(payload.max_picks);
2806
+ const resolveOptions = {
2807
+ maxPicks,
2808
+ onePerAccount: payload.one_per_account,
2809
+ windowCount
2810
+ };
2811
+ if (env?.mode === "IOS") {
2812
+ try {
2813
+ const capabilities = await withTimeout(
2814
+ highLevelApi.API.request("ai.get_capabilities"),
2815
+ CAPABILITIES_TIMEOUT_MS,
2816
+ "ai.get_capabilities"
2817
+ );
2818
+ if (capabilities?.available) {
2819
+ const prompt = template({
2820
+ meetings: rankedMeetings,
2821
+ context: payload.context,
2822
+ max_picks: maxPicks,
2823
+ one_per_account: payload.one_per_account,
2824
+ time_zone: timeZone
2825
+ });
2826
+ const runOnce = async () => {
2827
+ const completion = await withTimeout(
2828
+ aiComplete({ prompt, max_tokens: weeklyFocusOutputReserve(maxPicks) }),
2829
+ ON_DEVICE_COMPLETE_TIMEOUT_MS,
2830
+ "ai.complete"
2831
+ );
2832
+ const parsed2 = extractWeeklyFocus(completion.text);
2833
+ return { parsed: parsed2, resolved: resolveWeeklyFocusPicks(parsed2, rankedMeetings, resolveOptions) };
2834
+ };
2835
+ let attempt = await runOnce();
2836
+ if (attempt.resolved.top.length < weeklyFocusTarget(rankedMeetings, resolveOptions)) {
2837
+ try {
2838
+ const second = await runOnce();
2839
+ if (second.resolved.top.length > attempt.resolved.top.length) attempt = second;
2840
+ } catch (error) {
2841
+ console.warn("[weeklyFocusRank] on-device retry failed, keeping the first attempt:", error);
2842
+ }
2843
+ }
2844
+ const { parsed, resolved } = attempt;
2845
+ if (resolved.top.length > 0 || parsed.hero) {
2846
+ return {
2847
+ hero: parsed.hero,
2848
+ top: resolved.top,
2849
+ collapsed_count: resolved.collapsed_count,
2850
+ source: "on_device"
2851
+ };
2852
+ }
2853
+ }
2854
+ } catch (error) {
2855
+ console.warn("[weeklyFocusRank] on-device path unavailable, falling back to online:", error);
2507
2856
  }
2508
- throw error;
2509
- } finally {
2510
- clearTimeout(timer);
2511
2857
  }
2858
+ const instanceId = payload.instance_id || env?.pitcher?.instance?.id;
2859
+ if (!instanceId) {
2860
+ throw new Error("weeklyFocusRank: instance_id could not be resolved from the payload or env");
2861
+ }
2862
+ const data = await postJsonWithTimeout(
2863
+ `${apiOriginFromEnv(env)}${WEEKLY_FOCUS_ROUTE}`,
2864
+ {
2865
+ instance_id: instanceId,
2866
+ // Send the WINDOW, not the caller's whole calendar. The route re-windows
2867
+ // anyway (idempotent — same rule, same zone), so this only drops meetings
2868
+ // it would have dropped, while keeping `collapsed_count` correct: the route
2869
+ // derives the window size from what it receives, so sending the
2870
+ // already-capped 12 would understate it. It also keeps a caller with a long
2871
+ // history from tripping the route's 500-meeting body cap over meetings
2872
+ // outside the week entirely.
2873
+ meetings: windowMeetings,
2874
+ time_zone: timeZone,
2875
+ ...payload.context && { context: payload.context },
2876
+ // Clamped, not raw: the route 400s on out-of-range values.
2877
+ ...payload.max_picks !== void 0 && { max_picks: maxPicks },
2878
+ ...payload.one_per_account !== void 0 && { one_per_account: payload.one_per_account }
2879
+ },
2880
+ env.pitcher.access_token,
2881
+ ONLINE_TIMEOUT_MS,
2882
+ "weekly_focus"
2883
+ );
2884
+ const output = data?.weekly_focus ?? {};
2885
+ return {
2886
+ hero: typeof output.hero === "string" ? output.hero : "",
2887
+ top: Array.isArray(output.top) ? output.top : [],
2888
+ collapsed_count: typeof output.collapsed_count === "number" ? output.collapsed_count : 0,
2889
+ source: "online"
2890
+ };
2891
+ }
2892
+
2893
+ const PLATFORM_TYPE = {
2894
+ web: "web",
2895
+ ios: "ios",
2896
+ android: "android",
2897
+ windows: "windows",
2898
+ macos: "macos"
2899
+ };
2900
+
2901
+ const WEB_MODE = "WEB";
2902
+ function isNativeHost(mode) {
2903
+ return typeof mode === "string" && mode !== "" && mode !== WEB_MODE;
2904
+ }
2905
+ const PLATFORM_TYPE_BY_MODE = {
2906
+ WEB: PLATFORM_TYPE.web,
2907
+ IOS: PLATFORM_TYPE.ios,
2908
+ MACOS: PLATFORM_TYPE.macos,
2909
+ WINDOWS: PLATFORM_TYPE.windows,
2910
+ ANDROID: PLATFORM_TYPE.android
2911
+ };
2912
+ function platformTypeForMode(mode) {
2913
+ if (!mode) return void 0;
2914
+ return Object.prototype.hasOwnProperty.call(PLATFORM_TYPE_BY_MODE, mode) ? PLATFORM_TYPE_BY_MODE[mode] : void 0;
2512
2915
  }
2513
2916
 
2514
2917
  const APPS_DB_BASE_PATH = "/core/api/protected/appsdb";
@@ -2519,7 +2922,7 @@ async function fetchAppsDbContext() {
2519
2922
  let origin = claimsDomain || metadataDomain || "";
2520
2923
  if (origin && !origin.startsWith("http")) origin = `https://${origin}`;
2521
2924
  return {
2522
- isIos: (env?.mode ?? env?.pitcher?.mode) === "IOS",
2925
+ isNative: isNativeHost(env?.mode ?? env?.pitcher?.mode),
2523
2926
  origin,
2524
2927
  accessToken: env?.pitcher?.access_token ?? "",
2525
2928
  instanceId: env?.pitcher?.instance?.id
@@ -2658,7 +3061,7 @@ async function appsDbGetEntries(payload) {
2658
3061
  return Promise.reject(new Error("type is required and must be a non-empty string"));
2659
3062
  }
2660
3063
  const ctx = await getAppsDbContext();
2661
- if (ctx.isIos) {
3064
+ if (ctx.isNative) {
2662
3065
  try {
2663
3066
  return await highLevelApi.API.request("appsdb_get_entries", payload);
2664
3067
  } catch (error) {
@@ -2675,7 +3078,7 @@ async function appsDbUpsertEntry(payload) {
2675
3078
  return Promise.reject(new Error("type is required when creating an entry (no id provided)"));
2676
3079
  }
2677
3080
  const ctx = await getAppsDbContext();
2678
- if (ctx.isIos) {
3081
+ if (ctx.isNative) {
2679
3082
  try {
2680
3083
  return await highLevelApi.API.request("appsdb_upsert_entry", payload);
2681
3084
  } catch (error) {
@@ -2692,7 +3095,7 @@ async function appsDbDeleteEntry(payload) {
2692
3095
  return Promise.reject(new Error("id is required and must be a non-empty string"));
2693
3096
  }
2694
3097
  const ctx = await getAppsDbContext();
2695
- if (ctx.isIos) {
3098
+ if (ctx.isNative) {
2696
3099
  try {
2697
3100
  return await highLevelApi.API.request("appsdb_delete_entry", payload);
2698
3101
  } catch (error) {
@@ -2735,7 +3138,7 @@ async function appsDbPsql(payload) {
2735
3138
  return Promise.reject(new Error("query is required and must be a non-empty string"));
2736
3139
  }
2737
3140
  const ctx = await getAppsDbContext();
2738
- if (ctx.isIos) {
3141
+ if (ctx.isNative) {
2739
3142
  const parsed = parseSimplePsql(payload.query);
2740
3143
  let mirrorUnavailable = false;
2741
3144
  if (parsed && await isDeviceOffline()) {
@@ -3871,6 +4274,7 @@ const modules = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
3871
4274
  openWebViewAlwaysOnTop,
3872
4275
  patchCoreFolder,
3873
4276
  piaSearchAnswer,
4277
+ postJsonWithTimeout,
3874
4278
  query,
3875
4279
  refreshAccessToken,
3876
4280
  refreshServiceToken,
@@ -3898,7 +4302,8 @@ const modules = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
3898
4302
  updateCanvasIndicators,
3899
4303
  updateFile,
3900
4304
  updateFolder,
3901
- updateMyUser
4305
+ updateMyUser,
4306
+ weeklyFocusRank
3902
4307
  }, Symbol.toStringTag, { value: 'Module' }));
3903
4308
 
3904
4309
  class EventEmitter {
@@ -4177,24 +4582,32 @@ function paramsSerializer(params) {
4177
4582
  }
4178
4583
  return searchParams.toString();
4179
4584
  }
4585
+ function isNonRetryableStatus(status) {
4586
+ if (typeof status !== "number") return false;
4587
+ if (status >= 200 && status < 300) return true;
4588
+ return status >= 400 && status < 500;
4589
+ }
4180
4590
  async function fetchWithRetry(url, options, remainingRetries = MAX_RETRIES) {
4181
4591
  try {
4182
4592
  const response = await fetch(url, options);
4183
4593
  if (!response.ok) {
4184
- if (response.status === 401) {
4594
+ if (response.status === 401 && remainingRetries > 0) {
4185
4595
  const newToken = await refreshToken();
4186
4596
  options.headers = options.headers || {};
4187
4597
  options.headers.Authorization = `Bearer ${newToken}`;
4188
- return fetchWithRetry(url, options, remainingRetries);
4598
+ return fetchWithRetry(url, options, remainingRetries - 1);
4189
4599
  } else if (response.status >= 500 && response.status < 600 && remainingRetries > 0) {
4190
4600
  const delay = BASE_DELAY * Math.pow(2, MAX_RETRIES - remainingRetries);
4191
4601
  await new Promise((resolve) => setTimeout(resolve, delay));
4192
4602
  return fetchWithRetry(url, options, remainingRetries - 1);
4193
4603
  } else {
4194
- const errorData = await response.json();
4195
- const error = new Error(
4196
- `HTTP error! status: ${response.status}, message: ${errorData.message || response.statusText}`
4197
- );
4604
+ const raw = await response.text().catch(() => "");
4605
+ let message = response.statusText;
4606
+ try {
4607
+ message = JSON.parse(raw)?.message || response.statusText;
4608
+ } catch {
4609
+ }
4610
+ const error = new Error(`HTTP error! status: ${response.status}, message: ${message}`);
4198
4611
  error.status = response.status;
4199
4612
  throw error;
4200
4613
  }
@@ -4202,9 +4615,23 @@ async function fetchWithRetry(url, options, remainingRetries = MAX_RETRIES) {
4202
4615
  if (response.status === 204 || response.status === 205) {
4203
4616
  return;
4204
4617
  }
4205
- return response.json();
4618
+ const body = await response.text();
4619
+ if (!body) {
4620
+ const error = new Error(
4621
+ `Empty response body for status ${response.status} (expected JSON)`
4622
+ );
4623
+ error.status = response.status;
4624
+ throw error;
4625
+ }
4626
+ try {
4627
+ return JSON.parse(body);
4628
+ } catch (parseError) {
4629
+ ;
4630
+ parseError.status = response.status;
4631
+ throw parseError;
4632
+ }
4206
4633
  } catch (error) {
4207
- if (remainingRetries > 0 && !(error instanceof TypeError) && error.status !== 404) {
4634
+ if (remainingRetries > 0 && !(error instanceof TypeError) && !isNonRetryableStatus(error.status)) {
4208
4635
  const delay = BASE_DELAY * Math.pow(2, MAX_RETRIES - remainingRetries);
4209
4636
  await new Promise((resolve) => setTimeout(resolve, delay));
4210
4637
  return fetchWithRetry(url, options, remainingRetries - 1);
@@ -4380,16 +4807,17 @@ const onlineRestApiHandlers = {
4380
4807
  },
4381
4808
  update_canvas: async (params) => {
4382
4809
  check();
4383
- const { id, fields, ...canvasData } = params;
4810
+ const { id, fields, lazy_sections, ...canvasData } = params;
4811
+ const lazyQs = lazy_sections === true ? "lazy_sections=true" : "";
4384
4812
  const useCoreEndpoint = env?.launch_darkly?.enable_canvas_core_patch === true;
4385
4813
  if (useCoreEndpoint) {
4386
4814
  const origin = env.pitcher.token_claims["https://pitcher.com/claims/urls"].custom_domain;
4387
- const fieldsQs = fields ? `?fields=${encodeURIComponent(fields)}` : "";
4388
- const url = `${origin}/core/api/protected/v1/canvases/${id}${fieldsQs}`;
4815
+ const qs = [fields ? `fields=${encodeURIComponent(fields)}` : "", lazyQs].filter(Boolean).join("&");
4816
+ const url = `${origin}/core/api/protected/v1/canvases/${id}${qs ? `?${qs}` : ""}`;
4389
4817
  const res2 = await http.patchUrl(url, canvasData);
4390
4818
  return res2;
4391
4819
  }
4392
- const res = await http.patch(`/canvases/${id}`, { fields, ...canvasData });
4820
+ const res = await http.patch(`/canvases/${id}${lazyQs ? `?${lazyQs}` : ""}`, { fields, ...canvasData });
4393
4821
  return res;
4394
4822
  },
4395
4823
  delete_canvas: async (params) => {
@@ -4405,7 +4833,8 @@ const onlineRestApiHandlers = {
4405
4833
  } catch (e) {
4406
4834
  if (e?.status === 404) {
4407
4835
  link = await http.post("/shared-links", {
4408
- canvas_id: params.id
4836
+ canvas_id: params.id,
4837
+ ...params.brand_id ? { brand_id: params.brand_id } : {}
4409
4838
  });
4410
4839
  } else {
4411
4840
  throw e;
@@ -5500,12 +5929,15 @@ async function sendPeerConnectivityEvent(payload, options) {
5500
5929
  let highLevelApi;
5501
5930
  let prevOptions;
5502
5931
  function usePitcherApi(options) {
5503
- if (!highLevelApi || !isEqual(options, prevOptions)) {
5932
+ if (!highLevelApi || options !== void 0 && !isEqual(options, prevOptions)) {
5504
5933
  highLevelApi = createHighLevelApi(options);
5505
- prevOptions = options;
5934
+ prevOptions = options === void 0 ? void 0 : { ...options };
5506
5935
  }
5507
5936
  return highLevelApi;
5508
5937
  }
5938
+ function createScopedPitcherApi(options) {
5939
+ return createHighLevelApi({ ...prevOptions, ...options });
5940
+ }
5509
5941
  function enhanceWithSnakeCase(api) {
5510
5942
  Object.entries(api).forEach(([key, value]) => {
5511
5943
  const newKey = snakeCase(key);
@@ -5553,5 +5985,5 @@ function useApi(options) {
5553
5985
 
5554
5986
  window.postRobot = pr;
5555
5987
 
5556
- export { ADMIN_API_METHOD_TYPES, ADMIN_API_TYPES, ADMIN_MESSAGE, ADMIN_MESSAGE_TYPES, DEFAULT_PEER_CONNECTIVITY_VERSION, DSR_API_METHOD_TYPES, DSR_API_TYPES, DSR_MESSAGE, DSR_MESSAGE_TYPES, PEER_CONNECTIVITY_EVENT, PEER_CONNECTIVITY_HANDLER_MATCH_ALL, PITCHER_EVENT, PeerConnectivityActions, PitcherBroadcastedEventName, PitcherEventName, PitcherExternalEventName, PitcherMessageType, PitcherResponseStatus, UI_API_METHOD_TYPES, UI_MESSAGE, UI_MESSAGE_TYPES, UI_NATIVE_MESSAGE_TYPES, getAvailableApis, highLevelApi, registerPeerConnectivityHandler, sendPeerConnectivityEvent, useAdmin, useApi, useDsr, usePitcherApi, useUi };
5988
+ export { ADMIN_API_METHOD_TYPES, ADMIN_API_TYPES, ADMIN_MESSAGE, ADMIN_MESSAGE_TYPES, DEFAULT_PEER_CONNECTIVITY_VERSION, DSR_API_METHOD_TYPES, DSR_API_TYPES, DSR_MESSAGE, DSR_MESSAGE_TYPES, PEER_CONNECTIVITY_EVENT, PEER_CONNECTIVITY_HANDLER_MATCH_ALL, PITCHER_EVENT, PeerConnectivityActions, PitcherBroadcastedEventName, PitcherEventName, PitcherExternalEventName, PitcherMessageType, PitcherResponseStatus, UI_API_METHOD_TYPES, UI_MESSAGE, UI_MESSAGE_TYPES, UI_NATIVE_MESSAGE_TYPES, WEB_MODE, createScopedPitcherApi, getAvailableApis, highLevelApi, isNativeHost, platformTypeForMode, registerPeerConnectivityHandler, sendPeerConnectivityEvent, useAdmin, useApi, useDsr, usePitcherApi, useUi };
5557
5989
  //# sourceMappingURL=js-api.esm.js.map