UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

276 lines • 10.5 kB
import { z } from 'zod'; import { units } from "./document.js"; import { admissionMatcher } from "./policy.js"; const key = z.number().int().nonnegative(); function sameLine(record, command, argv, cwd) { if (command === undefined || record.cwd !== cwd || record.command !== command || record.argv.length !== argv.length) return false; for (let index = 0; index < argv.length; index++) { if (record.argv[index] !== argv[index]) return false; } return true; } /** Decode one stateless approval result from the shared policy stream. */ export function approvalQuery(query, result) { return result.parse(admissionMatcher(null).ask('approvals', { query })); } /** One existing record, with an invocation-local identity distinct from its public id. */ export function recordWire(record, key, rule, argv, cwd) { return { keys: [key], rule, same_line: sameLine(record, argv[0], argv.slice(1), cwd), outcome: record.outcome, scope: record.scope, }; } /** Mechanical identity transport for a synchronous Rust approval query. */ export class ApprovalSnapshot { records; static RESPONSE = { keys: z.array(key), plan: z .object({ answers: z.array(key.nullable()), denied: key.nullable(), missing: z.array(key), once: z.array(key), waiting: z.array(key.nullable()), claim: z .object({ records: z.array(key), live: z.array(key) }) .strict() .nullable(), }) .strict(), claim: z.object({ records: z.array(key), live: z.array(key) }).strict(), handUp: z.object({ parent: key, claims: z.array(key), live: z.array(key) }).strict(), }; recordObjects; holderObjects = []; claimObjects = []; occurrenceObjects = []; recordKeys; holderKeys = new Map(); claimKeys = new Map(); occurrenceKeys = new Map(); live; constructor(records = [], live = [], roots = []) { this.records = records; this.recordObjects = [...records]; this.recordKeys = new Map(); this.live = [...live]; records.forEach((record, index) => this.recordKeys.set(record, index)); for (const holder of [...this.live, ...roots]) this.holderKey(holder); } recordKey(record) { const found = this.recordKeys.get(record); if (found !== undefined) return found; const key = this.recordObjects.length; this.recordObjects.push(record); this.recordKeys.set(record, key); return key; } holderKey(holder) { let node = holder; while (node !== null && !this.holderKeys.has(node)) { this.holderKeys.set(node, this.holderObjects.length); this.holderObjects.push(node); for (const claim of node.claimed) { if (!this.claimKeys.has(claim)) { this.claimKeys.set(claim, this.claimObjects.length); this.claimObjects.push(claim); this.recordKey(claim.decision); this.occurrenceKey(claim.occurrence); } } node = node.parent; } const found = this.holderKeys.get(holder); if (found === undefined) throw new Error('approval holder was not registered'); return found; } occurrenceKey(occurrence) { if (occurrence === null) return null; let node = occurrence; while (node !== null && !this.occurrenceKeys.has(node)) { this.occurrenceKeys.set(node, this.occurrenceObjects.length); this.occurrenceObjects.push(node); node = node.parent; } const found = this.occurrenceKeys.get(occurrence); if (found === undefined) throw new Error('approval occurrence was not registered'); return found; } record(key) { const record = this.recordObjects[key]; if (record === undefined) throw new Error('approval returned an unknown record'); return record; } holder(key) { const holder = this.holderObjects[key]; if (holder === undefined) throw new Error('approval returned an unknown holder'); return holder; } originalClaim(key) { const claim = this.claimObjects[key]; if (claim === undefined) throw new Error('approval returned an unknown claim'); return claim; } recordsWire(rules, argv, cwd) { const batches = []; let previous; const command = argv[0]; const args = argv.slice(1); this.records.forEach((record, index) => { const rule = rules[index]; if (rule === undefined) throw new Error('approval record has no rule key'); const line = sameLine(record, command, args, cwd); const outcome = record.outcome; const scope = record.scope; const key = this.recordKeys.get(record) ?? this.recordKey(record); if (previous?.rule === rule && previous.same_line === line && previous.outcome === outcome && previous.scope === scope) { previous.keys.push(key); } else { previous = { keys: [key], rule, same_line: line, outcome, scope }; batches.push(previous); } }); return batches; } get wire() { const sources = []; const sourceKeys = new Map(); const occurrences = this.occurrenceObjects.map((occurrence, key) => { let source = sourceKeys.get(occurrence.source); if (source === undefined) { source = sources.length; sourceKeys.set(occurrence.source, source); sources.push(units(occurrence.source)); } return { key, parent: this.occurrenceKey(occurrence.parent), source, start: occurrence.start, end: occurrence.end, }; }); return { holders: this.holderObjects.map((holder, key) => ({ key, parent: holder.parent === null ? null : this.holderKey(holder.parent), claims: holder.claimed.map((claim) => { const key = this.claimKeys.get(claim); if (key === undefined) throw new Error('approval claim was not registered'); return key; }), })), claims: this.claimObjects.map((claim, key) => ({ key, record: this.recordKey(claim.decision), occurrence: this.occurrenceKey(claim.occurrence), })), occurrences, sources, live: this.live.map((holder) => this.holderKey(holder)), }; } plan(recordRules, rules, argv, cwd, claimant) { const reader = claimant === null ? null : { holder: this.holderKey(claimant.line), occurrence: this.occurrenceKey(claimant.occurrence), }; const query = { kind: 'plan', state: { ...this.wire, records: this.recordsWire(recordRules, argv, cwd), }, rules: [...rules], claimant: reader, }; const result = approvalQuery(query, ApprovalSnapshot.RESPONSE.plan); return { answers: result.answers.map((key) => (key === null ? null : this.record(key))), denied: result.denied, missing: result.missing, once: result.once.map((key) => this.record(key)), waiting: result.waiting.map((key) => (key === null ? null : this.record(key))), claim: result.claim === null ? null : { records: result.claim.records.map((key) => this.record(key)), live: result.claim.live.map((key) => this.holder(key)), }, }; } waiting(argv, cwd) { const found = approvalQuery({ kind: 'waiting', records: this.recordsWire(Array(this.records.length).fill(0), argv, cwd), rule: 0, }, key.nullable()); return found === null ? null : this.record(found); } answer(id, outcome) { const found = approvalQuery({ kind: 'answer', records: this.records.map((record) => ({ key: this.recordKey(record), id: units(record.id), outcome: record.outcome, })), id: units(id), outcome, }, key.nullable()); return found === null ? null : this.record(found); } claim(holder, records) { const owner = this.holderKey(holder); const recordKeys = records.map((record) => this.recordKey(record)); const result = approvalQuery({ kind: 'claim', state: this.wire, holder: owner, records: recordKeys }, ApprovalSnapshot.RESPONSE.claim); return { records: result.records.map((key) => this.record(key)), live: result.live.map((key) => this.holder(key)), }; } split(holder, scope) { const owner = this.holderKey(holder); const occurrence = this.occurrenceKey(scope); return approvalQuery({ kind: 'split', state: this.wire, holder: owner, scope: occurrence }, ApprovalSnapshot.RESPONSE.keys).map((key) => this.originalClaim(key)); } handUp(holder) { const owner = this.holderKey(holder); const result = approvalQuery({ kind: 'hand_up', state: this.wire, holder: owner }, ApprovalSnapshot.RESPONSE.handUp); return { parent: this.holder(result.parent), claims: result.claims.map((key) => this.originalClaim(key)), live: result.live.map((key) => this.holder(key)), }; } revoke(holder) { const owner = this.holderKey(holder); return approvalQuery({ kind: 'revoke', state: this.wire, holder: owner }, ApprovalSnapshot.RESPONSE.keys).map((key) => this.record(key)); } } //# sourceMappingURL=approvals.js.map