@wix/himalaya-cli 0.1377.0 → 0.1379.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 (178) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/app-info/src/index.d.ts +4 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ecom/src/extensions.d.ts +113 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/app-info.mjs +2 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +2 -1
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +2 -1
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ecom.mjs +77 -0
  7. package/dist/cli.mjs +24 -23
  8. package/dist/preview-assets.generated.bin +0 -0
  9. package/guides/importable-sdks.md +1 -1
  10. package/guides/index.json +6 -0
  11. package/guides/sdk-reference.json +128 -2
  12. package/guides/wix-api-usage.md +7 -5
  13. package/guides/wix-pro-gallery.md +145 -0
  14. package/package.json +2 -2
  15. package/templates/beauty-salon/config.ts +23 -0
  16. package/templates/beauty-salon/dev/index.ts +2611 -1
  17. package/templates/beauty-salon/himalaya.content.json +9 -0
  18. package/templates/beauty-salon/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  19. package/templates/beauty-salon/tier5-src/_shared/member-access.ts +14 -0
  20. package/templates/beauty-salon/tier5-src/_shared/member-account-routes.ts +43 -0
  21. package/templates/beauty-salon/tier5-src/_shared/member-address.ts +129 -0
  22. package/templates/beauty-salon/tier5-src/_shared/saved-card.ts +20 -0
  23. package/templates/beauty-salon/tier5-src/himi-branded-lite-address/index.ts +223 -0
  24. package/templates/beauty-salon/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  25. package/templates/beauty-salon/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  26. package/templates/beauty-salon/tier5-src/himi-store-account/index.ts +17 -0
  27. package/templates/beauty-salon-owner/dev/index.ts +5 -27
  28. package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +99 -40
  29. package/templates/beauty-salon-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  30. package/templates/beauty-salon-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  31. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  32. package/templates/branded-lite/config.ts +23 -0
  33. package/templates/branded-lite/dev/index.ts +2614 -2
  34. package/templates/branded-lite/himalaya.content.json +9 -0
  35. package/templates/branded-lite/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  36. package/templates/branded-lite/tier5-src/_shared/member-access.ts +14 -0
  37. package/templates/branded-lite/tier5-src/_shared/member-account-routes.ts +43 -0
  38. package/templates/branded-lite/tier5-src/_shared/member-address.ts +129 -0
  39. package/templates/branded-lite/tier5-src/_shared/saved-card.ts +20 -0
  40. package/templates/branded-lite/tier5-src/himi-branded-lite-address/index.ts +223 -0
  41. package/templates/branded-lite/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  42. package/templates/branded-lite/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  43. package/templates/branded-lite/tier5-src/himi-store-account/index.ts +17 -0
  44. package/templates/community-club/dev/index.ts +3 -1
  45. package/templates/community-club/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  46. package/templates/community-club/tier5-src/_shared/member-access.ts +14 -0
  47. package/templates/community-club/tier5-src/_shared/member-account-routes.ts +43 -0
  48. package/templates/community-club/tier5-src/himi-store-account/index.ts +17 -0
  49. package/templates/community-club-owner/dev/index.ts +5 -27
  50. package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +99 -40
  51. package/templates/community-club-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  52. package/templates/community-club-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  53. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  54. package/templates/events-meetups/dev/index.ts +3 -1
  55. package/templates/events-meetups/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  56. package/templates/events-meetups/tier5-src/_shared/member-access.ts +14 -0
  57. package/templates/events-meetups/tier5-src/_shared/member-account-routes.ts +43 -0
  58. package/templates/events-meetups/tier5-src/himi-store-account/index.ts +17 -0
  59. package/templates/events-meetups-owner/dev/index.ts +5 -27
  60. package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +99 -40
  61. package/templates/events-meetups-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  62. package/templates/events-meetups-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  63. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  64. package/templates/gym-fitness/config.ts +23 -0
  65. package/templates/gym-fitness/dev/index.ts +2611 -1
  66. package/templates/gym-fitness/himalaya.content.json +9 -0
  67. package/templates/gym-fitness/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  68. package/templates/gym-fitness/tier5-src/_shared/member-access.ts +14 -0
  69. package/templates/gym-fitness/tier5-src/_shared/member-account-routes.ts +43 -0
  70. package/templates/gym-fitness/tier5-src/_shared/member-address.ts +129 -0
  71. package/templates/gym-fitness/tier5-src/_shared/saved-card.ts +20 -0
  72. package/templates/gym-fitness/tier5-src/himi-branded-lite-address/index.ts +223 -0
  73. package/templates/gym-fitness/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  74. package/templates/gym-fitness/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  75. package/templates/gym-fitness/tier5-src/himi-store-account/index.ts +17 -0
  76. package/templates/gym-fitness-owner/dev/index.ts +5 -27
  77. package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +99 -40
  78. package/templates/gym-fitness-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  79. package/templates/gym-fitness-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  80. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  81. package/templates/nonprofit-cause/config.ts +7 -0
  82. package/templates/nonprofit-cause/dev/index.ts +762 -1
  83. package/templates/nonprofit-cause/himalaya.content.json +3 -0
  84. package/templates/nonprofit-cause/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  85. package/templates/nonprofit-cause/tier5-src/_shared/member-access.ts +14 -0
  86. package/templates/nonprofit-cause/tier5-src/_shared/member-account-routes.ts +43 -0
  87. package/templates/nonprofit-cause/tier5-src/_shared/saved-card.ts +20 -0
  88. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  89. package/templates/nonprofit-cause/tier5-src/himi-store-account/index.ts +17 -0
  90. package/templates/nonprofit-cause-owner/dev/index.ts +5 -27
  91. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +99 -40
  92. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  93. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  94. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  95. package/templates/owner-lite/dev/index.ts +5 -27
  96. package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +99 -40
  97. package/templates/owner-lite/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  98. package/templates/owner-lite/tier5-src/_shared/aria-widget-view.ts +6 -0
  99. package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  100. package/templates/podcast-creator/config.ts +7 -0
  101. package/templates/podcast-creator/dev/index.ts +762 -1
  102. package/templates/podcast-creator/himalaya.content.json +3 -0
  103. package/templates/podcast-creator/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  104. package/templates/podcast-creator/tier5-src/_shared/member-access.ts +14 -0
  105. package/templates/podcast-creator/tier5-src/_shared/member-account-routes.ts +43 -0
  106. package/templates/podcast-creator/tier5-src/_shared/saved-card.ts +20 -0
  107. package/templates/podcast-creator/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  108. package/templates/podcast-creator/tier5-src/himi-store-account/index.ts +17 -0
  109. package/templates/podcast-creator-owner/dev/index.ts +5 -27
  110. package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +99 -40
  111. package/templates/podcast-creator-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  112. package/templates/podcast-creator-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  113. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  114. package/templates/portfolio-creative/config.ts +23 -0
  115. package/templates/portfolio-creative/dev/index.ts +2611 -1
  116. package/templates/portfolio-creative/himalaya.content.json +9 -0
  117. package/templates/portfolio-creative/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  118. package/templates/portfolio-creative/tier5-src/_shared/member-access.ts +14 -0
  119. package/templates/portfolio-creative/tier5-src/_shared/member-account-routes.ts +43 -0
  120. package/templates/portfolio-creative/tier5-src/_shared/member-address.ts +129 -0
  121. package/templates/portfolio-creative/tier5-src/_shared/saved-card.ts +20 -0
  122. package/templates/portfolio-creative/tier5-src/himi-branded-lite-address/index.ts +223 -0
  123. package/templates/portfolio-creative/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  124. package/templates/portfolio-creative/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  125. package/templates/portfolio-creative/tier5-src/himi-store-account/index.ts +17 -0
  126. package/templates/portfolio-creative-owner/dev/index.ts +5 -27
  127. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +99 -40
  128. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  129. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  130. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  131. package/templates/restaurant/config.ts +23 -0
  132. package/templates/restaurant/dev/index.ts +2611 -1
  133. package/templates/restaurant/himalaya.content.json +9 -0
  134. package/templates/restaurant/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  135. package/templates/restaurant/tier5-src/_shared/member-access.ts +14 -0
  136. package/templates/restaurant/tier5-src/_shared/member-account-routes.ts +43 -0
  137. package/templates/restaurant/tier5-src/_shared/member-address.ts +129 -0
  138. package/templates/restaurant/tier5-src/_shared/saved-card.ts +20 -0
  139. package/templates/restaurant/tier5-src/himi-branded-lite-address/index.ts +223 -0
  140. package/templates/restaurant/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  141. package/templates/restaurant/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  142. package/templates/restaurant/tier5-src/himi-store-account/index.ts +17 -0
  143. package/templates/restaurant-owner/dev/index.ts +5 -27
  144. package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +99 -40
  145. package/templates/restaurant-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  146. package/templates/restaurant-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  147. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  148. package/templates/retail-store/config.ts +23 -0
  149. package/templates/retail-store/dev/index.ts +2611 -1
  150. package/templates/retail-store/himalaya.content.json +9 -0
  151. package/templates/retail-store/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  152. package/templates/retail-store/tier5-src/_shared/member-access.ts +14 -0
  153. package/templates/retail-store/tier5-src/_shared/member-account-routes.ts +43 -0
  154. package/templates/retail-store/tier5-src/_shared/member-address.ts +129 -0
  155. package/templates/retail-store/tier5-src/_shared/saved-card.ts +20 -0
  156. package/templates/retail-store/tier5-src/himi-branded-lite-address/index.ts +223 -0
  157. package/templates/retail-store/tier5-src/himi-branded-lite-addresses/index.ts +202 -0
  158. package/templates/retail-store/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  159. package/templates/retail-store/tier5-src/himi-store-account/index.ts +17 -0
  160. package/templates/retail-store-owner/dev/index.ts +5 -27
  161. package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +99 -40
  162. package/templates/retail-store-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  163. package/templates/retail-store-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  164. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
  165. package/templates/yoga-studio/config.ts +7 -0
  166. package/templates/yoga-studio/dev/index.ts +762 -1
  167. package/templates/yoga-studio/himalaya.content.json +3 -0
  168. package/templates/yoga-studio/tier5-src/_shared/branded-lite-hosted.ts +3 -0
  169. package/templates/yoga-studio/tier5-src/_shared/member-access.ts +14 -0
  170. package/templates/yoga-studio/tier5-src/_shared/member-account-routes.ts +43 -0
  171. package/templates/yoga-studio/tier5-src/_shared/saved-card.ts +20 -0
  172. package/templates/yoga-studio/tier5-src/himi-branded-lite-wallet/index.ts +217 -0
  173. package/templates/yoga-studio/tier5-src/himi-store-account/index.ts +17 -0
  174. package/templates/yoga-studio-owner/dev/index.ts +5 -27
  175. package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +99 -40
  176. package/templates/yoga-studio-owner/tier5-src/_shared/aria-widget-oauth.ts +42 -0
  177. package/templates/yoga-studio-owner/tier5-src/_shared/aria-widget-view.ts +6 -0
  178. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +12 -1
