UNPKG

trellis

Version:

Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications

66 lines (64 loc) 1.82 kB
// src/core/ontology/sync-policy.ts var RealtimeFieldError = class extends Error { field; status = 400; constructor(field) { super( `Field "${field}" has sync:realtime \u2014 use trellis/realtime, not durable mutate` ); this.name = "RealtimeFieldError"; this.field = field; } }; var EntityConflictError = class extends Error { id; status = 409; constructor(id) { super(`Entity already exists: ${id}`); this.name = "EntityConflictError"; this.id = id; } }; function effectiveFieldSync(field) { if (field.sync) return field.sync; if (field.valueType === "formula" || field.valueType === "rollup" || field.computed === true) { return "derived"; } return "durable"; } function findSchemaForType(ontologies, type) { const list = Array.from(ontologies); const byId = list.find((s) => s["@id"] === type); if (byId) return byId; const trellisId = `trellis:${type}`; const byTrellis = list.find((s) => s["@id"] === trellisId); if (byTrellis) return byTrellis; const byLabel = list.find( (s) => (s.tier ?? "user") !== "core" && (s.label === type || s["@id"].endsWith(`:${type}`)) ); return byLabel; } function filterDurableAttributes(attributes, schema) { if (!schema) return attributes; const byName = new Map(schema.fields.map((f) => [f.name, f])); const out = {}; for (const [key, value] of Object.entries(attributes)) { const field = byName.get(key); if (!field) { out[key] = value; continue; } const tier = effectiveFieldSync(field); if (tier === "derived") continue; if (tier === "realtime") throw new RealtimeFieldError(key); out[key] = value; } return out; } export { RealtimeFieldError, EntityConflictError, effectiveFieldSync, findSchemaForType, filterDurableAttributes };