Vendored
+17
-15
@@ -523,6 +523,7 @@ async function runTurn(ctx) {
|
||||
let lastText = '';
|
||||
let goalNudges = 0;
|
||||
let toolNudges = 0;
|
||||
let browserRetries = 0;
|
||||
|
||||
async function runOneTool(item, turn) {
|
||||
const name = item.name;
|
||||
@@ -647,6 +648,7 @@ async function runTurn(ctx) {
|
||||
} catch (err) {
|
||||
out = { error: err.message };
|
||||
}
|
||||
if (cancelled()) return { reason: 'cancelled', turns: turn + 1 };
|
||||
const rendered = truncate.renderToolResult(out, resultCap(budget, name));
|
||||
const toolMsg = { role: 'tool', name, content: rendered, tool_call_id: toolCallId };
|
||||
pushHistory(session, toolMsg);
|
||||
@@ -673,7 +675,12 @@ async function runTurn(ctx) {
|
||||
const ctxSize = loadedCtxSize();
|
||||
// Generate one-shot reminders once; usage estimation must not consume
|
||||
// them before inference. Reserve their space during compaction as well.
|
||||
// Route from actual conversation history, before internal user-role reminders.
|
||||
const browserTurn = webProcess.needsGroqWebProcess(session.history);
|
||||
const turnSidecars = sidecarMessages(session, tracker, budget);
|
||||
if (browserTurn && browserRetries) turnSidecars.push({
|
||||
role: 'user', content: 'The previous completion produced no answer. Use the browser page_text already in the tool results to continue the original request. Call the next tool if needed, or give the user a substantive answer.',
|
||||
});
|
||||
const sidecarTokens = compaction.conversationTokens(turnSidecars) + 256;
|
||||
const beforeUsage = compaction.usage(session.history, toolDefs, ctxSize);
|
||||
emitLive(emit, session.id, jobId, Object.assign({ type: 'context' }, beforeUsage));
|
||||
@@ -736,7 +743,7 @@ async function runTurn(ctx) {
|
||||
let result;
|
||||
for (let overflowTry = 0; overflowTry < 4; overflowTry++) {
|
||||
const history = session.history.concat(turnSidecars);
|
||||
const webTurn = groqWebTurn(history);
|
||||
const webTurn = browserTurn && typeof engine.remoteActive === 'function' && engine.remoteActive();
|
||||
const turnTools = webTurn ? webProcess.browserToolsOnly(toolDefs) : toolDefs;
|
||||
streamBase = compaction.usage(history, turnTools, ctxSize);
|
||||
streamChars = 0;
|
||||
@@ -748,8 +755,8 @@ async function runTurn(ctx) {
|
||||
webProcess: webTurn,
|
||||
toolDialect: webTurn ? 'openai' : catalog.toolDialectFor(session.model),
|
||||
desktopVision: payload && payload.desktopVision === false ? false : undefined,
|
||||
timeoutMs: (webTurn || webProcess.needsGroqWebProcess(history)) ? (budget.completeTimeoutMs || 90000) : budget.completeTimeoutMs,
|
||||
idleMs: (webTurn || webProcess.needsGroqWebProcess(history)) ? (budget.completeIdleMs || 45000) : budget.completeIdleMs,
|
||||
timeoutMs: browserTurn ? Math.max(budget.completeTimeoutMs || 0, 90000) : budget.completeTimeoutMs,
|
||||
idleMs: browserTurn ? Math.max(budget.completeIdleMs || 0, 45000) : budget.completeIdleMs,
|
||||
},
|
||||
(ev) => {
|
||||
if (ev.type === 'contentDelta') {
|
||||
@@ -805,6 +812,7 @@ async function runTurn(ctx) {
|
||||
Object.assign({ type: 'context' }, usageFromStats(result && result.stats, liveUsed(), ctxSize))
|
||||
);
|
||||
|
||||
if (cancelled()) return endTurn(emit, session, jobId, tracker, { reason: 'cancelled', turns: turn + 1 });
|
||||
let calls = ((result && result.toolCalls) || []).map(normalizeCall);
|
||||
if (!calls.length && result) {
|
||||
const recovered = toolParse.recover({
|
||||
@@ -819,15 +827,17 @@ async function runTurn(ctx) {
|
||||
result.text = toolParse.stripToolMarkup(result.text);
|
||||
}
|
||||
if (budget.answerOnly) calls = [];
|
||||
if ((result && result.text) || calls.length) {
|
||||
if ((result && String(result.text || '').trim()) || calls.length) {
|
||||
if (result.text) lastText = result.text;
|
||||
const assistant = { role: 'assistant', content: result.text || '' };
|
||||
if (calls.length) assistant.tool_calls = calls;
|
||||
pushHistory(session, assistant);
|
||||
}
|
||||
if (!calls.length && result && !String(result.text || '').trim()) {
|
||||
const report = webProcess.pageReport(webProcess.latestBrowserReading(session.history));
|
||||
if (report) result.text = report;
|
||||
if (!calls.length && !String(result && result.text || '').trim()) {
|
||||
if (browserTurn) {
|
||||
if (browserRetries++ < 1 && turn + 1 < budget.maxTurns) continue;
|
||||
throw new Error('Browser page contents were received, but the model could not finish processing them. Please try again.');
|
||||
}
|
||||
}
|
||||
if (!calls.length) {
|
||||
const goalActive = goalMod.isActive(session.goal);
|
||||
@@ -965,14 +975,6 @@ async function runTurn(ctx) {
|
||||
if (err && err.message === 'cancelled') {
|
||||
return endTurn(emit, session, jobId, tracker, { reason: 'cancelled', text: lastText });
|
||||
}
|
||||
const report = webProcess.pageReport(webProcess.latestBrowserReading(session.history));
|
||||
if (report) {
|
||||
return endTurn(emit, session, jobId, tracker, {
|
||||
reason: 'stop',
|
||||
text: report,
|
||||
turns: lastText ? undefined : 1,
|
||||
});
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user