@yugenlab/vaayu 0.1.3 → 0.1.4
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/chunks/agentic-tool-loop-2FZK72JO.js +147 -0
- package/gateway.js +190 -18
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import "./chunk-IGKYKEKT.js";
|
|
2
|
+
|
|
3
|
+
// apps/gateway/dist/agent/agentic-tool-loop.js
|
|
4
|
+
async function runAgenticToolLoop(params) {
|
|
5
|
+
const { initialContent, initialModel, contextMessages, tools, getToolRegistration, isToolAllowed, reChat, maxIterations, signal, logger, sessionId } = params;
|
|
6
|
+
let currentToolCalls = params.toolCalls;
|
|
7
|
+
let allToolResults = [];
|
|
8
|
+
const accumulatedMessages = [...contextMessages];
|
|
9
|
+
let finalContent = initialContent;
|
|
10
|
+
let finalModel = initialModel;
|
|
11
|
+
let iteration = 0;
|
|
12
|
+
while (currentToolCalls.length > 0 && iteration < maxIterations) {
|
|
13
|
+
iteration++;
|
|
14
|
+
if (signal?.aborted) {
|
|
15
|
+
logger.info("agentic_loop_aborted", { sessionId, iteration });
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
accumulatedMessages.push({
|
|
19
|
+
role: "assistant",
|
|
20
|
+
content: finalContent,
|
|
21
|
+
toolCalls: currentToolCalls
|
|
22
|
+
});
|
|
23
|
+
const iterationResults = [];
|
|
24
|
+
for (const call of currentToolCalls) {
|
|
25
|
+
const callId = call.id ?? `call_${call.name}_${iteration}`;
|
|
26
|
+
if (!isToolAllowed(call.name)) {
|
|
27
|
+
const errorMsg = `Tool "${call.name}" is not allowed by current policy.`;
|
|
28
|
+
logger.warn("agentic_tool_blocked", { sessionId, tool: call.name, iteration });
|
|
29
|
+
iterationResults.push({
|
|
30
|
+
name: call.name,
|
|
31
|
+
input: call.input,
|
|
32
|
+
output: { error: errorMsg },
|
|
33
|
+
ok: false,
|
|
34
|
+
callId
|
|
35
|
+
});
|
|
36
|
+
accumulatedMessages.push({
|
|
37
|
+
role: "tool",
|
|
38
|
+
content: JSON.stringify({ error: errorMsg }),
|
|
39
|
+
name: call.name,
|
|
40
|
+
toolCallId: callId
|
|
41
|
+
});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const registration = getToolRegistration(call.name);
|
|
45
|
+
if (!registration) {
|
|
46
|
+
const errorMsg = `Tool "${call.name}" not found in registry.`;
|
|
47
|
+
logger.warn("agentic_tool_not_found", { sessionId, tool: call.name, iteration });
|
|
48
|
+
iterationResults.push({
|
|
49
|
+
name: call.name,
|
|
50
|
+
input: call.input,
|
|
51
|
+
output: { error: errorMsg },
|
|
52
|
+
ok: false,
|
|
53
|
+
callId
|
|
54
|
+
});
|
|
55
|
+
accumulatedMessages.push({
|
|
56
|
+
role: "tool",
|
|
57
|
+
content: JSON.stringify({ error: errorMsg }),
|
|
58
|
+
name: call.name,
|
|
59
|
+
toolCallId: callId
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const ctx = {
|
|
65
|
+
sessionId,
|
|
66
|
+
signal
|
|
67
|
+
};
|
|
68
|
+
const result = await registration.handler(call.input, ctx);
|
|
69
|
+
const output = result.ok ? result.output : result.error;
|
|
70
|
+
iterationResults.push({
|
|
71
|
+
name: call.name,
|
|
72
|
+
input: call.input,
|
|
73
|
+
output,
|
|
74
|
+
ok: result.ok,
|
|
75
|
+
callId
|
|
76
|
+
});
|
|
77
|
+
accumulatedMessages.push({
|
|
78
|
+
role: "tool",
|
|
79
|
+
content: JSON.stringify(result.ok ? result.output : { error: result.error }),
|
|
80
|
+
name: call.name,
|
|
81
|
+
toolCallId: callId
|
|
82
|
+
});
|
|
83
|
+
logger.info("agentic_tool_executed", {
|
|
84
|
+
sessionId,
|
|
85
|
+
tool: call.name,
|
|
86
|
+
ok: result.ok,
|
|
87
|
+
iteration
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
91
|
+
logger.warn("agentic_tool_error", {
|
|
92
|
+
sessionId,
|
|
93
|
+
tool: call.name,
|
|
94
|
+
error: errorMsg,
|
|
95
|
+
iteration
|
|
96
|
+
});
|
|
97
|
+
iterationResults.push({
|
|
98
|
+
name: call.name,
|
|
99
|
+
input: call.input,
|
|
100
|
+
output: { error: errorMsg },
|
|
101
|
+
ok: false,
|
|
102
|
+
callId
|
|
103
|
+
});
|
|
104
|
+
accumulatedMessages.push({
|
|
105
|
+
role: "tool",
|
|
106
|
+
content: JSON.stringify({ error: errorMsg }),
|
|
107
|
+
name: call.name,
|
|
108
|
+
toolCallId: callId
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
allToolResults = [...allToolResults, ...iterationResults];
|
|
113
|
+
try {
|
|
114
|
+
const response = await reChat(accumulatedMessages, tools);
|
|
115
|
+
finalContent = response.content;
|
|
116
|
+
finalModel = response.model;
|
|
117
|
+
currentToolCalls = response.toolCalls ?? [];
|
|
118
|
+
} catch (error) {
|
|
119
|
+
logger.warn("agentic_rechat_failed", {
|
|
120
|
+
sessionId,
|
|
121
|
+
iteration,
|
|
122
|
+
error: error instanceof Error ? error.message : String(error)
|
|
123
|
+
});
|
|
124
|
+
if (!finalContent && allToolResults.length > 0) {
|
|
125
|
+
finalContent = allToolResults.map((r) => `${r.name}: ${r.ok ? JSON.stringify(r.output) : `Error: ${JSON.stringify(r.output)}`}`).join("\n");
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (iteration >= maxIterations && currentToolCalls.length > 0) {
|
|
131
|
+
logger.warn("agentic_loop_max_iterations", {
|
|
132
|
+
sessionId,
|
|
133
|
+
maxIterations,
|
|
134
|
+
remainingToolCalls: currentToolCalls.length
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
finalContent,
|
|
139
|
+
toolResults: allToolResults,
|
|
140
|
+
iterations: iteration,
|
|
141
|
+
finalModel
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export {
|
|
145
|
+
runAgenticToolLoop
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=agentic-tool-loop-2FZK72JO.js.map
|
package/gateway.js
CHANGED
|
@@ -14387,10 +14387,33 @@ var OpenAICompatibleProvider = class {
|
|
|
14387
14387
|
}
|
|
14388
14388
|
const payload = {
|
|
14389
14389
|
model: request.model,
|
|
14390
|
-
messages: request.messages.map((message) =>
|
|
14391
|
-
role
|
|
14392
|
-
|
|
14393
|
-
|
|
14390
|
+
messages: request.messages.map((message) => {
|
|
14391
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
14392
|
+
return {
|
|
14393
|
+
role: "assistant",
|
|
14394
|
+
content: message.content || null,
|
|
14395
|
+
tool_calls: message.toolCalls.map((call) => ({
|
|
14396
|
+
id: call.id ?? `call_${call.name}`,
|
|
14397
|
+
type: "function",
|
|
14398
|
+
function: {
|
|
14399
|
+
name: call.name,
|
|
14400
|
+
arguments: JSON.stringify(call.input)
|
|
14401
|
+
}
|
|
14402
|
+
}))
|
|
14403
|
+
};
|
|
14404
|
+
}
|
|
14405
|
+
if (message.role === "tool") {
|
|
14406
|
+
return {
|
|
14407
|
+
role: "tool",
|
|
14408
|
+
tool_call_id: message.toolCallId ?? message.name ?? "unknown",
|
|
14409
|
+
content: message.content
|
|
14410
|
+
};
|
|
14411
|
+
}
|
|
14412
|
+
return {
|
|
14413
|
+
role: message.role,
|
|
14414
|
+
content: message.content
|
|
14415
|
+
};
|
|
14416
|
+
}),
|
|
14394
14417
|
temperature: request.temperature,
|
|
14395
14418
|
top_p: request.topP,
|
|
14396
14419
|
max_tokens: request.maxTokens,
|
|
@@ -14508,10 +14531,49 @@ function splitSystem(messages) {
|
|
|
14508
14531
|
};
|
|
14509
14532
|
}
|
|
14510
14533
|
function toAnthropicMessages(messages) {
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14534
|
+
const result = [];
|
|
14535
|
+
for (let i = 0; i < messages.length; i++) {
|
|
14536
|
+
const message = messages[i];
|
|
14537
|
+
if (message.role === "system") continue;
|
|
14538
|
+
if (message.role === "tool") {
|
|
14539
|
+
const toolResults = [];
|
|
14540
|
+
let j = i;
|
|
14541
|
+
while (j < messages.length) {
|
|
14542
|
+
const tm = messages[j];
|
|
14543
|
+
if (tm.role !== "tool") break;
|
|
14544
|
+
toolResults.push({
|
|
14545
|
+
type: "tool_result",
|
|
14546
|
+
tool_use_id: tm.toolCallId ?? tm.name ?? "unknown",
|
|
14547
|
+
content: tm.content
|
|
14548
|
+
});
|
|
14549
|
+
j++;
|
|
14550
|
+
}
|
|
14551
|
+
result.push({ role: "user", content: toolResults });
|
|
14552
|
+
i = j - 1;
|
|
14553
|
+
continue;
|
|
14554
|
+
}
|
|
14555
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
14556
|
+
const content = [];
|
|
14557
|
+
if (message.content) {
|
|
14558
|
+
content.push({ type: "text", text: message.content });
|
|
14559
|
+
}
|
|
14560
|
+
for (const call of message.toolCalls) {
|
|
14561
|
+
content.push({
|
|
14562
|
+
type: "tool_use",
|
|
14563
|
+
id: call.id ?? `call_${call.name}`,
|
|
14564
|
+
name: call.name,
|
|
14565
|
+
input: call.input
|
|
14566
|
+
});
|
|
14567
|
+
}
|
|
14568
|
+
result.push({ role: "assistant", content });
|
|
14569
|
+
continue;
|
|
14570
|
+
}
|
|
14571
|
+
result.push({
|
|
14572
|
+
role: message.role === "assistant" ? "assistant" : "user",
|
|
14573
|
+
content: [{ type: "text", text: message.content }]
|
|
14574
|
+
});
|
|
14575
|
+
}
|
|
14576
|
+
return result;
|
|
14515
14577
|
}
|
|
14516
14578
|
function buildUrl2(config) {
|
|
14517
14579
|
if (config.path) {
|
|
@@ -29723,7 +29785,7 @@ function buildForcedIntentPlan(params) {
|
|
|
29723
29785
|
return null;
|
|
29724
29786
|
}
|
|
29725
29787
|
async function handleToolPlanning(params) {
|
|
29726
|
-
const { session, message, runId, signal, profile, locale, contextMessages, combinedSystem, resolvedProviderId, resolvedModel, budgetFallbackTarget, routingDecision, routingResult, isPureGreeting: isPureGreeting2, isPureAck: isPureAck2, maybeAppendSmritiMemory, config, logger, storage, toolRegistry, toolPolicy, isToolAllowed: isToolAllowed2, interpretRules: interpretRules2, interpretNlu, planToolInvocation: planToolInvocation2, looksLikeWeatherAsk: looksLikeWeatherAsk2, cleanLocationInput: cleanLocationInput2, isTemporalLocation: isTemporalLocation2, getToolApprovalRequirement: getToolApprovalRequirement2, createToolApprovalRequest, skillSynthEngine, skillSynthEnabled, getProvider, chitraguptaBridge } = params;
|
|
29788
|
+
const { session, message, runId, signal, plannerMode = "default", profile, locale, contextMessages, combinedSystem, resolvedProviderId, resolvedModel, budgetFallbackTarget, routingDecision, routingResult, isPureGreeting: isPureGreeting2, isPureAck: isPureAck2, maybeAppendSmritiMemory, config, logger, storage, toolRegistry, toolPolicy, isToolAllowed: isToolAllowed2, interpretRules: interpretRules2, interpretNlu, planToolInvocation: planToolInvocation2, looksLikeWeatherAsk: looksLikeWeatherAsk2, cleanLocationInput: cleanLocationInput2, isTemporalLocation: isTemporalLocation2, getToolApprovalRequirement: getToolApprovalRequirement2, createToolApprovalRequest, skillSynthEngine, skillSynthEnabled, getProvider, chitraguptaBridge } = params;
|
|
29727
29789
|
if (!message.text)
|
|
29728
29790
|
return null;
|
|
29729
29791
|
const normalized = normalizeIncomingText(message.text);
|
|
@@ -29937,6 +29999,10 @@ async function handleToolPlanning(params) {
|
|
|
29937
29999
|
let plannerProvider = null;
|
|
29938
30000
|
let plannerResult = null;
|
|
29939
30001
|
if (!plan) {
|
|
30002
|
+
if (plannerMode === "deterministic_only") {
|
|
30003
|
+
await maybeRecordActiveToolDiscovery();
|
|
30004
|
+
return null;
|
|
30005
|
+
}
|
|
29940
30006
|
const plannerRole = config.routing.roles?.planner;
|
|
29941
30007
|
plannerProviderId = plannerRole?.providerId ?? resolvedProviderId;
|
|
29942
30008
|
plannerModel = plannerRole?.model ?? resolvedModel;
|
|
@@ -30982,6 +31048,8 @@ async function runChatWithFallback(params) {
|
|
|
30982
31048
|
messages: prunedMessages ?? baseMessages,
|
|
30983
31049
|
maxTokens: config.routing.budgets?.maxTokensPerRequest,
|
|
30984
31050
|
metadata: requestMeta,
|
|
31051
|
+
tools: params.tools,
|
|
31052
|
+
toolChoice: params.toolChoice,
|
|
30985
31053
|
signal: attemptSignal
|
|
30986
31054
|
});
|
|
30987
31055
|
response = await chatWithPolicy({
|
|
@@ -31057,7 +31125,8 @@ async function runChatWithFallback(params) {
|
|
|
31057
31125
|
reason: "no_healthy_provider",
|
|
31058
31126
|
retryable: true,
|
|
31059
31127
|
responseModel: "provider.failure"
|
|
31060
|
-
}
|
|
31128
|
+
},
|
|
31129
|
+
friendlyMessage: "I'm switching routes right now and can still handle quick tasks like weather, reminders, and notes. Please retry this request in a moment."
|
|
31061
31130
|
};
|
|
31062
31131
|
}
|
|
31063
31132
|
return {
|
|
@@ -31068,7 +31137,8 @@ async function runChatWithFallback(params) {
|
|
|
31068
31137
|
reason: "attempts_exhausted",
|
|
31069
31138
|
retryable: true,
|
|
31070
31139
|
responseModel: "provider.failure"
|
|
31071
|
-
}
|
|
31140
|
+
},
|
|
31141
|
+
friendlyMessage: "I couldn't complete that with the current model route. I'm rebalancing providers automatically - please retry this request now."
|
|
31072
31142
|
};
|
|
31073
31143
|
}
|
|
31074
31144
|
return {
|
|
@@ -33238,7 +33308,8 @@ async function executeAgentRun(params) {
|
|
|
33238
33308
|
taskType: margaDecision.taskType,
|
|
33239
33309
|
complexity: margaDecision.complexity
|
|
33240
33310
|
});
|
|
33241
|
-
const
|
|
33311
|
+
const skipKind = margaDecision.taskType === "heartbeat" ? "ack" : "greeting";
|
|
33312
|
+
const skipContent = deps.buildSmalltalkReply(runtime.profile, skipKind, payload.message.channel, locale);
|
|
33242
33313
|
const skipModel = `marga:${margaDecision.taskType}`;
|
|
33243
33314
|
await appendAssistantEvent(storage, session.id, skipContent, {
|
|
33244
33315
|
providerId: "marga",
|
|
@@ -33302,6 +33373,11 @@ async function executeAgentRun(params) {
|
|
|
33302
33373
|
routingResult.fallbackUsed = false;
|
|
33303
33374
|
return buildEarlyResult(session, cacheModel, cached2.responseContent, routingDecision, routingResult);
|
|
33304
33375
|
}
|
|
33376
|
+
const agenticTools = runtime.toolRegistry.list().filter((t2) => deps.isToolAllowed(toolPolicy, t2.name)).filter((t2) => !t2.name.startsWith("memory.")).map((t2) => ({
|
|
33377
|
+
name: t2.name,
|
|
33378
|
+
description: t2.description,
|
|
33379
|
+
inputSchema: t2.inputSchema
|
|
33380
|
+
}));
|
|
33305
33381
|
const chatResult = await runChatWithFallback({
|
|
33306
33382
|
sessionId: session.id,
|
|
33307
33383
|
messageText: payload.message.text,
|
|
@@ -33338,10 +33414,63 @@ async function executeAgentRun(params) {
|
|
|
33338
33414
|
providerHealth: runtime.providerHealth,
|
|
33339
33415
|
lastAnthropicCallAt,
|
|
33340
33416
|
logger,
|
|
33341
|
-
signal: runSignal
|
|
33417
|
+
signal: runSignal,
|
|
33418
|
+
tools: agenticTools.length > 0 ? agenticTools : void 0
|
|
33342
33419
|
});
|
|
33343
33420
|
if (!chatResult.ok) {
|
|
33344
33421
|
const escalation = chatResult.escalation;
|
|
33422
|
+
if (escalation.reason !== "request_aborted" && actionability.kind !== "smalltalk") {
|
|
33423
|
+
const degradedToolResult = await handleToolPlanning({
|
|
33424
|
+
session,
|
|
33425
|
+
message,
|
|
33426
|
+
runId,
|
|
33427
|
+
signal: runSignal,
|
|
33428
|
+
plannerMode: "deterministic_only",
|
|
33429
|
+
profile,
|
|
33430
|
+
locale: locale ?? "en",
|
|
33431
|
+
contextMessages: context.messages,
|
|
33432
|
+
combinedSystem,
|
|
33433
|
+
resolvedProviderId,
|
|
33434
|
+
resolvedModel,
|
|
33435
|
+
budgetFallbackTarget,
|
|
33436
|
+
routingDecision,
|
|
33437
|
+
routingResult,
|
|
33438
|
+
isPureGreeting: deps.isPureGreeting,
|
|
33439
|
+
isPureAck: deps.isPureAck,
|
|
33440
|
+
maybeAppendSmritiMemory: maybeAppendSmritiMemorySafe,
|
|
33441
|
+
config,
|
|
33442
|
+
storage,
|
|
33443
|
+
logger,
|
|
33444
|
+
providerHealth: runtime.providerHealth,
|
|
33445
|
+
getProfile: () => runtime.profile,
|
|
33446
|
+
toolRegistry: runtime.toolRegistry,
|
|
33447
|
+
toolPolicy,
|
|
33448
|
+
isToolAllowed: deps.isToolAllowed,
|
|
33449
|
+
interpretRules: deps.interpretRules,
|
|
33450
|
+
interpretNlu: deps.interpretNlu,
|
|
33451
|
+
planToolInvocation: deps.planToolInvocation,
|
|
33452
|
+
looksLikeWeatherAsk: deps.looksLikeWeatherAsk,
|
|
33453
|
+
cleanLocationInput: deps.cleanLocationInput,
|
|
33454
|
+
isTemporalLocation: deps.isTemporalLocation,
|
|
33455
|
+
getToolApprovalRequirement: deps.getToolApprovalRequirement,
|
|
33456
|
+
createToolApprovalRequest: deps.createToolApprovalRequest,
|
|
33457
|
+
guardToolExecution: deps.guardToolExecution,
|
|
33458
|
+
updateWeatherDefaults: deps.updateWeatherDefaults,
|
|
33459
|
+
formatWeatherResponse: deps.formatWeatherResponse,
|
|
33460
|
+
formatWeatherForecastResponse: deps.formatWeatherForecastResponse,
|
|
33461
|
+
renderToolOutput: deps.renderToolOutput,
|
|
33462
|
+
renderToolFailure: deps.renderToolFailure,
|
|
33463
|
+
stripModelThinking: deps.stripModelThinking,
|
|
33464
|
+
getProvider,
|
|
33465
|
+
skillSynthEngine: deps.skillSynthEngine,
|
|
33466
|
+
skillSynthEnabled: deps.skillSynthEnabled,
|
|
33467
|
+
chitraguptaBridge: runtime.chitraguptaBridge
|
|
33468
|
+
});
|
|
33469
|
+
if (degradedToolResult) {
|
|
33470
|
+
routingResult.escalation = escalation;
|
|
33471
|
+
return degradedToolResult;
|
|
33472
|
+
}
|
|
33473
|
+
}
|
|
33345
33474
|
const smalltalkFallback = resolveSmalltalkProviderFallback({
|
|
33346
33475
|
actionability,
|
|
33347
33476
|
escalation,
|
|
@@ -33370,7 +33499,7 @@ async function executeAgentRun(params) {
|
|
|
33370
33499
|
routingResult.fallbackUsed = false;
|
|
33371
33500
|
return buildEarlyResult(session, smalltalkFallback.model, smalltalkFallback.content, routingDecision, routingResult);
|
|
33372
33501
|
}
|
|
33373
|
-
const content =
|
|
33502
|
+
const content = chatResult.friendlyMessage ? chatResult.friendlyMessage : formatProviderError2(chatResult.error ?? new Error("Provider failed"));
|
|
33374
33503
|
const errorModel = escalation.responseModel;
|
|
33375
33504
|
routingResult.escalation = escalation;
|
|
33376
33505
|
await appendAssistantEvent(storage, session.id, content, {
|
|
@@ -33392,6 +33521,43 @@ async function executeAgentRun(params) {
|
|
|
33392
33521
|
return buildEarlyResult(session, errorModel, content, routingDecision, routingResult);
|
|
33393
33522
|
}
|
|
33394
33523
|
const { response, provider, model, fallbackUsed } = chatResult;
|
|
33524
|
+
let finalResponse = response;
|
|
33525
|
+
if (response.toolCalls?.length && agenticTools.length > 0) {
|
|
33526
|
+
const { runAgenticToolLoop } = await import("./chunks/agentic-tool-loop-2FZK72JO.js");
|
|
33527
|
+
const agenticResult = await runAgenticToolLoop({
|
|
33528
|
+
toolCalls: response.toolCalls,
|
|
33529
|
+
initialContent: response.content,
|
|
33530
|
+
initialModel: model,
|
|
33531
|
+
contextMessages: [...context.messages, { role: "user", content: payload.message.text }],
|
|
33532
|
+
tools: agenticTools,
|
|
33533
|
+
getToolRegistration: (name) => runtime.toolRegistry.get(name),
|
|
33534
|
+
isToolAllowed: (name) => deps.isToolAllowed(toolPolicy, name),
|
|
33535
|
+
reChat: async (msgs, tools) => {
|
|
33536
|
+
return provider.chat({
|
|
33537
|
+
model,
|
|
33538
|
+
messages: msgs,
|
|
33539
|
+
tools,
|
|
33540
|
+
maxTokens: config.routing.budgets?.maxTokensPerRequest,
|
|
33541
|
+
signal: runSignal
|
|
33542
|
+
});
|
|
33543
|
+
},
|
|
33544
|
+
maxIterations: config.routing.agenticMaxIterations ?? 5,
|
|
33545
|
+
signal: runSignal,
|
|
33546
|
+
logger,
|
|
33547
|
+
sessionId: session.id
|
|
33548
|
+
});
|
|
33549
|
+
finalResponse = {
|
|
33550
|
+
...response,
|
|
33551
|
+
content: agenticResult.finalContent,
|
|
33552
|
+
model: agenticResult.finalModel,
|
|
33553
|
+
toolCalls: void 0
|
|
33554
|
+
};
|
|
33555
|
+
logger.info("agentic_loop_complete", {
|
|
33556
|
+
sessionId: session.id,
|
|
33557
|
+
iterations: agenticResult.iterations,
|
|
33558
|
+
toolsExecuted: agenticResult.toolResults.length
|
|
33559
|
+
});
|
|
33560
|
+
}
|
|
33395
33561
|
if (runSignal.aborted) {
|
|
33396
33562
|
throw new Error("Request aborted");
|
|
33397
33563
|
}
|
|
@@ -33399,7 +33565,7 @@ async function executeAgentRun(params) {
|
|
|
33399
33565
|
sessionId: session.id,
|
|
33400
33566
|
category: semanticCacheCategory,
|
|
33401
33567
|
query: routingText,
|
|
33402
|
-
responseContent:
|
|
33568
|
+
responseContent: finalResponse.content,
|
|
33403
33569
|
selected: { providerId: provider.id, model },
|
|
33404
33570
|
ttlMs: semanticCacheRule.ttlMs
|
|
33405
33571
|
});
|
|
@@ -33424,7 +33590,7 @@ async function executeAgentRun(params) {
|
|
|
33424
33590
|
config,
|
|
33425
33591
|
provider,
|
|
33426
33592
|
model,
|
|
33427
|
-
response,
|
|
33593
|
+
response: finalResponse,
|
|
33428
33594
|
fallbackUsed,
|
|
33429
33595
|
routingDecision,
|
|
33430
33596
|
routingResult,
|
|
@@ -38453,6 +38619,7 @@ var routingSchema = external_exports.object({
|
|
|
38453
38619
|
chatTimeoutMs: external_exports.number().int().min(1e3).max(12e4).default(15e3),
|
|
38454
38620
|
maxAttempts: external_exports.number().int().min(1).max(10).default(2),
|
|
38455
38621
|
plannerMaxAttempts: external_exports.number().int().min(1).max(10).default(1),
|
|
38622
|
+
agenticMaxIterations: external_exports.number().int().min(1).max(20).default(5),
|
|
38456
38623
|
strategy: external_exports.enum(["first", "hash"]).default("hash"),
|
|
38457
38624
|
minChars: external_exports.number().int().min(10).max(5e3).default(280),
|
|
38458
38625
|
minWords: external_exports.number().int().min(5).max(500).default(60),
|
|
@@ -41004,6 +41171,9 @@ function formatProviderError(error) {
|
|
|
41004
41171
|
return "I hit an error while handling that.";
|
|
41005
41172
|
const raw = error instanceof Error ? error.message : String(error);
|
|
41006
41173
|
const sanitized = sanitizeProviderError(raw);
|
|
41174
|
+
if (/^(i['’]m|please try)/i.test(sanitized)) {
|
|
41175
|
+
return sanitized;
|
|
41176
|
+
}
|
|
41007
41177
|
return `I hit an error while handling that: ${sanitized}`;
|
|
41008
41178
|
}
|
|
41009
41179
|
function stripAnsi(input) {
|
|
@@ -41047,10 +41217,12 @@ function sanitizeProviderError(message) {
|
|
|
41047
41217
|
if (/\b(timeout|timed out|etimedout|econnrefused|econnreset|fetch failed|network)\b/i.test(cleaned)) {
|
|
41048
41218
|
return `${providerLabel} is temporarily unreachable.`;
|
|
41049
41219
|
}
|
|
41220
|
+
if (/\b(no healthy provider|all providers on cooldown|all candidates on cooldown)\b/i.test(cleaned) || /\bprovider\s+[a-z0-9._-]+\s+unavailable\b/i.test(cleaned)) {
|
|
41221
|
+
return "I'm switching routes automatically right now. Please retry your request in a moment.";
|
|
41222
|
+
}
|
|
41050
41223
|
const cooling = cleaned.match(/\bcooling down\s*\(([^)]+)\)/i);
|
|
41051
41224
|
if (cooling) {
|
|
41052
|
-
|
|
41053
|
-
return `${providerLabel} is cooling down (${reason}). You can run /provider reset all or wait briefly.`;
|
|
41225
|
+
return "I'm switching routes automatically right now. Please retry your request in a moment.";
|
|
41054
41226
|
}
|
|
41055
41227
|
if (providerId) {
|
|
41056
41228
|
return `${providerLabel} failed.`;
|