@agentforge-io/chat-sdk 2.0.18 → 2.0.19
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/entities.d.ts +10 -0
- package/dist/react.d.ts +42 -0
- package/dist/react.js +52 -23
- package/dist/session.d.ts +11 -1
- package/dist/session.js +30 -9
- package/package.json +1 -1
package/dist/entities.d.ts
CHANGED
|
@@ -24,10 +24,20 @@ export type ChatMessageMetadata = {
|
|
|
24
24
|
approvalId: string;
|
|
25
25
|
toolName: string;
|
|
26
26
|
expiresAt: string;
|
|
27
|
+
/** Friendly connector display name surfaced by the server when
|
|
28
|
+
* available (e.g. `'Granola'`). Lets the View render a
|
|
29
|
+
* natural-language card without the host having to map slugs
|
|
30
|
+
* to product names. */
|
|
31
|
+
connectorName?: string;
|
|
32
|
+
/** First line of the tool's description from the connector
|
|
33
|
+
* definition. Used as a one-line "what will happen" hint. */
|
|
34
|
+
toolDescription?: string;
|
|
27
35
|
} | {
|
|
28
36
|
kind: 'tool_blocked';
|
|
29
37
|
toolName: string;
|
|
30
38
|
reason?: string;
|
|
39
|
+
connectorName?: string;
|
|
40
|
+
toolDescription?: string;
|
|
31
41
|
} | {
|
|
32
42
|
kind: string;
|
|
33
43
|
[k: string]: unknown;
|
package/dist/react.d.ts
CHANGED
|
@@ -34,6 +34,42 @@ export type ApprovalActionHandler = (args: {
|
|
|
34
34
|
approvalId: string;
|
|
35
35
|
action: 'approve' | 'deny';
|
|
36
36
|
}) => Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Localizable copy for the approval / blocked bubbles. Pass via the
|
|
39
|
+
* `approvalCopy` prop on `<ChatWidget>` to drop the defaults (Spanish,
|
|
40
|
+
* conversational) and tailor every line to your audience.
|
|
41
|
+
*
|
|
42
|
+
* Functions receive whatever context the server enriched the chunk
|
|
43
|
+
* with — typically a friendly connector name like `'Granola'`. When
|
|
44
|
+
* the server didn't supply it, the function is called with `undefined`
|
|
45
|
+
* and the implementation should pick a sensible generic line. The
|
|
46
|
+
* widget itself never references the raw tool slug in copy.
|
|
47
|
+
*/
|
|
48
|
+
export interface ApprovalCopy {
|
|
49
|
+
title: string;
|
|
50
|
+
body: (ctx: {
|
|
51
|
+
connectorName?: string;
|
|
52
|
+
toolDescription?: string;
|
|
53
|
+
}) => string;
|
|
54
|
+
approveLabel: string;
|
|
55
|
+
approveBusyLabel: string;
|
|
56
|
+
denyLabel: string;
|
|
57
|
+
denyBusyLabel: string;
|
|
58
|
+
approvedPill: string;
|
|
59
|
+
deniedPill: string;
|
|
60
|
+
/** Shown when the host didn't wire `onApprovalAction` — the visitor
|
|
61
|
+
* can't decide from inside the widget so we tell them where to go. */
|
|
62
|
+
readOnlyHint: string;
|
|
63
|
+
/** Used by the `expires in …` countdown. Receives minutes/seconds
|
|
64
|
+
* and returns the formatted string. */
|
|
65
|
+
expiresIn: (mins: number, secs: number) => string;
|
|
66
|
+
/** Block bubble title + body. */
|
|
67
|
+
blockedTitle: string;
|
|
68
|
+
blockedBody: (ctx: {
|
|
69
|
+
connectorName?: string;
|
|
70
|
+
reason?: string;
|
|
71
|
+
}) => string;
|
|
72
|
+
}
|
|
37
73
|
export interface ChatWidgetProps {
|
|
38
74
|
/** Public chat token (`aft_*`) issued from the admin UI. */
|
|
39
75
|
token: string;
|
|
@@ -61,6 +97,12 @@ export interface ChatWidgetProps {
|
|
|
61
97
|
* hints.
|
|
62
98
|
*/
|
|
63
99
|
onApprovalAction?: ApprovalActionHandler;
|
|
100
|
+
/**
|
|
101
|
+
* Override any subset of the approval-card copy. Keys you don't
|
|
102
|
+
* provide fall back to the Spanish defaults in `DEFAULT_APPROVAL_COPY`.
|
|
103
|
+
* Use this for translations or to match your product's voice.
|
|
104
|
+
*/
|
|
105
|
+
approvalCopy?: Partial<ApprovalCopy>;
|
|
64
106
|
}
|
|
65
107
|
/**
|
|
66
108
|
* Drop-in chat widget. Owns its own `ChatSession` and re-renders on every
|
package/dist/react.js
CHANGED
|
@@ -153,12 +153,38 @@ function renderMarkdown(src) {
|
|
|
153
153
|
}
|
|
154
154
|
return out.join('');
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Defaults are Spanish + conversational. The host overrides individual
|
|
158
|
+
* keys via the `approvalCopy` prop; unset keys keep these values.
|
|
159
|
+
*/
|
|
160
|
+
const DEFAULT_APPROVAL_COPY = {
|
|
161
|
+
title: 'Necesito tu permiso',
|
|
162
|
+
body: ({ connectorName }) => connectorName
|
|
163
|
+
? `¿Me das permiso para usar ${connectorName}?`
|
|
164
|
+
: '¿Me das permiso para continuar?',
|
|
165
|
+
approveLabel: 'Permitir',
|
|
166
|
+
approveBusyLabel: 'Permitiendo…',
|
|
167
|
+
denyLabel: 'No, gracias',
|
|
168
|
+
denyBusyLabel: 'Cancelando…',
|
|
169
|
+
approvedPill: 'Listo, continuando…',
|
|
170
|
+
deniedPill: 'Cancelado',
|
|
171
|
+
readOnlyHint: 'Pídele al administrador del workspace que lo apruebe.',
|
|
172
|
+
expiresIn: (m, s) => m >= 60
|
|
173
|
+
? `Expira en ${Math.floor(m / 60)}h ${m % 60}m`
|
|
174
|
+
: `Expira en ${m}m ${s.toString().padStart(2, '0')}s`,
|
|
175
|
+
blockedTitle: 'No disponible',
|
|
176
|
+
blockedBody: ({ connectorName, reason }) => reason ??
|
|
177
|
+
(connectorName
|
|
178
|
+
? `No puedo usar ${connectorName} en esta cuenta.`
|
|
179
|
+
: 'No puedo usar esa herramienta en esta cuenta.'),
|
|
180
|
+
};
|
|
156
181
|
/**
|
|
157
182
|
* Drop-in chat widget. Owns its own `ChatSession` and re-renders on every
|
|
158
183
|
* SDK event. Consumers don't need to read `session.getState()` themselves.
|
|
159
184
|
*/
|
|
160
185
|
function ChatWidget(props) {
|
|
161
|
-
const { token, apiBaseUrl, inline = false, position, browserSessionId, resumeConversationId, stream, className, style, onApprovalAction, } = props;
|
|
186
|
+
const { token, apiBaseUrl, inline = false, position, browserSessionId, resumeConversationId, stream, className, style, onApprovalAction, approvalCopy, } = props;
|
|
187
|
+
const copy = { ...DEFAULT_APPROVAL_COPY, ...(approvalCopy ?? {}) };
|
|
162
188
|
const [session, setSession] = (0, react_1.useState)(null);
|
|
163
189
|
const [status, setStatus] = (0, react_1.useState)('idle');
|
|
164
190
|
const [agent, setAgent] = (0, react_1.useState)();
|
|
@@ -278,30 +304,27 @@ function ChatWidget(props) {
|
|
|
278
304
|
};
|
|
279
305
|
return ((0, jsx_runtime_1.jsxs)("div", { className: rootClass, style: rootStyle, "data-style-id": styleId, children: [!inline && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-toggle", "aria-label": open ? 'Close chat' : 'Open chat', "aria-expanded": open, onClick: () => setOpen((v) => !v), children: open ? (0, jsx_runtime_1.jsx)(CloseIcon, {}) : (0, jsx_runtime_1.jsx)(ChatIcon, {}) })), (0, jsx_runtime_1.jsxs)("div", { className: `af-panel ${open ? 'af-open' : ''}`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "af-header", children: [theme?.avatarUrl ? (
|
|
280
306
|
// eslint-disable-next-line @next/next/no-img-element
|
|
281
|
-
(0, jsx_runtime_1.jsx)("img", { className: "af-header-avatar", src: theme.avatarUrl, alt: "" })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "af-header-info", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-header-title", children: theme?.title ?? agent?.name ?? 'Chat' }), (0, jsx_runtime_1.jsx)("div", { className: "af-header-subtitle", children: status === 'loading' ? 'Loading…' : agent?.description ?? '' })] }), !inline && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-close", onClick: () => setOpen(false), "aria-label": "Close chat", children: (0, jsx_runtime_1.jsx)(CloseIcon, {}) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "af-messages", ref: messagesRef, children: messages.map((m) => ((0, jsx_runtime_1.jsx)(MessageBubble, { message: m, onApprovalAction: onApprovalAction, onContinue: () => {
|
|
307
|
+
(0, jsx_runtime_1.jsx)("img", { className: "af-header-avatar", src: theme.avatarUrl, alt: "" })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "af-header-info", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-header-title", children: theme?.title ?? agent?.name ?? 'Chat' }), (0, jsx_runtime_1.jsx)("div", { className: "af-header-subtitle", children: status === 'loading' ? 'Loading…' : agent?.description ?? '' })] }), !inline && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-close", onClick: () => setOpen(false), "aria-label": "Close chat", children: (0, jsx_runtime_1.jsx)(CloseIcon, {}) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "af-messages", ref: messagesRef, children: messages.map((m) => ((0, jsx_runtime_1.jsx)(MessageBubble, { message: m, copy: copy, onApprovalAction: onApprovalAction, onContinue: () => {
|
|
282
308
|
// After a successful Approve, kick the next turn so the
|
|
283
309
|
// gate's fast-path consumes the approval and the tool
|
|
284
|
-
// actually runs.
|
|
285
|
-
//
|
|
310
|
+
// actually runs. `silent: true` keeps the literal
|
|
311
|
+
// "continue" prompt out of the visible transcript —
|
|
312
|
+
// the visitor just sees the assistant's next reply
|
|
313
|
+
// appearing under the "Approved" pill.
|
|
286
314
|
if (!session)
|
|
287
315
|
return;
|
|
288
316
|
setTimeout(() => {
|
|
289
|
-
void session.send('continue');
|
|
317
|
+
void session.send('continue', { silent: true });
|
|
290
318
|
}, 250);
|
|
291
319
|
} }, m.id))) }), lastError && status === 'error' && ((0, jsx_runtime_1.jsx)("div", { className: "af-error", children: lastError })), (0, jsx_runtime_1.jsxs)("div", { className: "af-input-row", children: [(0, jsx_runtime_1.jsx)("textarea", { className: "af-input", value: draft, onChange: (e) => setDraft(e.target.value), onKeyDown: onKeyDown, placeholder: "Type a message\u2026", rows: 1, disabled: status === 'ended' || status === 'loading' || status === 'idle' }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-send", onClick: handleSend, disabled: sendDisabled, "aria-label": "Send message", children: (0, jsx_runtime_1.jsx)(SendIcon, {}) })] }), (0, jsx_runtime_1.jsx)("div", { className: "af-footer", children: "Powered by AgentForge" })] })] }));
|
|
292
320
|
}
|
|
293
|
-
function MessageBubble({ message, onApprovalAction, onContinue, }) {
|
|
294
|
-
// Structured metadata takes precedence over plain text. The server
|
|
295
|
-
// tags messages with `kind: 'awaiting_approval' | 'tool_blocked'`
|
|
296
|
-
// and the widget renders a dedicated bubble for each — unknown
|
|
297
|
-
// kinds fall through to the markdown renderer with the plain text
|
|
298
|
-
// body the server also persists.
|
|
321
|
+
function MessageBubble({ message, copy, onApprovalAction, onContinue, }) {
|
|
299
322
|
const kind = message.metadata?.kind;
|
|
300
323
|
if (kind === 'awaiting_approval') {
|
|
301
|
-
return ((0, jsx_runtime_1.jsx)(ApprovalBubble, { message: message, onAction: onApprovalAction, onContinue: onContinue }));
|
|
324
|
+
return ((0, jsx_runtime_1.jsx)(ApprovalBubble, { message: message, copy: copy, onAction: onApprovalAction, onContinue: onContinue }));
|
|
302
325
|
}
|
|
303
326
|
if (kind === 'tool_blocked') {
|
|
304
|
-
return (0, jsx_runtime_1.jsx)(BlockedBubble, { message: message });
|
|
327
|
+
return (0, jsx_runtime_1.jsx)(BlockedBubble, { message: message, copy: copy });
|
|
305
328
|
}
|
|
306
329
|
const cls = `af-msg af-msg-${message.role}${message.role === 'assistant' && message.isStreaming
|
|
307
330
|
? message.content
|
|
@@ -328,12 +351,12 @@ function MessageBubble({ message, onApprovalAction, onContinue, }) {
|
|
|
328
351
|
* so the chat auto-sends "continue" and the gate's fast-path consumes
|
|
329
352
|
* the row on the next turn.
|
|
330
353
|
*/
|
|
331
|
-
function ApprovalBubble({ message, onAction, onContinue, }) {
|
|
354
|
+
function ApprovalBubble({ message, copy, onAction, onContinue, }) {
|
|
332
355
|
const meta = message.metadata;
|
|
333
356
|
const [busy, setBusy] = (0, react_1.useState)(null);
|
|
334
357
|
const [decided, setDecided] = (0, react_1.useState)(null);
|
|
335
358
|
const [err, setErr] = (0, react_1.useState)(null);
|
|
336
|
-
const remaining = useExpiresIn(meta?.expiresAt);
|
|
359
|
+
const remaining = useExpiresIn(meta?.expiresAt, copy.expiresIn);
|
|
337
360
|
if (!meta)
|
|
338
361
|
return null;
|
|
339
362
|
const act = async (action) => {
|
|
@@ -354,20 +377,28 @@ function ApprovalBubble({ message, onAction, onContinue, }) {
|
|
|
354
377
|
setBusy(null);
|
|
355
378
|
}
|
|
356
379
|
};
|
|
357
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "af-msg af-msg-approval", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-approval-title", children:
|
|
380
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "af-msg af-msg-approval", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-approval-title", children: copy.title }), (0, jsx_runtime_1.jsx)("div", { className: "af-approval-body", children: copy.body({
|
|
381
|
+
connectorName: meta.connectorName,
|
|
382
|
+
toolDescription: meta.toolDescription,
|
|
383
|
+
}) }), remaining && !decided && ((0, jsx_runtime_1.jsx)("div", { className: "af-approval-meta", children: remaining })), decided && ((0, jsx_runtime_1.jsx)("div", { className: `af-approval-pill af-approval-pill-${decided}`, children: decided === 'approved' ? copy.approvedPill : copy.deniedPill })), !decided && onAction && ((0, jsx_runtime_1.jsxs)("div", { className: "af-approval-actions", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-approval-btn af-approval-approve", disabled: busy !== null, onClick: () => act('approve'), children: busy === 'approve' ? copy.approveBusyLabel : copy.approveLabel }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "af-approval-btn af-approval-deny", disabled: busy !== null, onClick: () => act('deny'), children: busy === 'deny' ? copy.denyBusyLabel : copy.denyLabel })] })), !decided && !onAction && ((0, jsx_runtime_1.jsx)("div", { className: "af-approval-hint", children: copy.readOnlyHint })), err && (0, jsx_runtime_1.jsx)("div", { className: "af-approval-error", children: err })] }));
|
|
358
384
|
}
|
|
359
385
|
/**
|
|
360
386
|
* Terminal "tool blocked" bubble. No action — just informs the visitor
|
|
361
387
|
* that the tool the agent tried isn't available.
|
|
362
388
|
*/
|
|
363
|
-
function BlockedBubble({ message }) {
|
|
389
|
+
function BlockedBubble({ message, copy, }) {
|
|
364
390
|
const meta = message.metadata;
|
|
365
391
|
if (!meta)
|
|
366
392
|
return null;
|
|
367
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "af-msg af-msg-blocked", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-blocked-title", children:
|
|
393
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "af-msg af-msg-blocked", children: [(0, jsx_runtime_1.jsx)("div", { className: "af-blocked-title", children: copy.blockedTitle }), (0, jsx_runtime_1.jsx)("div", { className: "af-blocked-body", children: copy.blockedBody({
|
|
394
|
+
connectorName: meta.connectorName,
|
|
395
|
+
reason: meta.reason,
|
|
396
|
+
}) })] }));
|
|
368
397
|
}
|
|
369
|
-
/** Live "expires in" countdown. Returns null after the deadline.
|
|
370
|
-
function
|
|
398
|
+
/** Live "expires in" countdown. Returns null after the deadline.
|
|
399
|
+
* The format function is host-supplied so the label stays localisable —
|
|
400
|
+
* the hook itself doesn't hard-code any user-facing string. */
|
|
401
|
+
function useExpiresIn(iso, format) {
|
|
371
402
|
const [, force] = (0, react_1.useState)(0);
|
|
372
403
|
(0, react_1.useEffect)(() => {
|
|
373
404
|
if (!iso)
|
|
@@ -383,9 +414,7 @@ function useExpiresIn(iso) {
|
|
|
383
414
|
const totalSeconds = Math.floor(ms / 1000);
|
|
384
415
|
const m = Math.floor(totalSeconds / 60);
|
|
385
416
|
const s = totalSeconds % 60;
|
|
386
|
-
|
|
387
|
-
return `Expires in ${Math.floor(m / 60)}h ${m % 60}m`;
|
|
388
|
-
return `Expires in ${m}m ${s.toString().padStart(2, '0')}s`;
|
|
417
|
+
return format(m, s);
|
|
389
418
|
}
|
|
390
419
|
function ChatIcon() {
|
|
391
420
|
return ((0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: (0, jsx_runtime_1.jsx)("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) }));
|
package/dist/session.d.ts
CHANGED
|
@@ -42,8 +42,18 @@ export declare class ChatSession {
|
|
|
42
42
|
* Send a user message. Opens the conversation on first call. Returns the
|
|
43
43
|
* final assistant content for callers that want to await it; the same
|
|
44
44
|
* content is also emitted via `message_added` / `message_updated`.
|
|
45
|
+
*
|
|
46
|
+
* `silent: true` suppresses the user-message bubble that would normally
|
|
47
|
+
* appear in the view layer. Used by the tool-approval auto-continue
|
|
48
|
+
* flow: after the visitor clicks Approve, the widget fires a hidden
|
|
49
|
+
* `send('continue', { silent: true })` so the gate's fast-path
|
|
50
|
+
* triggers without leaking a literal "continue" message into the
|
|
51
|
+
* conversation. The server still sees a regular user message and the
|
|
52
|
+
* agent's reply comes back through the normal stream.
|
|
45
53
|
*/
|
|
46
|
-
send(text: string
|
|
54
|
+
send(text: string, opts?: {
|
|
55
|
+
silent?: boolean;
|
|
56
|
+
}): Promise<string>;
|
|
47
57
|
private runStream;
|
|
48
58
|
private runNonStream;
|
|
49
59
|
private appendMessage;
|
package/dist/session.js
CHANGED
|
@@ -142,8 +142,16 @@ class ChatSession {
|
|
|
142
142
|
* Send a user message. Opens the conversation on first call. Returns the
|
|
143
143
|
* final assistant content for callers that want to await it; the same
|
|
144
144
|
* content is also emitted via `message_added` / `message_updated`.
|
|
145
|
+
*
|
|
146
|
+
* `silent: true` suppresses the user-message bubble that would normally
|
|
147
|
+
* appear in the view layer. Used by the tool-approval auto-continue
|
|
148
|
+
* flow: after the visitor clicks Approve, the widget fires a hidden
|
|
149
|
+
* `send('continue', { silent: true })` so the gate's fast-path
|
|
150
|
+
* triggers without leaking a literal "continue" message into the
|
|
151
|
+
* conversation. The server still sees a regular user message and the
|
|
152
|
+
* agent's reply comes back through the normal stream.
|
|
145
153
|
*/
|
|
146
|
-
async send(text) {
|
|
154
|
+
async send(text, opts) {
|
|
147
155
|
const trimmed = text.trim();
|
|
148
156
|
if (!trimmed)
|
|
149
157
|
return '';
|
|
@@ -152,12 +160,14 @@ class ChatSession {
|
|
|
152
160
|
}
|
|
153
161
|
if (!this.started)
|
|
154
162
|
await this.start();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
if (!opts?.silent) {
|
|
164
|
+
this.appendMessage({
|
|
165
|
+
id: makeMessageId('u'),
|
|
166
|
+
role: 'user',
|
|
167
|
+
content: trimmed,
|
|
168
|
+
createdAt: new Date(),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
161
171
|
const assistant = {
|
|
162
172
|
id: makeMessageId('a'),
|
|
163
173
|
role: 'assistant',
|
|
@@ -202,9 +212,14 @@ class ChatSession {
|
|
|
202
212
|
approvalId: c.approvalId,
|
|
203
213
|
toolName: c.toolName,
|
|
204
214
|
expiresAt: c.expiresAt,
|
|
215
|
+
connectorName: c.connectorName,
|
|
216
|
+
toolDescription: c.toolDescription,
|
|
205
217
|
};
|
|
206
218
|
assistant.content =
|
|
207
|
-
full ||
|
|
219
|
+
full ||
|
|
220
|
+
(c.connectorName
|
|
221
|
+
? `Necesito tu permiso para usar ${c.connectorName}.`
|
|
222
|
+
: `Necesito tu permiso para continuar.`);
|
|
208
223
|
this.updateMessage(assistant);
|
|
209
224
|
continue;
|
|
210
225
|
}
|
|
@@ -214,9 +229,15 @@ class ChatSession {
|
|
|
214
229
|
kind: 'tool_blocked',
|
|
215
230
|
toolName: c.toolName,
|
|
216
231
|
reason: c.reason,
|
|
232
|
+
connectorName: c.connectorName,
|
|
233
|
+
toolDescription: c.toolDescription,
|
|
217
234
|
};
|
|
218
235
|
assistant.content =
|
|
219
|
-
full ||
|
|
236
|
+
full ||
|
|
237
|
+
c.reason ||
|
|
238
|
+
(c.connectorName
|
|
239
|
+
? `No puedo usar ${c.connectorName} en esta cuenta.`
|
|
240
|
+
: `No puedo usar esa herramienta en esta cuenta.`);
|
|
220
241
|
this.updateMessage(assistant);
|
|
221
242
|
continue;
|
|
222
243
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge-io/chat-sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.19",
|
|
4
4
|
"description": "Framework-free chat session SDK for AgentForge public chat tokens. Headless — no DOM. Drop into any frontend (React, Vue, Svelte, vanilla) and listen for events.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|