@wix/himalaya-cli 0.1030.0 → 0.1031.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 (121) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +7 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.d.ts +32 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.rules.d.ts +2 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +7 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +64 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-genie-chat.mjs +41 -1
  7. package/dist/cli.mjs +260 -104
  8. package/dist/preview-assets.generated.bin +0 -0
  9. package/guides/sdk-reference.json +50 -2
  10. package/package.json +2 -2
  11. package/templates/beauty-salon/tier5-src/_shared/owner-load-error.ts +7 -1
  12. package/templates/beauty-salon-owner/config.ts +1 -1
  13. package/templates/beauty-salon-owner/dev/index.ts +247 -9
  14. package/templates/beauty-salon-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  15. package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +405 -20
  16. package/templates/beauty-salon-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  17. package/templates/beauty-salon-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  18. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  19. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  20. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  21. package/templates/branded-lite/tier5-src/_shared/owner-load-error.ts +7 -1
  22. package/templates/community-club/tier5-src/_shared/owner-load-error.ts +7 -1
  23. package/templates/community-club-owner/config.ts +1 -1
  24. package/templates/community-club-owner/dev/index.ts +247 -9
  25. package/templates/community-club-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  26. package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +405 -20
  27. package/templates/community-club-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  28. package/templates/community-club-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  29. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  30. package/templates/community-club-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  31. package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  32. package/templates/events-meetups/tier5-src/_shared/owner-load-error.ts +7 -1
  33. package/templates/events-meetups-owner/config.ts +1 -1
  34. package/templates/events-meetups-owner/dev/index.ts +247 -9
  35. package/templates/events-meetups-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  36. package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +405 -20
  37. package/templates/events-meetups-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  38. package/templates/events-meetups-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  39. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  40. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  41. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  42. package/templates/gym-fitness/tier5-src/_shared/owner-load-error.ts +7 -1
  43. package/templates/gym-fitness-owner/config.ts +1 -1
  44. package/templates/gym-fitness-owner/dev/index.ts +247 -9
  45. package/templates/gym-fitness-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  46. package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +405 -20
  47. package/templates/gym-fitness-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  48. package/templates/gym-fitness-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  49. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  50. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  51. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  52. package/templates/himi-chat/tier5-src/_shared/owner-load-error.ts +7 -1
  53. package/templates/nonprofit-cause/tier5-src/_shared/owner-load-error.ts +7 -1
  54. package/templates/nonprofit-cause-owner/config.ts +1 -1
  55. package/templates/nonprofit-cause-owner/dev/index.ts +247 -9
  56. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  57. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +405 -20
  58. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  59. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  60. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  61. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  62. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  63. package/templates/owner-lite/config.ts +1 -1
  64. package/templates/owner-lite/dev/index.ts +247 -9
  65. package/templates/owner-lite/tier5-src/_shared/aria-attachments.ts +179 -0
  66. package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +405 -20
  67. package/templates/owner-lite/tier5-src/_shared/owner-bookings.ts +20 -0
  68. package/templates/owner-lite/tier5-src/_shared/owner-load-error.ts +7 -1
  69. package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  70. package/templates/owner-lite/tier5-src/himi-owner-lite-home/index.ts +2 -12
  71. package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  72. package/templates/podcast-creator/tier5-src/_shared/owner-load-error.ts +7 -1
  73. package/templates/podcast-creator-owner/config.ts +1 -1
  74. package/templates/podcast-creator-owner/dev/index.ts +247 -9
  75. package/templates/podcast-creator-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  76. package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +405 -20
  77. package/templates/podcast-creator-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  78. package/templates/podcast-creator-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  79. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  80. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  81. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  82. package/templates/portfolio-creative/tier5-src/_shared/owner-load-error.ts +7 -1
  83. package/templates/portfolio-creative-owner/config.ts +1 -1
  84. package/templates/portfolio-creative-owner/dev/index.ts +247 -9
  85. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  86. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +405 -20
  87. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  88. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  89. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  90. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  91. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  92. package/templates/restaurant/tier5-src/_shared/owner-load-error.ts +7 -1
  93. package/templates/restaurant-owner/config.ts +1 -1
  94. package/templates/restaurant-owner/dev/index.ts +247 -9
  95. package/templates/restaurant-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  96. package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +405 -20
  97. package/templates/restaurant-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  98. package/templates/restaurant-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  99. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  100. package/templates/restaurant-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  101. package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  102. package/templates/retail-store/tier5-src/_shared/owner-load-error.ts +7 -1
  103. package/templates/retail-store-owner/config.ts +1 -1
  104. package/templates/retail-store-owner/dev/index.ts +247 -9
  105. package/templates/retail-store-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  106. package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +405 -20
  107. package/templates/retail-store-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  108. package/templates/retail-store-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  109. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  110. package/templates/retail-store-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  111. package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  112. package/templates/yoga-studio/tier5-src/_shared/owner-load-error.ts +7 -1
  113. package/templates/yoga-studio-owner/config.ts +1 -1
  114. package/templates/yoga-studio-owner/dev/index.ts +247 -9
  115. package/templates/yoga-studio-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  116. package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +405 -20
  117. package/templates/yoga-studio-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  118. package/templates/yoga-studio-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  119. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  120. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  121. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
