@yolk-sdk/agent 0.1.0-canary.104 → 0.1.0-canary.106

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.
Files changed (71) hide show
  1. package/dist/classification/errors.d.mts +1 -1
  2. package/dist/classification/errors.mjs +1 -1
  3. package/dist/client/transport.d.mts +1 -1
  4. package/dist/client/transport.mjs +1 -1
  5. package/dist/loop/error.d.mts +1 -1
  6. package/dist/loop/error.mjs +1 -1
  7. package/dist/loop/llm-event.d.mts +1 -1
  8. package/dist/loop/llm-event.mjs +1 -1
  9. package/dist/loop/run.d.mts +33 -0
  10. package/dist/loop/run.d.mts.map +1 -1
  11. package/dist/loop/run.mjs +97 -21
  12. package/dist/loop/run.mjs.map +1 -1
  13. package/dist/providers/anthropic/conformance/cases.mjs +1 -1
  14. package/dist/providers/anthropic-messages-provider-internal.mjs +1 -1
  15. package/dist/providers/anthropic-provider-internal.mjs +1 -1
  16. package/dist/providers/openai/conformance/responses-cases-internal.mjs +1 -1
  17. package/dist/providers/openai/provider.d.mts +1 -1
  18. package/dist/providers/openai/provider.mjs +1 -1
  19. package/dist/providers/openai/realtime/client-codec.mjs +1 -1
  20. package/dist/providers/openai/realtime/session-config.d.mts +1 -1
  21. package/dist/providers/openai/realtime/session-config.mjs +1 -1
  22. package/dist/providers/openai-responses-provider-internal.d.mts +1 -1
  23. package/dist/providers/openai-responses-provider-internal.mjs +1 -1
  24. package/dist/providers/opencode/conformance/cases.mjs +1 -1
  25. package/dist/providers/vercel/ai-gateway-classifier.mjs +1 -1
  26. package/dist/react/chat-actions.d.mts +20 -20
  27. package/dist/react/chat-actions.d.mts.map +1 -1
  28. package/dist/react/chat-items.d.mts +13 -13
  29. package/dist/react/chat-items.mjs +1 -1
  30. package/dist/react/chat-messages.d.mts +12 -12
  31. package/dist/react/chat-session-events.d.mts +1 -1
  32. package/dist/react/chat-session-events.mjs +1 -1
  33. package/dist/runtime/error.d.mts +1 -1
  34. package/dist/runtime/error.mjs +1 -1
  35. package/dist/runtime/run-runtime.d.mts.map +1 -1
  36. package/dist/runtime/run-runtime.mjs +29 -6
  37. package/dist/runtime/run-runtime.mjs.map +1 -1
  38. package/dist/runtime/session-event-store.d.mts +1 -1
  39. package/dist/runtime/session-event-store.mjs +1 -1
  40. package/dist/skillset/merge.d.mts +3 -3
  41. package/dist/tools/arguments.d.mts +1 -1
  42. package/dist/tools/arguments.mjs +1 -1
  43. package/dist/tools/background.d.mts +1 -1
  44. package/dist/tools/background.mjs +1 -1
  45. package/dist/tools/change-preview.mjs +1 -1
  46. package/dist/tools/input.d.mts +1 -1
  47. package/dist/tools/input.mjs +1 -1
  48. package/dist/tools/interaction.d.mts +1 -1
  49. package/dist/tools/interaction.mjs +1 -1
  50. package/dist/tools/ledger.d.mts +1 -1
  51. package/dist/tools/ledger.mjs +1 -1
  52. package/dist/tools/plan-review.mjs +1 -1
  53. package/dist/tools/plan-runtime.mjs +1 -1
  54. package/dist/tools/plan.d.mts +1 -1
  55. package/dist/tools/plan.mjs +1 -1
  56. package/dist/tools/registry.d.mts +1 -1
  57. package/dist/tools/registry.mjs +1 -1
  58. package/dist/tools/subagent.mjs +1 -1
  59. package/dist/voice/projection.d.mts +1 -1
  60. package/dist/voice/projection.mjs +1 -1
  61. package/dist/voice/protocol.d.mts +1 -1
  62. package/dist/voice/protocol.mjs +1 -1
  63. package/dist/voice/session-log.d.mts +1 -1
  64. package/dist/voice/session-log.mjs +1 -1
  65. package/dist/voice/speech.d.mts +1 -1
  66. package/dist/voice/speech.mjs +1 -1
  67. package/dist/voice/tool-bridge.mjs +1 -1
  68. package/dist/voice/tool-server.mjs +1 -1
  69. package/package.json +2 -2
  70. package/src/loop/run.ts +203 -35
  71. package/src/runtime/run-runtime.ts +42 -3
