@rowan-agent/agent 0.10.1 → 0.11.0
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/dist/index.d.ts +135 -99
- package/dist/index.js +611 -171
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -518,15 +518,32 @@ async function executeRuntimeToolCall(input) {
|
|
|
518
518
|
let decision;
|
|
519
519
|
if (input.beforeToolCall) {
|
|
520
520
|
await input.observe?.({ type: "approval_requested", tool, args });
|
|
521
|
-
decision = await input.beforeToolCall({
|
|
522
|
-
await input.observe?.({
|
|
523
|
-
type: "approval_result",
|
|
521
|
+
decision = await input.beforeToolCall({
|
|
524
522
|
tool,
|
|
525
523
|
args,
|
|
526
|
-
|
|
524
|
+
toolCallId: input.toolCall.id
|
|
527
525
|
});
|
|
526
|
+
if (decision && "allow" in decision) {
|
|
527
|
+
await input.observe?.({
|
|
528
|
+
type: "approval_result",
|
|
529
|
+
tool,
|
|
530
|
+
args,
|
|
531
|
+
decision
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (decision && "interaction" in decision) {
|
|
536
|
+
const result = toolResult({
|
|
537
|
+
context: input.toolContext,
|
|
538
|
+
toolName: tool.name,
|
|
539
|
+
ok: false,
|
|
540
|
+
content: null,
|
|
541
|
+
error: `Tool interaction required: ${decision.interaction.prompt}`
|
|
542
|
+
});
|
|
543
|
+
await input.observe?.({ type: "tool_blocked", tool, reason: decision.interaction.prompt });
|
|
544
|
+
return result;
|
|
528
545
|
}
|
|
529
|
-
if (decision && !decision.allow) {
|
|
546
|
+
if (decision && "allow" in decision && !decision.allow) {
|
|
530
547
|
const result = toolResult({
|
|
531
548
|
context: input.toolContext,
|
|
532
549
|
toolName: tool.name,
|
|
@@ -660,7 +677,18 @@ function createReadTool(context) {
|
|
|
660
677
|
error: invalidLimit
|
|
661
678
|
});
|
|
662
679
|
}
|
|
663
|
-
|
|
680
|
+
let fileStat;
|
|
681
|
+
try {
|
|
682
|
+
fileStat = await stat(resolved.absolutePath);
|
|
683
|
+
} catch (error) {
|
|
684
|
+
return toolResult({
|
|
685
|
+
context: toolContext,
|
|
686
|
+
toolName: "read",
|
|
687
|
+
ok: false,
|
|
688
|
+
content: null,
|
|
689
|
+
error: error instanceof Error ? error.message : String(error)
|
|
690
|
+
});
|
|
691
|
+
}
|
|
664
692
|
if (!fileStat.isFile()) {
|
|
665
693
|
return toolResult({
|
|
666
694
|
context: toolContext,
|
|
@@ -670,7 +698,18 @@ function createReadTool(context) {
|
|
|
670
698
|
error: `Not a file: ${resolved.relativePath}`
|
|
671
699
|
});
|
|
672
700
|
}
|
|
673
|
-
|
|
701
|
+
let bytes;
|
|
702
|
+
try {
|
|
703
|
+
bytes = await readFile2(resolved.absolutePath);
|
|
704
|
+
} catch (error) {
|
|
705
|
+
return toolResult({
|
|
706
|
+
context: toolContext,
|
|
707
|
+
toolName: "read",
|
|
708
|
+
ok: false,
|
|
709
|
+
content: null,
|
|
710
|
+
error: error instanceof Error ? error.message : String(error)
|
|
711
|
+
});
|
|
712
|
+
}
|
|
674
713
|
const source = new TextDecoder().decode(bytes);
|
|
675
714
|
const sourceLines = source.split(/\r\n|\n|\r/);
|
|
676
715
|
const requestedOffset = parsed.offset ?? 1;
|
|
@@ -1363,6 +1402,8 @@ function createPhaseInteractionDriver(state, phase, signal) {
|
|
|
1363
1402
|
kind: input.kind,
|
|
1364
1403
|
prompt: input.prompt,
|
|
1365
1404
|
...input.payload === void 0 ? {} : { payload: input.payload },
|
|
1405
|
+
...input.origin === void 0 ? {} : { origin: input.origin },
|
|
1406
|
+
...input.toolCallId === void 0 ? {} : { toolCallId: input.toolCallId },
|
|
1366
1407
|
createdAt: createTimestamp(),
|
|
1367
1408
|
status: "pending"
|
|
1368
1409
|
};
|
|
@@ -1377,6 +1418,13 @@ function createPhaseInteractionDriver(state, phase, signal) {
|
|
|
1377
1418
|
answers() {
|
|
1378
1419
|
return new Map(answers);
|
|
1379
1420
|
},
|
|
1421
|
+
checkpoint() {
|
|
1422
|
+
return checkpoint;
|
|
1423
|
+
},
|
|
1424
|
+
clearCheckpoint() {
|
|
1425
|
+
checkpoint = void 0;
|
|
1426
|
+
sync();
|
|
1427
|
+
},
|
|
1380
1428
|
suspend(input = {}) {
|
|
1381
1429
|
assertActive();
|
|
1382
1430
|
const pending = this.pending();
|
|
@@ -2488,34 +2536,48 @@ async function executePhaseWithModel(ctx) {
|
|
|
2488
2536
|
...ctx.context,
|
|
2489
2537
|
messages: ctx.messageManager.visible()
|
|
2490
2538
|
};
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
// but do not let the route escape the error/re-decision boundary.
|
|
2498
|
-
toolCalls: collected.toolCalls.some((candidate) => candidate.name === PhaseRouteTool) && collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool) ? collected.toolCalls.filter((candidate) => candidate.name !== PhaseRouteTool) : collected.toolCalls
|
|
2499
|
-
};
|
|
2500
|
-
for (const toolCall of collected.toolCalls) {
|
|
2501
|
-
if (toolCall.name !== PhaseRouteTool) continue;
|
|
2502
|
-
const messageId = ctx.messageManager.start(
|
|
2503
|
-
"tool",
|
|
2504
|
-
createRouteToolResultContent(
|
|
2505
|
-
toolCall,
|
|
2506
|
-
collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool) ? "Route must be called separately after ordinary tools finish; this route decision was ignored." : void 0
|
|
2507
|
-
),
|
|
2508
|
-
{
|
|
2509
|
-
phase: ctx.phase.name
|
|
2510
|
-
}
|
|
2539
|
+
let executableToolCalls;
|
|
2540
|
+
const checkpoint = ctx.execution.interaction.checkpoint();
|
|
2541
|
+
if (checkpoint && typeof checkpoint === "object" && checkpoint.kind === "tool_call_suspension") {
|
|
2542
|
+
const toolSuspension = checkpoint;
|
|
2543
|
+
executableToolCalls = toolSuspension.toolCalls.filter(
|
|
2544
|
+
(toolCall) => executableToolNames.has(toolCall.name)
|
|
2511
2545
|
);
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2546
|
+
output = {
|
|
2547
|
+
message: "",
|
|
2548
|
+
phase: ctx.phase.name,
|
|
2549
|
+
toolCalls: [...toolSuspension.toolCalls]
|
|
2550
|
+
};
|
|
2551
|
+
} else {
|
|
2552
|
+
const collected = await ctx.execution.invokeModel(roundContext);
|
|
2553
|
+
output = {
|
|
2554
|
+
message: collected.text,
|
|
2555
|
+
phase: ctx.phase.name,
|
|
2556
|
+
// A route decision sharing a model response with an ordinary Tool is
|
|
2557
|
+
// rejected for this round. Keep ordinary calls visible so they can run,
|
|
2558
|
+
// but do not let the route escape the error/re-decision boundary.
|
|
2559
|
+
toolCalls: collected.toolCalls.some((candidate) => candidate.name === PhaseRouteTool) && collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool) ? collected.toolCalls.filter((candidate) => candidate.name !== PhaseRouteTool) : collected.toolCalls
|
|
2560
|
+
};
|
|
2561
|
+
for (const toolCall of collected.toolCalls) {
|
|
2562
|
+
if (toolCall.name !== PhaseRouteTool) continue;
|
|
2563
|
+
const messageId = ctx.messageManager.start(
|
|
2564
|
+
"tool",
|
|
2565
|
+
createRouteToolResultContent(
|
|
2566
|
+
toolCall,
|
|
2567
|
+
collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool) ? "Route must be called separately after ordinary tools finish; this route decision was ignored." : void 0
|
|
2568
|
+
),
|
|
2569
|
+
{
|
|
2570
|
+
phase: ctx.phase.name
|
|
2571
|
+
}
|
|
2572
|
+
);
|
|
2573
|
+
await ctx.messageManager.end(messageId);
|
|
2574
|
+
}
|
|
2575
|
+
executableToolCalls = collected.toolCalls.filter(
|
|
2576
|
+
(toolCall) => executableToolNames.has(toolCall.name)
|
|
2577
|
+
);
|
|
2578
|
+
if (executableToolCalls.length === 0) {
|
|
2579
|
+
return output;
|
|
2580
|
+
}
|
|
2519
2581
|
}
|
|
2520
2582
|
const results = await ctx.execution.executeTools(roundContext, executableToolCalls);
|
|
2521
2583
|
for (const result of results) {
|
|
@@ -2991,7 +3053,8 @@ async function executeToolCall(input) {
|
|
|
2991
3053
|
if (input.config.runtime?.tools) {
|
|
2992
3054
|
result = await input.config.runtime.tools({
|
|
2993
3055
|
config: input.config,
|
|
2994
|
-
toolCall: input.toolCall
|
|
3056
|
+
toolCall: input.toolCall,
|
|
3057
|
+
driver: input.driver
|
|
2995
3058
|
});
|
|
2996
3059
|
} else {
|
|
2997
3060
|
const toolContext = {
|
|
@@ -3017,7 +3080,8 @@ async function executeToolCalls(input) {
|
|
|
3017
3080
|
if (input.config.runtime?.toolsBatch) {
|
|
3018
3081
|
const results2 = await input.config.runtime.toolsBatch({
|
|
3019
3082
|
config: input.config,
|
|
3020
|
-
toolCalls: input.toolCalls
|
|
3083
|
+
toolCalls: input.toolCalls,
|
|
3084
|
+
driver: input.driver
|
|
3021
3085
|
});
|
|
3022
3086
|
if (results2.length !== input.toolCalls.length) throw new Error("Runtime returned an invalid Tool batch result");
|
|
3023
3087
|
return results2.map((result, index) => ({
|
|
@@ -3115,7 +3179,8 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3115
3179
|
}
|
|
3116
3180
|
},
|
|
3117
3181
|
tools,
|
|
3118
|
-
toolCall
|
|
3182
|
+
toolCall,
|
|
3183
|
+
driver: interaction
|
|
3119
3184
|
});
|
|
3120
3185
|
await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
|
|
3121
3186
|
return result;
|
|
@@ -3137,7 +3202,8 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3137
3202
|
}
|
|
3138
3203
|
},
|
|
3139
3204
|
tools,
|
|
3140
|
-
toolCalls
|
|
3205
|
+
toolCalls,
|
|
3206
|
+
driver: interaction
|
|
3141
3207
|
});
|
|
3142
3208
|
for (const result of results) {
|
|
3143
3209
|
await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
|
|
@@ -4222,12 +4288,30 @@ function assembleRegisteredExtensions(snapshot, runner, options = {}) {
|
|
|
4222
4288
|
beforePrompt: (phaseId, input) => runner.emitBeforePrompt(phaseId, input),
|
|
4223
4289
|
beforeToolCall: async (input) => {
|
|
4224
4290
|
const tool = projectTool(input.tool, input.context.agentId, input.context.runId);
|
|
4225
|
-
const decision = await runner.emitBeforeToolCall(tool, input.args
|
|
4291
|
+
const decision = await runner.emitBeforeToolCall(tool, input.args, {
|
|
4292
|
+
runId: input.context.runId,
|
|
4293
|
+
agentId: input.context.agentId,
|
|
4294
|
+
toolCallId: input.context.toolCallId,
|
|
4295
|
+
metadata: input.context.runMetadata,
|
|
4296
|
+
answer: input.answer
|
|
4297
|
+
});
|
|
4298
|
+
if (decision.interaction !== void 0) {
|
|
4299
|
+
return { interaction: decision.interaction };
|
|
4300
|
+
}
|
|
4226
4301
|
return decision.allow ? { allow: true } : { allow: false, reason: decision.reason ?? "Extension hook rejected the Tool." };
|
|
4227
4302
|
},
|
|
4228
4303
|
afterToolCall: async (input) => {
|
|
4229
4304
|
const tool = projectTool(input.tool, input.context.agentId, input.context.runId);
|
|
4230
|
-
const result = await runner.emitAfterToolCall(
|
|
4305
|
+
const result = await runner.emitAfterToolCall(
|
|
4306
|
+
tool,
|
|
4307
|
+
toLoopResult(input.result, input.context.toolCallId, input.tool.name),
|
|
4308
|
+
{
|
|
4309
|
+
runId: input.context.runId,
|
|
4310
|
+
agentId: input.context.agentId,
|
|
4311
|
+
toolCallId: input.context.toolCallId,
|
|
4312
|
+
metadata: input.context.runMetadata
|
|
4313
|
+
}
|
|
4314
|
+
);
|
|
4231
4315
|
return fromLoopResult(result);
|
|
4232
4316
|
},
|
|
4233
4317
|
setContext: (context2) => {
|
|
@@ -4873,19 +4957,28 @@ var ExtensionRunner = class {
|
|
|
4873
4957
|
});
|
|
4874
4958
|
return result?.input ?? input;
|
|
4875
4959
|
}
|
|
4876
|
-
async emitBeforeToolCall(tool, args) {
|
|
4960
|
+
async emitBeforeToolCall(tool, args, context) {
|
|
4877
4961
|
const result = await this.emitHook("before_tool_call", {
|
|
4878
4962
|
type: "before_tool_call",
|
|
4879
4963
|
tool,
|
|
4880
|
-
args
|
|
4964
|
+
args,
|
|
4965
|
+
...context?.runId !== void 0 ? { runId: context.runId } : {},
|
|
4966
|
+
...context?.agentId !== void 0 ? { agentId: context.agentId } : {},
|
|
4967
|
+
...context?.toolCallId !== void 0 ? { toolCallId: context.toolCallId } : {},
|
|
4968
|
+
...context?.metadata !== void 0 ? { metadata: context.metadata } : {},
|
|
4969
|
+
...context?.answer !== void 0 ? { answer: context.answer } : {}
|
|
4881
4970
|
});
|
|
4882
4971
|
return result ?? { allow: true };
|
|
4883
4972
|
}
|
|
4884
|
-
async emitAfterToolCall(tool, result) {
|
|
4973
|
+
async emitAfterToolCall(tool, result, context) {
|
|
4885
4974
|
const hookResult = await this.emitHook("after_tool_call", {
|
|
4886
4975
|
type: "after_tool_call",
|
|
4887
4976
|
tool,
|
|
4888
|
-
result
|
|
4977
|
+
result,
|
|
4978
|
+
...context?.runId !== void 0 ? { runId: context.runId } : {},
|
|
4979
|
+
...context?.agentId !== void 0 ? { agentId: context.agentId } : {},
|
|
4980
|
+
...context?.toolCallId !== void 0 ? { toolCallId: context.toolCallId } : {},
|
|
4981
|
+
...context?.metadata !== void 0 ? { metadata: context.metadata } : {}
|
|
4889
4982
|
});
|
|
4890
4983
|
return hookResult?.result ?? result;
|
|
4891
4984
|
}
|
|
@@ -6235,7 +6328,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6235
6328
|
},
|
|
6236
6329
|
onContext: assembly.setContext,
|
|
6237
6330
|
runtime: {
|
|
6238
|
-
tools: ({ toolCall }) => {
|
|
6331
|
+
tools: ({ toolCall, driver }) => {
|
|
6239
6332
|
const task = toolQueue.then(async () => {
|
|
6240
6333
|
const execution = await this.executeToolBatch({
|
|
6241
6334
|
run,
|
|
@@ -6244,7 +6337,11 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6244
6337
|
expectedRevision: executionRevision,
|
|
6245
6338
|
toolConfig: executionTools,
|
|
6246
6339
|
toolCalls: [toolCall],
|
|
6247
|
-
signal: controller.signal
|
|
6340
|
+
signal: controller.signal,
|
|
6341
|
+
driver,
|
|
6342
|
+
onRevision: (rev) => {
|
|
6343
|
+
executionRevision = rev;
|
|
6344
|
+
}
|
|
6248
6345
|
});
|
|
6249
6346
|
executionRevision = execution.revision;
|
|
6250
6347
|
return execution.results[0];
|
|
@@ -6252,7 +6349,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6252
6349
|
toolQueue = task.then(() => void 0, () => void 0);
|
|
6253
6350
|
return task;
|
|
6254
6351
|
},
|
|
6255
|
-
toolsBatch: ({ toolCalls }) => {
|
|
6352
|
+
toolsBatch: ({ toolCalls, driver }) => {
|
|
6256
6353
|
const task = toolQueue.then(async () => {
|
|
6257
6354
|
const execution = await this.executeToolBatch({
|
|
6258
6355
|
run,
|
|
@@ -6261,7 +6358,11 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6261
6358
|
expectedRevision: executionRevision,
|
|
6262
6359
|
toolConfig: executionTools,
|
|
6263
6360
|
toolCalls,
|
|
6264
|
-
signal: controller.signal
|
|
6361
|
+
signal: controller.signal,
|
|
6362
|
+
driver,
|
|
6363
|
+
onRevision: (rev) => {
|
|
6364
|
+
executionRevision = rev;
|
|
6365
|
+
}
|
|
6265
6366
|
});
|
|
6266
6367
|
executionRevision = execution.revision;
|
|
6267
6368
|
return execution.results;
|
|
@@ -6303,19 +6404,20 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6303
6404
|
return;
|
|
6304
6405
|
}
|
|
6305
6406
|
if (result.type === "input_required") {
|
|
6306
|
-
const
|
|
6407
|
+
const isToolCallInteraction = result.interactions?.some((i) => i.origin === "tool_call");
|
|
6408
|
+
const output = result.interactions && result.interactions.length > 0 ? void 0 : latestAssistant(
|
|
6307
6409
|
run,
|
|
6308
6410
|
result.messages.slice(modelMessages.length),
|
|
6309
6411
|
modelMessages.length
|
|
6310
6412
|
);
|
|
6311
|
-
const prompt = output ?? promptMessage(run, result.request.prompt, result.messages.length);
|
|
6413
|
+
const prompt = isToolCallInteraction ? void 0 : output ?? promptMessage(run, result.request.prompt, result.messages.length);
|
|
6312
6414
|
await this.owned.commitInputRequired({
|
|
6313
6415
|
runId: run.id,
|
|
6314
6416
|
execution: claim.execution,
|
|
6315
6417
|
expectedRevision: executionRevision,
|
|
6316
6418
|
requestId: createId("input"),
|
|
6317
6419
|
phase: result.request.phase,
|
|
6318
|
-
prompt,
|
|
6420
|
+
...prompt ? { prompt } : {},
|
|
6319
6421
|
checkpoint: result.checkpoint,
|
|
6320
6422
|
interactions: result.interactions,
|
|
6321
6423
|
interactionAnswers: claim.run.interactionAnswers
|
|
@@ -6387,109 +6489,421 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6387
6489
|
return { result: batch.results[0], revision: batch.revision };
|
|
6388
6490
|
}
|
|
6389
6491
|
async executeToolBatch(input) {
|
|
6390
|
-
const
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
expectedRevision: input.expectedRevision,
|
|
6394
|
-
requestMessageId: createId("msg"),
|
|
6395
|
-
calls: input.toolCalls.map((toolCall) => ({
|
|
6396
|
-
providerToolCallId: toolCall.id,
|
|
6397
|
-
name: toolCall.name,
|
|
6398
|
-
args: toJsonValue(toolCall.args)
|
|
6399
|
-
}))
|
|
6400
|
-
});
|
|
6401
|
-
let revision = reserved.run.revision;
|
|
6402
|
-
const results = [];
|
|
6403
|
-
for (let index = 0; index < input.toolCalls.length; index += 1) {
|
|
6404
|
-
const toolCall = input.toolCalls[index];
|
|
6405
|
-
const tool = reserved.toolCalls[index];
|
|
6406
|
-
const execution = await this.executeReservedTool({
|
|
6407
|
-
...input,
|
|
6408
|
-
toolCall,
|
|
6409
|
-
tool,
|
|
6410
|
-
expectedRevision: revision
|
|
6411
|
-
});
|
|
6412
|
-
revision = execution.revision;
|
|
6413
|
-
results.push(execution.result);
|
|
6414
|
-
}
|
|
6415
|
-
return { results, revision };
|
|
6416
|
-
}
|
|
6417
|
-
async executeReservedTool(input) {
|
|
6418
|
-
const durableTool = input.toolConfig.tools.find((candidate) => candidate.name === input.toolCall.name);
|
|
6419
|
-
const providerToolCallId = input.toolCall.id;
|
|
6420
|
-
const toolCallId = input.tool.id;
|
|
6492
|
+
const checkpoint = input.driver?.checkpoint();
|
|
6493
|
+
const isSuspensionResume = checkpoint && typeof checkpoint === "object" && checkpoint.kind === "tool_call_suspension";
|
|
6494
|
+
const suspension = isSuspensionResume ? checkpoint : void 0;
|
|
6421
6495
|
let revision = input.expectedRevision;
|
|
6422
|
-
const
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6496
|
+
const setRevision = (newRevision) => {
|
|
6497
|
+
revision = newRevision;
|
|
6498
|
+
input.onRevision?.(revision);
|
|
6499
|
+
};
|
|
6500
|
+
if (!suspension && input.toolCalls.length > 1) {
|
|
6501
|
+
let hasInteraction = false;
|
|
6502
|
+
const preDecisions = [];
|
|
6503
|
+
const toolCallIds = input.toolCalls.map(() => createId("tool"));
|
|
6504
|
+
for (let i = 0; i < input.toolCalls.length; i++) {
|
|
6505
|
+
const toolCall = input.toolCalls[i];
|
|
6506
|
+
const durableTool = input.toolConfig.tools.find((c) => c.name === toolCall.name);
|
|
6507
|
+
if (!durableTool || !input.toolConfig.beforeToolCall) {
|
|
6508
|
+
preDecisions.push({ allow: true });
|
|
6509
|
+
continue;
|
|
6510
|
+
}
|
|
6511
|
+
const toolCallId = toolCallIds[i];
|
|
6512
|
+
const context = {
|
|
6513
|
+
agentId: input.run.agentId,
|
|
6514
|
+
runId: input.run.id,
|
|
6515
|
+
...input.agentMetadata === void 0 ? {} : { agentMetadata: input.agentMetadata },
|
|
6516
|
+
...input.run.metadata === void 0 ? {} : { runMetadata: input.run.metadata },
|
|
6517
|
+
toolCallId,
|
|
6518
|
+
reportProgress: () => {
|
|
6519
|
+
}
|
|
6520
|
+
};
|
|
6438
6521
|
try {
|
|
6439
|
-
|
|
6440
|
-
|
|
6522
|
+
const decision = await input.toolConfig.beforeToolCall({
|
|
6523
|
+
tool: durableTool,
|
|
6524
|
+
args: toJsonValue(toolCall.args),
|
|
6525
|
+
context,
|
|
6526
|
+
signal: input.signal
|
|
6527
|
+
});
|
|
6528
|
+
if ("interaction" in decision && decision.interaction !== void 0) {
|
|
6529
|
+
hasInteraction = true;
|
|
6530
|
+
break;
|
|
6531
|
+
}
|
|
6532
|
+
preDecisions.push(decision);
|
|
6441
6533
|
} catch {
|
|
6442
|
-
|
|
6534
|
+
preDecisions.push({ allow: true });
|
|
6443
6535
|
}
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6536
|
+
}
|
|
6537
|
+
if (!hasInteraction) {
|
|
6538
|
+
const reserved = await this.owned.reserveToolCalls({
|
|
6447
6539
|
runId: input.run.id,
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6540
|
+
execution: input.execution,
|
|
6541
|
+
expectedRevision: revision,
|
|
6542
|
+
requestMessageId: createId("msg"),
|
|
6543
|
+
calls: input.toolCalls.map((tc, i) => ({
|
|
6544
|
+
toolCallId: toolCallIds[i],
|
|
6545
|
+
providerToolCallId: tc.id,
|
|
6546
|
+
name: tc.name,
|
|
6547
|
+
args: toJsonValue(tc.args)
|
|
6548
|
+
}))
|
|
6451
6549
|
});
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
const
|
|
6459
|
-
|
|
6550
|
+
setRevision(reserved.run.revision);
|
|
6551
|
+
const results2 = [];
|
|
6552
|
+
for (let i = 0; i < input.toolCalls.length; i++) {
|
|
6553
|
+
const toolCall = input.toolCalls[i];
|
|
6554
|
+
const durableTool = input.toolConfig.tools.find((c) => c.name === toolCall.name);
|
|
6555
|
+
const providerToolCallId = toolCall.id;
|
|
6556
|
+
const toolCallId = toolCallIds[i];
|
|
6557
|
+
const protocolFailure = (error) => ({
|
|
6558
|
+
toolCallId: providerToolCallId,
|
|
6559
|
+
toolName: toolCall.name,
|
|
6560
|
+
ok: false,
|
|
6561
|
+
content: null,
|
|
6562
|
+
error
|
|
6563
|
+
});
|
|
6564
|
+
if (!durableTool) {
|
|
6565
|
+
const failed = await this.owned.commitToolResult({
|
|
6566
|
+
runId: input.run.id,
|
|
6567
|
+
execution: input.execution,
|
|
6568
|
+
expectedRevision: revision,
|
|
6569
|
+
toolCallId,
|
|
6570
|
+
state: "failed",
|
|
6571
|
+
result: { ok: false, content: null, error: `Tool ${toolCall.name} is not available.` }
|
|
6572
|
+
});
|
|
6573
|
+
setRevision(failed.run.revision);
|
|
6574
|
+
results2.push(protocolFailure(`Tool ${toolCall.name} is not available.`));
|
|
6575
|
+
continue;
|
|
6576
|
+
}
|
|
6577
|
+
const decision = preDecisions[i] ?? { allow: true };
|
|
6578
|
+
if ("allow" in decision && !decision.allow) {
|
|
6579
|
+
const failed = await this.owned.commitToolResult({
|
|
6580
|
+
runId: input.run.id,
|
|
6581
|
+
execution: input.execution,
|
|
6582
|
+
expectedRevision: revision,
|
|
6583
|
+
toolCallId,
|
|
6584
|
+
state: "failed",
|
|
6585
|
+
result: { ok: false, content: null, error: decision.reason }
|
|
6586
|
+
});
|
|
6587
|
+
setRevision(failed.run.revision);
|
|
6588
|
+
results2.push(protocolFailure(decision.reason));
|
|
6589
|
+
continue;
|
|
6590
|
+
}
|
|
6591
|
+
let progressActive = false;
|
|
6592
|
+
const context = {
|
|
6593
|
+
agentId: input.run.agentId,
|
|
6594
|
+
runId: input.run.id,
|
|
6595
|
+
...input.agentMetadata === void 0 ? {} : { agentMetadata: input.agentMetadata },
|
|
6596
|
+
...input.run.metadata === void 0 ? {} : { runMetadata: input.run.metadata },
|
|
6597
|
+
toolCallId,
|
|
6598
|
+
reportProgress: (progress) => {
|
|
6599
|
+
const active = this.executions.get(input.run.id);
|
|
6600
|
+
if (!progressActive || this.closed || input.signal.aborted || active?.executionId !== input.execution.executionId || !isJsonValue(progress)) return;
|
|
6601
|
+
let copy;
|
|
6602
|
+
try {
|
|
6603
|
+
if (JSON.stringify(progress).length > 64 * 1024) return;
|
|
6604
|
+
copy = structuredClone(progress);
|
|
6605
|
+
} catch {
|
|
6606
|
+
return;
|
|
6607
|
+
}
|
|
6608
|
+
this.transientEvents.publish({
|
|
6609
|
+
kind: "tool_progress",
|
|
6610
|
+
durability: "transient",
|
|
6611
|
+
runId: input.run.id,
|
|
6612
|
+
executionId: input.execution.executionId,
|
|
6613
|
+
toolCallId,
|
|
6614
|
+
progress: copy
|
|
6615
|
+
});
|
|
6616
|
+
}
|
|
6617
|
+
};
|
|
6618
|
+
const started = await this.owned.startToolCall({
|
|
6619
|
+
runId: input.run.id,
|
|
6620
|
+
execution: input.execution,
|
|
6621
|
+
expectedRevision: revision,
|
|
6622
|
+
toolCallId
|
|
6623
|
+
});
|
|
6624
|
+
setRevision(started.run.revision);
|
|
6625
|
+
progressActive = true;
|
|
6626
|
+
try {
|
|
6627
|
+
let result = await durableTool.execute(toJsonValue(toolCall.args), context, input.signal);
|
|
6628
|
+
assertToolExecutionResult(result);
|
|
6629
|
+
if (input.toolConfig.afterToolCall) {
|
|
6630
|
+
result = await input.toolConfig.afterToolCall({
|
|
6631
|
+
tool: durableTool,
|
|
6632
|
+
result,
|
|
6633
|
+
context,
|
|
6634
|
+
signal: input.signal
|
|
6635
|
+
});
|
|
6636
|
+
}
|
|
6637
|
+
assertToolExecutionResult(result);
|
|
6638
|
+
result = await spillLargeToolResult(
|
|
6639
|
+
result,
|
|
6640
|
+
this.archiveDirFor(input.run.agentId),
|
|
6641
|
+
toolCall.name
|
|
6642
|
+
);
|
|
6643
|
+
const committed = await this.owned.commitToolResult({
|
|
6644
|
+
runId: input.run.id,
|
|
6645
|
+
execution: input.execution,
|
|
6646
|
+
expectedRevision: revision,
|
|
6647
|
+
toolCallId,
|
|
6648
|
+
state: result.ok ? "completed" : "failed",
|
|
6649
|
+
result
|
|
6650
|
+
});
|
|
6651
|
+
setRevision(committed.run.revision);
|
|
6652
|
+
results2.push({
|
|
6653
|
+
toolCallId: providerToolCallId,
|
|
6654
|
+
toolName: toolCall.name,
|
|
6655
|
+
...result
|
|
6656
|
+
});
|
|
6657
|
+
} catch (error) {
|
|
6658
|
+
const reason = error instanceof Error ? error.message : "Tool execution outcome is indeterminate.";
|
|
6659
|
+
const indeterminate = await this.owned.commitToolResult({
|
|
6660
|
+
runId: input.run.id,
|
|
6661
|
+
execution: input.execution,
|
|
6662
|
+
expectedRevision: revision,
|
|
6663
|
+
toolCallId,
|
|
6664
|
+
state: "indeterminate",
|
|
6665
|
+
reason,
|
|
6666
|
+
result: { ok: false, content: null, error: reason }
|
|
6667
|
+
});
|
|
6668
|
+
setRevision(indeterminate.run.revision);
|
|
6669
|
+
results2.push(protocolFailure(reason));
|
|
6670
|
+
} finally {
|
|
6671
|
+
progressActive = false;
|
|
6672
|
+
this.transientEvents.clearTool(input.run.id, toolCallId);
|
|
6673
|
+
}
|
|
6460
6674
|
}
|
|
6675
|
+
return { results: results2, revision };
|
|
6461
6676
|
}
|
|
6462
|
-
} catch (error) {
|
|
6463
|
-
const reason = error instanceof Error ? error.message : "Tool policy rejected the call.";
|
|
6464
|
-
const failed = await this.owned.commitToolResult({ runId: input.run.id, execution: input.execution, expectedRevision: revision, toolCallId, state: "failed", result: { ok: false, content: null, error: reason } });
|
|
6465
|
-
return { result: protocolFailure(reason), revision: failed.run.revision };
|
|
6466
6677
|
}
|
|
6467
|
-
const
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6678
|
+
const results = suspension ? [...suspension.completedResults] : [];
|
|
6679
|
+
const startIndex = suspension ? suspension.pendingIndex : 0;
|
|
6680
|
+
for (let index = startIndex; index < input.toolCalls.length; index += 1) {
|
|
6681
|
+
const toolCall = input.toolCalls[index];
|
|
6682
|
+
const durableTool = input.toolConfig.tools.find((candidate) => candidate.name === toolCall.name);
|
|
6683
|
+
const providerToolCallId = toolCall.id;
|
|
6684
|
+
const toolCallId = suspension && index === suspension.pendingIndex && suspension.toolCallId ? suspension.toolCallId : createId("tool");
|
|
6685
|
+
const protocolFailure = (error) => ({
|
|
6686
|
+
toolCallId: providerToolCallId,
|
|
6687
|
+
toolName: toolCall.name,
|
|
6688
|
+
ok: false,
|
|
6689
|
+
content: null,
|
|
6690
|
+
error
|
|
6691
|
+
});
|
|
6692
|
+
if (!durableTool) {
|
|
6693
|
+
const reserved2 = await this.owned.reserveToolCalls({
|
|
6694
|
+
runId: input.run.id,
|
|
6695
|
+
execution: input.execution,
|
|
6696
|
+
expectedRevision: revision,
|
|
6697
|
+
requestMessageId: createId("msg"),
|
|
6698
|
+
calls: [{
|
|
6699
|
+
toolCallId,
|
|
6700
|
+
providerToolCallId,
|
|
6701
|
+
name: toolCall.name,
|
|
6702
|
+
args: toJsonValue(toolCall.args)
|
|
6703
|
+
}]
|
|
6704
|
+
});
|
|
6705
|
+
setRevision(reserved2.run.revision);
|
|
6706
|
+
const failed = await this.owned.commitToolResult({
|
|
6707
|
+
runId: input.run.id,
|
|
6708
|
+
execution: input.execution,
|
|
6709
|
+
expectedRevision: revision,
|
|
6710
|
+
toolCallId,
|
|
6711
|
+
state: "failed",
|
|
6712
|
+
result: { ok: false, content: null, error: `Tool ${toolCall.name} is not available.` }
|
|
6713
|
+
});
|
|
6714
|
+
setRevision(failed.run.revision);
|
|
6715
|
+
results.push(protocolFailure(`Tool ${toolCall.name} is not available.`));
|
|
6716
|
+
continue;
|
|
6717
|
+
}
|
|
6718
|
+
let progressActive = false;
|
|
6719
|
+
const context = {
|
|
6720
|
+
agentId: input.run.agentId,
|
|
6721
|
+
runId: input.run.id,
|
|
6722
|
+
...input.agentMetadata === void 0 ? {} : { agentMetadata: input.agentMetadata },
|
|
6723
|
+
...input.run.metadata === void 0 ? {} : { runMetadata: input.run.metadata },
|
|
6724
|
+
toolCallId,
|
|
6725
|
+
reportProgress: (progress) => {
|
|
6726
|
+
const active = this.executions.get(input.run.id);
|
|
6727
|
+
if (!progressActive || this.closed || input.signal.aborted || active?.executionId !== input.execution.executionId || !isJsonValue(progress)) return;
|
|
6728
|
+
let copy;
|
|
6729
|
+
try {
|
|
6730
|
+
if (JSON.stringify(progress).length > 64 * 1024) return;
|
|
6731
|
+
copy = structuredClone(progress);
|
|
6732
|
+
} catch {
|
|
6733
|
+
return;
|
|
6734
|
+
}
|
|
6735
|
+
this.transientEvents.publish({
|
|
6736
|
+
kind: "tool_progress",
|
|
6737
|
+
durability: "transient",
|
|
6738
|
+
runId: input.run.id,
|
|
6739
|
+
executionId: input.execution.executionId,
|
|
6740
|
+
toolCallId,
|
|
6741
|
+
progress: copy
|
|
6742
|
+
});
|
|
6743
|
+
}
|
|
6484
6744
|
};
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6745
|
+
const answer = suspension && index === suspension.pendingIndex && suspension.interactionId ? input.driver?.answers().get(suspension.interactionId) : void 0;
|
|
6746
|
+
try {
|
|
6747
|
+
if (input.toolConfig.beforeToolCall) {
|
|
6748
|
+
const decision = await input.toolConfig.beforeToolCall({
|
|
6749
|
+
tool: durableTool,
|
|
6750
|
+
args: toJsonValue(toolCall.args),
|
|
6751
|
+
context,
|
|
6752
|
+
signal: input.signal,
|
|
6753
|
+
answer
|
|
6754
|
+
});
|
|
6755
|
+
if ("interaction" in decision && decision.interaction !== void 0) {
|
|
6756
|
+
if (!input.driver) {
|
|
6757
|
+
throw new Error("Tool call requested interaction but no interaction driver is active.");
|
|
6758
|
+
}
|
|
6759
|
+
const interactionRequest = input.driver.request({
|
|
6760
|
+
id: decision.interaction.id,
|
|
6761
|
+
kind: decision.interaction.kind,
|
|
6762
|
+
prompt: decision.interaction.prompt,
|
|
6763
|
+
payload: decision.interaction.payload,
|
|
6764
|
+
origin: "tool_call",
|
|
6765
|
+
toolCallId
|
|
6766
|
+
});
|
|
6767
|
+
input.driver.suspend({
|
|
6768
|
+
checkpoint: {
|
|
6769
|
+
kind: "tool_call_suspension",
|
|
6770
|
+
toolCalls: input.toolCalls,
|
|
6771
|
+
pendingIndex: index,
|
|
6772
|
+
toolCallId,
|
|
6773
|
+
interactionId: interactionRequest.id,
|
|
6774
|
+
completedResults: results
|
|
6775
|
+
}
|
|
6776
|
+
});
|
|
6777
|
+
}
|
|
6778
|
+
if ("allow" in decision && !decision.allow) {
|
|
6779
|
+
const reserved2 = await this.owned.reserveToolCalls({
|
|
6780
|
+
runId: input.run.id,
|
|
6781
|
+
execution: input.execution,
|
|
6782
|
+
expectedRevision: revision,
|
|
6783
|
+
requestMessageId: createId("msg"),
|
|
6784
|
+
calls: [{
|
|
6785
|
+
toolCallId,
|
|
6786
|
+
providerToolCallId,
|
|
6787
|
+
name: toolCall.name,
|
|
6788
|
+
args: toJsonValue(toolCall.args)
|
|
6789
|
+
}]
|
|
6790
|
+
});
|
|
6791
|
+
setRevision(reserved2.run.revision);
|
|
6792
|
+
const failed = await this.owned.commitToolResult({
|
|
6793
|
+
runId: input.run.id,
|
|
6794
|
+
execution: input.execution,
|
|
6795
|
+
expectedRevision: revision,
|
|
6796
|
+
toolCallId,
|
|
6797
|
+
state: "failed",
|
|
6798
|
+
result: { ok: false, content: null, error: decision.reason }
|
|
6799
|
+
});
|
|
6800
|
+
setRevision(failed.run.revision);
|
|
6801
|
+
results.push(protocolFailure(decision.reason));
|
|
6802
|
+
continue;
|
|
6803
|
+
}
|
|
6804
|
+
}
|
|
6805
|
+
} catch (error) {
|
|
6806
|
+
if (error instanceof PhaseInteractionBoundary || error instanceof PhaseInteractionCancelledError) {
|
|
6807
|
+
throw error;
|
|
6808
|
+
}
|
|
6809
|
+
const reason = error instanceof Error ? error.message : "Tool policy rejected the call.";
|
|
6810
|
+
const reserved2 = await this.owned.reserveToolCalls({
|
|
6811
|
+
runId: input.run.id,
|
|
6812
|
+
execution: input.execution,
|
|
6813
|
+
expectedRevision: revision,
|
|
6814
|
+
requestMessageId: createId("msg"),
|
|
6815
|
+
calls: [{
|
|
6816
|
+
toolCallId,
|
|
6817
|
+
providerToolCallId,
|
|
6818
|
+
name: toolCall.name,
|
|
6819
|
+
args: toJsonValue(toolCall.args)
|
|
6820
|
+
}]
|
|
6821
|
+
});
|
|
6822
|
+
setRevision(reserved2.run.revision);
|
|
6823
|
+
const failed = await this.owned.commitToolResult({
|
|
6824
|
+
runId: input.run.id,
|
|
6825
|
+
execution: input.execution,
|
|
6826
|
+
expectedRevision: revision,
|
|
6827
|
+
toolCallId,
|
|
6828
|
+
state: "failed",
|
|
6829
|
+
result: { ok: false, content: null, error: reason }
|
|
6830
|
+
});
|
|
6831
|
+
setRevision(failed.run.revision);
|
|
6832
|
+
results.push(protocolFailure(reason));
|
|
6833
|
+
continue;
|
|
6834
|
+
}
|
|
6835
|
+
const reserved = await this.owned.reserveToolCalls({
|
|
6836
|
+
runId: input.run.id,
|
|
6837
|
+
execution: input.execution,
|
|
6838
|
+
expectedRevision: revision,
|
|
6839
|
+
requestMessageId: createId("msg"),
|
|
6840
|
+
calls: [{
|
|
6841
|
+
toolCallId,
|
|
6842
|
+
providerToolCallId,
|
|
6843
|
+
name: toolCall.name,
|
|
6844
|
+
args: toJsonValue(toolCall.args)
|
|
6845
|
+
}]
|
|
6846
|
+
});
|
|
6847
|
+
setRevision(reserved.run.revision);
|
|
6848
|
+
const started = await this.owned.startToolCall({
|
|
6849
|
+
runId: input.run.id,
|
|
6850
|
+
execution: input.execution,
|
|
6851
|
+
expectedRevision: revision,
|
|
6852
|
+
toolCallId
|
|
6853
|
+
});
|
|
6854
|
+
setRevision(started.run.revision);
|
|
6855
|
+
progressActive = true;
|
|
6856
|
+
try {
|
|
6857
|
+
let result = await durableTool.execute(toJsonValue(toolCall.args), context, input.signal);
|
|
6858
|
+
assertToolExecutionResult(result);
|
|
6859
|
+
if (input.toolConfig.afterToolCall) {
|
|
6860
|
+
result = await input.toolConfig.afterToolCall({
|
|
6861
|
+
tool: durableTool,
|
|
6862
|
+
result,
|
|
6863
|
+
context,
|
|
6864
|
+
signal: input.signal
|
|
6865
|
+
});
|
|
6866
|
+
}
|
|
6867
|
+
assertToolExecutionResult(result);
|
|
6868
|
+
result = await spillLargeToolResult(
|
|
6869
|
+
result,
|
|
6870
|
+
this.archiveDirFor(input.run.agentId),
|
|
6871
|
+
toolCall.name
|
|
6872
|
+
);
|
|
6873
|
+
const committed = await this.owned.commitToolResult({
|
|
6874
|
+
runId: input.run.id,
|
|
6875
|
+
execution: input.execution,
|
|
6876
|
+
expectedRevision: revision,
|
|
6877
|
+
toolCallId,
|
|
6878
|
+
state: result.ok ? "completed" : "failed",
|
|
6879
|
+
result
|
|
6880
|
+
});
|
|
6881
|
+
setRevision(committed.run.revision);
|
|
6882
|
+
results.push({
|
|
6883
|
+
toolCallId: providerToolCallId,
|
|
6884
|
+
toolName: toolCall.name,
|
|
6885
|
+
...result
|
|
6886
|
+
});
|
|
6887
|
+
} catch (error) {
|
|
6888
|
+
const reason = error instanceof Error ? error.message : "Tool execution outcome is indeterminate.";
|
|
6889
|
+
const indeterminate = await this.owned.commitToolResult({
|
|
6890
|
+
runId: input.run.id,
|
|
6891
|
+
execution: input.execution,
|
|
6892
|
+
expectedRevision: revision,
|
|
6893
|
+
toolCallId,
|
|
6894
|
+
state: "indeterminate",
|
|
6895
|
+
reason,
|
|
6896
|
+
result: { ok: false, content: null, error: reason }
|
|
6897
|
+
});
|
|
6898
|
+
setRevision(indeterminate.run.revision);
|
|
6899
|
+
results.push(protocolFailure(reason));
|
|
6900
|
+
} finally {
|
|
6901
|
+
progressActive = false;
|
|
6902
|
+
this.transientEvents.clearTool(input.run.id, toolCallId);
|
|
6903
|
+
}
|
|
6492
6904
|
}
|
|
6905
|
+
input.driver?.clearCheckpoint();
|
|
6906
|
+
return { results, revision };
|
|
6493
6907
|
}
|
|
6494
6908
|
async requireAgent(agentId) {
|
|
6495
6909
|
const agent = (await this.owned.listAgents()).find((candidate) => candidate.id === agentId);
|
|
@@ -6668,7 +7082,7 @@ function boundaryFromSnapshot(snapshot) {
|
|
|
6668
7082
|
type: "input_required",
|
|
6669
7083
|
requestId: snapshot.request.id,
|
|
6670
7084
|
phase: snapshot.request.phase,
|
|
6671
|
-
prompt: snapshot.request.prompt,
|
|
7085
|
+
...snapshot.request.prompt ? { prompt: snapshot.request.prompt } : {},
|
|
6672
7086
|
interactions: snapshot.interactions,
|
|
6673
7087
|
answers: snapshot.answers
|
|
6674
7088
|
};
|
|
@@ -7243,24 +7657,28 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7243
7657
|
const requestId = input.requestId ?? createId("input");
|
|
7244
7658
|
const operationKey = `input_required:${requestId}`;
|
|
7245
7659
|
const interactions = input.interactions ?? [];
|
|
7246
|
-
const operationPayload = canonicalJson([input.runId, input.expectedRevision, input.phase, input.prompt.id, input.checkpoint, interactions, input.interactionAnswers ?? null]);
|
|
7660
|
+
const operationPayload = canonicalJson([input.runId, input.expectedRevision, input.phase, input.prompt ? input.prompt.id : null, input.checkpoint, interactions, input.interactionAnswers ?? null]);
|
|
7247
7661
|
const replay = this.replayOperation(operationKey, operationPayload);
|
|
7248
7662
|
if (replay) return clone(replay);
|
|
7249
7663
|
const run = this.requireRun(input.runId);
|
|
7250
7664
|
this.assertExecution(run, input.execution, input.expectedRevision);
|
|
7251
7665
|
this.assertState(run, ["running"]);
|
|
7252
7666
|
this.assertNoOpenTools(run);
|
|
7253
|
-
const
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7667
|
+
const isToolCallInteraction = interactions.length > 0 && interactions.some((interaction) => interaction.origin === "tool_call");
|
|
7668
|
+
let prompt;
|
|
7669
|
+
if (input.prompt && !isToolCallInteraction) {
|
|
7670
|
+
prompt = {
|
|
7671
|
+
...clone(input.prompt),
|
|
7672
|
+
sequenceWithinRun: this.nextMessageSequence(run.id)
|
|
7673
|
+
};
|
|
7674
|
+
this.messages.set(prompt.id, prompt);
|
|
7675
|
+
}
|
|
7257
7676
|
const request = {
|
|
7258
7677
|
id: requestId,
|
|
7259
7678
|
phase: input.phase,
|
|
7260
|
-
messageId: prompt.id,
|
|
7679
|
+
...prompt ? { messageId: prompt.id } : {},
|
|
7261
7680
|
createdAt: createTimestamp()
|
|
7262
7681
|
};
|
|
7263
|
-
this.messages.set(prompt.id, prompt);
|
|
7264
7682
|
run.state = "input_required";
|
|
7265
7683
|
run.checkpoint = clone(input.checkpoint);
|
|
7266
7684
|
run.openInputRequest = request;
|
|
@@ -7275,9 +7693,16 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7275
7693
|
delete run.execution;
|
|
7276
7694
|
run.revision += 1;
|
|
7277
7695
|
run.updatedAt = createTimestamp();
|
|
7278
|
-
|
|
7696
|
+
if (prompt) {
|
|
7697
|
+
this.appendMessage(run, prompt);
|
|
7698
|
+
}
|
|
7279
7699
|
this.appendTransition(run, "running", "input_required", request, prompt, void 0, void 0, void 0, interactions, run.interactionAnswers ?? {});
|
|
7280
|
-
const result = {
|
|
7700
|
+
const result = {
|
|
7701
|
+
run: clone(run),
|
|
7702
|
+
...prompt ? { prompt: clone(prompt) } : {},
|
|
7703
|
+
request: clone(request),
|
|
7704
|
+
interactions: clone(interactions)
|
|
7705
|
+
};
|
|
7281
7706
|
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
7282
7707
|
return result;
|
|
7283
7708
|
}
|
|
@@ -7330,28 +7755,33 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7330
7755
|
this.assertRevision(run, input.expectedRevision);
|
|
7331
7756
|
this.assertState(run, ["input_required"]);
|
|
7332
7757
|
const openInteractions = run.openInteractions ?? [];
|
|
7333
|
-
|
|
7758
|
+
const targetInteraction = openInteractions.find((interaction) => interaction.id === input.interactionId);
|
|
7759
|
+
if (!targetInteraction) {
|
|
7334
7760
|
throw new RuntimeError("input_request_conflict", { runId: run.id, requestId: input.interactionId, reason: "not_found" });
|
|
7335
7761
|
}
|
|
7336
|
-
const
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7762
|
+
const isToolCall = targetInteraction.origin === "tool_call";
|
|
7763
|
+
const now = createTimestamp();
|
|
7764
|
+
if (!isToolCall) {
|
|
7765
|
+
const message = {
|
|
7766
|
+
id: createId("msg"),
|
|
7767
|
+
agentId: run.agentId,
|
|
7768
|
+
runId: run.id,
|
|
7769
|
+
role: "user",
|
|
7770
|
+
content: typeof input.input === "string" ? input.input : JSON.stringify(input.input),
|
|
7771
|
+
metadata: { kind: "phase_interaction", interactionId: input.interactionId },
|
|
7772
|
+
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
7773
|
+
createdAt: now
|
|
7774
|
+
};
|
|
7775
|
+
this.messages.set(message.id, message);
|
|
7776
|
+
this.appendMessage(run, message);
|
|
7777
|
+
}
|
|
7347
7778
|
run.openInteractions = openInteractions.filter((interaction) => interaction.id !== input.interactionId);
|
|
7348
7779
|
run.interactionAnswers = {
|
|
7349
7780
|
...run.interactionAnswers ?? {},
|
|
7350
7781
|
[input.interactionId]: clone(input.input)
|
|
7351
7782
|
};
|
|
7352
7783
|
run.revision += 1;
|
|
7353
|
-
run.updatedAt =
|
|
7354
|
-
this.appendMessage(run, message);
|
|
7784
|
+
run.updatedAt = now;
|
|
7355
7785
|
if (run.openInteractions.length === 0) {
|
|
7356
7786
|
delete run.openInteractions;
|
|
7357
7787
|
delete run.openInputRequest;
|
|
@@ -7652,12 +8082,16 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7652
8082
|
return { ...base, state: run.state };
|
|
7653
8083
|
case "input_required": {
|
|
7654
8084
|
const request = run.openInputRequest;
|
|
7655
|
-
const prompt = request
|
|
7656
|
-
if (!prompt || prompt.role !== "assistant") throw new Error(`Run ${run.id} has an invalid input prompt.`);
|
|
8085
|
+
const prompt = request?.messageId ? this.messages.get(request.messageId) : void 0;
|
|
8086
|
+
if (request?.messageId && (!prompt || prompt.role !== "assistant")) throw new Error(`Run ${run.id} has an invalid input prompt.`);
|
|
7657
8087
|
return {
|
|
7658
8088
|
...base,
|
|
7659
8089
|
state: "input_required",
|
|
7660
|
-
request: {
|
|
8090
|
+
request: {
|
|
8091
|
+
id: request?.id ?? "",
|
|
8092
|
+
phase: request?.phase ?? "",
|
|
8093
|
+
...prompt ? { prompt: clone(prompt) } : {}
|
|
8094
|
+
},
|
|
7661
8095
|
interactions: clone(run.openInteractions ?? []),
|
|
7662
8096
|
answers: clone(run.interactionAnswers ?? {})
|
|
7663
8097
|
};
|
|
@@ -7979,7 +8413,13 @@ ${record.summary}`,
|
|
|
7979
8413
|
kind: "run_state_changed",
|
|
7980
8414
|
from,
|
|
7981
8415
|
to,
|
|
7982
|
-
...to === "input_required" && request
|
|
8416
|
+
...to === "input_required" && request ? {
|
|
8417
|
+
request: {
|
|
8418
|
+
id: request.id,
|
|
8419
|
+
phase: request.phase,
|
|
8420
|
+
...prompt ? { prompt } : {}
|
|
8421
|
+
}
|
|
8422
|
+
} : {},
|
|
7983
8423
|
...to === "input_required" ? { interactions: clone(interactions ?? []), answers: clone(answers ?? {}) } : {},
|
|
7984
8424
|
...to === "completed" && outcome ? { outcome } : {},
|
|
7985
8425
|
...to === "failed" && failure ? { failure } : {},
|