@@ -16748,7 +16748,25 @@
16748
16748
  "name": "ConversationMessage",
16749
16749
  "kind": "interface",
16750
16750
  "jsdoc": "",
16751
- "decl": "export interface ConversationMessage {\n id?: string;\n content?: string;\n role?: MessageRole;\n createdDate?: string;\n status?: MessageStatus;\n /** Client tools this assistant turn asks the CALLER to run — see `FunctionCall`. */\n functionCalls?: FunctionCall[];\n}"
16751
+ "decl": "export interface ConversationMessage {\n id?: string;\n content?: string;\n role?: MessageRole;\n createdDate?: string;\n status?: MessageStatus;\n /** Files the owner attached to this turn, as the service stored them. */\n attachments?: Attachment[];\n /** Client tools this assistant turn asks the CALLER to run — see `FunctionCall`. */\n functionCalls?: FunctionCall[];\n}"
16752
+ },
16753
+ {
16754
+ "name": "Attachment",
16755
+ "kind": "interface",
16756
+ "jsdoc": "/** A file on a message — the service's `Attachment` entity.\n *\n * `url` is the service's own REFERENCE to an uploaded file\n * (`genie-upload://<id>`, see `genieUploadRef`), not a fetchable address: no\n * route that resolves it to a download url is published, so a client can name a\n * sent attachment but not show it again from the server's copy. `viewUrl` is\n * whatever preview the SENDING client chose to store, and is not trusted to\n * resolve anywhere else. */",
16757
+ "decl": "export interface Attachment {\n /** Original file name including extension. The service caps it at 255. */\n fileName: string;\n /** e.g. `\"image/jpeg\"`. The service caps it at 100. */\n mimeType: string;\n url?: string;\n viewUrl?: string;\n}"
16758
+ },
16759
+ {
16760
+ "name": "CreateFileUploadResponse",
16761
+ "kind": "interface",
16762
+ "jsdoc": "/** The mint of an upload: where to send the bytes, and the record's id. */",
16763
+ "decl": "export interface CreateFileUploadResponse { upload?: { uploadUrl?: string; id?: string } }"
16764
+ },
16765
+ {
16766
+ "name": "CreateFileUploadOptions",
16767
+ "kind": "interface",
16768
+ "jsdoc": "",
16769
+ "decl": "export interface CreateFileUploadOptions {\n /** The same client-declared scoping flag every other chat-service request\n * takes. Omitted unless given — the dashboard sends it only when its own\n * account-scoping gate is on. */\n enforceAccountScopedConversations?: boolean;\n}"
16752
16770
  },
16753
16771
  {
16754
16772
  "name": "FunctionCall",
@@ -16820,7 +16838,7 @@
16820
16838
  "name": "SendMessageOptions",
16821
16839
  "kind": "interface",
16822
16840
  "jsdoc": "/** Optional wire flags on `sendMessage`. `communicationMode` /\n * `enableRealtimeEvents` were in the original captured payload; only POLLING is\n * verified end-to-end. The rest were added from the 2026-09-19 re-capture. */",
16823
- "decl": "export interface SendMessageOptions {\n communicationMode?: CommunicationMode;\n enableRealtimeEvents?: boolean;\n metadata?: UserMessageMetadata;\n /** The dashboard sends `true`. Optional: verified to answer either way. */\n enforceAccountScopedConversations?: boolean;\n /** Tag the turn with the same origin the conversation was created under. */\n origin?: string;\n}"
16841
+ "decl": "export interface SendMessageOptions {\n communicationMode?: CommunicationMode;\n enableRealtimeEvents?: boolean;\n metadata?: UserMessageMetadata;\n /** The dashboard sends `true`. Optional: verified to answer either way. */\n enforceAccountScopedConversations?: boolean;\n /** Tag the turn with the same origin the conversation was created under. */\n origin?: string;\n /** Files already UPLOADED (see `createFileUpload`) to store with the turn.\n * Rides step 1 only — the trigger names the stored turn, which carries them. */\n attachments?: Attachment[];\n}"
16824
16842
  },