@@ -1,5 +1,5 @@
1
- import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
2
1
  import * as Schema from "effect/Schema";
2
+ import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
3
3
 
4
4
  //#region src/classification/errors.d.ts
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import { ClassificationUsage } from "./schema.mjs";
2
- import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
3
2
  import * as Schema from "effect/Schema";
3
+ import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
4
4
  //#region src/classification/errors.ts
5
5
  /**
6
6
  * Why an answer does not fit its question:
@@ -1,7 +1,7 @@
1
1
  import { AgentTranscript } from "./state.mjs";
2
2
  import { Cause, Effect, Layer, Stream } from "effect";
3
- import { AgentEvent, AgentReasoningEffort, HitlResponse, InputResponse, InteractionResponse, QuestionResponse, ToolApprovalResponse } from "@yolk-sdk/agent/protocol";
4
3
  import * as Schema$1 from "effect/Schema";
4
+ import { AgentEvent, AgentReasoningEffort, HitlResponse, InputResponse, InteractionResponse, QuestionResponse, ToolApprovalResponse } from "@yolk-sdk/agent/protocol";
5
5
  import { HttpClient } from "effect/http";
6
6
 
7
7
  //#region src/client/transport.d.ts
@@ -1,6 +1,6 @@
1
1
  import { Cause, Channel, Data, Effect, Exit, Match, Predicate, Pull, Queue, Ref, Result, Scope, Stream } from "effect";
2
- import { AgentEvent, AgentWebSocketServerMessage, InputResponseInput, InteractionResponseInput, QuestionResponseInput, ToolApprovalResponseInput, UserInput, isTerminalAgentEvent } from "@yolk-sdk/agent/protocol";
3
2
  import * as Schema$1 from "effect/Schema";
3
+ import { AgentEvent, AgentWebSocketServerMessage, InputResponseInput, InteractionResponseInput, QuestionResponseInput, ToolApprovalResponseInput, UserInput, isTerminalAgentEvent } from "@yolk-sdk/agent/protocol";
4
4
  import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/http";
5
5
  //#region src/client/transport.ts
6
6
  var AgentTransportError = class extends Schema$1.TaggedError()("AgentTransportError", {
@@ -1,5 +1,5 @@
1
- import { AgentError, ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
2
1
  import * as Schema from "effect/Schema";
2
+ import { AgentError, ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
3
3
 
4
4
  //#region src/loop/error.d.ts
5
5
  declare const LLMResponseIssue: Schema.Literal<"missing_done">;
@@ -1,6 +1,6 @@
1
1
  import { Match } from "effect";
2
- import { AgentError, ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
3
2
  import * as Schema$1 from "effect/Schema";
3
+ import { AgentError, ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
4
4
  //#region src/loop/error.ts
5
5
  const LLMResponseIssue = Schema$1.Literal("missing_done");
6
6
  var LLMError = class extends Schema$1.TaggedError()("LLMError", {
@@ -1,5 +1,5 @@
1
- import { AgentUsage, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
2
1
  import * as Schema from "effect/Schema";
2
+ import { AgentUsage, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
3
3
 
4
4
  //#region src/loop/llm-event.d.ts
5
5
  declare const LLMTextDelta_base: Schema.Class<LLMTextDelta, Schema.TaggedStruct<"TextDelta", {
@@ -1,5 +1,5 @@
1
- import { AgentUsage, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
2
1
  import * as Schema from "effect/Schema";
2
+ import { AgentUsage, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
3
3
  //#region src/loop/llm-event.ts
4
4
  var LLMTextDelta = class extends Schema.TaggedClass()("TextDelta", { text: Schema.String }) {};
5
5
  var LLMReasoningDelta = class extends Schema.TaggedClass()("ReasoningDelta", { text: Schema.String }) {};
@@ -23,6 +23,16 @@ type RunConfig = {
23
23
  * ResolvedToolSet.approvalPreviews): pending approval requests carry their preview.
24
24
  */
