UNPKG

agentfootprint

Version:

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

159 lines • 8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.queriedPeriodMatches = exports.scopesMatch = exports.executedScope = exports.scopeDeclarationOf = exports.ownConfigArray = exports.boundedResultId = exports.boundedText = exports.BINDING_LIMITS = void 0; /** Authored scope projection over the arguments actually delivered to execute. */ const boundedJson_js_1 = require("../../lib/boundedJson.js"); const canonicalJson_js_1 = require("../../lib/canonicalJson.js"); const instant_js_1 = require("../../time/instant.js"); const period_js_1 = require("../../semantics/coverage/period.js"); exports.BINDING_LIMITS = Object.freeze({ text: 512, resultIdText: 3104, dimensions: 16, path: 16, scopeBytes: 8192, resultBytes: 256 * 1024, snapshotBytes: 1024 * 1024, results: 256, }); function boundedText(value) { return typeof value === 'string' && value.trim() !== '' && value.length <= exports.BINDING_LIMITS.text; } exports.boundedText = boundedText; function boundedResultId(value) { return (typeof value === 'string' && value.startsWith('claim-result/') && value.length <= exports.BINDING_LIMITS.resultIdText); } exports.boundedResultId = boundedResultId; /** Shallow descriptor-only admission for authored arrays containing callbacks. */ function ownConfigArray(value, maximum) { if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) throw new Error('Expected a plain configuration array.'); const length = Object.getOwnPropertyDescriptor(value, 'length')?.value; if (typeof length !== 'number' || !Number.isSafeInteger(length) || length > maximum || Reflect.ownKeys(value).length !== length + 1) throw new Error('Invalid configuration array.'); const items = []; for (let index = 0; index < length; index++) { const descriptor = Object.getOwnPropertyDescriptor(value, String(index)); if (!descriptor?.enumerable || !('value' in descriptor)) throw new Error('Expected dense configuration data.'); items.push(descriptor.value); } return Object.freeze(items); } exports.ownConfigArray = ownConfigArray; /** Inspect authored configuration without evaluating getters or inherited fields. */ function scopeDeclarationOf(raw) { const source = (0, boundedJson_js_1.ownData)(raw, ['id', 'version', 'dimensions', 'periodDimension']); const sourceDimensions = ownConfigArray(source.dimensions, exports.BINDING_LIMITS.dimensions); if (!boundedText(source.id) || !boundedText(source.version) || sourceDimensions.length === 0) throw new Error('Invalid scope declaration.'); const names = new Set(); const dimensions = sourceDimensions.map((rawDimension) => { const dimension = (0, boundedJson_js_1.ownData)(rawDimension, ['name', 'argumentPath', 'default', 'normalize']); const path = (0, boundedJson_js_1.copyJson)(dimension.argumentPath, exports.BINDING_LIMITS.scopeBytes, true); if (!boundedText(dimension.name) || names.has(dimension.name) || !Array.isArray(path) || path.length === 0 || path.length > exports.BINDING_LIMITS.path || !path.every(boundedText) || (Object.hasOwn(dimension, 'normalize') && typeof dimension.normalize !== 'function')) throw new Error('Invalid scope dimension.'); names.add(dimension.name); return Object.freeze({ name: dimension.name, argumentPath: path, ...(Object.hasOwn(dimension, 'default') && { default: (0, boundedJson_js_1.copyJson)(dimension.default, exports.BINDING_LIMITS.scopeBytes, true), }), ...(typeof dimension.normalize === 'function' && { normalize: dimension.normalize, }), }); }); if (Object.hasOwn(source, 'periodDimension') && (!boundedText(source.periodDimension) || !names.has(source.periodDimension))) throw new Error('Invalid period dimension.'); return Object.freeze({ id: source.id, version: source.version, dimensions: Object.freeze(dimensions), ...(typeof source.periodDimension === 'string' && { periodDimension: source.periodDimension }), }); } exports.scopeDeclarationOf = scopeDeclarationOf; /** Own data properties only: inherited names and accessors supply no scope. */ function argumentAt(args, path) { if (path.length === 0 || path.length > exports.BINDING_LIMITS.path || !path.every(boundedText)) throw new Error('Invalid scope path.'); let cursor = args; for (const key of path) { if (cursor === null || typeof cursor !== 'object') return undefined; const descriptor = Object.getOwnPropertyDescriptor(cursor, key); if (descriptor === undefined) { if (key in cursor) throw new Error('Inherited scope is not executed own-data.'); return undefined; } if (!descriptor.enumerable || !('value' in descriptor)) throw new Error('Scope requires own data.'); cursor = descriptor.value; } return cursor; } function executedScope(args, declaration) { declaration = scopeDeclarationOf(declaration); const scope = {}; for (const dimension of declaration.dimensions) { if (!boundedText(dimension.name) || Object.hasOwn(scope, dimension.name)) throw new Error('Invalid scope dimension.'); let value = argumentAt(args, dimension.argumentPath); if (value === undefined && Object.hasOwn(dimension, 'default')) value = dimension.default; if (value === undefined) throw new Error('Required scope is missing.'); // Detach BEFORE invoking an authored normalizer: it cannot mutate dispatch. value = (0, boundedJson_js_1.copyJson)(value, exports.BINDING_LIMITS.scopeBytes, true); if (dimension.normalize !== undefined) value = dimension.normalize(value); Object.defineProperty(scope, dimension.name, { value: (0, boundedJson_js_1.copyJson)(value, exports.BINDING_LIMITS.scopeBytes, true), enumerable: true, }); } if (declaration.periodDimension !== undefined && !Object.hasOwn(scope, declaration.periodDimension)) throw new Error('The period dimension is missing.'); return (0, boundedJson_js_1.copyJson)(scope, exports.BINDING_LIMITS.scopeBytes, true); } exports.executedScope = executedScope; /** Exact declared dimensions; no inferred subset, defaults or currency conversion. */ function scopesMatch(evidence, intended) { const expected = (0, boundedJson_js_1.ownData)((0, boundedJson_js_1.copyJson)(intended, exports.BINDING_LIMITS.scopeBytes, true)); return (0, canonicalJson_js_1.canonicalJson)(evidence) === (0, canonicalJson_js_1.canonicalJson)(expected); } exports.scopesMatch = scopesMatch; /** The existing period/instant owners decide validity and temporal equivalence. */ function queriedPeriodMatches(scopeValue, period) { const query = (0, boundedJson_js_1.ownData)(scopeValue, ['from', 'to']); if ((0, period_js_1.periodProblem)({ queried: query, held: 'unknown' }, 'camel') !== undefined) return false; const from = (0, instant_js_1.instantOf)(query.from, 'lenient'); const to = (0, instant_js_1.instantOf)(query.to, 'lenient'); const actualFrom = (0, instant_js_1.instantOf)(period.queried.from, 'lenient'); const actualTo = (0, instant_js_1.instantOf)(period.queried.to, 'lenient'); return (from !== undefined && to !== undefined && actualFrom !== undefined && actualTo !== undefined && (0, instant_js_1.compareInstants)(from, actualFrom) === 0 && (0, instant_js_1.compareInstants)(to, actualTo) === 0); } exports.queriedPeriodMatches = queriedPeriodMatches; //# sourceMappingURL=scope.js.map