@robosystems/client 1.12.2 → 1.13.1
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/artifacts/InvestorClient.d.ts +7 -0
- package/artifacts/InvestorClient.ts +7 -0
- package/artifacts/LedgerClient.d.ts +7 -0
- package/artifacts/LedgerClient.ts +7 -0
- package/artifacts/LibraryClient.d.ts +7 -0
- package/artifacts/LibraryClient.ts +7 -0
- package/artifacts/OperationClient.d.ts +2 -0
- package/artifacts/OperationClient.ts +3 -0
- package/artifacts/OperatorClient.d.ts +40 -6
- package/artifacts/OperatorClient.js +171 -105
- package/artifacts/OperatorClient.ts +231 -134
- package/artifacts/QueryClient.d.ts +2 -0
- package/artifacts/QueryClient.ts +3 -0
- package/artifacts/SSEClient.d.ts +26 -0
- package/artifacts/SSEClient.js +28 -2
- package/artifacts/SSEClient.ts +51 -3
- package/artifacts/graphql/client.d.ts +8 -0
- package/artifacts/graphql/client.js +8 -1
- package/artifacts/graphql/client.ts +17 -1
- package/artifacts/hooks.js +5 -0
- package/artifacts/hooks.ts +5 -0
- package/artifacts/index.d.ts +7 -3
- package/artifacts/index.js +38 -3
- package/artifacts/index.ts +47 -5
- package/artifacts/retry.d.ts +59 -0
- package/artifacts/retry.js +121 -0
- package/artifacts/retry.ts +134 -0
- package/package.json +1 -1
|
@@ -30,6 +30,13 @@ interface InvestorClientConfig {
|
|
|
30
30
|
tokenProvider?: TokenProvider;
|
|
31
31
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
32
32
|
timeout?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
35
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
36
|
+
*/
|
|
37
|
+
maxRetries?: number;
|
|
38
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
39
|
+
retryDelay?: number;
|
|
33
40
|
}
|
|
34
41
|
export declare class InvestorClient {
|
|
35
42
|
private config;
|
|
@@ -101,6 +101,13 @@ interface InvestorClientConfig {
|
|
|
101
101
|
tokenProvider?: TokenProvider
|
|
102
102
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
103
103
|
timeout?: number
|
|
104
|
+
/**
|
|
105
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
106
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
107
|
+
*/
|
|
108
|
+
maxRetries?: number
|
|
109
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
110
|
+
retryDelay?: number
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
export class InvestorClient {
|
|
@@ -227,6 +227,13 @@ interface LedgerClientConfig {
|
|
|
227
227
|
tokenProvider?: TokenProvider;
|
|
228
228
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
229
229
|
timeout?: number;
|
|
230
|
+
/**
|
|
231
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
232
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
233
|
+
*/
|
|
234
|
+
maxRetries?: number;
|
|
235
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
236
|
+
retryDelay?: number;
|
|
230
237
|
}
|
|
231
238
|
export declare class LedgerClient {
|
|
232
239
|
private config;
|
|
@@ -576,6 +576,13 @@ interface LedgerClientConfig {
|
|
|
576
576
|
tokenProvider?: TokenProvider
|
|
577
577
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
578
578
|
timeout?: number
|
|
579
|
+
/**
|
|
580
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
581
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
582
|
+
*/
|
|
583
|
+
maxRetries?: number
|
|
584
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
585
|
+
retryDelay?: number
|
|
579
586
|
}
|
|
580
587
|
|
|
581
588
|
export class LedgerClient {
|
|
@@ -71,6 +71,13 @@ interface LibraryClientConfig {
|
|
|
71
71
|
tokenProvider?: TokenProvider;
|
|
72
72
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
73
73
|
timeout?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
76
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
77
|
+
*/
|
|
78
|
+
maxRetries?: number;
|
|
79
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
80
|
+
retryDelay?: number;
|
|
74
81
|
}
|
|
75
82
|
export declare class LibraryClient {
|
|
76
83
|
private config;
|
|
@@ -150,6 +150,13 @@ interface LibraryClientConfig {
|
|
|
150
150
|
tokenProvider?: TokenProvider
|
|
151
151
|
/** GraphQL request timeout in milliseconds (default 60s). */
|
|
152
152
|
timeout?: number
|
|
153
|
+
/**
|
|
154
|
+
* Replays of a rate-limited (429) request. Defaults to
|
|
155
|
+
* `DEFAULT_MAX_RETRIES`; set `0` to surface the rejection immediately.
|
|
156
|
+
*/
|
|
157
|
+
maxRetries?: number
|
|
158
|
+
/** Base of the retry backoff, in milliseconds. */
|
|
159
|
+
retryDelay?: number
|
|
153
160
|
}
|
|
154
161
|
|
|
155
162
|
export class LibraryClient {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TokenProvider } from './graphql/client';
|
|
1
2
|
export interface OperationProgress {
|
|
2
3
|
message: string;
|
|
3
4
|
progressPercent?: number;
|
|
@@ -25,6 +26,7 @@ export declare class OperationClient {
|
|
|
25
26
|
credentials?: 'include' | 'same-origin' | 'omit';
|
|
26
27
|
headers?: Record<string, string>;
|
|
27
28
|
token?: string;
|
|
29
|
+
tokenProvider?: TokenProvider;
|
|
28
30
|
maxRetries?: number;
|
|
29
31
|
retryDelay?: number;
|
|
30
32
|
});
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { cancelOperation as cancelOperationSDK, getOperationStatus } from '../sdk.gen'
|
|
9
|
+
import type { TokenProvider } from './graphql/client'
|
|
9
10
|
import { EventType, SSEClient } from './SSEClient'
|
|
10
11
|
|
|
11
12
|
export interface OperationProgress {
|
|
@@ -35,6 +36,7 @@ export class OperationClient {
|
|
|
35
36
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
36
37
|
headers?: Record<string, string>
|
|
37
38
|
token?: string // JWT token for authentication
|
|
39
|
+
tokenProvider?: TokenProvider // consulted on every SSE connect; wins over `token`
|
|
38
40
|
maxRetries?: number
|
|
39
41
|
retryDelay?: number
|
|
40
42
|
}
|
|
@@ -46,6 +48,7 @@ export class OperationClient {
|
|
|
46
48
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
47
49
|
headers?: Record<string, string>
|
|
48
50
|
token?: string // JWT token for authentication
|
|
51
|
+
tokenProvider?: TokenProvider // consulted on every SSE connect; wins over `token`
|
|
49
52
|
maxRetries?: number
|
|
50
53
|
retryDelay?: number
|
|
51
54
|
}) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TokenProvider } from './graphql/client';
|
|
1
2
|
export interface OperatorQueryRequest {
|
|
2
3
|
message: string;
|
|
3
4
|
history?: Array<{
|
|
@@ -13,6 +14,12 @@ export interface OperatorOptions {
|
|
|
13
14
|
mode?: 'auto' | 'sync' | 'async';
|
|
14
15
|
maxWait?: number;
|
|
15
16
|
onProgress?: (message: string, percentage?: number) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Interval between `/v1/operations/{id}/status` polls while the client
|
|
19
|
+
* follows a queued run it could not open an SSE stream for. Defaults to
|
|
20
|
+
* 2000 ms; only the fallback path uses it.
|
|
21
|
+
*/
|
|
22
|
+
pollIntervalMs?: number;
|
|
16
23
|
}
|
|
17
24
|
export interface OperatorResult {
|
|
18
25
|
content: string;
|
|
@@ -27,6 +34,12 @@ export interface OperatorResult {
|
|
|
27
34
|
confidence_score?: number;
|
|
28
35
|
execution_time?: number;
|
|
29
36
|
timestamp?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Present when the API reports a failed run inside an otherwise successful
|
|
39
|
+
* response (credit pre-flight, operator timeouts, cancelled runs). `content`
|
|
40
|
+
* then carries the explanation rather than an answer.
|
|
41
|
+
*/
|
|
42
|
+
error_details?: Record<string, any>;
|
|
30
43
|
}
|
|
31
44
|
export interface QueuedOperatorResponse {
|
|
32
45
|
status: 'queued';
|
|
@@ -34,15 +47,25 @@ export interface QueuedOperatorResponse {
|
|
|
34
47
|
message: string;
|
|
35
48
|
sse_endpoint?: string;
|
|
36
49
|
}
|
|
50
|
+
export interface OperatorClientConfig {
|
|
51
|
+
baseUrl: string;
|
|
52
|
+
credentials?: 'include' | 'same-origin' | 'omit';
|
|
53
|
+
headers?: Record<string, string>;
|
|
54
|
+
/**
|
|
55
|
+
* Static JWT captured at construction. Prefer `tokenProvider` in the
|
|
56
|
+
* browser — see `SSEConfig` for why a captured token goes stale.
|
|
57
|
+
*/
|
|
58
|
+
token?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Consulted on every SSE connect so a rotated JWT keeps the progress
|
|
61
|
+
* stream authenticated. Wins over `token` when both are set.
|
|
62
|
+
*/
|
|
63
|
+
tokenProvider?: TokenProvider;
|
|
64
|
+
}
|
|
37
65
|
export declare class OperatorClient {
|
|
38
66
|
private sseClient?;
|
|
39
67
|
private config;
|
|
40
|
-
constructor(config:
|
|
41
|
-
baseUrl: string;
|
|
42
|
-
credentials?: 'include' | 'same-origin' | 'omit';
|
|
43
|
-
headers?: Record<string, string>;
|
|
44
|
-
token?: string;
|
|
45
|
-
});
|
|
68
|
+
constructor(config: OperatorClientConfig);
|
|
46
69
|
/**
|
|
47
70
|
* Execute operator query with automatic operator selection
|
|
48
71
|
*/
|
|
@@ -51,7 +74,18 @@ export declare class OperatorClient {
|
|
|
51
74
|
* Execute specific operator type
|
|
52
75
|
*/
|
|
53
76
|
executeOperator(graphId: string, operatorType: string, request: OperatorQueryRequest, options?: OperatorOptions): Promise<OperatorResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Resolve an operator endpoint response: a sync 200 body is the result, a
|
|
79
|
+
* 202 with an `operation_id` is followed to completion.
|
|
80
|
+
*/
|
|
81
|
+
private settle;
|
|
54
82
|
private waitForOperatorCompletion;
|
|
83
|
+
/**
|
|
84
|
+
* Follow a queued run over `/v1/operations/{id}/status` until it settles.
|
|
85
|
+
* Used when the SSE stream could not be opened; `streamError` is folded
|
|
86
|
+
* into the failure message if polling cannot reach a verdict either.
|
|
87
|
+
*/
|
|
88
|
+
private pollForCompletion;
|
|
55
89
|
/**
|
|
56
90
|
* Convenience method for simple agent queries with auto-selection
|
|
57
91
|
*/
|
|
@@ -8,6 +8,50 @@ exports.QueuedOperatorError = exports.OperatorClient = void 0;
|
|
|
8
8
|
*/
|
|
9
9
|
const sdk_gen_1 = require("../sdk.gen");
|
|
10
10
|
const SSEClient_1 = require("./SSEClient");
|
|
11
|
+
const DEFAULT_POLL_INTERVAL_MS = 2000;
|
|
12
|
+
// Consecutive `/status` failures tolerated before the polling fallback gives
|
|
13
|
+
// up: one transient network error must not lose a run that is still going.
|
|
14
|
+
const MAX_CONSECUTIVE_POLL_FAILURES = 3;
|
|
15
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
16
|
+
const describeError = (err) => (err instanceof Error ? err.message : String(err));
|
|
17
|
+
/**
|
|
18
|
+
* Text for the `error` slot of a generated-client envelope: a thrown `Error`
|
|
19
|
+
* (network failure — the client returns those rather than throwing), an API
|
|
20
|
+
* body with `detail`, or whatever else came back.
|
|
21
|
+
*/
|
|
22
|
+
const describeEnvelopeError = (err) => {
|
|
23
|
+
if (err instanceof Error)
|
|
24
|
+
return err.message;
|
|
25
|
+
if (err && typeof err === 'object' && 'detail' in err)
|
|
26
|
+
return String(err.detail);
|
|
27
|
+
if (err === undefined || err === null)
|
|
28
|
+
return 'empty response';
|
|
29
|
+
return typeof err === 'string' ? err : JSON.stringify(err);
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Shape an operator payload — the sync 200 body, the `operation_completed`
|
|
33
|
+
* event, or the `/status` `result` — into the public result type. All three
|
|
34
|
+
* carry the same fields, so one mapper keeps them consistent.
|
|
35
|
+
*/
|
|
36
|
+
function toOperatorResult(data) {
|
|
37
|
+
const result = {
|
|
38
|
+
content: data.content ?? '',
|
|
39
|
+
operator_used: data.operator_used || 'unknown',
|
|
40
|
+
mode_used: data.mode_used || 'standard',
|
|
41
|
+
metadata: data.metadata,
|
|
42
|
+
tokens_used: data.tokens_used,
|
|
43
|
+
confidence_score: data.confidence_score,
|
|
44
|
+
execution_time: data.execution_time,
|
|
45
|
+
timestamp: data.timestamp || new Date().toISOString(),
|
|
46
|
+
};
|
|
47
|
+
if (data.error_details) {
|
|
48
|
+
result.error_details = data.error_details;
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
/** Internal: a `/status` verdict that must not be retried. */
|
|
53
|
+
class PollAbort extends Error {
|
|
54
|
+
}
|
|
11
55
|
class OperatorClient {
|
|
12
56
|
constructor(config) {
|
|
13
57
|
this.config = config;
|
|
@@ -29,32 +73,7 @@ class OperatorClient {
|
|
|
29
73
|
},
|
|
30
74
|
};
|
|
31
75
|
const response = await (0, sdk_gen_1.autoSelectOperator)(data);
|
|
32
|
-
|
|
33
|
-
// Check if this is an immediate response (sync execution)
|
|
34
|
-
if (responseData?.content !== undefined && responseData?.operator_used) {
|
|
35
|
-
return {
|
|
36
|
-
content: responseData.content,
|
|
37
|
-
operator_used: responseData.operator_used,
|
|
38
|
-
mode_used: responseData.mode_used,
|
|
39
|
-
metadata: responseData.metadata,
|
|
40
|
-
tokens_used: responseData.tokens_used,
|
|
41
|
-
confidence_score: responseData.confidence_score,
|
|
42
|
-
execution_time: responseData.execution_time,
|
|
43
|
-
timestamp: new Date().toISOString(),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
// Check if this is a queued response (async background task execution)
|
|
47
|
-
if (responseData?.operation_id) {
|
|
48
|
-
const queuedResponse = responseData;
|
|
49
|
-
// If user doesn't want to wait, throw with queue info
|
|
50
|
-
if (options.maxWait === 0) {
|
|
51
|
-
throw new QueuedOperatorError(queuedResponse);
|
|
52
|
-
}
|
|
53
|
-
// Use SSE to monitor the operation
|
|
54
|
-
return this.waitForOperatorCompletion(queuedResponse.operation_id, options);
|
|
55
|
-
}
|
|
56
|
-
// Unexpected response format
|
|
57
|
-
throw new Error('Unexpected response format from operator endpoint');
|
|
76
|
+
return this.settle(response.data, options);
|
|
58
77
|
}
|
|
59
78
|
/**
|
|
60
79
|
* Execute specific operator type
|
|
@@ -73,103 +92,150 @@ class OperatorClient {
|
|
|
73
92
|
},
|
|
74
93
|
};
|
|
75
94
|
const response = await (0, sdk_gen_1.executeSpecificOperator)(data);
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
return this.settle(response.data, options);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolve an operator endpoint response: a sync 200 body is the result, a
|
|
99
|
+
* 202 with an `operation_id` is followed to completion.
|
|
100
|
+
*/
|
|
101
|
+
async settle(responseData, options) {
|
|
102
|
+
// Immediate response (sync execution)
|
|
78
103
|
if (responseData?.content !== undefined && responseData?.operator_used) {
|
|
79
|
-
return
|
|
80
|
-
content: responseData.content,
|
|
81
|
-
operator_used: responseData.operator_used,
|
|
82
|
-
mode_used: responseData.mode_used,
|
|
83
|
-
metadata: responseData.metadata,
|
|
84
|
-
tokens_used: responseData.tokens_used,
|
|
85
|
-
confidence_score: responseData.confidence_score,
|
|
86
|
-
execution_time: responseData.execution_time,
|
|
87
|
-
timestamp: new Date().toISOString(),
|
|
88
|
-
};
|
|
104
|
+
return toOperatorResult(responseData);
|
|
89
105
|
}
|
|
90
|
-
//
|
|
106
|
+
// Queued response (async background task execution)
|
|
91
107
|
if (responseData?.operation_id) {
|
|
92
108
|
const queuedResponse = responseData;
|
|
93
109
|
// If user doesn't want to wait, throw with queue info
|
|
94
110
|
if (options.maxWait === 0) {
|
|
95
111
|
throw new QueuedOperatorError(queuedResponse);
|
|
96
112
|
}
|
|
97
|
-
// Use SSE to monitor the operation
|
|
98
113
|
return this.waitForOperatorCompletion(queuedResponse.operation_id, options);
|
|
99
114
|
}
|
|
100
115
|
// Unexpected response format
|
|
101
116
|
throw new Error('Unexpected response format from operator endpoint');
|
|
102
117
|
}
|
|
103
118
|
async waitForOperatorCompletion(operationId, options) {
|
|
119
|
+
const sseClient = new SSEClient_1.SSEClient(this.config);
|
|
120
|
+
this.sseClient = sseClient;
|
|
121
|
+
try {
|
|
122
|
+
await sseClient.connect(operationId);
|
|
123
|
+
}
|
|
124
|
+
catch (streamError) {
|
|
125
|
+
// The run is already queued and finishes whether or not anyone is
|
|
126
|
+
// watching, so a stream that cannot open — a revoked token, a proxy
|
|
127
|
+
// that will not hold the connection, the per-user connection cap —
|
|
128
|
+
// must not lose the result. Follow the operation over `/status`,
|
|
129
|
+
// which rides the regular REST auth path, instead.
|
|
130
|
+
this.sseClient = undefined;
|
|
131
|
+
return this.pollForCompletion(operationId, options, streamError);
|
|
132
|
+
}
|
|
104
133
|
return new Promise((resolve, reject) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.
|
|
108
|
-
.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
let result = null;
|
|
135
|
+
const finish = () => {
|
|
136
|
+
sseClient.close();
|
|
137
|
+
if (this.sseClient === sseClient) {
|
|
138
|
+
this.sseClient = undefined;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
// Listen for progress events
|
|
142
|
+
sseClient.on(SSEClient_1.EventType.OPERATION_PROGRESS, (data) => {
|
|
143
|
+
options.onProgress?.(data.message, data.progress_percentage);
|
|
144
|
+
});
|
|
145
|
+
// Listen for agent-specific events
|
|
146
|
+
sseClient.on('operator_started', (data) => {
|
|
147
|
+
options.onProgress?.(`Operator ${data.operator_type} started`, 0);
|
|
148
|
+
});
|
|
149
|
+
sseClient.on('operator_initialized', (data) => {
|
|
150
|
+
options.onProgress?.(`${data.agent_name} initialized`, 10);
|
|
151
|
+
});
|
|
152
|
+
sseClient.on('progress', (data) => {
|
|
153
|
+
options.onProgress?.(data.message, data.percentage);
|
|
154
|
+
});
|
|
155
|
+
sseClient.on('operator_completed', (data) => {
|
|
156
|
+
result = toOperatorResult(data);
|
|
157
|
+
finish();
|
|
158
|
+
resolve(result);
|
|
159
|
+
});
|
|
160
|
+
// Fallback to generic completion event
|
|
161
|
+
sseClient.on(SSEClient_1.EventType.OPERATION_COMPLETED, (data) => {
|
|
162
|
+
if (!result) {
|
|
163
|
+
result = toOperatorResult(data.result || data);
|
|
164
|
+
finish();
|
|
136
165
|
resolve(result);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
sseClient.close();
|
|
153
|
-
resolve(result);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
sseClient.on(SSEClient_1.EventType.OPERATION_ERROR, (error) => {
|
|
157
|
-
sseClient.close();
|
|
158
|
-
reject(new Error(error.message || error.error));
|
|
159
|
-
});
|
|
160
|
-
sseClient.on(SSEClient_1.EventType.OPERATION_CANCELLED, () => {
|
|
161
|
-
sseClient.close();
|
|
162
|
-
reject(new Error('Agent execution cancelled'));
|
|
163
|
-
});
|
|
164
|
-
// Handle generic error event
|
|
165
|
-
sseClient.on('error', (error) => {
|
|
166
|
-
sseClient.close();
|
|
167
|
-
reject(new Error(error.error || error.message || 'Agent execution failed'));
|
|
168
|
-
});
|
|
169
|
-
})
|
|
170
|
-
.catch(reject);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
sseClient.on(SSEClient_1.EventType.OPERATION_ERROR, (error) => {
|
|
169
|
+
finish();
|
|
170
|
+
reject(new Error(error.message || error.error));
|
|
171
|
+
});
|
|
172
|
+
sseClient.on(SSEClient_1.EventType.OPERATION_CANCELLED, () => {
|
|
173
|
+
finish();
|
|
174
|
+
reject(new Error('Agent execution cancelled'));
|
|
175
|
+
});
|
|
176
|
+
// Handle generic error event
|
|
177
|
+
sseClient.on('error', (error) => {
|
|
178
|
+
finish();
|
|
179
|
+
reject(new Error(error.error || error.message || 'Agent execution failed'));
|
|
180
|
+
});
|
|
171
181
|
});
|
|
172
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Follow a queued run over `/v1/operations/{id}/status` until it settles.
|
|
185
|
+
* Used when the SSE stream could not be opened; `streamError` is folded
|
|
186
|
+
* into the failure message if polling cannot reach a verdict either.
|
|
187
|
+
*/
|
|
188
|
+
async pollForCompletion(operationId, options, streamError) {
|
|
189
|
+
const interval = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
190
|
+
const streamDetail = describeError(streamError);
|
|
191
|
+
let consecutiveFailures = 0;
|
|
192
|
+
options.onProgress?.('Live progress unavailable — waiting for the result');
|
|
193
|
+
for (;;) {
|
|
194
|
+
let status;
|
|
195
|
+
try {
|
|
196
|
+
const response = await (0, sdk_gen_1.getOperationStatus)({ path: { operation_id: operationId } });
|
|
197
|
+
if (response.error || !response.data) {
|
|
198
|
+
const httpStatus = response.response?.status;
|
|
199
|
+
const detail = describeEnvelopeError(response.error);
|
|
200
|
+
// A definitive 4xx (expired, not ours, unauthenticated) ends the
|
|
201
|
+
// wait; anything else is treated as transient and retried below.
|
|
202
|
+
if (httpStatus !== undefined &&
|
|
203
|
+
httpStatus >= 400 &&
|
|
204
|
+
httpStatus < 500 &&
|
|
205
|
+
httpStatus !== 429) {
|
|
206
|
+
throw new PollAbort(`Operator stream failed (${streamDetail}); status check failed (${httpStatus}: ${detail})`);
|
|
207
|
+
}
|
|
208
|
+
throw new Error(detail);
|
|
209
|
+
}
|
|
210
|
+
status = response.data;
|
|
211
|
+
consecutiveFailures = 0;
|
|
212
|
+
}
|
|
213
|
+
catch (pollError) {
|
|
214
|
+
if (pollError instanceof PollAbort) {
|
|
215
|
+
throw new Error(pollError.message);
|
|
216
|
+
}
|
|
217
|
+
consecutiveFailures += 1;
|
|
218
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {
|
|
219
|
+
throw new Error(`Operator stream failed (${streamDetail}); status polling failed (${describeError(pollError)})`);
|
|
220
|
+
}
|
|
221
|
+
await sleep(interval);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
switch (status.status) {
|
|
225
|
+
case 'completed':
|
|
226
|
+
return toOperatorResult(status.result || {});
|
|
227
|
+
case 'failed':
|
|
228
|
+
throw new Error(status.error || status.message || 'Operator run failed');
|
|
229
|
+
case 'cancelled':
|
|
230
|
+
throw new Error('Agent execution cancelled');
|
|
231
|
+
default:
|
|
232
|
+
if (status.message) {
|
|
233
|
+
options.onProgress?.(status.message);
|
|
234
|
+
}
|
|
235
|
+
await sleep(interval);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
173
239
|
/**
|
|
174
240
|
* Convenience method for simple agent queries with auto-selection
|
|
175
241
|
*/
|