UNPKG

agentfootprint

Version:

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

392 lines • 16.7 kB
"use strict"; /** * Rows "It checked" and "It did not check" — one block per tool call of THIS * run, in call order, from what each tool DECLARED (`tools.absent` / * `tools.coverage_declared`). An item prints its declared `short` form, else its * full `what`, verbatim. More than five calls fold into `row.more@1`. * * A resumed leg never says "did not run any tools": the calls answered before * the pause are read from the committed state this record holds * (`pausedLeg.ts` · `readPausedLeg`) — each with what its tool declared, from * its `coverageDeclared` rows — and, when the record holds no committed * history, said to be out of this record. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.readCheckedRows = exports.foldMore = exports.noResultsBeforePause = exports.beforePauseMore = exports.anchorPointer = exports.heldChip = exports.declaredBeforePause = exports.MAX_LISTED_CALLS = void 0; const render_js_1 = require("../render.js"); const calls_js_1 = require("./calls.js"); const common_js_1 = require("./common.js"); /** Calls listed per row before folding. */ exports.MAX_LISTED_CALLS = 5; const toolOf = (call) => call.tool; const declaredOf = (call) => ({ ...(call.coverage !== undefined && { coverage: call.coverage }), tool: call.tool, toolName: call.fact.toolName, pointers: call.fact.pointers, }); /** A call answered before the pause, as its declaration's lines read it. */ const declaredBeforePause = (call) => ({ ...(call.coverage !== undefined && { coverage: call.coverage }), tool: call.tool, toolName: call.toolName.slice(0, common_js_1.FACT_TEXT_CHARS), pointers: [(0, common_js_1.historyAt)(call.historyIndex, '/toolName', call.toolCallId)], }); exports.declaredBeforePause = declaredBeforePause; /** The chip every line about the part before the pause carries, read from the state. */ const heldChip = () => (0, render_js_1.chip)('before-pause', 'chip.beforePause.held'); exports.heldChip = heldChip; /** The pointer that shows the rule that refused a call. */ function rulePointer(call) { const e = call.ruleEvent; if (e === undefined) return undefined; if (e.type.endsWith('middleware.decision')) return (0, common_js_1.at)(e, 'middleware'); if (e.type.endsWith('permission.check')) return (0, common_js_1.at)(e, 'policyRuleId'); if (e.type.endsWith('checkin.decision')) return (0, common_js_1.at)(e, 'approved'); return (0, common_js_1.at)(e, 'notExecuted'); } function itemLines(ctx, call, section, id) { const source = `tool:${call.toolName}`; const declared = call.coverage?.items.filter((i) => i.section === section) ?? []; // Items whose words the record keeps out: counted on one line, never printed. const kept = declared.filter((i) => i.keptOut === true); const all = declared.filter((i) => i.keptOut !== true); const items = []; for (const item of all) { if (!(0, common_js_1.takeItem)(ctx, Math.min((item.short ?? item.what).length, render_js_1.MAX_VAR_CHARS))) break; items.push(item); } const lines = items.map((item) => { const chips = item.kind === 'existence' ? [(0, render_js_1.chip)('kind', 'chip.kind.existence', 'warn')] : item.kind === 'scope' ? [(0, render_js_1.chip)('kind', 'chip.kind.scope')] : []; const kindPointer = item.kind !== undefined ? [(0, calls_js_1.itemAt)(item, 'kind')] : []; return item.short !== undefined ? ctx.say(id.short, { vars: { short: (0, render_js_1.v)(item.short, source, (0, calls_js_1.itemAt)(item, 'short')), tool: call.tool }, pointers: [(0, calls_js_1.itemAt)(item, 'what'), ...kindPointer], chips, item: true, }) : ctx.say(id.full, { vars: { what: (0, render_js_1.v)(item.what, source, (0, calls_js_1.itemAt)(item, 'what')), tool: call.tool }, pointers: kindPointer, chips, item: true, }); }); if (kept.length > 0) lines.push(ctx.say('items.keptOut', { vars: { n: (0, render_js_1.n)(kept.length) }, status: 'not-recorded', missing: 'redacted', pointers: kept.slice(0, exports.MAX_LISTED_CALLS).map((item) => (0, calls_js_1.itemAt)(item, 'what')), item: true, })); const omitted = all.length - items.length; if (omitted > 0) lines.push(ctx.say('items.more', { vars: { n: (0, render_js_1.n)(omitted) }, status: 'recorded', pointers: call.coverage ? [(0, calls_js_1.coverageHead)(call.coverage)] : [], item: true, })); return lines; } /** The one line an unnamed call gets: it is in the record, and no event names its tool. */ function unnamedLine(ctx, call) { return ctx.say('checked.unnamed', { vars: { id: call.tool }, status: 'not-recorded', missing: 'unreadable', pointers: call.fact.pointers, }); } function checkedBlock(ctx, call) { if (call.unnamed) return [unnamedLine(ctx, call)]; const tool = toolOf(call); const by = call.fact.refusedBy; const rule = rulePointer(call); const endPointers = call.fact.pointers; switch (call.fact.outcome) { case 'failed': return [ ctx.say('checked.failed', { vars: { tool }, pointers: call.end ? [(0, common_js_1.at)(call.end, 'error')] : [], }), ]; case 'refused': return [ by !== undefined && rule !== undefined ? ctx.say('checked.refused', { vars: { tool, by: (0, render_js_1.v)(by, 'library', rule) } }) : ctx.say('checked.refused.unnamed', { vars: { tool }, pointers: rule ? [rule] : endPointers, }), ]; case 'declined': return [ ctx.say('checked.declined', { vars: { tool }, pointers: rule ? [rule] : endPointers }), ]; case 'not-dispatched': return [ctx.say('checked.notDispatched', { vars: { tool }, pointers: endPointers })]; case 'unknown': return [ ctx.say('checked.unknown', { vars: { tool }, status: 'not-recorded', missing: 'no-event', pointers: endPointers, }), ]; case 'ran': { const checked = call.coverage?.items.filter((i) => i.section === 'checked') ?? []; if (call.coverage === undefined) { return [ ctx.say('checked.undeclared', { vars: { tool }, pointers: endPointers, chips: [(0, render_js_1.chip)('not-declared', 'chip.notDeclared')], }), ]; } if (checked.length === 0) { return [ ctx.say('checked.silent', { vars: { tool }, pointers: [(0, calls_js_1.coverageHead)(call.coverage)] }), ]; } return [ ctx.say('checked.declared', { vars: { tool }, pointers: [(0, calls_js_1.coverageHead)(call.coverage)], chips: [(0, render_js_1.chip)('declared', 'chip.declared')], }), ...itemLines(ctx, declaredOf(call), 'checked', { short: 'checked.item', full: 'checked.item.full', }), ]; } } } /** * The "It checked" block of a call answered BEFORE the pause — what its tool * declared, read from its `coverageDeclared` rows (`pausedLeg.ts`). Whether it * failed or was refused is in that part's events, so the line says what the * model read, never that the tool "ran". */ function checkedBeforePauseBlock(ctx, call) { const d = (0, exports.declaredBeforePause)(call); const checked = call.coverage?.items.filter((i) => i.section === 'checked') ?? []; if (call.coverage === undefined) { return [ ctx.say('checked.beforePause.undeclared', { vars: { tool: d.tool }, pointers: d.pointers, chips: [(0, render_js_1.chip)('not-declared', 'chip.notDeclared'), (0, exports.heldChip)()], }), ]; } if (checked.length === 0) { return [ ctx.say('checked.beforePause.silent', { vars: { tool: d.tool }, pointers: [(0, calls_js_1.coverageHead)(call.coverage)], chips: [(0, exports.heldChip)()], }), ]; } return [ ctx.say('checked.beforePause.declared', { vars: { tool: d.tool }, pointers: [(0, calls_js_1.coverageHead)(call.coverage)], chips: [(0, render_js_1.chip)('declared', 'chip.declared'), (0, exports.heldChip)()], }), ...itemLines(ctx, d, 'checked', { short: 'checked.item', full: 'checked.item.full' }), ]; } function notCheckedBlock(ctx, call, extra = []) { const tool = call.tool; if (call.coverage === undefined) { return [ ctx.say('notChecked.undeclared', { vars: { tool }, pointers: call.pointers, chips: [(0, render_js_1.chip)('not-declared', 'chip.notDeclared'), ...extra], }), ]; } const head = (0, calls_js_1.coverageHead)(call.coverage); const lines = []; const has = (section) => (call.coverage?.items ?? []).some((i) => i.section === section); if (has('notChecked')) { lines.push(ctx.say('notChecked.declared', { vars: { tool }, pointers: [head], chips: [(0, render_js_1.chip)('declared', 'chip.declared'), ...extra], }), ...itemLines(ctx, call, 'notChecked', { short: 'notChecked.item', full: 'notChecked.item.full', })); } else { lines.push(ctx.say('notChecked.silent', { vars: { tool }, pointers: [head], chips: [...extra] })); } if (has('cannotCover')) { lines.push(ctx.say('cannotCover.declared', { vars: { tool }, pointers: [head], chips: [(0, render_js_1.chip)('declared', 'chip.declared'), ...extra], }), ...itemLines(ctx, call, 'cannotCover', { short: 'cannotCover.item', full: 'cannotCover.item.full', })); } const other = call.coverage.tryInsteadTool; if (other !== undefined) { lines.push(ctx.say('tryInstead.tool', { vars: { tool, other: (0, render_js_1.v)(other.tool, `tool:${call.toolName}`, other.pointer, common_js_1.FACT_TEXT_CHARS), }, })); } return lines; } /** The anchor a "nothing ran" line points at: the end of the turn, else its start. */ function anchorPointer(ctx) { const anchor = ctx.view.last('agent.turn_end') ?? ctx.view.first('agent.turn_start') ?? ctx.view.events[0]; return anchor === undefined ? [] : [{ kind: 'event', index: anchor.index, type: anchor.type, path: '#meta/runId' }]; } exports.anchorPointer = anchorPointer; /** "…and N more tool calls from before the pause." — past `MAX_LISTED_CALLS` of them. */ function beforePauseMore(ctx, before) { const hidden = before.length - exports.MAX_LISTED_CALLS; if (hidden <= 0) return undefined; return ctx.say('beforePause.more', { vars: { n: (0, render_js_1.n)(hidden) }, pointers: before .slice(exports.MAX_LISTED_CALLS) .map((c) => (0, common_js_1.historyAt)(c.historyIndex, '/toolName', c.toolCallId)), chips: [(0, exports.heldChip)()], }); } exports.beforePauseMore = beforePauseMore; /** * The committed history holds no tool result from before the pause. Said as * exactly that — never "nothing ran": a window strategy may have dropped an * earlier result, and the record cannot tell the two apart. A history the * record keeps out (a redaction policy's placeholder) is said to be kept out. */ function noResultsBeforePause(ctx) { if (ctx.view.isStateKeptOut('history')) { return ctx.say('beforePause.keptOut', { status: 'not-recorded', missing: 'redacted', chips: [(0, exports.heldChip)()], }); } return ctx.say('beforePause.noResults', { status: 'not-recorded', missing: 'before-pause', chips: [(0, exports.heldChip)()], }); } exports.noResultsBeforePause = noResultsBeforePause; function foldMore(ctx, calls) { const hidden = Math.max(0, calls.calls.length - exports.MAX_LISTED_CALLS) + calls.omitted; if (hidden === 0) return undefined; const pointers = calls.calls.slice(exports.MAX_LISTED_CALLS).flatMap((c) => c.fact.pointers.slice(0, 1)); return ctx.say('row.more', { vars: { n: (0, render_js_1.n)(hidden) }, pointers, status: pointers.length > 0 ? 'recorded' : 'not-recorded', }); } exports.foldMore = foldMore; function readCheckedRows(ctx, calls, pausedLeg) { const listed = calls.calls.slice(0, exports.MAX_LISTED_CALLS); const checked = listed.flatMap((c) => checkedBlock(ctx, c)); // Listed: what the row PRINTS. Whether any call ran is a judgement — over every call, // on the outcome alone, named or not (R2-B1). const ranListed = listed.filter((c) => c.fact.outcome === 'ran'); const ranAll = calls.all.filter((c) => c.fact.outcome === 'ran'); const notChecked = ranListed.flatMap((c) => c.unnamed ? [ ctx.say('notChecked.unnamed', { vars: { id: c.tool }, status: 'not-recorded', missing: 'unreadable', pointers: c.fact.pointers, }), ] : notCheckedBlock(ctx, declaredOf(c))); if (ctx.resumedLeg && pausedLeg.stateHeld) { // The part before the pause, read from the committed state this record holds. const before = pausedLeg.calls; const shown = before.slice(0, exports.MAX_LISTED_CALLS); checked.push(...shown.flatMap((c) => checkedBeforePauseBlock(ctx, c))); notChecked.push(...shown.flatMap((c) => notCheckedBlock(ctx, (0, exports.declaredBeforePause)(c), [(0, exports.heldChip)()]))); const more = beforePauseMore(ctx, before); if (more !== undefined) { checked.push(more); notChecked.push(more); } if (before.length === 0) { checked.push(noResultsBeforePause(ctx)); if (notChecked.length === 0) notChecked.push(noResultsBeforePause(ctx)); } } else if (ctx.resumedLeg) { // No committed history in this record: nothing of the part before the pause can be read. checked.push(ctx.say('checked.beforePause.none', { status: 'not-recorded', missing: 'before-pause', chips: [(0, render_js_1.chip)('before-pause', 'chip.beforePause')], })); notChecked.push(ctx.say('notChecked.beforePause', { status: 'not-recorded', missing: 'before-pause', chips: [(0, render_js_1.chip)('before-pause', 'chip.beforePause')], })); } else if (calls.all.length === 0) { checked.push(ctx.say('checked.noCalls', { pointers: anchorPointer(ctx) })); notChecked.push(ctx.say('notChecked.noCalls', { status: 'not-applicable', pointers: anchorPointer(ctx) })); } else if (ranAll.length === 0) { notChecked.push(ctx.say('notChecked.noneRan', { status: 'not-applicable', pointers: calls.all.flatMap((c) => c.fact.pointers.slice(-1)), })); } else if (notChecked.length === 0) { // Calls ran, but none of the LISTED ones did: say where they are, never "none ran". notChecked.push(ctx.say('notChecked.notListed', { vars: { n: (0, render_js_1.n)(ranAll.length) }, pointers: ranAll.flatMap((c) => c.fact.pointers.slice(0, 1)), })); } const more = foldMore(ctx, calls); return { checked, notChecked, ...(more !== undefined && { checkedMore: more, notCheckedMore: more }), }; } exports.readCheckedRows = readCheckedRows; //# sourceMappingURL=checked.js.map