@stackable-labs/sdk-extension-contracts 2.30.0 → 3.0.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.
package/dist/index.d.ts CHANGED
@@ -468,6 +468,396 @@ declare const IDENTITY_CLAIM_MAX_STRING_VALUE_LEN = 256;
468
468
  */
469
469
  type ExtendIdentityHandler = (claims: IdentityBaseClaims) => Record<string, unknown> | Promise<Record<string, unknown>>;
470
470
 
471
+ /**
472
+ * Messaging Contract — all messaging-domain types (events + send capability).
473
+ */
474
+
475
+ /** Messaging context — conversation and app identifiers. */
476
+ interface MessagingContext {
477
+ conversationId?: string | null;
478
+ appId?: string | null;
479
+ }
480
+ /** Messaging event subscription types — 'postback' for all, 'postback:<actionName>' for specific */
481
+ type MessagingEventType = 'postback' | `postback:${string}`;
482
+ /** Normalized postback event payload */
483
+ interface MessagingPostbackEvent {
484
+ eventName: 'postback';
485
+ data: {
486
+ /**
487
+ * The postback button's display text (Zendesk-specific).
488
+ * NOTE: This is NOT an event system field — `eventType` and `eventName` are our event system
489
+ * conventions. `actionName` is a domain-specific payload field identifying which button was
490
+ * clicked, and lives inside `data` alongside other Zendesk messaging fields.
491
+ */
492
+ actionName: string;
493
+ conversationId: string;
494
+ timestamp: ISOTimestamp;
495
+ };
496
+ }
497
+ /** Union of all messaging events (extensible for future event types) */
498
+ type MessagingEvent = MessagingPostbackEvent;
499
+ /** Handler type for useMessagingEvent — use with useCallback for memoized handlers */
500
+ type MessagingEventHandler = (event: MessagingEvent) => void;
501
+ /**
502
+ * Primitives allowed as values in metadata (both message-level and action-level).
503
+ * Sunco rejects nested objects/arrays at the wire layer; total metadata capped at 4KB.
504
+ */
505
+ type ActionMetadataValue = string | number | boolean | null;
506
+ /**
507
+ * Format of a message body. Drives which Sunco wire field the host populates:
508
+ * - 'text' → Sunco `content.text` (plain — default; max 4096 chars)
509
+ * - 'markdown' → Sunco `content.markdownText` (server-converts to htmlText)
510
+ * - 'html' → Sunco `content.htmlText` (max 4096 chars; mutex with markdownText)
511
+ *
512
+ * Sunco auto-converts markdown/html to plain text for channels that don't support
513
+ * rich text — graceful cross-channel fallback.
514
+ */
515
+ type TextFormat = 'text' | 'markdown' | 'html';
516
+ /** Common base — fields available on EVERY message kind. */
517
+ interface BaseMessagePayload {
518
+ /**
519
+ * When true, disables the user's chat input while this is the most recent
520
+ * message in the conversation. Useful for guided / forced-button-response flows.
521
+ * Maps to Sunco `content.blockChatInput`.
522
+ */
523
+ disableUserInput?: boolean;
524
+ /**
525
+ * Caller-supplied metadata. Merged with host-injected `stackable.*` block
526
+ * (extensionId / capabilityCallId / instanceId — non-overridable by extensions).
527
+ * Values are primitives; total ≤4KB. Doesn't render in the Messenger widget.
528
+ */
529
+ metadata?: Record<string, ActionMetadataValue>;
530
+ }
531
+ /**
532
+ * Mixin for message kinds that support a text body + format. Extended by
533
+ * text (required override), and future image/file/carousel (optional caption).
534
+ */
535
+ interface TextEnabledPayload {
536
+ body?: string;
537
+ bodyFormat?: TextFormat;
538
+ }
539
+ /** Common base for all action types — shared label + per-action metadata. */
540
+ interface BaseAction {
541
+ label: string;
542
+ /** Optional flat metadata attached to this action. Primitives only; 4KB cap total. */
543
+ metadata?: Record<string, ActionMetadataValue>;
544
+ }
545
+ /**
546
+ * Reply action — clicking inserts a visible user-reply bubble carrying `payload`
547
+ * back to the conversation, as if the user typed it.
548
+ *
549
+ * MUTUALLY EXCLUSIVE — a `reply` action cannot appear in the same `actions[]`
550
+ * array as any other action type. Sunco returns 400 if mixed. The host validates
551
+ * pre-flight and surfaces `invalid_message` to the extension.
552
+ */
553
+ interface ReplyAction extends BaseAction {
554
+ type: 'reply';
555
+ /** Opaque string. Sunco rejects non-string payloads. For structured data, use `metadata`. */
556
+ payload: string;
557
+ /** Optional icon URL rendered next to the reply pill. */
558
+ iconUrl?: string;
559
+ }
560
+ /**
561
+ * Link action — clicking opens `url` in a new tab/window. No bubble inserted.
562
+ * Freely mixable with other non-reply action types.
563
+ */
564
+ interface LinkAction extends BaseAction {
565
+ type: 'link';
566
+ url: string;
567
+ }
568
+ /**
569
+ * Postback action — clicking fires a server-side `conversation:postback` webhook
570
+ * to the Stackable backend with the full `payload` + any `metadata`. NO visible
571
+ * bubble inserted. Extensions receive postback events via declared event handlers
572
+ * (see `events:messaging` permission). Freely mixable with other non-reply types.
573
+ */
574
+ interface PostbackAction extends BaseAction {
575
+ type: 'postback';
576
+ /** Opaque string. Sunco rejects non-string payloads. For structured data, use `metadata`. */
577
+ payload: string;
578
+ }
579
+ /**
580
+ * Location-request action — prompts the user to share their device location.
581
+ * Response arrives as a separate `location`-type message inbound to the conversation.
582
+ * Freely mixable with other non-reply action types.
583
+ */
584
+ interface LocationRequestAction extends BaseAction {
585
+ type: 'locationRequest';
586
+ }
587
+ /**
588
+ * Union of message-level action types. Used as the type of `actions` on
589
+ * top-level message payloads. For carousel and list ITEMS (future), see
590
+ * `MessageItemAction` (a subset that excludes `reply` and `locationRequest`).
591
+ */
592
+ type MessageAction = ReplyAction | LinkAction | PostbackAction | LocationRequestAction;
593
+ /**
594
+ * Subset of action types valid inside future carousel/list items. Sunco's
595
+ * `actionSubset` schema excludes `reply` and `locationRequest`. Surfaced as a
596
+ * separate type so the SDK compile-time prevents using them where Sunco doesn't.
597
+ */
598
+ type MessageItemAction = LinkAction | PostbackAction;
599
+ /**
600
+ * Text message — plain text body with optional in-message actions.
601
+ *
602
+ * Inherits from:
603
+ * - BaseMessagePayload → disableUserInput, metadata
604
+ * - TextEnabledPayload → body (narrowed to REQUIRED here), bodyFormat
605
+ */
606
+ interface SendTextMessagePayload extends BaseMessagePayload, TextEnabledPayload {
607
+ kind: 'text';
608
+ /**
609
+ * Body text — THE message itself for the `text` kind. Required.
610
+ * Narrows the optional `body` from TextEnabledPayload to required for this kind.
611
+ * Sunco caps at 4096 chars (across all of text/htmlText/markdownText).
612
+ */
613
+ body: string;
614
+ /**
615
+ * Optional in-message actions. Reply actions are mutex with all other types
616
+ * (host validates and surfaces `invalid_message`). Practical max ~10 per message.
617
+ */
618
+ actions?: MessageAction[];
619
+ /**
620
+ * Echoed payload from a prior `reply` action click. Set by the host on inbound
621
+ * messages; not generally set by extension authors on outbound. Maps to Sunco
622
+ * `textMessage.payload`.
623
+ */
624
+ payload?: string;
625
+ }
626
+ /**
627
+ * Image message — embedded image with optional caption + action buttons.
628
+ * Use for product photos, screenshots, visual help / troubleshooting.
629
+ *
630
+ * Inherits from:
631
+ * - BaseMessagePayload → disableUserInput, metadata
632
+ * - TextEnabledPayload → body (optional caption alongside the image), bodyFormat
633
+ *
634
+ * Spec note: Sunco `imageMessage.mediaUrl` has no explicit maxLength in the OpenAPI
635
+ * spec. `altText` is OPTIONAL — Sunco defaults it to the URL's filename if omitted.
636
+ */
637
+ interface SendImageMessagePayload extends BaseMessagePayload, TextEnabledPayload {
638
+ kind: 'image';
639
+ /** Public URL or pre-signed URL. Must respond with Content-Type `image/*`. */
640
+ url: string;
641
+ /**
642
+ * Optional accessibility label, max 128 chars. If omitted, Sunco populates
643
+ * from the URL's filename.
644
+ */
645
+ altText?: string;
646
+ /** Optional in-message actions. Reply-mutex rule applies (see ReplyAction). */
647
+ actions?: MessageAction[];
648
+ }
649
+ /**
650
+ * File message — embedded file attachment (PDF, document, etc.) with optional
651
+ * caption. Use for return labels, receipts, NDAs, referral docs, warranty paperwork.
652
+ *
653
+ * Inherits from:
654
+ * - BaseMessagePayload → disableUserInput, metadata
655
+ * - TextEnabledPayload → body (optional caption alongside the file), bodyFormat
656
+ *
657
+ * Spec note: file messages have NO actions field (Sunco fileMessage schema doesn't
658
+ * support them). `altText` optional, defaults to filename. `mediaSize` + `mediaType`
659
+ * are readonly server-set fields.
660
+ */
661
+ interface SendFileMessagePayload extends BaseMessagePayload, TextEnabledPayload {
662
+ kind: 'file';
663
+ /** Public URL or pre-signed URL. Content-Type drives how Sunco renders the attachment. */
664
+ url: string;
665
+ /**
666
+ * Optional accessibility label, max 128 chars. If omitted, Sunco populates
667
+ * from the URL's filename.
668
+ */
669
+ altText?: string;
670
+ }
671
+ /**
672
+ * Shared item shape used by carousel payloads (and reserved for future list
673
+ * support if/when the Zendesk Messenger Widget adds rendering — see note on
674
+ * SendMessagePayload below). Maps to Sunco's single `item` schema.
675
+ *
676
+ * Spec note: `actions` is REQUIRED with min 1 / max 3 entries, all from the
677
+ * `MessageItemAction` subset (no reply, no locationRequest). The tuple-rest
678
+ * type enforces ≥1 at compile time; max 3 is host-validated.
679
+ */
680
+ interface MessageItem {
681
+ /** Required, 1-128 chars. */
682
+ title: string;
683
+ /** Optional, max 128 chars. */
684
+ description?: string;
685
+ /** Optional image URL, max 2048 chars. */
686
+ imageUrl?: string;
687
+ /** Optional accessibility label, max 128 chars. */
688
+ altText?: string;
689
+ /** Display size for the item's image. Maps to Sunco `item.size`. */
690
+ imageSize?: 'compact' | 'large';
691
+ /** REQUIRED 1-3 actions per item. Subset only — no reply, no locationRequest. */
692
+ actions: [MessageItemAction, ...MessageItemAction[]];
693
+ /** Optional flat metadata, primitives only, 4KB cap. */
694
+ metadata?: Record<string, ActionMetadataValue>;
695
+ }
696
+ /**
697
+ * Carousel message — horizontally scrolling cards. THE conversational-commerce
698
+ * primitive: product recommendations, size/color pickers, search results with
699
+ * images, multi-option selection.
700
+ *
701
+ * Inherits from BaseMessagePayload only — Sunco `carouselMessage` has no
702
+ * settable text body (its `text` field is a readonly server-set fallback for
703
+ * channels that don't render carousels). Use a separate text message before
704
+ * the carousel if you need an intro.
705
+ *
706
+ * Spec note: NO message-level `actions` field — Sunco carouselMessage doesn't
707
+ * define one. Actions live per-card on `items[].actions`. `items` REQUIRED,
708
+ * min 1, max 10.
709
+ */
710
+ interface SendCarouselMessagePayload extends BaseMessagePayload {
711
+ kind: 'carousel';
712
+ /** 1-10 cards. Host validates the cap. */
713
+ items: MessageItem[];
714
+ /** Optional carousel-level display tweaks. */
715
+ displaySettings?: {
716
+ /**
717
+ * How carousel images render. `horizontal` (default) or `square`. Only
718
+ * supported by Facebook Messenger, Web Messenger, Android SDK, iOS SDK;
719
+ * other channels ignore.
720
+ */
721
+ imageAspectRatio?: 'horizontal' | 'square';
722
+ };
723
+ }
724
+ /**
725
+ * Payload for messaging.send capability — discriminated by `kind`.
726
+ */
727
+ type SendMessagePayload = SendTextMessagePayload | SendImageMessagePayload | SendFileMessagePayload | SendCarouselMessagePayload;
728
+ /** Discriminator literals — one per supported kind. */
729
+ type MessagePayloadKind = SendMessagePayload['kind'];
730
+ /**
731
+ * Canonical example payloads — one per kind. Single source of truth for the
732
+ * developer-docs cookbook generator. `satisfies` makes TypeScript verify every
733
+ * example is a valid `SendMessagePayload` AND that every kind has an entry, so
734
+ * adding a new kind (or renaming/removing a field) breaks the build until the
735
+ * example is updated alongside the type.
736
+ */
737
+ declare const MESSAGING_SEND_EXAMPLES: {
738
+ readonly text: {
739
+ readonly kind: "text";
740
+ readonly body: "Order approved ✓";
741
+ readonly actions: [{
742
+ readonly type: "reply";
743
+ readonly label: "Got it";
744
+ readonly payload: "ACK";
745
+ }, {
746
+ readonly type: "reply";
747
+ readonly label: "Show details";
748
+ readonly payload: "DETAILS";
749
+ }];
750
+ };
751
+ readonly image: {
752
+ readonly kind: "image";
753
+ readonly url: "https://cdn.example.com/products/widget-blue.jpg";
754
+ readonly altText: "Blue widget — model A24";
755
+ readonly body: "Here is the product you asked about:";
756
+ readonly actions: [{
757
+ readonly type: "link";
758
+ readonly label: "View on site";
759
+ readonly url: "https://example.com/p/widget-a24";
760
+ }];
761
+ };
762
+ readonly file: {
763
+ readonly kind: "file";
764
+ readonly url: "https://cdn.example.com/receipts/order-12345.pdf";
765
+ readonly altText: "Receipt for order #12345";
766
+ readonly body: "Your receipt is attached.";
767
+ };
768
+ readonly carousel: {
769
+ readonly kind: "carousel";
770
+ readonly items: [{
771
+ readonly title: "Widget A24 — Blue";
772
+ readonly description: "In stock — ships in 1-2 days";
773
+ readonly imageUrl: "https://cdn.example.com/products/widget-blue.jpg";
774
+ readonly actions: [{
775
+ readonly type: "link";
776
+ readonly label: "View";
777
+ readonly url: "https://example.com/p/widget-a24-blue";
778
+ }, {
779
+ readonly type: "postback";
780
+ readonly label: "Add to cart";
781
+ readonly payload: "add_to_cart:widget-a24-blue";
782
+ }];
783
+ }, {
784
+ readonly title: "Widget A24 — Red";
785
+ readonly description: "Limited stock";
786
+ readonly imageUrl: "https://cdn.example.com/products/widget-red.jpg";
787
+ readonly actions: [{
788
+ readonly type: "link";
789
+ readonly label: "View";
790
+ readonly url: "https://example.com/p/widget-a24-red";
791
+ }, {
792
+ readonly type: "postback";
793
+ readonly label: "Add to cart";
794
+ readonly payload: "add_to_cart:widget-a24-red";
795
+ }];
796
+ }];
797
+ readonly displaySettings: {
798
+ readonly imageAspectRatio: "horizontal";
799
+ };
800
+ };
801
+ };
802
+ /**
803
+ * Canonical example actions — one per action type. Single source of truth for
804
+ * the developer-docs cookbook generator. The mapped-type satisfies clause
805
+ * forces each entry to be the SPECIFIC narrowed action (reply must have a
806
+ * payload; locationRequest must not; etc.) AND that every action type
807
+ * literal has an entry, so adding/removing/renaming an action breaks the
808
+ * build until the example is updated alongside the type.
809
+ */
810
+ declare const MESSAGING_ACTION_EXAMPLES: {
811
+ readonly reply: {
812
+ readonly type: "reply";
813
+ readonly label: "Got it";
814
+ readonly payload: "ACK";
815
+ };
816
+ readonly link: {
817
+ readonly type: "link";
818
+ readonly label: "View on site";
819
+ readonly url: "https://example.com/p/widget-a24";
820
+ };
821
+ readonly postback: {
822
+ readonly type: "postback";
823
+ readonly label: "Add to cart";
824
+ readonly payload: "add_to_cart:widget-a24";
825
+ };
826
+ readonly locationRequest: {
827
+ readonly type: "locationRequest";
828
+ readonly label: "Share location";
829
+ };
830
+ };
831
+ /**
832
+ * Response from messaging.send — minimum surface for extensions to correlate
833
+ * with their own UI. Full Sunco response shape intentionally not surfaced.
834
+ */
835
+ interface SendMessageResponse {
836
+ messageId: string;
837
+ /** ISO 8601 — when Sunco persisted the message. */
838
+ receivedAt: string;
839
+ }
840
+ /**
841
+ * Codes that the extension author can meaningfully react to in UI. These are
842
+ * the only codes that surface via the `useMessaging` hook's `state.error` and
843
+ * cause `send()` to throw. End-users can act on each (retry, fix payload,
844
+ * back off rate-limit, retry transient upstream issue). The wider
845
+ * `SendMessageErrorCode` includes host-handled codes that the SDK swallows.
846
+ */
847
+ type SendMessageActionableErrorCode = 'invalid_message' | 'rate_limited' | 'upstream_error';
848
+ /**
849
+ * Full wire taxonomy returned by the host's `messaging.send` capability.
850
+ * Superset of `SendMessageActionableErrorCode` plus host-handled codes that
851
+ * the SDK does NOT surface to extension state:
852
+ * - `no_conversation`: framework logs `console.info`; extension can pre-empt via `useContextData().messaging?.conversationId`
853
+ * - `reauth_required`: framework logs `console.warn`; server flips `messagingDisconnected:true` → admin dashboard surfaces Reconnect UI
854
+ * - `forbidden`: framework logs `console.warn`; extension manifest/permission misconfig — admin/dev resolves
855
+ *
856
+ * Lowercase snake_case to match the existing convention (e.g.
857
+ * `reauth_required` on the reconnect endpoint).
858
+ */
859
+ type SendMessageErrorCode = SendMessageActionableErrorCode | 'no_conversation' | 'reauth_required' | 'forbidden';
860
+
471
861
  /**
472
862
  * Capabilities Contract
473
863
  * Defines the host-mediated APIs that extensions can call via RPC.
@@ -552,11 +942,6 @@ interface ActionInvokePayload {
552
942
  action: InvokeAction;
553
943
  payload?: Record<string, unknown>;
554
944
  }
555
- /** Messaging context — conversation and app identifiers */
556
- interface MessagingContext {
557
- conversationId?: string | null;
558
- appId?: string | null;
559
- }
560
945
  /** Context returned by context.read capability */
