@ouro.bot/cli 0.1.0-alpha.810 → 0.1.0-alpha.811
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/changelog.json +12 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +1 -1
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +8 -7
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +1 -1
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +1 -1
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +2 -2
- package/deploy/unraid/sanctuary.xml +1 -1
- package/dist/heart/config.js +32 -2
- package/dist/heart/core.js +167 -115
- package/dist/heart/daemon/daemon.js +19 -9
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +88 -50
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +53 -15
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +6 -26
- package/dist/heart/frontend-approval-runtime.js +87 -13
- package/dist/heart/identity.js +17 -5
- package/dist/heart/session-events.js +8 -1
- package/dist/heart/tool-approval.js +64 -31
- package/dist/mind/pending.js +4 -4
- package/dist/repertoire/mcp-manager.js +365 -381
- package/dist/repertoire/mcp-tools.js +66 -25
- package/dist/repertoire/plugin-mcp.js +3 -3
- package/dist/repertoire/shell-sessions.js +8 -7
- package/dist/repertoire/tool-arguments.js +30 -8
- package/dist/repertoire/tools-session.js +30 -5
- package/dist/repertoire/tools-shell.js +30 -14
- package/dist/repertoire/tools-voice.js +6 -6
- package/dist/repertoire/tools.js +231 -205
- package/dist/senses/bluebubbles/index.js +4 -2
- package/dist/senses/cli.js +6 -5
- package/dist/senses/private-runtime.js +9 -3
- package/dist/senses/shared-turn.js +12 -9
- package/dist/senses/teams.js +15 -12
- package/dist/senses/telegram-approval-runtime.js +129 -20
- package/dist/senses/telegram-client.js +19 -2
- package/dist/senses/telegram.js +54 -15
- package/dist/senses/voice/twilio-phone.js +123 -173
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/heart/core.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MAX_PROVIDER_ITERATIONS = void 0;
|
|
4
4
|
exports.validateToolCallBatchAtProductionBoundary = validateToolCallBatchAtProductionBoundary;
|
|
5
5
|
exports.createProviderRegistry = createProviderRegistry;
|
|
6
|
+
exports.getProviderRuntime = getProviderRuntime;
|
|
6
7
|
exports.resetProviderRuntime = resetProviderRuntime;
|
|
7
8
|
exports.getModel = getModel;
|
|
8
9
|
exports.getProvider = getProvider;
|
|
@@ -22,8 +23,8 @@ const identity_1 = require("./identity");
|
|
|
22
23
|
const tools_1 = require("../repertoire/tools");
|
|
23
24
|
const tool_arguments_1 = require("../repertoire/tool-arguments");
|
|
24
25
|
const session_events_1 = require("./session-events");
|
|
26
|
+
const tool_approval_1 = require("./tool-approval");
|
|
25
27
|
const friends_1 = require("@ouro.bot/friends");
|
|
26
|
-
const tools_2 = require("../repertoire/tools");
|
|
27
28
|
const streaming_1 = require("./streaming");
|
|
28
29
|
const runtime_1 = require("../nerves/runtime");
|
|
29
30
|
function validateToolCallBatchAtProductionBoundary(calls, activeTools) {
|
|
@@ -73,15 +74,15 @@ const _providerRuntimeFactories = {
|
|
|
73
74
|
function providerLaneForFacing(facing) {
|
|
74
75
|
return facing === "human" ? "outward" : "inner";
|
|
75
76
|
}
|
|
76
|
-
function resolveRuntimeProviderBinding(facing) {
|
|
77
|
+
function resolveRuntimeProviderBinding(facing, owner) {
|
|
77
78
|
const lane = providerLaneForFacing(facing);
|
|
78
|
-
const config = (0, identity_1.loadAgentConfig)();
|
|
79
|
+
const config = (0, identity_1.loadAgentConfig)(owner);
|
|
79
80
|
const facingConfig = facing === "human" ? config.humanFacing : config.agentFacing;
|
|
80
81
|
return { lane, provider: facingConfig.provider, model: facingConfig.model };
|
|
81
82
|
}
|
|
82
|
-
async function getProviderRuntimeFingerprint(facing) {
|
|
83
|
-
const agentName = (0, identity_2.getAgentName)();
|
|
84
|
-
const binding = resolveRuntimeProviderBinding(facing);
|
|
83
|
+
async function getProviderRuntimeFingerprint(facing, owner) {
|
|
84
|
+
const agentName = owner?.agentName ?? (0, identity_2.getAgentName)();
|
|
85
|
+
const binding = resolveRuntimeProviderBinding(facing, owner);
|
|
85
86
|
const credential = await (0, provider_credentials_1.readProviderCredentialRecord)(agentName, binding.provider);
|
|
86
87
|
if (!credential.ok) {
|
|
87
88
|
throw new Error([
|
|
@@ -103,6 +104,7 @@ async function getProviderRuntimeFingerprint(facing) {
|
|
|
103
104
|
return {
|
|
104
105
|
binding,
|
|
105
106
|
fingerprint: JSON.stringify({
|
|
107
|
+
...(owner ? { agentName: owner.agentName, agentRoot: owner.agentRoot } : {}),
|
|
106
108
|
lane: binding.lane,
|
|
107
109
|
provider: binding.provider,
|
|
108
110
|
model: binding.model,
|
|
@@ -133,10 +135,11 @@ function createProviderRegistry() {
|
|
|
133
135
|
},
|
|
134
136
|
};
|
|
135
137
|
}
|
|
136
|
-
async function getProviderRuntime(facing = "human") {
|
|
138
|
+
async function getProviderRuntime(facing = "human", owner) {
|
|
139
|
+
const scope = owner ? { agentName: owner.agentName, agentRoot: owner.agentRoot } : undefined;
|
|
137
140
|
let runtime = null;
|
|
138
141
|
try {
|
|
139
|
-
const { binding, fingerprint, credential } = await getProviderRuntimeFingerprint(facing);
|
|
142
|
+
const { binding, fingerprint, credential } = await getProviderRuntimeFingerprint(facing, scope);
|
|
140
143
|
const cached = _providerRuntimeFactories[facing];
|
|
141
144
|
if (!cached || cached.fingerprint !== fingerprint) {
|
|
142
145
|
const create = () => createProviderRegistry().resolve(binding.provider, binding.model, credential);
|
|
@@ -323,15 +326,25 @@ async function resumeApprovalContinuation(options) {
|
|
|
323
326
|
await options.persist(materialized.messages);
|
|
324
327
|
await options.markContinuationMaterialized();
|
|
325
328
|
}
|
|
326
|
-
|
|
327
|
-
|
|
329
|
+
const currentOptions = options.revalidate ? await options.revalidate()
|
|
330
|
+
: options.runAgentOptions?.toolContext?.relationshipAuthorization ? null : options.runAgentOptions;
|
|
331
|
+
if (!materialized.resumeProvider || currentOptions === null) {
|
|
332
|
+
if (currentOptions === null)
|
|
333
|
+
(0, runtime_1.emitNervesEvent)({
|
|
334
|
+
level: "warn", component: "engine", event: "engine.approval_continuation_authority_block",
|
|
335
|
+
message: "approval continuation has no current relationship authority",
|
|
336
|
+
meta: { approvalId: options.record.approvalId, state: options.record.state },
|
|
337
|
+
});
|
|
338
|
+
const effect = options.record.state === "succeeded" ? "the approved action completed"
|
|
339
|
+
: options.record.state === "failed" ? "the approved action failed" : "the protected action was not executed";
|
|
340
|
+
await options.deliver(materialized.directNotice ?? `${effect}; current relationship access is unavailable, so no model continuation was run`);
|
|
328
341
|
await options.completeContinuation();
|
|
329
342
|
return { outcome: "terminal_notice", messages: materialized.messages };
|
|
330
343
|
}
|
|
331
344
|
const outward = { value: "" };
|
|
332
345
|
const callbacks = continuationCallbacks(options.callbacks, outward);
|
|
333
346
|
await options.markContinuationAttempted();
|
|
334
|
-
const result = await options.runAgent(materialized.messages, callbacks, options.channel, options.signal,
|
|
347
|
+
const result = await options.runAgent(materialized.messages, callbacks, options.channel, options.signal, currentOptions);
|
|
335
348
|
if (result.outcome === "suspended") {
|
|
336
349
|
await options.completeContinuation();
|
|
337
350
|
return { outcome: result.outcome, messages: materialized.messages, suspension: result.suspension };
|
|
@@ -406,7 +419,7 @@ function recordBlockedHabitSurfaceAttempts(habitSession, toolCalls, reason) {
|
|
|
406
419
|
});
|
|
407
420
|
}
|
|
408
421
|
}
|
|
409
|
-
async function habitToolBatchBlockReason(habitSession, toolCalls, delegatedOrigins) {
|
|
422
|
+
async function habitToolBatchBlockReason(habitSession, toolCalls, delegatedOrigins, selection) {
|
|
410
423
|
if (!habitSession)
|
|
411
424
|
return null;
|
|
412
425
|
const granted = new Set(habitSession.toolPolicy.grantedTools);
|
|
@@ -420,7 +433,7 @@ async function habitToolBatchBlockReason(habitSession, toolCalls, delegatedOrigi
|
|
|
420
433
|
return `habit tool '${call.name}' was not granted to this habit session`;
|
|
421
434
|
// The canonical pre-batch schema gate guarantees object arguments here.
|
|
422
435
|
const args = JSON.parse(call.arguments);
|
|
423
|
-
const riskProfile = (0, tools_1.riskProfileForToolName)(call.name, args);
|
|
436
|
+
const riskProfile = (0, tools_1.riskProfileForToolName)(call.name, args, selection);
|
|
424
437
|
if (!riskProfile)
|
|
425
438
|
return `habit tool '${call.name}' does not have a known executable risk profile`;
|
|
426
439
|
const externalMutation = highRiskExternalMutation(riskProfile);
|
|
@@ -569,7 +582,7 @@ function requiredToolResultSucceeded(name, content, args, validate) {
|
|
|
569
582
|
return false;
|
|
570
583
|
return validate?.(name, content, args) ?? true;
|
|
571
584
|
}
|
|
572
|
-
function effectFingerprint(name, rawArguments) {
|
|
585
|
+
function effectFingerprint(name, rawArguments, selection) {
|
|
573
586
|
let args;
|
|
574
587
|
try {
|
|
575
588
|
const parsed = JSON.parse(rawArguments);
|
|
@@ -580,13 +593,13 @@ function effectFingerprint(name, rawArguments) {
|
|
|
580
593
|
catch {
|
|
581
594
|
return null;
|
|
582
595
|
}
|
|
583
|
-
const profile = (0, tools_1.riskProfileForToolName)(name, args);
|
|
596
|
+
const profile = (0, tools_1.riskProfileForToolName)(name, args, selection);
|
|
584
597
|
if (!profile || profile.mutates === "none")
|
|
585
598
|
return null;
|
|
586
599
|
delete args.expectedVersion;
|
|
587
600
|
return (0, tool_arguments_1.digestJson)({ name, args });
|
|
588
601
|
}
|
|
589
|
-
function historicalFailedEffectsForExactRepeatedRequest(messages) {
|
|
602
|
+
function historicalFailedEffectsForExactRepeatedRequest(messages, selection) {
|
|
590
603
|
const userRequests = [];
|
|
591
604
|
for (let index = 0; index < messages.length; index += 1) {
|
|
592
605
|
const message = messages[index];
|
|
@@ -611,7 +624,7 @@ function historicalFailedEffectsForExactRepeatedRequest(messages) {
|
|
|
611
624
|
for (const call of message.tool_calls) {
|
|
612
625
|
if (call.type !== "function" || !call.id || !call.function.name)
|
|
613
626
|
continue;
|
|
614
|
-
const fingerprint = effectFingerprint(call.function.name, call.function.arguments);
|
|
627
|
+
const fingerprint = effectFingerprint(call.function.name, call.function.arguments, selection);
|
|
615
628
|
if (fingerprint)
|
|
616
629
|
effectsByCallId.set(call.id, { name: call.function.name, fingerprint });
|
|
617
630
|
}
|
|
@@ -964,7 +977,10 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
964
977
|
}
|
|
965
978
|
};
|
|
966
979
|
const facing = (0, friends_1.channelToFacing)(channel);
|
|
967
|
-
|
|
980
|
+
const owner = options?.toolContext?.agentName && options.toolContext.agentRoot
|
|
981
|
+
? { agentName: options.toolContext.agentName, agentRoot: options.toolContext.agentRoot }
|
|
982
|
+
: undefined;
|
|
983
|
+
let providerRuntime = options?.providerRuntimeOverride ?? await getProviderRuntime(facing, owner);
|
|
968
984
|
const provider = providerRuntime.id;
|
|
969
985
|
const toolChoiceRequired = options?.hardDisableTools ? false : options?.toolChoiceRequired ?? true;
|
|
970
986
|
const traceId = options?.traceId;
|
|
@@ -1085,7 +1101,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1085
1101
|
await (0, kept_notes_1.injectKeptNotes)(messages, {
|
|
1086
1102
|
channel,
|
|
1087
1103
|
friend: currentContext?.friend,
|
|
1088
|
-
judge: async (input) => (0, kept_notes_1.createKeptNotesJudge)(await getProviderRuntime("agent"), signal)(input),
|
|
1104
|
+
judge: async (input) => (0, kept_notes_1.createKeptNotesJudge)(await getProviderRuntime("agent", owner), signal)(input),
|
|
1089
1105
|
signal,
|
|
1090
1106
|
traceId,
|
|
1091
1107
|
});
|
|
@@ -1121,7 +1137,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1121
1137
|
// a ponder packet created the return obligation in this turn.
|
|
1122
1138
|
let noToolCallRetries = 0;
|
|
1123
1139
|
const NO_TOOL_CALL_MAX_RETRIES = 2;
|
|
1124
|
-
let unresolvedHistoricalEffects =
|
|
1140
|
+
let unresolvedHistoricalEffects = [];
|
|
1125
1141
|
let historicalToolFailureRetries = 0;
|
|
1126
1142
|
let providerIterations = 0;
|
|
1127
1143
|
const requiredToolCallNames = [...new Set(options?.requiredToolCalls?.names ?? [])];
|
|
@@ -1189,38 +1205,62 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1189
1205
|
require("events").setMaxListeners(50, signal);
|
|
1190
1206
|
}
|
|
1191
1207
|
catch { /* unsupported */ }
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1208
|
+
try {
|
|
1209
|
+
const toolPreferences = currentContext?.friend?.toolPreferences;
|
|
1210
|
+
const filterTrustedTools = (tools, selected) => tools.filter((tool) => !selected.engine.some((engine) => engine.function.name === tool.function.name)
|
|
1211
|
+
&& (channel !== "inner" || options?.toolProfile === "sanctuary-health-private" || !["send_message", "surface"].includes(tool.function.name)
|
|
1212
|
+
|| selected.ordinary.some((definition) => definition.tool.function.name === tool.function.name)));
|
|
1213
|
+
const selectCurrentTools = () => {
|
|
1214
|
+
if (options?.hardDisableTools)
|
|
1215
|
+
return Object.freeze({ ordinary: Object.freeze([]), engine: Object.freeze([]) });
|
|
1216
|
+
const selected = (0, tools_1.selectToolsForChannel)(channel ? (0, friends_1.getChannelCapabilities)(channel) : undefined, toolPreferences, currentContext, providerRuntime.capabilities, options?.mcpManager, providerRuntime.model, { ...options?.toolContext, ...(options?.habitSession ? { habitSession: options.habitSession } : {}) });
|
|
1217
|
+
const ordinary = options?.tools !== undefined && !options.toolContext?.relationshipAuthorization
|
|
1218
|
+
? filterTrustedTools(options.tools, selected).flatMap((tool) => {
|
|
1219
|
+
const definition = (0, tools_1.resolveToolDefinition)(tool.function.name, selected) ?? (0, tools_1.resolveToolDefinition)(tool.function.name);
|
|
1220
|
+
return definition ? [{ ...definition, tool }] : [];
|
|
1221
|
+
})
|
|
1222
|
+
: selected.ordinary;
|
|
1223
|
+
const bound = bindCurrentIngressEvidenceLocator(ordinary.map((definition) => definition.tool), options?.toolContext?.currentIngressEvidence);
|
|
1224
|
+
return Object.freeze({
|
|
1225
|
+
ordinary: Object.freeze(ordinary.map((definition, index) => definition.tool === bound[index]
|
|
1226
|
+
? definition : Object.freeze({ ...definition, tool: bound[index] }))),
|
|
1227
|
+
engine: selected.engine,
|
|
1228
|
+
});
|
|
1229
|
+
};
|
|
1230
|
+
let toolSelection = selectCurrentTools();
|
|
1231
|
+
const relationship = options?.toolContext?.relationshipAuthorization;
|
|
1232
|
+
if (!options?.hardDisableTools && options?.tools !== undefined) {
|
|
1233
|
+
if (relationship) {
|
|
1234
|
+
toolSelection = (0, tools_1.reduceToolSelection)(toolSelection, options.tools);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
const unboundBaseTools = !options?.hardDisableTools && !relationship && options?.tools
|
|
1238
|
+
? filterTrustedTools(options.tools, toolSelection)
|
|
1239
|
+
: toolSelection.ordinary.map((definition) => definition.tool);
|
|
1240
|
+
const relationshipToolNames = options?.toolContext?.relationshipAuthorization?.advertisedToolNames;
|
|
1241
|
+
const relationshipScopedTools = relationshipToolNames
|
|
1242
|
+
? unboundBaseTools.filter((tool) => relationshipToolNames.includes(tool.function.name))
|
|
1243
|
+
: unboundBaseTools;
|
|
1244
|
+
const baseTools = bindCurrentIngressEvidenceLocator(relationshipScopedTools, options?.toolContext?.currentIngressEvidence);
|
|
1245
|
+
// Augment tool context with reasoning effort controls from provider
|
|
1246
|
+
const baseToolContext = options?.toolContext
|
|
1247
|
+
?? { signin: async () => undefined, ...(turnOrientationFrame ? { orientationFrame: turnOrientationFrame } : {}) };
|
|
1248
|
+
const habitSession = options?.habitSession ?? baseToolContext?.habitSession;
|
|
1249
|
+
const augmentedToolContext = {
|
|
1205
1250
|
...baseToolContext,
|
|
1206
1251
|
supportedReasoningEfforts: providerRuntime.supportedReasoningEfforts,
|
|
1207
1252
|
setReasoningEffort: (level) => { currentReasoningEffort = level; },
|
|
1208
1253
|
activeWorkFrame: options?.activeWorkFrame,
|
|
1209
1254
|
orientationFrame: turnOrientationFrame ?? baseToolContext.orientationFrame,
|
|
1210
1255
|
...(habitSession ? { habitSession } : {}),
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
: undefined;
|
|
1220
|
-
// Rebase provider-owned turn state from canonical messages at user-turn start.
|
|
1221
|
-
// This prevents stale provider caches from replaying prior-turn context.
|
|
1222
|
-
providerRuntime.resetTurnState(messages);
|
|
1223
|
-
try {
|
|
1256
|
+
toolSelection,
|
|
1257
|
+
selectCurrentTools,
|
|
1258
|
+
};
|
|
1259
|
+
const trustedToolContext = options?.toolContext || turnOrientationFrame || habitSession ? augmentedToolContext : undefined;
|
|
1260
|
+
unresolvedHistoricalEffects = historicalFailedEffectsForExactRepeatedRequest(messages, toolSelection);
|
|
1261
|
+
// Rebase provider-owned turn state from canonical messages at user-turn start.
|
|
1262
|
+
// This prevents stale provider caches from replaying prior-turn context.
|
|
1263
|
+
providerRuntime.resetTurnState(messages);
|
|
1224
1264
|
while (!done) {
|
|
1225
1265
|
// Channel-based tool filtering:
|
|
1226
1266
|
// - Private runtime: exclude send_message (delivery via surface), observe (no one to observe)
|
|
@@ -1231,23 +1271,9 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1231
1271
|
// Private runtime gets restTool instead of settleTool (rest = end turn, gated by attention queue).
|
|
1232
1272
|
// toolChoiceRequired only controls whether tool_choice: "required" is set in the API call.
|
|
1233
1273
|
const isPrivateRuntimeChannel = channel === "inner";
|
|
1234
|
-
const privateRuntimeHabitCanSendMessage = isPrivateRuntimeChannel
|
|
1235
|
-
&& habitSession?.toolPolicy.outwardMessagingAllowed === true
|
|
1236
|
-
&& habitSession.toolPolicy.grantedTools.includes("send_message");
|
|
1237
|
-
const privateRuntimeHabitCanSurface = isPrivateRuntimeChannel
|
|
1238
|
-
&& (!habitSession || (habitSession.toolPolicy.outwardMessagingAllowed === true
|
|
1239
|
-
&& habitSession.toolPolicy.grantedTools.includes("surface")));
|
|
1240
|
-
const filteredBaseTools = isPrivateRuntimeChannel
|
|
1241
|
-
? baseTools.filter((t) => privateRuntimeHabitCanSendMessage || t.function.name !== "send_message")
|
|
1242
|
-
: baseTools;
|
|
1243
1274
|
const unscopedOrdinaryActiveTools = [
|
|
1244
|
-
...
|
|
1245
|
-
...
|
|
1246
|
-
...(isPrivateRuntimeChannel && privateRuntimeHabitCanSurface ? [tools_2.surfaceToolDef] : []),
|
|
1247
|
-
...(isPrivateRuntimeChannel ? [tools_1.restTool] : []),
|
|
1248
|
-
...(!isPrivateRuntimeChannel ? [tools_1.observeTool] : []),
|
|
1249
|
-
...(!isPrivateRuntimeChannel ? [tools_1.settleTool] : []),
|
|
1250
|
-
...(isChatStyleChannel(channel ?? "") ? [tools_1.speakTool] : []),
|
|
1275
|
+
...baseTools,
|
|
1276
|
+
...toolSelection.engine,
|
|
1251
1277
|
];
|
|
1252
1278
|
const ordinaryActiveTools = relationshipToolNames
|
|
1253
1279
|
? unscopedOrdinaryActiveTools.filter((tool) => relationshipToolNames.includes(tool.function.name))
|
|
@@ -1325,7 +1351,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1325
1351
|
callbacks.onModelStart();
|
|
1326
1352
|
turnCallbackBufferRef.current = habitSession
|
|
1327
1353
|
? createHabitCallbackBuffer(callbacks)
|
|
1328
|
-
: callbacks.settleOutputMode === "final_only"
|
|
1354
|
+
: callbacks.settleOutputMode === "final_only" || relationship !== undefined
|
|
1329
1355
|
? createFinalOnlyTextBuffer(callbacks)
|
|
1330
1356
|
: null;
|
|
1331
1357
|
try {
|
|
@@ -1390,18 +1416,19 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1390
1416
|
const seconds = delayMs / 1000;
|
|
1391
1417
|
const cause = RETRY_LABELS[record.classification];
|
|
1392
1418
|
try {
|
|
1419
|
+
const agentName = owner?.agentName ?? (0, identity_2.getAgentName)();
|
|
1393
1420
|
if (record.provider === "openai-codex" && record.classification === "auth-failure") {
|
|
1394
|
-
await (0, openai_codex_token_1.refreshOpenAICodexProviderCredentials)(
|
|
1421
|
+
await (0, openai_codex_token_1.refreshOpenAICodexProviderCredentials)(agentName, {
|
|
1395
1422
|
force: true,
|
|
1396
1423
|
reason: "turn-auth-failure",
|
|
1397
1424
|
});
|
|
1398
1425
|
}
|
|
1399
|
-
await (0, provider_credentials_1.refreshProviderCredentialPool)(
|
|
1426
|
+
await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName, {
|
|
1400
1427
|
preserveCachedOnFailure: true,
|
|
1401
1428
|
providers: [record.provider],
|
|
1402
1429
|
});
|
|
1403
1430
|
_providerRuntimeFactories[facing] = null;
|
|
1404
|
-
providerRuntime = await getProviderRuntime(facing);
|
|
1431
|
+
providerRuntime = await getProviderRuntime(facing, owner);
|
|
1405
1432
|
providerRuntime.resetTurnState(attemptMessages);
|
|
1406
1433
|
}
|
|
1407
1434
|
catch (refreshError) {
|
|
@@ -1712,7 +1739,21 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1712
1739
|
entry.call,
|
|
1713
1740
|
entry.validated.arguments,
|
|
1714
1741
|
]));
|
|
1715
|
-
const
|
|
1742
|
+
const preflightRejections = new Map();
|
|
1743
|
+
for (const entry of validCalls) {
|
|
1744
|
+
if (!relationship && !toolSelection.engine.some((tool) => tool.function.name === entry.call.name))
|
|
1745
|
+
continue;
|
|
1746
|
+
const prepared = await (0, tools_1.preflightToolCall)(entry.call.name, validatedCallArguments.get(entry.call), augmentedToolContext);
|
|
1747
|
+
if (prepared.kind !== "ready")
|
|
1748
|
+
preflightRejections.set(entry.call.id, prepared.text);
|
|
1749
|
+
}
|
|
1750
|
+
if (preflightRejections.size > 0) {
|
|
1751
|
+
streamCallbackBuffer?.discard();
|
|
1752
|
+
rejectToolBatch(msg, result.toolCalls.map((call) => preflightRejections.get(call.id)
|
|
1753
|
+
?? "rejected: another call in this batch failed current authorization; no handler was executed."));
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
const habitBlockReason = await habitToolBatchBlockReason(habitSession, result.toolCalls, augmentedToolContext?.delegatedOrigins, toolSelection);
|
|
1716
1757
|
if (habitBlockReason) {
|
|
1717
1758
|
streamCallbackBuffer?.discard();
|
|
1718
1759
|
recordBlockedHabitSurfaceAttempts(habitSession, result.toolCalls, habitBlockReason);
|
|
@@ -1728,7 +1769,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1728
1769
|
continue;
|
|
1729
1770
|
}
|
|
1730
1771
|
const soleViolation = result.toolCalls.length > 1
|
|
1731
|
-
? result.toolCalls.find((call) => SOLE_CALL_REJECTION[call.name] !== undefined || (0, tools_1.resolveToolDefinition)(call.name)?.terminalProjection?.requiresSoleCall === true)
|
|
1772
|
+
? result.toolCalls.find((call) => SOLE_CALL_REJECTION[call.name] !== undefined || (0, tools_1.resolveToolDefinition)(call.name, toolSelection)?.terminalProjection?.requiresSoleCall === true)
|
|
1732
1773
|
: undefined;
|
|
1733
1774
|
if (soleViolation) {
|
|
1734
1775
|
streamCallbackBuffer?.discard();
|
|
@@ -1740,7 +1781,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1740
1781
|
? result.toolCalls[0]
|
|
1741
1782
|
: null;
|
|
1742
1783
|
const soleTerminalProjection = soleTerminalCall
|
|
1743
|
-
? (0, tools_1.resolveToolDefinition)(soleTerminalCall.name)?.terminalProjection
|
|
1784
|
+
? (0, tools_1.resolveToolDefinition)(soleTerminalCall.name, toolSelection)?.terminalProjection
|
|
1744
1785
|
: undefined;
|
|
1745
1786
|
if (soleTerminalCall && soleTerminalProjection?.mode === "verbatim") {
|
|
1746
1787
|
const terminalArgs = validatedCallArguments.get(soleTerminalCall);
|
|
@@ -1755,29 +1796,30 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1755
1796
|
callbacks.onClearText?.();
|
|
1756
1797
|
callbacks.onToolStart(soleTerminalCall.name, terminalArgs);
|
|
1757
1798
|
let terminalResult;
|
|
1799
|
+
let terminalSucceeded = false;
|
|
1758
1800
|
try {
|
|
1759
|
-
|
|
1760
|
-
|
|
1801
|
+
if (options?.execTool && !relationship) {
|
|
1802
|
+
terminalResult = await options.execTool(soleTerminalCall.name, terminalArgs, trustedToolContext);
|
|
1803
|
+
terminalSucceeded = true;
|
|
1804
|
+
}
|
|
1805
|
+
else {
|
|
1806
|
+
const execution = await (0, tools_1.executeTool)(soleTerminalCall.name, terminalArgs, augmentedToolContext, options?.execTool);
|
|
1807
|
+
terminalResult = "error" in execution
|
|
1808
|
+
? `error: ${execution.error instanceof Error ? execution.error.message : String(execution.error)}`
|
|
1809
|
+
: execution.text;
|
|
1810
|
+
terminalSucceeded = execution.kind === "handler_succeeded";
|
|
1811
|
+
}
|
|
1761
1812
|
}
|
|
1762
1813
|
catch (error) {
|
|
1763
|
-
|
|
1764
|
-
pushGenerated(msg);
|
|
1765
|
-
const failure = error instanceof Error ? `error: ${error.message}` : `error: ${String(error)}`;
|
|
1766
|
-
pushGenerated({ role: "tool", tool_call_id: soleTerminalCall.id, content: failure });
|
|
1767
|
-
providerRuntime.appendToolOutput(soleTerminalCall.id, failure);
|
|
1768
|
-
callbacks.onTextChunk(failure);
|
|
1769
|
-
completion = { answer: failure, intent: "blocked" };
|
|
1770
|
-
outcome = "blocked";
|
|
1771
|
-
done = true;
|
|
1772
|
-
continue;
|
|
1814
|
+
terminalResult = error instanceof Error ? `error: ${error.message}` : `error: ${String(error)}`;
|
|
1773
1815
|
}
|
|
1774
|
-
callbacks.onToolEnd(soleTerminalCall.name, (0, tools_1.summarizeArgs)(soleTerminalCall.name, terminalArgs),
|
|
1816
|
+
callbacks.onToolEnd(soleTerminalCall.name, (0, tools_1.summarizeArgs)(soleTerminalCall.name, terminalArgs, toolSelection), terminalSucceeded);
|
|
1775
1817
|
pushGenerated(msg);
|
|
1776
1818
|
pushGenerated({ role: "tool", tool_call_id: soleTerminalCall.id, content: terminalResult });
|
|
1777
1819
|
providerRuntime.appendToolOutput(soleTerminalCall.id, terminalResult);
|
|
1778
1820
|
callbacks.onTextChunk(terminalResult);
|
|
1779
|
-
completion = { answer: terminalResult, intent: "complete" };
|
|
1780
|
-
outcome = "settled";
|
|
1821
|
+
completion = { answer: terminalResult, intent: terminalSucceeded ? "complete" : "blocked" };
|
|
1822
|
+
outcome = terminalSucceeded ? "settled" : "blocked";
|
|
1781
1823
|
done = true;
|
|
1782
1824
|
continue;
|
|
1783
1825
|
}
|
|
@@ -1788,7 +1830,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1788
1830
|
const requiredToolCallsGate = pendingRequiredToolCalls();
|
|
1789
1831
|
if (requiredToolCallsGate) {
|
|
1790
1832
|
streamCallbackBuffer?.discard();
|
|
1791
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1833
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), false);
|
|
1792
1834
|
callbacks.onClearText?.();
|
|
1793
1835
|
queueRequiredCorrection(msg, requiredToolCallsGate.message, "before required tool calls completed");
|
|
1794
1836
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -1804,7 +1846,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1804
1846
|
const attentionQueue = augmentedToolContext?.delegatedOrigins;
|
|
1805
1847
|
if (isPrivateRuntimeChannel && attentionQueue && attentionQueue.length > 0) {
|
|
1806
1848
|
streamCallbackBuffer?.discard();
|
|
1807
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1849
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), false);
|
|
1808
1850
|
callbacks.onClearText?.();
|
|
1809
1851
|
const gateMessage = "current held-work frame still has unsurfaced items — return each listed item with surface(delegationId=...) before you settle. Older transcript claims are historical; only the current held-work frame is the gate.";
|
|
1810
1852
|
rejectToolBatch(msg, [gateMessage]);
|
|
@@ -1816,7 +1858,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1816
1858
|
const requiredAnswerRejection = options?.requiredToolCalls?.validateTerminalAnswer?.(answer);
|
|
1817
1859
|
if (requiredAnswerRejection) {
|
|
1818
1860
|
streamCallbackBuffer?.discard();
|
|
1819
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1861
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), false);
|
|
1820
1862
|
callbacks.onClearText?.();
|
|
1821
1863
|
queueRequiredCorrection(msg, requiredAnswerRejection, "before required terminal answer validation completed");
|
|
1822
1864
|
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.required_tool_answer_rejected", message: "unsupported settle answer rejected after required reads", meta: { answerLength: answer.length } });
|
|
@@ -1825,7 +1867,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1825
1867
|
// Private-runtime settle: no CompletionMetadata, "(settled)" ack
|
|
1826
1868
|
if (isPrivateRuntimeChannel) {
|
|
1827
1869
|
streamCallbackBuffer?.discard();
|
|
1828
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), true);
|
|
1870
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), true);
|
|
1829
1871
|
pushGenerated(msg);
|
|
1830
1872
|
const settled = "(settled)";
|
|
1831
1873
|
pushGenerated({ role: "tool", tool_call_id: result.toolCalls[0].id, content: settled });
|
|
@@ -1854,12 +1896,12 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1854
1896
|
await streamCallbackBuffer?.flush();
|
|
1855
1897
|
}
|
|
1856
1898
|
catch (error) {
|
|
1857
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1899
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), false);
|
|
1858
1900
|
streamCallbackBuffer?.discard();
|
|
1859
1901
|
finishTerminalProviderError(new streaming_1.SettleFinalizationCallbackError(error), "unknown");
|
|
1860
1902
|
continue;
|
|
1861
1903
|
}
|
|
1862
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), true);
|
|
1904
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), true);
|
|
1863
1905
|
completion = {
|
|
1864
1906
|
answer: deliveredAnswer,
|
|
1865
1907
|
intent: validDirectReply ? "direct_reply" : intent === "blocked" ? "blocked" : "complete",
|
|
@@ -1884,7 +1926,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1884
1926
|
// The payload is structurally final, but a semantic continuation
|
|
1885
1927
|
// gate rejected it. Return that exact gate reason to the model.
|
|
1886
1928
|
streamCallbackBuffer?.discard();
|
|
1887
|
-
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1929
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs, toolSelection), false);
|
|
1888
1930
|
callbacks.onClearText?.();
|
|
1889
1931
|
rejectToolBatch(msg, [retryError]);
|
|
1890
1932
|
}
|
|
@@ -1905,7 +1947,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1905
1947
|
message: "agent observed without responding",
|
|
1906
1948
|
meta: { ...(reason ? { reason } : {}) },
|
|
1907
1949
|
});
|
|
1908
|
-
callbacks.onToolEnd("observe", (0, tools_1.summarizeArgs)("observe", observeArgs), true);
|
|
1950
|
+
callbacks.onToolEnd("observe", (0, tools_1.summarizeArgs)("observe", observeArgs, toolSelection), true);
|
|
1909
1951
|
pushGenerated(msg);
|
|
1910
1952
|
const silenced = "(silenced)";
|
|
1911
1953
|
pushGenerated({ role: "tool", tool_call_id: result.toolCalls[0].id, content: silenced });
|
|
@@ -1923,14 +1965,14 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1923
1965
|
// Attention queue gate: reject rest if items remain
|
|
1924
1966
|
const attentionQueue = augmentedToolContext?.delegatedOrigins;
|
|
1925
1967
|
if (attentionQueue && attentionQueue.length > 0) {
|
|
1926
|
-
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs), false);
|
|
1968
|
+
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs, toolSelection), false);
|
|
1927
1969
|
const gateMessage = "current held-work frame still has unsurfaced items — return each listed item with surface(delegationId=...) before you rest. Older transcript claims are historical; only the current held-work frame is the gate.";
|
|
1928
1970
|
rejectToolBatch(msg, [gateMessage]);
|
|
1929
1971
|
continue;
|
|
1930
1972
|
}
|
|
1931
1973
|
if (hasFreshPendingWork(options) && !freshWorkGateFired) {
|
|
1932
1974
|
freshWorkGateFired = true;
|
|
1933
|
-
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs), false);
|
|
1975
|
+
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs, toolSelection), false);
|
|
1934
1976
|
const gateMessage = "fresh work arrived for me this turn — inspect the pending messages above and take the next concrete action before you rest.";
|
|
1935
1977
|
rejectToolBatch(msg, [gateMessage]);
|
|
1936
1978
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -1942,7 +1984,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1942
1984
|
});
|
|
1943
1985
|
continue;
|
|
1944
1986
|
}
|
|
1945
|
-
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs), true);
|
|
1987
|
+
callbacks.onToolEnd("rest", (0, tools_1.summarizeArgs)("rest", restArgs, toolSelection), true);
|
|
1946
1988
|
pushGenerated(msg);
|
|
1947
1989
|
const ack = "(resting)";
|
|
1948
1990
|
pushGenerated({ role: "tool", tool_call_id: result.toolCalls[0].id, content: ack });
|
|
@@ -1968,7 +2010,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1968
2010
|
streamCallbackBuffer?.discard();
|
|
1969
2011
|
for (const rejection of requiredDispatchRejections.values()) {
|
|
1970
2012
|
callbacks.onToolStart(rejection.name, rejection.args);
|
|
1971
|
-
callbacks.onToolEnd(rejection.name, (0, tools_1.summarizeArgs)(rejection.name, rejection.args), false);
|
|
2013
|
+
callbacks.onToolEnd(rejection.name, (0, tools_1.summarizeArgs)(rejection.name, rejection.args, toolSelection), false);
|
|
1972
2014
|
options?.toolBoundaryObserver?.({
|
|
1973
2015
|
name: rejection.name, reason: "dependency_rejected",
|
|
1974
2016
|
globallyResolvable: typeof (0, tools_1.resolveToolDefinition)(rejection.name)?.handler === "function",
|
|
@@ -1987,7 +2029,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1987
2029
|
const executionRejections = new Map();
|
|
1988
2030
|
for (const entry of validCalls) {
|
|
1989
2031
|
const args = validatedCallArguments.get(entry.call);
|
|
1990
|
-
const fingerprint = effectFingerprint(entry.call.name, entry.call.arguments);
|
|
2032
|
+
const fingerprint = effectFingerprint(entry.call.name, entry.call.arguments, toolSelection);
|
|
1991
2033
|
if (forcingHistoricalEffect && fingerprint && !unresolvedHistoricalEffects.some((effect) => effect.fingerprint === fingerprint)) {
|
|
1992
2034
|
executionRejections.set(entry.call.id, "rejected: this turn is retrying an unresolved historical effect, and these mutation arguments do not match it. Read current state or retry the exact failed effect.");
|
|
1993
2035
|
}
|
|
@@ -2007,7 +2049,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2007
2049
|
continue;
|
|
2008
2050
|
const args = validatedCallArguments.get(entry.call);
|
|
2009
2051
|
callbacks.onToolStart(entry.call.name, args);
|
|
2010
|
-
callbacks.onToolEnd(entry.call.name, (0, tools_1.summarizeArgs)(entry.call.name, args), false);
|
|
2052
|
+
callbacks.onToolEnd(entry.call.name, (0, tools_1.summarizeArgs)(entry.call.name, args, toolSelection), false);
|
|
2011
2053
|
}
|
|
2012
2054
|
rejectToolBatch(msg, result.toolCalls.map((call) => executionRejections.get(call.id)
|
|
2013
2055
|
?? "rejected: another call in this batch was inadmissible; no handler was executed."));
|
|
@@ -2048,11 +2090,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2048
2090
|
continue;
|
|
2049
2091
|
}
|
|
2050
2092
|
streamCallbackBuffer?.discard();
|
|
2051
|
-
const toolDigest = (0,
|
|
2052
|
-
name: protectedCall.call.name,
|
|
2053
|
-
schemaDigest: protectedCall.validated.schemaDigest,
|
|
2054
|
-
policyId: protectedCall.policy.policyId,
|
|
2055
|
-
});
|
|
2093
|
+
const toolDigest = (0, tool_approval_1.digestApprovalToolDefinition)((0, tools_1.resolveToolDefinition)(protectedCall.call.name, toolSelection), protectedCall.validated.schemaDigest, protectedCall.policy.policyId);
|
|
2056
2094
|
const policyDigest = (0, tool_arguments_1.digestJson)({
|
|
2057
2095
|
policyId: protectedCall.policy.policyId,
|
|
2058
2096
|
actionClass: protectedCall.policy.actionClass,
|
|
@@ -2094,7 +2132,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2094
2132
|
if (signal?.aborted)
|
|
2095
2133
|
break;
|
|
2096
2134
|
const args = validatedCallArguments.get(tc);
|
|
2097
|
-
const currentEffectFingerprint = effectFingerprint(tc.name, tc.arguments);
|
|
2135
|
+
const currentEffectFingerprint = effectFingerprint(tc.name, tc.arguments, toolSelection);
|
|
2098
2136
|
if (tc.name === "send_message" && args.friendId === "self") {
|
|
2099
2137
|
sawSendMessageSelf = true;
|
|
2100
2138
|
}
|
|
@@ -2102,7 +2140,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2102
2140
|
// The canonical pre-batch schema gate guarantees a required string.
|
|
2103
2141
|
const speakArgs = JSON.parse(tc.arguments);
|
|
2104
2142
|
const speakMessage = speakArgs.message;
|
|
2105
|
-
const argSummary = (0, tools_1.summarizeArgs)("speak", { message: speakMessage });
|
|
2143
|
+
const argSummary = (0, tools_1.summarizeArgs)("speak", { message: speakMessage }, toolSelection);
|
|
2106
2144
|
callbacks.onToolStart("speak", { message: speakMessage });
|
|
2107
2145
|
if (speakMessage.trim().length === 0) {
|
|
2108
2146
|
const err = "speak requires a non-empty `message` string.";
|
|
@@ -2154,7 +2192,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2154
2192
|
}
|
|
2155
2193
|
if (tc.name === "ponder") {
|
|
2156
2194
|
const parsedArgs = normalizeLegacyPonderArgs(parsePonderPayload(tc.arguments));
|
|
2157
|
-
const argSummary = (0, tools_1.summarizeArgs)(tc.name, parsedArgs);
|
|
2195
|
+
const argSummary = (0, tools_1.summarizeArgs)(tc.name, parsedArgs, toolSelection);
|
|
2158
2196
|
callbacks.onToolStart(tc.name, parsedArgs);
|
|
2159
2197
|
let toolResult;
|
|
2160
2198
|
let success = false;
|
|
@@ -2320,19 +2358,28 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2320
2358
|
callbacks.onToolStart(tc.name, args);
|
|
2321
2359
|
let toolResult;
|
|
2322
2360
|
let success;
|
|
2361
|
+
let invoked = false;
|
|
2323
2362
|
try {
|
|
2324
|
-
const execToolFn = options?.execTool ?? tools_1.execTool;
|
|
2325
2363
|
const routineActionSelection = approvalCalls.find((entry) => entry.call.id === tc.id)?.routineActionSelection;
|
|
2326
2364
|
const executionToolContext = routineActionSelection && augmentedToolContext ? { ...augmentedToolContext, routineActionSelection } : augmentedToolContext;
|
|
2327
|
-
if (
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2365
|
+
if (options?.execTool && !relationship) {
|
|
2366
|
+
invoked = true;
|
|
2367
|
+
toolResult = await options.execTool(tc.name, args, trustedToolContext);
|
|
2368
|
+
success = true;
|
|
2369
|
+
}
|
|
2370
|
+
else {
|
|
2371
|
+
const execution = await (0, tools_1.executeTool)(tc.name, args, executionToolContext, options?.execTool);
|
|
2372
|
+
invoked = execution.kind !== "rejected_before_handler";
|
|
2373
|
+
success = execution.kind === "handler_succeeded";
|
|
2374
|
+
toolResult = "error" in execution ? `error: ${execution.error}` : execution.text;
|
|
2375
|
+
}
|
|
2331
2376
|
}
|
|
2332
2377
|
catch (e) {
|
|
2333
2378
|
toolResult = `error: ${e}`;
|
|
2334
2379
|
success = false;
|
|
2335
2380
|
}
|
|
2381
|
+
if (invoked && requiredToolCallNames.includes(tc.name) && !options?.requiredToolCalls?.requireSuccessfulResults)
|
|
2382
|
+
dispatchedRequiredToolCalls.add(tc.name);
|
|
2336
2383
|
const modelResult = (0, tool_friction_1.rewriteToolResultForModel)(tc.name, toolResult, toolFrictionLedger);
|
|
2337
2384
|
pushGenerated({ role: "tool", tool_call_id: tc.id, content: modelResult });
|
|
2338
2385
|
providerRuntime.appendToolOutput(tc.id, modelResult);
|
|
@@ -2355,17 +2402,17 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2355
2402
|
if (success && currentEffectFingerprint && !toolResultIndicatesFailure(toolResult)) {
|
|
2356
2403
|
unresolvedHistoricalEffects = unresolvedHistoricalEffects.filter((effect) => effect.fingerprint !== currentEffectFingerprint);
|
|
2357
2404
|
}
|
|
2358
|
-
const resolvedRiskProfile = (0, tools_1.resolveToolDefinition)(tc.name)?.riskProfile;
|
|
2405
|
+
const resolvedRiskProfile = (0, tools_1.resolveToolDefinition)(tc.name, toolSelection)?.riskProfile;
|
|
2359
2406
|
const toolRiskProfile = typeof resolvedRiskProfile === "function" ? resolvedRiskProfile(args) : resolvedRiskProfile;
|
|
2360
2407
|
options?.toolBoundaryObserver?.({
|
|
2361
2408
|
name: tc.name,
|
|
2362
2409
|
reason: "dispatched",
|
|
2363
|
-
globallyResolvable: typeof (0, tools_1.resolveToolDefinition)(tc.name)?.handler === "function",
|
|
2364
|
-
invoked
|
|
2410
|
+
globallyResolvable: typeof (0, tools_1.resolveToolDefinition)(tc.name, toolSelection)?.handler === "function",
|
|
2411
|
+
invoked,
|
|
2365
2412
|
sideEffect: success && toolRiskProfile?.mutates !== "none",
|
|
2366
2413
|
});
|
|
2367
2414
|
(0, tool_loop_1.recordToolOutcome)(toolLoopState, tc.name, args, modelResult, success);
|
|
2368
|
-
callbacks.onToolEnd(tc.name, (0, tools_1.buildToolResultSummary)(tc.name, args, modelResult, success), success);
|
|
2415
|
+
callbacks.onToolEnd(tc.name, (0, tools_1.buildToolResultSummary)(tc.name, args, modelResult, success, toolSelection), success);
|
|
2369
2416
|
callbacks.onToolResult?.(messages);
|
|
2370
2417
|
}
|
|
2371
2418
|
}
|
|
@@ -2391,6 +2438,11 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2391
2438
|
}
|
|
2392
2439
|
}
|
|
2393
2440
|
}
|
|
2441
|
+
catch (error) {
|
|
2442
|
+
if (!(error instanceof tools_1.ToolSelectionError))
|
|
2443
|
+
throw error;
|
|
2444
|
+
finishTerminalProviderError(error, "unknown");
|
|
2445
|
+
}
|
|
2394
2446
|
finally {
|
|
2395
2447
|
nextAttemptControls = [];
|
|
2396
2448
|
rejectedAttempt = [];
|