16825
16843
  {
16826
16844
  "name": "ConversationUserMessageResponse",
@@ -16870,6 +16888,30 @@
16870
16888
  "jsdoc": "/** Ask the service to abandon the assistant reply it is generating for\n * `userMessageId` — the \"stop\" a chat surface puts beside a reply in progress.\n *\n * Addressed by USER message, not by conversation: the thing being abandoned is\n * one turn, and the id comes from that turn's own send response\n * (`userMessageIdOf`). There is no route that looks it up afterwards, so a\n * caller that did not keep it cannot abort.\n *\n * Resolving means the service ACCEPTED the abort, not that generation had not\n * already finished — a reply that was already written still lands in the\n * transcript. Rejecting means the turn is still running: treat it as \"could\n * not stop\", never as \"stopped\". */",
16871
16889
  "decl": "export function abortAssistantMessageGeneration(userMessageId: string): Promise<AbortAssistantMessageGenerationResponse>;"
16872
16890
  },
16891
+ {
16892
+ "name": "createFileUpload",
16893
+ "kind": "function",
16894
+ "jsdoc": "/** Mint an upload for one file: a pre-signed url to send its bytes to, and the\n * id the message will reference it by (`genieUploadRef`).\n *\n * Only the MINT goes through the chat-service; the bytes go straight to\n * `upload.uploadUrl` (see the file header). Resolving is not proof the file\n * exists — nothing is stored until those bytes land, so a caller must not\n * attach the reference before its upload has succeeded. */",
16895
+ "decl": "export function createFileUpload(\n fileName: string,\n mimeType: string,\n opts: CreateFileUploadOptions = {},\n): Promise<CreateFileUploadResponse>;"
16896
+ },
16897
+ {
16898
+ "name": "GENIE_UPLOAD_SCHEME",
16899
+ "kind": "const",
16900
+ "jsdoc": "/** The scheme every first-party creator uses to reference an uploaded file from\n * a message attachment. */",
16901
+ "decl": "export const GENIE_UPLOAD_SCHEME = \"genie-upload://\";"
16902
+ },
16903
+ {
16904
+ "name": "genieUploadRef",
16905
+ "kind": "function",
16906
+ "jsdoc": "/** `genie-upload://<id>`, or \"\" for no id — never a reference to nothing. */",
16907
+ "decl": "export function genieUploadRef(id: string | undefined): string;"
16908
+ },
16909
+ {
16910
+ "name": "uploadTargetUrl",
16911
+ "kind": "function",
16912
+ "jsdoc": "/** Where the bytes actually go: `uploadUrl` with `path` and `acl=private` set.\n *\n * Mirrors the Media Platform browser uploader every first-party client relies\n * on. The service rewrites the storage key itself, so `path` is advisory; it is\n * sent anyway, for parity with the clients whose uploads are known to work.\n *\n * String surgery rather than `new URL`, because the worker runtimes (JSContext,\n * Hermes, QuickJS) do not all ship the URL constructor — and MERGED rather than\n * appended, because the signed url may already carry a query, and a second `?`\n * would corrupt the signature it carries. An existing `path` / `acl` is\n * replaced rather than duplicated; everything else, the fragment included, is\n * kept byte for byte. */",
16913
+ "decl": "export function uploadTargetUrl(uploadUrl: string, fileName: string): string;"
16914
+ },
16873
16915
  {
16874
16916
  "name": "getConversationMessages",
16875
16917
  "kind": "function",
@@ -16906,6 +16948,12 @@
16906
16948
  "jsdoc": "/** A message's text. `content` is normally a string, but can arrive as an object\n * carrying `text`; anything else is stringified rather than dropped. */",
16907
16949
  "decl": "export function messageText(m: ConversationMessage | null | undefined): string;"
16908
16950
  },
16951
+ {
16952
+ "name": "attachmentsOf",
16953
+ "kind": "function",
16954
+ "jsdoc": "/** A message's attachments that name a file, in order. Anything that is not an\n * object with a non-empty `fileName` is dropped rather than rendered as a blank\n * entry — the list is display-only, so a malformed row has nothing to show. */",
16955
+ "decl": "export function attachmentsOf(m: ConversationMessage | null | undefined): Attachment[];"
16956
+ },
16909
16957
  {
16910
16958
  "name": "lastAssistantMessage",
16911
16959
  "kind": "function",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1030.0",
3
+ "version": "0.1031.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -65,5 +65,5 @@
65
65
  "artifactId": "himalaya-cli"
66
66
  }
