aboutsummaryrefslogtreecommitdiff
path: root/modules/core/core-bundle.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-11-02 20:50:25 +0100
committerAgando <roduccomm@gmail.com>2026-11-02 20:50:25 +0100
commitd6eee520bc26631455135d1f2229d4013721e5b9 (patch)
tree728f82b9883564e586be05f2c8a44aaf746ee6fb /modules/core/core-bundle.js
parent8d5c4b563da5225c4dbd2a44c7635c49a16d5ab1 (diff)
fix(newos4): chat() threw on every tool-using turn and never returned its answer
Regression from 32608bc, caught by the .chat() caller sweep before it aged: - `recent` was referenced in chat()'s finally block but never declared, so any turn with toolTurns > 0 threw ReferenceError there and chat() REJECTED. delegateTask's catch turned that into "agent failed"; the 'completed' fallback was only ever reachable on tool-free turns. - chat() still had no return at all, so a tool-free turn resolved undefined and module-orchestrator.js:1250 fell through to `|| 'completed'`. Both fixed: `const recent` is now built from _toolCallLog, and chat() returns { content: finalAnswer, toolTurns } before the archive block (a return at the end of the method would let _archiveSession swallow the answer). Verified with /tmp/probe-chat-hotfix.js, 6/6: tool-using turn resolves {content:'WORKER ANSWER', toolTurns:2}, tool-free turn resolves the answer, the orchestrator's own projection returns the answer instead of 'completed', and _chatLock is released. Run against 32608bc the same probe says "recent is not defined" - i.e. it reproduces the shipped defect. Not included: the _chatLock serialisation (orchestrate-parallel still runs sub-tasks one at a time and the 10s force-release can clear the main turn's lock). That stays open in STEER-20261102-201045-ab08.
Diffstat (limited to 'modules/core/core-bundle.js')
-rw-r--r--modules/core/core-bundle.js9
1 files changed, 8 insertions, 1 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js
index 56f0c97..ef2d425 100644
--- a/modules/core/core-bundle.js
+++ b/modules/core/core-bundle.js
@@ -9891,13 +9891,20 @@ max_chars: { type: 'integer', description: 'Max characters of page content to re
// Log the AI interaction
this.terminal.log('INFO', 'AI', 'Query: ' + userMessage.substring(0, 100));
if (loopResult && loopResult.toolTurns) {
- const toolNames = this._toolCallLog.slice(-(loopResult.toolTurns || 0)).map(function(e) { return e.name; }).join(', ');
+ // `recent` was referenced but never declared: the bare identifier threw
+ // ReferenceError inside this finally block, rejecting chat() on every
+ // tool-using turn (shipped in 32608bc, caught by the caller sweep).
+ const recent = this._toolCallLog.slice(-(loopResult.toolTurns || 0));
+ const toolNames = recent.map(function(e) { return e.name; }).join(', ');
this.terminal.log('INFO', 'AI', 'Used ' + loopResult.toolTurns + ' tool(s): ' + toolNames
+ ' · returned ' + Math.round(recent.reduce((a, e) => a + e.returnedBytes, 0) / 1024) + 'KB'
+ ' · clipped ' + Math.round(recent.reduce((a, e) => a + e.clippedBytes, 0) / 1024) + 'KB'
+ ' · ' + recent.filter(e => e.truncated).length + ' truncated');
}
}
+ // Callers (orchestrator delegateTask) need the answer itself, not just the
+ // side effects it left in the session context.
+ return { content: loopResult && loopResult.finalAnswer, toolTurns: (loopResult && loopResult.toolTurns) || 0 };
// Auto-archive every 10 messages
if (this._messageCount > 0 && this._messageCount % 10 === 0) {
this._archiveSession('Auto-archive at message ' + this._messageCount);