saasco-sdk 0.1.44 → 0.2.3

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.
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Iframe-side half of the cross-origin bridge. Runs inside the Saasco
3
+ * `/embed/support-chat` page and talks to the host page's loader over
4
+ * `postMessage`:
5
+ *
6
+ * - inbound host messages (boot/identify/updateJwt/setStateSnapshot/viewport/
7
+ * open/close) are validated by `event.origin` against the project's trusted
8
+ * domains, then written into the {@link registry} the live widget subscribes to;
9
+ * - outbound round-trips (page-context lookups, host-registered client tools) are
10
+ * promise-based with a `requestId` and a per-call timeout so a missing or slow
11
+ * host handler can never hang a streaming turn.
12
+ *
13
+ * The first valid inbound message pins the parent origin; every reply targets
14
+ * that pinned origin (never `"*"`). The initial `ready` and any pre-boot resize
15
+ * carry no secrets, so they fall back to `"*"` until the origin is known.
16
+ */
17
+
18
+ /**
19
+ * Wires the message listener and announces readiness. Idempotent. `allowedOrigins`
20
+ * is the project's trusted-domain allowlist plus the Saasco origin itself (so
21
+ * same-origin dogfooding works); patterns accept full origins, bare hosts and
22
+ * `*.example.com` wildcards (see `matchesOriginPattern`).
23
+ */
24
+ declare function initEmbedBridge(options: {
25
+ allowedOrigins: string[];
26
+ }): void;
27
+
28
+ /** Snapshot of host-app state appended to the agent's system prompt each turn. */
29
+ declare function setStateSnapshot(snapshot: unknown): void;
30
+
31
+ /**
32
+ * Public types for the embeddable support chat widget. These restate the
33
+ * server wire contracts (`libs/support/shared` / `libs/chat/shared`) locally
34
+ * so the published package carries zero workspace dependencies.
35
+ */
36
+ /**
37
+ * A minimal structural JSON Schema object describing a tool's arguments. It is
38
+ * declared locally (no `json-schema` package import) so the published SDK stays
39
+ * dependency-free. The root must be a `type: "object"` schema; additional JSON
40
+ * Schema keywords (`$schema`, `$defs`, …) are allowed via the index signature.
41
+ */
42
+ type JSONSchema7Object = {
43
+ additionalProperties?: boolean | Record<string, unknown>;
44
+ properties?: Record<string, unknown>;
45
+ required?: string[];
46
+ type: "object";
47
+ [key: string]: unknown;
48
+ };
49
+ /**
50
+ * The runtime shape of a tool the support widget can run in the browser. Tools
51
+ * are authored in the dashboard (stored in `Meta`) and served by the public
52
+ * settings endpoint as a `PublicChatTool`, which the widget rebuilds into this
53
+ * shape via `reconstructDashboardTool`.
54
+ *
55
+ * `execute` runs in the host app's browser when the agent calls a host tool
56
+ * and may touch in-page state, mutations, or SDKs. Server tools (dashboard
57
+ * `execution: "server"`) are proxied by the agent instead and never reach the
58
+ * widget; the reconstructed `execute` is only a same-origin `credentials:
59
+ * "include"` fallback. Tools marked `destructive` pause for an explicit
60
+ * Approve/Reject before running.
61
+ */
62
+ type SupportChatTool = {
63
+ /** Shown to the model; 1–2000 chars. */
64
+ description: string;
65
+ /** Pauses for an explicit Approve/Reject before running. */
66
+ destructive?: boolean;
67
+ /**
68
+ * Where the call runs. `"host"` round-trips to the host page's loader, which
69
+ * runs the consumer's `registerTool` handler in the host realm; `"server"` is
70
+ * run by the agent (proxied to `endpoint`), so the widget never calls
71
+ * `execute` for it. Destructive tools always run host-side behind the
72
+ * approval gate.
73
+ */
74
+ execution?: "host" | "server";
75
+ /**
76
+ * REST URL template for server-proxied or host-executed HTTP tools. Ignored
77
+ * for in-browser-only tools.
78
+ */
79
+ endpoint?: string;
80
+ execute: (args: Record<string, unknown>) => Promise<unknown> | unknown;
81
+ /** JSON Schema (object) for the args; travels over the wire to the agent. */
82
+ inputSchema: JSONSchema7Object;
83
+ /** HTTP method for REST execution. */
84
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
85
+ /** Display name shown in the dashboard and chat UI. */
86
+ name: string;
87
+ /**
88
+ * Parameter names filled from visitor context at call time — not supplied by
89
+ * the model. See `getStateSnapshot` on {@link WidgetConfig}.
90
+ */
91
+ contextParameters?: string[];
92
+ };
93
+ /** A canned prompt offered in the empty state; clicking it fills the input. */
94
+ type SupportChatSuggestion = {
95
+ /** Optional second line shown under the label. */
96
+ description?: string;
97
+ label: string;
98
+ /** The text placed in the input when the suggestion is picked. */
99
+ prompt: string;
100
+ };
101
+ type WidgetConfig = {
102
+ /** Origin of the saasco app hosting the support-chat API, e.g. https://app.example.com */
103
+ baseUrl: string;
104
+ /** Read at submit time and appended to the agent's system prompt. */
105
+ getStateSnapshot?: () => unknown;
106
+ /** Input placeholder. */
107
+ placeholder?: string;
108
+ projectId: string;
109
+ /** Canned prompts offered before the first message. */
110
+ suggestions?: SupportChatSuggestion[];
111
+ };
112
+
113
+ /**
114
+ * Plain-fetch transport for the public support-chat REST endpoints. The
115
+ * embedding origin must be on the project's allowlist (configured in the
116
+ * support widget settings) for cross-origin calls to pass CORS.
117
+ */
118
+
119
+ type ChatSession = {
120
+ attachments?: ConversationImageAttachment[];
121
+ conversationId: string;
122
+ sessionToken: string;
123
+ };
124
+ type ConversationImageAttachment = {
125
+ contentType?: string;
126
+ fileName?: string;
127
+ url: string;
128
+ };
129
+ type ChatThreadMessage = {
130
+ attachments?: ConversationImageAttachment[];
131
+ /** Replier's first name — present for `role: "team"` (human) messages only. */
132
+ authorName?: string;
133
+ /** Rich body (HTML when from email); not shown in the widget. */
134
+ content: string | null;
135
+ createdAt: number;
136
+ id: string;
137
+ /** Resolved help-center sources referenced by `[[kb:…]]` markers in plainBody. */
138
+ kbCitations?: {
139
+ id: string;
140
+ title: string;
141
+ url: string;
142
+ }[];
143
+ /** Plain-text body for bubbles and session previews. */
144
+ plainBody: string | null;
145
+ role: "user" | "team" | "bot";
146
+ };
147
+ type ChatThread = {
148
+ /** False while a human has taken over — the widget goes persist-only. */
149
+ agentEnabled: boolean;
150
+ conversationId: string;
151
+ messages: ChatThreadMessage[];
152
+ state: "open" | "closed" | "snoozed";
153
+ };
154
+
155
+ /**
156
+ * Embeddable customer-facing support chat for third-party apps — an
157
+ * Intercom-style messenger (Home + Messages tabs, branded workspace rows, a
158
+ * restyled chat with a workspace header and per-message meta lines) on top of the
159
+ * persisted support channel:
160
+ *
161
+ * - the customer talks to a streaming AI support agent that can call the
162
+ * project's dashboard-configured tools (loaded from the public settings
163
+ * endpoint), with an Approve/Reject gate for tools marked `destructive`,
164
+ * - an email gate captures a reply-to address before the first message when the
165
+ * host app hasn't already identified the visitor; every message is persisted
166
+ * into the saasco support inbox under `projectId`, with human replies merged
167
+ * into the open chat by polling the thread endpoint, and
168
+ * - once a human takes the conversation over the agent stream is muted, the
169
+ * customer sees a handoff acknowledgment, a "Waiting for a teammate" indicator
170
+ * until someone replies, then "{name} has joined the conversation" above the
171
+ * first team message.
172
+ *
173
+ * The per-conversation session token (and the captured email) are persisted in
174
+ * the Saasco iframe-origin `localStorage` so anonymous threads survive reloads
175
+ * (best-effort — Safari/strict-Firefox partition third-party storage; identified
176
+ * users resume server-side via the JWT instead). This component is the iframe
177
+ * app entry: it renders directly into the `/embed/support-chat` page (no host-
178
+ * realm blank-iframe wrapper), and the host integrates over the postMessage
179
+ * bridge — identity, JWT, state snapshots, viewport and open/close all arrive
180
+ * through {@link initEmbedBridge} and are read here from the registry.
181
+ */
182
+ declare function SupportChatWidgetInner({ baseUrl, getStateSnapshot, placeholder, projectId, suggestions, }: WidgetConfig): React.ReactElement;
183
+
184
+ export { type ChatSession, type ChatThread, type ChatThreadMessage, type JSONSchema7Object, type SupportChatSuggestion, type SupportChatTool, SupportChatWidgetInner, type WidgetConfig, initEmbedBridge, setStateSnapshot };
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Iframe-side half of the cross-origin bridge. Runs inside the Saasco
3
+ * `/embed/support-chat` page and talks to the host page's loader over
4
+ * `postMessage`:
5
+ *
6
+ * - inbound host messages (boot/identify/updateJwt/setStateSnapshot/viewport/
7
+ * open/close) are validated by `event.origin` against the project's trusted
8
+ * domains, then written into the {@link registry} the live widget subscribes to;
9
+ * - outbound round-trips (page-context lookups, host-registered client tools) are
10
+ * promise-based with a `requestId` and a per-call timeout so a missing or slow
11
+ * host handler can never hang a streaming turn.
12
+ *
13
+ * The first valid inbound message pins the parent origin; every reply targets
14
+ * that pinned origin (never `"*"`). The initial `ready` and any pre-boot resize
15
+ * carry no secrets, so they fall back to `"*"` until the origin is known.
16
+ */
17
+
18
+ /**
19
+ * Wires the message listener and announces readiness. Idempotent. `allowedOrigins`
20
+ * is the project's trusted-domain allowlist plus the Saasco origin itself (so
21
+ * same-origin dogfooding works); patterns accept full origins, bare hosts and
22
+ * `*.example.com` wildcards (see `matchesOriginPattern`).
23
+ */
24
+ declare function initEmbedBridge(options: {
25
+ allowedOrigins: string[];
26
+ }): void;
27
+
28
+ /** Snapshot of host-app state appended to the agent's system prompt each turn. */
29
+ declare function setStateSnapshot(snapshot: unknown): void;
30
+
31
+ /**
32
+ * Public types for the embeddable support chat widget. These restate the
33
+ * server wire contracts (`libs/support/shared` / `libs/chat/shared`) locally
34
+ * so the published package carries zero workspace dependencies.
35
+ */
36
+ /**
37
+ * A minimal structural JSON Schema object describing a tool's arguments. It is
38
+ * declared locally (no `json-schema` package import) so the published SDK stays
39
+ * dependency-free. The root must be a `type: "object"` schema; additional JSON
40
+ * Schema keywords (`$schema`, `$defs`, …) are allowed via the index signature.
41
+ */
42
+ type JSONSchema7Object = {
43
+ additionalProperties?: boolean | Record<string, unknown>;
44
+ properties?: Record<string, unknown>;
45
+ required?: string[];
46
+ type: "object";
47
+ [key: string]: unknown;
48
+ };
49
+ /**
50
+ * The runtime shape of a tool the support widget can run in the browser. Tools
51
+ * are authored in the dashboard (stored in `Meta`) and served by the public
52
+ * settings endpoint as a `PublicChatTool`, which the widget rebuilds into this
53
+ * shape via `reconstructDashboardTool`.
54
+ *
55
+ * `execute` runs in the host app's browser when the agent calls a host tool
56
+ * and may touch in-page state, mutations, or SDKs. Server tools (dashboard
57
+ * `execution: "server"`) are proxied by the agent instead and never reach the
58
+ * widget; the reconstructed `execute` is only a same-origin `credentials:
59
+ * "include"` fallback. Tools marked `destructive` pause for an explicit
60
+ * Approve/Reject before running.
61
+ */
62
+ type SupportChatTool = {
63
+ /** Shown to the model; 1–2000 chars. */
64
+ description: string;
65
+ /** Pauses for an explicit Approve/Reject before running. */
66
+ destructive?: boolean;
67
+ /**
68
+ * Where the call runs. `"host"` round-trips to the host page's loader, which
69
+ * runs the consumer's `registerTool` handler in the host realm; `"server"` is
70
+ * run by the agent (proxied to `endpoint`), so the widget never calls
71
+ * `execute` for it. Destructive tools always run host-side behind the
72
+ * approval gate.
73
+ */
74
+ execution?: "host" | "server";
75
+ /**
76
+ * REST URL template for server-proxied or host-executed HTTP tools. Ignored
77
+ * for in-browser-only tools.
78
+ */
79
+ endpoint?: string;
80
+ execute: (args: Record<string, unknown>) => Promise<unknown> | unknown;
81
+ /** JSON Schema (object) for the args; travels over the wire to the agent. */
82
+ inputSchema: JSONSchema7Object;
83
+ /** HTTP method for REST execution. */
84
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
85
+ /** Display name shown in the dashboard and chat UI. */
86
+ name: string;
87
+ /**
88
+ * Parameter names filled from visitor context at call time — not supplied by
89
+ * the model. See `getStateSnapshot` on {@link WidgetConfig}.
90
+ */
91
+ contextParameters?: string[];
92
+ };
93
+ /** A canned prompt offered in the empty state; clicking it fills the input. */
94
+ type SupportChatSuggestion = {
95
+ /** Optional second line shown under the label. */
96
+ description?: string;
97
+ label: string;
98
+ /** The text placed in the input when the suggestion is picked. */
99
+ prompt: string;
100
+ };
101
+ type WidgetConfig = {
102
+ /** Origin of the saasco app hosting the support-chat API, e.g. https://app.example.com */
103
+ baseUrl: string;
104
+ /** Read at submit time and appended to the agent's system prompt. */
105
+ getStateSnapshot?: () => unknown;
106
+ /** Input placeholder. */
107
+ placeholder?: string;
108
+ projectId: string;
109
+ /** Canned prompts offered before the first message. */
110
+ suggestions?: SupportChatSuggestion[];
111
+ };
112
+
113
+ /**
114
+ * Plain-fetch transport for the public support-chat REST endpoints. The
115
+ * embedding origin must be on the project's allowlist (configured in the
116
+ * support widget settings) for cross-origin calls to pass CORS.
117
+ */
118
+
119
+ type ChatSession = {
120
+ attachments?: ConversationImageAttachment[];
121
+ conversationId: string;
122
+ sessionToken: string;
123
+ };
124
+ type ConversationImageAttachment = {
125
+ contentType?: string;
126
+ fileName?: string;
127
+ url: string;
128
+ };
129
+ type ChatThreadMessage = {
130
+ attachments?: ConversationImageAttachment[];
131
+ /** Replier's first name — present for `role: "team"` (human) messages only. */
132
+ authorName?: string;
133
+ /** Rich body (HTML when from email); not shown in the widget. */
134
+ content: string | null;
135
+ createdAt: number;
136
+ id: string;
137
+ /** Resolved help-center sources referenced by `[[kb:…]]` markers in plainBody. */
138
+ kbCitations?: {
139
+ id: string;
140
+ title: string;
141
+ url: string;
142
+ }[];
143
+ /** Plain-text body for bubbles and session previews. */
144
+ plainBody: string | null;
145
+ role: "user" | "team" | "bot";
146
+ };
147
+ type ChatThread = {
148
+ /** False while a human has taken over — the widget goes persist-only. */
149
+ agentEnabled: boolean;
150
+ conversationId: string;
151
+ messages: ChatThreadMessage[];
152
+ state: "open" | "closed" | "snoozed";
153
+ };
154
+
155
+ /**
156
+ * Embeddable customer-facing support chat for third-party apps — an
157
+ * Intercom-style messenger (Home + Messages tabs, branded workspace rows, a
158
+ * restyled chat with a workspace header and per-message meta lines) on top of the
159
+ * persisted support channel:
160
+ *
161
+ * - the customer talks to a streaming AI support agent that can call the
162
+ * project's dashboard-configured tools (loaded from the public settings
163
+ * endpoint), with an Approve/Reject gate for tools marked `destructive`,
164
+ * - an email gate captures a reply-to address before the first message when the
165
+ * host app hasn't already identified the visitor; every message is persisted
166
+ * into the saasco support inbox under `projectId`, with human replies merged
167
+ * into the open chat by polling the thread endpoint, and
168
+ * - once a human takes the conversation over the agent stream is muted, the
169
+ * customer sees a handoff acknowledgment, a "Waiting for a teammate" indicator
170
+ * until someone replies, then "{name} has joined the conversation" above the
171
+ * first team message.
172
+ *
173
+ * The per-conversation session token (and the captured email) are persisted in
174
+ * the Saasco iframe-origin `localStorage` so anonymous threads survive reloads
175
+ * (best-effort — Safari/strict-Firefox partition third-party storage; identified
176
+ * users resume server-side via the JWT instead). This component is the iframe
177
+ * app entry: it renders directly into the `/embed/support-chat` page (no host-
178
+ * realm blank-iframe wrapper), and the host integrates over the postMessage
179
+ * bridge — identity, JWT, state snapshots, viewport and open/close all arrive
180
+ * through {@link initEmbedBridge} and are read here from the registry.
181
+ */
182
+ declare function SupportChatWidgetInner({ baseUrl, getStateSnapshot, placeholder, projectId, suggestions, }: WidgetConfig): React.ReactElement;
183
+
184
+ export { type ChatSession, type ChatThread, type ChatThreadMessage, type JSONSchema7Object, type SupportChatSuggestion, type SupportChatTool, SupportChatWidgetInner, type WidgetConfig, initEmbedBridge, setStateSnapshot };