@symbolica/agentica 0.3.1 → 0.4.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/LICENSE +21 -77
- package/README.md +10 -9
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/src/agentica/agent.d.ts +3 -2
- package/dist/src/agentica/agent.d.ts.map +1 -1
- package/dist/src/agentica/agent.js +3 -4
- package/dist/src/agentica/agent.js.map +1 -1
- package/dist/src/agentica/agentic.d.ts.map +1 -1
- package/dist/src/agentica/agentic.js +1 -3
- package/dist/src/agentica/agentic.js.map +1 -1
- package/dist/src/agentica/common.d.ts +10 -5
- package/dist/src/agentica/common.d.ts.map +1 -1
- package/dist/src/agentica/common.js +32 -17
- package/dist/src/agentica/common.js.map +1 -1
- package/dist/src/agentica-unplugin.d.ts +2 -2
- package/dist/src/agentica-unplugin.d.ts.map +1 -1
- package/dist/src/bundlers/esbuild.d.ts +1 -1
- package/dist/src/bundlers/vite.d.ts +1 -1
- package/dist/src/client-session-manager/client-session-manager.d.ts +10 -8
- package/dist/src/client-session-manager/client-session-manager.d.ts.map +1 -1
- package/dist/src/client-session-manager/client-session-manager.js +172 -95
- package/dist/src/client-session-manager/client-session-manager.js.map +1 -1
- package/dist/src/client-session-manager/types.d.ts +1 -1
- package/dist/src/client-session-manager/types.d.ts.map +1 -1
- package/dist/src/coming-soon.d.ts +7 -18
- package/dist/src/coming-soon.d.ts.map +1 -1
- package/dist/src/coming-soon.js +21 -41
- package/dist/src/coming-soon.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.d.ts +7 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.d.ts.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.js +144 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.js.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.test.d.ts +2 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.test.d.ts.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.test.js +253 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/str.test.js.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/utils.d.ts +5 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/utils.d.ts.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/utils.js +17 -0
- package/dist/src/warpc/msg-protocol/concept/python-mirrors/utils.js.map +1 -0
- package/dist/src/warpc/msg-protocol/concept/resource/system-msg.d.ts +2 -1
- package/dist/src/warpc/msg-protocol/concept/resource/system-msg.d.ts.map +1 -1
- package/dist/src/warpc/msg-protocol/concept/resource/system-msg.js +14 -10
- package/dist/src/warpc/msg-protocol/concept/resource/system-msg.js.map +1 -1
- package/dist-transformer/agentica/agent.d.ts +4 -2
- package/dist-transformer/agentica/agent.d.ts.map +1 -1
- package/dist-transformer/agentica/agent.js +3 -3
- package/dist-transformer/agentica/agentic.d.ts.map +1 -1
- package/dist-transformer/agentica/agentic.js +1 -3
- package/dist-transformer/agentica/common.d.ts +23 -13
- package/dist-transformer/agentica/common.d.ts.map +1 -1
- package/dist-transformer/agentica/common.js +46 -25
- package/dist-transformer/client-session-manager/client-session-manager.d.ts +20 -12
- package/dist-transformer/client-session-manager/client-session-manager.d.ts.map +1 -1
- package/dist-transformer/client-session-manager/client-session-manager.js +214 -108
- package/dist-transformer/client-session-manager/types.d.ts +1 -1
- package/dist-transformer/client-session-manager/types.d.ts.map +1 -1
- package/dist-transformer/coming-soon.d.ts +7 -18
- package/dist-transformer/coming-soon.d.ts.map +1 -1
- package/dist-transformer/coming-soon.js +21 -39
- package/dist-transformer/version.d.ts +1 -1
- package/dist-transformer/version.js +1 -1
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/str.d.ts +7 -0
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/str.d.ts.map +1 -0
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/str.js +151 -0
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/utils.d.ts +5 -0
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/utils.d.ts.map +1 -0
- package/dist-transformer/warpc/msg-protocol/concept/python-mirrors/utils.js +16 -0
- package/dist-transformer/warpc/msg-protocol/concept/resource/system-msg.d.ts +2 -1
- package/dist-transformer/warpc/msg-protocol/concept/resource/system-msg.d.ts.map +1 -1
- package/dist-transformer/warpc/msg-protocol/concept/resource/system-msg.js +14 -11
- package/package.json +5 -3
|
@@ -20,9 +20,9 @@ export interface InvokeAgentParams {
|
|
|
20
20
|
parentIid?: string;
|
|
21
21
|
}
|
|
22
22
|
export declare class ClientSessionManager {
|
|
23
|
-
private
|
|
24
|
-
private
|
|
25
|
-
private
|
|
23
|
+
private sessionManagers;
|
|
24
|
+
private smLocks;
|
|
25
|
+
private uidToSm;
|
|
26
26
|
private uidIidRecvQueue;
|
|
27
27
|
private uidIidException;
|
|
28
28
|
private matchIid;
|
|
@@ -46,15 +46,17 @@ export declare class ClientSessionManager {
|
|
|
46
46
|
setEndpoints(baseHttp: string, baseWs: string): void;
|
|
47
47
|
private registerSession;
|
|
48
48
|
private buildHeaders;
|
|
49
|
-
private
|
|
50
|
-
private
|
|
51
|
-
private
|
|
49
|
+
private smWriter;
|
|
50
|
+
private smReader;
|
|
51
|
+
private _failSmFutures;
|
|
52
|
+
private _cleanupSessionManager;
|
|
53
|
+
private _ensureSmConnection;
|
|
52
54
|
private _initAgentState;
|
|
53
55
|
newAgent(cmar: CreateAgentRequest, parentLogger?: ScopedLogger): Promise<string>;
|
|
54
56
|
invokeAgent(params: InvokeAgentParams, parentLogger?: ScopedLogger): Promise<AgentInvocationHandle>;
|
|
55
57
|
echo(cancelSignal: AbortSignal, uid: string, iid?: string): AsyncGenerator<Chunk, void, unknown>;
|
|
56
58
|
logs(uid: string, iid?: string, params?: Record<string, any>): Promise<Array<Record<string, any>>>;
|
|
57
|
-
fetchUsage(uid: string, iid: string,
|
|
59
|
+
fetchUsage(uid: string, iid: string, _lastTotal?: Usage): Promise<{
|
|
58
60
|
usage: Usage;
|
|
59
61
|
newTotal: Usage;
|
|
60
62
|
}>;
|
|
@@ -69,5 +71,5 @@ declare global {
|
|
|
69
71
|
var __AGENTICA_AGENTIC_MANAGER: ClientSessionManager | undefined;
|
|
70
72
|
}
|
|
71
73
|
export declare const __AGENTIC_MANAGER: ClientSessionManager;
|
|
72
|
-
export declare const __AGENTIC_PROTO_VER = "typescript/0.
|
|
74
|
+
export declare const __AGENTIC_PROTO_VER = "typescript/0.4.0";
|
|
73
75
|
//# sourceMappingURL=client-session-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-session-manager.d.ts","sourceRoot":"","sources":["../../../src/client-session-manager/client-session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,kBAAkB,EAKlB,cAAc,EACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAY,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EAAE,KAAK,YAAY,EAA+B,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"client-session-manager.d.ts","sourceRoot":"","sources":["../../../src/client-session-manager/client-session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,9 +27,9 @@ import { injectTraceContext } from "../otel-config.js";
|
|
|
27
27
|
import { CustomLogFW } from "../otel-logging.js";
|
|
28
28
|
import { version } from "../version.js";
|
|
29
29
|
export class ClientSessionManager {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
sessionManagers = new Map();
|
|
31
|
+
smLocks = new Map();
|
|
32
|
+
uidToSm = new Map();
|
|
33
33
|
uidIidRecvQueue;
|
|
34
34
|
uidIidException;
|
|
35
35
|
matchIid;
|
|
@@ -136,29 +136,28 @@ export class ClientSessionManager {
|
|
|
136
136
|
headers['X-Client-Session-ID'] = this.clientSessionId;
|
|
137
137
|
return headers;
|
|
138
138
|
}
|
|
139
|
-
async
|
|
139
|
+
async smWriter(smId, control) {
|
|
140
140
|
await waitForTracing;
|
|
141
|
-
const wsLogger = this.logger.withScope(
|
|
141
|
+
const wsLogger = this.logger.withScope(`ws-writer-${smId.slice(0, 8)}`);
|
|
142
142
|
wsLogger.debug('Writer task started');
|
|
143
|
-
const ws = this.websocket;
|
|
144
143
|
try {
|
|
145
144
|
while (!control.shouldStop) {
|
|
145
|
+
const smc = this.sessionManagers.get(smId);
|
|
146
|
+
if (!smc) {
|
|
147
|
+
wsLogger.debug('Session manager connection removed, exiting writer');
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
146
150
|
try {
|
|
147
|
-
const
|
|
148
|
-
if (!sendQueue) {
|
|
149
|
-
wsLogger.debug('Send queue removed, exiting writer');
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
const msg = await sendQueue.get();
|
|
151
|
+
const msg = await smc.sendQueue.get();
|
|
153
152
|
const msgUid = msg.uid;
|
|
154
153
|
const msgLogger = msgUid ? (this.uidToLogger.get(msgUid) ?? wsLogger) : wsLogger;
|
|
155
|
-
if (
|
|
154
|
+
if (smc.websocket.readyState !== 1) {
|
|
156
155
|
const error = new WebSocketConnectionError(`cannot send as websocket is not open.`);
|
|
157
156
|
enrichError(error, { uid: msgUid, sessionId: this.clientSessionId });
|
|
158
157
|
throw error;
|
|
159
158
|
}
|
|
160
159
|
msgLogger.debug(`Sending ${msg.type} message`);
|
|
161
|
-
|
|
160
|
+
smc.websocket.send(encodeMessage(msg));
|
|
162
161
|
}
|
|
163
162
|
catch (error) {
|
|
164
163
|
if (error instanceof Error && error.message === 'Queue closed') {
|
|
@@ -172,23 +171,20 @@ export class ClientSessionManager {
|
|
|
172
171
|
}
|
|
173
172
|
catch (error) {
|
|
174
173
|
wsLogger.error('Writer task failed', error);
|
|
175
|
-
|
|
176
|
-
handlers.reject(new WebSocketConnectionError(`WebSocket writer failed: ${error.message}`));
|
|
177
|
-
this.matchIid.delete(matchId);
|
|
178
|
-
}
|
|
179
|
-
for (const [_, exceptionMap] of this.uidIidException.entries()) {
|
|
180
|
-
for (const [_iid, handlers] of exceptionMap.entries()) {
|
|
181
|
-
handlers.reject(new WebSocketConnectionError(`WebSocket writer failed: ${error.message}`));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
174
|
+
await this._cleanupSessionManager(smId);
|
|
184
175
|
throw error;
|
|
185
176
|
}
|
|
186
177
|
}
|
|
187
|
-
async
|
|
178
|
+
async smReader(smId, control) {
|
|
188
179
|
await waitForTracing;
|
|
189
|
-
const wsLogger = this.logger.withScope(
|
|
180
|
+
const wsLogger = this.logger.withScope(`ws-reader-${smId.slice(0, 8)}`);
|
|
190
181
|
wsLogger.debug('Reader task started');
|
|
191
|
-
const
|
|
182
|
+
const smc = this.sessionManagers.get(smId);
|
|
183
|
+
if (!smc) {
|
|
184
|
+
wsLogger.warn('Session manager connection not found');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const ws = smc.websocket;
|
|
192
188
|
ws.onmessage = (event) => {
|
|
193
189
|
if (control.shouldStop)
|
|
194
190
|
return;
|
|
@@ -289,45 +285,99 @@ export class ClientSessionManager {
|
|
|
289
285
|
ws.onclose = (event) => {
|
|
290
286
|
wsLogger.debug(`WebSocket closed (code=${event.code}, reason=${event.reason || 'none'})`);
|
|
291
287
|
control.shouldStop = true;
|
|
292
|
-
|
|
293
|
-
handlers.reject(new WebSocketConnectionError(`WebSocket closed: ${event.reason || 'Connection closed'}`));
|
|
294
|
-
this.matchIid.delete(matchId);
|
|
295
|
-
}
|
|
296
|
-
for (const [_, exceptionMap] of this.uidIidException.entries()) {
|
|
297
|
-
for (const [_iid, handlers] of exceptionMap.entries()) {
|
|
298
|
-
handlers.reject(new WebSocketConnectionError(`WebSocket closed: ${event.reason || 'Connection closed'}`));
|
|
299
|
-
}
|
|
300
|
-
exceptionMap.clear();
|
|
301
|
-
}
|
|
288
|
+
this._failSmFutures(smId, `WebSocket closed: ${event.reason || 'Connection closed'}`);
|
|
302
289
|
resolve();
|
|
303
290
|
};
|
|
304
291
|
ws.onerror = (_error) => {
|
|
305
292
|
wsLogger.error('WebSocket error');
|
|
306
293
|
control.shouldStop = true;
|
|
307
|
-
|
|
308
|
-
handlers.reject(new WebSocketConnectionError('WebSocket error occurred'));
|
|
309
|
-
this.matchIid.delete(matchId);
|
|
310
|
-
}
|
|
311
|
-
for (const [_, exceptionMap] of this.uidIidException.entries()) {
|
|
312
|
-
for (const [_iid, handlers] of exceptionMap.entries()) {
|
|
313
|
-
handlers.reject(new WebSocketConnectionError('WebSocket error occurred'));
|
|
314
|
-
}
|
|
315
|
-
exceptionMap.clear();
|
|
316
|
-
}
|
|
294
|
+
this._failSmFutures(smId, 'WebSocket error occurred');
|
|
317
295
|
resolve();
|
|
318
296
|
};
|
|
319
297
|
});
|
|
320
298
|
}
|
|
321
|
-
|
|
322
|
-
|
|
299
|
+
_failSmFutures(smId, reason) {
|
|
300
|
+
const affectedUids = [];
|
|
301
|
+
for (const [uid, sid] of this.uidToSm.entries()) {
|
|
302
|
+
if (sid === smId) {
|
|
303
|
+
affectedUids.push(uid);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
for (const [matchId, handlers] of this.matchIid.entries()) {
|
|
307
|
+
handlers.reject(new WebSocketConnectionError(reason));
|
|
308
|
+
this.matchIid.delete(matchId);
|
|
309
|
+
}
|
|
310
|
+
for (const uid of affectedUids) {
|
|
311
|
+
const exceptionMap = this.uidIidException.get(uid);
|
|
312
|
+
if (exceptionMap) {
|
|
313
|
+
for (const [_iid, handlers] of exceptionMap.entries()) {
|
|
314
|
+
handlers.reject(new WebSocketConnectionError(reason));
|
|
315
|
+
}
|
|
316
|
+
exceptionMap.clear();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async _cleanupSessionManager(smId) {
|
|
321
|
+
const smc = this.sessionManagers.get(smId);
|
|
322
|
+
if (!smc) {
|
|
323
323
|
return;
|
|
324
324
|
}
|
|
325
|
+
this.logger.debug(`Cleaning up session manager ${smId.slice(0, 8)}`);
|
|
326
|
+
this.sessionManagers.delete(smId);
|
|
327
|
+
this.smLocks.delete(smId);
|
|
328
|
+
const [readerControl, writerControl] = smc.tasks;
|
|
329
|
+
readerControl.shouldStop = true;
|
|
330
|
+
writerControl.shouldStop = true;
|
|
331
|
+
smc.sendQueue.close();
|
|
332
|
+
try {
|
|
333
|
+
if (smc.websocket.readyState === 0 || smc.websocket.readyState === 1) {
|
|
334
|
+
smc.websocket.close(1000, 'Normal closure');
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
this.logger.warn(`Failed to close WebSocket for session manager ${smId.slice(0, 8)}`, error);
|
|
339
|
+
}
|
|
340
|
+
await Promise.allSettled([readerControl.promise, writerControl.promise]);
|
|
341
|
+
this._failSmFutures(smId, 'Session manager connection closed');
|
|
342
|
+
const affectedUids = [];
|
|
343
|
+
for (const [uid, sid] of this.uidToSm.entries()) {
|
|
344
|
+
if (sid === smId) {
|
|
345
|
+
affectedUids.push(uid);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
for (const uid of affectedUids) {
|
|
349
|
+
this.uidToSm.delete(uid);
|
|
350
|
+
}
|
|
351
|
+
this.logger.debug(`Cleaned up session manager ${smId.slice(0, 8)}`);
|
|
352
|
+
}
|
|
353
|
+
async _ensureSmConnection(smId) {
|
|
354
|
+
const existing = this.sessionManagers.get(smId);
|
|
355
|
+
if (existing && existing.websocket.readyState === 1) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const existingLock = this.smLocks.get(smId);
|
|
359
|
+
if (existingLock) {
|
|
360
|
+
await existingLock;
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
let resolveLock;
|
|
364
|
+
const lockPromise = new Promise((resolve) => {
|
|
365
|
+
resolveLock = resolve;
|
|
366
|
+
});
|
|
367
|
+
this.smLocks.set(smId, lockPromise);
|
|
325
368
|
await waitForTracing;
|
|
326
|
-
const span = this.logger.startSpan('sdk.
|
|
369
|
+
const span = this.logger.startSpan('sdk.sm_connection');
|
|
370
|
+
span.setAttribute('session_manager.id', smId);
|
|
327
371
|
try {
|
|
328
|
-
|
|
372
|
+
const doubleCheck = this.sessionManagers.get(smId);
|
|
373
|
+
if (doubleCheck && doubleCheck.websocket.readyState === 1) {
|
|
374
|
+
resolveLock();
|
|
375
|
+
this.smLocks.delete(smId);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const sendQueue = new Queue();
|
|
329
379
|
const websocket_uri = `${this.baseWs}/socket`;
|
|
330
|
-
this.logger.debug(`Connecting WebSocket`);
|
|
380
|
+
this.logger.debug(`Connecting WebSocket for session manager ${smId.slice(0, 8)}`);
|
|
331
381
|
span.setAttribute('websocket.uri', websocket_uri);
|
|
332
382
|
span.setAttribute('websocket.state', 'connecting');
|
|
333
383
|
const headers = {};
|
|
@@ -347,7 +397,6 @@ export class ClientSessionManager {
|
|
|
347
397
|
ws.binaryType = 'arraybuffer';
|
|
348
398
|
return new Promise((resolve, reject) => {
|
|
349
399
|
ws.onopen = () => {
|
|
350
|
-
this.websocket = ws;
|
|
351
400
|
try {
|
|
352
401
|
ws._socket?.unref?.();
|
|
353
402
|
}
|
|
@@ -361,23 +410,32 @@ export class ClientSessionManager {
|
|
|
361
410
|
shouldStop: false,
|
|
362
411
|
promise: Promise.resolve(),
|
|
363
412
|
};
|
|
364
|
-
|
|
365
|
-
|
|
413
|
+
const smc = {
|
|
414
|
+
websocket: ws,
|
|
415
|
+
sendQueue,
|
|
416
|
+
tasks: [readerControl, writerControl],
|
|
417
|
+
};
|
|
418
|
+
this.sessionManagers.set(smId, smc);
|
|
419
|
+
readerControl.promise = this.smReader(smId, readerControl).catch((error) => {
|
|
420
|
+
this.logger.error(`Reader task crashed for session manager ${smId.slice(0, 8)}`, error);
|
|
366
421
|
});
|
|
367
|
-
writerControl.promise = this.
|
|
368
|
-
this.logger.error(
|
|
422
|
+
writerControl.promise = this.smWriter(smId, writerControl).catch((error) => {
|
|
423
|
+
this.logger.error(`Writer task crashed for session manager ${smId.slice(0, 8)}`, error);
|
|
369
424
|
});
|
|
370
|
-
this.
|
|
371
|
-
this.logger.info(`WebSocket connected`);
|
|
425
|
+
this.logger.info(`WebSocket connected for session manager ${smId.slice(0, 8)}`);
|
|
372
426
|
span.setAttribute('websocket.state', 'connected');
|
|
373
427
|
span.end();
|
|
428
|
+
resolveLock();
|
|
429
|
+
this.smLocks.delete(smId);
|
|
374
430
|
resolve();
|
|
375
431
|
};
|
|
376
432
|
ws.onerror = (error) => {
|
|
377
|
-
this.logger.error(`WebSocket connection failed:\n${error.toString()}`);
|
|
433
|
+
this.logger.error(`WebSocket connection failed for session manager ${smId.slice(0, 8)}:\n${error.toString()}`);
|
|
378
434
|
span.setAttribute('websocket.state', 'error');
|
|
379
435
|
span.recordException(error);
|
|
380
436
|
span.end();
|
|
437
|
+
resolveLock();
|
|
438
|
+
this.smLocks.delete(smId);
|
|
381
439
|
reject(new WebSocketConnectionError('WebSocket connection failed'));
|
|
382
440
|
};
|
|
383
441
|
});
|
|
@@ -386,6 +444,8 @@ export class ClientSessionManager {
|
|
|
386
444
|
span.setAttribute('websocket.state', 'error');
|
|
387
445
|
span.recordException(error);
|
|
388
446
|
span.end();
|
|
447
|
+
resolveLock();
|
|
448
|
+
this.smLocks.delete(smId);
|
|
389
449
|
throw error;
|
|
390
450
|
}
|
|
391
451
|
}
|
|
@@ -457,10 +517,22 @@ export class ClientSessionManager {
|
|
|
457
517
|
logger.warn(message);
|
|
458
518
|
}
|
|
459
519
|
}
|
|
460
|
-
const
|
|
520
|
+
const responseData = await response.json();
|
|
521
|
+
const uid = responseData.uid;
|
|
522
|
+
const smId = responseData.session_manager_id;
|
|
523
|
+
if (!uid) {
|
|
524
|
+
logger.error(`Server response missing "uid" field: ${JSON.stringify(responseData)}`);
|
|
525
|
+
throw new ConnectionError('Invalid server response: missing "uid" field');
|
|
526
|
+
}
|
|
527
|
+
if (!smId) {
|
|
528
|
+
logger.error(`Server response missing "session_manager_id" field: ${JSON.stringify(responseData)}`);
|
|
529
|
+
throw new ConnectionError('Invalid server response: missing "session_manager_id" field');
|
|
530
|
+
}
|
|
461
531
|
logger.info('Created agent');
|
|
462
532
|
span.setAttribute('agent.uid', uid);
|
|
463
|
-
|
|
533
|
+
span.setAttribute('agent.session_manager_id', smId);
|
|
534
|
+
this.uidToSm.set(uid, smId);
|
|
535
|
+
await this._ensureSmConnection(smId);
|
|
464
536
|
this.knownUids.add(uid);
|
|
465
537
|
this._initAgentState(uid, parentLogger);
|
|
466
538
|
return uid;
|
|
@@ -493,7 +565,20 @@ export class ClientSessionManager {
|
|
|
493
565
|
enrichError(error, { uid, sessionId: this.clientSessionId });
|
|
494
566
|
throw error;
|
|
495
567
|
}
|
|
568
|
+
const smId = this.uidToSm.get(uid);
|
|
569
|
+
if (!smId) {
|
|
570
|
+
const error = new WebSocketConnectionError(`No session manager found for agent ${uid}`);
|
|
571
|
+
enrichError(error, { uid, sessionId: this.clientSessionId });
|
|
572
|
+
throw error;
|
|
573
|
+
}
|
|
574
|
+
const smc = this.sessionManagers.get(smId);
|
|
575
|
+
if (!smc || smc.websocket.readyState !== 1) {
|
|
576
|
+
const error = new WebSocketConnectionError(`No active connection for session manager ${smId}`);
|
|
577
|
+
enrichError(error, { uid, sessionId: this.clientSessionId });
|
|
578
|
+
throw error;
|
|
579
|
+
}
|
|
496
580
|
span.setAttribute('agent.uid', uid);
|
|
581
|
+
span.setAttribute('agent.session_manager_id', smId);
|
|
497
582
|
span.setAttribute('agent.task_desc', typeof taskDesc === 'string' ? taskDesc : taskDesc.template);
|
|
498
583
|
span.setAttribute('invocation.streaming', streaming);
|
|
499
584
|
const matchId = this.idIssuer();
|
|
@@ -506,11 +591,11 @@ export class ClientSessionManager {
|
|
|
506
591
|
prompt: taskDesc,
|
|
507
592
|
streaming: streaming,
|
|
508
593
|
};
|
|
509
|
-
invLogger.debug(`Invoking with match_id=${matchId}`);
|
|
594
|
+
invLogger.debug(`Invoking with match_id=${matchId} on session manager ${smId.slice(0, 8)}`);
|
|
510
595
|
const iidPromise = new Promise((resolve, reject) => {
|
|
511
596
|
this.matchIid.set(matchId, { resolve, reject });
|
|
512
597
|
});
|
|
513
|
-
|
|
598
|
+
smc.sendQueue.put(msg);
|
|
514
599
|
const iid = await iidPromise;
|
|
515
600
|
this.iidToUid.set(iid, uid);
|
|
516
601
|
invLogger.info(`Invocation created with iid=${iid}`);
|
|
@@ -527,8 +612,13 @@ export class ClientSessionManager {
|
|
|
527
612
|
return { resolvers: { resolve, reject, promise }, promise };
|
|
528
613
|
})();
|
|
529
614
|
this.uidIidException.get(uid).set(iid, resolvers);
|
|
615
|
+
const capturedSmId = smId;
|
|
530
616
|
return {
|
|
531
617
|
send_message: async (data) => {
|
|
618
|
+
const currentSmc = this.sessionManagers.get(capturedSmId);
|
|
619
|
+
if (!currentSmc || currentSmc.websocket.readyState !== 1) {
|
|
620
|
+
throw new WebSocketConnectionError(`Session manager connection closed for ${capturedSmId}`);
|
|
621
|
+
}
|
|
532
622
|
const dataMsg = {
|
|
533
623
|
type: 'data',
|
|
534
624
|
uid,
|
|
@@ -536,7 +626,7 @@ export class ClientSessionManager {
|
|
|
536
626
|
data,
|
|
537
627
|
timestamp: new Date().toISOString(),
|
|
538
628
|
};
|
|
539
|
-
|
|
629
|
+
currentSmc.sendQueue.put(dataMsg);
|
|
540
630
|
invLogger.debug(`Queued ${data.length} bytes to send`);
|
|
541
631
|
},
|
|
542
632
|
recv_message: async () => {
|
|
@@ -728,23 +818,27 @@ export class ClientSessionManager {
|
|
|
728
818
|
}
|
|
729
819
|
return response.json();
|
|
730
820
|
}
|
|
731
|
-
async fetchUsage(uid, iid,
|
|
821
|
+
async fetchUsage(uid, iid, _lastTotal) {
|
|
732
822
|
let total = Usage.zero();
|
|
733
823
|
const logs = await this.logs(uid, iid, { type: 'sm_inference_usage' });
|
|
734
824
|
for (const log of logs) {
|
|
735
825
|
const logUsage = log.usage;
|
|
736
826
|
if (logUsage) {
|
|
737
|
-
total = total.add(Usage.fromCompletions(logUsage
|
|
827
|
+
total = total.add(Usage.fromCompletions(logUsage));
|
|
738
828
|
}
|
|
739
829
|
}
|
|
740
|
-
|
|
741
|
-
if (lastTotal) {
|
|
742
|
-
usage = total.sub(lastTotal.replace({ outputTokens: 0 }));
|
|
743
|
-
}
|
|
744
|
-
return { usage, newTotal: total };
|
|
830
|
+
return { usage: total, newTotal: total };
|
|
745
831
|
}
|
|
746
832
|
agentExists(uid) {
|
|
747
|
-
|
|
833
|
+
if (!this.knownUids.has(uid)) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
const smId = this.uidToSm.get(uid);
|
|
837
|
+
if (!smId) {
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
const smc = this.sessionManagers.get(smId);
|
|
841
|
+
return smc !== undefined && smc.websocket.readyState === 1;
|
|
748
842
|
}
|
|
749
843
|
getUidForIid(iid) {
|
|
750
844
|
return this.iidToUid.get(iid);
|
|
@@ -796,6 +890,7 @@ export class ClientSessionManager {
|
|
|
796
890
|
this.uidIidException.delete(uid);
|
|
797
891
|
this.knownUids.delete(uid);
|
|
798
892
|
this.uidToLogger.delete(uid);
|
|
893
|
+
this.uidToSm.delete(uid);
|
|
799
894
|
logger.debug(`Closed agent ${uid.slice(0, 8)}`);
|
|
800
895
|
await this.destroyAgent(uid);
|
|
801
896
|
this.unrefConnection();
|
|
@@ -807,32 +902,14 @@ export class ClientSessionManager {
|
|
|
807
902
|
const span = this.logger.startSpan('stop');
|
|
808
903
|
try {
|
|
809
904
|
const agentCount = this.knownUids.size;
|
|
810
|
-
this.
|
|
905
|
+
const smCount = this.sessionManagers.size;
|
|
906
|
+
this.logger.debug(`CSM Stop: stopping with ${agentCount} agent(s) on ${smCount} session manager(s)`);
|
|
811
907
|
span.setAttribute('agent_count', agentCount);
|
|
908
|
+
span.setAttribute('session_manager_count', smCount);
|
|
812
909
|
const uids = Array.from(this.knownUids);
|
|
813
910
|
await Promise.allSettled(uids.map((uid) => this.closeAgent(uid)));
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
this.sendQueue = null;
|
|
817
|
-
}
|
|
818
|
-
if (this.websocket) {
|
|
819
|
-
try {
|
|
820
|
-
if (this.websocket.readyState === 0 || this.websocket.readyState === 1) {
|
|
821
|
-
this.websocket.close(1000, 'Normal closure');
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
catch (error) {
|
|
825
|
-
this.logger.warn('Failed to close WebSocket', error);
|
|
826
|
-
}
|
|
827
|
-
this.websocket = null;
|
|
828
|
-
}
|
|
829
|
-
if (this.tasks) {
|
|
830
|
-
const [readerControl, writerControl] = this.tasks;
|
|
831
|
-
readerControl.shouldStop = true;
|
|
832
|
-
writerControl.shouldStop = true;
|
|
833
|
-
await Promise.allSettled([readerControl.promise, writerControl.promise]);
|
|
834
|
-
this.tasks = null;
|
|
835
|
-
}
|
|
911
|
+
const smIds = Array.from(this.sessionManagers.keys());
|
|
912
|
+
await Promise.allSettled(smIds.map((smId) => this._cleanupSessionManager(smId)));
|
|
836
913
|
this.logger.debug('All resources cleaned up');
|
|
837
914
|
this.isStopped = true;
|
|
838
915
|
if (this.invocationGuard) {
|