@agentforge-io/chat-sdk 2.0.15 → 2.0.17
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 +32 -0
- package/dist/index.d.ts +1 -1
- package/dist/session.js +40 -1
- package/dist/transport.d.ts +4 -0
- package/dist/transport.js +1 -0
- package/package.json +1 -1
package/dist/entities.d.ts
CHANGED
|
@@ -4,6 +4,34 @@
|
|
|
4
4
|
* and easy to reason about.
|
|
5
5
|
*/
|
|
6
6
|
export type ChatRole = 'user' | 'assistant' | 'system';
|
|
7
|
+
/**
|
|
8
|
+
* Structured payload attached to messages the server tagged with a
|
|
9
|
+
* non-text intent. Today's kinds:
|
|
10
|
+
*
|
|
11
|
+
* - `awaiting_approval`: a tool the agent wanted to run requires
|
|
12
|
+
* human approval. The View layer renders an Approve/Deny card
|
|
13
|
+
* using `approvalId` + `toolName`. After Approve the client should
|
|
14
|
+
* auto-send a "continue" follow-up so the gate's fast-path consumes
|
|
15
|
+
* the pending row and the turn finishes.
|
|
16
|
+
* - `tool_blocked`: a tool was hard-blocked by the gate. Terminal,
|
|
17
|
+
* no action — render as an error card.
|
|
18
|
+
*
|
|
19
|
+
* Future kinds extend this union without breaking back-compat: the
|
|
20
|
+
* View checks `kind` and falls back to plain text when it's unknown.
|
|
21
|
+
*/
|
|
22
|
+
export type ChatMessageMetadata = {
|
|
23
|
+
kind: 'awaiting_approval';
|
|
24
|
+
approvalId: string;
|
|
25
|
+
toolName: string;
|
|
26
|
+
expiresAt: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'tool_blocked';
|
|
29
|
+
toolName: string;
|
|
30
|
+
reason?: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: string;
|
|
33
|
+
[k: string]: unknown;
|
|
34
|
+
};
|
|
7
35
|
export interface ChatMessage {
|
|
8
36
|
/** Stable client-side id so view layers can key off it. */
|
|
9
37
|
id: string;
|
|
@@ -15,6 +43,10 @@ export interface ChatMessage {
|
|
|
15
43
|
/** True while the assistant is still streaming this message. The UI uses
|
|
16
44
|
* this to render a caret/cursor next to a half-written reply. */
|
|
17
45
|
isStreaming?: boolean;
|
|
46
|
+
/** Structured payload for non-text messages (approval cards, blocked
|
|
47
|
+
* errors, …). View layers should branch on `metadata.kind` before
|
|
48
|
+
* falling back to `content`. */
|
|
49
|
+
metadata?: ChatMessageMetadata;
|
|
18
50
|
}
|
|
19
51
|
export interface ChatAgentSummary {
|
|
20
52
|
slug: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
export { ChatSession } from './session';
|
|
11
11
|
export { HttpTransport } from './transport';
|
|
12
12
|
export type { StreamEvent, ServerStreamChunk, TransportError, } from './transport';
|
|
13
|
-
export type { ChatAgentSummary, ChatEvent, ChatMessage, ChatRole, ChatSessionOptions, ChatSessionState, ChatSessionStatus, ChatTheme, } from './entities';
|
|
13
|
+
export type { ChatAgentSummary, ChatEvent, ChatMessage, ChatMessageMetadata, ChatRole, ChatSessionOptions, ChatSessionState, ChatSessionStatus, ChatTheme, } from './entities';
|
package/dist/session.js
CHANGED
|
@@ -80,6 +80,7 @@ class ChatSession {
|
|
|
80
80
|
role: m.role,
|
|
81
81
|
content: m.content,
|
|
82
82
|
createdAt: new Date(m.createdAt),
|
|
83
|
+
metadata: m.metadata,
|
|
83
84
|
});
|
|
84
85
|
}
|
|
85
86
|
if (history.status === 'completed') {
|
|
@@ -186,6 +187,39 @@ class ChatSession {
|
|
|
186
187
|
}
|
|
187
188
|
if (evt.kind === 'chunk') {
|
|
188
189
|
sawAnyChunk = true;
|
|
190
|
+
// Approval gate intercepts. The server emits one of these as
|
|
191
|
+
// the final chunk before closing the stream; we mutate the
|
|
192
|
+
// in-flight assistant message with the structured payload so
|
|
193
|
+
// the View can swap the bubble for an Approve/Deny card. The
|
|
194
|
+
// text body falls back to a sensible plain-text version so a
|
|
195
|
+
// legacy widget (no metadata renderer) still shows something
|
|
196
|
+
// readable.
|
|
197
|
+
const chunkType = evt.chunk.type;
|
|
198
|
+
if (chunkType === 'awaiting_approval') {
|
|
199
|
+
const c = evt.chunk;
|
|
200
|
+
assistant.metadata = {
|
|
201
|
+
kind: 'awaiting_approval',
|
|
202
|
+
approvalId: c.approvalId,
|
|
203
|
+
toolName: c.toolName,
|
|
204
|
+
expiresAt: c.expiresAt,
|
|
205
|
+
};
|
|
206
|
+
assistant.content =
|
|
207
|
+
full || `(waiting for approval to run \`${c.toolName}\`)`;
|
|
208
|
+
this.updateMessage(assistant);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (chunkType === 'tool_blocked') {
|
|
212
|
+
const c = evt.chunk;
|
|
213
|
+
assistant.metadata = {
|
|
214
|
+
kind: 'tool_blocked',
|
|
215
|
+
toolName: c.toolName,
|
|
216
|
+
reason: c.reason,
|
|
217
|
+
};
|
|
218
|
+
assistant.content =
|
|
219
|
+
full || c.reason || `Tool "${c.toolName}" is blocked.`;
|
|
220
|
+
this.updateMessage(assistant);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
189
223
|
const delta = extractDelta(evt.chunk);
|
|
190
224
|
if (!delta)
|
|
191
225
|
continue;
|
|
@@ -207,7 +241,12 @@ class ChatSession {
|
|
|
207
241
|
// than leaving an empty assistant bubble. Most often this means the
|
|
208
242
|
// backend swallowed an exception inside streamMessage (e.g. the
|
|
209
243
|
// history query failed or the runner rejected the model).
|
|
210
|
-
|
|
244
|
+
//
|
|
245
|
+
// Exception: when the stream ended on an approval / blocked
|
|
246
|
+
// chunk, the bubble carries that structured payload and is a
|
|
247
|
+
// legitimate terminal state — not a missing reply. Skip the
|
|
248
|
+
// "empty response" guard for those.
|
|
249
|
+
if (!full && !assistant.metadata) {
|
|
211
250
|
throw new Error(sawAnyChunk
|
|
212
251
|
? 'The model returned an empty response.'
|
|
213
252
|
: 'No response received from the server.');
|
package/dist/transport.d.ts
CHANGED
|
@@ -77,6 +77,10 @@ export declare class HttpTransport {
|
|
|
77
77
|
role: 'user' | 'assistant' | 'system';
|
|
78
78
|
content: string;
|
|
79
79
|
createdAt: string;
|
|
80
|
+
/** Structured payload for non-text messages (approval cards,
|
|
81
|
+
* blocked errors). Passed through unchanged from the server's
|
|
82
|
+
* message row so a reload re-renders the same card. */
|
|
83
|
+
metadata?: Record<string, unknown>;
|
|
80
84
|
}>;
|
|
81
85
|
} | null>;
|
|
82
86
|
endConversation(conversationId: string, browserSessionId: string): Promise<void>;
|
package/dist/transport.js
CHANGED
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.17",
|
|
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",
|