@@ -88,6 +88,7 @@ import {
88
88
  type WidgetOptionRow,
89
89
  type WidgetView,
90
90
  } from "./aria-widget-view.js";
91
+ import { oauthView, DEFAULT_OAUTH_COPY, OAUTH_AUTHORIZED_NOTE, OAUTH_DECLINED_NOTE, type OAuthCopy } from "./aria-widget-oauth.js";
91
92
  import { substituteSelection } from "./aria-widget-model.js";
92
93
  import { MENTION_PAGE_SIZE, allowlisted, emptyMentionModel, mentionView,
93
94
  type MentionItemRow, type MentionLabels, type MentionModel, type MentionProvider, type MentionView } from "./aria-mentions.js";
@@ -468,6 +469,7 @@ export interface AriaChatLabels {
468
469
  mentionItemsFailed?: (category: string) => string;
469
470
  /** Shown when a response widget's item provider cannot be queried. */
470
471
  widgetItemsFailed?: Resolvable<string>;
472
+ oauth?: Partial<Record<keyof OAuthCopy, Resolvable<string>>>;
471
473
  /** Shown when this host cannot reach Wix's item provider service. */
472
474
  widgetItemsUnavailable?: Resolvable<string>;
473
475
  /** Attachment copy — see `AriaChatOptions.attachments`. Chip states: */
@@ -994,13 +996,23 @@ function withAttachments(content: string, names: readonly string[]): { content:
994
996
  return { content, attachText, attachHidden: !attachText };
995
997
  }
996
998
 
999
+ /** Only OAuth protocol suffixes are hidden in owner replies. Ordinary owner text
1000
+ * stays literal; apply this to optimistic rows and their later server echoes. */
1001
+ function visibleOwnerReply(content: string): string {
1002
+ for (const note of [OAUTH_AUTHORIZED_NOTE, OAUTH_DECLINED_NOTE]) {
1003
+ const suffix = `<HIDDEN>${note}</HIDDEN>`;
1004
+ if (content.endsWith(suffix)) return content.slice(0, -suffix.length).trimEnd();
1005
+ }
1006
+ return content;
1007
+ }
1008
+
997
1009
  /** A greeting or optimistic bubble: no links, all slots defaulted. `attached`
998
1010
  * names the files an optimistic USER bubble is being sent with, and `refs` is
999
1011
  * its mention line, already formatted. */
1000
1012
  export function plainBubble(
1001
1013
  id: string, role: string, who: string, content: string, attached: readonly string[] = [], refs = "",
1002
1014
  ): AriaBubble {
1003
- const a = withAttachments(content, attached);
1015
+ const a = withAttachments(role === "USER" ? visibleOwnerReply(content) : content, attached);
1004
1016
  return { id, role, who, notUser: role !== "USER", notAria: role === "USER", spoken: spokenOf(who, a.content),
1005
1017
  refs, refsHidden: !refs, ...linkFieldsOf("", role), ...a };
1006
1018
  }
@@ -1086,7 +1098,7 @@ function bubbleOf(
1086
1098
  // A row the service is still writing is scanned as STREAMING: an
1087
1099
  // envelope whose `>>` has not arrived yet is held back rather than
1088
1100
  // painted as raw JSON until the row finishes.
1089
- const prose = role === "USER" ? raw : assistantProse(raw, !writing);
1101
+ const prose = role === "USER" ? visibleOwnerReply(raw) : assistantProse(raw, !writing);
1090
1102
  const content = role === "USER" ? prose : stripMarkdown(prose);
1091
1103
  // A turn that is only attachments still happened, and dropping it would hide
1092
1104
  // what the owner sent: `withAttachments` makes the file line its content.
@@ -1512,7 +1524,7 @@ export interface AriaChatCore {
1512
1524
  * region is `$service:`-bound and has no item, and the worker already holds
1513
1525
  * the value anyway — so the descriptor names the action and nothing else,
1514
1526
  * which is also one less place for a model-supplied url to travel through. */
1515
- widgetPrimary(s: AriaChatState): Promise<AriaChatState>;
1527
+ widgetPrimary(s: AriaChatState): Promise<AriaChatState | undefined>;
1516
1528
  widgetSecondary(s: AriaChatState): Promise<AriaChatState>;
1517
1529
  /** Toggle one option of a MULTI_SELECT-style widget. Synchronous: it is a
1518
1530
  * state edit, and making it async would put a turn boundary where there is
@@ -1651,6 +1663,16 @@ export function createAriaChat(o: AriaChatOptions): AriaChatCore {
1651
1663
  o.labels?.dictationEmpty ?? "Didn't catch that. Check microphone access and try again.",
1652
1664
  );
1653
1665
  const dictationFailedText = () => res(o.labels?.dictationFailed ?? "Dictation isn't available right now.");
1666
+ const oauthCopy = (): OAuthCopy => Object.fromEntries(
1667
+ Object.entries(DEFAULT_OAUTH_COPY).map(([key, fallback]) =>
1668
+ [key, res(o.labels?.oauth?.[key as keyof OAuthCopy] ?? fallback)]),
1669
+ ) as unknown as OAuthCopy;
1670
+ let oauthKey = "";
1671
+ let oauthSeq = 0;
1672
+ /** The identity of the OAuth ask on screen: its message and its URL. */
1673
+ const oauthKeyOf = (w: WidgetView): string => w.kind === "OAUTH_REQUIRED"
1674
+ ? `${w.sourceMessageId ?? ""}\0${w.oauthAuthorizationUrl ?? ""}` : "";
1675
+ let oauthOpening = "";
1654
1676
  const widgetItemsFailedText = () => res(o.labels?.widgetItemsFailed ?? "Couldn't load these items.");
1655
1677
  const widgetItemsUnavailableText = () => res(o.labels?.widgetItemsUnavailable ?? "Items aren't available here.");
1656
1678
  const attachUploadingText = () => res(o.labels?.attachUploading ?? "Uploading…");
@@ -2522,6 +2544,10 @@ export function createAriaChat(o: AriaChatOptions): AriaChatCore {
2522
2544
  // transcript row itself is unchanged.
2523
2545
  if (!next.sourceMessageId || prev.sourceMessageId !== next.sourceMessageId) return next;
2524
2546
  if (prev.kind !== next.kind) return next;
2547
+ if (next.kind === "OAUTH_REQUIRED" && prev.oauthAuthorizationUrl === next.oauthAuthorizationUrl) {
2548
+ return { ...oauthView(next, next.oauthAuthorizationUrl ?? "", disclosedLabel, oauthCopy(), prev.oauthPhase),
2549
+ notice: prev.notice, noticeHidden: prev.noticeHidden };
2550
+ }
2525
2551
  // Keep the latest service status while this exact job and transcript row
2526
2552
  // remain visible. Rebuilding from the envelope must not restart a terminal
2527
2553
  // job or replace progress with its initial status message.
@@ -2634,36 +2660,43 @@ export function createAriaChat(o: AriaChatOptions): AriaChatCore {
2634
2660
  const localized = (w: WidgetView): WidgetView =>
2635
2661
  w.kind === "QUESTIONNAIRE"
2636
2662
  ? questionnaireSynced(w, w.questionIndex, questionnaireCopy(), !w.answersTextHidden)
2637
- : w;
2638
-
2639
- const observed = (msgs: ConversationMessage[], prev?: WidgetView) => ({
2640
- _srvUsers: countTurns(msgs, "USER"),
2641
- _srvAssistants: countTurns(msgs, "ASSISTANT"),
2642
- // Derived HERE, with the counts, because this is the one expression every
2643
- // transcript rebuild already spreads — load, resume, tick and both newChat
2644
- // arms. That is what makes the widget impossible to leave stale: a rebuild
2645
- // that forgot to clear it would also have to have forgotten the counts,
2646
- // which the reply-detection depends on. `observed([])` (new chat) yields
2647
- // NO_WIDGET for free.
2648
- // Content is normalized HERE, not in the view: `messageText` decodes the
2649
- // `{ text: … }` shape the service also sends (treated as empty before,
2650
- // so those widgets never appeared at all), and `stripHidden` removes
2651
- // `<HIDDEN>` spans — which are transcript-only, and were promoting hidden
2652
- // envelopes into live interactive cards. The transcript path already did
2653
- // both; the widget path did neither.
2654
- widget: carrySelection(
2655
- localized(activeWidgetOf(
2656
- // A draft offers no controls: the agent has not finished asking, and
2657
- // an answer tapped now would start a second turn on top of this one.
2658
- // An empty newest row is NO_WIDGET — the placeholder rule.
2659
- msgs.map((m) => ({ id: m.id, role: m.role, content: stillWriting(m) ? "" : stripHidden(messageText(m)) })),
2660
- disclosedLabel,
2661
- o.subtree,
2662
- (url) => isWixMediaHost(hostOf(url)),
2663
- )),
2664
- prev,
2665
- ),
2666
- });
2663
+ : w.kind === "OAUTH_REQUIRED"
2664
+ ? oauthView(w, w.oauthAuthorizationUrl ?? "", disclosedLabel, oauthCopy(), w.oauthPhase)
2665
+ : w;
2666
+
2667
+ const observed = (msgs: ConversationMessage[], prev?: WidgetView) => {
2668
+ const result = {
2669
+ _srvUsers: countTurns(msgs, "USER"),
2670
+ _srvAssistants: countTurns(msgs, "ASSISTANT"),
2671
+ // Derived HERE, with the counts, because this is the one expression every
2672
+ // transcript rebuild already spreads — load, resume, tick and both newChat
2673
+ // arms. That is what makes the widget impossible to leave stale: a rebuild
2674
+ // that forgot to clear it would also have to have forgotten the counts,
2675
+ // which the reply-detection depends on. `observed([])` (new chat) yields
2676
+ // NO_WIDGET for free.
2677
+ // Content is normalized HERE, not in the view: `messageText` decodes the
2678
+ // `{ text: … }` shape the service also sends (treated as empty before,
2679
+ // so those widgets never appeared at all), and `stripHidden` removes
2680
+ // `<HIDDEN>` spans — which are transcript-only, and were promoting hidden
2681
+ // envelopes into live interactive cards. The transcript path already did
2682
+ // both; the widget path did neither.
2683
+ widget: carrySelection(
2684
+ localized(activeWidgetOf(
2685
+ // A draft offers no controls: the agent has not finished asking, and
2686
+ // an answer tapped now would start a second turn on top of this one.
2687
+ // An empty newest row is NO_WIDGET — the placeholder rule.
2688
+ msgs.map((m) => ({ id: m.id, role: m.role, content: stillWriting(m) ? "" : stripHidden(messageText(m)) })),
2689
+ disclosedLabel,
2690
+ o.subtree,
2691
+ (url) => isWixMediaHost(hostOf(url)),
2692
+ )),
2693
+ prev,
2694
+ ),
2695
+ };
2696
+ const key = oauthKeyOf(result.widget);
2697
+ if (key !== oauthKey) { oauthKey = key; oauthSeq++; }
2698
+ return result;
2699
+ };
2667
2700
 
2668
2701
  const greetingOnly = (): AriaBubble[] => [plainBubble(GREETING_ID, "ASSISTANT", assistant(), res(o.greeting))];
2669
2702
 
@@ -4028,12 +4061,38 @@ export function createAriaChat(o: AriaChatOptions): AriaChatCore {
4028
4061
  // The url wins when both are present: a button that names a destination
4029
4062
  // should go there, and `respondText` beside it is the fallback the
4030
4063
  // service sends for clients that cannot open one.
4031
- widgetPrimary: (s) => s.widget.primaryUrl
4032
- ? openWidgetUrl(s, s.widget.primaryUrl)
4033
- : impl.widgetRespond(s, { value: "primary" }),
4034
- widgetSecondary: (s) => s.widget.secondaryUrl
4035
- ? openWidgetUrl(s, s.widget.secondaryUrl)
4036
- : impl.widgetRespond(s, { value: "secondary" }),
4064
+ widgetPrimary: async (s) => {
4065
+ const w = s.widget;
4066
+ if (w.kind !== "OAUTH_REQUIRED") return w.primaryUrl
4067
+ ? openWidgetUrl(s, w.primaryUrl) : impl.widgetRespond(s, { value: "primary" });
4068
+ if (w.primaryHidden || !w.oauthAuthorizationUrl || s._pending) return s;
4069
+ if (w.oauthPhase === "authorizing") {
4070
+ oauthSeq++;
4071
+ return impl.widgetRespond(s, { value: "primary" });
4072
+ }
4073
+ // Key from the card itself: a worker rebuilt over persisted state restores
4074
+ // the card without a transcript rebuild, so the module-local key is still
4075
+ // empty and the in-flight guard below would swallow the first Authorize.
4076
+ const key = oauthKeyOf(w);
4077
+ if (key !== oauthKey) { oauthKey = key; oauthSeq++; }
4078
+ if (oauthOpening === key) return undefined;
4079
+ oauthOpening = key;
4080
+ const seq = ++oauthSeq, turn = turnSeq, draft = draftSeq;
4081
+ let opened = false;
4082
+ try { opened = !!(await o.openLink?.(w.oauthAuthorizationUrl)); } catch { /* shown below */ }
4083
+ finally { if (oauthOpening === key) oauthOpening = ""; }
4084
+ // Never merge an old action snapshot over a newer conversation, widget
4085
+ // or composer edit. An external browser opening can take arbitrarily long.
4086
+ if (seq !== oauthSeq || key !== oauthKey || turn !== turnSeq || draft !== draftSeq) return undefined;
4087
+ return opened
4088
+ ? { ...s, widget: oauthView(w, w.oauthAuthorizationUrl, disclosedLabel, oauthCopy(), "authorizing") }
4089
+ : { ...s, widget: { ...w, notice: oauthCopy().openFailed, noticeHidden: false } };
4090
+ },
4091
+ widgetSecondary: (s) => {
4092
+ if (s.widget.kind === "OAUTH_REQUIRED") oauthSeq++;
4093
+ return s.widget.secondaryUrl ? openWidgetUrl(s, s.widget.secondaryUrl)
4094
+ : impl.widgetRespond(s, { value: "secondary" });
4095
+ },
4037
4096
 
4038
4097
  dictate: (s) => {
4039
4098
  if (!o.dictation || s.listening) return s;
@@ -4478,7 +4537,7 @@ export function createAriaChat(o: AriaChatOptions): AriaChatCore {
4478
4537
  widgetAnswer: (s, arg) => gated(impl.widgetAnswer(s, arg)),
4479
4538
  widgetStep: (s, arg) => gated(impl.widgetStep(s, arg)),
4480
4539
  widgetRespond: (s, arg) => impl.widgetRespond(s, arg).then(gated),
4481
- widgetPrimary: (s) => impl.widgetPrimary(s).then(gated),
4540
+ widgetPrimary: (s) => impl.widgetPrimary(s).then((r) => r ? gated(r) : r),
4482
4541
  widgetSecondary: (s) => impl.widgetSecondary(s).then(gated),
4483
4542
  dictate: (s) => gated(impl.dictate(s)),
4484
4543
  finishDictation: (s) => gated(impl.finishDictation(s)),
@@ -0,0 +1,42 @@
1
+ import type { Disclose, WidgetView } from "./aria-widget-view.js";
2
+ import { isWebUrl } from "./aria-widget-model.js";
3
+
4
+ export interface OAuthCopy {
5
+ title: string; body: string; pending: string; authorize: string; decline: string;
6
+ done: string; authorized: string; declined: string; openFailed: string;
7
+ }
8
+
9
+ export const DEFAULT_OAUTH_COPY: OAuthCopy = {
10
+ title: "Connect an account", body: "Authorize access to continue this task.",
11
+ pending: "Finish authorization in your browser, then return and choose Done.",
12
+ authorize: "Authorize", decline: "Decline", done: "Done",
13
+ authorized: "Authorized", declined: "Declined",
14
+ openFailed: "Couldn't open authorization. Try again or decline.",
15
+ };
16
+
17
+ // These instructions are wire content from the native Aria client, not copy.
18
+ export const OAUTH_AUTHORIZED_NOTE = "The user completed the OAuth authorization flow. Please retry the previous tool call.";
19
+ export const OAUTH_DECLINED_NOTE = "The user declined OAuth authorization. Do not retry the tool.";
20
+
21
+ /** A browser-open result is not an OAuth callback. Only the owner's subsequent
22
+ * Done action sends completion. The destination is disclosed by the same helper
23
+ * as every other widget URL; no guessed server callback is invoked. */
24
+ export function oauthView(
25
+ view: WidgetView, rawUrl: string, disclose: Disclose,
26
+ copy: OAuthCopy = DEFAULT_OAUTH_COPY, phase: "pending" | "authorizing" = "pending",
27
+ ): WidgetView {
28
+ const url = isWebUrl(rawUrl.trim()) ? rawUrl.trim() : "";
29
+ const authorizing = phase === "authorizing" && !!url;
30
+ return {
31
+ ...view, notice: "", noticeHidden: true, hidden: false, oauthPhase: authorizing ? "authorizing" : "pending",
32
+ oauthAuthorizationUrl: url,
33
+ title: copy.title, titleHidden: !copy.title,
34
+ text: authorizing ? copy.pending : copy.body, textHidden: false,
35
+ primaryLabel: authorizing ? copy.done : disclose({ label: copy.authorize, url }),
36
+ primaryUrl: authorizing ? "" : url,
37
+ primaryHidden: !url, primaryDisabled: false, primaryEnabled: true,
38
+ primaryRespondText: authorizing ? `${copy.authorized}\n<HIDDEN>${OAUTH_AUTHORIZED_NOTE}</HIDDEN>` : "",
39
+ secondaryLabel: copy.decline, secondaryHidden: false, secondaryUrl: "",
40
+ secondaryRespondText: `${copy.declined}\n<HIDDEN>${OAUTH_DECLINED_NOTE}</HIDDEN>`,
41
+ };
42
+ }
@@ -14,6 +14,7 @@
14
14
 
15
15
  import type { NormalizedWidget, WidgetKind, WidgetOption } from "./aria-widget-model.js";
16
16
  import { SELECTED_TOKEN, VALUES_TOKEN, isWebUrl, stripMarkdown } from "./aria-widget-model.js";
17
+ import { oauthView } from "./aria-widget-oauth.js";
17
18
  import { composeGenericCard } from "./aria-generic-widget.js";
18
19
  import { normalizeWidget } from "./aria-widget-kinds.js";
19
20
  import { scanEnvelopes, widgetsOfParts } from "./aria-widgets.js";
@@ -127,6 +128,8 @@ export interface WidgetStep {
127
128
  /** The active widget, as the screen reads it. */
128
129
  export interface WidgetView {
129
130
  kind: WidgetCase;
131
+ oauthPhase?: "pending" | "authorizing";
132
+ oauthAuthorizationUrl?: string;
130
133
  /** Transcript row that owns this widget; prevents state carrying into a later
131
134
  * identical-looking ask. */
132
135
  sourceMessageId?: string;
@@ -1021,6 +1024,9 @@ export function viewOf(
1021
1024
  // A questionnaire is shown one question at a time; its on-screen fields are
1022
1025
  // derived, never stored, so they start from the same function every later
1023
1026
  // change goes through. The worker re-derives with its own copy.
1027
+ if (w.kind === "OAUTH_REQUIRED") {
1028
+ return oauthView(view, typeof extra.authorizationUrl === "string" ? extra.authorizationUrl : "", disclose);
1029
+ }
1024
1030
  return w.kind === "QUESTIONNAIRE"
1025
1031
  ? questionnaireSynced(view, 0, DEFAULT_QUESTIONNAIRE_COPY, false)
1026
1032
  : view;
@@ -248,6 +248,17 @@ const core = createAriaChat({
248
248
  // sentence around it is localized.
249
249
  mentionItemsFailed: (category: string) =>
250
250
  copyTemplate("ownerAria.mention.itemsFailed", "Couldn't load {category}.", { category }),
251
+ oauth: {
252
+ title: () => copyParam("ownerAria.oauth.title", "Connect an account"),
253
+ body: () => copyParam("ownerAria.oauth.body", "Authorize access to continue this task."),
254
+ pending: () => copyParam("ownerAria.oauth.pending", "Finish authorization in your browser, then return and choose Done."),
255
+ authorize: () => copyParam("ownerAria.oauth.authorize", "Authorize"),
256
+ decline: () => copyParam("ownerAria.oauth.decline", "Decline"),
257
+ done: () => copyParam("ownerAria.oauth.done", "Done"),
258
+ authorized: () => copyParam("ownerAria.oauth.authorized", "Authorized"),
259
+ declined: () => copyParam("ownerAria.oauth.declined", "Declined"),
260
+ openFailed: () => copyParam("ownerAria.oauth.openFailed", "Couldn't open authorization. Try again or decline."),
261
+ },
251
262
  widgetItemsFailed: () => copyParam("ownerAria.widget.itemsFailed", "Couldn't load these items."),
252
263
  widgetItemsUnavailable: () => copyParam("ownerAria.widget.itemsUnavailable", "Items aren't available here."),
253
264
  attachUploading: () => copyParam("ownerAria.attach.uploading", "Uploading…"),
@@ -432,7 +443,7 @@ const svc = defineService<AriaChatState, {
432
443
  // moved on must not commit its pre-await snapshot over the new one.
433
444
  copyMessage: (s: AriaChatState, arg?: AriaActionArg) => Promise<AriaChatState | undefined>;
434
445
  regenerate: (s: AriaChatState) => Promise<AriaChatState>;
435
- widgetPrimary: (s: AriaChatState) => Promise<AriaChatState>;
446
+ widgetPrimary: (s: AriaChatState) => Promise<AriaChatState | undefined>;
436
447
  widgetSecondary: (s: AriaChatState) => Promise<AriaChatState>;
437
448
  widgetToggle: (s: AriaChatState, arg?: AriaActionArg) => AriaChatState;
438
449
  widgetSelectOne: (s: AriaChatState, arg?: AriaActionArg) => AriaChatState;
@@ -3371,6 +3371,7 @@ const SCREENS = runtimeSetting({
3371
3371
  "onAppear": {
3372
3372
  "actionId": "tier5.himiStoreAccount.refresh",
3373
3373
  "params": {
3374
+ "memberAccountLinks": "1",
3374
3375
  "copy": "{\"account.subtitle\":\"RSVPs, groups and saved content in one place.\",\"storeAccount.authBody\":\"Sign in to continue — RSVPs and groups stay with you.\",\"storeAccount.authBodyRegister\":\"Create a member account to continue — RSVPs and groups stay with you.\"}"
3375
3376
  }
3376
3377
  }
@@ -3381,7 +3382,8 @@ const SCREENS = runtimeSetting({
3381
3382
  "integrity": "",
3382
3383
  "contentType": "application/javascript+ts-bundle",
3383
3384
  "declaredCapabilities": [
3384
- "wix_api"
3385
+ "wix_api",
3386
+ "app_info"
3385
3387
  ],
3386
3388
  "minBinaryVersion": "0.2.0",
3387
3389
  "bundleVersion": "0.0.1"
@@ -65,6 +65,8 @@ export const VERTICAL_ROOT_SCREENS: Readonly<Record<string, readonly string[]>>
65
65
  * (`brandedLiteScreenOwners`, checked by the app's hosted-mode tests), so a screen added
66
66
  * to a vertical without being listed here fails the build. */
67
67
  export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLiteVertical[]>> = {
68
+ himi_address: ["restaurants", "store"],
69
+ himi_addresses: ["restaurants", "store"],
68
70
  himi_badge: ["badges"],
69
71
  himi_badges: ["badges"],
70
72
  himi_blog: ["blog"],
@@ -127,6 +129,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
127
129
  himi_video: ["videos"],
128
130
  himi_video_channel: ["videos"],
129
131
  himi_videos: ["videos"],
132
+ himi_wallet: ["bookings", "plans", "restaurants", "store"],
130
133
  };
131
134
 
132
135
  /** The templated (`<prefix>[_/]<id>`) detail routes each vertical owns, pinned the same way. */
@@ -36,3 +36,17 @@ export async function assertMemberAccess(member: MemberAccess): Promise<void> {
36
36
  export function memberAccessDenied(error: unknown): boolean {
37
37
  return (error as { name?: string } | null)?.name === "MemberAccessChanged" || /(?:HTTP\s*(?:401|403)|READ_ORDER_FORBIDDEN|permission denied|forbidden)/i.test(String(error));
38
38
  }
39
+
40
+ /** Did this write fail because the member changed (signed out, or another account)? Then
41
+ * the screen reloads for whoever is signed in now. A 401/403 for the SAME member is only a
42
+ * failed write: the caller keeps what the member typed and says so. */
43
+ export async function memberChanged(member: MemberAccess | undefined, error: unknown): Promise<boolean> {
44
+ if ((error as { name?: string } | null)?.name === "MemberAccessChanged") return true;
45
+ if (!member || !memberAccessDenied(error)) return false;
46
+ try {
47
+ await assertMemberAccess(member);
48
+ return false;
49
+ } catch {
50
+ return true;
51
+ }
52
+ }
@@ -0,0 +1,43 @@
1
+ // Can this host reach the member account routes My Addresses and My Wallet need?
2
+ //
3
+ // Both are served OFF www.wixapis.com (the address book on ecom.wix.com, saved cards on
4
+ // the member's own site), so only a native runtime whose WixApiCapability pins them can
5
+ // call them: HimalayaCore 1.4.0 and later. The web bridges refuse absolute URLs, and a
6
+ // hosted app (Spaces) signs its calls with a capability pinned to www.wixapis.com. Saved
7
+ // cards also need the shell to have bound its own site (app_info `memberSiteBound`): a
8
+ // multi-app host such as Himi Player binds none, so its wallet route has no host. The
9
+ // Account screen hides a link whose route is unreachable, and the screen says so instead
10
+ // of failing a load.
11
+ import { get as getAppInfo } from "@himalaya/app-info";
12
+ import { isHostedWorker } from "./hosted-checkout.js";
13
+
14
+ /** The HimalayaCore version whose WixApiCapability pins these routes. Checked here, at run
15
+ * time: the screens declare no `minBinaryVersion`, because a release takes its highest
16
+ * screen floor as its own and would then refuse every older binary. */
17
+ export const MEMBER_ACCOUNT_ROUTES_MIN_BINARY = "1.4.0";
18
+
19
+ function atLeast(version: string, floor: string): boolean {
20
+ const parts = (v: string) => v.split("-")[0].split(".").map((p) => Number.parseInt(p, 10) || 0);
21
+ const a = parts(version), b = parts(floor);
22
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
23
+ const x = a[i] ?? 0, y = b[i] ?? 0;
24
+ if (x !== y) return x > y;
25
+ }
26
+ return true;
27
+ }
28
+
29
+ export interface MemberAccountRoutes {
30
+ /** The address book on ecom.wix.com (My Addresses). */
31
+ addresses: boolean;
32
+ /** Saved cards on the member's own site (My Wallet). */
33
+ wallet: boolean;
34
+ }
35
+
36
+ export async function memberAccountRoutes(): Promise<MemberAccountRoutes> {
37
+ if (isHostedWorker()) return { addresses: false, wallet: false };
38
+ const info = await getAppInfo().catch(() => undefined);
39
+ if (!info) return { addresses: false, wallet: false };
40
+ const native = info.platform === "ios" || info.platform === "android" || info.platform === "macos";
41
+ const addresses = native && atLeast(info.binaryVersion ?? "", MEMBER_ACCOUNT_ROUTES_MIN_BINARY);
42
+ return { addresses, wallet: addresses && info.memberSiteBound === true };
43
+ }
@@ -13,6 +13,7 @@ import { dispatch } from "@himalaya/dispatch";
13
13
  import { searchOrders, type WixOrder } from "@himalaya/wix-ecom";
14
14
  import { guestProfile, loadMemberProfile, strOf, fmtDate, titleCase, type AccountActivityRow } from "../_shared/himi-account";
15
15
  import { stashCopy, copyParam, copyTemplate } from "../_shared/himi-copy.js";
16
+ import { memberAccountRoutes } from "../_shared/member-account-routes.js";
16
17
 
17
18
  interface AuthRouteInput {
18
19
  intent?: string;
@@ -205,6 +206,14 @@ interface S {
205
206
  activityEmptyText: string;
206
207
  hasActivity: boolean;
207
208
  noActivity: boolean;
209
+ /** Set once a descriptor asks for the member-account links (appear param
210
+ * `memberAccountLinks: "1"`). Only then does the probe read app_info, so a descriptor
211
+ * that renders no such link need not declare that capability. */
212
+ memberAccountLinks: boolean;
213
+ /** Hides My Addresses where this runtime cannot reach the address book. */
214
+ noMemberAddresses: boolean;
215
+ /** Hides My Wallet where this runtime cannot reach saved cards. */
216
+ noMemberWallet: boolean;
208
217
  }
209
218
 
210
219
  function derive(s: S): S {
@@ -278,6 +287,8 @@ async function orderRows(memberEmail: string): Promise<AccountActivityRow[]> {
278
287
  async function probe(s: S, arg?: unknown): Promise<S> {
279
288
  const intent = authIntentFromArg(arg, s);
280
289
  const profile = await loadMemberProfile(copyParam("storeAccount.guestDetail", "Sign in to keep your cart and orders connected."));
290
+ const memberAccountLinks = s.memberAccountLinks || strField(arg, "memberAccountLinks") === "1";
291
+ const routes = memberAccountLinks ? await memberAccountRoutes() : { addresses: false, wallet: false };
281
292
  let activityRows: AccountActivityRow[] = [];
282
293
  if (profile.isMember) {
283
294
  try {
@@ -301,6 +312,9 @@ async function probe(s: S, arg?: unknown): Promise<S> {
301
312
  noMemberImage: profile.noMemberImage,
302
313
  email: profile.memberEmail || s.email,
303
314
  message: "",
315
+ memberAccountLinks,
316
+ noMemberAddresses: !routes.addresses,
317
+ noMemberWallet: !routes.wallet,
304
318
  activityRows,
305
319
  activityTitle: copyParam("storeAccount.activityTitle", "Previous orders"),
306
320
  activitySummary: activityRows.length
@@ -394,6 +408,9 @@ const svc = defineService<S, {
394
408
  activityEmptyText: "No previous orders for this member yet.",
395
409
  hasActivity: false,
396
410
  noActivity: true,
411
+ memberAccountLinks: false,
412
+ noMemberAddresses: true,
413
+ noMemberWallet: true,
397
414
  }),
398
415
  actions: {
399
416
  load: (s, arg) => { stashCopy(arg); return probe(s, arg); },
@@ -60582,22 +60582,6 @@ const SCREENS = runtimeSetting({
60582
60582
  "props": {
60583
60583
  "spacing": 8,
60584
60584
  "children": [
60585
- {
60586
- "id": "",
60587
- "body": {
60588
- "package": "himalaya",
60589
- "type": "Text",
60590
- "props": {
60591
- "text": "$service:himiOwnerLiteAria.widget.badge",
60592
- "style": "footnote",
60593
- "color": "textSecondary",
60594
- "maxLines": 12
60595
- }
60596
- },
60597
- "modifiers": {
60598
- "hiddenPath": "$service:himiOwnerLiteAria.widget.badgeHidden"
60599
- }
60600
- },
60601
60585
  {
60602
60586
  "id": "",
60603
60587
  "body": {
@@ -60634,21 +60618,21 @@ const SCREENS = runtimeSetting({
60634
60618
  "package": "himalaya",
60635
60619
  "type": "Text",
60636
60620
  "props": {
60637
- "text": "$service:himiOwnerLiteAria.widget.bottomText",
60621
+ "text": "$service:himiOwnerLiteAria.widget.notice",
60638
60622
  "style": "footnote",
60639
60623
  "color": "textSecondary",
60640
60624
  "maxLines": 12
60641
60625
  }
60642
60626
  },
60643
60627
  "modifiers": {
60644
- "hiddenPath": "$service:himiOwnerLiteAria.widget.bottomTextHidden"
60628
+ "hiddenPath": "$service:himiOwnerLiteAria.widget.noticeHidden"
60645
60629
  }
60646
60630
  },
60647
60631
  {
60648
60632
  "id": "himi_owner_lite_aria.widget.OAUTH_REQUIRED.footer",
60649
60633
  "body": {
60650
60634
  "package": "himalaya",
60651
- "type": "HStack",
60635
+ "type": "VStack",
60652
60636
  "props": {
60653
60637
  "spacing": 8,
60654
60638
  "children": [
@@ -60660,6 +60644,7 @@ const SCREENS = runtimeSetting({
60660
60644
  "props": {
60661
60645
  "title": "$service:himiOwnerLiteAria.widget.primaryLabel",
60662
60646
  "style": "primary",
60647
+ "fullWidth": true,
60663
60648
  "action": {
60664
60649
  "actionId": "tier5.himiOwnerLiteAria.widgetPrimary"
60665
60650
  }
@@ -60677,6 +60662,7 @@ const SCREENS = runtimeSetting({
60677
60662
  "props": {
60678
60663
  "title": "$service:himiOwnerLiteAria.widget.secondaryLabel",
60679
60664
  "style": "secondary",
60665
+ "fullWidth": true,
60680
60666
  "action": {
60681
60667
  "actionId": "tier5.himiOwnerLiteAria.widgetSecondary"
60682
60668
  }
@@ -60685,14 +60671,6 @@ const SCREENS = runtimeSetting({
60685
60671
  "modifiers": {
60686
60672
  "hiddenPath": "$service:himiOwnerLiteAria.widget.secondaryHidden"
60687
60673
  }
60688
- },
60689
- {
60690
- "id": "",
60691
- "body": {
60692
- "package": "himalaya",
60693
- "type": "Spacer",
60694
- "props": {}
60695
- }
60696
60674
  }
60697
60675
  ]
60698
60676
  }