orchestrator-client 5.7.3 → 5.7.10
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/index.cjs +519 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -17
- package/dist/index.d.ts +232 -17
- package/dist/index.js +508 -60
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DEFAULT_FLOW_TIMEOUT_MS: () => DEFAULT_FLOW_TIMEOUT_MS,
|
|
33
34
|
EVENT_ERROR_EVENT_RECORDED: () => EVENT_ERROR_EVENT_RECORDED,
|
|
34
35
|
EVENT_MESSAGE_ADDED: () => EVENT_MESSAGE_ADDED,
|
|
35
36
|
EVENT_MESSAGE_STREAMING: () => EVENT_MESSAGE_STREAMING,
|
|
@@ -41,6 +42,10 @@ __export(index_exports, {
|
|
|
41
42
|
EVENT_TASK_ITERATION_CHANGED: () => EVENT_TASK_ITERATION_CHANGED,
|
|
42
43
|
EVENT_TASK_RESULT_UPDATED: () => EVENT_TASK_RESULT_UPDATED,
|
|
43
44
|
EVENT_TASK_STATUS_CHANGED: () => EVENT_TASK_STATUS_CHANGED,
|
|
45
|
+
Flow: () => Flow,
|
|
46
|
+
FlowCancelledError: () => FlowCancelledError,
|
|
47
|
+
FlowError: () => FlowError,
|
|
48
|
+
FlowTimeoutError: () => FlowTimeoutError,
|
|
44
49
|
Orchestrator: () => Orchestrator,
|
|
45
50
|
OrchestratorAPIError: () => OrchestratorAPIError,
|
|
46
51
|
OrchestratorAsync: () => OrchestratorAsync,
|
|
@@ -51,8 +56,13 @@ __export(index_exports, {
|
|
|
51
56
|
OrchestratorNotFoundError: () => OrchestratorNotFoundError,
|
|
52
57
|
RealtimeClient: () => RealtimeClient,
|
|
53
58
|
VERSION: () => VERSION,
|
|
59
|
+
camelToSnake: () => camelToSnake,
|
|
54
60
|
createInsecureFetch: () => createInsecureFetch,
|
|
55
|
-
|
|
61
|
+
deepCamelCase: () => deepCamelCase,
|
|
62
|
+
extractJsonFromMessage: () => extractJsonFromMessage,
|
|
63
|
+
loadConfig: () => loadConfig,
|
|
64
|
+
setupDefaultClient: () => setupDefaultClient,
|
|
65
|
+
snakeToCamel: () => snakeToCamel
|
|
56
66
|
});
|
|
57
67
|
module.exports = __toCommonJS(index_exports);
|
|
58
68
|
|
|
@@ -73,8 +83,8 @@ var OrchestratorConnectionError = class extends OrchestratorError {
|
|
|
73
83
|
}
|
|
74
84
|
};
|
|
75
85
|
var OrchestratorAuthError = class extends OrchestratorError {
|
|
76
|
-
constructor(message, statusCode = 401) {
|
|
77
|
-
super(message, { statusCode });
|
|
86
|
+
constructor(message, statusCode = 401, errorCode) {
|
|
87
|
+
super(message, { statusCode, errorCode });
|
|
78
88
|
this.name = "OrchestratorAuthError";
|
|
79
89
|
}
|
|
80
90
|
};
|
|
@@ -101,6 +111,28 @@ var OrchestratorConfigError = class extends OrchestratorError {
|
|
|
101
111
|
}
|
|
102
112
|
};
|
|
103
113
|
|
|
114
|
+
// src/utils.ts
|
|
115
|
+
function snakeToCamel(str) {
|
|
116
|
+
return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
117
|
+
}
|
|
118
|
+
function camelToSnake(str) {
|
|
119
|
+
return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
120
|
+
}
|
|
121
|
+
function deepCamelCase(obj) {
|
|
122
|
+
if (Array.isArray(obj)) {
|
|
123
|
+
return obj.map(deepCamelCase);
|
|
124
|
+
}
|
|
125
|
+
if (typeof obj === "object" && obj !== null) {
|
|
126
|
+
return Object.fromEntries(
|
|
127
|
+
Object.entries(obj).map(([key, value]) => [
|
|
128
|
+
snakeToCamel(key),
|
|
129
|
+
deepCamelCase(value)
|
|
130
|
+
])
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return obj;
|
|
134
|
+
}
|
|
135
|
+
|
|
104
136
|
// src/client.ts
|
|
105
137
|
var RETRY_BACKOFF_BASE = 500;
|
|
106
138
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -120,22 +152,66 @@ function buildTaskSummary(t) {
|
|
|
120
152
|
return {
|
|
121
153
|
id: t.id ?? "",
|
|
122
154
|
status: t.status ?? "",
|
|
123
|
-
workflowId: t.workflowId ??
|
|
155
|
+
workflowId: t.workflowId ?? "",
|
|
124
156
|
iteration: t.iteration ?? 0,
|
|
125
|
-
maxIterations: t.maxIterations ??
|
|
126
|
-
goalPrompt: t.goalPrompt ??
|
|
157
|
+
maxIterations: t.maxIterations ?? 0,
|
|
158
|
+
goalPrompt: t.goalPrompt ?? "",
|
|
127
159
|
result: t.result ?? "",
|
|
128
|
-
resultLocalized: t.resultLocalized ??
|
|
129
|
-
approvalReason: t.approvalReason ??
|
|
130
|
-
ticketId: t.ticketId ??
|
|
131
|
-
availableTools: t.availableTools ??
|
|
160
|
+
resultLocalized: t.resultLocalized ?? null,
|
|
161
|
+
approvalReason: t.approvalReason ?? "",
|
|
162
|
+
ticketId: t.ticketId ?? null,
|
|
163
|
+
availableTools: t.availableTools ?? null,
|
|
132
164
|
insight: t.insight ?? null,
|
|
133
|
-
insightLocalized: t.insightLocalized ??
|
|
134
|
-
createdAt: t.createdAt ??
|
|
135
|
-
updatedAt: t.updatedAt ??
|
|
136
|
-
pendingTranslationsForLocales: t.pendingTranslationsForLocales ??
|
|
165
|
+
insightLocalized: t.insightLocalized ?? null,
|
|
166
|
+
createdAt: t.createdAt ?? "",
|
|
167
|
+
updatedAt: t.updatedAt ?? "",
|
|
168
|
+
pendingTranslationsForLocales: t.pendingTranslationsForLocales ?? null
|
|
137
169
|
};
|
|
138
170
|
}
|
|
171
|
+
function parseApiErrorBody(body, fallbackMessage) {
|
|
172
|
+
let errorCode = body.error_code ?? null;
|
|
173
|
+
if (!errorCode && body.error && typeof body.error === "object") {
|
|
174
|
+
const nested = body.error;
|
|
175
|
+
errorCode = nested.code ?? null;
|
|
176
|
+
}
|
|
177
|
+
let message = null;
|
|
178
|
+
if (typeof body.error === "string") {
|
|
179
|
+
message = body.error;
|
|
180
|
+
} else if (typeof body.message === "string") {
|
|
181
|
+
message = body.message;
|
|
182
|
+
}
|
|
183
|
+
let details = body.details ?? null;
|
|
184
|
+
const detail = body.detail;
|
|
185
|
+
if (typeof detail === "string") {
|
|
186
|
+
message = detail;
|
|
187
|
+
} else if (detail && typeof detail === "object" && !Array.isArray(detail)) {
|
|
188
|
+
const detailObj = detail;
|
|
189
|
+
if (!errorCode) {
|
|
190
|
+
errorCode = detailObj.error_code ?? null;
|
|
191
|
+
}
|
|
192
|
+
if (typeof detailObj.error === "string") {
|
|
193
|
+
message = detailObj.error;
|
|
194
|
+
} else if (typeof detailObj.message === "string") {
|
|
195
|
+
message = detailObj.message;
|
|
196
|
+
}
|
|
197
|
+
if (!details) {
|
|
198
|
+
details = detailObj;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!message) {
|
|
202
|
+
message = fallbackMessage;
|
|
203
|
+
}
|
|
204
|
+
const missingFields = body.missing_fields;
|
|
205
|
+
if (Array.isArray(missingFields) && missingFields.length > 0) {
|
|
206
|
+
const fields = missingFields.filter(
|
|
207
|
+
(f) => typeof f === "string"
|
|
208
|
+
);
|
|
209
|
+
if (fields.length > 0) {
|
|
210
|
+
message = `${message} (missing: ${fields.join(", ")})`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return { message, errorCode, details };
|
|
214
|
+
}
|
|
139
215
|
var OrchestratorAsync = class {
|
|
140
216
|
constructor(opts = {}) {
|
|
141
217
|
this._abortController = null;
|
|
@@ -149,7 +225,7 @@ var OrchestratorAsync = class {
|
|
|
149
225
|
this._timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
150
226
|
this._maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
151
227
|
this._locale = opts.locale;
|
|
152
|
-
this._fetch = opts.fetch ?? globalThis.fetch;
|
|
228
|
+
this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
153
229
|
if (opts.insecure && !opts.fetch && typeof process !== "undefined" && process.versions?.node) {
|
|
154
230
|
this._insecure = true;
|
|
155
231
|
}
|
|
@@ -163,6 +239,11 @@ var OrchestratorAsync = class {
|
|
|
163
239
|
_makeUrl(path) {
|
|
164
240
|
return `${this._baseUrl}${path}`;
|
|
165
241
|
}
|
|
242
|
+
_makeAbsoluteUrl(path) {
|
|
243
|
+
const raw = this._makeUrl(path);
|
|
244
|
+
const base = typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0;
|
|
245
|
+
return new URL(raw, base);
|
|
246
|
+
}
|
|
166
247
|
async _resolveHeaders() {
|
|
167
248
|
const headers = {};
|
|
168
249
|
if (this._apiKey) {
|
|
@@ -179,7 +260,7 @@ var OrchestratorAsync = class {
|
|
|
179
260
|
return headers;
|
|
180
261
|
}
|
|
181
262
|
async _request(method, path, opts) {
|
|
182
|
-
const url =
|
|
263
|
+
const url = this._makeAbsoluteUrl(path);
|
|
183
264
|
if (opts?.params) {
|
|
184
265
|
for (const [key, value] of Object.entries(opts.params)) {
|
|
185
266
|
if (value !== void 0) {
|
|
@@ -207,16 +288,21 @@ var OrchestratorAsync = class {
|
|
|
207
288
|
signal
|
|
208
289
|
});
|
|
209
290
|
clearTimeout(timeoutId);
|
|
210
|
-
if (response.status === 401) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
291
|
+
if (response.status === 401 || response.status === 403) {
|
|
292
|
+
const defaultAuthMsg = response.status === 401 ? `Authentication failed for ${method} ${path}` : `Access denied for ${method} ${path}`;
|
|
293
|
+
let authErrorCode = null;
|
|
294
|
+
let authErrorMsg = defaultAuthMsg;
|
|
295
|
+
try {
|
|
296
|
+
const body = await response.clone().json();
|
|
297
|
+
const parsed = parseApiErrorBody(body, defaultAuthMsg);
|
|
298
|
+
authErrorMsg = parsed.message;
|
|
299
|
+
authErrorCode = parsed.errorCode;
|
|
300
|
+
} catch {
|
|
301
|
+
}
|
|
217
302
|
throw new OrchestratorAuthError(
|
|
218
|
-
|
|
219
|
-
|
|
303
|
+
authErrorMsg,
|
|
304
|
+
response.status,
|
|
305
|
+
authErrorCode
|
|
220
306
|
);
|
|
221
307
|
}
|
|
222
308
|
if (response.status === 404) {
|
|
@@ -243,21 +329,27 @@ var OrchestratorAsync = class {
|
|
|
243
329
|
if (response.ok) {
|
|
244
330
|
const contentType = response.headers.get("content-type") ?? "";
|
|
245
331
|
if (contentType.includes("application/json")) {
|
|
246
|
-
return response.json();
|
|
332
|
+
return deepCamelCase(await response.json());
|
|
247
333
|
}
|
|
248
334
|
return { _text: await response.text() };
|
|
249
335
|
}
|
|
250
|
-
|
|
336
|
+
const defaultMessage = `API Error with status ${response.status}`;
|
|
337
|
+
let errorMessage = defaultMessage;
|
|
251
338
|
let errorCode = null;
|
|
252
339
|
let errorDetails = null;
|
|
253
340
|
try {
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
errorMessage =
|
|
258
|
-
|
|
341
|
+
const clonedResponse = response.clone();
|
|
342
|
+
const body = await clonedResponse.json();
|
|
343
|
+
const parsed = parseApiErrorBody(body, JSON.stringify(body));
|
|
344
|
+
errorMessage = parsed.message;
|
|
345
|
+
errorCode = parsed.errorCode;
|
|
346
|
+
errorDetails = parsed.details;
|
|
259
347
|
} catch {
|
|
260
|
-
|
|
348
|
+
try {
|
|
349
|
+
errorMessage = await response.text();
|
|
350
|
+
} catch {
|
|
351
|
+
errorMessage = defaultMessage;
|
|
352
|
+
}
|
|
261
353
|
}
|
|
262
354
|
throw new OrchestratorAPIError(
|
|
263
355
|
errorMessage,
|
|
@@ -327,7 +419,7 @@ var OrchestratorAsync = class {
|
|
|
327
419
|
params: {
|
|
328
420
|
page: params?.page,
|
|
329
421
|
limit: params?.limit,
|
|
330
|
-
order_by: params?.orderBy,
|
|
422
|
+
order_by: params?.orderBy ? camelToSnake(params.orderBy) : void 0,
|
|
331
423
|
order_direction: params?.orderDirection,
|
|
332
424
|
workflow_id: params?.workflowId
|
|
333
425
|
},
|
|
@@ -400,10 +492,10 @@ var OrchestratorAsync = class {
|
|
|
400
492
|
};
|
|
401
493
|
}
|
|
402
494
|
async getArchivedMessageContent(taskId, messageId) {
|
|
403
|
-
return this._get(
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
);
|
|
495
|
+
return this._get("/task/message/archived-content", {
|
|
496
|
+
task_id: taskId,
|
|
497
|
+
message_id: messageId
|
|
498
|
+
});
|
|
407
499
|
}
|
|
408
500
|
async getTaskCompactions(taskId) {
|
|
409
501
|
return this._get("/task/compactions", {
|
|
@@ -462,19 +554,39 @@ var OrchestratorAsync = class {
|
|
|
462
554
|
// ------------------------------------------------------------------
|
|
463
555
|
// Attachments
|
|
464
556
|
// ------------------------------------------------------------------
|
|
465
|
-
async uploadAttachment(file, filename) {
|
|
557
|
+
async uploadAttachment(file, filename, options) {
|
|
466
558
|
const formData = new FormData();
|
|
467
559
|
formData.append("file", file, filename);
|
|
468
560
|
const headers = await this._resolveHeaders();
|
|
469
561
|
const response = await this._fetch(this._makeUrl("/attachment"), {
|
|
470
562
|
method: "POST",
|
|
471
563
|
headers: { ...headers },
|
|
472
|
-
body: formData
|
|
564
|
+
body: formData,
|
|
565
|
+
signal: options?.signal
|
|
473
566
|
});
|
|
474
567
|
if (!response.ok) {
|
|
568
|
+
const defaultMessage = `Attachment upload failed: ${response.statusText}`;
|
|
569
|
+
let errorMessage = defaultMessage;
|
|
570
|
+
let errorCode = null;
|
|
571
|
+
let errorDetails = null;
|
|
572
|
+
try {
|
|
573
|
+
const body = await response.clone().json();
|
|
574
|
+
const parsed = parseApiErrorBody(body, defaultMessage);
|
|
575
|
+
errorMessage = parsed.message;
|
|
576
|
+
errorCode = parsed.errorCode;
|
|
577
|
+
errorDetails = parsed.details;
|
|
578
|
+
} catch {
|
|
579
|
+
try {
|
|
580
|
+
errorMessage = await response.text() || defaultMessage;
|
|
581
|
+
} catch {
|
|
582
|
+
errorMessage = defaultMessage;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
475
585
|
throw new OrchestratorAPIError(
|
|
476
|
-
|
|
477
|
-
response.status
|
|
586
|
+
errorMessage,
|
|
587
|
+
response.status,
|
|
588
|
+
errorCode,
|
|
589
|
+
errorDetails ?? void 0
|
|
478
590
|
);
|
|
479
591
|
}
|
|
480
592
|
const data = await response.json();
|
|
@@ -942,7 +1054,7 @@ var OrchestratorAsync = class {
|
|
|
942
1054
|
// ------------------------------------------------------------------
|
|
943
1055
|
async listErrors(params) {
|
|
944
1056
|
const authHeaders = await this._resolveHeaders();
|
|
945
|
-
const url =
|
|
1057
|
+
const url = this._makeAbsoluteUrl("/errors");
|
|
946
1058
|
if (params?.page !== void 0)
|
|
947
1059
|
url.searchParams.set("page", String(params.page));
|
|
948
1060
|
if (params?.limit !== void 0)
|
|
@@ -992,10 +1104,24 @@ var OrchestratorAsync = class {
|
|
|
992
1104
|
if (since) params.since = since;
|
|
993
1105
|
return this._get("/errors/stats", params);
|
|
994
1106
|
}
|
|
995
|
-
async countErrors(since) {
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
1107
|
+
async countErrors(since, severity) {
|
|
1108
|
+
const authHeaders = await this._resolveHeaders();
|
|
1109
|
+
const url = new URL(this._makeUrl("/errors/count"));
|
|
1110
|
+
if (since) url.searchParams.set("since", since);
|
|
1111
|
+
for (const s of severity ?? []) {
|
|
1112
|
+
url.searchParams.append("severity", s);
|
|
1113
|
+
}
|
|
1114
|
+
const response = await this._fetch(url.toString(), {
|
|
1115
|
+
method: "GET",
|
|
1116
|
+
headers: { ...authHeaders }
|
|
1117
|
+
});
|
|
1118
|
+
if (!response.ok) {
|
|
1119
|
+
throw new OrchestratorAPIError(
|
|
1120
|
+
`countErrors failed: ${response.statusText}`,
|
|
1121
|
+
response.status
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
return deepCamelCase(await response.json());
|
|
999
1125
|
}
|
|
1000
1126
|
async purgeErrors() {
|
|
1001
1127
|
return this._delete("/errors");
|
|
@@ -1027,7 +1153,35 @@ var OrchestratorAsync = class {
|
|
|
1027
1153
|
return this._get("/configuration/system/status");
|
|
1028
1154
|
}
|
|
1029
1155
|
async updateSettings(settings) {
|
|
1030
|
-
|
|
1156
|
+
const body = {};
|
|
1157
|
+
if (settings.agentModelId !== void 0) {
|
|
1158
|
+
body.agent_model_id = settings.agentModelId;
|
|
1159
|
+
}
|
|
1160
|
+
if (settings.orchestratorModelId !== void 0) {
|
|
1161
|
+
body.orchestrator_model_id = settings.orchestratorModelId;
|
|
1162
|
+
}
|
|
1163
|
+
if (settings.compactorModelId !== void 0) {
|
|
1164
|
+
body.compactor_model_id = settings.compactorModelId;
|
|
1165
|
+
}
|
|
1166
|
+
if (settings.journalModelId !== void 0) {
|
|
1167
|
+
body.journal_model_id = settings.journalModelId;
|
|
1168
|
+
}
|
|
1169
|
+
if (settings.summaryModelId !== void 0) {
|
|
1170
|
+
body.summary_model_id = settings.summaryModelId;
|
|
1171
|
+
}
|
|
1172
|
+
if (settings.translateModelId !== void 0) {
|
|
1173
|
+
body.translate_model_id = settings.translateModelId;
|
|
1174
|
+
}
|
|
1175
|
+
if (settings.maxConcurrentTasksPerReplica !== void 0) {
|
|
1176
|
+
body.max_concurrent_tasks_per_replica = settings.maxConcurrentTasksPerReplica;
|
|
1177
|
+
}
|
|
1178
|
+
if (settings.subagentsEnabled !== void 0) {
|
|
1179
|
+
body.subagents_enabled = settings.subagentsEnabled;
|
|
1180
|
+
}
|
|
1181
|
+
if (settings.localizationTargets !== void 0) {
|
|
1182
|
+
body.localization_targets = settings.localizationTargets;
|
|
1183
|
+
}
|
|
1184
|
+
return this._post("/configuration/system/settings", body);
|
|
1031
1185
|
}
|
|
1032
1186
|
async getConfigurationStatus() {
|
|
1033
1187
|
return this._get("/configuration/status");
|
|
@@ -1047,9 +1201,7 @@ var OrchestratorAsync = class {
|
|
|
1047
1201
|
return { message: data.message ?? "" };
|
|
1048
1202
|
}
|
|
1049
1203
|
async getLLMBackendStatus() {
|
|
1050
|
-
return this._get(
|
|
1051
|
-
"/configuration/llmbackend/status"
|
|
1052
|
-
);
|
|
1204
|
+
return this._get("/configuration/llmbackend/status");
|
|
1053
1205
|
}
|
|
1054
1206
|
async addLLMBackend(host, apiKey) {
|
|
1055
1207
|
const data = await this._post(
|
|
@@ -1066,9 +1218,7 @@ var OrchestratorAsync = class {
|
|
|
1066
1218
|
return { message: data.message ?? "" };
|
|
1067
1219
|
}
|
|
1068
1220
|
async getMCPServerStatus() {
|
|
1069
|
-
return this._get(
|
|
1070
|
-
"/configuration/mcpserver/status"
|
|
1071
|
-
);
|
|
1221
|
+
return this._get("/configuration/mcpserver/status");
|
|
1072
1222
|
}
|
|
1073
1223
|
async addMCPServer(host, apiKey) {
|
|
1074
1224
|
const data = await this._post(
|
|
@@ -1257,8 +1407,8 @@ var Orchestrator = class {
|
|
|
1257
1407
|
// ------------------------------------------------------------------
|
|
1258
1408
|
// Attachments
|
|
1259
1409
|
// ------------------------------------------------------------------
|
|
1260
|
-
uploadAttachment(file, filename) {
|
|
1261
|
-
return runSync(this._async.uploadAttachment(file, filename));
|
|
1410
|
+
uploadAttachment(file, filename, options) {
|
|
1411
|
+
return runSync(this._async.uploadAttachment(file, filename, options));
|
|
1262
1412
|
}
|
|
1263
1413
|
downloadAttachment(attachmentId) {
|
|
1264
1414
|
return runSync(this._async.downloadAttachment(attachmentId));
|
|
@@ -1459,8 +1609,8 @@ var Orchestrator = class {
|
|
|
1459
1609
|
getErrorStats(since) {
|
|
1460
1610
|
return runSync(this._async.getErrorStats(since));
|
|
1461
1611
|
}
|
|
1462
|
-
countErrors(since) {
|
|
1463
|
-
return runSync(this._async.countErrors(since));
|
|
1612
|
+
countErrors(since, severity) {
|
|
1613
|
+
return runSync(this._async.countErrors(since, severity));
|
|
1464
1614
|
}
|
|
1465
1615
|
purgeErrors() {
|
|
1466
1616
|
return runSync(this._async.purgeErrors());
|
|
@@ -1763,12 +1913,18 @@ var RealtimeClient = class {
|
|
|
1763
1913
|
/**
|
|
1764
1914
|
* Dispatch a message envelope to registered handlers and subscribers.
|
|
1765
1915
|
* The server sends: socket.emit("message", {type: "message", event: {..., event_type: "...", ...}})
|
|
1916
|
+
*
|
|
1917
|
+
* All event payloads are deep-converted from snake_case to camelCase so
|
|
1918
|
+
* consumers receive consistent camelCase objects (same convention as the
|
|
1919
|
+
* REST responses from _request). The raw event_type string is extracted
|
|
1920
|
+
* before conversion so the handler-map lookup still works.
|
|
1766
1921
|
*/
|
|
1767
1922
|
_dispatch(payload) {
|
|
1768
1923
|
const envelope = payload;
|
|
1769
|
-
const
|
|
1770
|
-
const eventType =
|
|
1924
|
+
const rawEvent = envelope.event ?? envelope;
|
|
1925
|
+
const eventType = rawEvent.event_type;
|
|
1771
1926
|
if (!eventType) return;
|
|
1927
|
+
const event = deepCamelCase(rawEvent);
|
|
1772
1928
|
const handlers = this._handlers.get(eventType);
|
|
1773
1929
|
if (handlers) {
|
|
1774
1930
|
for (const h of handlers) {
|
|
@@ -1977,10 +2133,303 @@ var RealtimeClient = class {
|
|
|
1977
2133
|
}
|
|
1978
2134
|
};
|
|
1979
2135
|
|
|
2136
|
+
// src/flow.ts
|
|
2137
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
2138
|
+
"completed",
|
|
2139
|
+
"failed",
|
|
2140
|
+
"cancelled",
|
|
2141
|
+
"translation"
|
|
2142
|
+
]);
|
|
2143
|
+
var DEFAULT_FLOW_TIMEOUT_MS = 6e5;
|
|
2144
|
+
var _defaultClient;
|
|
2145
|
+
var _defaultRealtime;
|
|
2146
|
+
function setupDefaultClient(client, realtime) {
|
|
2147
|
+
_defaultClient = client;
|
|
2148
|
+
_defaultRealtime = realtime;
|
|
2149
|
+
}
|
|
2150
|
+
function getDefaultClient() {
|
|
2151
|
+
if (!_defaultClient) {
|
|
2152
|
+
throw new Error(
|
|
2153
|
+
"No default OrchestratorAsync set. Call setupDefaultClient() during application startup, or pass client to flow.run()."
|
|
2154
|
+
);
|
|
2155
|
+
}
|
|
2156
|
+
return _defaultClient;
|
|
2157
|
+
}
|
|
2158
|
+
function getDefaultRealtime() {
|
|
2159
|
+
return _defaultRealtime;
|
|
2160
|
+
}
|
|
2161
|
+
var FlowError = class extends Error {
|
|
2162
|
+
constructor(message) {
|
|
2163
|
+
super(message);
|
|
2164
|
+
this.name = "FlowError";
|
|
2165
|
+
}
|
|
2166
|
+
};
|
|
2167
|
+
var FlowTimeoutError = class extends FlowError {
|
|
2168
|
+
constructor(message) {
|
|
2169
|
+
super(message);
|
|
2170
|
+
this.name = "FlowTimeoutError";
|
|
2171
|
+
}
|
|
2172
|
+
};
|
|
2173
|
+
var FlowCancelledError = class extends FlowError {
|
|
2174
|
+
constructor(taskId) {
|
|
2175
|
+
super(`Task ${taskId} was cancelled`);
|
|
2176
|
+
this.name = "FlowCancelledError";
|
|
2177
|
+
this.taskId = taskId;
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
function extractJsonFromMessage(content) {
|
|
2181
|
+
const cleaned = content.replace(/^\ufeff|\u200b|\u200c|\u200d/, "").trim();
|
|
2182
|
+
if (cleaned.startsWith("{")) {
|
|
2183
|
+
try {
|
|
2184
|
+
return JSON.parse(cleaned);
|
|
2185
|
+
} catch {
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
const start = content.indexOf("{");
|
|
2189
|
+
const end = content.lastIndexOf("}");
|
|
2190
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
2191
|
+
try {
|
|
2192
|
+
return JSON.parse(content.slice(start, end + 1));
|
|
2193
|
+
} catch {
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
const jsonFenceMatch = content.match(/```(?:json)\s*\n([\s\S]*?)\n```/i);
|
|
2197
|
+
if (jsonFenceMatch) {
|
|
2198
|
+
try {
|
|
2199
|
+
return JSON.parse(jsonFenceMatch[1].trim());
|
|
2200
|
+
} catch {
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
const anyFenceMatch = content.match(/```(?:[\w]*)\s*\n([\s\S]*?)\n```/);
|
|
2204
|
+
if (anyFenceMatch) {
|
|
2205
|
+
try {
|
|
2206
|
+
return JSON.parse(anyFenceMatch[1].trim());
|
|
2207
|
+
} catch {
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
const bareBraceMatch = content.match(/\{[\s\S]*\}/);
|
|
2211
|
+
if (bareBraceMatch) {
|
|
2212
|
+
try {
|
|
2213
|
+
return JSON.parse(bareBraceMatch[0]);
|
|
2214
|
+
} catch {
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
throw new FlowError(
|
|
2218
|
+
"Could not extract a valid JSON object from the agent's final message. The agent did not format its answer as required."
|
|
2219
|
+
);
|
|
2220
|
+
}
|
|
2221
|
+
var Flow = class {
|
|
2222
|
+
constructor() {
|
|
2223
|
+
// -- Workflow-level defaults (override in subclass) --------------------
|
|
2224
|
+
/** Orchestrator workflow type — `"proactive"` by default. */
|
|
2225
|
+
this.workflowId = "proactive";
|
|
2226
|
+
/** Maximum agent turns before the orchestrator forces a failure. */
|
|
2227
|
+
this.maxIterations = 100;
|
|
2228
|
+
/** LLM reasoning budget: `"low"`, `"medium"`, or `"high"`. */
|
|
2229
|
+
this.reasoningEffort = "medium";
|
|
2230
|
+
/**
|
|
2231
|
+
* Maximum milliseconds to wait for the orchestrator task to reach a
|
|
2232
|
+
* terminal state. When exceeded, {@link FlowTimeoutError} is raised.
|
|
2233
|
+
*/
|
|
2234
|
+
this.flowTimeoutMs = DEFAULT_FLOW_TIMEOUT_MS;
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* Optional system-prompt override.
|
|
2238
|
+
* When set, this replaces the orchestrator's default system prompt.
|
|
2239
|
+
*/
|
|
2240
|
+
get systemPrompt() {
|
|
2241
|
+
return void 0;
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Optional developer-prompt override appended after system prompt.
|
|
2245
|
+
*/
|
|
2246
|
+
get developerPrompt() {
|
|
2247
|
+
return void 0;
|
|
2248
|
+
}
|
|
2249
|
+
/**
|
|
2250
|
+
* Restrict which MCP / built-in tools the agent may use.
|
|
2251
|
+
* `undefined` means *all* tools are available. An empty array means
|
|
2252
|
+
* *no* tools — text-only reasoning.
|
|
2253
|
+
*/
|
|
2254
|
+
get availableTools() {
|
|
2255
|
+
return void 0;
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Per-task feature toggles sent in the creation request.
|
|
2259
|
+
* By default summaries and translation are disabled since flow
|
|
2260
|
+
* output is typically machine-consumed, not human-read.
|
|
2261
|
+
* Override in subclasses that produce human-facing content.
|
|
2262
|
+
*/
|
|
2263
|
+
get taskOptions() {
|
|
2264
|
+
return { disableSummaries: true, disableTranslation: true };
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Override the agent model for this flow.
|
|
2268
|
+
*/
|
|
2269
|
+
get agentModelId() {
|
|
2270
|
+
return void 0;
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Override the orchestrator (validation) model for this flow.
|
|
2274
|
+
*/
|
|
2275
|
+
get orchestratorModelId() {
|
|
2276
|
+
return void 0;
|
|
2277
|
+
}
|
|
2278
|
+
/**
|
|
2279
|
+
* Cancel the underlying orchestrator task, if one is running.
|
|
2280
|
+
*
|
|
2281
|
+
* Calling `cancel()` after `run()` has returned is a no-op.
|
|
2282
|
+
* The `run()` promise will reject with {@link FlowCancelledError}
|
|
2283
|
+
* after the orchestrator task transitions to `"cancelled"`.
|
|
2284
|
+
*/
|
|
2285
|
+
async cancel(client) {
|
|
2286
|
+
if (!this._lastTaskId) return;
|
|
2287
|
+
const resolvedClient = client ?? getDefaultClient();
|
|
2288
|
+
await resolvedClient.cancelTask(this._lastTaskId);
|
|
2289
|
+
}
|
|
2290
|
+
// -- Lifecycle ---------------------------------------------------------
|
|
2291
|
+
/**
|
|
2292
|
+
* Execute the flow end-to-end.
|
|
2293
|
+
*
|
|
2294
|
+
* @returns The parsed result.
|
|
2295
|
+
* @throws {FlowError} If the task fails, times out, or cannot be parsed.
|
|
2296
|
+
*/
|
|
2297
|
+
async run(params) {
|
|
2298
|
+
const client = params?.client ?? getDefaultClient();
|
|
2299
|
+
const realtime = params?.realtime ?? getDefaultRealtime();
|
|
2300
|
+
const timeoutMs = params?.timeoutMs ?? this.flowTimeoutMs;
|
|
2301
|
+
console.log(
|
|
2302
|
+
`[Flow] Starting ${this.constructor.name} \u2014 workflow=${this.workflowId} goal=${this.goalPrompt.slice(0, 80)}`
|
|
2303
|
+
);
|
|
2304
|
+
const response = await client.createTask({
|
|
2305
|
+
workflowId: this.workflowId,
|
|
2306
|
+
goalPrompt: this.goalPrompt,
|
|
2307
|
+
systemPrompt: this.systemPrompt,
|
|
2308
|
+
developerPrompt: this.developerPrompt,
|
|
2309
|
+
availableTools: this.availableTools,
|
|
2310
|
+
options: this.taskOptions,
|
|
2311
|
+
maxIterations: this.maxIterations,
|
|
2312
|
+
reasoningEffort: this.reasoningEffort,
|
|
2313
|
+
agentModelId: this.agentModelId,
|
|
2314
|
+
orchestratorModelId: this.orchestratorModelId
|
|
2315
|
+
});
|
|
2316
|
+
this._lastTaskId = response.taskId;
|
|
2317
|
+
const taskId = response.taskId;
|
|
2318
|
+
console.log(
|
|
2319
|
+
`[Flow] Task created \u2014 taskId=${taskId} status=${response.status}`
|
|
2320
|
+
);
|
|
2321
|
+
const status = await this._waitForTerminal(client, taskId, {
|
|
2322
|
+
realtime,
|
|
2323
|
+
timeoutMs
|
|
2324
|
+
});
|
|
2325
|
+
if (status.status === "cancelled") {
|
|
2326
|
+
throw new FlowCancelledError(taskId);
|
|
2327
|
+
}
|
|
2328
|
+
const finalMessage = await this._getFinalMessage(client, taskId);
|
|
2329
|
+
console.log(
|
|
2330
|
+
`[Flow] ${this.constructor.name} completed \u2014 taskId=${taskId} messageLen=${finalMessage.length}`
|
|
2331
|
+
);
|
|
2332
|
+
return this.parseResult(finalMessage);
|
|
2333
|
+
}
|
|
2334
|
+
// -- Completion waiting -----------------------------------------------
|
|
2335
|
+
async _waitForTerminal(client, taskId, opts) {
|
|
2336
|
+
const { realtime, timeoutMs } = opts;
|
|
2337
|
+
const status = await client.getTaskStatus(taskId);
|
|
2338
|
+
if (TERMINAL_STATUSES.has(status.status)) {
|
|
2339
|
+
console.log(
|
|
2340
|
+
`[Flow] Task ${taskId} already terminal \u2014 status=${status.status}`
|
|
2341
|
+
);
|
|
2342
|
+
return status;
|
|
2343
|
+
}
|
|
2344
|
+
if (realtime) {
|
|
2345
|
+
await this._waitViaSocketIO(taskId, realtime, timeoutMs);
|
|
2346
|
+
} else {
|
|
2347
|
+
console.log(
|
|
2348
|
+
`[Flow] No RealtimeClient available \u2014 polling task ${taskId} with backoff (timeout=${timeoutMs}ms)`
|
|
2349
|
+
);
|
|
2350
|
+
await this._waitViaPolling(client, taskId, timeoutMs);
|
|
2351
|
+
}
|
|
2352
|
+
return client.getTaskStatus(taskId);
|
|
2353
|
+
}
|
|
2354
|
+
async _waitViaSocketIO(taskId, realtime, timeoutMs) {
|
|
2355
|
+
realtime.subscribeTask(taskId);
|
|
2356
|
+
return new Promise((resolve, reject) => {
|
|
2357
|
+
const timer = setTimeout(() => {
|
|
2358
|
+
cleanup();
|
|
2359
|
+
reject(
|
|
2360
|
+
new FlowTimeoutError(
|
|
2361
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms`
|
|
2362
|
+
)
|
|
2363
|
+
);
|
|
2364
|
+
}, timeoutMs);
|
|
2365
|
+
const handler = (...args) => {
|
|
2366
|
+
const event = args[0] ?? {};
|
|
2367
|
+
if (event.task_id !== taskId) return;
|
|
2368
|
+
const newStatus = event.new_status ?? "";
|
|
2369
|
+
if (TERMINAL_STATUSES.has(newStatus)) {
|
|
2370
|
+
cleanup();
|
|
2371
|
+
resolve();
|
|
2372
|
+
}
|
|
2373
|
+
};
|
|
2374
|
+
const cleanup = () => {
|
|
2375
|
+
clearTimeout(timer);
|
|
2376
|
+
realtime.off("task_status_changed", handler);
|
|
2377
|
+
realtime.unsubscribeTask(taskId);
|
|
2378
|
+
};
|
|
2379
|
+
realtime.on("task_status_changed", handler);
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
async _waitViaPolling(client, taskId, timeoutMs) {
|
|
2383
|
+
const deadline = Date.now() + timeoutMs;
|
|
2384
|
+
let delay = 1e3;
|
|
2385
|
+
while (Date.now() < deadline) {
|
|
2386
|
+
const status = await client.getTaskStatus(taskId);
|
|
2387
|
+
if (TERMINAL_STATUSES.has(status.status)) return;
|
|
2388
|
+
await this._sleep(delay);
|
|
2389
|
+
delay = Math.min(Math.round(delay * 1.5), 1e4);
|
|
2390
|
+
}
|
|
2391
|
+
throw new FlowTimeoutError(
|
|
2392
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms (polling fallback)`
|
|
2393
|
+
);
|
|
2394
|
+
}
|
|
2395
|
+
// -- Conversation helpers ---------------------------------------------
|
|
2396
|
+
async _getFinalMessage(client, taskId) {
|
|
2397
|
+
const conversation = await client.getTaskConversation(taskId, {
|
|
2398
|
+
includeSummaries: false,
|
|
2399
|
+
excludeArchived: false
|
|
2400
|
+
});
|
|
2401
|
+
const messages = conversation.conversation;
|
|
2402
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2403
|
+
const msg = messages[i];
|
|
2404
|
+
if (msg.role === "assistant" && msg.content?.trim()) {
|
|
2405
|
+
return msg.content;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2409
|
+
const msg = messages[i];
|
|
2410
|
+
if (msg.role === "assistant" && msg.archived && msg.id != null) {
|
|
2411
|
+
const archived = await client.getArchivedMessageContent(taskId, msg.id);
|
|
2412
|
+
if (archived.content?.trim()) {
|
|
2413
|
+
return archived.content;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
const status = await client.getTaskStatus(taskId);
|
|
2418
|
+
throw new FlowError(
|
|
2419
|
+
`No assistant message with content found in task ${taskId}. Status: ${status.status}. Result: ${(status.result ?? "").slice(0, 200) || "empty"}. Messages in conversation: ${messages.length}.`
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
// -- Helper -----------------------------------------------------------
|
|
2423
|
+
_sleep(ms) {
|
|
2424
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2425
|
+
}
|
|
2426
|
+
};
|
|
2427
|
+
|
|
1980
2428
|
// src/index.ts
|
|
1981
2429
|
var VERSION = "5.6.0";
|
|
1982
2430
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1983
2431
|
0 && (module.exports = {
|
|
2432
|
+
DEFAULT_FLOW_TIMEOUT_MS,
|
|
1984
2433
|
EVENT_ERROR_EVENT_RECORDED,
|
|
1985
2434
|
EVENT_MESSAGE_ADDED,
|
|
1986
2435
|
EVENT_MESSAGE_STREAMING,
|
|
@@ -1992,6 +2441,10 @@ var VERSION = "5.6.0";
|
|
|
1992
2441
|
EVENT_TASK_ITERATION_CHANGED,
|
|
1993
2442
|
EVENT_TASK_RESULT_UPDATED,
|
|
1994
2443
|
EVENT_TASK_STATUS_CHANGED,
|
|
2444
|
+
Flow,
|
|
2445
|
+
FlowCancelledError,
|
|
2446
|
+
FlowError,
|
|
2447
|
+
FlowTimeoutError,
|
|
1995
2448
|
Orchestrator,
|
|
1996
2449
|
OrchestratorAPIError,
|
|
1997
2450
|
OrchestratorAsync,
|
|
@@ -2002,7 +2455,12 @@ var VERSION = "5.6.0";
|
|
|
2002
2455
|
OrchestratorNotFoundError,
|
|
2003
2456
|
RealtimeClient,
|
|
2004
2457
|
VERSION,
|
|
2458
|
+
camelToSnake,
|
|
2005
2459
|
createInsecureFetch,
|
|
2006
|
-
|
|
2460
|
+
deepCamelCase,
|
|
2461
|
+
extractJsonFromMessage,
|
|
2462
|
+
loadConfig,
|
|
2463
|
+
setupDefaultClient,
|
|
2464
|
+
snakeToCamel
|
|
2007
2465
|
});
|
|
2008
2466
|
//# sourceMappingURL=index.cjs.map
|