orchestrator-client 5.7.4 → 5.7.12
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 +341 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -1
- package/dist/index.d.ts +163 -1
- package/dist/index.js +334 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -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,
|
|
@@ -54,7 +59,9 @@ __export(index_exports, {
|
|
|
54
59
|
camelToSnake: () => camelToSnake,
|
|
55
60
|
createInsecureFetch: () => createInsecureFetch,
|
|
56
61
|
deepCamelCase: () => deepCamelCase,
|
|
62
|
+
extractJsonFromMessage: () => extractJsonFromMessage,
|
|
57
63
|
loadConfig: () => loadConfig,
|
|
64
|
+
setupDefaultClient: () => setupDefaultClient,
|
|
58
65
|
snakeToCamel: () => snakeToCamel
|
|
59
66
|
});
|
|
60
67
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -232,6 +239,11 @@ var OrchestratorAsync = class {
|
|
|
232
239
|
_makeUrl(path) {
|
|
233
240
|
return `${this._baseUrl}${path}`;
|
|
234
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
|
+
}
|
|
235
247
|
async _resolveHeaders() {
|
|
236
248
|
const headers = {};
|
|
237
249
|
if (this._apiKey) {
|
|
@@ -248,7 +260,7 @@ var OrchestratorAsync = class {
|
|
|
248
260
|
return headers;
|
|
249
261
|
}
|
|
250
262
|
async _request(method, path, opts) {
|
|
251
|
-
const url =
|
|
263
|
+
const url = this._makeAbsoluteUrl(path);
|
|
252
264
|
if (opts?.params) {
|
|
253
265
|
for (const [key, value] of Object.entries(opts.params)) {
|
|
254
266
|
if (value !== void 0) {
|
|
@@ -1042,7 +1054,7 @@ var OrchestratorAsync = class {
|
|
|
1042
1054
|
// ------------------------------------------------------------------
|
|
1043
1055
|
async listErrors(params) {
|
|
1044
1056
|
const authHeaders = await this._resolveHeaders();
|
|
1045
|
-
const url =
|
|
1057
|
+
const url = this._makeAbsoluteUrl("/errors");
|
|
1046
1058
|
if (params?.page !== void 0)
|
|
1047
1059
|
url.searchParams.set("page", String(params.page));
|
|
1048
1060
|
if (params?.limit !== void 0)
|
|
@@ -1836,6 +1848,11 @@ var RealtimeClient = class {
|
|
|
1836
1848
|
this._socket = null;
|
|
1837
1849
|
this._handlers = /* @__PURE__ */ new Map();
|
|
1838
1850
|
this._connected = false;
|
|
1851
|
+
// Every room joined through any API (subscribeTask, joinRooms, subscribe(),
|
|
1852
|
+
// subscribeEvents, etc.) is tracked here so it can be replayed on reconnect.
|
|
1853
|
+
// Server-side room membership is tied to the socket connection and is lost
|
|
1854
|
+
// on disconnect — the full set must be re-emitted on every reconnect.
|
|
1855
|
+
this._rooms = /* @__PURE__ */ new Set();
|
|
1839
1856
|
// Multi-subscriber room-diffing state (mirrors WebSocketProvider)
|
|
1840
1857
|
this._subscriptions = /* @__PURE__ */ new Map();
|
|
1841
1858
|
this._currentRooms = /* @__PURE__ */ new Set();
|
|
@@ -1872,6 +1889,10 @@ var RealtimeClient = class {
|
|
|
1872
1889
|
this._socket.on("connect", () => {
|
|
1873
1890
|
this._connected = true;
|
|
1874
1891
|
this._currentRooms = /* @__PURE__ */ new Set();
|
|
1892
|
+
if (this._rooms.size > 0) {
|
|
1893
|
+
this._socket?.emit("join", { rooms: [...this._rooms] });
|
|
1894
|
+
this._currentRooms = new Set(this._rooms);
|
|
1895
|
+
}
|
|
1875
1896
|
this._syncRooms();
|
|
1876
1897
|
});
|
|
1877
1898
|
this._socket.on("disconnect", () => {
|
|
@@ -1929,7 +1950,9 @@ var RealtimeClient = class {
|
|
|
1929
1950
|
*/
|
|
1930
1951
|
subscribeTask(taskId) {
|
|
1931
1952
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1932
|
-
|
|
1953
|
+
const room = `task:${taskId}`;
|
|
1954
|
+
this._socket.emit("join", { rooms: [room] });
|
|
1955
|
+
this._rooms.add(room);
|
|
1933
1956
|
}
|
|
1934
1957
|
/**
|
|
1935
1958
|
* Unsubscribe from realtime events for a specific task.
|
|
@@ -1937,7 +1960,9 @@ var RealtimeClient = class {
|
|
|
1937
1960
|
*/
|
|
1938
1961
|
unsubscribeTask(taskId) {
|
|
1939
1962
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1940
|
-
|
|
1963
|
+
const room = `task:${taskId}`;
|
|
1964
|
+
this._socket.emit("leave", { rooms: [room] });
|
|
1965
|
+
this._rooms.delete(room);
|
|
1941
1966
|
}
|
|
1942
1967
|
/**
|
|
1943
1968
|
* Subscribe to event-type-scoped rooms.
|
|
@@ -1947,6 +1972,7 @@ var RealtimeClient = class {
|
|
|
1947
1972
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1948
1973
|
const rooms = eventTypes.map((t) => `event:${t}`);
|
|
1949
1974
|
this._socket.emit("join", { rooms });
|
|
1975
|
+
for (const r of rooms) this._rooms.add(r);
|
|
1950
1976
|
}
|
|
1951
1977
|
/**
|
|
1952
1978
|
* Unsubscribe from event-type-scoped rooms.
|
|
@@ -1955,6 +1981,7 @@ var RealtimeClient = class {
|
|
|
1955
1981
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1956
1982
|
const rooms = eventTypes.map((t) => `event:${t}`);
|
|
1957
1983
|
this._socket.emit("leave", { rooms });
|
|
1984
|
+
for (const r of rooms) this._rooms.delete(r);
|
|
1958
1985
|
}
|
|
1959
1986
|
/**
|
|
1960
1987
|
* Subscribe to the `all` broadcast room (receives all events).
|
|
@@ -1962,20 +1989,25 @@ var RealtimeClient = class {
|
|
|
1962
1989
|
subscribeAll() {
|
|
1963
1990
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1964
1991
|
this._socket.emit("join", { rooms: ["all"] });
|
|
1992
|
+
this._rooms.add("all");
|
|
1965
1993
|
}
|
|
1966
1994
|
/**
|
|
1967
1995
|
* Subscribe to a locale-specific room.
|
|
1968
1996
|
*/
|
|
1969
1997
|
subscribeLocale(locale) {
|
|
1970
1998
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1971
|
-
|
|
1999
|
+
const room = `locale:${locale}`;
|
|
2000
|
+
this._socket.emit("join", { rooms: [room] });
|
|
2001
|
+
this._rooms.add(room);
|
|
1972
2002
|
}
|
|
1973
2003
|
/**
|
|
1974
2004
|
* Unsubscribe from a locale-specific room.
|
|
1975
2005
|
*/
|
|
1976
2006
|
unsubscribeLocale(locale) {
|
|
1977
2007
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1978
|
-
|
|
2008
|
+
const room = `locale:${locale}`;
|
|
2009
|
+
this._socket.emit("leave", { rooms: [room] });
|
|
2010
|
+
this._rooms.delete(room);
|
|
1979
2011
|
}
|
|
1980
2012
|
/**
|
|
1981
2013
|
* Join arbitrary rooms by name.
|
|
@@ -1983,6 +2015,7 @@ var RealtimeClient = class {
|
|
|
1983
2015
|
joinRooms(rooms) {
|
|
1984
2016
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1985
2017
|
this._socket.emit("join", { rooms });
|
|
2018
|
+
for (const r of rooms) this._rooms.add(r);
|
|
1986
2019
|
}
|
|
1987
2020
|
/**
|
|
1988
2021
|
* Leave arbitrary rooms by name.
|
|
@@ -1990,6 +2023,7 @@ var RealtimeClient = class {
|
|
|
1990
2023
|
leaveRooms(rooms) {
|
|
1991
2024
|
if (!this._socket) throw new Error("RealtimeClient not connected");
|
|
1992
2025
|
this._socket.emit("leave", { rooms });
|
|
2026
|
+
for (const r of rooms) this._rooms.delete(r);
|
|
1993
2027
|
}
|
|
1994
2028
|
// ------------------------------------------------------------------
|
|
1995
2029
|
// Multi-subscriber API (mirrors WebSocketProvider room-diffing)
|
|
@@ -2047,6 +2081,8 @@ var RealtimeClient = class {
|
|
|
2047
2081
|
const toLeave = [...this._currentRooms].filter((r) => !needed.has(r));
|
|
2048
2082
|
if (toJoin.length) socket.emit("join", { rooms: toJoin });
|
|
2049
2083
|
if (toLeave.length) socket.emit("leave", { rooms: toLeave });
|
|
2084
|
+
for (const r of toJoin) this._rooms.add(r);
|
|
2085
|
+
for (const r of toLeave) this._rooms.delete(r);
|
|
2050
2086
|
this._currentRooms = needed;
|
|
2051
2087
|
}
|
|
2052
2088
|
/**
|
|
@@ -2121,10 +2157,303 @@ var RealtimeClient = class {
|
|
|
2121
2157
|
}
|
|
2122
2158
|
};
|
|
2123
2159
|
|
|
2160
|
+
// src/flow.ts
|
|
2161
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
2162
|
+
"completed",
|
|
2163
|
+
"failed",
|
|
2164
|
+
"cancelled",
|
|
2165
|
+
"translation"
|
|
2166
|
+
]);
|
|
2167
|
+
var DEFAULT_FLOW_TIMEOUT_MS = 6e5;
|
|
2168
|
+
var _defaultClient;
|
|
2169
|
+
var _defaultRealtime;
|
|
2170
|
+
function setupDefaultClient(client, realtime) {
|
|
2171
|
+
_defaultClient = client;
|
|
2172
|
+
_defaultRealtime = realtime;
|
|
2173
|
+
}
|
|
2174
|
+
function getDefaultClient() {
|
|
2175
|
+
if (!_defaultClient) {
|
|
2176
|
+
throw new Error(
|
|
2177
|
+
"No default OrchestratorAsync set. Call setupDefaultClient() during application startup, or pass client to flow.run()."
|
|
2178
|
+
);
|
|
2179
|
+
}
|
|
2180
|
+
return _defaultClient;
|
|
2181
|
+
}
|
|
2182
|
+
function getDefaultRealtime() {
|
|
2183
|
+
return _defaultRealtime;
|
|
2184
|
+
}
|
|
2185
|
+
var FlowError = class extends Error {
|
|
2186
|
+
constructor(message) {
|
|
2187
|
+
super(message);
|
|
2188
|
+
this.name = "FlowError";
|
|
2189
|
+
}
|
|
2190
|
+
};
|
|
2191
|
+
var FlowTimeoutError = class extends FlowError {
|
|
2192
|
+
constructor(message) {
|
|
2193
|
+
super(message);
|
|
2194
|
+
this.name = "FlowTimeoutError";
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
var FlowCancelledError = class extends FlowError {
|
|
2198
|
+
constructor(taskId) {
|
|
2199
|
+
super(`Task ${taskId} was cancelled`);
|
|
2200
|
+
this.name = "FlowCancelledError";
|
|
2201
|
+
this.taskId = taskId;
|
|
2202
|
+
}
|
|
2203
|
+
};
|
|
2204
|
+
function extractJsonFromMessage(content) {
|
|
2205
|
+
const cleaned = content.replace(/^\ufeff|\u200b|\u200c|\u200d/, "").trim();
|
|
2206
|
+
if (cleaned.startsWith("{")) {
|
|
2207
|
+
try {
|
|
2208
|
+
return JSON.parse(cleaned);
|
|
2209
|
+
} catch {
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
const start = content.indexOf("{");
|
|
2213
|
+
const end = content.lastIndexOf("}");
|
|
2214
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
2215
|
+
try {
|
|
2216
|
+
return JSON.parse(content.slice(start, end + 1));
|
|
2217
|
+
} catch {
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
const jsonFenceMatch = content.match(/```(?:json)\s*\n([\s\S]*?)\n```/i);
|
|
2221
|
+
if (jsonFenceMatch) {
|
|
2222
|
+
try {
|
|
2223
|
+
return JSON.parse(jsonFenceMatch[1].trim());
|
|
2224
|
+
} catch {
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
const anyFenceMatch = content.match(/```(?:[\w]*)\s*\n([\s\S]*?)\n```/);
|
|
2228
|
+
if (anyFenceMatch) {
|
|
2229
|
+
try {
|
|
2230
|
+
return JSON.parse(anyFenceMatch[1].trim());
|
|
2231
|
+
} catch {
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
const bareBraceMatch = content.match(/\{[\s\S]*\}/);
|
|
2235
|
+
if (bareBraceMatch) {
|
|
2236
|
+
try {
|
|
2237
|
+
return JSON.parse(bareBraceMatch[0]);
|
|
2238
|
+
} catch {
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
throw new FlowError(
|
|
2242
|
+
"Could not extract a valid JSON object from the agent's final message. The agent did not format its answer as required."
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
var Flow = class {
|
|
2246
|
+
constructor() {
|
|
2247
|
+
// -- Workflow-level defaults (override in subclass) --------------------
|
|
2248
|
+
/** Orchestrator workflow type — `"proactive"` by default. */
|
|
2249
|
+
this.workflowId = "proactive";
|
|
2250
|
+
/** Maximum agent turns before the orchestrator forces a failure. */
|
|
2251
|
+
this.maxIterations = 100;
|
|
2252
|
+
/** LLM reasoning budget: `"low"`, `"medium"`, or `"high"`. */
|
|
2253
|
+
this.reasoningEffort = "medium";
|
|
2254
|
+
/**
|
|
2255
|
+
* Maximum milliseconds to wait for the orchestrator task to reach a
|
|
2256
|
+
* terminal state. When exceeded, {@link FlowTimeoutError} is raised.
|
|
2257
|
+
*/
|
|
2258
|
+
this.flowTimeoutMs = DEFAULT_FLOW_TIMEOUT_MS;
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Optional system-prompt override.
|
|
2262
|
+
* When set, this replaces the orchestrator's default system prompt.
|
|
2263
|
+
*/
|
|
2264
|
+
get systemPrompt() {
|
|
2265
|
+
return void 0;
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* Optional developer-prompt override appended after system prompt.
|
|
2269
|
+
*/
|
|
2270
|
+
get developerPrompt() {
|
|
2271
|
+
return void 0;
|
|
2272
|
+
}
|
|
2273
|
+
/**
|
|
2274
|
+
* Restrict which MCP / built-in tools the agent may use.
|
|
2275
|
+
* `undefined` means *all* tools are available. An empty array means
|
|
2276
|
+
* *no* tools — text-only reasoning.
|
|
2277
|
+
*/
|
|
2278
|
+
get availableTools() {
|
|
2279
|
+
return void 0;
|
|
2280
|
+
}
|
|
2281
|
+
/**
|
|
2282
|
+
* Per-task feature toggles sent in the creation request.
|
|
2283
|
+
* By default summaries and translation are disabled since flow
|
|
2284
|
+
* output is typically machine-consumed, not human-read.
|
|
2285
|
+
* Override in subclasses that produce human-facing content.
|
|
2286
|
+
*/
|
|
2287
|
+
get taskOptions() {
|
|
2288
|
+
return { disableSummaries: true, disableTranslation: true };
|
|
2289
|
+
}
|
|
2290
|
+
/**
|
|
2291
|
+
* Override the agent model for this flow.
|
|
2292
|
+
*/
|
|
2293
|
+
get agentModelId() {
|
|
2294
|
+
return void 0;
|
|
2295
|
+
}
|
|
2296
|
+
/**
|
|
2297
|
+
* Override the orchestrator (validation) model for this flow.
|
|
2298
|
+
*/
|
|
2299
|
+
get orchestratorModelId() {
|
|
2300
|
+
return void 0;
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* Cancel the underlying orchestrator task, if one is running.
|
|
2304
|
+
*
|
|
2305
|
+
* Calling `cancel()` after `run()` has returned is a no-op.
|
|
2306
|
+
* The `run()` promise will reject with {@link FlowCancelledError}
|
|
2307
|
+
* after the orchestrator task transitions to `"cancelled"`.
|
|
2308
|
+
*/
|
|
2309
|
+
async cancel(client) {
|
|
2310
|
+
if (!this._lastTaskId) return;
|
|
2311
|
+
const resolvedClient = client ?? getDefaultClient();
|
|
2312
|
+
await resolvedClient.cancelTask(this._lastTaskId);
|
|
2313
|
+
}
|
|
2314
|
+
// -- Lifecycle ---------------------------------------------------------
|
|
2315
|
+
/**
|
|
2316
|
+
* Execute the flow end-to-end.
|
|
2317
|
+
*
|
|
2318
|
+
* @returns The parsed result.
|
|
2319
|
+
* @throws {FlowError} If the task fails, times out, or cannot be parsed.
|
|
2320
|
+
*/
|
|
2321
|
+
async run(params) {
|
|
2322
|
+
const client = params?.client ?? getDefaultClient();
|
|
2323
|
+
const realtime = params?.realtime ?? getDefaultRealtime();
|
|
2324
|
+
const timeoutMs = params?.timeoutMs ?? this.flowTimeoutMs;
|
|
2325
|
+
console.log(
|
|
2326
|
+
`[Flow] Starting ${this.constructor.name} \u2014 workflow=${this.workflowId} goal=${this.goalPrompt.slice(0, 80)}`
|
|
2327
|
+
);
|
|
2328
|
+
const response = await client.createTask({
|
|
2329
|
+
workflowId: this.workflowId,
|
|
2330
|
+
goalPrompt: this.goalPrompt,
|
|
2331
|
+
systemPrompt: this.systemPrompt,
|
|
2332
|
+
developerPrompt: this.developerPrompt,
|
|
2333
|
+
availableTools: this.availableTools,
|
|
2334
|
+
options: this.taskOptions,
|
|
2335
|
+
maxIterations: this.maxIterations,
|
|
2336
|
+
reasoningEffort: this.reasoningEffort,
|
|
2337
|
+
agentModelId: this.agentModelId,
|
|
2338
|
+
orchestratorModelId: this.orchestratorModelId
|
|
2339
|
+
});
|
|
2340
|
+
this._lastTaskId = response.taskId;
|
|
2341
|
+
const taskId = response.taskId;
|
|
2342
|
+
console.log(
|
|
2343
|
+
`[Flow] Task created \u2014 taskId=${taskId} status=${response.status}`
|
|
2344
|
+
);
|
|
2345
|
+
const status = await this._waitForTerminal(client, taskId, {
|
|
2346
|
+
realtime,
|
|
2347
|
+
timeoutMs
|
|
2348
|
+
});
|
|
2349
|
+
if (status.status === "cancelled") {
|
|
2350
|
+
throw new FlowCancelledError(taskId);
|
|
2351
|
+
}
|
|
2352
|
+
const finalMessage = await this._getFinalMessage(client, taskId);
|
|
2353
|
+
console.log(
|
|
2354
|
+
`[Flow] ${this.constructor.name} completed \u2014 taskId=${taskId} messageLen=${finalMessage.length}`
|
|
2355
|
+
);
|
|
2356
|
+
return this.parseResult(finalMessage);
|
|
2357
|
+
}
|
|
2358
|
+
// -- Completion waiting -----------------------------------------------
|
|
2359
|
+
async _waitForTerminal(client, taskId, opts) {
|
|
2360
|
+
const { realtime, timeoutMs } = opts;
|
|
2361
|
+
const status = await client.getTaskStatus(taskId);
|
|
2362
|
+
if (TERMINAL_STATUSES.has(status.status)) {
|
|
2363
|
+
console.log(
|
|
2364
|
+
`[Flow] Task ${taskId} already terminal \u2014 status=${status.status}`
|
|
2365
|
+
);
|
|
2366
|
+
return status;
|
|
2367
|
+
}
|
|
2368
|
+
if (realtime) {
|
|
2369
|
+
await this._waitViaSocketIO(taskId, realtime, timeoutMs);
|
|
2370
|
+
} else {
|
|
2371
|
+
console.log(
|
|
2372
|
+
`[Flow] No RealtimeClient available \u2014 polling task ${taskId} with backoff (timeout=${timeoutMs}ms)`
|
|
2373
|
+
);
|
|
2374
|
+
await this._waitViaPolling(client, taskId, timeoutMs);
|
|
2375
|
+
}
|
|
2376
|
+
return client.getTaskStatus(taskId);
|
|
2377
|
+
}
|
|
2378
|
+
async _waitViaSocketIO(taskId, realtime, timeoutMs) {
|
|
2379
|
+
realtime.subscribeTask(taskId);
|
|
2380
|
+
return new Promise((resolve, reject) => {
|
|
2381
|
+
const timer = setTimeout(() => {
|
|
2382
|
+
cleanup();
|
|
2383
|
+
reject(
|
|
2384
|
+
new FlowTimeoutError(
|
|
2385
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms`
|
|
2386
|
+
)
|
|
2387
|
+
);
|
|
2388
|
+
}, timeoutMs);
|
|
2389
|
+
const handler = (...args) => {
|
|
2390
|
+
const event = args[0] ?? {};
|
|
2391
|
+
if (event.task_id !== taskId) return;
|
|
2392
|
+
const newStatus = event.new_status ?? "";
|
|
2393
|
+
if (TERMINAL_STATUSES.has(newStatus)) {
|
|
2394
|
+
cleanup();
|
|
2395
|
+
resolve();
|
|
2396
|
+
}
|
|
2397
|
+
};
|
|
2398
|
+
const cleanup = () => {
|
|
2399
|
+
clearTimeout(timer);
|
|
2400
|
+
realtime.off("task_status_changed", handler);
|
|
2401
|
+
realtime.unsubscribeTask(taskId);
|
|
2402
|
+
};
|
|
2403
|
+
realtime.on("task_status_changed", handler);
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
async _waitViaPolling(client, taskId, timeoutMs) {
|
|
2407
|
+
const deadline = Date.now() + timeoutMs;
|
|
2408
|
+
let delay = 1e3;
|
|
2409
|
+
while (Date.now() < deadline) {
|
|
2410
|
+
const status = await client.getTaskStatus(taskId);
|
|
2411
|
+
if (TERMINAL_STATUSES.has(status.status)) return;
|
|
2412
|
+
await this._sleep(delay);
|
|
2413
|
+
delay = Math.min(Math.round(delay * 1.5), 1e4);
|
|
2414
|
+
}
|
|
2415
|
+
throw new FlowTimeoutError(
|
|
2416
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms (polling fallback)`
|
|
2417
|
+
);
|
|
2418
|
+
}
|
|
2419
|
+
// -- Conversation helpers ---------------------------------------------
|
|
2420
|
+
async _getFinalMessage(client, taskId) {
|
|
2421
|
+
const conversation = await client.getTaskConversation(taskId, {
|
|
2422
|
+
includeSummaries: false,
|
|
2423
|
+
excludeArchived: false
|
|
2424
|
+
});
|
|
2425
|
+
const messages = conversation.conversation;
|
|
2426
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2427
|
+
const msg = messages[i];
|
|
2428
|
+
if (msg.role === "assistant" && msg.content?.trim()) {
|
|
2429
|
+
return msg.content;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2433
|
+
const msg = messages[i];
|
|
2434
|
+
if (msg.role === "assistant" && msg.archived && msg.id != null) {
|
|
2435
|
+
const archived = await client.getArchivedMessageContent(taskId, msg.id);
|
|
2436
|
+
if (archived.content?.trim()) {
|
|
2437
|
+
return archived.content;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
const status = await client.getTaskStatus(taskId);
|
|
2442
|
+
throw new FlowError(
|
|
2443
|
+
`No assistant message with content found in task ${taskId}. Status: ${status.status}. Result: ${(status.result ?? "").slice(0, 200) || "empty"}. Messages in conversation: ${messages.length}.`
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
// -- Helper -----------------------------------------------------------
|
|
2447
|
+
_sleep(ms) {
|
|
2448
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2449
|
+
}
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2124
2452
|
// src/index.ts
|
|
2125
2453
|
var VERSION = "5.6.0";
|
|
2126
2454
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2127
2455
|
0 && (module.exports = {
|
|
2456
|
+
DEFAULT_FLOW_TIMEOUT_MS,
|
|
2128
2457
|
EVENT_ERROR_EVENT_RECORDED,
|
|
2129
2458
|
EVENT_MESSAGE_ADDED,
|
|
2130
2459
|
EVENT_MESSAGE_STREAMING,
|
|
@@ -2136,6 +2465,10 @@ var VERSION = "5.6.0";
|
|
|
2136
2465
|
EVENT_TASK_ITERATION_CHANGED,
|
|
2137
2466
|
EVENT_TASK_RESULT_UPDATED,
|
|
2138
2467
|
EVENT_TASK_STATUS_CHANGED,
|
|
2468
|
+
Flow,
|
|
2469
|
+
FlowCancelledError,
|
|
2470
|
+
FlowError,
|
|
2471
|
+
FlowTimeoutError,
|
|
2139
2472
|
Orchestrator,
|
|
2140
2473
|
OrchestratorAPIError,
|
|
2141
2474
|
OrchestratorAsync,
|
|
@@ -2149,7 +2482,9 @@ var VERSION = "5.6.0";
|
|
|
2149
2482
|
camelToSnake,
|
|
2150
2483
|
createInsecureFetch,
|
|
2151
2484
|
deepCamelCase,
|
|
2485
|
+
extractJsonFromMessage,
|
|
2152
2486
|
loadConfig,
|
|
2487
|
+
setupDefaultClient,
|
|
2153
2488
|
snakeToCamel
|
|
2154
2489
|
});
|
|
2155
2490
|
//# sourceMappingURL=index.cjs.map
|