agentfootprint 9.112.2 → 9.113.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/CHANGELOG.md +296 -0
- package/CLAUDE.md +1 -0
- package/dist/adapters/observability/audit.js +8 -0
- package/dist/adapters/observability/audit.js.map +1 -1
- package/dist/adapters/observability/otel.js +44 -2
- package/dist/adapters/observability/otel.js.map +1 -1
- package/dist/adapters/observability/xray.js +19 -0
- package/dist/adapters/observability/xray.js.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/core/Agent.js +11 -1
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/composeRequest.js +19 -11
- package/dist/core/agent/composeRequest.js.map +1 -1
- package/dist/core/agent/coverage/absent.js +163 -7
- package/dist/core/agent/coverage/absent.js.map +1 -1
- package/dist/core/agent/coverage/answer.js +3 -1
- package/dist/core/agent/coverage/answer.js.map +1 -1
- package/dist/core/agent/coverage/read.js +15 -11
- package/dist/core/agent/coverage/read.js.map +1 -1
- package/dist/core/agent/findings/ledger.js +27 -5
- package/dist/core/agent/findings/ledger.js.map +1 -1
- package/dist/core/agent/findings/offer.js +29 -9
- package/dist/core/agent/findings/offer.js.map +1 -1
- package/dist/core/agent/findings/serve.js +76 -7
- package/dist/core/agent/findings/serve.js.map +1 -1
- package/dist/core/agent/findings/types.js.map +1 -1
- package/dist/core/agent/findings/unsettled.js +276 -0
- package/dist/core/agent/findings/unsettled.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +30 -8
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/route.js +10 -2
- package/dist/core/agent/stages/route.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +247 -31
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/agent/stages/window.js +5 -2
- package/dist/core/agent/stages/window.js.map +1 -1
- package/dist/core/agent/toolResultCap.js +0 -0
- package/dist/core/agent/toolResultCap.js.map +1 -1
- package/dist/core/agent/window/ledgerFactPins.js +13 -2
- package/dist/core/agent/window/ledgerFactPins.js.map +1 -1
- package/dist/core/agent/window/toolNames.js +17 -2
- package/dist/core/agent/window/toolNames.js.map +1 -1
- package/dist/core/checkin.js +5 -1
- package/dist/core/checkin.js.map +1 -1
- package/dist/core/runCheckpoint.js +26 -2
- package/dist/core/runCheckpoint.js.map +1 -1
- package/dist/esm/adapters/observability/audit.d.ts +8 -0
- package/dist/esm/adapters/observability/audit.js +8 -0
- package/dist/esm/adapters/observability/audit.js.map +1 -1
- package/dist/esm/adapters/observability/otel.d.ts +17 -2
- package/dist/esm/adapters/observability/otel.js +44 -2
- package/dist/esm/adapters/observability/otel.js.map +1 -1
- package/dist/esm/adapters/observability/xray.d.ts +8 -0
- package/dist/esm/adapters/observability/xray.js +19 -0
- package/dist/esm/adapters/observability/xray.js.map +1 -1
- package/dist/esm/adapters/types.d.ts +49 -0
- package/dist/esm/adapters/types.js.map +1 -1
- package/dist/esm/core/Agent.js +11 -1
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/composeRequest.d.ts +10 -7
- package/dist/esm/core/agent/composeRequest.js +19 -11
- package/dist/esm/core/agent/composeRequest.js.map +1 -1
- package/dist/esm/core/agent/coverage/absent.d.ts +31 -4
- package/dist/esm/core/agent/coverage/absent.js +160 -6
- package/dist/esm/core/agent/coverage/absent.js.map +1 -1
- package/dist/esm/core/agent/coverage/answer.js +3 -1
- package/dist/esm/core/agent/coverage/answer.js.map +1 -1
- package/dist/esm/core/agent/coverage/index.d.ts +1 -1
- package/dist/esm/core/agent/coverage/read.d.ts +9 -1
- package/dist/esm/core/agent/coverage/read.js +16 -12
- package/dist/esm/core/agent/coverage/read.js.map +1 -1
- package/dist/esm/core/agent/coverage/types.d.ts +42 -0
- package/dist/esm/core/agent/findings/ledger.d.ts +23 -6
- package/dist/esm/core/agent/findings/ledger.js +27 -5
- package/dist/esm/core/agent/findings/ledger.js.map +1 -1
- package/dist/esm/core/agent/findings/offer.d.ts +23 -6
- package/dist/esm/core/agent/findings/offer.js +27 -8
- package/dist/esm/core/agent/findings/offer.js.map +1 -1
- package/dist/esm/core/agent/findings/serve.d.ts +19 -6
- package/dist/esm/core/agent/findings/serve.js +77 -8
- package/dist/esm/core/agent/findings/serve.js.map +1 -1
- package/dist/esm/core/agent/findings/types.d.ts +81 -1
- package/dist/esm/core/agent/findings/types.js.map +1 -1
- package/dist/esm/core/agent/findings/unsettled.d.ts +121 -0
- package/dist/esm/core/agent/findings/unsettled.js +271 -0
- package/dist/esm/core/agent/findings/unsettled.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.js +30 -8
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/route.js +10 -2
- package/dist/esm/core/agent/stages/route.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +90 -2
- package/dist/esm/core/agent/stages/toolCalls.js +244 -31
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/stages/window.js +5 -2
- package/dist/esm/core/agent/stages/window.js.map +1 -1
- package/dist/esm/core/agent/toolResultCap.d.ts +4 -1
- package/dist/esm/core/agent/toolResultCap.js +0 -0
- package/dist/esm/core/agent/toolResultCap.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +5 -0
- package/dist/esm/core/agent/window/ledgerFactPins.d.ts +10 -1
- package/dist/esm/core/agent/window/ledgerFactPins.js +13 -2
- package/dist/esm/core/agent/window/ledgerFactPins.js.map +1 -1
- package/dist/esm/core/agent/window/strategy.d.ts +2 -1
- package/dist/esm/core/agent/window/toolNames.d.ts +16 -1
- package/dist/esm/core/agent/window/toolNames.js +17 -2
- package/dist/esm/core/agent/window/toolNames.js.map +1 -1
- package/dist/esm/core/checkin.js +5 -1
- package/dist/esm/core/checkin.js.map +1 -1
- package/dist/esm/core/runCheckpoint.js +26 -2
- package/dist/esm/core/runCheckpoint.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +76 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/bug-report/transcript.d.ts +5 -0
- package/dist/esm/lib/bug-report/transcript.js +1 -0
- package/dist/esm/lib/bug-report/transcript.js.map +1 -1
- package/dist/esm/lib/semantics/projection.js +1 -0
- package/dist/esm/lib/semantics/projection.js.map +1 -1
- package/dist/esm/lib/time-travel/receipt.d.ts +4 -3
- package/dist/esm/lib/time-travel/receipt.js +4 -3
- package/dist/esm/lib/time-travel/receipt.js.map +1 -1
- package/dist/esm/lib/time-travel/servedView.js +13 -9
- package/dist/esm/lib/time-travel/servedView.js.map +1 -1
- package/dist/esm/lib/trace-toolpack/traceToolpack.js +130 -17
- package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/esm/memory/causal/evidenceRecorder.d.ts +2 -0
- package/dist/esm/memory/causal/evidenceRecorder.js +13 -0
- package/dist/esm/memory/causal/evidenceRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.d.ts +2 -0
- package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.js +11 -0
- package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/BoundaryRecorder.d.ts +10 -1
- package/dist/esm/recorders/observability/BoundaryRecorder.js +9 -1
- package/dist/esm/recorders/observability/BoundaryRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/FlowchartRecorder.d.ts +4 -1
- package/dist/esm/recorders/observability/FlowchartRecorder.js +13 -1
- package/dist/esm/recorders/observability/FlowchartRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/LiveStateRecorder.d.ts +2 -0
- package/dist/esm/recorders/observability/LiveStateRecorder.js +9 -0
- package/dist/esm/recorders/observability/LiveStateRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/RouteRecorder.js +5 -0
- package/dist/esm/recorders/observability/RouteRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/StatusRecorder.js +7 -0
- package/dist/esm/recorders/observability/StatusRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/ToolChoiceRecorder.js +5 -0
- package/dist/esm/recorders/observability/ToolChoiceRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +18 -2
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/esm/recorders/observability/status/statusTemplates.js +5 -0
- package/dist/esm/recorders/observability/status/statusTemplates.js.map +1 -1
- package/dist/esm/security/extractSequence.d.ts +36 -5
- package/dist/esm/security/extractSequence.js +99 -26
- package/dist/esm/security/extractSequence.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/bug-report/transcript.js +1 -0
- package/dist/lib/bug-report/transcript.js.map +1 -1
- package/dist/lib/semantics/projection.js +1 -0
- package/dist/lib/semantics/projection.js.map +1 -1
- package/dist/lib/time-travel/receipt.js +4 -3
- package/dist/lib/time-travel/receipt.js.map +1 -1
- package/dist/lib/time-travel/servedView.js +13 -9
- package/dist/lib/time-travel/servedView.js.map +1 -1
- package/dist/lib/trace-toolpack/traceToolpack.js +130 -17
- package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/memory/causal/evidenceRecorder.js +13 -0
- package/dist/memory/causal/evidenceRecorder.js.map +1 -1
- package/dist/recorders/observability/AgentThinkingTraceRecorder.js +11 -0
- package/dist/recorders/observability/AgentThinkingTraceRecorder.js.map +1 -1
- package/dist/recorders/observability/BoundaryRecorder.js +9 -1
- package/dist/recorders/observability/BoundaryRecorder.js.map +1 -1
- package/dist/recorders/observability/FlowchartRecorder.js +13 -1
- package/dist/recorders/observability/FlowchartRecorder.js.map +1 -1
- package/dist/recorders/observability/LiveStateRecorder.js +9 -0
- package/dist/recorders/observability/LiveStateRecorder.js.map +1 -1
- package/dist/recorders/observability/RouteRecorder.js +5 -0
- package/dist/recorders/observability/RouteRecorder.js.map +1 -1
- package/dist/recorders/observability/StatusRecorder.js +7 -0
- package/dist/recorders/observability/StatusRecorder.js.map +1 -1
- package/dist/recorders/observability/ToolChoiceRecorder.js +5 -0
- package/dist/recorders/observability/ToolChoiceRecorder.js.map +1 -1
- package/dist/recorders/observability/commentary/commentaryTemplates.js +18 -2
- package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/recorders/observability/status/statusTemplates.js +5 -0
- package/dist/recorders/observability/status/statusTemplates.js.map +1 -1
- package/dist/security/extractSequence.js +99 -26
- package/dist/security/extractSequence.js.map +1 -1
- package/dist/types/adapters/observability/audit.d.ts +8 -0
- package/dist/types/adapters/observability/audit.d.ts.map +1 -1
- package/dist/types/adapters/observability/otel.d.ts +17 -2
- package/dist/types/adapters/observability/otel.d.ts.map +1 -1
- package/dist/types/adapters/observability/xray.d.ts +8 -0
- package/dist/types/adapters/observability/xray.d.ts.map +1 -1
- package/dist/types/adapters/types.d.ts +49 -0
- package/dist/types/adapters/types.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/composeRequest.d.ts +10 -7
- package/dist/types/core/agent/composeRequest.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/absent.d.ts +31 -4
- package/dist/types/core/agent/coverage/absent.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/answer.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/index.d.ts +1 -1
- package/dist/types/core/agent/coverage/index.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/read.d.ts +9 -1
- package/dist/types/core/agent/coverage/read.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/types.d.ts +42 -0
- package/dist/types/core/agent/coverage/types.d.ts.map +1 -1
- package/dist/types/core/agent/findings/ledger.d.ts +23 -6
- package/dist/types/core/agent/findings/ledger.d.ts.map +1 -1
- package/dist/types/core/agent/findings/offer.d.ts +23 -6
- package/dist/types/core/agent/findings/offer.d.ts.map +1 -1
- package/dist/types/core/agent/findings/serve.d.ts +19 -6
- package/dist/types/core/agent/findings/serve.d.ts.map +1 -1
- package/dist/types/core/agent/findings/types.d.ts +81 -1
- package/dist/types/core/agent/findings/types.d.ts.map +1 -1
- package/dist/types/core/agent/findings/unsettled.d.ts +122 -0
- package/dist/types/core/agent/findings/unsettled.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/route.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +90 -2
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/stages/window.d.ts.map +1 -1
- package/dist/types/core/agent/toolResultCap.d.ts +4 -1
- package/dist/types/core/agent/toolResultCap.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +5 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/agent/window/ledgerFactPins.d.ts +10 -1
- package/dist/types/core/agent/window/ledgerFactPins.d.ts.map +1 -1
- package/dist/types/core/agent/window/strategy.d.ts +2 -1
- package/dist/types/core/agent/window/strategy.d.ts.map +1 -1
- package/dist/types/core/agent/window/toolNames.d.ts +16 -1
- package/dist/types/core/agent/window/toolNames.d.ts.map +1 -1
- package/dist/types/core/checkin.d.ts.map +1 -1
- package/dist/types/core/runCheckpoint.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +76 -1
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/bug-report/transcript.d.ts +5 -0
- package/dist/types/lib/bug-report/transcript.d.ts.map +1 -1
- package/dist/types/lib/semantics/projection.d.ts.map +1 -1
- package/dist/types/lib/time-travel/receipt.d.ts +4 -3
- package/dist/types/lib/time-travel/receipt.d.ts.map +1 -1
- package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
- package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
- package/dist/types/memory/causal/evidenceRecorder.d.ts +2 -0
- package/dist/types/memory/causal/evidenceRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/AgentThinkingTraceRecorder.d.ts +2 -0
- package/dist/types/recorders/observability/AgentThinkingTraceRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/BoundaryRecorder.d.ts +10 -1
- package/dist/types/recorders/observability/BoundaryRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/FlowchartRecorder.d.ts +4 -1
- package/dist/types/recorders/observability/FlowchartRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/LiveStateRecorder.d.ts +2 -0
- package/dist/types/recorders/observability/LiveStateRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/RouteRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/ToolChoiceRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
- package/dist/types/recorders/observability/status/statusTemplates.d.ts.map +1 -1
- package/dist/types/security/extractSequence.d.ts +36 -5
- package/dist/types/security/extractSequence.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* payload so footprintjs captures a checkpoint.
|
|
10
10
|
* • `resume` runs after the consumer supplies the human's answer.
|
|
11
11
|
* Treats that answer as the paused tool's result, appends to
|
|
12
|
-
* history, then continues the ReAct iteration loop.
|
|
12
|
+
* history, then continues the ReAct iteration loop. Calls the model
|
|
13
|
+
* batched AFTER the paused one were never dispatched; every resume
|
|
14
|
+
* path settles them with one fixed sentence each, a bracket and a
|
|
15
|
+
* count, and runs none of them ("── The batch settlement (9.113.0)").
|
|
13
16
|
*
|
|
14
17
|
* Dispatch resolution order (9.92.0 — DISPATCH FOLLOWS THE OFFER):
|
|
15
18
|
* 0. A name on THIS epoch's wire resolves to the party whose contract the
|
|
@@ -47,7 +50,7 @@
|
|
|
47
50
|
* activates that Skill (lifetime: turn).
|
|
48
51
|
*/
|
|
49
52
|
import type { PausableHandler, TypedScope } from 'footprintjs';
|
|
50
|
-
import type { PermissionChecker } from '../../../adapters/types.js';
|
|
53
|
+
import type { LLMMessage, PermissionChecker } from '../../../adapters/types.js';
|
|
51
54
|
import { type TurnRoute } from '../../../lib/injection-engine/routingPolicy.js';
|
|
52
55
|
import { type SkillTargetClass } from '../../../lib/injection-engine/skillGraph.js';
|
|
53
56
|
import { type SpokenIds } from '../../../lib/spokenIds.js';
|
|
@@ -67,6 +70,7 @@ import type { Classifier } from '../../../classify/types.js';
|
|
|
67
70
|
import type { ResolvedEvidenceGate } from '../evidence/types.js';
|
|
68
71
|
import { type ToolArgValidationMode } from '../toolArgsValidation.js';
|
|
69
72
|
import { type StepPlanFor } from '../../../lib/injection-engine/skillSteps.js';
|
|
73
|
+
import type { ProducedResult } from '../../../integrity/empty-lookup/check.js';
|
|
70
74
|
import type { ColumnCheckMode } from '../../../integrity/column-types/check.js';
|
|
71
75
|
import type { ToolResultColumns } from '../../../integrity/column-types/types.js';
|
|
72
76
|
import type { AgentState } from '../types.js';
|
|
@@ -668,4 +672,88 @@ export declare function composeReadSkillRefusal(args: {
|
|
|
668
672
|
* `test/security/skill-visibility.test.ts` — and the refusal printed it raw. */
|
|
669
673
|
readonly cursorWithheld?: boolean;
|
|
670
674
|
}): string;
|
|
675
|
+
/** One call the model proposed on an assistant turn (`LLMMessage.toolCalls`). */
|
|
676
|
+
export type ProposedCall = NonNullable<LLMMessage['toolCalls']>[number];
|
|
677
|
+
/**
|
|
678
|
+
* THE PAUSED BATCH (9.113.0) — the turn that proposed the paused call, and
|
|
679
|
+
* the calls on it that a pause left un-dispatched.
|
|
680
|
+
*
|
|
681
|
+
* The batch loop in `execute` dispatches a turn's calls one at a time, in the
|
|
682
|
+
* order the model proposed them, and every pause RETURNS from inside it: the
|
|
683
|
+
* checkpoint is taken on call k, and calls k+1..N were never reached — no
|
|
684
|
+
* gate judged them, no tool ran, no bracket opened. The resume paths used to
|
|
685
|
+
* answer call k and stop, so the next request carried N `tool_use` blocks and
|
|
686
|
+
* fewer `tool_result`s (a provider builds results only from `role: 'tool'`
|
|
687
|
+
* messages), and `iteration_end` counted one call.
|
|
688
|
+
*
|
|
689
|
+
* READ FROM `history`, NEVER CARRIED. Every pause site commits
|
|
690
|
+
* `scope.history = newHistory` before it returns, so the assistant turn that
|
|
691
|
+
* proposed the batch is on the checkpoint — and it is the very message a
|
|
692
|
+
* provider turns into the `tool_use` blocks the settlement must answer. It is
|
|
693
|
+
* therefore the one owner of "which calls does the next request carry", and
|
|
694
|
+
* the checkpoint gains no key: a checkpoint written before this release
|
|
695
|
+
* settles the same way. The window never removes the turn holding the paused
|
|
696
|
+
* call (`../window/turns.ts` · `refusalFor`, its `paused-tool` arm).
|
|
697
|
+
*
|
|
698
|
+
* The LATEST turn proposing the id is the paused one — the pause site commits
|
|
699
|
+
* that turn last, and a provider may reuse an id across turns. No such turn:
|
|
700
|
+
* `size: 0` and nothing to settle, the only answer a missing turn supports.
|
|
701
|
+
*
|
|
702
|
+
* A call after the paused one that history ALREADY answers — a `role: 'tool'`
|
|
703
|
+
* message for its id after that turn — is not un-dispatched, whoever wrote
|
|
704
|
+
* the answer. No library door writes one before the resume; a checkpoint is
|
|
705
|
+
* data, though, and an app may have patched results into a stored one.
|
|
706
|
+
* Settling such a call again would put a second result for its id on the
|
|
707
|
+
* next request, a shape a provider rejects.
|
|
708
|
+
*/
|
|
709
|
+
export declare function pausedBatchOf(history: readonly LLMMessage[], pausedToolCallId: string): {
|
|
710
|
+
readonly size: number;
|
|
711
|
+
readonly undispatched: readonly ProposedCall[];
|
|
712
|
+
};
|
|
713
|
+
/**
|
|
714
|
+
* What a call the paused batch never dispatched gets back (9.113.0) — ONE
|
|
715
|
+
* fixed sentence, on all four resume paths.
|
|
716
|
+
*
|
|
717
|
+
* Every clause is a past fact about one finished event, anchored by name: the
|
|
718
|
+
* call this result answers ("that call"), the call the run paused on (by id
|
|
719
|
+
* and by tool), and the resume. It names no destination. The design page's draft
|
|
720
|
+
* (`docs/design/2026-09-honest-answer-ledger.md`, § 5.5, "The batch
|
|
721
|
+
* settlement") ended "propose it again if still needed" — an instruction about a LATER call,
|
|
722
|
+
* re-read on every call after this one, the tool-less wrap-up included.
|
|
723
|
+
* Whether the call is still needed is the model's to judge from the facts;
|
|
724
|
+
* the surfaces recomposed per request (the tool list, the system prompt) own
|
|
725
|
+
* the present tense. Precedents: the 9.86.1 resumed-call refusal in this file
|
|
726
|
+
* ("was not executed on that call, and the resumed dispatch had no second
|
|
727
|
+
* checkpoint…") and `../selfCallNotice.ts` · `selfCallNotice`.
|
|
728
|
+
*
|
|
729
|
+
* "The run paused ON call …", never "call … paused the run": on two of the
|
|
730
|
+
* four doors the pause was a gate's, not the call's — a middleware's `ask`, a
|
|
731
|
+
* credential's consent need — and on all four the run paused AT that call.
|
|
732
|
+
*
|
|
733
|
+
* The sentence is for the MODEL. The same fact as data rides the settled
|
|
734
|
+
* message as `LLMMessage.notDispatched` and both of its brackets as
|
|
735
|
+
* `notDispatched` (`notDispatchedMarker`), and a reader asking "did this call
|
|
736
|
+
* run?" reads that — never this text.
|
|
737
|
+
*
|
|
738
|
+
* Exported for the producer registry (`test/modelFacingSurfaces.test.ts`).
|
|
739
|
+
*/
|
|
740
|
+
export declare function notDispatchedResult(toolName: string, paused: {
|
|
741
|
+
readonly toolName: string;
|
|
742
|
+
readonly toolCallId: string;
|
|
743
|
+
}): string;
|
|
744
|
+
/**
|
|
745
|
+
* The empty-lookup check's PRODUCER CORPUS (9.77.0) — every `role: 'tool'`
|
|
746
|
+
* RESULT in `history` from a tool the judged one names in `argumentsFrom`,
|
|
747
|
+
* as the run served it. The caller hands the history the judged call was
|
|
748
|
+
* served (the call itself is pushed after it), so a producer called earlier in
|
|
749
|
+
* the same batch is already in it — which is right: the model can only have
|
|
750
|
+
* taken a value from a result it had already been served.
|
|
751
|
+
*
|
|
752
|
+
* A message the batch settlement wrote (9.113.0) is no result: its ground
|
|
753
|
+
* never ran, so it produced nothing to take a value from. Read off the marker
|
|
754
|
+
* (`../findings/offer.ts` · `isResultMessage`), never the sentence.
|
|
755
|
+
*
|
|
756
|
+
* Exported for its unit test (`test/integrity/emptyLookup.test.ts`).
|
|
757
|
+
*/
|
|
758
|
+
export declare function producerCorpusOf(history: readonly LLMMessage[], argumentsFrom: readonly string[]): ProducedResult[];
|
|
671
759
|
export declare function buildToolCallsHandler(deps: ToolCallsHandlerDeps): PausableHandler<TypedScope<AgentState>>;
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* payload so footprintjs captures a checkpoint.
|
|
10
10
|
* • `resume` runs after the consumer supplies the human's answer.
|
|
11
11
|
* Treats that answer as the paused tool's result, appends to
|
|
12
|
-
* history, then continues the ReAct iteration loop.
|
|
12
|
+
* history, then continues the ReAct iteration loop. Calls the model
|
|
13
|
+
* batched AFTER the paused one were never dispatched; every resume
|
|
14
|
+
* path settles them with one fixed sentence each, a bracket and a
|
|
15
|
+
* count, and runs none of them ("── The batch settlement (9.113.0)").
|
|
13
16
|
*
|
|
14
17
|
* Dispatch resolution order (9.92.0 — DISPATCH FOLLOWS THE OFFER):
|
|
15
18
|
* 0. A name on THIS epoch's wire resolves to the party whose contract the
|
|
@@ -72,9 +75,10 @@ import { agentToolDispatch } from '../toolDispatch.js';
|
|
|
72
75
|
import { runToolChain, runToolAfterChain } from '../middleware/runChain.js';
|
|
73
76
|
import { recordDecisions } from '../middleware/ledger.js';
|
|
74
77
|
import { ownsReservedArgument, splitFindings } from '../findings/reserved.js';
|
|
75
|
-
import { knownResults } from '../findings/offer.js';
|
|
78
|
+
import { isResultMessage, knownResults } from '../findings/offer.js';
|
|
76
79
|
import { basisRowFrom, foldLedger, recordFindings, standingRowsFrom, } from '../findings/ledger.js';
|
|
77
80
|
import { contingentRowsOf, groundedArgumentValues, hasSetAsideStanding, } from '../findings/contingent.js';
|
|
81
|
+
import { withUnsettledRows } from '../findings/unsettled.js';
|
|
78
82
|
import { evidenceFromHistory, exemptFromRun, } from '../evidence/evidenceIndex.js';
|
|
79
83
|
import { noteRepeatedCall, repeatedCallLedgers } from '../repeatedCall.js';
|
|
80
84
|
import { formatToolArgIssues, validateToolArgs, } from '../toolArgsValidation.js';
|
|
@@ -448,6 +452,127 @@ function argsForPausedCall(scope, toolCallId, peel = false) {
|
|
|
448
452
|
function appendBatchResult(scope, entry) {
|
|
449
453
|
scope.toolResults = [...(scope.toolResults ?? []), entry];
|
|
450
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* THE PAUSED BATCH (9.113.0) — the turn that proposed the paused call, and
|
|
457
|
+
* the calls on it that a pause left un-dispatched.
|
|
458
|
+
*
|
|
459
|
+
* The batch loop in `execute` dispatches a turn's calls one at a time, in the
|
|
460
|
+
* order the model proposed them, and every pause RETURNS from inside it: the
|
|
461
|
+
* checkpoint is taken on call k, and calls k+1..N were never reached — no
|
|
462
|
+
* gate judged them, no tool ran, no bracket opened. The resume paths used to
|
|
463
|
+
* answer call k and stop, so the next request carried N `tool_use` blocks and
|
|
464
|
+
* fewer `tool_result`s (a provider builds results only from `role: 'tool'`
|
|
465
|
+
* messages), and `iteration_end` counted one call.
|
|
466
|
+
*
|
|
467
|
+
* READ FROM `history`, NEVER CARRIED. Every pause site commits
|
|
468
|
+
* `scope.history = newHistory` before it returns, so the assistant turn that
|
|
469
|
+
* proposed the batch is on the checkpoint — and it is the very message a
|
|
470
|
+
* provider turns into the `tool_use` blocks the settlement must answer. It is
|
|
471
|
+
* therefore the one owner of "which calls does the next request carry", and
|
|
472
|
+
* the checkpoint gains no key: a checkpoint written before this release
|
|
473
|
+
* settles the same way. The window never removes the turn holding the paused
|
|
474
|
+
* call (`../window/turns.ts` · `refusalFor`, its `paused-tool` arm).
|
|
475
|
+
*
|
|
476
|
+
* The LATEST turn proposing the id is the paused one — the pause site commits
|
|
477
|
+
* that turn last, and a provider may reuse an id across turns. No such turn:
|
|
478
|
+
* `size: 0` and nothing to settle, the only answer a missing turn supports.
|
|
479
|
+
*
|
|
480
|
+
* A call after the paused one that history ALREADY answers — a `role: 'tool'`
|
|
481
|
+
* message for its id after that turn — is not un-dispatched, whoever wrote
|
|
482
|
+
* the answer. No library door writes one before the resume; a checkpoint is
|
|
483
|
+
* data, though, and an app may have patched results into a stored one.
|
|
484
|
+
* Settling such a call again would put a second result for its id on the
|
|
485
|
+
* next request, a shape a provider rejects.
|
|
486
|
+
*/
|
|
487
|
+
export function pausedBatchOf(history, pausedToolCallId) {
|
|
488
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
489
|
+
const message = history[i];
|
|
490
|
+
if (message?.role !== 'assistant')
|
|
491
|
+
continue;
|
|
492
|
+
const proposed = message.toolCalls ?? [];
|
|
493
|
+
const at = proposed.findIndex((call) => call.id === pausedToolCallId);
|
|
494
|
+
if (at < 0)
|
|
495
|
+
continue;
|
|
496
|
+
const answered = new Set(history.slice(i + 1).flatMap((m) => (m.role === 'tool' ? [m.toolCallId] : [])));
|
|
497
|
+
return {
|
|
498
|
+
size: proposed.length,
|
|
499
|
+
undispatched: proposed.slice(at + 1).filter((call) => !answered.has(call.id)),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
return { size: 0, undispatched: [] };
|
|
503
|
+
}
|
|
504
|
+
// LENS · tool-result · persistent-history
|
|
505
|
+
// reads: toolName ← the un-dispatched call on the paused turn (`pausedBatchOf`); paused ← scope.pausedToolName + scope.pausedToolCallId, the checkpoint's own carriers
|
|
506
|
+
// law: may omit, never deny; every clause anchored to the call it was composed on; names no destination.
|
|
507
|
+
/**
|
|
508
|
+
* What a call the paused batch never dispatched gets back (9.113.0) — ONE
|
|
509
|
+
* fixed sentence, on all four resume paths.
|
|
510
|
+
*
|
|
511
|
+
* Every clause is a past fact about one finished event, anchored by name: the
|
|
512
|
+
* call this result answers ("that call"), the call the run paused on (by id
|
|
513
|
+
* and by tool), and the resume. It names no destination. The design page's draft
|
|
514
|
+
* (`docs/design/2026-09-honest-answer-ledger.md`, § 5.5, "The batch
|
|
515
|
+
* settlement") ended "propose it again if still needed" — an instruction about a LATER call,
|
|
516
|
+
* re-read on every call after this one, the tool-less wrap-up included.
|
|
517
|
+
* Whether the call is still needed is the model's to judge from the facts;
|
|
518
|
+
* the surfaces recomposed per request (the tool list, the system prompt) own
|
|
519
|
+
* the present tense. Precedents: the 9.86.1 resumed-call refusal in this file
|
|
520
|
+
* ("was not executed on that call, and the resumed dispatch had no second
|
|
521
|
+
* checkpoint…") and `../selfCallNotice.ts` · `selfCallNotice`.
|
|
522
|
+
*
|
|
523
|
+
* "The run paused ON call …", never "call … paused the run": on two of the
|
|
524
|
+
* four doors the pause was a gate's, not the call's — a middleware's `ask`, a
|
|
525
|
+
* credential's consent need — and on all four the run paused AT that call.
|
|
526
|
+
*
|
|
527
|
+
* The sentence is for the MODEL. The same fact as data rides the settled
|
|
528
|
+
* message as `LLMMessage.notDispatched` and both of its brackets as
|
|
529
|
+
* `notDispatched` (`notDispatchedMarker`), and a reader asking "did this call
|
|
530
|
+
* run?" reads that — never this text.
|
|
531
|
+
*
|
|
532
|
+
* Exported for the producer registry (`test/modelFacingSurfaces.test.ts`).
|
|
533
|
+
*/
|
|
534
|
+
export function notDispatchedResult(toolName, paused) {
|
|
535
|
+
return (`Tool '${toolName}' was not executed on that call: the run paused on call ` +
|
|
536
|
+
`'${paused.toolCallId}' to '${paused.toolName}', earlier in the same batch, and resumed ` +
|
|
537
|
+
`without executing the calls that followed it in that batch.`);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* The same fact as DATA (9.113.0) — the ONE composer of the settlement's
|
|
541
|
+
* marker, `{ pausedCall: { toolCallId, toolName } }`. The settled call's
|
|
542
|
+
* history message (`LLMMessage.notDispatched`) and both of its brackets
|
|
543
|
+
* (`ToolStartPayload.notDispatched`, `ToolEndPayload.notDispatched`) each take
|
|
544
|
+
* a fresh copy from here, so the three carriers can never disagree and no
|
|
545
|
+
* reader holds an object another reader holds.
|
|
546
|
+
*/
|
|
547
|
+
function notDispatchedMarker(paused) {
|
|
548
|
+
return { pausedCall: { toolCallId: paused.toolCallId, toolName: paused.toolName } };
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* The empty-lookup check's PRODUCER CORPUS (9.77.0) — every `role: 'tool'`
|
|
552
|
+
* RESULT in `history` from a tool the judged one names in `argumentsFrom`,
|
|
553
|
+
* as the run served it. The caller hands the history the judged call was
|
|
554
|
+
* served (the call itself is pushed after it), so a producer called earlier in
|
|
555
|
+
* the same batch is already in it — which is right: the model can only have
|
|
556
|
+
* taken a value from a result it had already been served.
|
|
557
|
+
*
|
|
558
|
+
* A message the batch settlement wrote (9.113.0) is no result: its ground
|
|
559
|
+
* never ran, so it produced nothing to take a value from. Read off the marker
|
|
560
|
+
* (`../findings/offer.ts` · `isResultMessage`), never the sentence.
|
|
561
|
+
*
|
|
562
|
+
* Exported for its unit test (`test/integrity/emptyLookup.test.ts`).
|
|
563
|
+
*/
|
|
564
|
+
export function producerCorpusOf(history, argumentsFrom) {
|
|
565
|
+
const produced = [];
|
|
566
|
+
for (const message of history) {
|
|
567
|
+
if (!isResultMessage(message))
|
|
568
|
+
continue;
|
|
569
|
+
const name = message.toolName;
|
|
570
|
+
if (typeof name !== 'string' || !argumentsFrom.includes(name))
|
|
571
|
+
continue;
|
|
572
|
+
produced.push({ toolName: name, text: message.content });
|
|
573
|
+
}
|
|
574
|
+
return produced;
|
|
575
|
+
}
|
|
451
576
|
/**
|
|
452
577
|
* The judge's turn on ONE landed result (9.104.0) — called at the five
|
|
453
578
|
* places a result joins the batch (the execute loop and the four resume
|
|
@@ -710,6 +835,13 @@ export function buildToolCallsHandler(deps) {
|
|
|
710
835
|
checked,
|
|
711
836
|
...(notChecked.length > 0 && { notChecked }),
|
|
712
837
|
...(cannotCover.length > 0 && { cannotCover }),
|
|
838
|
+
// The suggestion, as declared (9.113.0): the sentence, and the
|
|
839
|
+
// typed tool as a copy (`tryInsteadToolOfAbsence`). The EVENT only:
|
|
840
|
+
// it is advice about a call not yet made, not ground the answer
|
|
841
|
+
// stands on, so the tracked row below and the block composed from
|
|
842
|
+
// it never carry it.
|
|
843
|
+
...(facts.tryInstead !== undefined && { tryInstead: facts.tryInstead }),
|
|
844
|
+
...(facts.tryInsteadTool !== undefined && { tryInsteadTool: facts.tryInsteadTool }),
|
|
713
845
|
});
|
|
714
846
|
}
|
|
715
847
|
else {
|
|
@@ -777,20 +909,9 @@ export function buildToolCallsHandler(deps) {
|
|
|
777
909
|
ledger?.note('empty-lookup', 'write', 'not-applicable');
|
|
778
910
|
return;
|
|
779
911
|
}
|
|
780
|
-
// The producer corpus:
|
|
781
|
-
//
|
|
782
|
-
|
|
783
|
-
// in the same batch is already in it — which is right: the model can only
|
|
784
|
-
// have taken a value from a result it had already been served.
|
|
785
|
-
const produced = [];
|
|
786
|
-
for (const message of history) {
|
|
787
|
-
if (message.role !== 'tool')
|
|
788
|
-
continue;
|
|
789
|
-
const name = message.toolName;
|
|
790
|
-
if (typeof name !== 'string' || !argumentsFrom.includes(name))
|
|
791
|
-
continue;
|
|
792
|
-
produced.push({ toolName: name, text: message.content });
|
|
793
|
-
}
|
|
912
|
+
// The producer corpus: the earlier RESULTS from a tool THIS tool declares
|
|
913
|
+
// as one of its grounds — never a settled message (`producerCorpusOf`).
|
|
914
|
+
const produced = producerCorpusOf(history, argumentsFrom);
|
|
794
915
|
const { findings, disposition } = emptyLookupOf({
|
|
795
916
|
toolName: call.toolName,
|
|
796
917
|
toolCallId: call.toolCallId,
|
|
@@ -1999,6 +2120,68 @@ export function buildToolCallsHandler(deps) {
|
|
|
1999
2120
|
recordDecisions(scope, verdict.decisions);
|
|
2000
2121
|
return verdict.kind === 'deny' ? verdict.reason : verdict.result;
|
|
2001
2122
|
};
|
|
2123
|
+
const settleBatch = (answered, paused) => {
|
|
2124
|
+
const batch = pausedBatchOf(answered, paused.toolCallId);
|
|
2125
|
+
if (batch.undispatched.length === 0)
|
|
2126
|
+
return { history: answered, settled: [], size: batch.size, paused };
|
|
2127
|
+
const settled = batch.undispatched.map((call) => ({
|
|
2128
|
+
call,
|
|
2129
|
+
result: notDispatchedResult(call.name, paused),
|
|
2130
|
+
}));
|
|
2131
|
+
return {
|
|
2132
|
+
history: [
|
|
2133
|
+
...answered,
|
|
2134
|
+
...settled.map(({ call, result }) => ({
|
|
2135
|
+
role: 'tool',
|
|
2136
|
+
content: result,
|
|
2137
|
+
toolCallId: call.id,
|
|
2138
|
+
toolName: call.name,
|
|
2139
|
+
notDispatched: notDispatchedMarker(paused),
|
|
2140
|
+
})),
|
|
2141
|
+
],
|
|
2142
|
+
settled,
|
|
2143
|
+
size: batch.size,
|
|
2144
|
+
paused,
|
|
2145
|
+
};
|
|
2146
|
+
};
|
|
2147
|
+
/**
|
|
2148
|
+
* Each settled sibling's bracket, after the paused call's own `tool_end` —
|
|
2149
|
+
* the ONE site that stamps `notDispatched` on the stream: `tool_start` with
|
|
2150
|
+
* the args the call would have run with (the batch loop's peel, so
|
|
2151
|
+
* `_findings` never shows on a bracket), then `tool_end` carrying the
|
|
2152
|
+
* sentence and `durationMs: 0`. Both carry the marker the history message
|
|
2153
|
+
* carries (`notDispatchedMarker`), and no other bracket in the library ever
|
|
2154
|
+
* does.
|
|
2155
|
+
*
|
|
2156
|
+
* No `error`. It says a call FAILED — the tool threw, or the call itself
|
|
2157
|
+
* could not run as written (an args rejection, a `wants` block, a consent
|
|
2158
|
+
* the tool needed and did not get, an unknown name). A settled call did not
|
|
2159
|
+
* fail: the library decided not to dispatch it, as it does for a call a
|
|
2160
|
+
* permission policy denies or halts, and those brackets carry no `error`
|
|
2161
|
+
* either. Stamped here, it would register a tool failure in every
|
|
2162
|
+
* error-rate reader (a span status, a dashboard, an alert) on every
|
|
2163
|
+
* mid-batch pause, and say a second, false thing beside the marker, which
|
|
2164
|
+
* is the one owner of why there is no result (`src/core/README.md` · "One
|
|
2165
|
+
* owner of 'never dispatched' — in history and on the stream", the reader
|
|
2166
|
+
* table). No `status` either: that field is the TOOL's own word.
|
|
2167
|
+
*/
|
|
2168
|
+
const bracketSettled = (scope, settlement) => {
|
|
2169
|
+
for (const { call, result } of settlement.settled) {
|
|
2170
|
+
typedEmit(scope, 'agentfootprint.stream.tool_start', {
|
|
2171
|
+
toolName: call.name,
|
|
2172
|
+
toolCallId: call.id,
|
|
2173
|
+
args: peelCall(call).args,
|
|
2174
|
+
parallelCount: settlement.size,
|
|
2175
|
+
notDispatched: notDispatchedMarker(settlement.paused),
|
|
2176
|
+
});
|
|
2177
|
+
typedEmit(scope, 'agentfootprint.stream.tool_end', {
|
|
2178
|
+
toolCallId: call.id,
|
|
2179
|
+
result,
|
|
2180
|
+
durationMs: 0,
|
|
2181
|
+
notDispatched: notDispatchedMarker(settlement.paused),
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
};
|
|
2002
2185
|
// Resolve a tool's declared credential (declare-and-push) and execute it,
|
|
2003
2186
|
// emitting the same credential.* events as the main loop. Used by the
|
|
2004
2187
|
// check-in RESUME path when a human APPROVES — the tool never ran at pause
|
|
@@ -2324,15 +2507,24 @@ export function buildToolCallsHandler(deps) {
|
|
|
2324
2507
|
// came from (9.102.0; before, only the last batch resolved and an
|
|
2325
2508
|
// offered older id filed as `unknownId`). Read through the same
|
|
2326
2509
|
// per-call peel the loop below applies (a tool that owns the name
|
|
2327
|
-
// declares nothing).
|
|
2510
|
+
// declares nothing). A ruled-out standing whose result THIS door
|
|
2511
|
+
// recorded as an absence (`declareCoverage`'s rows on
|
|
2512
|
+
// `coverageDeclared`, never a second reading of a return) AND the
|
|
2513
|
+
// model was served as one (the served string — the door records the
|
|
2514
|
+
// return before the after-tool chain, the ceiling and placement act,
|
|
2515
|
+
// so a denied, refused or ticketed result files nothing) gets its
|
|
2516
|
+
// `unsettled-by-absence` row immediately after it, in the same write,
|
|
2517
|
+
// worded from what was served (9.113.0, `findings/unsettled.ts`; the
|
|
2518
|
+
// key is read only for such a standing); the standing rows pass
|
|
2519
|
+
// through untouched. Gated: unarmed, not one line runs.
|
|
2328
2520
|
if (deps.findings === true) {
|
|
2329
2521
|
const known = knownResults([...(scope.history ?? [])], [...(scope.toolResults ?? [])]);
|
|
2330
|
-
recordFindings(scope, toolCalls.flatMap((tc) => {
|
|
2522
|
+
recordFindings(scope, withUnsettledRows(toolCalls.flatMap((tc) => {
|
|
2331
2523
|
const declared = peelCall(tc).findings;
|
|
2332
2524
|
return declared?.previous !== undefined
|
|
2333
2525
|
? standingRowsFrom(known, declared, { toolCallId: tc.id }, iteration)
|
|
2334
2526
|
: [];
|
|
2335
|
-
}));
|
|
2527
|
+
}), known, () => [...(scope.coverageDeclared ?? [])]));
|
|
2336
2528
|
}
|
|
2337
2529
|
scope.toolResults = [];
|
|
2338
2530
|
// ── THE TOWERS AT DISPATCH (9.110.0) — one corpus per batch ────────
|
|
@@ -3904,10 +4096,13 @@ export function buildToolCallsHandler(deps) {
|
|
|
3904
4096
|
askResultStr += applyToolEffects(scope, { toolName, toolCallId, iteration }, resumeEnvelope, askTransition);
|
|
3905
4097
|
emitTransitionConflict(scope, iteration, askTransition);
|
|
3906
4098
|
}
|
|
3907
|
-
|
|
4099
|
+
// The batch settlement (9.113.0): the answered call's result, then the
|
|
4100
|
+
// siblings the pause left un-dispatched, each settled — never run.
|
|
4101
|
+
const askSettlement = settleBatch([
|
|
3908
4102
|
...scope.history,
|
|
3909
4103
|
{ role: 'tool', content: askResultStr, toolCallId, toolName },
|
|
3910
|
-
];
|
|
4104
|
+
], { toolName, toolCallId });
|
|
4105
|
+
const askHistory = askSettlement.history;
|
|
3911
4106
|
scope.history = askHistory;
|
|
3912
4107
|
scope.lastToolResult = {
|
|
3913
4108
|
toolName,
|
|
@@ -3928,10 +4123,14 @@ export function buildToolCallsHandler(deps) {
|
|
|
3928
4123
|
...(error === true && { error: true }),
|
|
3929
4124
|
...(resumeEnvelope?.status !== undefined && { status: resumeEnvelope.status }),
|
|
3930
4125
|
});
|
|
4126
|
+
bracketSettled(scope, askSettlement);
|
|
3931
4127
|
typedEmit(scope, 'agentfootprint.agent.iteration_end', {
|
|
3932
4128
|
turnIndex: 0,
|
|
3933
4129
|
iterIndex: iteration,
|
|
3934
|
-
|
|
4130
|
+
// The brackets THIS leg closed: the answered call's, plus one per
|
|
4131
|
+
// settled sibling. The calls before the paused one closed theirs on
|
|
4132
|
+
// the leg that paused, which ended in a checkpoint, not here.
|
|
4133
|
+
toolCallCount: 1 + askSettlement.settled.length,
|
|
3935
4134
|
history: askHistory,
|
|
3936
4135
|
});
|
|
3937
4136
|
scope.iteration = iteration + 1;
|
|
@@ -4048,10 +4247,12 @@ export function buildToolCallsHandler(deps) {
|
|
|
4048
4247
|
decisionResultStr += applyToolEffects(scope, { toolName, toolCallId, iteration }, resumeEnvelope, decisionTransition);
|
|
4049
4248
|
emitTransitionConflict(scope, iteration, decisionTransition);
|
|
4050
4249
|
}
|
|
4051
|
-
|
|
4250
|
+
// The batch settlement (9.113.0) — the ask path's twin.
|
|
4251
|
+
const decisionSettlement = settleBatch([
|
|
4052
4252
|
...scope.history,
|
|
4053
4253
|
{ role: 'tool', content: decisionResultStr, toolCallId, toolName },
|
|
4054
|
-
];
|
|
4254
|
+
], { toolName, toolCallId });
|
|
4255
|
+
const decisionHistory = decisionSettlement.history;
|
|
4055
4256
|
scope.history = decisionHistory;
|
|
4056
4257
|
// Drives `on-tool-return` triggers, same as the execute path.
|
|
4057
4258
|
scope.lastToolResult = {
|
|
@@ -4073,10 +4274,12 @@ export function buildToolCallsHandler(deps) {
|
|
|
4073
4274
|
...(error === true && { error: true }),
|
|
4074
4275
|
...(resumeEnvelope?.status !== undefined && { status: resumeEnvelope.status }),
|
|
4075
4276
|
});
|
|
4277
|
+
bracketSettled(scope, decisionSettlement);
|
|
4076
4278
|
typedEmit(scope, 'agentfootprint.agent.iteration_end', {
|
|
4077
4279
|
turnIndex: 0,
|
|
4078
4280
|
iterIndex: iteration,
|
|
4079
|
-
|
|
4281
|
+
// The brackets this leg closed — see the ask path's twin.
|
|
4282
|
+
toolCallCount: 1 + decisionSettlement.settled.length,
|
|
4080
4283
|
history: decisionHistory,
|
|
4081
4284
|
});
|
|
4082
4285
|
scope.iteration = iteration + 1;
|
|
@@ -4158,10 +4361,12 @@ export function buildToolCallsHandler(deps) {
|
|
|
4158
4361
|
consentResultStr += applyToolEffects(scope, { toolName, toolCallId, iteration }, consentEnvelope, consentTransition);
|
|
4159
4362
|
emitTransitionConflict(scope, iteration, consentTransition);
|
|
4160
4363
|
}
|
|
4161
|
-
|
|
4364
|
+
// The batch settlement (9.113.0) — the ask path's twin.
|
|
4365
|
+
const consentSettlement = settleBatch([
|
|
4162
4366
|
...scope.history,
|
|
4163
4367
|
{ role: 'tool', content: consentResultStr, toolCallId, toolName },
|
|
4164
|
-
];
|
|
4368
|
+
], { toolName, toolCallId });
|
|
4369
|
+
const consentHistory = consentSettlement.history;
|
|
4165
4370
|
scope.history = consentHistory;
|
|
4166
4371
|
scope.lastToolResult = {
|
|
4167
4372
|
toolName,
|
|
@@ -4182,10 +4387,12 @@ export function buildToolCallsHandler(deps) {
|
|
|
4182
4387
|
...(error === true && { error: true }),
|
|
4183
4388
|
...(consentEnvelope?.status !== undefined && { status: consentEnvelope.status }),
|
|
4184
4389
|
});
|
|
4390
|
+
bracketSettled(scope, consentSettlement);
|
|
4185
4391
|
typedEmit(scope, 'agentfootprint.agent.iteration_end', {
|
|
4186
4392
|
turnIndex: 0,
|
|
4187
4393
|
iterIndex: iteration,
|
|
4188
|
-
|
|
4394
|
+
// The brackets this leg closed — see the ask path's twin.
|
|
4395
|
+
toolCallCount: 1 + consentSettlement.settled.length,
|
|
4189
4396
|
history: consentHistory,
|
|
4190
4397
|
});
|
|
4191
4398
|
scope.iteration = iteration + 1;
|
|
@@ -4263,7 +4470,10 @@ export function buildToolCallsHandler(deps) {
|
|
|
4263
4470
|
if (deps.stepPlanFor) {
|
|
4264
4471
|
resultStr += applyStepReturn(scope, { toolName, toolCallId, iteration });
|
|
4265
4472
|
}
|
|
4266
|
-
|
|
4473
|
+
// The batch settlement (9.113.0) — the door a `requestInput` answer
|
|
4474
|
+
// comes back through, and the one most likely to meet a batch: a tool
|
|
4475
|
+
// that asks a person mid-lookup, batched with the lookups after it.
|
|
4476
|
+
const pauseSettlement = settleBatch([
|
|
4267
4477
|
...scope.history,
|
|
4268
4478
|
{
|
|
4269
4479
|
role: 'tool',
|
|
@@ -4271,7 +4481,8 @@ export function buildToolCallsHandler(deps) {
|
|
|
4271
4481
|
toolCallId,
|
|
4272
4482
|
toolName,
|
|
4273
4483
|
},
|
|
4274
|
-
];
|
|
4484
|
+
], { toolName, toolCallId });
|
|
4485
|
+
const newHistory = pauseSettlement.history;
|
|
4275
4486
|
scope.history = newHistory;
|
|
4276
4487
|
// Drives `on-tool-return` triggers, same as every other dispatch path.
|
|
4277
4488
|
scope.lastToolResult = { toolName, result: resultStr };
|
|
@@ -4287,10 +4498,12 @@ export function buildToolCallsHandler(deps) {
|
|
|
4287
4498
|
result: pauseCapped.result,
|
|
4288
4499
|
durationMs: Date.now() - startMs,
|
|
4289
4500
|
});
|
|
4501
|
+
bracketSettled(scope, pauseSettlement);
|
|
4290
4502
|
typedEmit(scope, 'agentfootprint.agent.iteration_end', {
|
|
4291
4503
|
turnIndex: 0,
|
|
4292
4504
|
iterIndex: iteration,
|
|
4293
|
-
|
|
4505
|
+
// The brackets this leg closed — see the ask path's twin.
|
|
4506
|
+
toolCallCount: 1 + pauseSettlement.settled.length,
|
|
4294
4507
|
// Plain local array — see the matching note on the execute path.
|
|
4295
4508
|
history: newHistory,
|
|
4296
4509
|
});
|