UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

120 lines • 5.28 kB
/** * search/compose — ONE call's coverage, composed by the library from the * tool's `search` declaration and the arguments the call ran with. * * Pattern: linear composition of small pure rules — * door (what came back) → inEffect (each argument) → facets * (`checked`) → gaps → complete → the reading the funnel files. * Role: semantics/ layer, pure. Called by the dispatch funnel * (`../../../core/agent/stages/searchCoverage.ts` · `buildSearchCoverage`) at * every execute boundary, before `declareCoverage`. * Emits: N/A (the funnel emits, from the reading). * * ## Composition can only under-claim — relative to a TRUE declaration * * A declaration that misdescribes the query (an undeclared qualifier, a wrong * `complete`) is the trusted base, said out loud: the law holds relative to * it, never to the backend. * * A facet enters `checked` from exactly four places — a value the call sent, a * declared default composed as if sent, a declared fixed qualifier, the * declared (or sent) source — plus a host-filled identity filter (which only * narrows) and a result-declared period (which only narrows). Every * classified argument none of them covers is a bearing gap; a cap in effect, * a declared server cap, a page, a `partial` outcome is a completeness gap * unless the result says otherwise. So the composed scope is never wider than * what the declaration and the arguments say. A wrong declaration is the * trusted base, said out loud. * * ## Local and remote * * A `search` that arrived over MCP or from a `ToolProvider` composes the same * shape, marked `'remote'`, and is never `complete`: it establishes nothing. */ import { readCoverageResult } from '../read.js'; import { readSearchDoor } from './door.js'; import { composeChecked } from './facets.js'; import { blocksComplete, composeGaps } from './gaps.js'; import { readArgument } from './inEffect.js'; import { servedAbsence, servedLedger } from './served.js'; /** The facts the reader files for a door, before composition overrides its lists. */ function baseFacts(served, door, toolName) { const read = readCoverageResult(served, toolName)?.declared[0]; if (read !== undefined) return read; return { kind: door.door === 'declared-absence' ? 'absence' : 'ledger', coverage: { checked: [], notChecked: [], cannotCover: [] }, ...(door.period !== undefined && { period: door.period }), }; } /** * Compose one call's coverage from its search, or `undefined` when the value * came through no door (plain data: nothing is composed, nothing changes). * THROWS a refusal (`refused: …`) for a `coverage()` wrapped around a * declared absence — at the execute boundary, that is the call's error. * * @example * ```ts * const out = composeSearchCoverage(call, absent({ what: 'x', checked: 'declared' })); * out?.outcome === 'composed' && out.reading.declared[0]?.composed?.complete; * ``` */ export function composeSearchCoverage(call, result) { const door = readSearchDoor(result, call.toolName); if (door === undefined) return undefined; if (door.outcome === 'checked-beside-declared') { return { outcome: 'declined', code: 'checked-beside-declared' }; } const facts = door.facts; const readings = call.search.arguments.map((arg) => [arg, readArgument(arg, call.args, call.hostFilled)]); const checked = composeChecked({ search: call.search, readings, ...(facts.resolved !== undefined && { resolved: facts.resolved }), ...(facts.period !== undefined && { resultPeriod: facts.period }), ...(call.period !== undefined && { period: call.period }), ...(call.dispatchedAt !== undefined && { dispatchedAt: call.dispatchedAt }), }); const { gaps, notChecked, cannotCover } = composeGaps({ search: call.search, readings, rows: facts.rows, ...(facts.paging !== undefined && { paging: facts.paging }), ...(facts.period !== undefined && { period: facts.period }), ...(call.status !== undefined && { status: call.status }), handNotChecked: facts.handNotChecked, handCannotCover: facts.handCannotCover, }); const complete = call.origin === 'local' && call.search.complete === 'within-arguments' && !gaps.some(blocksComplete); const lists = { notChecked, cannotCover }; const value = facts.absence !== undefined ? servedAbsence(facts.absence, checked, lists) : facts.ledger !== undefined ? servedLedger(facts.ledger, checked, lists) : result; const base = baseFacts(value, facts, call.toolName); const composedFacts = { ...base, coverage: { checked, notChecked, cannotCover }, composed: { origin: call.origin, resultId: call.resultId, handle: call.handle, complete, gaps, }, }; return { outcome: 'composed', value, reading: { ...(facts.door === 'declared-absence' && { status: 'absent' }), declared: [composedFacts], }, }; } //# sourceMappingURL=compose.js.map