UNPKG

agentfootprint

Version:

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

93 lines • 4.12 kB
"use strict"; /** * arguments/askMarker — how a reader recognises the inputs layer's OWN ask, * without loading the ask. * * Pattern: Map leaf. The reserved `context` key, its kind, the one reader of * them, and what the resume event may carry of an answer to it. * Role: core/ layer leaf of the inputs layer (honesty layer 2). Kept apart * from `ask.ts` — which loads through `import()` only when an ask is * raised (`test/trace-toolpack/browserGraph.test.ts`) — so a * reader on every agent's graph (`RunnerBase` · `emitPauseResume`) * can ask "was this pause the library's argument ask?" without * pulling the ask onto that graph. * Emits: N/A. * * ## Why the resume event never carries the answer * * The person's answer to the library's ask fills arguments a tool's own view * may hide (`core/toolShownArgs.ts` · `shownArgsOf`), and the layer's law is * that such a value appears on no row, no event, no served note and no ask * context. The `agentfootprint.pause.resume` event carries the reply it * resumed with, and every recording keeps that event. So for this ask the * event carries the reply's SHAPE — the request id, the field ids — with each * value read as `'REDACTED'`. The `answered` rows and their events already * carry what each tool's view allows. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.argumentAskReplyForEvent = exports.isArgumentAskPause = exports.isArgumentAskContext = exports.ARGUMENT_ASK_KIND = exports.ASK_CONTEXT_KEY = void 0; const rows_js_1 = require("./rows.js"); /** The reserved key of the ask's `context` — the library's marker. */ exports.ASK_CONTEXT_KEY = 'agentfootprint'; /** What the reserved key says this ask is. */ exports.ARGUMENT_ASK_KIND = 'arguments'; const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value); /** Whether an ask `context` carries the library's own marker (`{ agentfootprint: { ask: 'arguments' } }`). */ function isArgumentAskContext(context) { if (!isObject(context)) return false; const marker = context[exports.ASK_CONTEXT_KEY]; return isObject(marker) && marker.ask === exports.ARGUMENT_ASK_KIND; } exports.isArgumentAskContext = isArgumentAskContext; /** * Whether a pause's data is the inputs layer's own ask — read off * `pauseData.awaitingInput.context`, whatever else the data holds, and never * throwing on a shape it does not know (a reader of every pause kind must not * fail on one). */ function isArgumentAskPause(pauseData) { if (!isObject(pauseData)) return false; const awaiting = pauseData.awaitingInput; return isObject(awaiting) && isArgumentAskContext(awaiting.context); } exports.isArgumentAskPause = isArgumentAskPause; /** Keys of a reply that carry no answer — kept as they are on the event. */ const SHAPE_KEYS = new Set([ 'status', 'requestId', 'origins', 'origin', 'context', 'cancel', ]); /** * The reply to the library's ask as the resume event may carry it: the request * id, the status, the origins and the field ids, with every answered value — * and anything the reply carries that is not one of those keys — read as * `'REDACTED'`. A reply that is not an object is itself the answer, so it is * redacted whole. * * @example * ```ts * argumentAskReplyForEvent({ requestId: 'r1', values: { f1: 'ACCT-99' } }); * // { requestId: 'r1', values: { f1: 'REDACTED' } } * ``` */ function argumentAskReplyForEvent(reply) { if (!isObject(reply)) return { input: rows_js_1.HIDDEN_VALUE }; const out = {}; for (const [key, value] of Object.entries(reply)) { if (key === 'values' && isObject(value)) { out.values = Object.fromEntries(Object.keys(value).map((id) => [id, rows_js_1.HIDDEN_VALUE])); } else { out[key] = SHAPE_KEYS.has(key) ? value : rows_js_1.HIDDEN_VALUE; } } return out; } exports.argumentAskReplyForEvent = argumentAskReplyForEvent; //# sourceMappingURL=askMarker.js.map