agentfootprint 9.119.0 → 9.121.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/AGENTS.md +3 -2
- package/CAPABILITIES.md +2 -0
- package/README.md +1 -1
- package/ai-instructions/claude-code/SKILL.md +3 -2
- package/dist/core/Agent.js +132 -8
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +25 -3
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/assessment/assess.js +411 -0
- package/dist/core/agent/assessment/assess.js.map +1 -0
- package/dist/core/agent/assessment/reasons.js +94 -0
- package/dist/core/agent/assessment/reasons.js.map +1 -0
- package/dist/core/agent/assessment/types.js +22 -0
- package/dist/core/agent/assessment/types.js.map +1 -0
- package/dist/core/agent/buildAgentChart.js +5 -3
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +5 -3
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/coverage/answer.js +68 -2
- package/dist/core/agent/coverage/answer.js.map +1 -1
- package/dist/core/agent/coverage/emptiness.js +221 -0
- package/dist/core/agent/coverage/emptiness.js.map +1 -0
- package/dist/core/agent/coverage/index.js +3 -1
- package/dist/core/agent/coverage/index.js.map +1 -1
- package/dist/core/agent/coverage/ledger.js +7 -20
- package/dist/core/agent/coverage/ledger.js.map +1 -1
- package/dist/core/agent/coverage/recognize.js +28 -7
- package/dist/core/agent/coverage/recognize.js.map +1 -1
- package/dist/core/agent/stages/answerCoverage.js +57 -0
- package/dist/core/agent/stages/answerCoverage.js.map +1 -0
- package/dist/core/agent/stages/prepareFinal.js +45 -15
- package/dist/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +76 -4
- package/dist/esm/core/Agent.js +109 -8
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +24 -2
- package/dist/esm/core/agent/AgentBuilder.js +25 -3
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/assessment/assess.d.ts +83 -0
- package/dist/esm/core/agent/assessment/assess.js +407 -0
- package/dist/esm/core/agent/assessment/assess.js.map +1 -0
- package/dist/esm/core/agent/assessment/reasons.d.ts +38 -0
- package/dist/esm/core/agent/assessment/reasons.js +90 -0
- package/dist/esm/core/agent/assessment/reasons.js.map +1 -0
- package/dist/esm/core/agent/assessment/types.d.ts +166 -0
- package/dist/esm/core/agent/assessment/types.js +21 -0
- package/dist/esm/core/agent/assessment/types.js.map +1 -0
- package/dist/esm/core/agent/buildAgentChart.d.ts +12 -1
- package/dist/esm/core/agent/buildAgentChart.js +6 -4
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +6 -4
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/coverage/answer.d.ts +35 -1
- package/dist/esm/core/agent/coverage/answer.js +65 -1
- package/dist/esm/core/agent/coverage/answer.js.map +1 -1
- package/dist/esm/core/agent/coverage/emptiness.d.ts +173 -0
- package/dist/esm/core/agent/coverage/emptiness.js +214 -0
- package/dist/esm/core/agent/coverage/emptiness.js.map +1 -0
- package/dist/esm/core/agent/coverage/index.d.ts +1 -1
- package/dist/esm/core/agent/coverage/index.js +1 -1
- package/dist/esm/core/agent/coverage/index.js.map +1 -1
- package/dist/esm/core/agent/coverage/ledger.d.ts +2 -8
- package/dist/esm/core/agent/coverage/ledger.js +5 -18
- package/dist/esm/core/agent/coverage/ledger.js.map +1 -1
- package/dist/esm/core/agent/coverage/recognize.d.ts +17 -7
- package/dist/esm/core/agent/coverage/recognize.js +26 -6
- package/dist/esm/core/agent/coverage/recognize.js.map +1 -1
- package/dist/esm/core/agent/stages/answerCoverage.d.ts +43 -0
- package/dist/esm/core/agent/stages/answerCoverage.js +53 -0
- package/dist/esm/core/agent/stages/answerCoverage.js.map +1 -0
- package/dist/esm/core/agent/stages/prepareFinal.d.ts +24 -5
- package/dist/esm/core/agent/stages/prepareFinal.js +44 -15
- package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +16 -0
- package/dist/esm/events/payloads.d.ts +18 -0
- package/dist/esm/lib/answer-account/account.js +1 -7
- package/dist/esm/lib/answer-account/account.js.map +1 -1
- package/dist/esm/lib/answer-account/declarations.js +4 -2
- package/dist/esm/lib/answer-account/declarations.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/calls.d.ts +7 -1
- package/dist/esm/lib/answer-account/facts/calls.js +22 -3
- package/dist/esm/lib/answer-account/facts/calls.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/common.d.ts +5 -18
- package/dist/esm/lib/answer-account/facts/common.js +8 -48
- package/dist/esm/lib/answer-account/facts/common.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/found.d.ts +6 -4
- package/dist/esm/lib/answer-account/facts/found.js +55 -5
- package/dist/esm/lib/answer-account/facts/found.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/howSure.d.ts +12 -3
- package/dist/esm/lib/answer-account/facts/howSure.js +176 -11
- package/dist/esm/lib/answer-account/facts/howSure.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/inView.js +5 -2
- package/dist/esm/lib/answer-account/facts/inView.js.map +1 -1
- package/dist/esm/lib/answer-account/shown.js +3 -0
- package/dist/esm/lib/answer-account/shown.js.map +1 -1
- package/dist/esm/lib/answer-account/templates.d.ts +26 -1
- package/dist/esm/lib/answer-account/templates.js +33 -2
- package/dist/esm/lib/answer-account/templates.js.map +1 -1
- package/dist/esm/lib/answer-account/types.d.ts +31 -3
- package/dist/esm/observe.d.ts +2 -0
- package/dist/esm/observe.js +7 -0
- package/dist/esm/observe.js.map +1 -1
- package/dist/lib/answer-account/account.js +1 -7
- package/dist/lib/answer-account/account.js.map +1 -1
- package/dist/lib/answer-account/declarations.js +4 -2
- package/dist/lib/answer-account/declarations.js.map +1 -1
- package/dist/lib/answer-account/facts/calls.js +21 -2
- package/dist/lib/answer-account/facts/calls.js.map +1 -1
- package/dist/lib/answer-account/facts/common.js +7 -52
- package/dist/lib/answer-account/facts/common.js.map +1 -1
- package/dist/lib/answer-account/facts/found.js +55 -5
- package/dist/lib/answer-account/facts/found.js.map +1 -1
- package/dist/lib/answer-account/facts/howSure.js +175 -10
- package/dist/lib/answer-account/facts/howSure.js.map +1 -1
- package/dist/lib/answer-account/facts/inView.js +4 -1
- package/dist/lib/answer-account/facts/inView.js.map +1 -1
- package/dist/lib/answer-account/shown.js +3 -0
- package/dist/lib/answer-account/shown.js.map +1 -1
- package/dist/lib/answer-account/templates.js +33 -2
- package/dist/lib/answer-account/templates.js.map +1 -1
- package/dist/observe.js +10 -2
- package/dist/observe.js.map +1 -1
- package/dist/types/core/Agent.d.ts +76 -4
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +24 -2
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/assess.d.ts +84 -0
- package/dist/types/core/agent/assessment/assess.d.ts.map +1 -0
- package/dist/types/core/agent/assessment/reasons.d.ts +39 -0
- package/dist/types/core/agent/assessment/reasons.d.ts.map +1 -0
- package/dist/types/core/agent/assessment/types.d.ts +167 -0
- package/dist/types/core/agent/assessment/types.d.ts.map +1 -0
- package/dist/types/core/agent/buildAgentChart.d.ts +12 -1
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/answer.d.ts +35 -1
- package/dist/types/core/agent/coverage/answer.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/emptiness.d.ts +174 -0
- package/dist/types/core/agent/coverage/emptiness.d.ts.map +1 -0
- 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/ledger.d.ts +2 -8
- package/dist/types/core/agent/coverage/ledger.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/recognize.d.ts +17 -7
- package/dist/types/core/agent/coverage/recognize.d.ts.map +1 -1
- package/dist/types/core/agent/stages/answerCoverage.d.ts +44 -0
- package/dist/types/core/agent/stages/answerCoverage.d.ts.map +1 -0
- package/dist/types/core/agent/stages/prepareFinal.d.ts +24 -5
- package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +16 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +18 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/lib/answer-account/account.d.ts.map +1 -1
- package/dist/types/lib/answer-account/declarations.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/calls.d.ts +7 -1
- package/dist/types/lib/answer-account/facts/calls.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/common.d.ts +5 -18
- package/dist/types/lib/answer-account/facts/common.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/found.d.ts +6 -4
- package/dist/types/lib/answer-account/facts/found.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/howSure.d.ts +12 -3
- package/dist/types/lib/answer-account/facts/howSure.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/inView.d.ts.map +1 -1
- package/dist/types/lib/answer-account/shown.d.ts.map +1 -1
- package/dist/types/lib/answer-account/templates.d.ts +26 -1
- package/dist/types/lib/answer-account/templates.d.ts.map +1 -1
- package/dist/types/lib/answer-account/types.d.ts +31 -3
- package/dist/types/lib/answer-account/types.d.ts.map +1 -1
- package/dist/types/observe.d.ts +2 -0
- package/dist/types/observe.d.ts.map +1 -1
- package/package.json +2 -1
package/AGENTS.md
CHANGED
|
@@ -259,8 +259,9 @@ delivered status `'absent'` (route it with `onToolStatus: 'absent'`) and grounds
|
|
|
259
259
|
COVERAGE in the evidence gate — so an id the model invented does not become grounded by one
|
|
260
260
|
lookup that found nothing. It is never an error: nothing retries it, nothing refuses it, no
|
|
261
261
|
`error: true`. Add `.limitsTravelWithTheAnswer()` on the agent and the framework APPENDS the
|
|
262
|
-
run's declared coverage to the final answer string (not to streamed tokens
|
|
263
|
-
|
|
262
|
+
run's declared coverage to the final answer string (not to streamed tokens), so the model
|
|
263
|
+
cannot drop what it never wrote. With `.outputSchema()` nothing is appended — the JSON stays
|
|
264
|
+
parseable by `runTyped()` and the same limits come back as data: `agent.answerCoverage()`.
|
|
264
265
|
|
|
265
266
|
## Observing a run
|
|
266
267
|
|
package/CAPABILITIES.md
CHANGED
|
@@ -64,10 +64,12 @@ not in this table, search `src/index.ts` for the nearest noun before writing cod
|
|
|
64
64
|
| a model head-mathing a total from tool-result numbers while a compute tool sits unused on the wire — a LATE line each iteration naming the staged refs and the `wants` tool that spends them (recency working FOR the instruction), plus the revise correction naming the same route | `nudge: true` (default off) + `stagedRefsNudgeLine` + `findStagedRefs` + `grounding_nudged` | `src/core/agent/stagedRefs.ts` | 9.75.0 |
|
|
65
65
|
| a tool answering "I looked and found nothing", routably | `absent` + `looked_for` + `checked`/`not_checked`/`cannot_cover` + `tryInstead` (delivered status `'absent'`, routable by `onToolStatus`) | `src/core/agent/coverage/absent.ts` | 9.43.0 |
|
|
66
66
|
| stating what a clean answer does NOT rule out | `coverage` + the declaration `{ checked, not_checked?, cannot_cover? }` | `src/core/agent/coverage/ledger.ts` | 9.43.0 |
|
|
67
|
+
| a TYPED answer (`.outputSchema()`) carrying the limits its tools declared WITHOUT breaking its JSON — the same limits `.limitsTravelWithTheAnswer()` appends to a prose answer, as data beside it (checked / not checked / cannot cover, duplicates said once, every entry kept); `runTyped()` parses the model's answer untouched | `agent.answerCoverage()` + `turn_end.answerCoverage` + `AgentState.answerCoverage` (with `.outputSchema()` + `.limitsTravelWithTheAnswer()`; absent when no tool declared a limit) | `src/core/agent/stages/answerCoverage.ts` | 9.121.0 |
|
|
67
68
|
| a person-readable short form of a coverage item, and whether an unchecked item is about EXISTENCE (does the thing asked about exist at all) or SCOPE (outside what the tool reaches) — on the record for a report, never in the model's request, never evidence. `short`: at most 80 chars, one line, never longer than `what`. `kind`: 'existence' or 'scope', on notChecked and cannotCover only. Refused at `absent()` and `coverage()`, read-never-repaired on a foreign envelope; carried by `tools.absent`, `tools.coverage_declared` and `coverageDeclared`; stripped from every served envelope, with `tool_end.modelResult` stamped where it differs | `CoverageItem` + `absent` + `coverage` | `src/core/agent/coverage/` | 9.116.0 |
|
|
68
69
|
| a skill's plain name for a person ("array estate report" for `array-inventory`) on the recording, without changing what the model reads or what a graph draws — at most 60 chars, one line of plain visible text, not the id; carried as `skill.graph_declared` `nodes[].title` on a skill-graph agent, absent when not declared | `defineSkill` + `title` | `src/lib/injection-engine/factories/defineSkill.ts` | 9.116.0 |
|
|
69
70
|
| how many of an answer's values the evidence check actually LOOKED UP — `candidates` also counts values the person's message or the app's instructions already held, which are never looked up; found plus not found, before the 12-value slice, on every `evidence_checked` | `lookedUp` + `EvidenceVerdict` | `src/core/agent/evidence/` | 9.116.0 |
|
|
70
71
|
| explaining ONE answer to a person in plain words — what was asked, how it was routed, what each tool checked and did not check, what it found, how sure, and anything wrong — every line from the record by a fixed versioned template (never a model), each with its template id and who vouches for it (person / library / tool / model / app), "not recorded" instead of a guess, own-run events only, three checks with the ones that could not run said aloud | `accountForAnswer` + `AnswerAccount` | `src/lib/answer-account/` | 9.116.0 |
|
|
72
|
+
| how far an answer STANDS — known · consistent with the record · not sure (with the reasons) · ask · not assessed — folded from the run's COMMITTED record (never from the model's confidence, never from events, never "known" from silence: only a passed enforce answer check supports it); each reason names the row it rests on, `checked` counts what ran, this turn only; a pause of any kind reads `ask` from the recording alone, a run with no answer has no standing; one emptiness reader shared with the answer account (`coverage/emptiness.ts`: a `coverage()` envelope read through, a described result counted, an undeclared empty rowset said aloud) | `assessAnswer` + `AnswerAssessment` (on the observe door), `agent.assessment()` | `src/core/agent/assessment/` | 9.120.0 |
|
|
71
73
|
| serving that explanation to a browser without the recording: one opt-in wire op returns the account plus allow-listed "show me" leaves, owner-only on the `artifact-get` path, lane-free, cached and single-flight, a stated size ceiling, and a swept record answering "not available" even when cached | `standingAgent({ answerAccounts })` + `{ op: 'answer-account', ref }` + `answerAccountPointerKey` | `src/hosting/answerAccounts.ts` | 9.116.0 |
|
|
72
74
|
| bounding what one session can ask of the artifact door at once: `artifact-head`, `artifact-get` and `answer-account` counted together per session, after the ownership check, refused 429 by name while every other session is served | `standingAgent({ artifactOpsPerSession })` + `ArtifactOpsBusyError` | `src/hosting/standingAgent.ts` | 9.116.0 |
|
|
73
75
|
| minting one of those shapes from a tool that is NOT JavaScript — the canonical note sentences and reserved marker keys as DATA, so a Python/Go/Rust sidecar reads a file instead of regex-scraping `dist/esm` (which a consumer really did) | `canonical-notes.json` at the package root + the `./canonical-notes.json` exports entry, GENERATED from the built barrel by `scripts/gen-canonical-notes.mjs` | `scripts/gen-canonical-notes.mjs` | 9.70.0 |
|
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ Whatever a tool returns is what the model reads next. When that value has limits
|
|
|
117
117
|
| `coverage(value, { … })` | any other value that has limits | your value, with what was and was not checked | `tools.coverage_declared` |
|
|
118
118
|
| `absent({ … })` | nothing matched | what was looked for, where, and that a retry returns the same | `tools.absent` |
|
|
119
119
|
|
|
120
|
-
Never wrap one in another. Add `.limitsTravelWithTheAnswer()` and the declared coverage is appended to the final answer —
|
|
120
|
+
Never wrap one in another. Add `.limitsTravelWithTheAnswer()` and the declared coverage is appended to the final answer — or, for a typed `.outputSchema()` answer, returned beside it as data by `agent.answerCoverage()`. Provenance and grain never are.
|
|
121
121
|
|
|
122
122
|
```typescript
|
|
123
123
|
import { absent, coverage, describedResult } from 'agentfootprint';
|
|
@@ -259,8 +259,9 @@ delivered status `'absent'` (route it with `onToolStatus: 'absent'`) and grounds
|
|
|
259
259
|
COVERAGE in the evidence gate — so an id the model invented does not become grounded by one
|
|
260
260
|
lookup that found nothing. It is never an error: nothing retries it, nothing refuses it, no
|
|
261
261
|
`error: true`. Add `.limitsTravelWithTheAnswer()` on the agent and the framework APPENDS the
|
|
262
|
-
run's declared coverage to the final answer string (not to streamed tokens
|
|
263
|
-
|
|
262
|
+
run's declared coverage to the final answer string (not to streamed tokens), so the model
|
|
263
|
+
cannot drop what it never wrote. With `.outputSchema()` nothing is appended — the JSON stays
|
|
264
|
+
parseable by `runTyped()` and the same limits come back as data: `agent.answerCoverage()`.
|
|
264
265
|
|
|
265
266
|
## Observing a run
|
|
266
267
|
|
package/dist/core/Agent.js
CHANGED
|
@@ -14,6 +14,29 @@
|
|
|
14
14
|
* agentfootprint.stream.tool_start / tool_end
|
|
15
15
|
* agentfootprint.context.* (via ContextRecorder)
|
|
16
16
|
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
17
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
41
|
exports.Agent = exports.AgentBuilder = void 0;
|
|
19
42
|
const footprintjs_1 = require("footprintjs");
|
|
@@ -135,6 +158,7 @@ const RunnerBase_js_1 = require("./RunnerBase.js");
|
|
|
135
158
|
const validators_js_1 = require("./agent/validators.js");
|
|
136
159
|
const route_js_1 = require("./agent/stages/route.js");
|
|
137
160
|
const answerValidation_js_1 = require("./agent/stages/answerValidation.js");
|
|
161
|
+
const answerCoverage_js_1 = require("./agent/stages/answerCoverage.js");
|
|
138
162
|
const index_js_1 = require("../answer-validation/index.js");
|
|
139
163
|
const seed_js_1 = require("./agent/stages/seed.js");
|
|
140
164
|
const errors_js_3 = require("./agent/middleware/errors.js");
|
|
@@ -266,10 +290,12 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
266
290
|
*/
|
|
267
291
|
evidenceGate;
|
|
268
292
|
/**
|
|
269
|
-
* `.limitsTravelWithTheAnswer()`
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
293
|
+
* `.limitsTravelWithTheAnswer()` — whether the run's declared coverage
|
|
294
|
+
* travels with the final answer: appended as a block to a prose answer, or,
|
|
295
|
+
* when an output schema makes the answer TYPED, committed beside it as data
|
|
296
|
+
* (`answerCoverage()`), because JSON followed by prose is not JSON. False for
|
|
297
|
+
* every agent that did not ask for it; the RECORDING half of the coverage
|
|
298
|
+
* primitives does not consult it.
|
|
273
299
|
*/
|
|
274
300
|
limitsTravelWithTheAnswerValue = false;
|
|
275
301
|
skillGraphCascade;
|
|
@@ -1310,6 +1336,10 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
1310
1336
|
*
|
|
1311
1337
|
* Throws if the agent has no outputSchema set or if the run
|
|
1312
1338
|
* pauses (use `run()` directly when pauses are expected).
|
|
1339
|
+
*
|
|
1340
|
+
* With `.limitsTravelWithTheAnswer()`, nothing is appended to a typed
|
|
1341
|
+
* answer: the limits its tools declared come back as data, from
|
|
1342
|
+
* `agent.answerCoverage()`.
|
|
1313
1343
|
*/
|
|
1314
1344
|
async runTyped(input, options) {
|
|
1315
1345
|
if (!this.outputSchemaParser) {
|
|
@@ -3165,6 +3195,88 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3165
3195
|
?.answerValidation;
|
|
3166
3196
|
return report === undefined ? undefined : structuredClone(report);
|
|
3167
3197
|
}
|
|
3198
|
+
/**
|
|
3199
|
+
* The limits of the last run's TYPED answer, as data — what its tools
|
|
3200
|
+
* declared they `checked`, did not check (`notChecked`) and can never see
|
|
3201
|
+
* (`cannotCover`), folded across the run: duplicates said once, every entry
|
|
3202
|
+
* kept.
|
|
3203
|
+
*
|
|
3204
|
+
* Set when the agent has an output schema AND `.limitsTravelWithTheAnswer()`:
|
|
3205
|
+
* a typed answer is JSON, and the limits block that option appends to a
|
|
3206
|
+
* prose answer would stop it being JSON, so for a typed answer the limits
|
|
3207
|
+
* travel beside it instead — here, on `turn_end.answerCoverage`, and in
|
|
3208
|
+
* `getLastSnapshot().sharedState.answerCoverage`, one value three ways. The
|
|
3209
|
+
* answer string, and so `runTyped()`, is exactly the model's.
|
|
3210
|
+
*
|
|
3211
|
+
* `undefined` when the run's tools declared no limits, on a prose answer
|
|
3212
|
+
* (the block is in the answer string there; `sharedState.coverageDeclared`
|
|
3213
|
+
* holds the raw rows either way), and before the first run. Detached from
|
|
3214
|
+
* the execution record, so a caller may keep or mutate it.
|
|
3215
|
+
*
|
|
3216
|
+
* @example
|
|
3217
|
+
* ```ts
|
|
3218
|
+
* const agent = Agent.create({ provider, model })
|
|
3219
|
+
* .tool(replicationHealth) // returns coverage(verdict, { … })
|
|
3220
|
+
* .outputSchema(Verdict)
|
|
3221
|
+
* .limitsTravelWithTheAnswer()
|
|
3222
|
+
* .build();
|
|
3223
|
+
*
|
|
3224
|
+
* const verdict = await agent.runTyped({ message: 'is replication healthy?' });
|
|
3225
|
+
* const limits = agent.answerCoverage();
|
|
3226
|
+
* for (const item of limits?.cannotCover ?? []) {
|
|
3227
|
+
* console.log(`never covered: ${item.what} (${item.why})`);
|
|
3228
|
+
* }
|
|
3229
|
+
* ```
|
|
3230
|
+
*/
|
|
3231
|
+
answerCoverage() {
|
|
3232
|
+
const limits = this.getLastSnapshot()?.sharedState
|
|
3233
|
+
?.answerCoverage;
|
|
3234
|
+
return limits === undefined ? undefined : structuredClone(limits);
|
|
3235
|
+
}
|
|
3236
|
+
/**
|
|
3237
|
+
* How far the last run's answer stands — folded from its COMMITTED record,
|
|
3238
|
+
* never from how sure the model sounded: `known` · `consistent` (checks ran,
|
|
3239
|
+
* none fired — never "verified") · `not-sure` (with the reasons) · `ask` (the
|
|
3240
|
+
* run paused on a question still waiting for a person) · `not-assessed`
|
|
3241
|
+
* (nothing on the record could be checked).
|
|
3242
|
+
*
|
|
3243
|
+
* The same pure fold as `assessAnswer` on `agentfootprint/observe`, over this
|
|
3244
|
+
* agent's last snapshot; it reads committed state, never events, so a later
|
|
3245
|
+
* reader of the same recording folds the same standing. It resolves
|
|
3246
|
+
* asynchronously because the fold is loaded through `import()` on first use —
|
|
3247
|
+
* an agent that never asks does not carry it.
|
|
3248
|
+
*
|
|
3249
|
+
* Resolves to `undefined` when there is no answer to assess: before the first
|
|
3250
|
+
* run, while a run is in flight, and after a run that threw or whose answer a
|
|
3251
|
+
* rule refused (the typed error carries that verdict).
|
|
3252
|
+
*
|
|
3253
|
+
* `declarations` is the answer account's object, accepted as it is: the fold
|
|
3254
|
+
* reads `tools[name].rowsAt`, where an object result keeps its rows.
|
|
3255
|
+
*
|
|
3256
|
+
* @example
|
|
3257
|
+
* ```ts
|
|
3258
|
+
* await agent.run({ message: 'Which ports on switch A are down?' });
|
|
3259
|
+
* const a = await agent.assessment();
|
|
3260
|
+
* if (a?.standing === 'not-sure') {
|
|
3261
|
+
* for (const r of a.reasons) console.log(r.reason); // e.g. 'empty-undeclared'
|
|
3262
|
+
* }
|
|
3263
|
+
* ```
|
|
3264
|
+
*/
|
|
3265
|
+
async assessment(declarations) {
|
|
3266
|
+
const snapshot = this.getLastSnapshot();
|
|
3267
|
+
if (snapshot === undefined)
|
|
3268
|
+
return undefined;
|
|
3269
|
+
// Settled before the fold, which cannot tell a crash from its committed state: an answer
|
|
3270
|
+
// this run RETURNED (`lastRunAnswer`, cleared at every run's start), or a pause — the fold
|
|
3271
|
+
// reads that one from the committed state itself. Read BEFORE the import resolves, so a
|
|
3272
|
+
// run started meanwhile cannot change which run is assessed.
|
|
3273
|
+
const paused = this.lastExecutor?.isPaused() === true;
|
|
3274
|
+
if (!paused && this.lastRunAnswer === undefined)
|
|
3275
|
+
return undefined;
|
|
3276
|
+
// Loaded on first use, off the default graph (the findings/peel.ts precedent).
|
|
3277
|
+
const { assessAnswer } = await Promise.resolve().then(() => __importStar(require('./agent/assessment/assess.js')));
|
|
3278
|
+
return assessAnswer({ snapshot }, declarations);
|
|
3279
|
+
}
|
|
3168
3280
|
finalizeResult(executor, result) {
|
|
3169
3281
|
const paused = this.detectPause(executor, result);
|
|
3170
3282
|
if (paused)
|
|
@@ -3989,6 +4101,15 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3989
4101
|
const routeDecider = this.answerValidationConfig === undefined
|
|
3990
4102
|
? baseRouteDecider
|
|
3991
4103
|
: (0, answerValidation_js_1.withAnswerValidation)(baseRouteDecider, this.answerValidationConfig, this.outputSchemaParser, artifactStore, () => this.consentOutstanding.size > 0);
|
|
4104
|
+
// `.limitsTravelWithTheAnswer()` on a TYPED answer — decided once, here.
|
|
4105
|
+
// An output schema makes the answer JSON, and the appended block would
|
|
4106
|
+
// make it JSON followed by prose, which `runTyped()` cannot parse. So the
|
|
4107
|
+
// limits travel as DATA: the Route decider's terminal decision commits the
|
|
4108
|
+
// fold (`withAnswerCoverage`) and the Final branch projects it onto
|
|
4109
|
+
// `turn_end`. A prose answer keeps the block; an agent that asked for
|
|
4110
|
+
// neither is handed the decider it always had.
|
|
4111
|
+
const limitsAsData = this.limitsTravelWithTheAnswerValue && this.outputSchemaParser !== undefined;
|
|
4112
|
+
const terminalRouteDecider = limitsAsData ? (0, answerCoverage_js_1.withAnswerCoverage)(routeDecider) : routeDecider;
|
|
3992
4113
|
// toolCallsHandler extracted to ./agent/stages/toolCalls.ts (v2.11.2).
|
|
3993
4114
|
const toolCallsHandler = (0, toolCalls_js_1.buildToolCallsHandler)({
|
|
3994
4115
|
registryByName,
|
|
@@ -4164,7 +4285,7 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
4164
4285
|
maxIterations,
|
|
4165
4286
|
seed,
|
|
4166
4287
|
callLLM,
|
|
4167
|
-
routeDecider,
|
|
4288
|
+
routeDecider: terminalRouteDecider,
|
|
4168
4289
|
toolCallsHandler,
|
|
4169
4290
|
// The re-ask branch — mounted only when there are retries to spend. A
|
|
4170
4291
|
// `'tool-forced'` agent with `retries: 0` gets the constrained shape and
|
|
@@ -4219,11 +4340,14 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
4219
4340
|
// The declared ontology (9.106.0): the grouped chart carries the run
|
|
4220
4341
|
// constant across the sf-llm-call boundary, under the arm.
|
|
4221
4342
|
...(this.ontology !== undefined && { hasOntology: true }),
|
|
4222
|
-
// `.limitsTravelWithTheAnswer()`
|
|
4343
|
+
// `.limitsTravelWithTheAnswer()` — value-conditional, the
|
|
4223
4344
|
// `resolvedModel` precedent: absent from the deps object entirely for an
|
|
4224
4345
|
// agent that did not ask, so both builders mount the final-branch stage
|
|
4225
|
-
// function they have always mounted.
|
|
4226
|
-
|
|
4346
|
+
// function they have always mounted. ONE of the two, never both: a prose
|
|
4347
|
+
// answer gets the appended block, a TYPED one (`limitsAsData`, above)
|
|
4348
|
+
// gets the stage that appends nothing and carries the limits as data.
|
|
4349
|
+
...(this.limitsTravelWithTheAnswerValue && !limitsAsData && { attachCoverageLimits: true }),
|
|
4350
|
+
...(limitsAsData && { coverageLimitsAsData: true }),
|
|
4227
4351
|
...(this.answerValidationConfig !== undefined && { hasAnswerValidation: true }),
|
|
4228
4352
|
// The out-of-budget wrap-up branch (9.56.0) — the conditional-mount law
|
|
4229
4353
|
// above, decided once beside the Route decider that routes to it so the
|