67
67
  },
68
- "falconPackageHash": "490de5e74662e1485d41c6fbcf35c5211cea45af726de33892022b39"
68
+ "falconPackageHash": "b2432c45ff8926fa8325d6f05d7cfaddf683708c33a4537c34b9fa45"
69
69
  }
@@ -1,6 +1,12 @@
1
1
  import { copyParam } from "./himi-copy.js";
2
2
 
3
- /** Host-owned preview input. Absent on native and older hosts. */
3
+ /** Host-owned preview input. Absent on native and older hosts.
4
+ *
5
+ * `"sample"` — the built-in demo records; `"live"` — the viewer's own business over the
6
+ * owner rung; `"fixtures"` — a DEV web host over a sealed hermetic gateway, where
7
+ * the dev fixtures are the sample data. `"fixtures"` is neither live nor demo, so a
8
+ * worker READS through the bridge as it does on a device; it is still a preview host
9
+ * (`isOwnerPreviewHost`), so failure copy may name the web preview. */
4
10
  function ownerPreviewMode(): unknown {
5
11
  return (globalThis as unknown as { himalaya?: { input?: Record<string, unknown> } }).himalaya?.input?.__himiOwnerPreview;
6
12
  }
@@ -37,7 +37,7 @@ export default defineApp({
37
37
  actions: "http://localhost:8190/v1/actions",
38
38
  sync: "http://localhost:8190/v1/sync",
39
39
  },
40
- capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui"],
40
+ capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui","camera","presigned_upload"],
41
41
  designTokensPath: "./tokens.json",
42
42
  navigation: {
43
43
  "navKind": "responsive",
@@ -50387,7 +50387,7 @@ const SCREENS = runtimeSetting({
50387
50387
  "itemsPath": "$service:himiOwnerLiteManage.recents",
50388
50388
  "items": [
50389
50389
  {
50390
- "id": "",
50390
+ "id": "himi_owner_lite.manage.recent.$item.id",
50391
50391
  "body": {
50392
50392
  "package": "himalaya",
50393
50393
  "type": "VStack",
@@ -50532,7 +50532,7 @@ const SCREENS = runtimeSetting({
50532
50532
  "spacing": 14,
50533
50533
  "children": [
50534
50534
  {
50535
- "id": "",
50535
+ "id": "himi_owner_lite.manage.recent.create.$item.id",
50536
50536
  "body": {
50537
50537
  "package": "himalaya",
50538
50538
  "type": "Text",
@@ -50557,7 +50557,7 @@ const SCREENS = runtimeSetting({
50557
50557
  }
50558
50558
  },
50559
50559
  {
50560
- "id": "",
50560
+ "id": "himi_owner_lite.manage.recent.handoff.$item.id",
50561
50561
  "body": {
50562
50562
  "package": "himalaya",
50563
50563
  "type": "Text",
@@ -50693,7 +50693,7 @@ const SCREENS = runtimeSetting({
50693
50693
  "itemsPath": "$item.areas",
50694
50694
  "items": [
50695
50695
  {
50696
- "id": "",
50696
+ "id": "himi_owner_lite.manage.area.$item.id",
50697
50697
  "body": {
50698
50698
  "package": "himalaya",
50699
50699
  "type": "VStack",
@@ -50838,7 +50838,7 @@ const SCREENS = runtimeSetting({
50838
50838
  "spacing": 14,
50839
50839
  "children": [
50840
50840
  {
50841
- "id": "",
50841
+ "id": "himi_owner_lite.manage.area.create.$item.id",
50842
50842
  "body": {
50843
50843
  "package": "himalaya",
50844
50844
  "type": "Text",
@@ -50863,7 +50863,7 @@ const SCREENS = runtimeSetting({
50863
50863
  }
50864
50864
  },
50865
50865
  {
50866
- "id": "",
50866
+ "id": "himi_owner_lite.manage.area.handoff.$item.id",
50867
50867
  "body": {
50868
50868
  "package": "himalaya",
50869
50869
  "type": "Text",
@@ -51643,7 +51643,7 @@ const SCREENS = runtimeSetting({
51643
51643
  "props": {
51644
51644
  "items": [
51645
51645
  {
51646
- "id": "",
51646
+ "id": "ol_drawer_nav.$item.id",
51647
51647
  "body": {
51648
51648
  "package": "himalaya",
51649
51649
  "type": "ListItem",
@@ -51695,7 +51695,7 @@ const SCREENS = runtimeSetting({
51695
51695
  "props": {
51696
51696
  "items": [
51697
51697
  {
51698
- "id": "",
51698
+ "id": "ol_drawer_attention.$item.id",
51699
51699
  "body": {
51700
51700
  "package": "himalaya",
51701
51701
  "type": "ListItem",
@@ -55256,6 +55256,45 @@ const SCREENS = runtimeSetting({
55256
55256
  }
55257
55257
  }
55258
55258
  },
55259
+ {
55260
+ "id": "himi_owner_lite_aria.msg_attach_$item.id",
55261
+ "body": {
55262
+ "package": "himalaya",
55263
+ "type": "HStack",
55264
+ "props": {
55265
+ "spacing": 0,
55266
+ "children": [
55267
+ {
55268
+ "id": "",
55269
+ "body": {
55270
+ "package": "himalaya",
55271
+ "type": "Spacer",
55272
+ "props": {}
55273
+ },
55274
+ "modifiers": {
55275
+ "hiddenPath": "$item.notUser"
55276
+ }
55277
+ },
55278
+ {
55279
+ "id": "",
55280
+ "body": {
55281
+ "package": "himalaya",
55282
+ "type": "Text",
55283
+ "props": {
55284
+ "text": "$item.attachText",
55285
+ "style": "footnote",
55286
+ "color": "textSecondary",
55287
+ "maxLines": 3
55288
+ }
55289
+ }
55290
+ }
55291
+ ]
55292
+ }
55293
+ },
55294
+ "modifiers": {
55295
+ "hiddenPath": "$item.attachHidden"
55296
+ }
55297
+ },
55259
55298
  {
55260
55299
  "id": "himi_owner_lite_aria.msg_$item.id.link1",
55261
55300
  "body": {
@@ -58836,6 +58875,203 @@ const SCREENS = runtimeSetting({
58836
58875
  }
58837
58876
  }
58838
58877
  },
58878
+ {
58879
+ "id": "himi_owner_lite_aria.attachments.bound",
58880
+ "body": {
58881
+ "package": "himalaya",
58882
+ "type": "LazyList",
58883
+ "props": {
58884
+ "itemsPath": "$service:himiOwnerLiteAria.attachments",
58885
+ "horizontal": true,
58886
+ "spacing": 8,
58887
+ "items": [
58888
+ {
58889
+ "id": "himi_owner_lite_aria.attachment_$item.id",
58890
+ "body": {
58891
+ "package": "himalaya",
58892
+ "type": "VStack",
58893
+ "props": {
58894
+ "spacing": 4,
58895
+ "children": [
58896
+ {
58897
+ "id": "himi_owner_lite_aria.attachment_thumb_$item.id",
58898
+ "body": {
58899
+ "package": "himalaya",
58900
+ "type": "Image",
58901
+ "props": {
58902
+ "url": "$item.thumbUrl",
58903
+ "width": 72,
58904
+ "height": 72,
58905
+ "contentMode": "fill",
58906
+ "shape": "rounded",
58907
+ "contentDescription": "$item.name"
58908
+ }
58909
+ },
58910
+ "modifiers": {
58911
+ "hiddenPath": "$item.thumbHidden"
58912
+ }
58913
+ },
58914
+ {
58915
+ "id": "",
58916
+ "body": {
58917
+ "package": "himalaya",
58918
+ "type": "Text",
58919
+ "props": {
58920
+ "text": "$item.statusText",
58921
+ "style": "caption",
58922
+ "color": "textSecondary",
58923
+ "maxLines": 2
58924
+ }
58925
+ },
58926
+ "modifiers": {
58927
+ "hiddenPath": "$item.statusHidden"
58928
+ }
58929
+ },
58930
+ {
58931
+ "id": "",
58932
+ "body": {
58933
+ "package": "himalaya",
58934
+ "type": "HStack",
58935
+ "props": {
58936
+ "spacing": 8,
58937
+ "children": [
58938
+ {
58939
+ "id": "himi_owner_lite_aria.attachment_retry_$item.id",
58940
+ "body": {
58941
+ "package": "himalaya",
58942
+ "type": "Text",
58943
+ "props": {
58944
+ "text": "Retry",
58945
+ "style": "caption",
58946
+ "color": "accentPrimary",
58947
+ "maxLines": 1
58948
+ }
58949
+ },
58950
+ "modifiers": {
58951
+ "onTap": {
58952
+ "actionId": "tier5.himiOwnerLiteAria.retryAttachment",
58953
+ "params": {
58954
+ "id": "$item.id"
58955
+ }
58956
+ },
58957
+ "hiddenPath": "$item.retryHidden"
58958
+ }
58959
+ },
58960
+ {
58961
+ "id": "himi_owner_lite_aria.attachment_remove_$item.id",
58962
+ "body": {
58963
+ "package": "himalaya",
58964
+ "type": "Icon",
58965
+ "props": {
58966
+ "name": "close",
58967
+ "size": 14,
58968
+ "tint": "textSecondary"
58969
+ }
58970
+ },
58971
+ "modifiers": {
58972
+ "onTap": {
58973
+ "actionId": "tier5.himiOwnerLiteAria.removeAttachment",
58974
+ "params": {
58975
+ "id": "$item.id"
58976
+ }
58977
+ },
58978
+ "accessibilityLabel": "Remove photo"
58979
+ }
58980
+ }
58981
+ ]
58982
+ }
58983
+ }
58984
+ }
58985
+ ]
58986
+ }
58987
+ },
58988
+ "modifiers": {
58989
+ "width": 72
58990
+ }
58991
+ }
58992
+ ]
58993
+ }
58994
+ },
58995
+ "modifiers": {
58996
+ "hiddenPath": "$service:himiOwnerLiteAria.attachmentsHidden",
58997
+ "padding": {
58998
+ "leading": 0,
58999
+ "trailing": 0,
59000
+ "top": 8,
59001
+ "bottom": 0
59002
+ }
59003
+ }
59004
+ },
59005
+ {
59006
+ "id": "",
59007
+ "body": {
59008
+ "package": "himalaya",
59009
+ "type": "HStack",
59010
+ "props": {
59011
+ "spacing": 16,
59012
+ "children": [
59013
+ {
59014
+ "id": "himi_owner_lite_aria.attach.library",
59015
+ "body": {
59016
+ "package": "himalaya",
59017
+ "type": "Icon",
59018
+ "props": {
59019
+ "name": "image",
59020
+ "size": 22,
59021
+ "tint": "accentPrimary"
59022
+ }
59023
+ },
59024
+ "modifiers": {
59025
+ "onTap": {
59026
+ "actionId": "tier5.himiOwnerLiteAria.attach",
59027
+ "params": {
59028
+ "source": "library"
59029
+ }
59030
+ },
59031
+ "accessibilityLabel": "Add a photo"
59032
+ }
59033
+ },
59034
+ {
59035
+ "id": "himi_owner_lite_aria.attach.camera",
59036
+ "body": {
59037
+ "package": "himalaya",
59038
+ "type": "Icon",
59039
+ "props": {
59040
+ "name": "camera",
59041
+ "size": 22,
59042
+ "tint": "accentPrimary"
59043
+ }
59044
+ },
59045
+ "modifiers": {
59046
+ "onTap": {
59047
+ "actionId": "tier5.himiOwnerLiteAria.attach",
59048
+ "params": {
59049
+ "source": "camera"
59050
+ }
59051
+ },
59052
+ "accessibilityLabel": "Take a photo"
59053
+ }
59054
+ },
59055
+ {
59056
+ "id": "",
59057
+ "body": {
59058
+ "package": "himalaya",
59059
+ "type": "Spacer",
59060
+ "props": {}
59061
+ }
59062
+ }
59063
+ ]
59064
+ }
59065
+ },
59066
+ "modifiers": {
59067
+ "padding": {
59068
+ "leading": 0,
59069
+ "trailing": 0,
59070
+ "top": 8,
59071
+ "bottom": 0
59072
+ }
59073
+ }
59074
+ },
58839
59075
  {
58840
59076
  "id": "form_aria",
58841
59077
  "body": {
@@ -58921,7 +59157,9 @@ const SCREENS = runtimeSetting({
58921
59157
  "wix_api",
58922
59158
  "open_url",
58923
59159
  "clipboard",
58924
- "ui"
59160
+ "ui",
59161
+ "camera",
59162
+ "presigned_upload"
58925
59163
  ],
58926
59164
  "minBinaryVersion": "0.1.0",
58927
59165
  "bundleVersion": "0.0.1"
@@ -0,0 +1,179 @@
1
+ // Photo attachments for the Aria composer — the pure half.
2
+ //
3
+ // Everything here is a decision that can be made without touching the device
4
+ // or the network: which files may be attached, how many, how large, what a chip
5
+ // in the composer says in each of its three states, and how a picked image is
6
+ // turned into the bytes an upload sends. The half that DOES touch the world —
7
+ // minting the upload, sending the bytes, picking — lives in `aria-chat.ts`
8
+ // (the mint, through `@himalaya/wix-genie-chat`) and in each app's adapter (the
9
+ // picker and the byte transfer, which are device capabilities the adapter's
10
+ // screen has to declare).
11
+ //
12
+ // This file is copied verbatim into every generated starter app, so it explains
13
+ // itself without pointing at anything only this repo has.
14
+
15
+ /** Image types the composer accepts. The first-party clients' own allowlist
16
+ * for images: png, jpeg (and the non-standard `image/jpg` some pickers still
17
+ * report), webp, gif and heic. Anything else is REFUSED with a line saying so,
18
+ * never silently dropped — the native Aria app drops unsupported files without a
19
+ * word, and an owner who picked something and sees nothing happen assumes the
20
+ * button is broken. */
21
+ export const ARIA_IMAGE_TYPES: readonly string[] = [
22
+ "image/png",
23
+ "image/jpeg",
24
+ "image/jpg",
25
+ "image/webp",
26
+ "image/gif",
27
+ "image/heic",
28
+ ];
29
+
30
+ /** At most this many attachments ride one message. The native Aria app caps at
31
+ * 10; nothing on the wire says otherwise. */
32
+ export const ARIA_MAX_ATTACHMENTS = 10;
33
+
34
+ /** The largest image the composer will try to send, in bytes.
35
+ *
36
+ * Not a product choice: it is the ceiling of the transfer this slice uses. A
37
+ * picked photo crosses the worker bridge as a base64 string and is sent inline,
38
+ * and the inline upload refuses anything over 8 MiB (the `MAX_INLINE_BASE64_BYTES`
39
+ * bound of the pre-signed upload capability, which it enforces on every arm).
40
+ * Checking it HERE is what turns that refusal into a sentence the owner can act
41
+ * on, instead of a chip that fails for no stated reason. */
42
+ export const ARIA_MAX_IMAGE_BYTES = 8 * 1024 * 1024;
43
+
44
+ /** A chip in the composer. Every field is always present — a `$item.` path that
45
+ * is missing on some rows does not substitute — and each `…Hidden` flag
46
+ * collapses the part it names. */
47
+ export interface AriaAttachmentChip {
48
+ /** Minted by the worker, never derived from the file. The native Aria app keyed
49
+ * concurrent uploads by file NAME and collided on the second `IMG_0001.jpg`. */
50
+ id: string;
51
+ name: string;
52
+ mimeType: string;
53
+ state: "uploading" | "ready" | "failed";
54
+ /** The chip's thumbnail as a `data:` URI, set only when the picked image is
55
+ * small; "" otherwise, which collapses the preview. The full bytes an upload
56
+ * and a retry send are held by the worker, never in the chip, because the chip
57
+ * rides the service state and a large photo there would exceed the web
58
+ * runtime's frame limit. */
59
+ thumbUrl: string;
60
+ thumbHidden: boolean;
61
+ /** "Uploading…" / "Couldn't upload" / "" — collapses when empty. */
62
+ statusText: string;
63
+ statusHidden: boolean;
64
+ /** The retry control shows ONLY on a failed chip. */
65
+ retryHidden: boolean;
66
+ /** `genie-upload://<id>` once the bytes have landed; "" until then. The send
67
+ * carries a chip only when this is set. */
68
+ ref: string;
69
+ }
70
+
71
+ /** What an upload reports back, delivered as a fresh action so it lands on the
72
+ * CURRENT state rather than on the snapshot the upload started from. */
73
+ export interface AriaAttachmentOutcome {
74
+ id: string;
75
+ ok: boolean;
76
+ /** Set when `ok`. */
77
+ ref?: string;
78
+ }
79
+
80
+ export interface ParsedDataUri { mimeType: string; base64: string; bytes: number }
81
+
82
+ /** `data:<mime>;base64,<payload>` → its parts, or null for anything else.
83
+ *
84
+ * Only the base64 form: every picker this composer is wired to returns it, and
85
+ * a percent-encoded `data:` URI would need decoding the bridge cannot do. The
86
+ * byte count is computed from the payload length, so a multi-megabyte photo is
87
+ * sized without being decoded. */
88
+ export function parseDataUri(uri: string): ParsedDataUri | null {
89
+ const m = /^data:([^;,]*)((?:;[^;,]*)*?);base64,/i.exec(uri ?? "");
90
+ if (!m) return null;
91
+ const base64 = uri.slice(m[0].length).replace(/\s+/g, "");
92
+ const pad = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
93
+ const bytes = Math.max(0, Math.floor((base64.length * 3) / 4) - pad);
94
+ return { mimeType: (m[1] || "").trim().toLowerCase(), base64, bytes };
95
+ }
96
+
97
+ /** Normalize a MIME type a picker reported.
98
+ *
99
+ * Some pickers hand back a platform type identifier where a MIME type belongs
100
+ * (`public.jpeg`, `public.heic`), and the service validates the field as a MIME
101
+ * type. Mapped for the image identifiers this composer accepts; anything else
102
+ * is returned lowercased and left for the allowlist to judge. */
103
+ export function normalizeMime(mime: string): string {
104
+ const v = (mime ?? "").trim().toLowerCase();
105
+ switch (v) {
106
+ case "public.jpeg": return "image/jpeg";
107
+ case "public.png": return "image/png";
108
+ case "public.heic": return "image/heic";
109
+ case "com.compuserve.gif": return "image/gif";
110
+ case "org.webmproject.webp": return "image/webp";
111
+ case "image/jpg": return "image/jpeg";
112
+ default: return v;
113
+ }
114
+ }
115
+
116
+ /** A file name for an image the picker did not name, by type. The service
117
+ * requires one (1–255 characters), and it is what the transcript shows. */
118
+ export function imageFileName(mimeType: string, n: number, given?: string): string {
119
+ const name = (given ?? "").trim();
120
+ if (name) return name.slice(0, 255);
121
+ const ext = mimeType === "image/png" ? "png"
122
+ : mimeType === "image/webp" ? "webp"
123
+ : mimeType === "image/gif" ? "gif"
124
+ : mimeType === "image/heic" ? "heic"
125
+ : "jpg";
126
+ return `photo-${n}.${ext}`;
127
+ }
128
+
129
+ /** Why a picked file cannot be attached, or "" when it can. */
130
+ export type AttachRefusal = "" | "type" | "size" | "count";
131
+
132
+ export function refusalFor(parsed: ParsedDataUri | null, mimeType: string, attached: number): AttachRefusal {
133
+ if (attached >= ARIA_MAX_ATTACHMENTS) return "count";
134
+ if (!parsed || !ARIA_IMAGE_TYPES.includes(mimeType)) return "type";
135
+ if (parsed.bytes > ARIA_MAX_IMAGE_BYTES) return "size";
136
+ return "";
137
+ }
138
+
139
+ /** A chip in a given state. One constructor so the flags can never disagree
140
+ * with the state they describe — a failed chip without its retry control is
141
+ * the shape of bug this rules out. */
142
+ export function chipIn(
143
+ base: Pick<AriaAttachmentChip, "id" | "name" | "mimeType" | "thumbUrl">,
144
+ state: AriaAttachmentChip["state"],
145
+ labels: { uploading: string; failed: string },
146
+ ref = "",
147
+ ): AriaAttachmentChip {
148
+ const statusText = state === "uploading" ? labels.uploading : state === "failed" ? labels.failed : "";
149
+ return {
150
+ ...base,
151
+ state,
152
+ thumbHidden: !base.thumbUrl,
153
+ statusText,
154
+ statusHidden: !statusText,
155
+ retryHidden: state !== "failed",
156
+ ref: state === "ready" ? ref : "",
157
+ };
158
+ }
159
+
160
+ /** Why Send is refused while attachments are pending, or "" when it is not.
161
+ *
162
+ * An upload still running would be dropped from the message, and a failed one
163
+ * would be sent as if the owner had never picked it — in both cases the
164
+ * assistant answers about a photo it never received. So the send waits, and
165
+ * says what it is waiting for. */
166
+ export function sendBlocker(chips: readonly AriaAttachmentChip[]): "" | "uploading" | "failed" {
167
+ if (chips.some((c) => c.state === "uploading")) return "uploading";
168
+ if (chips.some((c) => c.state === "failed")) return "failed";
169
+ return "";
170
+ }
171
+
172
+ /** The one line a bubble shows for its attachments: a paperclip and the file
173
+ * names. Text, not thumbnails, and not by choice: a `genie-upload://`
174
+ * reference has no published download url, so a sent photo cannot be shown
175
+ * again from the server's copy — and a resumed conversation has nothing else. */
176
+ export function attachmentLine(names: readonly string[]): string {
177
+ const shown = names.map((n) => n.trim()).filter(Boolean);
178
+ return shown.length ? `📎 ${shown.join(", ")}` : "";
179
+ }