open-agents-ai 0.187.11 → 0.187.13
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.js +303 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -259789,6 +259789,194 @@ var init_app_state = __esm({
|
|
|
259789
259789
|
}
|
|
259790
259790
|
});
|
|
259791
259791
|
|
|
259792
|
+
// packages/orchestrator/dist/streaming-executor.js
|
|
259793
|
+
var StreamingToolExecutor;
|
|
259794
|
+
var init_streaming_executor = __esm({
|
|
259795
|
+
"packages/orchestrator/dist/streaming-executor.js"() {
|
|
259796
|
+
"use strict";
|
|
259797
|
+
init_tool_batching();
|
|
259798
|
+
StreamingToolExecutor = class {
|
|
259799
|
+
tools = /* @__PURE__ */ new Map();
|
|
259800
|
+
insertionOrder = [];
|
|
259801
|
+
config;
|
|
259802
|
+
executeFn = null;
|
|
259803
|
+
constructor(config) {
|
|
259804
|
+
this.config = {
|
|
259805
|
+
maxConcurrent: config?.maxConcurrent ?? 5
|
|
259806
|
+
};
|
|
259807
|
+
}
|
|
259808
|
+
/** Set the tool execution function */
|
|
259809
|
+
setExecutor(fn) {
|
|
259810
|
+
this.executeFn = fn;
|
|
259811
|
+
}
|
|
259812
|
+
/** Number of tools tracked */
|
|
259813
|
+
get size() {
|
|
259814
|
+
return this.tools.size;
|
|
259815
|
+
}
|
|
259816
|
+
/** Whether any tools have been queued */
|
|
259817
|
+
get hasTools() {
|
|
259818
|
+
return this.tools.size > 0;
|
|
259819
|
+
}
|
|
259820
|
+
/**
|
|
259821
|
+
* Queue a new tool call from streaming response.
|
|
259822
|
+
* Called when a tool_use block is first detected in the stream.
|
|
259823
|
+
*/
|
|
259824
|
+
queue(id, name10, partialArgs) {
|
|
259825
|
+
if (this.tools.has(id))
|
|
259826
|
+
return;
|
|
259827
|
+
this.tools.set(id, {
|
|
259828
|
+
id,
|
|
259829
|
+
name: name10,
|
|
259830
|
+
args: partialArgs ?? {},
|
|
259831
|
+
state: "queued",
|
|
259832
|
+
concurrencySafe: isConcurrencySafe(name10),
|
|
259833
|
+
finalized: false,
|
|
259834
|
+
queuedAt: Date.now()
|
|
259835
|
+
});
|
|
259836
|
+
this.insertionOrder.push(id);
|
|
259837
|
+
}
|
|
259838
|
+
/**
|
|
259839
|
+
* Finalize a tool call's arguments (stream complete for this tool_use block).
|
|
259840
|
+
* Parses the accumulated JSON args and triggers execution if conditions allow.
|
|
259841
|
+
*/
|
|
259842
|
+
finalize(id, args) {
|
|
259843
|
+
const entry = this.tools.get(id);
|
|
259844
|
+
if (!entry)
|
|
259845
|
+
return;
|
|
259846
|
+
entry.args = args;
|
|
259847
|
+
entry.finalized = true;
|
|
259848
|
+
if (entry.state === "queued") {
|
|
259849
|
+
this.processQueue();
|
|
259850
|
+
}
|
|
259851
|
+
}
|
|
259852
|
+
/**
|
|
259853
|
+
* Get all completed tool results that haven't been yielded yet.
|
|
259854
|
+
* Respects ordering: stops at first non-yielded exclusive tool that's still running.
|
|
259855
|
+
* Marks returned entries as "yielded".
|
|
259856
|
+
*/
|
|
259857
|
+
drainCompleted() {
|
|
259858
|
+
const results = [];
|
|
259859
|
+
for (const id of this.insertionOrder) {
|
|
259860
|
+
const entry = this.tools.get(id);
|
|
259861
|
+
if (!entry)
|
|
259862
|
+
continue;
|
|
259863
|
+
if (entry.state === "yielded")
|
|
259864
|
+
continue;
|
|
259865
|
+
if ((entry.state === "completed" || entry.state === "failed") && entry.result) {
|
|
259866
|
+
results.push({ id: entry.id, name: entry.name, result: entry.result });
|
|
259867
|
+
entry.state = "yielded";
|
|
259868
|
+
} else if (entry.state === "executing" && !entry.concurrencySafe) {
|
|
259869
|
+
break;
|
|
259870
|
+
}
|
|
259871
|
+
}
|
|
259872
|
+
return results;
|
|
259873
|
+
}
|
|
259874
|
+
/**
|
|
259875
|
+
* Wait for all queued/executing tools to complete.
|
|
259876
|
+
*/
|
|
259877
|
+
async waitAll() {
|
|
259878
|
+
this.processQueue();
|
|
259879
|
+
while (true) {
|
|
259880
|
+
const pending = Array.from(this.tools.values()).filter((e2) => e2.state === "queued" || e2.state === "executing");
|
|
259881
|
+
if (pending.length === 0)
|
|
259882
|
+
break;
|
|
259883
|
+
const executing = pending.filter((e2) => e2.promise);
|
|
259884
|
+
if (executing.length > 0) {
|
|
259885
|
+
await Promise.allSettled(executing.map((e2) => e2.promise));
|
|
259886
|
+
this.processQueue();
|
|
259887
|
+
} else {
|
|
259888
|
+
this.processQueue();
|
|
259889
|
+
await new Promise((r2) => setTimeout(r2, 1));
|
|
259890
|
+
}
|
|
259891
|
+
}
|
|
259892
|
+
}
|
|
259893
|
+
/** Get the current state of all tool calls */
|
|
259894
|
+
getStates() {
|
|
259895
|
+
const states = /* @__PURE__ */ new Map();
|
|
259896
|
+
for (const [id, entry] of this.tools) {
|
|
259897
|
+
states.set(id, entry.state);
|
|
259898
|
+
}
|
|
259899
|
+
return states;
|
|
259900
|
+
}
|
|
259901
|
+
/** Get count of tools in each state */
|
|
259902
|
+
getCounts() {
|
|
259903
|
+
const counts = {
|
|
259904
|
+
queued: 0,
|
|
259905
|
+
executing: 0,
|
|
259906
|
+
completed: 0,
|
|
259907
|
+
failed: 0,
|
|
259908
|
+
yielded: 0
|
|
259909
|
+
};
|
|
259910
|
+
for (const entry of this.tools.values()) {
|
|
259911
|
+
counts[entry.state]++;
|
|
259912
|
+
}
|
|
259913
|
+
return counts;
|
|
259914
|
+
}
|
|
259915
|
+
/** Clear all tool entries (call between turns) */
|
|
259916
|
+
reset() {
|
|
259917
|
+
this.tools.clear();
|
|
259918
|
+
this.insertionOrder = [];
|
|
259919
|
+
}
|
|
259920
|
+
// ─────────────────────────────────────────────────────────
|
|
259921
|
+
// Internal — Hannover-aligned concurrency control
|
|
259922
|
+
// ─────────────────────────────────────────────────────────
|
|
259923
|
+
/**
|
|
259924
|
+
* Can this tool start executing now?
|
|
259925
|
+
* Rules (from Hannover StreamingToolExecutor.canExecuteTool):
|
|
259926
|
+
* 1. No tools executing → any tool can start
|
|
259927
|
+
* 2. New tool is concurrent-safe AND all executing are concurrent-safe → start
|
|
259928
|
+
* 3. Otherwise → wait
|
|
259929
|
+
*/
|
|
259930
|
+
canExecute(entry) {
|
|
259931
|
+
if (!this.executeFn)
|
|
259932
|
+
return false;
|
|
259933
|
+
if (!entry.finalized)
|
|
259934
|
+
return false;
|
|
259935
|
+
const executing = Array.from(this.tools.values()).filter((e2) => e2.state === "executing");
|
|
259936
|
+
if (executing.length >= this.config.maxConcurrent)
|
|
259937
|
+
return false;
|
|
259938
|
+
if (executing.length === 0)
|
|
259939
|
+
return true;
|
|
259940
|
+
if (entry.concurrencySafe && executing.every((e2) => e2.concurrencySafe))
|
|
259941
|
+
return true;
|
|
259942
|
+
return false;
|
|
259943
|
+
}
|
|
259944
|
+
/**
|
|
259945
|
+
* Process the queue in insertion order.
|
|
259946
|
+
* Starts tools that can execute, stops at first exclusive tool that must wait.
|
|
259947
|
+
*/
|
|
259948
|
+
processQueue() {
|
|
259949
|
+
for (const id of this.insertionOrder) {
|
|
259950
|
+
const entry = this.tools.get(id);
|
|
259951
|
+
if (!entry || entry.state !== "queued")
|
|
259952
|
+
continue;
|
|
259953
|
+
if (this.canExecute(entry)) {
|
|
259954
|
+
this.startExecution(entry);
|
|
259955
|
+
} else if (!entry.concurrencySafe) {
|
|
259956
|
+
break;
|
|
259957
|
+
}
|
|
259958
|
+
}
|
|
259959
|
+
}
|
|
259960
|
+
startExecution(entry) {
|
|
259961
|
+
entry.state = "executing";
|
|
259962
|
+
entry.startedAt = Date.now();
|
|
259963
|
+
const exec4 = this.executeFn;
|
|
259964
|
+
entry.promise = exec4(entry.name, entry.args).then((result) => {
|
|
259965
|
+
entry.state = "completed";
|
|
259966
|
+
entry.result = result;
|
|
259967
|
+
entry.completedAt = Date.now();
|
|
259968
|
+
this.processQueue();
|
|
259969
|
+
}).catch((err) => {
|
|
259970
|
+
entry.state = "failed";
|
|
259971
|
+
entry.result = { success: false, output: "", error: String(err) };
|
|
259972
|
+
entry.completedAt = Date.now();
|
|
259973
|
+
this.processQueue();
|
|
259974
|
+
});
|
|
259975
|
+
}
|
|
259976
|
+
};
|
|
259977
|
+
}
|
|
259978
|
+
});
|
|
259979
|
+
|
|
259792
259980
|
// packages/orchestrator/dist/agenticRunner.js
|
|
259793
259981
|
function repairJson(raw) {
|
|
259794
259982
|
if (!raw || typeof raw !== "string")
|
|
@@ -259865,6 +260053,7 @@ var init_agenticRunner = __esm({
|
|
|
259865
260053
|
init_tool_batching();
|
|
259866
260054
|
init_hooks();
|
|
259867
260055
|
init_app_state();
|
|
260056
|
+
init_streaming_executor();
|
|
259868
260057
|
SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
|
|
259869
260058
|
SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
|
|
259870
260059
|
SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
|
|
@@ -259884,6 +260073,7 @@ var init_agenticRunner = __esm({
|
|
|
259884
260073
|
_skillCompactionStrategy = null;
|
|
259885
260074
|
_hookManager = new HookManager();
|
|
259886
260075
|
_appState = createAppState();
|
|
260076
|
+
_streamingExecutor = new StreamingToolExecutor({ maxConcurrent: 5 });
|
|
259887
260077
|
// -- Task State Tracking (Priority 3) --
|
|
259888
260078
|
_taskState = {
|
|
259889
260079
|
goal: "",
|
|
@@ -261016,25 +261206,30 @@ Then use file_read on individual FILES inside it.`);
|
|
|
261016
261206
|
return { tc, output };
|
|
261017
261207
|
};
|
|
261018
261208
|
const rawToolCalls = msg.toolCalls;
|
|
261019
|
-
|
|
261020
|
-
|
|
261021
|
-
|
|
261022
|
-
|
|
261023
|
-
|
|
261024
|
-
|
|
261025
|
-
|
|
261026
|
-
|
|
261027
|
-
|
|
261028
|
-
|
|
261029
|
-
|
|
261030
|
-
|
|
261031
|
-
|
|
261032
|
-
|
|
261033
|
-
|
|
261034
|
-
|
|
261035
|
-
|
|
261209
|
+
if (this.options.streamEnabled && this._streamingExecutor.hasTools) {
|
|
261210
|
+
this._streamingExecutor.setExecutor(async (name10, args) => {
|
|
261211
|
+
const matchTc = rawToolCalls.find((tc) => tc.name === name10 && JSON.stringify(tc.arguments) === JSON.stringify(args)) ?? rawToolCalls.find((tc) => tc.name === name10);
|
|
261212
|
+
if (!matchTc)
|
|
261213
|
+
return { success: false, output: "", error: `Tool ${name10} not found in response` };
|
|
261214
|
+
const r2 = await executeSingle(matchTc);
|
|
261215
|
+
if (!r2)
|
|
261216
|
+
return { success: false, output: "", error: "aborted" };
|
|
261217
|
+
const isError2 = r2.output.startsWith("Error:");
|
|
261218
|
+
return { success: !isError2, output: r2.output, error: isError2 ? r2.output : void 0 };
|
|
261219
|
+
});
|
|
261220
|
+
await this._streamingExecutor.waitAll();
|
|
261221
|
+
const streamResults = this._streamingExecutor.drainCompleted();
|
|
261222
|
+
const handledIds = /* @__PURE__ */ new Set();
|
|
261223
|
+
for (const sr of streamResults) {
|
|
261224
|
+
const matchTc = rawToolCalls.find((tc) => tc.id === sr.id) ?? rawToolCalls.find((tc) => tc.name === sr.name && !handledIds.has(tc.id));
|
|
261225
|
+
if (matchTc) {
|
|
261226
|
+
handledIds.add(matchTc.id);
|
|
261227
|
+
const output = sr.result.success ? sr.result.output : `Error: ${sr.result.error || "unknown"}
|
|
261228
|
+
${sr.result.output}`;
|
|
261229
|
+
messages2.push(this.buildToolMessage(output, matchTc.id));
|
|
261230
|
+
if (matchTc.name === "task_complete") {
|
|
261036
261231
|
completed = true;
|
|
261037
|
-
summary =
|
|
261232
|
+
summary = matchTc.arguments.summary || "";
|
|
261038
261233
|
if (summary && !this._assistantTextEmitted) {
|
|
261039
261234
|
this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
261040
261235
|
this._assistantTextEmitted = true;
|
|
@@ -261043,8 +261238,57 @@ Then use file_read on individual FILES inside it.`);
|
|
|
261043
261238
|
}
|
|
261044
261239
|
}
|
|
261045
261240
|
}
|
|
261046
|
-
if (completed)
|
|
261047
|
-
|
|
261241
|
+
if (!completed) {
|
|
261242
|
+
const unhandled = rawToolCalls.filter((tc) => !handledIds.has(tc.id));
|
|
261243
|
+
for (const tc of unhandled) {
|
|
261244
|
+
if (this.aborted)
|
|
261245
|
+
break;
|
|
261246
|
+
const r2 = await executeSingle(tc);
|
|
261247
|
+
if (r2) {
|
|
261248
|
+
messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
|
|
261249
|
+
if (r2.tc.name === "task_complete") {
|
|
261250
|
+
completed = true;
|
|
261251
|
+
summary = r2.tc.arguments.summary || "";
|
|
261252
|
+
if (summary && !this._assistantTextEmitted) {
|
|
261253
|
+
this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
261254
|
+
this._assistantTextEmitted = true;
|
|
261255
|
+
}
|
|
261256
|
+
break;
|
|
261257
|
+
}
|
|
261258
|
+
}
|
|
261259
|
+
}
|
|
261260
|
+
}
|
|
261261
|
+
} else {
|
|
261262
|
+
const batchToolCalls = rawToolCalls.map((tc) => ({
|
|
261263
|
+
name: tc.name,
|
|
261264
|
+
args: tc.arguments,
|
|
261265
|
+
id: tc.id
|
|
261266
|
+
}));
|
|
261267
|
+
const batches = partitionToolCalls(batchToolCalls);
|
|
261268
|
+
for (const batch2 of batches) {
|
|
261269
|
+
if (this.aborted)
|
|
261270
|
+
break;
|
|
261271
|
+
const results = await executeBatch(batch2, async (call) => {
|
|
261272
|
+
const originalTc = rawToolCalls.find((tc) => tc.id === call.id);
|
|
261273
|
+
return executeSingle(originalTc);
|
|
261274
|
+
}, 5);
|
|
261275
|
+
for (const r2 of results) {
|
|
261276
|
+
if (r2) {
|
|
261277
|
+
messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
|
|
261278
|
+
if (r2.tc.name === "task_complete") {
|
|
261279
|
+
completed = true;
|
|
261280
|
+
summary = r2.tc.arguments.summary || "";
|
|
261281
|
+
if (summary && !this._assistantTextEmitted) {
|
|
261282
|
+
this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
261283
|
+
this._assistantTextEmitted = true;
|
|
261284
|
+
}
|
|
261285
|
+
break;
|
|
261286
|
+
}
|
|
261287
|
+
}
|
|
261288
|
+
}
|
|
261289
|
+
if (completed)
|
|
261290
|
+
break;
|
|
261291
|
+
}
|
|
261048
261292
|
}
|
|
261049
261293
|
if (completed)
|
|
261050
261294
|
break;
|
|
@@ -262963,6 +263207,8 @@ ${description}`
|
|
|
262963
263207
|
const toolCallAccumulators = /* @__PURE__ */ new Map();
|
|
262964
263208
|
let streamUsage;
|
|
262965
263209
|
this.emit({ type: "stream_start", turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
263210
|
+
this._streamingExecutor.reset();
|
|
263211
|
+
let lastFinalizedIdx = -1;
|
|
262966
263212
|
for await (const chunk of backend.chatCompletionStream(request)) {
|
|
262967
263213
|
if (this.aborted)
|
|
262968
263214
|
break;
|
|
@@ -263014,21 +263260,52 @@ ${description}`
|
|
|
263014
263260
|
}
|
|
263015
263261
|
if (chunk.type === "tool_call_delta") {
|
|
263016
263262
|
const idx = chunk.toolCallIndex ?? 0;
|
|
263263
|
+
if (idx > lastFinalizedIdx && lastFinalizedIdx >= 0) {
|
|
263264
|
+
const prevAcc = toolCallAccumulators.get(lastFinalizedIdx);
|
|
263265
|
+
if (prevAcc && prevAcc.name) {
|
|
263266
|
+
let parsedArgs;
|
|
263267
|
+
try {
|
|
263268
|
+
parsedArgs = JSON.parse(prevAcc.args);
|
|
263269
|
+
} catch {
|
|
263270
|
+
parsedArgs = repairJson(prevAcc.args) ?? { _raw: prevAcc.args };
|
|
263271
|
+
}
|
|
263272
|
+
this._streamingExecutor.finalize(prevAcc.id, parsedArgs);
|
|
263273
|
+
}
|
|
263274
|
+
}
|
|
263017
263275
|
if (!toolCallAccumulators.has(idx)) {
|
|
263018
|
-
|
|
263019
|
-
|
|
263020
|
-
|
|
263021
|
-
|
|
263022
|
-
|
|
263276
|
+
const newId = chunk.toolCallId ?? crypto.randomUUID();
|
|
263277
|
+
const newName = chunk.toolCallName ?? "";
|
|
263278
|
+
toolCallAccumulators.set(idx, { id: newId, name: newName, args: "" });
|
|
263279
|
+
if (newName) {
|
|
263280
|
+
this._streamingExecutor.queue(newId, newName);
|
|
263281
|
+
}
|
|
263023
263282
|
}
|
|
263024
263283
|
const acc = toolCallAccumulators.get(idx);
|
|
263025
|
-
if (chunk.toolCallName)
|
|
263284
|
+
if (chunk.toolCallName) {
|
|
263026
263285
|
acc.name = chunk.toolCallName;
|
|
263286
|
+
if (!this._streamingExecutor.getStates().has(acc.id) && acc.name) {
|
|
263287
|
+
this._streamingExecutor.queue(acc.id, acc.name);
|
|
263288
|
+
}
|
|
263289
|
+
}
|
|
263027
263290
|
if (chunk.toolCallId)
|
|
263028
263291
|
acc.id = chunk.toolCallId;
|
|
263029
263292
|
if (chunk.toolCallArgs) {
|
|
263030
263293
|
acc.args += chunk.toolCallArgs;
|
|
263031
263294
|
}
|
|
263295
|
+
lastFinalizedIdx = idx;
|
|
263296
|
+
}
|
|
263297
|
+
}
|
|
263298
|
+
if (toolCallAccumulators.size > 0) {
|
|
263299
|
+
for (const [, acc] of toolCallAccumulators) {
|
|
263300
|
+
if (acc.name && !["completed", "failed", "yielded", "executing"].includes(this._streamingExecutor.getStates().get(acc.id) ?? "")) {
|
|
263301
|
+
let parsedArgs;
|
|
263302
|
+
try {
|
|
263303
|
+
parsedArgs = JSON.parse(acc.args || "{}");
|
|
263304
|
+
} catch {
|
|
263305
|
+
parsedArgs = repairJson(acc.args) ?? { _raw: acc.args };
|
|
263306
|
+
}
|
|
263307
|
+
this._streamingExecutor.finalize(acc.id, parsedArgs);
|
|
263308
|
+
}
|
|
263032
263309
|
}
|
|
263033
263310
|
}
|
|
263034
263311
|
this.emit({ type: "stream_end", content, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -265126,13 +265403,6 @@ var init_skill_fork = __esm({
|
|
|
265126
265403
|
}
|
|
265127
265404
|
});
|
|
265128
265405
|
|
|
265129
|
-
// packages/orchestrator/dist/streaming-executor.js
|
|
265130
|
-
var init_streaming_executor = __esm({
|
|
265131
|
-
"packages/orchestrator/dist/streaming-executor.js"() {
|
|
265132
|
-
"use strict";
|
|
265133
|
-
}
|
|
265134
|
-
});
|
|
265135
|
-
|
|
265136
265406
|
// packages/orchestrator/dist/index.js
|
|
265137
265407
|
var init_dist7 = __esm({
|
|
265138
265408
|
"packages/orchestrator/dist/index.js"() {
|
package/package.json
CHANGED