@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
276 lines • 10.5 kB
JavaScript
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