@mclean-capital/neura 3.6.0 → 3.6.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/core/server.bundled.mjs +71 -39
- package/core/server.bundled.mjs.map +2 -2
- package/core/version.txt +1 -1
- package/package.json +1 -1
package/core/server.bundled.mjs
CHANGED
|
@@ -80568,16 +80568,16 @@ ${context}
|
|
|
80568
80568
|
this.turnAudioChunks = 0;
|
|
80569
80569
|
this.turnAudioBytes = 0;
|
|
80570
80570
|
this.cb.onTurnComplete();
|
|
80571
|
-
const
|
|
80571
|
+
const res = msg.response;
|
|
80572
|
+
const outputItems = Array.isArray(res?.output) ? res.output : [];
|
|
80572
80573
|
const fullParts = [];
|
|
80573
|
-
|
|
80574
|
-
|
|
80575
|
-
|
|
80576
|
-
|
|
80577
|
-
|
|
80578
|
-
|
|
80579
|
-
|
|
80580
|
-
}
|
|
80574
|
+
for (const item of outputItems) {
|
|
80575
|
+
const it = item;
|
|
80576
|
+
if (it.type === "message" && Array.isArray(it.content)) {
|
|
80577
|
+
for (const part of it.content) {
|
|
80578
|
+
if (part.transcript) {
|
|
80579
|
+
this.pushTranscript("assistant", part.transcript);
|
|
80580
|
+
fullParts.push(part.transcript);
|
|
80581
80581
|
}
|
|
80582
80582
|
}
|
|
80583
80583
|
}
|
|
@@ -80585,53 +80585,85 @@ ${context}
|
|
|
80585
80585
|
if (fullParts.length > 0) {
|
|
80586
80586
|
this.cb.onOutputTranscriptComplete(fullParts.join(""));
|
|
80587
80587
|
}
|
|
80588
|
+
if (res?.status === "completed") {
|
|
80589
|
+
void this.dispatchFunctionCalls(outputItems);
|
|
80590
|
+
}
|
|
80588
80591
|
break;
|
|
80589
80592
|
}
|
|
80590
|
-
case "response.function_call_arguments.done":
|
|
80591
|
-
void this.handleFunctionCallDone(msg);
|
|
80592
|
-
break;
|
|
80593
80593
|
case "error":
|
|
80594
80594
|
log32.error("api error", { error: msg.error });
|
|
80595
80595
|
this.cb.onError(msg.error?.message || "Unknown error");
|
|
80596
80596
|
break;
|
|
80597
80597
|
}
|
|
80598
80598
|
}
|
|
80599
|
-
|
|
80600
|
-
|
|
80601
|
-
|
|
80602
|
-
|
|
80603
|
-
|
|
80604
|
-
|
|
80605
|
-
|
|
80606
|
-
|
|
80607
|
-
|
|
80608
|
-
|
|
80609
|
-
|
|
80610
|
-
|
|
80611
|
-
|
|
80612
|
-
|
|
80613
|
-
|
|
80614
|
-
|
|
80615
|
-
|
|
80616
|
-
|
|
80617
|
-
|
|
80618
|
-
|
|
80619
|
-
|
|
80599
|
+
/**
|
|
80600
|
+
* Execute every `function_call` item from a completed `response.done`
|
|
80601
|
+
* payload in parallel, post their outputs in original `output_index`
|
|
80602
|
+
* order, then fire exactly one `response.create` so the model sees the
|
|
80603
|
+
* full batch as a single follow-up turn.
|
|
80604
|
+
*
|
|
80605
|
+
* Authoritative source: `response.output`. We intentionally do NOT
|
|
80606
|
+
* buffer `response.function_call_arguments.done` deltas; `response.done`
|
|
80607
|
+
* carries the finalized list and is the only shape we trust — see the
|
|
80608
|
+
* Codex review cited in the corresponding commit.
|
|
80609
|
+
*/
|
|
80610
|
+
async dispatchFunctionCalls(outputItems) {
|
|
80611
|
+
const calls = [];
|
|
80612
|
+
outputItems.forEach((item, idx) => {
|
|
80613
|
+
const it = item;
|
|
80614
|
+
if (it.type !== "function_call" || !it.call_id || typeof it.name !== "string") return;
|
|
80615
|
+
let parsed = {};
|
|
80616
|
+
try {
|
|
80617
|
+
parsed = JSON.parse(it.arguments ?? "{}");
|
|
80618
|
+
} catch {
|
|
80619
|
+
}
|
|
80620
|
+
calls.push({ callId: it.call_id, name: it.name, args: parsed, outputIndex: idx });
|
|
80621
|
+
});
|
|
80622
|
+
const seen = /* @__PURE__ */ new Set();
|
|
80623
|
+
const unique = calls.filter((c) => {
|
|
80624
|
+
if (seen.has(c.callId)) return false;
|
|
80625
|
+
seen.add(c.callId);
|
|
80626
|
+
return true;
|
|
80620
80627
|
});
|
|
80621
|
-
|
|
80622
|
-
|
|
80628
|
+
if (unique.length === 0) return;
|
|
80629
|
+
const currentWs = this.ws;
|
|
80630
|
+
const outcomes = [];
|
|
80631
|
+
for (const c of unique) {
|
|
80632
|
+
this.cb.onToolCall(c.name, c.args);
|
|
80633
|
+
try {
|
|
80634
|
+
const result = await handleToolCall(c.name, c.args, {
|
|
80635
|
+
queryWatcher: this.cb.queryWatcher,
|
|
80636
|
+
memoryTools: this.config.memoryTools,
|
|
80637
|
+
enterMode: this.config.enterMode,
|
|
80638
|
+
taskTools: this.config.taskTools,
|
|
80639
|
+
skillTools: this.config.skillTools,
|
|
80640
|
+
workerControl: this.config.workerControl,
|
|
80641
|
+
workerDispatch: this.config.workerDispatch,
|
|
80642
|
+
systemState: this.config.systemState,
|
|
80643
|
+
workerLogs: this.config.workerLogs
|
|
80644
|
+
});
|
|
80645
|
+
this.cb.onToolResult(c.name, result);
|
|
80646
|
+
outcomes.push({ callId: c.callId, result, outputIndex: c.outputIndex });
|
|
80647
|
+
} catch (err) {
|
|
80648
|
+
const errorResult = { error: `Tool ${c.name} failed: ${String(err)}` };
|
|
80649
|
+
this.cb.onToolResult(c.name, errorResult);
|
|
80650
|
+
outcomes.push({ callId: c.callId, result: errorResult, outputIndex: c.outputIndex });
|
|
80651
|
+
}
|
|
80652
|
+
}
|
|
80653
|
+
if (!currentWs || currentWs !== this.ws || currentWs.readyState !== wrapper_default.OPEN) return;
|
|
80654
|
+
outcomes.sort((a, b) => a.outputIndex - b.outputIndex).forEach((o) => {
|
|
80623
80655
|
currentWs.send(
|
|
80624
80656
|
JSON.stringify({
|
|
80625
80657
|
type: "conversation.item.create",
|
|
80626
80658
|
item: {
|
|
80627
80659
|
type: "function_call_output",
|
|
80628
|
-
call_id: callId,
|
|
80629
|
-
output: JSON.stringify(result)
|
|
80660
|
+
call_id: o.callId,
|
|
80661
|
+
output: JSON.stringify(o.result)
|
|
80630
80662
|
}
|
|
80631
80663
|
})
|
|
80632
80664
|
);
|
|
80633
|
-
|
|
80634
|
-
}
|
|
80665
|
+
});
|
|
80666
|
+
currentWs.send(JSON.stringify({ type: "response.create" }));
|
|
80635
80667
|
}
|
|
80636
80668
|
sendAudio(base643) {
|
|
80637
80669
|
if (this.ws?.readyState === wrapper_default.OPEN) {
|