UNPKG

agentfootprint

Version:

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

130 lines • 6.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.stageDatasetArtifacts = exports.withDatasetArtifacts = void 0; const types_js_1 = require("./types.js"); const axis_js_1 = require("../time/axis.js"); const projection_js_1 = require("../semantics/projection.js"); /** * Adapt any local, HTTP-backed or MCP Tool using the SAME already-bound execution capability. * Claim-check: the host configures storage; the model carries tickets between tools. No UI required. * No store: pass through without calling the adapter; the host's normal result policy still applies. * Writes are independent, not a transaction. A failed source does not hide otherwise readable data; * its unavailable receipt must remain explicit in the producer's projection. Recheck tickets after * the batch because a later put can evict an earlier one. Expiry after publication remains possible. * This stages materialized payloads; it does not add remote handles, streaming or query pushdown. */ function withDatasetArtifacts(tool, adapter) { return { ...tool, async execute(args, ctx) { const result = await tool.execute(args, ctx); if (!ctx.hasArtifacts) return result; const semantics = (0, projection_js_1.snapshotProjectionSemantics)(result); const plan = await adapter.describe(result, args); if (plan === undefined) { const issues = (0, projection_js_1.projectionSemanticsIssues)(semantics, result); if (issues.length) throw new Error(issues[0].message); return result; } if (!plan || typeof plan.project !== 'function') { throw new TypeError('A dataset result plan requires a project function.'); } const projected = await plan.project(await stageDatasetArtifacts(plan.datasets, ctx.artifacts)); const issues = (0, projection_js_1.projectionSemanticsIssues)(semantics, projected); if (issues.length) throw new Error(issues[0].message); return projected; }, }; } exports.withDatasetArtifacts = withDatasetArtifacts; /** The same staging step for an existing tool pipeline that already owns execution and projection. */ async function stageDatasetArtifacts(datasets, artifacts) { assertInputs(datasets); const publications = []; for (const entry of datasets) { const source = entry.source ? await put(artifacts, entry.source) : undefined; const parentRefs = source?.status === 'stored' ? [...(entry.artifact.parentRefs ?? []), source.meta.ref] : entry.artifact.parentRefs; const artifact = await put(artifacts, { ...entry.artifact, ...(parentRefs && { parentRefs }) }); publications.push({ key: entry.key, artifact, ...(source && { source }) }); } const held = []; for (const publication of publications) { const artifact = await current(artifacts, publication.artifact); const source = publication.source ? await current(artifacts, publication.source) : undefined; held.push({ key: publication.key, artifact, ...(source && { source }) }); } return held; } exports.stageDatasetArtifacts = stageDatasetArtifacts; async function put(artifacts, input) { try { return { status: 'stored', meta: await artifacts.put(input) }; } catch { // Store exceptions may contain connection strings. The existing artifact event records the refusal. return { status: 'unavailable', reason: 'store-unavailable' }; } } async function current(artifacts, receipt) { if (receipt.status !== 'stored') return receipt; try { const meta = await artifacts.head(receipt.meta.ref); return meta ? { status: 'stored', meta } : { status: 'unavailable', reason: 'missing-or-expired' }; } catch { return { status: 'unavailable', reason: 'store-unavailable' }; } } /** Validate declaration shape before any writes. Payload serialization and parent proofs belong to the store. */ function assertInputs(datasets) { if (!Array.isArray(datasets)) { throw new TypeError('Dataset declarations must be an array.'); } const keys = new Set(); for (const entry of datasets) { if (!entry || typeof entry.key !== 'string' || entry.key.trim() === '' || keys.has(entry.key)) { throw new TypeError('Dataset keys must be nonempty and unique within one result.'); } keys.add(entry.key); for (const input of [entry.artifact, ...(entry.source === undefined ? [] : [entry.source])]) { if (!input || typeof input !== 'object' || Array.isArray(input) || typeof input.kind !== 'string' || !input.kind.trim() || typeof input.mediaType !== 'string' || !input.mediaType.trim() || !Object.prototype.hasOwnProperty.call(input, 'data')) { throw new TypeError('Each dataset/source artifact requires kind, mediaType and data.'); } // Judged BEFORE the first write: a malformed declaration refused at the // store would come back as a 'store-unavailable' receipt, which is a // different fact from "the producer declared something unreadable". if (input.timeAxis !== undefined) { const issues = (0, axis_js_1.timeAxisIssues)(input.timeAxis); if (issues.length > 0) { throw new types_js_1.InvalidArtifactError(`Dataset '${entry.key}': ${issues.join(' ')}`); } } if (input.parentRefs !== undefined) { if (!Array.isArray(input.parentRefs)) { throw new TypeError('Dataset/source parentRefs must be an array of strings.'); } for (const ref of input.parentRefs) { if (typeof ref !== 'string') { throw new TypeError('Dataset/source parentRefs must be an array of strings.'); } } } } } } //# sourceMappingURL=datasetResult.js.map