UNPKG

agentfootprint

Version:

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

276 lines • 12.4 kB
"use strict"; /** * Row "It found" — what each call of this run returned, as the MODEL read it, * then the earlier answers' results that were in front of the model. * * Branches on the call's outcome first: a call that did not run "found nothing" * because it did not run; a withheld result is never judged empty (the model * read the rule's refusal, not the rows). Emptiness is typed only, read by the * one emptiness reader (`core/agent/emptiness.ts` · `readEmptiness`): * a declared absence (or an empty rowset inside a declared boundary), a * described result's data counted per kind, a question handed back, a * zero-length top-level array, or the app's declared `rowsAt` (then the line * is vouched `app`, because only the app's declaration makes it "empty"). */ Object.defineProperty(exports, "__esModule", { value: true }); exports.readFoundRow = exports.beforePausePointers = exports.inViewPointers = exports.inViewVars = void 0; const render_js_1 = require("../render.js"); const common_js_1 = require("./common.js"); const view_js_1 = require("../view.js"); const calls_js_1 = require("./calls.js"); const checked_js_1 = require("./checked.js"); const toolOf = (call) => call.tool; /** The declaration pointer behind an app-counted emptiness. */ function rowsAtPointers(ctx, toolName, source) { return source === 'app' ? [(0, common_js_1.declarationAt)(ctx.declarations, `tools.${toolName}.rowsAt`)] : []; } function foundForCall(ctx, call) { if (call.unnamed) { return ctx.say('found.unnamed', { vars: { id: call.tool }, status: 'not-recorded', missing: 'unreadable', pointers: call.fact.pointers, }); } const tool = toolOf(call); const end = call.end; const endPointers = end ? [(0, calls_js_1.endPointer)(end, call.emptiness)] : []; switch (call.fact.outcome) { case 'failed': return ctx.say('found.failed', { vars: { tool }, pointers: endPointers }); case 'refused': return ctx.say('found.refused', { vars: { tool }, pointers: endPointers }); case 'declined': return ctx.say('found.declined', { vars: { tool }, pointers: endPointers }); case 'not-dispatched': return ctx.say('found.notDispatched', { vars: { tool }, pointers: endPointers }); case 'unknown': return ctx.say('found.unknown', { vars: { tool }, status: 'not-recorded', missing: 'no-event', pointers: endPointers, }); case 'ran': break; } if (call.fact.withheldBy !== undefined && call.ruleEvent !== undefined) { return ctx.say('found.withheld', { vars: { tool, by: (0, render_js_1.v)(call.fact.withheldBy, 'library', (0, common_js_1.at)(call.ruleEvent, 'middleware')) }, pointers: [(0, common_js_1.at)(call.ruleEvent, 'moment'), (0, common_js_1.at)(call.ruleEvent, 'outcome')], }); } const reading = call.emptiness; const basis = [(0, common_js_1.emptinessSource)(reading)]; const extra = rowsAtPointers(ctx, call.toolName, reading.source); switch (reading.emptiness) { case 'declared-absent': { const lookedFor = call.coverage?.lookedFor; return lookedFor !== undefined ? ctx.say('found.absent', { vars: { tool, lookedFor: (0, render_js_1.v)(lookedFor.text, `tool:${call.fact.toolName}`, lookedFor.pointer), }, pointers: endPointers, }) : ctx.say('found.bare', { vars: { tool }, pointers: endPointers }); } case 'undeclared-empty': return ctx.say('found.undeclaredEmpty', { vars: { tool }, basis, pointers: [...endPointers, ...extra], chips: [(0, render_js_1.chip)('undeclared-empty', 'chip.undeclaredEmpty', 'warn')], }); case 'non-empty': if (reading.described !== undefined && call.described !== undefined) { return describedLines(ctx, call, reading.described); } return ctx.say('found.rows', { vars: { tool, n: (0, render_js_1.n)(reading.rows ?? 0, (0, common_js_1.emptinessSource)(reading)) }, pointers: [...endPointers, ...extra], }); case 'clarify': return ctx.say('found.clarify', { vars: { tool }, pointers: call.described ? [(0, common_js_1.at)(call.described, 'toolCallId')] : endPointers, }); case 'unknown': return ctx.say('found.result', { vars: { tool }, pointers: endPointers }); } } const DESCRIBED_LINES = { facts: 'found.described.facts', series: 'found.described.series', edges: 'found.described.edges', }; /** * A described result: one line per kind of data, counted by the library from * the envelope the record keeps (the `tools.semantics_declared` row — the model * read its projection), then the tool's own source and time when it declared * both. */ function describedLines(ctx, call, counts) { const event = call.described; const lines = []; for (const kind of ['facts', 'series', 'edges']) { const count = counts[kind]; if (count === undefined) continue; lines.push(ctx.say(DESCRIBED_LINES[kind], { vars: { tool: toolOf(call), n: (0, render_js_1.n)(count) }, pointers: [(0, common_js_1.at)(event, 'toolCallId')], })); } const semantics = event.payload.semantics; const provenance = (0, view_js_1.isRecord)(semantics) ? semantics.provenance : undefined; const source = (0, view_js_1.isRecord)(provenance) ? (0, view_js_1.str)(provenance.source) : undefined; const measuredAt = (0, view_js_1.isRecord)(provenance) ? (0, view_js_1.str)(provenance.measured_at) : undefined; if (source !== undefined && measuredAt !== undefined) { const by = `tool:${call.fact.toolName}`; lines.push(ctx.say('found.described.provenance', { vars: { tool: toolOf(call), source: (0, render_js_1.v)(source, by, (0, common_js_1.at)(event, 'semantics', 'provenance', 'source')), measuredAt: (0, render_js_1.v)(measuredAt, by, (0, common_js_1.at)(event, 'semantics', 'provenance', 'measured_at')), }, })); } return lines; } /** The vars every in-view line shares. */ function inViewVars(read) { return { tool: read.tool, distance: (0, render_js_1.n)(read.fact.distance), distanceWindowed: (0, render_js_1.n)(read.fact.windowed ? 1 : 0), }; } exports.inViewVars = inViewVars; /** Pointers behind an in-view line: the witness, the history row, the derived emptiness. */ function inViewPointers(ctx, read) { return [ (0, common_js_1.at)(read.witness, 'sourceId'), ...(read.reading.emptiness === 'unknown' ? [] : [(0, common_js_1.historyAt)(read.historyIndex, '#emptiness', read.fact.toolCallId)]), ...rowsAtPointers(ctx, read.toolName, read.reading.source), ]; } exports.inViewPointers = inViewPointers; function inViewLine(ctx, read) { const vars = inViewVars(read); const pointers = inViewPointers(ctx, read); switch (read.reading.emptiness) { case 'undeclared-empty': return ctx.say('found.inView.undeclaredEmpty', { vars, basis: [(0, common_js_1.emptinessSource)(read.reading)], pointers, chips: [(0, render_js_1.chip)('undeclared-empty', 'chip.undeclaredEmpty', 'warn')], }); case 'declared-absent': return ctx.say('found.inView.absent', { vars, pointers }); default: return ctx.say('found.inView', { vars, pointers }); } } /** Pointers behind a line about what came back from a call before the pause. */ function beforePausePointers(call) { return [ (0, common_js_1.historyAt)(call.historyIndex, '/toolName', call.toolCallId), ...(call.reading.emptiness === 'unknown' ? [] : [(0, common_js_1.historyAt)(call.historyIndex, '#emptiness', call.toolCallId)]), ]; } exports.beforePausePointers = beforePausePointers; /** * What came back from a call answered BEFORE the pause, as the model read it — * the tool's own bytes in the committed history, with the door its * `coverageDeclared` rows hold (`pausedLeg.ts`). Never "it ran": a rule's * verdict on it is in that part's events. */ function foundBeforePause(ctx, call) { const tool = call.tool; const reading = call.reading; const pointers = [ ...beforePausePointers(call), ...rowsAtPointers(ctx, call.toolName, reading.source), ]; const chips = [(0, checked_js_1.heldChip)()]; switch (reading.emptiness) { case 'declared-absent': { const lookedFor = call.coverage?.lookedFor; return lookedFor !== undefined ? ctx.say('found.beforePause.absent', { vars: { tool, lookedFor: (0, render_js_1.v)(lookedFor.text, `tool:${call.toolName.slice(0, common_js_1.FACT_TEXT_CHARS)}`, lookedFor.pointer), }, pointers, chips, }) : ctx.say('found.beforePause.bare', { vars: { tool }, pointers, chips }); } case 'undeclared-empty': return ctx.say('found.beforePause.undeclaredEmpty', { vars: { tool }, basis: [(0, common_js_1.emptinessSource)(reading)], pointers, chips: [(0, render_js_1.chip)('undeclared-empty', 'chip.undeclaredEmpty', 'warn'), ...chips], }); case 'non-empty': if (reading.rows !== undefined) { return ctx.say('found.beforePause.rows', { vars: { tool, n: (0, render_js_1.n)(reading.rows, (0, common_js_1.emptinessSource)(reading)) }, pointers, chips, }); } return ctx.say('found.beforePause.result', { vars: { tool }, pointers, chips }); case 'clarify': return ctx.say('found.beforePause.clarify', { vars: { tool }, pointers, chips }); case 'unknown': return ctx.say('found.beforePause.result', { vars: { tool }, pointers, chips }); } } function readFoundRow(ctx, calls, inView, pausedLeg) { const lines = calls.calls.slice(0, checked_js_1.MAX_LISTED_CALLS).flatMap((c) => foundForCall(ctx, c)); // The same "…and N more tool calls" the other call rows carry, right after the listed calls. const more = (0, checked_js_1.foldMore)(ctx, calls); if (more !== undefined) lines.push(more); if (ctx.resumedLeg && pausedLeg.stateHeld) { const before = pausedLeg.calls; lines.push(...before.slice(0, checked_js_1.MAX_LISTED_CALLS).map((c) => foundBeforePause(ctx, c))); const moreBefore = (0, checked_js_1.beforePauseMore)(ctx, before); if (moreBefore !== undefined) lines.push(moreBefore); if (before.length === 0) lines.push((0, checked_js_1.noResultsBeforePause)(ctx)); } else if (ctx.resumedLeg) { // No paused state in this record: nothing of the part before the pause can be read. lines.push(ctx.say('found.beforePause', { status: 'not-recorded', missing: 'before-pause', chips: [(0, render_js_1.chip)('before-pause', 'chip.beforePause')], })); } if (!ctx.resumedLeg && calls.all.length === 0) { lines.push(ctx.say('found.noCalls', { pointers: (0, checked_js_1.anchorPointer)(ctx) })); } lines.push(...inView.listed.map((read) => inViewLine(ctx, read))); if (inView.more > 0) { lines.push(ctx.say('found.inView.more', { vars: { n: (0, render_js_1.n)(inView.more) }, pointers: inView.all.slice(inView.listed.length).map((r) => (0, common_js_1.at)(r.witness, 'sourceId')), })); } return lines; } exports.readFoundRow = readFoundRow; //# sourceMappingURL=found.js.map