25
25
  readonly approvalPreviews?: Readonly<Record<string, ToolApprovalPreviewer>>;
26
+ /** The requests of the pause being resumed (`AgentAwaitingInput.requests`). An unanswered
27
+ * approval request listed here stays pending even when its tool no longer requires approval.
28
+ */
29
+ readonly awaitingRequests?: ReadonlyArray<HitlRequest>;
30
+ /** Whether the transcript's pending tool calls resume a pause. Default: they do when
31
+ * `hitlResponses`, `awaitingRequests` or an `interactionHost` is given (otherwise a new model
32
+ * turn runs). `true` resumes them even without responses; `false` prepares them as a fresh
33
+ * batch (current policy, no recorded approval responses consulted).
34
+ */
35
+ readonly resume?: boolean;
26
36
  readonly model: string;
27
37
  readonly reasoningEffort?: AgentReasoningEffort;
28
38
  readonly capabilities?: AgentModelCapabilities;
@@ -41,6 +51,18 @@ type ToolBatchConfig = {
41
51
  * ResolvedToolSet.approvalPreviews).
42
52
  */
43
53
  readonly approvalPreviews?: Readonly<Record<string, ToolApprovalPreviewer>>;
54
+ /** The requests of the pause being resumed (`AgentAwaitingInput.requests`). An unanswered
55
+ * approval request listed here stays pending even when its tool no longer requires approval.
56
+ * A batch with `awaitingRequests` or any `hitlResponses` is a resume (recorded answers win
57
+ * over the current policy); pass only the responses of the batch being resumed, or set
58
+ * `resume`.
59
+ */
60
+ readonly awaitingRequests?: ReadonlyArray<HitlRequest>;
61
+ /** Whether this batch resumes a pause (default: `awaitingRequests` given, or any
62
+ * `hitlResponses`). Set `false` for a new model turn's batch even when passing responses: a
63
+ * provider may reuse call ids, and only a resume lets recorded answers override the policy.
64
+ */
65
+ readonly resume?: boolean;
44
66
  readonly model?: string;
45
67
  readonly createdMessages?: ReadonlyArray<AgentMessage>;
46
68
  readonly turn?: number;
@@ -87,6 +109,17 @@ declare const prepareToolBatch: (input: {
87
109
  * is pending, at most 8 at a time.
88
110
  */
89
111
  readonly approvalPreviews?: Readonly<Record<string, ToolApprovalPreviewer>>;
112
+ /** The requests of the pause being resumed (`AgentAwaitingInput.requests`). An unanswered
113
+ * approval request listed here stays pending even when its tool no longer requires approval;
114
+ * a recorded answer always wins over the current policy.
115
+ */
116
+ readonly awaitingRequests?: ReadonlyArray<HitlRequest>;
117
+ /** Whether this batch resumes a pause (default: `awaitingRequests` given, or any `responses`).
118
+ * Only a resume consults recorded approvals and the pause; a fresh batch (a new model turn,
119
+ * whose provider may reuse call ids) never settles an approval from `responses`: the current
120
+ * policy decides, and a gated call asks again.
121
+ */
122
+ readonly resume?: boolean | undefined;
90
123
  }) => Effect.Effect<PreparedToolBatch, ToolError>;
91
124
  declare const runModelTurn: (config: ModelTurnConfig) => Stream.Stream<AgentEvent, AgentLoopError, ContextTransformer | LLMProvider | LoopConfig>;
92
125
  declare const runToolBatch: (config: ToolBatchConfig) => Stream.Stream<AgentEvent, AgentLoopError, LoopConfig | ToolExecutor>;
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.mts","names":[],"sources":["../../src/loop/run.ts"],"mappings":"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"}
1
+ {"version":3,"file":"run.d.mts","names":[],"sources":["../../src/loop/run.ts"],"mappings":"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"}
package/dist/loop/run.mjs CHANGED
@@ -8,9 +8,9 @@ import "../protocol/change-preview.mjs";
8
8
  import { truncateCodePoints } from "../protocol/bounded-text.mjs";
9
9
  import { validInteractionReceipt as validInteractionReceipt$1 } from "../protocol/tool.mjs";
10
10
  import { withToolArgumentsErrorHint } from "../protocol/tool-argument-hints.mjs";