561
946
  interface ContextData {
562
947
  customerId?: string;
@@ -606,36 +991,12 @@ type CapabilityCall = {
606
991
  } | {
607
992
  type: 'identity.extend';
608
993
  payload: IdentityExtendPayload;
994
+ } | {
995
+ type: 'messaging.send';
996
+ payload: SendMessagePayload;
609
997
  };
610
998
  type CapabilityType = CapabilityCall['type'];
611
999
 
612
- /**
613
- * Messaging Contract
614
- * Types for the messaging event system (postback buttons, etc.).
615
- */
616
-
617
- /** Messaging event subscription types — 'postback' for all, 'postback:<actionName>' for specific */
618
- type MessagingEventType = 'postback' | `postback:${string}`;
619
- /** Normalized postback event payload */
620
- interface MessagingPostbackEvent {
621
- eventName: 'postback';
622
- data: {
623
- /**
624
- * The postback button's display text (Zendesk-specific).
625
- * NOTE: This is NOT an event system field — `eventType` and `eventName` are our event system
626
- * conventions. `actionName` is a domain-specific payload field identifying which button was
627
- * clicked, and lives inside `data` alongside other Zendesk messaging fields.
628
- */
629
- actionName: string;
630
- conversationId: string;
631
- timestamp: ISOTimestamp;
632
- };
633
- }
634
- /** Union of all messaging events (extensible for future event types) */
635
- type MessagingEvent = MessagingPostbackEvent;
636
- /** Handler type for useMessagingEvent — use with useCallback for memoized handlers */
637
- type MessagingEventHandler = (event: MessagingEvent) => void;
638
-
639
1000
  /**
640
1001
  * Activity Event Contract
641
1002
  * Types for the activity event system (host-to-extension push events).
@@ -690,6 +1051,7 @@ interface InstanceConfig {
690
1051
  identityProvider?: string;
691
1052
  messagingIntegrationId?: string;
692
1053
  messagingAppId?: string;
1054
+ messagingDisplayName?: string;
693
1055
  } & Record<string, unknown>;
694
1056
  secrets?: {
695
1057
  identityKey?: string;
@@ -731,7 +1093,7 @@ interface InstanceOption {
731
1093
  * Extensions declare required permissions in their manifest.
732
1094
  * Host enforces: capability calls must be a subset of granted permissions.
733
1095
  */
734
- declare const PERMISSIONS: readonly ["context:read", "data:query", "data:fetch", "actions:toast", "actions:invoke", "identity:extend", "events:identity", "events:messaging", "events:activity"];
1096
+ declare const PERMISSIONS: readonly ["context:read", "data:query", "data:fetch", "actions:toast", "actions:invoke", "messaging:send", "identity:extend", "events:identity", "events:messaging", "events:activity"];
735
1097
  type Permission = (typeof PERMISSIONS)[number];
736
1098
  /**
737
1099
  * Maps capability types (dot notation, used in code) to the permission
@@ -744,20 +1106,38 @@ declare const CAPABILITY_PERMISSION_MAP: {
744
1106
  readonly 'actions.toast': "actions:toast";
745
1107
  readonly 'actions.invoke': "actions:invoke";
746
1108
  readonly 'identity.extend': "identity:extend";
1109
+ readonly 'messaging.send': "messaging:send";
747
1110
  };
748
1111
  /** Capability key type — dot-notation API names (e.g., 'data.query', 'actions.toast') */
749
1112
  type Capability = keyof typeof CAPABILITY_PERMISSION_MAP;
750
1113
  /**
751
- * Maps event hook names (as used in source code) to the permission required to
752
- * subscribe via that hook.
1114
+ * Maps event-hook names to the permission required to subscribe via that hook.
1115
+ * Use this when iterating event hooks specifically (e.g., docs that talk about
1116
+ * the manifest `events` array, drift guardrails over `## events:*` doc sections).
1117
+ * For broader "any hook → permission" detection, use HOOK_PERMISSION_MAP below.
753
1118
  */
754
1119
  declare const EVENT_HOOK_PERMISSION_MAP: {
755
1120
  readonly useIdentityEvent: "events:identity";
756
1121
  readonly useMessagingEvent: "events:messaging";
757
1122
  readonly useActivityEvent: "events:activity";
758
1123
  };
759
- /** Event-hook key type — hook names (e.g., 'useIdentityEvent', 'useMessagingEvent') */
1124
+ /** Event-hook key type — hook names that subscribe to host events. */
760
1125
  type EventHook = keyof typeof EVENT_HOOK_PERMISSION_MAP;
1126
+ /**
1127
+ * Maps React hook names (as used in source code) to the permission required to
1128
+ * use that hook. Covers event hooks AND non-event hooks (useExtendIdentity,
1129
+ * useMessaging) so static analysis can detect the full author-facing surface.
1130
+ * Composed from EVENT_HOOK_PERMISSION_MAP + the non-event additions.
1131
+ */
1132
+ declare const HOOK_PERMISSION_MAP: {
1133
+ readonly useMessaging: "messaging:send";
1134
+ readonly useExtendIdentity: "identity:extend";
1135
+ readonly useIdentityEvent: "events:identity";
1136
+ readonly useMessagingEvent: "events:messaging";
1137
+ readonly useActivityEvent: "events:activity";
1138
+ };
1139
+ /** Hook key type — React hook names (e.g., 'useIdentityEvent', 'useMessaging'). */
1140
+ type Hook = keyof typeof HOOK_PERMISSION_MAP;
761
1141
 
762
1142
  /**
763
1143
  * Extension Manifest Schema
@@ -908,6 +1288,9 @@ type HostToSandboxMessage = {
908
1288
  } | {
909
1289
  type: 'surface-lifecycle';
910
1290
  data: SurfaceLifecycleMessage;
1291
+ } | {
1292
+ type: 'messaging-lifecycle';
1293
+ enabled: boolean;
911
1294
  } | {
912
1295
  type: 'extension-encryption-key';
913
1296
  encryptionKey: string;
@@ -1166,4 +1549,4 @@ interface Order {
1166
1549
  declare const TEMPLATE_FLAVORS: readonly ["minimal", "starter", "kitchen-sink"];
1167
1550
  type TemplateFlavor = typeof TEMPLATE_FLAVORS[number];
1168
1551
 
1169
- export { ACTIVITY_EVENT, ALLOWED_ICONS, type ActionInvokePayload, type ActionPayloadMap, type ActivityEvent, type ActivityEventHandler, type ActivityEventType, type Address, type AllowedIconName, type ApiError, type ApiRequest, type ApiResponse, CAPABILITY_PERMISSION_MAP, type Capability, type CapabilityCall, type CapabilityRequest, type CapabilityResponse, type CapabilityType, type ContextData, type ConversationField, type ConversationTags, type Customer, type DataField, type DataFieldType, EVENT_HOOK_PERMISSION_MAP, type EncryptedPayload, type EventDomain, type EventHook, type EventType, type ExtendIdentityHandler, type ExtendIdentityRequest, type ExtendIdentityResponse, type ExtensionGroup, type ExtensionManifest, type ExtensionRegistryEntry, type FetchRequest, type FetchRequestInit, type FetchResponse, type HostToSandboxMessage, IDENTITY_CLAIMS_MAX_KEYS, IDENTITY_CLAIM_KEY_PATTERN, IDENTITY_CLAIM_MAX_STRING_VALUE_LEN, IDENTITY_EVENT, INVOKE_ACTION, type IdentityBaseClaims, type IdentityEvent, type IdentityEventType, type IdentityExtendPayload, type IdentityExtendResponse, type IdentityState, type InstanceConfig, type InstanceOption, type InvokeAction, type MarketplaceExtension, type MessagingContext, type MessagingEvent, type MessagingEventHandler, type MessagingEventType, type MessagingPostbackEvent, type MessengerCommand, type NamedEntity, type NewConversationPayload, type Order, type OrderAction, type OrderItem, type OrderStatus, type OrderStatuses, PERMISSIONS, type Permission, type Price, RESERVED_CONTEXT_KEYS, RESERVED_IDENTITY_CLAIM_KEYS, type ReservedContextKey, STANDARD_IDENTITY_CLAIM_KEYS, SURFACE_TARGET, type SandboxToHostMessage, type Shipment, type SurfaceContext, type SurfaceLifecycleMessage, type SurfaceTarget, TEMPLATE_FLAVORS, type Target, type TemplateFlavor, type Theme, type ToastPayload, type UITag, type UITagCategory, UI_TAGS, UI_TAG_ATTRIBUTES, UI_TAG_ATTRIBUTE_VALUES, UI_TAG_CATEGORIES, UI_TAG_CHILDREN, UI_TAG_CHILD_ONLY, UI_TAG_COMPOUND, UI_TAG_DEFINITIONS, UI_TAG_SELF_CLOSING, type UserIdentity, type WellKnownActivityEvent, type WidgetAction, tagToComponentName };
1552
+ export { ACTIVITY_EVENT, ALLOWED_ICONS, type ActionInvokePayload, type ActionMetadataValue, type ActionPayloadMap, type ActivityEvent, type ActivityEventHandler, type ActivityEventType, type Address, type AllowedIconName, type ApiError, type ApiRequest, type ApiResponse, type BaseAction, type BaseMessagePayload, CAPABILITY_PERMISSION_MAP, type Capability, type CapabilityCall, type CapabilityRequest, type CapabilityResponse, type CapabilityType, type ContextData, type ConversationField, type ConversationTags, type Customer, type DataField, type DataFieldType, EVENT_HOOK_PERMISSION_MAP, type EncryptedPayload, type EventDomain, type EventHook, type EventType, type ExtendIdentityHandler, type ExtendIdentityRequest, type ExtendIdentityResponse, type ExtensionGroup, type ExtensionManifest, type ExtensionRegistryEntry, type FetchRequest, type FetchRequestInit, type FetchResponse, HOOK_PERMISSION_MAP, type Hook, type HostToSandboxMessage, IDENTITY_CLAIMS_MAX_KEYS, IDENTITY_CLAIM_KEY_PATTERN, IDENTITY_CLAIM_MAX_STRING_VALUE_LEN, IDENTITY_EVENT, INVOKE_ACTION, type IdentityBaseClaims, type IdentityEvent, type IdentityEventType, type IdentityExtendPayload, type IdentityExtendResponse, type IdentityState, type InstanceConfig, type InstanceOption, type InvokeAction, type LinkAction, type LocationRequestAction, MESSAGING_ACTION_EXAMPLES, MESSAGING_SEND_EXAMPLES, type MarketplaceExtension, type MessageAction, type MessageItem, type MessageItemAction, type MessagePayloadKind, type MessagingContext, type MessagingEvent, type MessagingEventHandler, type MessagingEventType, type MessagingPostbackEvent, type MessengerCommand, type NamedEntity, type NewConversationPayload, type Order, type OrderAction, type OrderItem, type OrderStatus, type OrderStatuses, PERMISSIONS, type Permission, type PostbackAction, type Price, RESERVED_CONTEXT_KEYS, RESERVED_IDENTITY_CLAIM_KEYS, type ReplyAction, type ReservedContextKey, STANDARD_IDENTITY_CLAIM_KEYS, SURFACE_TARGET, type SandboxToHostMessage, type SendCarouselMessagePayload, type SendFileMessagePayload, type SendImageMessagePayload, type SendMessageActionableErrorCode, type SendMessageErrorCode, type SendMessagePayload, type SendMessageResponse, type SendTextMessagePayload, type Shipment, type SurfaceContext, type SurfaceLifecycleMessage, type SurfaceTarget, TEMPLATE_FLAVORS, type Target, type TemplateFlavor, type TextEnabledPayload, type TextFormat, type Theme, type ToastPayload, type UITag, type UITagCategory, UI_TAGS, UI_TAG_ATTRIBUTES, UI_TAG_ATTRIBUTE_VALUES, UI_TAG_CATEGORIES, UI_TAG_CHILDREN, UI_TAG_CHILD_ONLY, UI_TAG_COMPOUND, UI_TAG_DEFINITIONS, UI_TAG_SELF_CLOSING, type UserIdentity, type WellKnownActivityEvent, type WidgetAction, tagToComponentName };
package/dist/index.js CHANGED
@@ -427,6 +427,63 @@ var IDENTITY_CLAIM_KEY_PATTERN = /^[a-z_][a-z0-9_]{0,63}$/;
427
427
  var IDENTITY_CLAIMS_MAX_KEYS = 20;
428
428
  var IDENTITY_CLAIM_MAX_STRING_VALUE_LEN = 256;
429
429
 
430
+ // src/messaging.ts
431
+ var MESSAGING_SEND_EXAMPLES = {
432
+ text: {
433
+ kind: "text",
434
+ body: "Order approved \u2713",
435
+ actions: [
436
+ { type: "reply", label: "Got it", payload: "ACK" },
437
+ { type: "reply", label: "Show details", payload: "DETAILS" }
438
+ ]
439
+ },
440
+ image: {
441
+ kind: "image",
442
+ url: "https://cdn.example.com/products/widget-blue.jpg",
443
+ altText: "Blue widget \u2014 model A24",
444
+ body: "Here is the product you asked about:",
445
+ actions: [
446
+ { type: "link", label: "View on site", url: "https://example.com/p/widget-a24" }
447
+ ]
448
+ },
449
+ file: {
450
+ kind: "file",
451
+ url: "https://cdn.example.com/receipts/order-12345.pdf",
452
+ altText: "Receipt for order #12345",
453
+ body: "Your receipt is attached."
454
+ },
455
+ carousel: {
456
+ kind: "carousel",
457
+ items: [
458
+ {
459
+ title: "Widget A24 \u2014 Blue",
460
+ description: "In stock \u2014 ships in 1-2 days",
461
+ imageUrl: "https://cdn.example.com/products/widget-blue.jpg",
462
+ actions: [
463
+ { type: "link", label: "View", url: "https://example.com/p/widget-a24-blue" },
464
+ { type: "postback", label: "Add to cart", payload: "add_to_cart:widget-a24-blue" }
465
+ ]
466
+ },
467
+ {
468
+ title: "Widget A24 \u2014 Red",
469
+ description: "Limited stock",
470
+ imageUrl: "https://cdn.example.com/products/widget-red.jpg",
471
+ actions: [
472
+ { type: "link", label: "View", url: "https://example.com/p/widget-a24-red" },
473
+ { type: "postback", label: "Add to cart", payload: "add_to_cart:widget-a24-red" }
474
+ ]
475
+ }
476
+ ],
477
+ displaySettings: { imageAspectRatio: "horizontal" }
478
+ }
479
+ };
480
+ var MESSAGING_ACTION_EXAMPLES = {
481
+ reply: { type: "reply", label: "Got it", payload: "ACK" },
482
+ link: { type: "link", label: "View on site", url: "https://example.com/p/widget-a24" },
483
+ postback: { type: "postback", label: "Add to cart", payload: "add_to_cart:widget-a24" },
484
+ locationRequest: { type: "locationRequest", label: "Share location" }
485
+ };
486
+
430
487
  // src/activity.ts
431
488
  var ACTIVITY_EVENT = {
432
489
  CLICK: "click",
@@ -445,6 +502,7 @@ var PERMISSIONS = [
445
502
  "data:fetch",
446
503
  "actions:toast",
447
504
  "actions:invoke",
505
+ "messaging:send",
448
506
  "identity:extend",
449
507
  "events:identity",
450
508
  "events:messaging",
@@ -456,13 +514,19 @@ var CAPABILITY_PERMISSION_MAP = {
456
514
  "data.fetch": "data:fetch",
457
515
  "actions.toast": "actions:toast",
458
516
  "actions.invoke": "actions:invoke",
459
- "identity.extend": "identity:extend"
517
+ "identity.extend": "identity:extend",
518
+ "messaging.send": "messaging:send"
460
519
  };
461
520
  var EVENT_HOOK_PERMISSION_MAP = {
462
521
  useIdentityEvent: "events:identity",
463
522
  useMessagingEvent: "events:messaging",
464
523
  useActivityEvent: "events:activity"
465
524
  };
525
+ var HOOK_PERMISSION_MAP = {
526
+ ...EVENT_HOOK_PERMISSION_MAP,
527
+ useMessaging: "messaging:send",
528
+ useExtendIdentity: "identity:extend"
529
+ };
466
530
 
467
531
  // src/manifest.ts
468
532
  var SURFACE_TARGET = {
@@ -475,4 +539,4 @@ var SURFACE_TARGET = {
475
539
  // src/scaffold.ts
476
540
  var TEMPLATE_FLAVORS = ["minimal", "starter", "kitchen-sink"];
477
541
 
478
- export { ACTIVITY_EVENT, ALLOWED_ICONS, CAPABILITY_PERMISSION_MAP, EVENT_HOOK_PERMISSION_MAP, EXTENSION_CATEGORY, EXTENSION_VISIBILITY, IDENTITY_CLAIMS_MAX_KEYS, IDENTITY_CLAIM_KEY_PATTERN, IDENTITY_CLAIM_MAX_STRING_VALUE_LEN, IDENTITY_EVENT, INVOKE_ACTION, PERMISSIONS, RESERVED_CONTEXT_KEYS, RESERVED_IDENTITY_CLAIM_KEYS, STANDARD_IDENTITY_CLAIM_KEYS, SURFACE_TARGET, TEMPLATE_FLAVORS, UI_TAGS, UI_TAG_ATTRIBUTES, UI_TAG_ATTRIBUTE_VALUES, UI_TAG_CATEGORIES, UI_TAG_CHILDREN, UI_TAG_CHILD_ONLY, UI_TAG_COMPOUND, UI_TAG_DEFINITIONS, UI_TAG_SELF_CLOSING, asClerkOrgId, asClerkUserId, asISOTimestamp, tagToComponentName };
542
+ export { ACTIVITY_EVENT, ALLOWED_ICONS, CAPABILITY_PERMISSION_MAP, EVENT_HOOK_PERMISSION_MAP, EXTENSION_CATEGORY, EXTENSION_VISIBILITY, HOOK_PERMISSION_MAP, IDENTITY_CLAIMS_MAX_KEYS, IDENTITY_CLAIM_KEY_PATTERN, IDENTITY_CLAIM_MAX_STRING_VALUE_LEN, IDENTITY_EVENT, INVOKE_ACTION, MESSAGING_ACTION_EXAMPLES, MESSAGING_SEND_EXAMPLES, PERMISSIONS, RESERVED_CONTEXT_KEYS, RESERVED_IDENTITY_CLAIM_KEYS, STANDARD_IDENTITY_CLAIM_KEYS, SURFACE_TARGET, TEMPLATE_FLAVORS, UI_TAGS, UI_TAG_ATTRIBUTES, UI_TAG_ATTRIBUTE_VALUES, UI_TAG_CATEGORIES, UI_TAG_CHILDREN, UI_TAG_CHILD_ONLY, UI_TAG_COMPOUND, UI_TAG_DEFINITIONS, UI_TAG_SELF_CLOSING, asClerkOrgId, asClerkUserId, asISOTimestamp, tagToComponentName };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackable-labs/sdk-extension-contracts",
3
- "version": "2.30.0",
3
+ "version": "3.0.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "private": false,