saasco-sdk 0.2.3 → 0.2.5
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/README.md +974 -0
- package/dist/index.cjs +189 -138
- package/dist/index.d.cts +45 -57
- package/dist/index.d.ts +45 -57
- package/dist/index.js +188 -137
- package/dist/{support-chat.cjs → support.cjs} +3579 -2088
- package/dist/{support-chat.d.cts → support.d.cts} +39 -29
- package/dist/{support-chat.d.ts → support.d.ts} +39 -29
- package/dist/{support-chat.js → support.js} +3526 -2035
- package/package.json +34 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Iframe-side half of the cross-origin bridge. Runs inside the Saasco
|
|
3
|
-
* `/embed/support
|
|
3
|
+
* `/embed/support` page and talks to the host page's loader over
|
|
4
4
|
* `postMessage`:
|
|
5
5
|
*
|
|
6
6
|
* - inbound host messages (boot/identify/updateJwt/setStateSnapshot/viewport/
|
|
@@ -25,11 +25,8 @@ declare function initEmbedBridge(options: {
|
|
|
25
25
|
allowedOrigins: string[];
|
|
26
26
|
}): void;
|
|
27
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
28
|
/**
|
|
32
|
-
* Public types for the embeddable support
|
|
29
|
+
* Public types for the embeddable support widget. These restate the
|
|
33
30
|
* server wire contracts (`libs/support/shared` / `libs/chat/shared`) locally
|
|
34
31
|
* so the published package carries zero workspace dependencies.
|
|
35
32
|
*/
|
|
@@ -49,18 +46,17 @@ type JSONSchema7Object = {
|
|
|
49
46
|
/**
|
|
50
47
|
* The runtime shape of a tool the support widget can run in the browser. Tools
|
|
51
48
|
* are authored in the dashboard (stored in `Meta`) and served by the public
|
|
52
|
-
* settings endpoint as a `
|
|
49
|
+
* settings endpoint as a `PublicSupportTool`, which the widget rebuilds into this
|
|
53
50
|
* shape via `reconstructDashboardTool`.
|
|
54
51
|
*
|
|
55
52
|
* `execute` runs in the host app's browser when the agent calls a host tool
|
|
56
53
|
* and may touch in-page state, mutations, or SDKs. Server tools (dashboard
|
|
57
|
-
* `execution: "server"`) are proxied by the agent instead
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Approve/Reject before running.
|
|
54
|
+
* `execution: "server"`) are proxied by the agent instead — the widget must
|
|
55
|
+
* not browser-fetch their absolute endpoints (that causes CORS noise). Tools
|
|
56
|
+
* marked `destructive` pause for an explicit Approve/Reject before running.
|
|
61
57
|
*/
|
|
62
|
-
type
|
|
63
|
-
/** Shown to the model
|
|
58
|
+
type SupportTool = {
|
|
59
|
+
/** Shown to the model. Active tools require a non-empty description. */
|
|
64
60
|
description: string;
|
|
65
61
|
/** Pauses for an explicit Approve/Reject before running. */
|
|
66
62
|
destructive?: boolean;
|
|
@@ -91,7 +87,7 @@ type SupportChatTool = {
|
|
|
91
87
|
contextParameters?: string[];
|
|
92
88
|
};
|
|
93
89
|
/** A canned prompt offered in the empty state; clicking it fills the input. */
|
|
94
|
-
type
|
|
90
|
+
type SupportSuggestion = {
|
|
95
91
|
/** Optional second line shown under the label. */
|
|
96
92
|
description?: string;
|
|
97
93
|
label: string;
|
|
@@ -99,24 +95,26 @@ type SupportChatSuggestion = {
|
|
|
99
95
|
prompt: string;
|
|
100
96
|
};
|
|
101
97
|
type WidgetConfig = {
|
|
102
|
-
/** Origin of the saasco app hosting the support
|
|
98
|
+
/** Origin of the saasco app hosting the support API, e.g. https://app.example.com */
|
|
103
99
|
baseUrl: string;
|
|
104
100
|
/** Read at submit time and appended to the agent's system prompt. */
|
|
105
101
|
getStateSnapshot?: () => unknown;
|
|
106
102
|
/** Input placeholder. */
|
|
107
103
|
placeholder?: string;
|
|
108
104
|
projectId: string;
|
|
105
|
+
/** Dashboard / embed preview: open the panel on mount. */
|
|
106
|
+
startOpen?: boolean;
|
|
109
107
|
/** Canned prompts offered before the first message. */
|
|
110
|
-
suggestions?:
|
|
108
|
+
suggestions?: SupportSuggestion[];
|
|
111
109
|
};
|
|
112
110
|
|
|
113
111
|
/**
|
|
114
|
-
* Plain-fetch transport for the public support
|
|
112
|
+
* Plain-fetch transport for the public support REST endpoints. The
|
|
115
113
|
* embedding origin must be on the project's allowlist (configured in the
|
|
116
114
|
* support widget settings) for cross-origin calls to pass CORS.
|
|
117
115
|
*/
|
|
118
116
|
|
|
119
|
-
type
|
|
117
|
+
type SupportSession = {
|
|
120
118
|
attachments?: ConversationImageAttachment[];
|
|
121
119
|
conversationId: string;
|
|
122
120
|
sessionToken: string;
|
|
@@ -126,7 +124,7 @@ type ConversationImageAttachment = {
|
|
|
126
124
|
fileName?: string;
|
|
127
125
|
url: string;
|
|
128
126
|
};
|
|
129
|
-
type
|
|
127
|
+
type SupportConversationMessage = {
|
|
130
128
|
attachments?: ConversationImageAttachment[];
|
|
131
129
|
/** Replier's first name — present for `role: "team"` (human) messages only. */
|
|
132
130
|
authorName?: string;
|
|
@@ -144,16 +142,28 @@ type ChatThreadMessage = {
|
|
|
144
142
|
plainBody: string | null;
|
|
145
143
|
role: "user" | "team" | "bot";
|
|
146
144
|
};
|
|
147
|
-
type
|
|
145
|
+
type SupportConversation = {
|
|
148
146
|
/** False while a human has taken over — the widget goes persist-only. */
|
|
149
147
|
agentEnabled: boolean;
|
|
150
148
|
conversationId: string;
|
|
151
|
-
messages:
|
|
149
|
+
messages: SupportConversationMessage[];
|
|
152
150
|
state: "open" | "closed" | "snoozed";
|
|
153
151
|
};
|
|
154
152
|
|
|
155
153
|
/**
|
|
156
|
-
*
|
|
154
|
+
* Iframe-side state store with subscribe/notify (same pattern as the internal
|
|
155
|
+
* AgentContext). In the cross-origin embed the widget UI runs inside the Saasco
|
|
156
|
+
* `/embed/support` iframe; the host page's loader pushes identity, the
|
|
157
|
+
* signed JWT, host-state snapshots, the host viewport and open/close commands
|
|
158
|
+
* over `postMessage`, and the embed bridge writes them here so the live widget
|
|
159
|
+
* (subscribed via `useSyncExternalStore`) picks them up without a reboot.
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
/** Snapshot of host-app state appended to the agent's system prompt each turn. */
|
|
163
|
+
declare function setStateSnapshot(snapshot: unknown): void;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Embeddable customer-facing support for third-party apps — an
|
|
157
167
|
* Intercom-style messenger (Home + Messages tabs, branded workspace rows, a
|
|
158
168
|
* restyled chat with a workspace header and per-message meta lines) on top of the
|
|
159
169
|
* persisted support channel:
|
|
@@ -164,21 +174,21 @@ type ChatThread = {
|
|
|
164
174
|
* - an email gate captures a reply-to address before the first message when the
|
|
165
175
|
* host app hasn't already identified the visitor; every message is persisted
|
|
166
176
|
* into the saasco support inbox under `projectId`, with human replies merged
|
|
167
|
-
* into the open chat by polling the
|
|
177
|
+
* into the open chat by polling the conversation endpoint, and
|
|
168
178
|
* - once a human takes the conversation over the agent stream is muted, the
|
|
169
179
|
* customer sees a handoff acknowledgment, a "Waiting for a teammate" indicator
|
|
170
|
-
*
|
|
171
|
-
* first team message.
|
|
180
|
+
* while they are waiting on a reply (open, customer last), then "{name} has
|
|
181
|
+
* joined the conversation" above the first team message.
|
|
172
182
|
*
|
|
173
183
|
* The per-conversation session token (and the captured email) are persisted in
|
|
174
184
|
* the Saasco iframe-origin `localStorage` so anonymous threads survive reloads
|
|
175
|
-
* (best-effort — Safari/strict-Firefox partition third-party storage;
|
|
176
|
-
* users resume server-side
|
|
177
|
-
* app entry: it renders directly into the `/embed/support
|
|
185
|
+
* (best-effort — Safari/strict-Firefox partition third-party storage;
|
|
186
|
+
* identified users resume server-side). This component is the iframe
|
|
187
|
+
* app entry: it renders directly into the `/embed/support` page (no host-
|
|
178
188
|
* realm blank-iframe wrapper), and the host integrates over the postMessage
|
|
179
189
|
* bridge — identity, JWT, state snapshots, viewport and open/close all arrive
|
|
180
190
|
* through {@link initEmbedBridge} and are read here from the registry.
|
|
181
191
|
*/
|
|
182
|
-
declare function
|
|
192
|
+
declare function SupportWidgetInner({ baseUrl, getStateSnapshot, placeholder, projectId, startOpen, suggestions, }: WidgetConfig): React.ReactElement;
|
|
183
193
|
|
|
184
|
-
export { type
|
|
194
|
+
export { type JSONSchema7Object, type SupportConversation, type SupportConversationMessage, type SupportSession, type SupportSuggestion, type SupportTool, SupportWidgetInner, type WidgetConfig, initEmbedBridge, setStateSnapshot };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Iframe-side half of the cross-origin bridge. Runs inside the Saasco
|
|
3
|
-
* `/embed/support
|
|
3
|
+
* `/embed/support` page and talks to the host page's loader over
|
|
4
4
|
* `postMessage`:
|
|
5
5
|
*
|
|
6
6
|
* - inbound host messages (boot/identify/updateJwt/setStateSnapshot/viewport/
|
|
@@ -25,11 +25,8 @@ declare function initEmbedBridge(options: {
|
|
|
25
25
|
allowedOrigins: string[];
|
|
26
26
|
}): void;
|
|
27
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
28
|
/**
|
|
32
|
-
* Public types for the embeddable support
|
|
29
|
+
* Public types for the embeddable support widget. These restate the
|
|
33
30
|
* server wire contracts (`libs/support/shared` / `libs/chat/shared`) locally
|
|
34
31
|
* so the published package carries zero workspace dependencies.
|
|
35
32
|
*/
|
|
@@ -49,18 +46,17 @@ type JSONSchema7Object = {
|
|
|
49
46
|
/**
|
|
50
47
|
* The runtime shape of a tool the support widget can run in the browser. Tools
|
|
51
48
|
* are authored in the dashboard (stored in `Meta`) and served by the public
|
|
52
|
-
* settings endpoint as a `
|
|
49
|
+
* settings endpoint as a `PublicSupportTool`, which the widget rebuilds into this
|
|
53
50
|
* shape via `reconstructDashboardTool`.
|
|
54
51
|
*
|
|
55
52
|
* `execute` runs in the host app's browser when the agent calls a host tool
|
|
56
53
|
* and may touch in-page state, mutations, or SDKs. Server tools (dashboard
|
|
57
|
-
* `execution: "server"`) are proxied by the agent instead
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Approve/Reject before running.
|
|
54
|
+
* `execution: "server"`) are proxied by the agent instead — the widget must
|
|
55
|
+
* not browser-fetch their absolute endpoints (that causes CORS noise). Tools
|
|
56
|
+
* marked `destructive` pause for an explicit Approve/Reject before running.
|
|
61
57
|
*/
|
|
62
|
-
type
|
|
63
|
-
/** Shown to the model
|
|
58
|
+
type SupportTool = {
|
|
59
|
+
/** Shown to the model. Active tools require a non-empty description. */
|
|
64
60
|
description: string;
|
|
65
61
|
/** Pauses for an explicit Approve/Reject before running. */
|
|
66
62
|
destructive?: boolean;
|
|
@@ -91,7 +87,7 @@ type SupportChatTool = {
|
|
|
91
87
|
contextParameters?: string[];
|
|
92
88
|
};
|
|
93
89
|
/** A canned prompt offered in the empty state; clicking it fills the input. */
|
|
94
|
-
type
|
|
90
|
+
type SupportSuggestion = {
|
|
95
91
|
/** Optional second line shown under the label. */
|
|
96
92
|
description?: string;
|
|
97
93
|
label: string;
|
|
@@ -99,24 +95,26 @@ type SupportChatSuggestion = {
|
|
|
99
95
|
prompt: string;
|
|
100
96
|
};
|
|
101
97
|
type WidgetConfig = {
|
|
102
|
-
/** Origin of the saasco app hosting the support
|
|
98
|
+
/** Origin of the saasco app hosting the support API, e.g. https://app.example.com */
|
|
103
99
|
baseUrl: string;
|
|
104
100
|
/** Read at submit time and appended to the agent's system prompt. */
|
|
105
101
|
getStateSnapshot?: () => unknown;
|
|
106
102
|
/** Input placeholder. */
|
|
107
103
|
placeholder?: string;
|
|
108
104
|
projectId: string;
|
|
105
|
+
/** Dashboard / embed preview: open the panel on mount. */
|
|
106
|
+
startOpen?: boolean;
|
|
109
107
|
/** Canned prompts offered before the first message. */
|
|
110
|
-
suggestions?:
|
|
108
|
+
suggestions?: SupportSuggestion[];
|
|
111
109
|
};
|
|
112
110
|
|
|
113
111
|
/**
|
|
114
|
-
* Plain-fetch transport for the public support
|
|
112
|
+
* Plain-fetch transport for the public support REST endpoints. The
|
|
115
113
|
* embedding origin must be on the project's allowlist (configured in the
|
|
116
114
|
* support widget settings) for cross-origin calls to pass CORS.
|
|
117
115
|
*/
|
|
118
116
|
|
|
119
|
-
type
|
|
117
|
+
type SupportSession = {
|
|
120
118
|
attachments?: ConversationImageAttachment[];
|
|
121
119
|
conversationId: string;
|
|
122
120
|
sessionToken: string;
|
|
@@ -126,7 +124,7 @@ type ConversationImageAttachment = {
|
|
|
126
124
|
fileName?: string;
|
|
127
125
|
url: string;
|
|
128
126
|
};
|
|
129
|
-
type
|
|
127
|
+
type SupportConversationMessage = {
|
|
130
128
|
attachments?: ConversationImageAttachment[];
|
|
131
129
|
/** Replier's first name — present for `role: "team"` (human) messages only. */
|
|
132
130
|
authorName?: string;
|
|
@@ -144,16 +142,28 @@ type ChatThreadMessage = {
|
|
|
144
142
|
plainBody: string | null;
|
|
145
143
|
role: "user" | "team" | "bot";
|
|
146
144
|
};
|
|
147
|
-
type
|
|
145
|
+
type SupportConversation = {
|
|
148
146
|
/** False while a human has taken over — the widget goes persist-only. */
|
|
149
147
|
agentEnabled: boolean;
|
|
150
148
|
conversationId: string;
|
|
151
|
-
messages:
|
|
149
|
+
messages: SupportConversationMessage[];
|
|
152
150
|
state: "open" | "closed" | "snoozed";
|
|
153
151
|
};
|
|
154
152
|
|
|
155
153
|
/**
|
|
156
|
-
*
|
|
154
|
+
* Iframe-side state store with subscribe/notify (same pattern as the internal
|
|
155
|
+
* AgentContext). In the cross-origin embed the widget UI runs inside the Saasco
|
|
156
|
+
* `/embed/support` iframe; the host page's loader pushes identity, the
|
|
157
|
+
* signed JWT, host-state snapshots, the host viewport and open/close commands
|
|
158
|
+
* over `postMessage`, and the embed bridge writes them here so the live widget
|
|
159
|
+
* (subscribed via `useSyncExternalStore`) picks them up without a reboot.
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
/** Snapshot of host-app state appended to the agent's system prompt each turn. */
|
|
163
|
+
declare function setStateSnapshot(snapshot: unknown): void;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Embeddable customer-facing support for third-party apps — an
|
|
157
167
|
* Intercom-style messenger (Home + Messages tabs, branded workspace rows, a
|
|
158
168
|
* restyled chat with a workspace header and per-message meta lines) on top of the
|
|
159
169
|
* persisted support channel:
|
|
@@ -164,21 +174,21 @@ type ChatThread = {
|
|
|
164
174
|
* - an email gate captures a reply-to address before the first message when the
|
|
165
175
|
* host app hasn't already identified the visitor; every message is persisted
|
|
166
176
|
* into the saasco support inbox under `projectId`, with human replies merged
|
|
167
|
-
* into the open chat by polling the
|
|
177
|
+
* into the open chat by polling the conversation endpoint, and
|
|
168
178
|
* - once a human takes the conversation over the agent stream is muted, the
|
|
169
179
|
* customer sees a handoff acknowledgment, a "Waiting for a teammate" indicator
|
|
170
|
-
*
|
|
171
|
-
* first team message.
|
|
180
|
+
* while they are waiting on a reply (open, customer last), then "{name} has
|
|
181
|
+
* joined the conversation" above the first team message.
|
|
172
182
|
*
|
|
173
183
|
* The per-conversation session token (and the captured email) are persisted in
|
|
174
184
|
* the Saasco iframe-origin `localStorage` so anonymous threads survive reloads
|
|
175
|
-
* (best-effort — Safari/strict-Firefox partition third-party storage;
|
|
176
|
-
* users resume server-side
|
|
177
|
-
* app entry: it renders directly into the `/embed/support
|
|
185
|
+
* (best-effort — Safari/strict-Firefox partition third-party storage;
|
|
186
|
+
* identified users resume server-side). This component is the iframe
|
|
187
|
+
* app entry: it renders directly into the `/embed/support` page (no host-
|
|
178
188
|
* realm blank-iframe wrapper), and the host integrates over the postMessage
|
|
179
189
|
* bridge — identity, JWT, state snapshots, viewport and open/close all arrive
|
|
180
190
|
* through {@link initEmbedBridge} and are read here from the registry.
|
|
181
191
|
*/
|
|
182
|
-
declare function
|
|
192
|
+
declare function SupportWidgetInner({ baseUrl, getStateSnapshot, placeholder, projectId, startOpen, suggestions, }: WidgetConfig): React.ReactElement;
|
|
183
193
|
|
|
184
|
-
export { type
|
|
194
|
+
export { type JSONSchema7Object, type SupportConversation, type SupportConversationMessage, type SupportSession, type SupportSuggestion, type SupportTool, SupportWidgetInner, type WidgetConfig, initEmbedBridge, setStateSnapshot };
|