11
- import { Clock, Data, Effect, Match, Option, Predicate, Ref, Stream } from "effect";
12
- import { AgentAwaitingInput, AgentEnd, AgentRetry, AgentStart, AssistantMessageEvent, InputRequest, InputRequested, InteractionRequest, InteractionRequested, InteractionResponse, LLMReasoningDelta, LLMStreamEnd, LLMStreamStart, LLMTextDelta, ProviderToolResult, QuestionRequest, QuestionRequested, QuestionToolParams, SubagentCompleted, SubagentStarted, ToolApprovalRequest, ToolApprovalRequested, ToolExecutionAccepted, ToolExecutionCompleted, ToolExecutionError, ToolExecutionStarted, ToolInputDelta, ToolInputEnd, ToolInputStart, ToolResult, TurnEnd, TurnStart, UsageUpdate, addAgentUsage, assistantHostToolCalls, contentParts, contentPreview, decodeBackgroundToolInput, formatInputResponseContent, formatQuestionResponseContent, hitlResponseEvent, inputRequestId, inputResponseStructuredContent, interactionRequestId, makeSubagentRunId, providerToolDefs, questionResponseStructuredContent, toolResultMessageFromResult, zeroAgentUsage } from "@yolk-sdk/agent/protocol";
11
+ import { Array as Array$1, Clock, Data, Effect, Match, Option, Predicate, Ref, Stream, Struct } from "effect";
13
12
  import * as Schema$1 from "effect/Schema";
13
+ import { AgentAwaitingInput, AgentEnd, AgentRetry, AgentStart, AssistantMessageEvent, InputRequest, InputRequested, InteractionRequest, InteractionRequested, InteractionResponse, LLMReasoningDelta, LLMStreamEnd, LLMStreamStart, LLMTextDelta, ProviderToolResult, QuestionRequest, QuestionRequested, QuestionToolParams, SubagentCompleted, SubagentStarted, ToolApprovalRequest, ToolApprovalRequested, ToolExecutionAccepted, ToolExecutionCompleted, ToolExecutionError, ToolExecutionStarted, ToolInputDelta, ToolInputEnd, ToolInputStart, ToolResult, TurnEnd, TurnStart, UsageUpdate, addAgentUsage, assistantHostToolCalls, contentParts, contentPreview, decodeBackgroundToolInput, formatInputResponseContent, formatQuestionResponseContent, hitlResponseEvent, inputRequestId, inputResponseStructuredContent, interactionRequestId, makeSubagentRunId, providerToolDefs, questionResponseStructuredContent, toolResultMessageFromResult, zeroAgentUsage } from "@yolk-sdk/agent/protocol";
14
14
  //#region src/loop/run.ts
15
15
  const objectField = (input, key) => {
16
16
  if (!Predicate.isObjectOrArray(input)) return;
@@ -198,6 +198,26 @@ const questionRequestId = (call) => `question:${call.id}`;
198
198
  const matchesApproval = (response, call, tools) => response.toolCallId === call.id && response.requestId === approvalRequestId(call, tools);
199
199
  const matchesQuestion = (response, call) => response.toolCallId === call.id && response.requestId === questionRequestId(call);
200
200
  const approvalResponseFor = (responses, call, tools) => responses.flatMap((response) => Predicate.isTagged(response, "ToolApprovalResponse") && matchesApproval(response, call, tools) ? [response] : [])[0];
201
+ /** Resume only: a denial for this call under another approval id of the same call (its tool's
202
+ * execution mode changed since the request) still denies. Approvals need the exact id.
203
+ */
204
+ const callDenialFor = (responses, call) => responses.flatMap((response) => Predicate.isTagged(response, "ToolApprovalResponse") && response.decision === "denied" && response.toolCallId === call.id && (response.requestId === `approval:${call.id}` || response.requestId.startsWith(`approval:${call.id}:`)) ? [response] : [])[0];
205
+ const outstandingApprovalFor = (awaiting, call) => awaiting.flatMap((request) => Predicate.isTagged(request, "ToolApprovalRequest") && request.toolCallId === call.id ? [request] : [])[0];
206
+ const canonicalParams = (params) => Schema$1.decodeUnknownOption(Schema$1.Json)(params).pipe(Option.map(canonicalJson));
207
+ const sameParams = (left, right) => {
208
+ const leftJson = canonicalParams(left);
209
+ const rightJson = canonicalParams(right);
210
+ return Option.isSome(leftJson) && Option.isSome(rightJson) && leftJson.value === rightJson.value;
211
+ };
212
+ /** The outstanding request, when it still describes this call exactly, without its preview
213
+ * (recomputed only while the tool has a previewer).
214
+ */
215
+ const reusableApprovalRequest = (outstanding, call, tools) => outstanding !== void 0 && outstanding.call.name === call.name && sameParams(outstanding.call.params, call.params) && outstanding.requestId === approvalRequestId(call, tools) ? ToolApprovalRequest.make({
216
+ requestId: outstanding.requestId,
217
+ toolCallId: outstanding.toolCallId,
218
+ call,
219
+ policy: outstanding.policy
220
+ }) : void 0;
201
221
  const questionResponseFor = (responses, call) => responses.flatMap((response) => Predicate.isTagged(response, "QuestionResponse") && matchesQuestion(response, call) ? [response] : [])[0];
202
222
  const toolApprovalRequest = (tools, call) => ToolApprovalRequest.make({
203
223
  requestId: approvalRequestId(call, tools),
@@ -262,7 +282,23 @@ const prepareQuestionCall = (call, index, responses) => Effect.gen(function* ()
262
282
  events: [QuestionRequested.make({ request })]
263
283
  });
264
284
  });
