orchestrator-client 5.7.4 → 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 +313 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +162 -1
- package/dist/index.d.ts +162 -1
- package/dist/index.js +306 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -171,6 +171,11 @@ var OrchestratorAsync = class {
|
|
|
171
171
|
_makeUrl(path) {
|
|
172
172
|
return `${this._baseUrl}${path}`;
|
|
173
173
|
}
|
|
174
|
+
_makeAbsoluteUrl(path) {
|
|
175
|
+
const raw = this._makeUrl(path);
|
|
176
|
+
const base = typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0;
|
|
177
|
+
return new URL(raw, base);
|
|
178
|
+
}
|
|
174
179
|
async _resolveHeaders() {
|
|
175
180
|
const headers = {};
|
|
176
181
|
if (this._apiKey) {
|
|
@@ -187,7 +192,7 @@ var OrchestratorAsync = class {
|
|
|
187
192
|
return headers;
|
|
188
193
|
}
|
|
189
194
|
async _request(method, path, opts) {
|
|
190
|
-
const url =
|
|
195
|
+
const url = this._makeAbsoluteUrl(path);
|
|
191
196
|
if (opts?.params) {
|
|
192
197
|
for (const [key, value] of Object.entries(opts.params)) {
|
|
193
198
|
if (value !== void 0) {
|
|
@@ -981,7 +986,7 @@ var OrchestratorAsync = class {
|
|
|
981
986
|
// ------------------------------------------------------------------
|
|
982
987
|
async listErrors(params) {
|
|
983
988
|
const authHeaders = await this._resolveHeaders();
|
|
984
|
-
const url =
|
|
989
|
+
const url = this._makeAbsoluteUrl("/errors");
|
|
985
990
|
if (params?.page !== void 0)
|
|
986
991
|
url.searchParams.set("page", String(params.page));
|
|
987
992
|
if (params?.limit !== void 0)
|
|
@@ -2060,9 +2065,302 @@ var RealtimeClient = class {
|
|
|
2060
2065
|
}
|
|
2061
2066
|
};
|
|
2062
2067
|
|
|
2068
|
+
// src/flow.ts
|
|
2069
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
2070
|
+
"completed",
|
|
2071
|
+
"failed",
|
|
2072
|
+
"cancelled",
|
|
2073
|
+
"translation"
|
|
2074
|
+
]);
|
|
2075
|
+
var DEFAULT_FLOW_TIMEOUT_MS = 6e5;
|
|
2076
|
+
var _defaultClient;
|
|
2077
|
+
var _defaultRealtime;
|
|
2078
|
+
function setupDefaultClient(client, realtime) {
|
|
2079
|
+
_defaultClient = client;
|
|
2080
|
+
_defaultRealtime = realtime;
|
|
2081
|
+
}
|
|
2082
|
+
function getDefaultClient() {
|
|
2083
|
+
if (!_defaultClient) {
|
|
2084
|
+
throw new Error(
|
|
2085
|
+
"No default OrchestratorAsync set. Call setupDefaultClient() during application startup, or pass client to flow.run()."
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
return _defaultClient;
|
|
2089
|
+
}
|
|
2090
|
+
function getDefaultRealtime() {
|
|
2091
|
+
return _defaultRealtime;
|
|
2092
|
+
}
|
|
2093
|
+
var FlowError = class extends Error {
|
|
2094
|
+
constructor(message) {
|
|
2095
|
+
super(message);
|
|
2096
|
+
this.name = "FlowError";
|
|
2097
|
+
}
|
|
2098
|
+
};
|
|
2099
|
+
var FlowTimeoutError = class extends FlowError {
|
|
2100
|
+
constructor(message) {
|
|
2101
|
+
super(message);
|
|
2102
|
+
this.name = "FlowTimeoutError";
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
var FlowCancelledError = class extends FlowError {
|
|
2106
|
+
constructor(taskId) {
|
|
2107
|
+
super(`Task ${taskId} was cancelled`);
|
|
2108
|
+
this.name = "FlowCancelledError";
|
|
2109
|
+
this.taskId = taskId;
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
function extractJsonFromMessage(content) {
|
|
2113
|
+
const cleaned = content.replace(/^\ufeff|\u200b|\u200c|\u200d/, "").trim();
|
|
2114
|
+
if (cleaned.startsWith("{")) {
|
|
2115
|
+
try {
|
|
2116
|
+
return JSON.parse(cleaned);
|
|
2117
|
+
} catch {
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
const start = content.indexOf("{");
|
|
2121
|
+
const end = content.lastIndexOf("}");
|
|
2122
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
2123
|
+
try {
|
|
2124
|
+
return JSON.parse(content.slice(start, end + 1));
|
|
2125
|
+
} catch {
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
const jsonFenceMatch = content.match(/```(?:json)\s*\n([\s\S]*?)\n```/i);
|
|
2129
|
+
if (jsonFenceMatch) {
|
|
2130
|
+
try {
|
|
2131
|
+
return JSON.parse(jsonFenceMatch[1].trim());
|
|
2132
|
+
} catch {
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
const anyFenceMatch = content.match(/```(?:[\w]*)\s*\n([\s\S]*?)\n```/);
|
|
2136
|
+
if (anyFenceMatch) {
|
|
2137
|
+
try {
|
|
2138
|
+
return JSON.parse(anyFenceMatch[1].trim());
|
|
2139
|
+
} catch {
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
const bareBraceMatch = content.match(/\{[\s\S]*\}/);
|
|
2143
|
+
if (bareBraceMatch) {
|
|
2144
|
+
try {
|
|
2145
|
+
return JSON.parse(bareBraceMatch[0]);
|
|
2146
|
+
} catch {
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
throw new FlowError(
|
|
2150
|
+
"Could not extract a valid JSON object from the agent's final message. The agent did not format its answer as required."
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
var Flow = class {
|
|
2154
|
+
constructor() {
|
|
2155
|
+
// -- Workflow-level defaults (override in subclass) --------------------
|
|
2156
|
+
/** Orchestrator workflow type — `"proactive"` by default. */
|
|
2157
|
+
this.workflowId = "proactive";
|
|
2158
|
+
/** Maximum agent turns before the orchestrator forces a failure. */
|
|
2159
|
+
this.maxIterations = 100;
|
|
2160
|
+
/** LLM reasoning budget: `"low"`, `"medium"`, or `"high"`. */
|
|
2161
|
+
this.reasoningEffort = "medium";
|
|
2162
|
+
/**
|
|
2163
|
+
* Maximum milliseconds to wait for the orchestrator task to reach a
|
|
2164
|
+
* terminal state. When exceeded, {@link FlowTimeoutError} is raised.
|
|
2165
|
+
*/
|
|
2166
|
+
this.flowTimeoutMs = DEFAULT_FLOW_TIMEOUT_MS;
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Optional system-prompt override.
|
|
2170
|
+
* When set, this replaces the orchestrator's default system prompt.
|
|
2171
|
+
*/
|
|
2172
|
+
get systemPrompt() {
|
|
2173
|
+
return void 0;
|
|
2174
|
+
}
|
|
2175
|
+
/**
|
|
2176
|
+
* Optional developer-prompt override appended after system prompt.
|
|
2177
|
+
*/
|
|
2178
|
+
get developerPrompt() {
|
|
2179
|
+
return void 0;
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2182
|
+
* Restrict which MCP / built-in tools the agent may use.
|
|
2183
|
+
* `undefined` means *all* tools are available. An empty array means
|
|
2184
|
+
* *no* tools — text-only reasoning.
|
|
2185
|
+
*/
|
|
2186
|
+
get availableTools() {
|
|
2187
|
+
return void 0;
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Per-task feature toggles sent in the creation request.
|
|
2191
|
+
* By default summaries and translation are disabled since flow
|
|
2192
|
+
* output is typically machine-consumed, not human-read.
|
|
2193
|
+
* Override in subclasses that produce human-facing content.
|
|
2194
|
+
*/
|
|
2195
|
+
get taskOptions() {
|
|
2196
|
+
return { disableSummaries: true, disableTranslation: true };
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* Override the agent model for this flow.
|
|
2200
|
+
*/
|
|
2201
|
+
get agentModelId() {
|
|
2202
|
+
return void 0;
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Override the orchestrator (validation) model for this flow.
|
|
2206
|
+
*/
|
|
2207
|
+
get orchestratorModelId() {
|
|
2208
|
+
return void 0;
|
|
2209
|
+
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Cancel the underlying orchestrator task, if one is running.
|
|
2212
|
+
*
|
|
2213
|
+
* Calling `cancel()` after `run()` has returned is a no-op.
|
|
2214
|
+
* The `run()` promise will reject with {@link FlowCancelledError}
|
|
2215
|
+
* after the orchestrator task transitions to `"cancelled"`.
|
|
2216
|
+
*/
|
|
2217
|
+
async cancel(client) {
|
|
2218
|
+
if (!this._lastTaskId) return;
|
|
2219
|
+
const resolvedClient = client ?? getDefaultClient();
|
|
2220
|
+
await resolvedClient.cancelTask(this._lastTaskId);
|
|
2221
|
+
}
|
|
2222
|
+
// -- Lifecycle ---------------------------------------------------------
|
|
2223
|
+
/**
|
|
2224
|
+
* Execute the flow end-to-end.
|
|
2225
|
+
*
|
|
2226
|
+
* @returns The parsed result.
|
|
2227
|
+
* @throws {FlowError} If the task fails, times out, or cannot be parsed.
|
|
2228
|
+
*/
|
|
2229
|
+
async run(params) {
|
|
2230
|
+
const client = params?.client ?? getDefaultClient();
|
|
2231
|
+
const realtime = params?.realtime ?? getDefaultRealtime();
|
|
2232
|
+
const timeoutMs = params?.timeoutMs ?? this.flowTimeoutMs;
|
|
2233
|
+
console.log(
|
|
2234
|
+
`[Flow] Starting ${this.constructor.name} \u2014 workflow=${this.workflowId} goal=${this.goalPrompt.slice(0, 80)}`
|
|
2235
|
+
);
|
|
2236
|
+
const response = await client.createTask({
|
|
2237
|
+
workflowId: this.workflowId,
|
|
2238
|
+
goalPrompt: this.goalPrompt,
|
|
2239
|
+
systemPrompt: this.systemPrompt,
|
|
2240
|
+
developerPrompt: this.developerPrompt,
|
|
2241
|
+
availableTools: this.availableTools,
|
|
2242
|
+
options: this.taskOptions,
|
|
2243
|
+
maxIterations: this.maxIterations,
|
|
2244
|
+
reasoningEffort: this.reasoningEffort,
|
|
2245
|
+
agentModelId: this.agentModelId,
|
|
2246
|
+
orchestratorModelId: this.orchestratorModelId
|
|
2247
|
+
});
|
|
2248
|
+
this._lastTaskId = response.taskId;
|
|
2249
|
+
const taskId = response.taskId;
|
|
2250
|
+
console.log(
|
|
2251
|
+
`[Flow] Task created \u2014 taskId=${taskId} status=${response.status}`
|
|
2252
|
+
);
|
|
2253
|
+
const status = await this._waitForTerminal(client, taskId, {
|
|
2254
|
+
realtime,
|
|
2255
|
+
timeoutMs
|
|
2256
|
+
});
|
|
2257
|
+
if (status.status === "cancelled") {
|
|
2258
|
+
throw new FlowCancelledError(taskId);
|
|
2259
|
+
}
|
|
2260
|
+
const finalMessage = await this._getFinalMessage(client, taskId);
|
|
2261
|
+
console.log(
|
|
2262
|
+
`[Flow] ${this.constructor.name} completed \u2014 taskId=${taskId} messageLen=${finalMessage.length}`
|
|
2263
|
+
);
|
|
2264
|
+
return this.parseResult(finalMessage);
|
|
2265
|
+
}
|
|
2266
|
+
// -- Completion waiting -----------------------------------------------
|
|
2267
|
+
async _waitForTerminal(client, taskId, opts) {
|
|
2268
|
+
const { realtime, timeoutMs } = opts;
|
|
2269
|
+
const status = await client.getTaskStatus(taskId);
|
|
2270
|
+
if (TERMINAL_STATUSES.has(status.status)) {
|
|
2271
|
+
console.log(
|
|
2272
|
+
`[Flow] Task ${taskId} already terminal \u2014 status=${status.status}`
|
|
2273
|
+
);
|
|
2274
|
+
return status;
|
|
2275
|
+
}
|
|
2276
|
+
if (realtime) {
|
|
2277
|
+
await this._waitViaSocketIO(taskId, realtime, timeoutMs);
|
|
2278
|
+
} else {
|
|
2279
|
+
console.log(
|
|
2280
|
+
`[Flow] No RealtimeClient available \u2014 polling task ${taskId} with backoff (timeout=${timeoutMs}ms)`
|
|
2281
|
+
);
|
|
2282
|
+
await this._waitViaPolling(client, taskId, timeoutMs);
|
|
2283
|
+
}
|
|
2284
|
+
return client.getTaskStatus(taskId);
|
|
2285
|
+
}
|
|
2286
|
+
async _waitViaSocketIO(taskId, realtime, timeoutMs) {
|
|
2287
|
+
realtime.subscribeTask(taskId);
|
|
2288
|
+
return new Promise((resolve, reject) => {
|
|
2289
|
+
const timer = setTimeout(() => {
|
|
2290
|
+
cleanup();
|
|
2291
|
+
reject(
|
|
2292
|
+
new FlowTimeoutError(
|
|
2293
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms`
|
|
2294
|
+
)
|
|
2295
|
+
);
|
|
2296
|
+
}, timeoutMs);
|
|
2297
|
+
const handler = (...args) => {
|
|
2298
|
+
const event = args[0] ?? {};
|
|
2299
|
+
if (event.task_id !== taskId) return;
|
|
2300
|
+
const newStatus = event.new_status ?? "";
|
|
2301
|
+
if (TERMINAL_STATUSES.has(newStatus)) {
|
|
2302
|
+
cleanup();
|
|
2303
|
+
resolve();
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
const cleanup = () => {
|
|
2307
|
+
clearTimeout(timer);
|
|
2308
|
+
realtime.off("task_status_changed", handler);
|
|
2309
|
+
realtime.unsubscribeTask(taskId);
|
|
2310
|
+
};
|
|
2311
|
+
realtime.on("task_status_changed", handler);
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2314
|
+
async _waitViaPolling(client, taskId, timeoutMs) {
|
|
2315
|
+
const deadline = Date.now() + timeoutMs;
|
|
2316
|
+
let delay = 1e3;
|
|
2317
|
+
while (Date.now() < deadline) {
|
|
2318
|
+
const status = await client.getTaskStatus(taskId);
|
|
2319
|
+
if (TERMINAL_STATUSES.has(status.status)) return;
|
|
2320
|
+
await this._sleep(delay);
|
|
2321
|
+
delay = Math.min(Math.round(delay * 1.5), 1e4);
|
|
2322
|
+
}
|
|
2323
|
+
throw new FlowTimeoutError(
|
|
2324
|
+
`Task ${taskId} did not reach a terminal state within ${timeoutMs}ms (polling fallback)`
|
|
2325
|
+
);
|
|
2326
|
+
}
|
|
2327
|
+
// -- Conversation helpers ---------------------------------------------
|
|
2328
|
+
async _getFinalMessage(client, taskId) {
|
|
2329
|
+
const conversation = await client.getTaskConversation(taskId, {
|
|
2330
|
+
includeSummaries: false,
|
|
2331
|
+
excludeArchived: false
|
|
2332
|
+
});
|
|
2333
|
+
const messages = conversation.conversation;
|
|
2334
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2335
|
+
const msg = messages[i];
|
|
2336
|
+
if (msg.role === "assistant" && msg.content?.trim()) {
|
|
2337
|
+
return msg.content;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2341
|
+
const msg = messages[i];
|
|
2342
|
+
if (msg.role === "assistant" && msg.archived && msg.id != null) {
|
|
2343
|
+
const archived = await client.getArchivedMessageContent(taskId, msg.id);
|
|
2344
|
+
if (archived.content?.trim()) {
|
|
2345
|
+
return archived.content;
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
const status = await client.getTaskStatus(taskId);
|
|
2350
|
+
throw new FlowError(
|
|
2351
|
+
`No assistant message with content found in task ${taskId}. Status: ${status.status}. Result: ${(status.result ?? "").slice(0, 200) || "empty"}. Messages in conversation: ${messages.length}.`
|
|
2352
|
+
);
|
|
2353
|
+
}
|
|
2354
|
+
// -- Helper -----------------------------------------------------------
|
|
2355
|
+
_sleep(ms) {
|
|
2356
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
|
|
2063
2360
|
// src/index.ts
|
|
2064
2361
|
var VERSION = "5.6.0";
|
|
2065
2362
|
export {
|
|
2363
|
+
DEFAULT_FLOW_TIMEOUT_MS,
|
|
2066
2364
|
EVENT_ERROR_EVENT_RECORDED,
|
|
2067
2365
|
EVENT_MESSAGE_ADDED,
|
|
2068
2366
|
EVENT_MESSAGE_STREAMING,
|
|
@@ -2074,6 +2372,10 @@ export {
|
|
|
2074
2372
|
EVENT_TASK_ITERATION_CHANGED,
|
|
2075
2373
|
EVENT_TASK_RESULT_UPDATED,
|
|
2076
2374
|
EVENT_TASK_STATUS_CHANGED,
|
|
2375
|
+
Flow,
|
|
2376
|
+
FlowCancelledError,
|
|
2377
|
+
FlowError,
|
|
2378
|
+
FlowTimeoutError,
|
|
2077
2379
|
Orchestrator,
|
|
2078
2380
|
OrchestratorAPIError,
|
|
2079
2381
|
OrchestratorAsync,
|
|
@@ -2087,7 +2389,9 @@ export {
|
|
|
2087
2389
|
camelToSnake,
|
|
2088
2390
|
createInsecureFetch,
|
|
2089
2391
|
deepCamelCase,
|
|
2392
|
+
extractJsonFromMessage,
|
|
2090
2393
|
loadConfig,
|
|
2394
|
+
setupDefaultClient,
|
|
2091
2395
|
snakeToCamel
|
|
2092
2396
|
};
|
|
2093
2397
|
//# sourceMappingURL=index.js.map
|