agentfootprint 9.113.0 → 9.114.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 +42 -0
- package/CLAUDE.md +1 -1
- package/dist/core/agent/coverage/read.js +3 -1
- package/dist/core/agent/coverage/read.js.map +1 -1
- package/dist/core/agent/findings/unsettled.js +11 -4
- package/dist/core/agent/findings/unsettled.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +118 -37
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/agent/toolDispatch.js +4 -1
- package/dist/core/agent/toolDispatch.js.map +1 -1
- package/dist/core/inputRequest.js +32 -2
- package/dist/core/inputRequest.js.map +1 -1
- package/dist/core/pause.js +13 -1
- package/dist/core/pause.js.map +1 -1
- package/dist/esm/core/agent/coverage/read.d.ts +3 -1
- package/dist/esm/core/agent/coverage/read.js +3 -1
- package/dist/esm/core/agent/coverage/read.js.map +1 -1
- package/dist/esm/core/agent/findings/unsettled.d.ts +11 -4
- package/dist/esm/core/agent/findings/unsettled.js +11 -4
- package/dist/esm/core/agent/findings/unsettled.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.js +118 -37
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/toolDispatch.d.ts +4 -1
- package/dist/esm/core/agent/toolDispatch.js +4 -1
- package/dist/esm/core/agent/toolDispatch.js.map +1 -1
- package/dist/esm/core/inputRequest.d.ts +20 -1
- package/dist/esm/core/inputRequest.js +32 -2
- package/dist/esm/core/inputRequest.js.map +1 -1
- package/dist/esm/core/pause.d.ts +13 -1
- package/dist/esm/core/pause.js +13 -1
- package/dist/esm/core/pause.js.map +1 -1
- package/dist/types/core/agent/coverage/read.d.ts +3 -1
- package/dist/types/core/agent/coverage/read.d.ts.map +1 -1
- package/dist/types/core/agent/findings/unsettled.d.ts +11 -4
- package/dist/types/core/agent/findings/unsettled.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/toolDispatch.d.ts +4 -1
- package/dist/types/core/agent/toolDispatch.d.ts.map +1 -1
- package/dist/types/core/inputRequest.d.ts +20 -1
- package/dist/types/core/inputRequest.d.ts.map +1 -1
- package/dist/types/core/pause.d.ts +13 -1
- package/dist/types/core/pause.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,48 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [9.114.0] - 2026-09-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`absence` on a `requestInput` declaration
|
|
13
|
+
(`InputRequestDeclaration.absence`)** — a lookup that searched, found
|
|
14
|
+
nothing, and then asks the person about the miss can now say what it looked
|
|
15
|
+
at: pass the envelope `absent()` returns, as in `requestInput({ id,
|
|
16
|
+
question, fields, absence: absent({ what, checked }) })`. Until now a lookup
|
|
17
|
+
that paused left no record of the miss it was asking about — no
|
|
18
|
+
`agentfootprint.tools.absent` event and no `coverageDeclared` row, because
|
|
19
|
+
both are filed when a tool RETURNS its result, and a pause returns nothing.
|
|
20
|
+
The library now files them when the request is raised, before the run
|
|
21
|
+
pauses: the same event payload and the same row, byte for byte, that the
|
|
22
|
+
same `absent(…)` files when a tool returns it; and when the tool declares
|
|
23
|
+
`argumentsFrom` under `noticeEmptyLookups`, the empty-lookup check reads the
|
|
24
|
+
miss too. Nothing that judges a SERVED result applies at the raise, because
|
|
25
|
+
nothing is served for the paused call: not the tool's `resultCeiling`, not
|
|
26
|
+
the column-type contract, not the evidence corpus. The paused call is
|
|
27
|
+
answered by the person, not delivered an `'absent'` status, so an
|
|
28
|
+
`onToolStatus` route keyed on `'absent'` does not fire for it. The rows are
|
|
29
|
+
filed once — nothing on resume reads the field. It is not part of the
|
|
30
|
+
pending question (`awaitingInput`) or of what the model is served for the
|
|
31
|
+
paused call, so the question states the miss only if your `question` says
|
|
32
|
+
so; under `.limitsTravelWithTheAnswer()` the final answer's limits block
|
|
33
|
+
carries it, as it does a returned miss. A value the absence recognizer
|
|
34
|
+
cannot read is refused when `requestInput` is called (`InputRequestError`,
|
|
35
|
+
naming `absent()`), and the call errors instead of pausing; `absence: null`
|
|
36
|
+
is the field omitted. An envelope built by hand whose lists cannot be read
|
|
37
|
+
(such as `checked: [null]`) errors the call at the raise with the same
|
|
38
|
+
message the value would give if returned: the run goes on, nothing pauses
|
|
39
|
+
and nothing is filed. A lookup reached through another tool
|
|
40
|
+
(`ctx.tools.call`, a runbook procedure, a `flowchartAsTool` stage) pauses
|
|
41
|
+
that outer call, so its miss is filed under the outer tool and call id. A
|
|
42
|
+
lookup a person approved before it ran (a `checkIn`, an approved middleware
|
|
43
|
+
`ask`, granted interactive consent) cannot pause at all — its raise is
|
|
44
|
+
refused as an error, as before, and its miss is not filed. A request without
|
|
45
|
+
`absence` records exactly what it did before, and a malformed hand-raised
|
|
46
|
+
one (`pauseHere`/`askHuman`) leaves the committed record it always left,
|
|
47
|
+
whether or not it carries `absence` (its error text can differ where 9.113.0
|
|
48
|
+
stopped first at the then-unknown key).
|
|
49
|
+
|
|
8
50
|
## [9.113.0] - 2026-09-23
|
|
9
51
|
|
|
10
52
|
### Added
|
package/CLAUDE.md
CHANGED
|
@@ -152,7 +152,7 @@ Traps: `src/observability/` holds the finder IMPLEMENTATIONS (canonical home; `d
|
|
|
152
152
|
- **Code staging-in (9.26.0)**: `CodeSession.stageInputs?(inputs) → StagedCodeInput[]` — OPTIONAL, feature-detected via `canStageCodeInputs`, and its contract is TWO promises: the payloads are readable at the returned paths, AND every later `execute` exposes the manifest as `STAGED_INPUTS_ENV` (`AF_STAGED_INPUTS`, `name → path`). `CodeInput.name` is the MANIFEST KEY (the wants arg name, so a static description can name it) and `fileName` is the on-disk name — separate fields so the two cannot drift. `codeRunnerTool({ wants })` composes the schema properties + the description clause and refuses BY NAME on a non-staging runner. Implemented by localCodeRunner only.
|
|
153
153
|
- **Repeated-call nudge (9.26.0)**: `core/agent/repeatedCall.ts` (pure `noteRepeatedCall` + `repeatedCallLedgers()`) + the ONE batch-loop hook in toolCalls. Fingerprints (FNV-1a) of stable-stringified args and the tool's OWN delivered result — never values. **The counters are NOT tracked state**: they live in a bounded run-keyed map held by `buildToolCallsHandler` and keyed by `deps.currentRun().runId`, so a turn that repeats nothing is byte-identical in state, commit log, narrative and recordings (a scope key would have changed all four for every agent that merely upgraded); the repeat itself rides `agentfootprint.tools.repeated_call`, the emit channel per-attempt facts belong on. A resume mints a new runId ⇒ counting restarts. Fires at the SECOND identical landing, once. `AgentOptions.repeatedCallNudge: false` disables (threaded value-conditionally; ON is the default). Deliberately NOT applied on the pause-resume dispatch paths.
|
|
154
154
|
- **Evidence gate (9.35.0)** — `.namesAndNumbersFromEvidence({ posture, shapes, exempt, minDigits })`: every name/number in the final answer must appear in a `role:'tool'` result. Postures reuse the routing VOCABULARY (`assist`|`guard`|`rails`) as a SEPARATE option — routing authority ≠ evidence discipline, and overloading `skillGraphCascade.strictness` would deny "strict routing, loose evidence". Wiring is the stepNudge blast radius verbatim: `ResolvedEvidenceGate` (builder-resolved, refusals at the CALL SITE) → Agent ctor trailing param → `buildRouteDeciderStage`'s 4th arg (`judgeEvidence` runs LAST of the three judges — schema > steps > evidence — and NOT on a denied or schema-exhausted answer) → `evidenceRecheckStage` branch (`{loopTo}`, mounted only for a revising posture) → `STAGE_IDS.EVIDENCE_RECHECK` + BOUNDARY_LOCAL_IDS + milestoneFor. TWO deps flags, and the second is the one a reader misses: `evidenceRecheckStage` (branch) AND `hasEvidenceGate` (bubbles `systemPromptInjections` out of sf-llm-call in the GROUPED chart — without it the gate flags the app's own prompt). Per-check facts ride `agentfootprint.agent.evidence_checked` (emit channel); only the terminal verdict is committed (`unsupportedValues`), because the boundary raises off it. `UnsupportedValuesError` joins the TERMINAL-typed-error list in `run()`'s catch (a verdict is not a crash — no retry handle for a wall). **Grounded numbers (9.75.0)** rides the SAME dial: `nudge: true` arms the staged-refs nudge — `toolWantsOf` harvests `Tool.wants` beside the `toolGrounding` harvest in `Agent.buildChart` (same ToolProvider blindness), callLLM appends ONE request-only late line when a placed ticket's kind matches a SERVED `wants` tool (judged on `registeredToolSchemas`, so wrap-up's withheld surface arms nothing; history untouched ⇒ never in the exempt corpus), recorded as `agent.grounding_nudged`; and the recheck names the same refs+spender whenever a `wants` tool exists, NOT gated on `nudge`. Since 9.96.0 `evidence/recovery.ts` · `buildEvidenceRecovery` composes request-only system guidance; `evidenceRecoveryPiece` carries it into the next request without synthetic conversation turns. Optional `recoveryInstruction` adds bounded synchronous guidance; `buildEvidenceCorrection` remains a legacy compatibility helper. Token extraction, exemptions and the single-revision budget are unchanged; this is not semantic validation or streaming draft suppression.
|
|
155
|
-
- **Coverage primitives (this release)** — `absent()` / `coverage()`, both copied from FIELD USE. THE argument is the direction of the error: a *nothing-found* misread as an *outage* costs an investigation, an *outage* misread as *nothing-found* declares a system healthy that was never checked — so the two must not share a shape. Blast radius, and it is the `resultCeiling` radius verbatim: `readCoverageResult` called by `declareCoverage` at BOTH execute boundaries in toolCalls.ts (batch loop + `resolveCredentialAndExecute`), on the UNWRAPPED content and BEFORE the ceiling. FOUR downstream changes and no more: (1) `ToolResultStatus` gained a SEVENTH word `'absent'` — routable by `onToolStatus`, because folding it into `'failure'` is the confusion itself and into `'success'` leaves nothing to route on; (2) two events (`tools.absent`, `tools.coverage_declared`); (3) tracked `AgentState.coverageDeclared` — a limit is a fact about the ANSWER, not about an attempt, which is why it is state and the repeated-call counters are not; (4) the evidence corpus indexes an absence's COVERAGE ONLY (`coverage/evidence.ts` — a failed lookup is the cheapest laundering machine, and `absent()` would have made it cheaper: this is frames.ts's argument on the tool side). Deliberately UNCHANGED: no `error: true`, no retry, no refusal, no gate flag. Survival into the answer is `.limitsTravelWithTheAnswer()` → `attachCoverageLimits` dep → BOTH builders swap the final branch's first stage for `prepareFinalWithLimitsStage` (same id, same position). It APPENDS rather than judges: a check for "did the model state its limits?" needs a second model to decide what counts, which is what evidence/README.md forbids.
|
|
155
|
+
- **Coverage primitives (this release)** — `absent()` / `coverage()`, both copied from FIELD USE. THE argument is the direction of the error: a *nothing-found* misread as an *outage* costs an investigation, an *outage* misread as *nothing-found* declares a system healthy that was never checked — so the two must not share a shape. Blast radius, and it is the `resultCeiling` radius verbatim: `readCoverageResult` called by `declareCoverage` at BOTH execute boundaries in toolCalls.ts (batch loop + `resolveCredentialAndExecute`), on the UNWRAPPED content and BEFORE the ceiling — and (9.114.0) at the RAISE site, `declareRaisedAbsence`, which files a `requestInput({ absence })` miss before the pause, once, never on resume. FOUR downstream changes and no more: (1) `ToolResultStatus` gained a SEVENTH word `'absent'` — routable by `onToolStatus`, because folding it into `'failure'` is the confusion itself and into `'success'` leaves nothing to route on; (2) two events (`tools.absent`, `tools.coverage_declared`); (3) tracked `AgentState.coverageDeclared` — a limit is a fact about the ANSWER, not about an attempt, which is why it is state and the repeated-call counters are not; (4) the evidence corpus indexes an absence's COVERAGE ONLY (`coverage/evidence.ts` — a failed lookup is the cheapest laundering machine, and `absent()` would have made it cheaper: this is frames.ts's argument on the tool side). Deliberately UNCHANGED: no `error: true`, no retry, no refusal, no gate flag. Survival into the answer is `.limitsTravelWithTheAnswer()` → `attachCoverageLimits` dep → BOTH builders swap the final branch's first stage for `prepareFinalWithLimitsStage` (same id, same position). It APPENDS rather than judges: a check for "did the model state its limits?" needs a second model to decide what counts, which is what evidence/README.md forbids.
|
|
156
156
|
- **Out-of-budget wrap-up (9.56.0)** — `wrapUpAtMaxIterations` (AgentOptions, default ON, `repeatedCallNudge`'s opt-out grammar): the FOURTH Route branch, and the SchemaRetry mechanism verbatim — `STAGE_IDS.WRAP_UP` + same `{loopTo}`, so the last call is one ordinary turn with its own `iteration_start`/`llm_start`/`cost.tick`. Two things are its own: (1) the tools are WITHHELD at REQUEST ASSEMBLY in callLLM (`scope.wrapUpAsked`, the `schemaTool` seam's mirror — the schema tool still rides, so an output contract survives), which is what makes the call terminal BY CONSTRUCTION rather than by a rule, and is why it is exempt from `maxIterations`; (2) the CONDITIONAL MOUNT is on the agent having a TOOL SURFACE (`registryByName.size > 0 || externalToolProvider`) — a limit only cuts a turn short when tool calls were pending, so a toolless agent's chart must not grow a box that can never run. `decideBranch` treats a spent wrap-up as cut-short for every downstream judge (`toolCalls.length > 0 || scope.wrapUpAsked`), or a step nudge / evidence revision would loop past the limit that fired. `wrapUpAsked` is deliberately NOT seeded — a turn that finishes inside its budget commits the exact key set it always did. The record is FOUR channels: `stoppedEarly` (now with `wrappedUp`, corrected on the pass after so `answerWasEmpty` describes the answer the caller GOT), `cost.limit_hit` (unchanged), the new `agent.budget_exhausted {action: 'wrapped-up'|'cut-short'}`, and an optional `turn_end.stoppedEarly` projection.
|
|
157
157
|
- **Closed seams**: Agent chart internals (AgentChartDeps not exported — extend via injections/tools/memory/thinking, never by adding a ReAct stage); ContextSlot (3 slots fixed); ProviderKind factory; dormant ports with no consumer (ContextSourceAdapter, EmbeddingProvider, RiskDetector — adapters/types.ts only); reserved tool names under selfExplain — 8.16.0 made the list DERIVED: `TRACE_TOOL_NAMES` (traceToolpack.ts, 11 names since 9.61.0: run_overview/find_context_errors/find_in_trace/trace_node/trace_slice/backtrack/who_wrote/get_value/inspect_tool_call/inspect_tool_run/read_narrative) is what AgentBuilder.ts:~1560 reserves in inline mode (`explain_run` in delegate mode), so a NEW toolpack tool joins ONE list and the reservation follows — but it must ALSO join the lazy template's mounted set (lazyToolpack builds over `{narrative: [], events: []}` so the catalog shape is fixed at build time) and the count assertion in test/lib/trace-toolpack/selfExplainAgent.test.ts. **8.17.0 `inspect_tool_run`** is the descent THROUGH the tool boundary: `flowchartAsTool({ keepRecord: true })` files each invocation's record in a bounded LRU store (lib/trace-toolpack/innerRunRecords.ts) keyed by the executing `ctx.toolCallId`, riding the `Tool` under the `INNER_RUN_RECORDS` registry symbol; `AgentBuilder.build()` → `collectInnerRuns(registry, injections)` → `SelfExplainSource.getInnerRuns` → `TraceToolpackArtifacts.innerRuns`. The inner views are the pack ITSELF re-run over `openRecording(record.recording)` — do not add a second query implementation. Provider-delivered tools are NOT collected (no build-time list); inner runtimeStageIds are a SEPARATE namespace and only `inspect_tool_run` accepts them. **9.61.0 `find_context_errors`** is the Context Integrity read-out: it reads `agentfootprint.integrity.context_error` + `…disposition` off the artifacts' EVENT TAIL (never re-running a check), joins each finding to the step it was filed at, and mounts UNCONDITIONALLY — a tool that vanished with the tail could not say the evidence channel is ABSENT, which is the one sentence this family forbids collapsing into "no errors found".
|
|
158
158
|
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Pattern: one reader, every dispatch door (the `applyResultCeiling`
|
|
6
6
|
* precedent). The batch loop and the credential/resume execute
|
|
7
7
|
* boundary both call this at the moment a handler's return lands, so
|
|
8
|
-
* a resumed call declares its coverage exactly as an inline one
|
|
8
|
+
* a resumed call declares its coverage exactly as an inline one; the
|
|
9
|
+
* raise site (`../stages/toolCalls.ts` · `declareRaisedAbsence`)
|
|
10
|
+
* calls it on the `absence` a `requestInput` declared (9.114.0).
|
|
9
11
|
* Role: core/ layer, pure. Recognition and normalization only — the caller
|
|
10
12
|
* owns the events, the scope write and the delivered status.
|
|
11
13
|
* Emits: N/A.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../../src/core/agent/coverage/read.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../../src/core/agent/coverage/read.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAGH,oEAAwF;AACxF,2CAKqB;AACrB,2CAAmE;AAoBnE;sDACsD;AACtD,SAAS,YAAY,CAAC,OAAoB;IACxC,MAAM,UAAU,GAAG,IAAA,+BAAmB,EAAC,OAAO,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,IAAA,mCAAuB,EAAC,OAAO,CAAC,CAAC;IACxD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,IAAA,6BAAiB,EAAC,OAAO,CAAC;QACpC,SAAS,EAAE,OAAO,CAAC,UAAU;QAC7B,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;QAC/C,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC;AAmBD,MAAM,aAAa,GAAqB,QAAQ,CAAC;AAEjD;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,MAAM,OAAO,GAAG,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC;IACnC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;IACtE,CAAC;IACD,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,uEAAuE;IACvE,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,GAAG,GAAG,IAAA,2BAAa,EAAC,KAAK,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACjD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAA,iCAAmB,EAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;IACD,MAAM,OAAO,GAAG,IAAA,8BAAkB,EAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,QAAQ,GAAoB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAA,4BAAgB,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,IAAA,uBAAW,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC7C,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAC7C,CAAC;AAvBD,gDAuBC"}
|
|
@@ -35,9 +35,12 @@
|
|
|
35
35
|
* The fences, because they are the rule's honesty:
|
|
36
36
|
* - TWO FACTS, TWO OWNERS, BOTH REQUIRED. "Did the tool return an absence?"
|
|
37
37
|
* has one owner: the dispatch door (`stages/toolCalls.ts ·
|
|
38
|
-
* declareCoverage`), which reads the value the tool RETURNED
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* declareCoverage`), which reads the value the tool RETURNED, or the
|
|
39
|
+
* `absence` a `requestInput` it raised declared (9.114.0,
|
|
40
|
+
* `stages/toolCalls.ts · declareRaisedAbsence`), through the one
|
|
41
|
+
* recognizer (`coverage/read.ts · readCoverageResult`), delivers the
|
|
42
|
+
* status `'absent'` (a returned one only — a raised one is not settled),
|
|
43
|
+
* emits `tools.absent` and files the call's rows on
|
|
41
44
|
* `AgentState.coverageDeclared`. This rule never re-reads a result to
|
|
42
45
|
* decide that: an envelope a tool returned as TEXT (an MCP server in its
|
|
43
46
|
* default text mode) was no absence at the door (no status, no event, no
|
|
@@ -82,7 +85,11 @@
|
|
|
82
85
|
* `integrity/empty-lookup/check.ts · readLookupResult` declines — a second
|
|
83
86
|
* answer), a result whose door rows are not on this run's state — an
|
|
84
87
|
* earlier turn of a continued conversation, or a run before `resumeOnError`
|
|
85
|
-
* (`coverageDeclared` is per run and not on the `AgentRunCheckpoint`) —
|
|
88
|
+
* (`coverageDeclared` is per run and not on the `AgentRunCheckpoint`) — a
|
|
89
|
+
* lookup that PAUSED on its miss (`requestInput`'s `absence`, 9.114.0): the
|
|
90
|
+
* door's rows hold its miss, but on resume the model is served the person's
|
|
91
|
+
* `InputResponseResult` for that call, which is no absence, so a ruling-out
|
|
92
|
+
* on it files nothing — and
|
|
86
93
|
* the envelope's TYPED suggestion, `try_instead_tool`: the row carries the
|
|
87
94
|
* `try_instead` string alone, because nothing in this release reads a typed
|
|
88
95
|
* tool off the row (the join that would, `source-not-consulted`, is not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unsettled.js","sourceRoot":"","sources":["../../../../src/core/agent/findings/unsettled.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"unsettled.js","sourceRoot":"","sources":["../../../../src/core/agent/findings/unsettled.ts"],"names":[],"mappings":"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"}
|
|
@@ -959,6 +959,45 @@ function buildToolCallsHandler(deps) {
|
|
|
959
959
|
ledger?.note('empty-lookup', 'write', disposition, disposition === 'checked-fail' ? Date.now() : undefined);
|
|
960
960
|
(0, integrityFindings_js_1.fileIntegrityFindings)(scope, findings, call.iteration);
|
|
961
961
|
};
|
|
962
|
+
/**
|
|
963
|
+
* A lookup that pauses still declares what it looked at (9.114.0) — the
|
|
964
|
+
* RAISE-SITE reader of `InputRequestDeclaration.absence`.
|
|
965
|
+
*
|
|
966
|
+
* A tool that found nothing and raised `requestInput` about the miss used
|
|
967
|
+
* to leave no record of it: `declareCoverage` reads a RETURNED value, and
|
|
968
|
+
* the pause branch returns the checkpoint before any of its call sites.
|
|
969
|
+
* The app could not file it either — the declaration's `context` rides to
|
|
970
|
+
* the model on resume, never to the record. So the raise site files it,
|
|
971
|
+
* through the same two readers a returned absence meets: `declareCoverage`
|
|
972
|
+
* (the one recognizer, `tools.absent`, the `coverageDeclared` row — the
|
|
973
|
+
* bytes a returned `absent(…)` files) and the empty-lookup write seam, with
|
|
974
|
+
* the envelope as the tool's own answer — it ran, nothing errored, nothing
|
|
975
|
+
* denied it, and no ceiling judged a result the model was never served.
|
|
976
|
+
*
|
|
977
|
+
* The delivered status `declareCoverage` returns is dropped on purpose: a
|
|
978
|
+
* paused call is not settled, so there is no `tool_end` for it to ride.
|
|
979
|
+
* Nothing on resume reads the field (the served result there is the
|
|
980
|
+
* person's `InputResponseResult`), so the rows are filed once, here.
|
|
981
|
+
*
|
|
982
|
+
* CONTAINED the way the returned path contains it. The recognizer reads an
|
|
983
|
+
* envelope minted elsewhere without repairing it, so its lists can be
|
|
984
|
+
* something `declareCoverage` cannot copy (`checked: [null]`,
|
|
985
|
+
* `not_checked: 5`). Returned, that throw lands in the dispatch `try` and
|
|
986
|
+
* errors the call; here it would land in the `catch` and fail the run. So
|
|
987
|
+
* the copy is caught here instead, and the error text comes back: the
|
|
988
|
+
* caller errors the call with it and does not pause. That is what the same
|
|
989
|
+
* value returned would do. `undefined` means filed.
|
|
990
|
+
*/
|
|
991
|
+
const declareRaisedAbsence = (scope, call, args, absence, history) => {
|
|
992
|
+
try {
|
|
993
|
+
declareCoverage(scope, call, absence);
|
|
994
|
+
}
|
|
995
|
+
catch (err) {
|
|
996
|
+
return err instanceof Error ? err.message : String(err);
|
|
997
|
+
}
|
|
998
|
+
noticeEmptyLookup(scope, call, args, absence, history, true);
|
|
999
|
+
return undefined;
|
|
1000
|
+
};
|
|
962
1001
|
/**
|
|
963
1002
|
* The semantic envelope (9.53.0) — recognized at the SAME execute
|
|
964
1003
|
* boundaries as coverage and the ceiling (one implementation, every door),
|
|
@@ -3290,6 +3329,9 @@ function buildToolCallsHandler(deps) {
|
|
|
3290
3329
|
await endCall(tc.id);
|
|
3291
3330
|
}
|
|
3292
3331
|
catch (err) {
|
|
3332
|
+
// Set when a raise declared a miss the door could not file:
|
|
3333
|
+
// the call then errors with this text and does not pause.
|
|
3334
|
+
let raisedMissError;
|
|
3293
3335
|
if ((0, pause_js_1.isPauseRequest)(err)) {
|
|
3294
3336
|
// The typed half of the question (9.24.0): a tool that raised
|
|
3295
3337
|
// `askHuman({ question, component })` nominated a screen
|
|
@@ -3307,51 +3349,90 @@ function buildToolCallsHandler(deps) {
|
|
|
3307
3349
|
await assertComponentDeliverable(scope, tc.name, rawComponent, `askHuman in tool '${tc.name}'`);
|
|
3308
3350
|
}
|
|
3309
3351
|
}
|
|
3310
|
-
// A pause has NOT settled this call — it is waiting for a
|
|
3311
|
-
// person, and the resources it opened are what the resume
|
|
3312
|
-
// needs. No `'call'` teardown here, deliberately.
|
|
3313
|
-
//
|
|
3314
|
-
// Commit partial state so resume() can find history intact.
|
|
3315
|
-
scope.history = newHistory;
|
|
3316
|
-
scope.pausedToolCallId = tc.id;
|
|
3317
|
-
scope.pausedToolName = tc.name;
|
|
3318
|
-
scope.pausedToolStartMs = startMs;
|
|
3319
|
-
// The args the tool WAS RUNNING WITH (post-transform), for the
|
|
3320
|
-
// after-tool moment on the far side of the pause (8.13.0) —
|
|
3321
|
-
// the same reason the three sibling pauses carry theirs.
|
|
3322
|
-
scope.pausedToolArgs = callArgs;
|
|
3323
3352
|
const declaration = typeof err.data === 'object' && err.data !== null
|
|
3324
3353
|
? err.data.inputRequest
|
|
3325
3354
|
: undefined;
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
//
|
|
3339
|
-
//
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3355
|
+
// A lookup that pauses still declares what it looked at
|
|
3356
|
+
// (9.114.0): the miss it is asking about is filed HERE, the
|
|
3357
|
+
// raise site, FIRST — the one moment the declaration's
|
|
3358
|
+
// `absence` is read. So a declaration that CARRIES one is
|
|
3359
|
+
// judged before anything is written for the pause, and a miss
|
|
3360
|
+
// the door cannot file errors the call below, as the same value
|
|
3361
|
+
// returned would, with nothing written for a pause. A MALFORMED
|
|
3362
|
+
// declaration still leaves the committed record it always left,
|
|
3363
|
+
// whether or not it carried `absence`: its error leaves the
|
|
3364
|
+
// stage only after the pause writes are made, so a hand-raised
|
|
3365
|
+
// request (a `pauseHere`/`askHuman` that never went through
|
|
3366
|
+
// `requestInput`) fails with the in-flight batch on the record.
|
|
3367
|
+
// `null` is the field omitted (`inputRequest.ts` ·
|
|
3368
|
+
// `validateInputDeclaration`).
|
|
3369
|
+
//
|
|
3370
|
+
// The pause writes: partial state, so resume() can find the
|
|
3371
|
+
// history intact.
|
|
3372
|
+
const writePause = () => {
|
|
3373
|
+
scope.history = newHistory;
|
|
3374
|
+
scope.pausedToolCallId = tc.id;
|
|
3375
|
+
scope.pausedToolName = tc.name;
|
|
3376
|
+
scope.pausedToolStartMs = startMs;
|
|
3377
|
+
// The args the tool WAS RUNNING WITH (post-transform), for
|
|
3378
|
+
// the after-tool moment on the far side of the pause
|
|
3379
|
+
// (8.13.0) — the same reason the three sibling pauses carry
|
|
3380
|
+
// theirs.
|
|
3381
|
+
scope.pausedToolArgs = callArgs;
|
|
3348
3382
|
};
|
|
3383
|
+
const carriesAbsence = typeof declaration === 'object' &&
|
|
3384
|
+
declaration !== null &&
|
|
3385
|
+
declaration.absence != null;
|
|
3386
|
+
let declared;
|
|
3387
|
+
if (carriesAbsence) {
|
|
3388
|
+
try {
|
|
3389
|
+
declared = (0, inputRequest_js_1.validateInputDeclaration)(declaration);
|
|
3390
|
+
}
|
|
3391
|
+
catch (invalid) {
|
|
3392
|
+
writePause();
|
|
3393
|
+
throw invalid;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
raisedMissError =
|
|
3397
|
+
declared?.absence === undefined
|
|
3398
|
+
? undefined
|
|
3399
|
+
: declareRaisedAbsence(scope, { toolName: tc.name, toolCallId: tc.id, iteration }, callArgs, declared.absence, newHistory);
|
|
3400
|
+
if (raisedMissError === undefined) {
|
|
3401
|
+
// A pause has NOT settled this call — it is waiting for a
|
|
3402
|
+
// person, and the resources it opened are what the resume
|
|
3403
|
+
// needs. No `'call'` teardown here, deliberately.
|
|
3404
|
+
writePause();
|
|
3405
|
+
const awaitingInput = declaration === undefined
|
|
3406
|
+
? undefined
|
|
3407
|
+
: (0, inputRequest_js_1.stampInputRequest)(declared ?? (0, inputRequest_js_1.validateInputDeclaration)(declaration), `${deps.currentRun?.().runId ?? scope.turnStartMs}:${tc.id}`, {
|
|
3408
|
+
originalRequest: scope.userMessage,
|
|
3409
|
+
toolCallId: tc.id,
|
|
3410
|
+
...(scope.currentSkillId !== undefined && {
|
|
3411
|
+
skillId: scope.currentSkillId,
|
|
3412
|
+
}),
|
|
3413
|
+
...(scope.turnRoute?.offered !== undefined && {
|
|
3414
|
+
offeredSkillIds: [...scope.turnRoute.offered],
|
|
3415
|
+
}),
|
|
3416
|
+
});
|
|
3417
|
+
// Returning a defined value triggers footprintjs pause —
|
|
3418
|
+
// the returned object becomes the checkpoint's pauseData.
|
|
3419
|
+
return {
|
|
3420
|
+
toolCallId: tc.id,
|
|
3421
|
+
toolName: tc.name,
|
|
3422
|
+
...(awaitingInput !== undefined
|
|
3423
|
+
? { question: awaitingInput.question, awaitingInput }
|
|
3424
|
+
: typeof err.data === 'object' && err.data !== null
|
|
3425
|
+
? err.data
|
|
3426
|
+
: { data: err.data }),
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3349
3429
|
}
|
|
3350
3430
|
// A tool that threw still RAN, and may have opened the thing it
|
|
3351
|
-
// was about to close.
|
|
3431
|
+
// was about to close. A raise whose miss could not be filed is
|
|
3432
|
+
// settled here too — the returned path's error, not a pause.
|
|
3352
3433
|
await endCall(tc.id);
|
|
3353
3434
|
error = true;
|
|
3354
|
-
result = err instanceof Error ? err.message : String(err);
|
|
3435
|
+
result = raisedMissError ?? (err instanceof Error ? err.message : String(err));
|
|
3355
3436
|
}
|
|
3356
3437
|
}
|
|
3357
3438
|
}
|