265
- const prepareApprovalCall = (tools, call, index, responses) => {
285
+ /**
286
+ * Approval of one call. A fresh batch (a new model turn) follows the current policy and never
287
+ * consults recorded answers: a provider may reuse call ids, so an earlier answer must never
288
+ * settle a new call (a gated call asks again). A resume batch binds the call to its pause
289
+ * instead, because hosts re-read tool policy at execution and the policy can change between the
290
+ * request and the answer:
291
+ *
292
+ * 1. A recorded answer wins: the first exact-match response settles the call (`denied`: the
293
+ * denied result, never executed; `approved`: executed). A denial for the same call under
294
+ * another approval id of that call (`approval:<id>` or `approval:<id>:…`) also denies.
295
+ * 2. Else an outstanding request from the resumed pause (`awaitingRequests`) stays pending: the
296
+ * same request while it still describes the call (name, canonical params, request id), else a
297
+ * fresh one.
298
+ * 3. Else the current policy decides: `manual` asks, anything else executes.
299
+ */
300
+ const prepareApprovalCall = (input) => {
301
+ const { tools, call, index, responses } = input;
266
302
  const envelope = backgroundEnvelope(tools, call);
267
303
  if (envelope !== void 0 && Option.isNone(envelope)) return PreparedToolCall.Result({
268
304
  index,
@@ -274,31 +310,37 @@ const prepareApprovalCall = (tools, call, index, responses) => {
274
310
  content: "Expected exactly execution (foreground or background) and arguments."
275
311
  })
276
312
  });
277
- if (!approvalRequired(tools, call)) return PreparedToolCall.Execute({
313
+ if (!input.resume && !approvalRequired(tools, call)) return PreparedToolCall.Execute({
278
314
  index,
279
315
  call,
280
316
  events: []
281
317
  });
282
- const request = toolApprovalRequest(tools, call);
283
- const response = approvalResponseFor(responses, call, tools);
284
- if (response === void 0) return PreparedToolCall.Pending({
285
- request,
286
- events: [ToolApprovalRequested.make({
287
- call,
288
- request
289
- })]
290
- });
291
- if (response.decision === "denied") return PreparedToolCall.Result({
318
+ const response = input.resume ? approvalResponseFor(responses, call, tools) ?? callDenialFor(responses, call) : void 0;
319
+ if (response?.decision === "denied") return PreparedToolCall.Result({
292
320
  index,
293
321
  call,
294
322
  result: deniedToolResult(call, response),
295
323
  events: [hitlResponseEvent(response)]
296
324
  });
297
- return PreparedToolCall.Execute({
325
+ if (response !== void 0) return PreparedToolCall.Execute({
298
326
  index,
299
327
  call,
300
328
  events: [hitlResponseEvent(response)]
301
329
  });
330
+ const outstanding = input.resume ? outstandingApprovalFor(input.awaiting, call) : void 0;
331
+ if (outstanding === void 0 && !approvalRequired(tools, call)) return PreparedToolCall.Execute({
332
+ index,
333
+ call,
334
+ events: []
335
+ });
336
+ const request = reusableApprovalRequest(outstanding, call, tools) ?? toolApprovalRequest(tools, call);
337
+ return PreparedToolCall.Pending({
338
+ request,
339
+ events: [ToolApprovalRequested.make({
340
+ call,
341
+ request
342
+ })]
343
+ });
302
344
  };
303
345
  /** Most approval change previews one batch computes at once. */
304
346
  const approvalPreviewConcurrency = 8;
@@ -533,7 +575,14 @@ const prepareModelToolCall = (input) => !input.receipts.has(input.call.id) && to
533
575
  content: "Question tool is unavailable",
534
576
  isError: true
535
577
  })
536
- })) : Effect.succeed(prepareApprovalCall(input.tools, input.call, input.index, input.responses));
578
+ })) : Effect.succeed(prepareApprovalCall({
579
+ tools: input.tools,
580
+ call: input.call,
581
+ index: input.index,
582
+ responses: input.responses,
583
+ awaiting: input.awaiting,
584
+ resume: input.resume
585
+ }));
537
586
  /** Preflight the entire batch before dispatching ANY call. Pending requests fence all execution.
538
587
  * Fails (`ToolError` `unavailable`) only when host storage an interaction call validator reads is
539
588
  * unavailable: the batch fails closed, like `loadInteractionReceipts`, and nothing runs.
@@ -542,12 +591,15 @@ const prepareToolBatch = (input) => Effect.gen(function* () {
542
591
  const handlers = input.inputs ?? {};
543
592
  const preflights = input.interactions ?? {};
544
593
  const previewers = input.approvalPreviews ?? {};
594
+ const resume = input.resume ?? (input.awaitingRequests !== void 0 || input.responses.length > 0);
545
595
  const planned = yield* Effect.forEach(input.calls, (call, index) => prepareToolCall({
546
596
  tools: input.tools,
547
597
  responses: input.responses,
548
598
  handlers,
549
599
  preflights,
550
600
  receipts: input.interactionReceipts ?? /* @__PURE__ */ new Map(),
