@ada-cx/messaging-bridge 1.3.3 → 1.4.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.
@@ -32,6 +32,10 @@ export declare const STATE: {
32
32
  readonly CHAT_IS_SENDING: "chat.isSending";
33
33
  readonly CHAT_MESSAGES: "chat.messages";
34
34
  readonly CHAT_COMPOSER_TEXT: "chat.composerText";
35
+ readonly CHAT_STAGED_ATTACHMENTS: "chat.stagedAttachments";
36
+ /** The newest entry of `chat.stagedAttachments`, for consumers written
37
+ * against the single-image contract. An app reading only this key cannot
38
+ * address the other staged images, and a send posts all of them. */
35
39
  readonly CHAT_STAGED_ATTACHMENT: "chat.stagedAttachment";
36
40
  readonly CHAT_ATTACHMENT_REJECTION: "chat.attachmentRejection";
37
41
  readonly CHAT_IMAGE_UPLOAD_VISIBLE: "chat.imageUploadVisible";
@@ -179,11 +179,19 @@ export interface StagedAttachment {
179
179
  /** Hosted URL, present once `status` is `ready`. */
180
180
  url?: string;
181
181
  }
182
- /** A pick the composer could not stage, kept apart from `chat.stagedAttachment`
183
- * so it never displaces a staged image. Replaced by the next pick. */
182
+ /** A pick the composer could not stage, kept apart from
183
+ * `chat.stagedAttachments` so it never displaces a staged image.
184
+ *
185
+ * Replaced by the next *rejection*, and cleared on a conversation boundary
186
+ * (handoff, rollover, reset). A later successful pick leaves it standing: under
187
+ * `multiple` the app forwards each file as its own stage event, so clearing on
188
+ * a stage would swallow the refusal of a file picked alongside an accepted one.
189
+ * Render it as a transient notice keyed on `id`, not as persistent state. */
184
190
  export interface StagedAttachmentRejection {
185
191
  id: string;
186
- error: "unsupported_type" | "too_large" | "unavailable" | "upload_failed";
192
+ /** `too_many` is new with multi-image staging: an exhaustive switch written
193
+ * against the single-image contract needs a case for it. */
194
+ error: "unsupported_type" | "too_large" | "too_many" | "unavailable" | "upload_failed";
187
195
  }
188
196
  export interface DownloadableMessage extends BaseMessage {
189
197
  type: "downloadable";
@@ -192,6 +200,10 @@ export interface DownloadableMessage extends BaseMessage {
192
200
  mimeType: string | null;
193
201
  /** Text sent with the file, when the chatter typed a message alongside it. */
194
202
  caption?: string;
203
+ /** Shared by every row of one multi-image send, so consecutive rows can be
204
+ * rendered as one group. Absent on a single image: treat that as a group of
205
+ * one rather than assuming the key is always there. */
206
+ attachmentGroupId?: string;
195
207
  }
196
208
  export interface AgentInfo {
197
209
  name: string;
@@ -484,10 +496,16 @@ export interface AppDisplayState {
484
496
  text: string;
485
497
  revision: number;
486
498
  } | null;
487
- /** The image the chatter picked for the next bot send. Hosted as soon as it is
488
- * picked; the composer shows it as a chip until the send consumes it. Absent on
489
- * a core document that predates image attachments. Core keeps the storage key
490
- * to itself. */
499
+ /** The images the chatter picked for the next bot send, in the order they are
500
+ * sent and rendered. Each is hosted as soon as it is picked; the composer shows
501
+ * them until the send consumes them. Absent on a core document that predates
502
+ * multi-image. Core keeps the storage key to itself. */
503
+ "chat.stagedAttachments"?: StagedAttachment[];
504
+ /** The NEWEST entry of `chat.stagedAttachments`, kept so an app written
505
+ * against the single-image contract keeps working — that contract replaced
506
+ * each pick with the next, so this key names what the chatter last chose.
507
+ * Prefer the list: this key cannot represent a second staged image, and a
508
+ * send posts every entry, including the ones it never showed. */
491
509
  "chat.stagedAttachment"?: StagedAttachment | null;
492
510
  /** The most recent pick that could not be staged, beside whatever is staged. */
493
511
  "chat.attachmentRejection"?: StagedAttachmentRejection | null;
@@ -788,9 +806,19 @@ export interface AppEvents {
788
806
  };
789
807
  "file.upload.cancel": undefined;
790
808
  "file.upload.errorDismiss": undefined;
791
- /** Host the picked image for the next bot send. */
809
+ /**
810
+ * Host the picked image for the next bot send.
811
+ *
812
+ * `allowMultiple` is the app's opt-in to the staged LIST. Without it a pick
813
+ * replaces the previous one, which is what an app written against the
814
+ * single-image contract expects: such an app renders
815
+ * `chat.stagedAttachment`, can only remove what it renders, and would
816
+ * otherwise send an image the chatter believes they swapped out. Opt in only
817
+ * once the app reads `chat.stagedAttachments` and can remove any entry.
818
+ */
792
819
  "chat.attachment.stage": {
793
820
  file: File;
821
+ allowMultiple?: boolean;
794
822
  };
795
823
  /** Drop the staged image named by `id`; ignored once another pick replaced it. */
796
824
  "chat.attachment.remove": {
@@ -24,6 +24,22 @@ export type FileUploadErrorReason =
24
24
  /** Size cap of the bot image attachment: api's `MAX_FILE_SIZE_BYTES_FOR_STORAGE_UPLOAD`. */
25
25
  export declare const IMAGE_ATTACHMENT_MAX_MB = 50;
26
26
  export declare const IMAGE_ATTACHMENT_MAX_BYTES: number;
27
+ /**
28
+ * How many images one send may carry.
29
+ *
30
+ * Not an api limit on this path. `MAX_DESCRIBED_IMAGE_ATTACHMENTS` is read in
31
+ * one api runtime site, `resolve_email_image_attachments_suffix`, which is the
32
+ * email channel; the bot path posts one `downloadable` per image and describes
33
+ * each through `resolve_uploaded_file_message_body`, which caps nothing. api
34
+ * also never reads `attachment_group_id` outside analytics, so it cannot batch
35
+ * a group into one describe budget. A fourth image would be hosted, rendered
36
+ * *and* described — in its own reasoner turn.
37
+ *
38
+ * So the cap is a product decision about that cost, not a ceiling api imposes:
39
+ * each extra image buys another bot turn and another describe call. Match it to
40
+ * `MAX_DESCRIBED_IMAGE_ATTACHMENTS` by coincidence of value only.
41
+ */
42
+ export declare const IMAGE_ATTACHMENT_MAX_COUNT = 3;
27
43
  /** The image types api's attachments route accepts; HEIC/HEIF are transcoded to JPEG there. */
28
44
  export declare const IMAGE_ATTACHMENT_MIME_TYPES: readonly string[];
29
45
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ada-cx/messaging-bridge",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "description": "Types, test mocks, and a thin CDN loader for building a custom app UI on Ada Messaging's bridge contract. The bridge runtime always loads from Ada's CDN.",
5
5
  "type": "module",
6
6
  "license": "ISC",