@agntk/client 0.1.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/README.md +46 -0
- package/dist/browser-stream.d.ts +127 -0
- package/dist/browser-stream.d.ts.map +1 -0
- package/dist/browser-stream.js +264 -0
- package/dist/browser-stream.js.map +1 -0
- package/dist/chat-client.d.ts +38 -0
- package/dist/chat-client.d.ts.map +1 -0
- package/dist/chat-client.js +142 -0
- package/dist/chat-client.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +34 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/http-client.d.ts +48 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +168 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/session.d.ts +36 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +60 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/websocket-client.d.ts +38 -0
- package/dist/websocket-client.d.ts.map +1 -0
- package/dist/websocket-client.js +140 -0
- package/dist/websocket-client.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @agntk/client
|
|
2
|
+
|
|
3
|
+
HTTP/WebSocket client for connecting to an [@agntk/server](https://www.npmjs.com/package/@agntk/server) instance.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @agntk/client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { AgentHttpClient } from '@agntk/client';
|
|
15
|
+
|
|
16
|
+
const client = new AgentHttpClient('http://localhost:3001');
|
|
17
|
+
|
|
18
|
+
// Synchronous
|
|
19
|
+
const result = await client.generate({
|
|
20
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Streaming (SSE)
|
|
24
|
+
for await (const event of client.generateStream({
|
|
25
|
+
messages: [{ role: 'user', content: 'Tell me a story' }],
|
|
26
|
+
})) {
|
|
27
|
+
if (event.type === 'text-delta') process.stdout.write(event.textDelta);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- **HTTP Client** — Synchronous and streaming generation
|
|
34
|
+
- **SSE Streams** — Real-time text deltas, tool calls, and step events
|
|
35
|
+
- **WebSocket Client** — Full-duplex communication
|
|
36
|
+
- **Chat Client** — Session management with history
|
|
37
|
+
- **Browser Stream Client** — Real-time viewport streaming
|
|
38
|
+
- **Resumable Streams** — Reconnect from where you left off
|
|
39
|
+
|
|
40
|
+
## Documentation
|
|
41
|
+
|
|
42
|
+
See the [main repository](https://github.com/agntk/agntk) for full documentation.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Browser stream client for real-time viewport streaming.
|
|
3
|
+
* Connects to the /ws/browser-stream WebSocket endpoint and provides
|
|
4
|
+
* a typed API for receiving frames and injecting user input.
|
|
5
|
+
*/
|
|
6
|
+
export interface BrowserStreamClientOptions {
|
|
7
|
+
/** WebSocket URL (e.g., ws://localhost:3000/ws/browser-stream) */
|
|
8
|
+
url: string;
|
|
9
|
+
/** Auto-reconnect on disconnect (default: true) */
|
|
10
|
+
reconnect?: boolean;
|
|
11
|
+
/** Max reconnect attempts (default: 5) */
|
|
12
|
+
maxReconnectAttempts?: number;
|
|
13
|
+
/** Base delay between reconnect attempts in ms (default: 1000) */
|
|
14
|
+
reconnectDelay?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface BrowserFrame {
|
|
17
|
+
/** Base64-encoded image data */
|
|
18
|
+
data: string;
|
|
19
|
+
/** Capture timestamp (ms since epoch) */
|
|
20
|
+
timestamp: number;
|
|
21
|
+
/** Frame sequence number */
|
|
22
|
+
sequence: number;
|
|
23
|
+
}
|
|
24
|
+
export interface BrowserStreamConfig {
|
|
25
|
+
fps?: number;
|
|
26
|
+
quality?: number;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
}
|
|
30
|
+
export type BrowserStreamState = 'disconnected' | 'connecting' | 'connected' | 'streaming' | 'reconnecting';
|
|
31
|
+
export interface BrowserStreamCallbacks {
|
|
32
|
+
/** Called for each viewport frame */
|
|
33
|
+
onFrame?: (frame: BrowserFrame) => void;
|
|
34
|
+
/** Called when the stream starts */
|
|
35
|
+
onStarted?: (config: BrowserStreamConfig) => void;
|
|
36
|
+
/** Called when the stream stops */
|
|
37
|
+
onStopped?: () => void;
|
|
38
|
+
/** Called on stream error */
|
|
39
|
+
onError?: (error: string) => void;
|
|
40
|
+
/** Called when connection state changes */
|
|
41
|
+
onStateChange?: (state: BrowserStreamState) => void;
|
|
42
|
+
/** Called when input injection is acknowledged */
|
|
43
|
+
onInputAck?: (inputType: string, success: boolean, error?: string) => void;
|
|
44
|
+
/** Called when config change is acknowledged */
|
|
45
|
+
onConfigAck?: (config: BrowserStreamConfig) => void;
|
|
46
|
+
}
|
|
47
|
+
export declare class BrowserStreamClient {
|
|
48
|
+
private ws;
|
|
49
|
+
private options;
|
|
50
|
+
private state;
|
|
51
|
+
private callbacks;
|
|
52
|
+
private reconnectAttempts;
|
|
53
|
+
private reconnectTimer;
|
|
54
|
+
private frameCount;
|
|
55
|
+
private lastFrameTime;
|
|
56
|
+
constructor(options: BrowserStreamClientOptions);
|
|
57
|
+
/**
|
|
58
|
+
* Connect to the browser stream WebSocket endpoint.
|
|
59
|
+
*/
|
|
60
|
+
connect(callbacks?: BrowserStreamCallbacks): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Disconnect from the browser stream.
|
|
63
|
+
*/
|
|
64
|
+
disconnect(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get current connection state.
|
|
67
|
+
*/
|
|
68
|
+
getState(): BrowserStreamState;
|
|
69
|
+
/**
|
|
70
|
+
* Get frame statistics.
|
|
71
|
+
*/
|
|
72
|
+
getStats(): {
|
|
73
|
+
frameCount: number;
|
|
74
|
+
lastFrameTime: number;
|
|
75
|
+
fps: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Inject a click at viewport coordinates.
|
|
79
|
+
*/
|
|
80
|
+
click(x: number, y: number): void;
|
|
81
|
+
/**
|
|
82
|
+
* Inject text typing. Optionally target a specific element.
|
|
83
|
+
*/
|
|
84
|
+
type(text: string, selector?: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Inject a key press.
|
|
87
|
+
*/
|
|
88
|
+
press(key: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Inject a scroll event.
|
|
91
|
+
*/
|
|
92
|
+
scroll(direction: 'up' | 'down' | 'left' | 'right', pixels?: number): void;
|
|
93
|
+
/**
|
|
94
|
+
* Fill an input element.
|
|
95
|
+
*/
|
|
96
|
+
fill(selector: string, text: string): void;
|
|
97
|
+
/**
|
|
98
|
+
* Update stream configuration (FPS, quality, resolution).
|
|
99
|
+
*/
|
|
100
|
+
setConfig(config: BrowserStreamConfig): void;
|
|
101
|
+
/**
|
|
102
|
+
* Pause the stream (stop frame capture).
|
|
103
|
+
*/
|
|
104
|
+
pause(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Resume the stream (restart frame capture).
|
|
107
|
+
*/
|
|
108
|
+
resume(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Register a frame callback.
|
|
111
|
+
*/
|
|
112
|
+
onFrame(callback: (frame: BrowserFrame) => void): void;
|
|
113
|
+
/**
|
|
114
|
+
* Register an error callback.
|
|
115
|
+
*/
|
|
116
|
+
onError(callback: (error: string) => void): void;
|
|
117
|
+
/**
|
|
118
|
+
* Register a state change callback.
|
|
119
|
+
*/
|
|
120
|
+
onStateChange(callback: (state: BrowserStreamState) => void): void;
|
|
121
|
+
private setState;
|
|
122
|
+
private send;
|
|
123
|
+
private handleMessage;
|
|
124
|
+
private handleReconnect;
|
|
125
|
+
private clearReconnectTimer;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=browser-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-stream.d.ts","sourceRoot":"","sources":["../src/browser-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Browser stream client for real-time viewport streaming.
|
|
3
|
+
* Connects to the /ws/browser-stream WebSocket endpoint and provides
|
|
4
|
+
* a typed API for receiving frames and injecting user input.
|
|
5
|
+
*/
|
|
6
|
+
import { createLogger } from '@agntk/logger';
|
|
7
|
+
const log = createLogger('@agntk/client:browser-stream');
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// BrowserStreamClient
|
|
10
|
+
// ============================================================================
|
|
11
|
+
export class BrowserStreamClient {
|
|
12
|
+
ws = null;
|
|
13
|
+
options;
|
|
14
|
+
state = 'disconnected';
|
|
15
|
+
callbacks = {};
|
|
16
|
+
reconnectAttempts = 0;
|
|
17
|
+
reconnectTimer = null;
|
|
18
|
+
frameCount = 0;
|
|
19
|
+
lastFrameTime = 0;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.options = {
|
|
22
|
+
reconnect: true,
|
|
23
|
+
maxReconnectAttempts: 5,
|
|
24
|
+
reconnectDelay: 1000,
|
|
25
|
+
...options,
|
|
26
|
+
};
|
|
27
|
+
log.debug('Created BrowserStreamClient', { url: options.url });
|
|
28
|
+
}
|
|
29
|
+
// --------------------------------------------------------------------------
|
|
30
|
+
// Lifecycle
|
|
31
|
+
// --------------------------------------------------------------------------
|
|
32
|
+
/**
|
|
33
|
+
* Connect to the browser stream WebSocket endpoint.
|
|
34
|
+
*/
|
|
35
|
+
connect(callbacks) {
|
|
36
|
+
if (callbacks)
|
|
37
|
+
this.callbacks = callbacks;
|
|
38
|
+
if (this.state === 'connected' || this.state === 'streaming') {
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}
|
|
41
|
+
this.setState('connecting');
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
try {
|
|
44
|
+
this.ws = new WebSocket(this.options.url);
|
|
45
|
+
this.ws.onopen = () => {
|
|
46
|
+
log.info('Browser stream connected');
|
|
47
|
+
this.setState('connected');
|
|
48
|
+
this.reconnectAttempts = 0;
|
|
49
|
+
resolve();
|
|
50
|
+
};
|
|
51
|
+
this.ws.onmessage = (event) => {
|
|
52
|
+
this.handleMessage(event);
|
|
53
|
+
};
|
|
54
|
+
this.ws.onclose = () => {
|
|
55
|
+
log.info('Browser stream disconnected');
|
|
56
|
+
if (this.state !== 'disconnected') {
|
|
57
|
+
this.handleReconnect();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
this.ws.onerror = (error) => {
|
|
61
|
+
log.error('Browser stream connection error', { error });
|
|
62
|
+
if (this.state === 'connecting') {
|
|
63
|
+
this.setState('disconnected');
|
|
64
|
+
reject(new Error('Failed to connect to browser stream'));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.setState('disconnected');
|
|
70
|
+
reject(new Error('Failed to create WebSocket connection'));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Disconnect from the browser stream.
|
|
76
|
+
*/
|
|
77
|
+
disconnect() {
|
|
78
|
+
log.debug('Disconnecting browser stream');
|
|
79
|
+
this.setState('disconnected');
|
|
80
|
+
this.clearReconnectTimer();
|
|
81
|
+
if (this.ws) {
|
|
82
|
+
this.ws.close();
|
|
83
|
+
this.ws = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get current connection state.
|
|
88
|
+
*/
|
|
89
|
+
getState() {
|
|
90
|
+
return this.state;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get frame statistics.
|
|
94
|
+
*/
|
|
95
|
+
getStats() {
|
|
96
|
+
const elapsed = (Date.now() - this.lastFrameTime) / 1000;
|
|
97
|
+
return {
|
|
98
|
+
frameCount: this.frameCount,
|
|
99
|
+
lastFrameTime: this.lastFrameTime,
|
|
100
|
+
fps: elapsed > 0 ? 1 / elapsed : 0,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// --------------------------------------------------------------------------
|
|
104
|
+
// Input Injection
|
|
105
|
+
// --------------------------------------------------------------------------
|
|
106
|
+
/**
|
|
107
|
+
* Inject a click at viewport coordinates.
|
|
108
|
+
*/
|
|
109
|
+
click(x, y) {
|
|
110
|
+
this.send({ type: 'click', x, y });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Inject text typing. Optionally target a specific element.
|
|
114
|
+
*/
|
|
115
|
+
type(text, selector) {
|
|
116
|
+
this.send({ type: 'type', text, selector });
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Inject a key press.
|
|
120
|
+
*/
|
|
121
|
+
press(key) {
|
|
122
|
+
this.send({ type: 'press', key });
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Inject a scroll event.
|
|
126
|
+
*/
|
|
127
|
+
scroll(direction, pixels) {
|
|
128
|
+
this.send({ type: 'scroll', direction, pixels });
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Fill an input element.
|
|
132
|
+
*/
|
|
133
|
+
fill(selector, text) {
|
|
134
|
+
this.send({ type: 'fill', selector, text });
|
|
135
|
+
}
|
|
136
|
+
// --------------------------------------------------------------------------
|
|
137
|
+
// Stream Control
|
|
138
|
+
// --------------------------------------------------------------------------
|
|
139
|
+
/**
|
|
140
|
+
* Update stream configuration (FPS, quality, resolution).
|
|
141
|
+
*/
|
|
142
|
+
setConfig(config) {
|
|
143
|
+
this.send({ type: 'config', ...config });
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Pause the stream (stop frame capture).
|
|
147
|
+
*/
|
|
148
|
+
pause() {
|
|
149
|
+
this.send({ type: 'stop' });
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Resume the stream (restart frame capture).
|
|
153
|
+
*/
|
|
154
|
+
resume() {
|
|
155
|
+
this.send({ type: 'start' });
|
|
156
|
+
}
|
|
157
|
+
// --------------------------------------------------------------------------
|
|
158
|
+
// Callbacks
|
|
159
|
+
// --------------------------------------------------------------------------
|
|
160
|
+
/**
|
|
161
|
+
* Register a frame callback.
|
|
162
|
+
*/
|
|
163
|
+
onFrame(callback) {
|
|
164
|
+
this.callbacks.onFrame = callback;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Register an error callback.
|
|
168
|
+
*/
|
|
169
|
+
onError(callback) {
|
|
170
|
+
this.callbacks.onError = callback;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Register a state change callback.
|
|
174
|
+
*/
|
|
175
|
+
onStateChange(callback) {
|
|
176
|
+
this.callbacks.onStateChange = callback;
|
|
177
|
+
}
|
|
178
|
+
// --------------------------------------------------------------------------
|
|
179
|
+
// Internal
|
|
180
|
+
// --------------------------------------------------------------------------
|
|
181
|
+
setState(newState) {
|
|
182
|
+
if (this.state !== newState) {
|
|
183
|
+
this.state = newState;
|
|
184
|
+
this.callbacks.onStateChange?.(newState);
|
|
185
|
+
log.debug('State changed', { state: newState });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
send(data) {
|
|
189
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
190
|
+
log.warn('Cannot send: WebSocket not connected');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
this.ws.send(JSON.stringify(data));
|
|
194
|
+
}
|
|
195
|
+
handleMessage(event) {
|
|
196
|
+
try {
|
|
197
|
+
const msg = JSON.parse(event.data);
|
|
198
|
+
switch (msg.type) {
|
|
199
|
+
case 'frame':
|
|
200
|
+
this.frameCount++;
|
|
201
|
+
this.lastFrameTime = Date.now();
|
|
202
|
+
if (this.state !== 'streaming') {
|
|
203
|
+
this.setState('streaming');
|
|
204
|
+
}
|
|
205
|
+
this.callbacks.onFrame?.({
|
|
206
|
+
data: msg.data,
|
|
207
|
+
timestamp: msg.timestamp,
|
|
208
|
+
sequence: msg.sequence,
|
|
209
|
+
});
|
|
210
|
+
break;
|
|
211
|
+
case 'started':
|
|
212
|
+
this.callbacks.onStarted?.(msg.config);
|
|
213
|
+
break;
|
|
214
|
+
case 'stopped':
|
|
215
|
+
if (this.state === 'streaming') {
|
|
216
|
+
this.setState('connected');
|
|
217
|
+
}
|
|
218
|
+
this.callbacks.onStopped?.();
|
|
219
|
+
break;
|
|
220
|
+
case 'error':
|
|
221
|
+
this.callbacks.onError?.(msg.error);
|
|
222
|
+
break;
|
|
223
|
+
case 'input-ack':
|
|
224
|
+
this.callbacks.onInputAck?.(msg.inputType, msg.success, msg.error);
|
|
225
|
+
break;
|
|
226
|
+
case 'config-ack':
|
|
227
|
+
this.callbacks.onConfigAck?.(msg.config);
|
|
228
|
+
break;
|
|
229
|
+
default:
|
|
230
|
+
log.warn('Unknown message type from server', { type: msg.type });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
log.error('Failed to parse server message', { error: String(err) });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
handleReconnect() {
|
|
238
|
+
if (!this.options.reconnect || this.state === 'disconnected')
|
|
239
|
+
return;
|
|
240
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
241
|
+
log.error('Max reconnect attempts reached for browser stream');
|
|
242
|
+
this.setState('disconnected');
|
|
243
|
+
this.callbacks.onError?.('Max reconnect attempts reached');
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.setState('reconnecting');
|
|
247
|
+
this.reconnectAttempts++;
|
|
248
|
+
const delay = Math.min(this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000);
|
|
249
|
+
log.info('Scheduling browser stream reconnect', { attempt: this.reconnectAttempts, delay });
|
|
250
|
+
this.clearReconnectTimer();
|
|
251
|
+
this.reconnectTimer = setTimeout(() => {
|
|
252
|
+
this.connect().catch(() => {
|
|
253
|
+
// Reconnect error handling is done in connect()
|
|
254
|
+
});
|
|
255
|
+
}, delay);
|
|
256
|
+
}
|
|
257
|
+
clearReconnectTimer() {
|
|
258
|
+
if (this.reconnectTimer) {
|
|
259
|
+
clearTimeout(this.reconnectTimer);
|
|
260
|
+
this.reconnectTimer = null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=browser-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-stream.js","sourceRoot":"","sources":["../src/browser-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AgentHttpClient } from './http-client.js';
|
|
2
|
+
import type { SessionManager } from './session.js';
|
|
3
|
+
import type { ChatRequest, GenerateStreamOptions, TokenUsage, ReconnectOptions, StreamMetadata } from './types.js';
|
|
4
|
+
export type StreamCallbacks = {
|
|
5
|
+
onTextDelta?: (text: string) => void;
|
|
6
|
+
onToolCall?: (toolCallId: string, name: string, args: unknown) => void;
|
|
7
|
+
onToolResult?: (toolCallId: string, name: string, result: unknown) => void;
|
|
8
|
+
onStepStart?: (index: number) => void;
|
|
9
|
+
onStepFinish?: (index: number, finishReason: string) => void;
|
|
10
|
+
onComplete?: (result: {
|
|
11
|
+
text: string;
|
|
12
|
+
usage?: TokenUsage;
|
|
13
|
+
}) => void;
|
|
14
|
+
onError?: (error: string) => void;
|
|
15
|
+
onReconnect?: (attempt: number, runId: string) => void;
|
|
16
|
+
};
|
|
17
|
+
export type ChatClientOptions = {
|
|
18
|
+
sessionManager?: SessionManager;
|
|
19
|
+
reconnect?: ReconnectOptions;
|
|
20
|
+
};
|
|
21
|
+
export declare class ChatClient {
|
|
22
|
+
private http;
|
|
23
|
+
private sessionManager?;
|
|
24
|
+
private reconnectConfig;
|
|
25
|
+
private _lastStreamMetadata?;
|
|
26
|
+
constructor(http: AgentHttpClient, options?: ChatClientOptions);
|
|
27
|
+
/**
|
|
28
|
+
* Get metadata from the last stream (workflow run ID, last event ID).
|
|
29
|
+
*/
|
|
30
|
+
get lastStreamMetadata(): StreamMetadata | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Stream a chat response with callback handlers.
|
|
33
|
+
* Supports auto-reconnection for resumable streams.
|
|
34
|
+
*/
|
|
35
|
+
stream(request: ChatRequest, callbacks: StreamCallbacks, options?: GenerateStreamOptions): Promise<void>;
|
|
36
|
+
private dispatch;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=chat-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-client.d.ts","sourceRoot":"","sources":["../src/chat-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EAErB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvE,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3E,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B,CAAC;AASF,qBAAa,UAAU;IAKT,OAAO,CAAC,IAAI;IAJxB,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,mBAAmB,CAAC,CAAiB;gBAEzB,IAAI,EAAE,eAAe,EAAE,OAAO,GAAE,iBAAsB;IAK1E;;OAEG;IACH,IAAI,kBAAkB,IAAI,cAAc,GAAG,SAAS,CAEnD;IAED;;;OAGG;IACG,MAAM,CACV,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC;IAwGhB,OAAO,CAAC,QAAQ;CA+BjB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { AgentHttpClient } from './http-client.js';
|
|
2
|
+
const DEFAULT_RECONNECT = {
|
|
3
|
+
enabled: true,
|
|
4
|
+
maxAttempts: 3,
|
|
5
|
+
baseDelayMs: 1000,
|
|
6
|
+
maxDelayMs: 30000,
|
|
7
|
+
};
|
|
8
|
+
export class ChatClient {
|
|
9
|
+
http;
|
|
10
|
+
sessionManager;
|
|
11
|
+
reconnectConfig;
|
|
12
|
+
_lastStreamMetadata;
|
|
13
|
+
constructor(http, options = {}) {
|
|
14
|
+
this.http = http;
|
|
15
|
+
this.sessionManager = options.sessionManager;
|
|
16
|
+
this.reconnectConfig = { ...DEFAULT_RECONNECT, ...options.reconnect };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get metadata from the last stream (workflow run ID, last event ID).
|
|
20
|
+
*/
|
|
21
|
+
get lastStreamMetadata() {
|
|
22
|
+
return this._lastStreamMetadata;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Stream a chat response with callback handlers.
|
|
26
|
+
* Supports auto-reconnection for resumable streams.
|
|
27
|
+
*/
|
|
28
|
+
async stream(request, callbacks, options = {}) {
|
|
29
|
+
try {
|
|
30
|
+
// If session manager is enabled and sessionId provided, append history
|
|
31
|
+
if (this.sessionManager && request.sessionId) {
|
|
32
|
+
const history = this.sessionManager.getHistory(request.sessionId);
|
|
33
|
+
if (history.length > 0) {
|
|
34
|
+
request.messages = [...history, ...request.messages];
|
|
35
|
+
}
|
|
36
|
+
// Add new user messages to session
|
|
37
|
+
for (const msg of request.messages.slice(history.length)) {
|
|
38
|
+
this.sessionManager.addMessage(request.sessionId, msg);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
let fullText = '';
|
|
42
|
+
let attempt = 0;
|
|
43
|
+
let workflowRunId = options.workflowRunId;
|
|
44
|
+
let lastEventId = options.lastEventId;
|
|
45
|
+
let completed = false;
|
|
46
|
+
while (!completed) {
|
|
47
|
+
try {
|
|
48
|
+
const streamOptions = {
|
|
49
|
+
...options,
|
|
50
|
+
workflowRunId,
|
|
51
|
+
lastEventId,
|
|
52
|
+
};
|
|
53
|
+
const generator = this.http.generateStream(request, streamOptions);
|
|
54
|
+
for await (const event of generator) {
|
|
55
|
+
if (event.type === 'text-delta') {
|
|
56
|
+
fullText += event.textDelta;
|
|
57
|
+
}
|
|
58
|
+
this.dispatch(event, callbacks);
|
|
59
|
+
// If we get any event successfully, reset attempt counter
|
|
60
|
+
attempt = 0;
|
|
61
|
+
}
|
|
62
|
+
// Stream finished normally
|
|
63
|
+
completed = true;
|
|
64
|
+
// Capture metadata for potential later reconnection
|
|
65
|
+
this._lastStreamMetadata = this.http.lastStreamMetadata;
|
|
66
|
+
if (this._lastStreamMetadata?.workflowRunId) {
|
|
67
|
+
workflowRunId = this._lastStreamMetadata.workflowRunId;
|
|
68
|
+
}
|
|
69
|
+
if (this._lastStreamMetadata?.lastEventId) {
|
|
70
|
+
lastEventId = this._lastStreamMetadata.lastEventId;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
// Capture what metadata we have before attempting reconnect
|
|
75
|
+
this._lastStreamMetadata = this.http.lastStreamMetadata;
|
|
76
|
+
if (this._lastStreamMetadata?.workflowRunId) {
|
|
77
|
+
workflowRunId = this._lastStreamMetadata.workflowRunId;
|
|
78
|
+
}
|
|
79
|
+
if (this._lastStreamMetadata?.lastEventId) {
|
|
80
|
+
lastEventId = this._lastStreamMetadata.lastEventId;
|
|
81
|
+
}
|
|
82
|
+
// Only attempt reconnection if:
|
|
83
|
+
// 1. We have a workflow run ID (durable stream)
|
|
84
|
+
// 2. Reconnect is enabled
|
|
85
|
+
// 3. We haven't exhausted attempts
|
|
86
|
+
// 4. The error isn't from an abort signal
|
|
87
|
+
const isAbort = error instanceof DOMException && error.name === 'AbortError';
|
|
88
|
+
const canReconnect = workflowRunId
|
|
89
|
+
&& this.reconnectConfig.enabled
|
|
90
|
+
&& attempt < this.reconnectConfig.maxAttempts
|
|
91
|
+
&& !isAbort;
|
|
92
|
+
if (!canReconnect) {
|
|
93
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
+
callbacks.onError?.(message);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
attempt++;
|
|
98
|
+
const delay = Math.min(this.reconnectConfig.baseDelayMs * Math.pow(2, attempt - 1), this.reconnectConfig.maxDelayMs);
|
|
99
|
+
callbacks.onReconnect?.(attempt, workflowRunId);
|
|
100
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Add assistant response to session
|
|
104
|
+
if (this.sessionManager && request.sessionId && fullText) {
|
|
105
|
+
this.sessionManager.addMessage(request.sessionId, {
|
|
106
|
+
role: 'assistant',
|
|
107
|
+
content: fullText,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
113
|
+
callbacks.onError?.(message);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
dispatch(event, callbacks) {
|
|
117
|
+
switch (event.type) {
|
|
118
|
+
case 'text-delta':
|
|
119
|
+
callbacks.onTextDelta?.(event.textDelta);
|
|
120
|
+
break;
|
|
121
|
+
case 'tool-call':
|
|
122
|
+
callbacks.onToolCall?.(event.toolCallId, event.toolName, event.args);
|
|
123
|
+
break;
|
|
124
|
+
case 'tool-result':
|
|
125
|
+
callbacks.onToolResult?.(event.toolCallId, event.toolName, event.result);
|
|
126
|
+
break;
|
|
127
|
+
case 'step-start':
|
|
128
|
+
callbacks.onStepStart?.(event.stepIndex);
|
|
129
|
+
break;
|
|
130
|
+
case 'step-finish':
|
|
131
|
+
callbacks.onStepFinish?.(event.stepIndex, event.finishReason);
|
|
132
|
+
break;
|
|
133
|
+
case 'finish':
|
|
134
|
+
callbacks.onComplete?.({ text: event.text, usage: event.usage });
|
|
135
|
+
break;
|
|
136
|
+
case 'error':
|
|
137
|
+
callbacks.onError?.(event.error);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=chat-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-client.js","sourceRoot":"","sources":["../src/chat-client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AgentHttpClient } from './http-client.js';
|
|
2
|
+
import { type WebSocketCallbacks, type ConnectionState } from './websocket-client.js';
|
|
3
|
+
import type { ChatRequest, ChatResponse, ChatMessage } from './types.js';
|
|
4
|
+
export interface AgentClientOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
useWebSocket?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class AgentClient {
|
|
9
|
+
private httpClient;
|
|
10
|
+
private wsClient?;
|
|
11
|
+
constructor(options: AgentClientOptions);
|
|
12
|
+
getHttpClient(): AgentHttpClient;
|
|
13
|
+
generate(request: ChatRequest): Promise<ChatResponse>;
|
|
14
|
+
stream(message: ChatMessage, callbacks: WebSocketCallbacks): Promise<void>;
|
|
15
|
+
onConnectionStateChange(handler: (state: ConnectionState) => void): void;
|
|
16
|
+
disconnect(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=client.d.ts.map
|