601
+ awaiting: resume ? input.awaitingRequests ?? [] : [],
602
+ resume,
551
603
  call,
552
604
  index
553
605
  }));
@@ -574,10 +626,16 @@ const syntheticToolCompletionEvents = (prepared) => prepared.flatMap((item) => P
574
626
  result: item.result
575
627
  })] : []);
576
628
  const toolResultIds = (messages) => new Set(messages.flatMap((message) => Predicate.isTagged(message, "ToolResult") ? [message.toolCallId] : []));
577
- const pendingHostToolCalls = (messages) => {
578
- const completed = toolResultIds(messages);
579
- return messages.flatMap((message) => Predicate.isTagged(message, "Assistant") ? assistantHostToolCalls(message).filter((call) => !completed.has(call.id)) : []);
580
- };
629
+ /**
630
+ * Host tool calls without a result. A call is settled only by a result in its result window: the
631
+ * consecutive `ToolResult` messages right after its assistant message (the transcript rule of
632
+ * `danglingHostToolCalls`). A provider-reused call id is never settled by an earlier call's result.
633
+ */
634
+ const pendingHostToolCalls = (messages) => messages.flatMap((message, index) => {
635
+ if (!Predicate.isTagged(message, "Assistant")) return [];
636
+ const completed = toolResultIds(Array$1.takeWhile(messages.slice(index + 1), (later) => Predicate.isTagged(later, "ToolResult")));
637
+ return assistantHostToolCalls(message).filter((call) => !completed.has(call.id));
638
+ });
581
639
  const nonEmptyHitlRequests = (requests) => {
582
640
  const first = requests[0];
583
641
  return first === void 0 ? void 0 : [first, ...requests.slice(1)];
@@ -652,6 +710,7 @@ const makeAfterLlmStream = (input, llmEventsRef) => Stream.unwrap(Effect.gen(fun
652
710
  const toolResultMessages = yield* Ref.make([]);
653
711
  const prepared = yield* prepareToolBatch({
654
712
  tools: input.config.tools,
713
+ resume: false,
655
714
  responses: input.config.hitlResponses ?? [],
656
715
  calls: completion.toolCalls,
657
716
  inputs: input.config.inputs,
@@ -699,6 +758,7 @@ const makeAfterLlmStream = (input, llmEventsRef) => Stream.unwrap(Effect.gen(fun
699
758
  reason: completion.stopReason
700
759
  })).pipe(Stream.concat(makeTurnStream({
701
760
  ...input,
761
+ config: withoutConsumedAnswers(input.config),
702
762
  currentMessages: [
703
763
  ...input.currentMessages,
704
764
  assistantMessage,
@@ -753,6 +813,15 @@ const makeModelOnlyLlmStream = (input, llmEvents, result) => {
753
813
  return Ref.update(input.usage, (usage) => addAgentUsage(usage, event.usage)).pipe(Effect.flatMap(() => appendEvent));
754
814
  }), Stream.flatMap((event) => Predicate.isTagged(event, "AgentRetry") ? Stream.make(event) : isLlmEvent(event) ? Stream.fromIterable(toLlmEvent(event)) : Stream.make(event)), Stream.concat(makeModelOnlyAfterLlmStream(input, llmEvents)));
755
815
  };
816
+ /**
817
+ * The config of the model turns after a batch settled: answers and the pause are consumed by the
818
+ * batch they settled and never reach a later turn, where a provider may reuse a call id.
819
+ */
820
+ const withoutConsumedAnswers = (config) => Struct.omit(config, [
821
+ "hitlResponses",
822
+ "awaitingRequests",
823
+ "resume"
824
+ ]);
756
825
  const makeTurnStream = (input) => Stream.suspend(() => {
757
826
  if (input.turn > input.loopConfig.maxTurns) return Stream.fail(new AbortError({ reason: "max_turns" }));
758
827
  const llmStream = Stream.unwrap(Effect.gen(function* () {
@@ -765,15 +834,19 @@ const makeTurnStream = (input) => Stream.suspend(() => {
765
834
  });
766
835
  const makePendingToolResumeStream = (input) => Stream.unwrap(Effect.gen(function* () {
767
836
  const pendingCalls = pendingHostToolCalls(input.currentMessages);
768
- if (pendingCalls.length === 0 || (input.config.hitlResponses ?? []).length === 0 && input.config.interactionHost === void 0) return makeTurnStream(input);
837
+ const detected = (input.config.hitlResponses ?? []).length > 0 || (input.config.awaitingRequests ?? []).length > 0 || input.config.interactionHost !== void 0;
838
+ if (pendingCalls.length === 0 || input.config.resume === void 0 && !detected) return makeTurnStream(input);
839
+ const resume = input.config.resume ?? true;
769
840
  const toolResultMessages = yield* Ref.make([]);
770
841
  const prepared = yield* prepareToolBatch({
771
842
  tools: input.config.tools,
843
+ resume,
772
844
  responses: input.config.hitlResponses ?? [],
773
845
  calls: pendingCalls,
774
846
  inputs: input.config.inputs,
775
847
  interactions: input.config.interactions,
776
848
  approvalPreviews: input.config.approvalPreviews,
849
+ awaitingRequests: input.config.awaitingRequests,
777
850
  interactionReceipts: yield* loadInteractionReceipts(pendingCalls, input.config.interactionHost)
778
851
  });
779
852
  if (prepared.resultMessages.length > 0) yield* Ref.update(toolResultMessages, (results) => [...results, ...prepared.resultMessages]);
@@ -808,6 +881,7 @@ const makePendingToolResumeStream = (input) => Stream.unwrap(Effect.gen(function
808
881
  const orderedResults = orderedToolResultMessages(results);
809
882
  return Ref.update(input.createdMessages, (messages) => [...messages, ...orderedResults]).pipe(Effect.as(makeTurnStream({
810
883
  ...input,
884
+ config: withoutConsumedAnswers(input.config),
811
885
  currentMessages: [...input.currentMessages, ...orderedResults]
812
886
  })));
813
887
  })));
@@ -852,6 +926,8 @@ const runToolBatch = (config) => Stream.unwrap(Effect.gen(function* () {
852
926
  inputs: config.inputs,
853
927
  interactions: config.interactions,
854
928
  approvalPreviews: config.approvalPreviews,
929
+ awaitingRequests: config.awaitingRequests,
930
+ resume: config.resume,
855
931
  interactionReceipts: yield* loadInteractionReceipts(config.calls, config.interactionHost)
856
932
  });
857
933
  const hasPendingRequests = prepared.pendingRequests.length > 0;