@sema-agent/core
Version:
Stateless, task-oriented AI agent core
145 lines (144 loc) • 6.47 kB
JavaScript
import { createHash } from "node:crypto";
export function canonical(node) {
if (Array.isArray(node))
return `[${node.map(canonical).join(",")}]`;
if (node === null || typeof node !== "object")
return JSON.stringify(node);
const keys = Object.keys(node).sort();
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(node[k])}`).join(",")}}`;
}
export function digestOf(node) {
return `sha256:${createHash("sha256").update(canonical(node)).digest("hex")}`;
}
export function catalogDigestOf(catalog) {
return digestOf({
...catalog,
bands: [...catalog.bands].sort((a, b) => a.id.localeCompare(b.id)),
messages: [...catalog.messages].sort((a, b) => a.id.localeCompare(b.id)),
sections: [...catalog.sections].sort((a, b) => a.rank - b.rank),
});
}
export function promptIdentityOf(layers) {
return digestOf({
catalog: layers.catalog,
renderers: layers.renderers,
overlays: digestOf({ center: layers.center ?? null, deploy: layers.deploy ?? null, task: layers.task ?? null }),
binding: layers.binding,
});
}
export const PROMPT_EPOCH_ACTIVATIONS = Object.freeze(["session_start", "compaction", "code_change", "selection_change"]);
export const PROMPT_EPOCH_CHANGES = Object.freeze(["catalog", "renderers", "deploy", "task", "published_schema"]);
const DIGEST = /^sha256:[0-9a-f]{64}$/;
const isDigest = (v) => typeof v === "string" && DIGEST.test(v);
const RETIRED_DESCRIPTOR_FIELDS = Object.freeze(["artifactDigest", "packId", "assemblyApi", "centerArtifactDigest"]);
function normalizeLayers(raw) {
if (raw === null || typeof raw !== "object" || Array.isArray(raw))
return undefined;
const r = raw;
for (const k of Object.keys(r))
if (!["catalog", "renderers", "center", "deploy", "task", "binding"].includes(k))
return undefined;
if (!isDigest(r.catalog) || !isDigest(r.binding))
return undefined;
for (const k of ["center", "deploy", "task"])
if (r[k] !== undefined && !isDigest(r[k]))
return undefined;
const rv = r.renderers;
if (rv === null || typeof rv !== "object" || Array.isArray(rv))
return undefined;
const entries = Object.entries(rv);
if (entries.length > 64 || entries.some(([k, v]) => k.length === 0 || k.length > 64 || typeof v !== "number" || !Number.isInteger(v) || v < 1 || v > 1_000_000))
return undefined;
return {
catalog: r.catalog,
renderers: Object.fromEntries(entries),
...(r.center !== undefined ? { center: r.center } : {}),
...(r.deploy !== undefined ? { deploy: r.deploy } : {}),
...(r.task !== undefined ? { task: r.task } : {}),
binding: r.binding,
};
}
export function normalizePromptEpoch(raw) {
if (raw === null || typeof raw !== "object")
return undefined;
const r = raw;
if (typeof r.epoch !== "number" || !Number.isInteger(r.epoch) || r.epoch < 1 || r.epoch > 1_000_000_000)
return undefined;
if (!isDigest(r.identity))
return undefined;
const layers = normalizeLayers(r.layers);
if (layers === undefined || promptIdentityOf(layers) !== r.identity)
return undefined;
if (!PROMPT_EPOCH_ACTIVATIONS.some((a) => a === r.activatedBy))
return undefined;
const activatedBy = r.activatedBy;
let changed;
if (r.changed !== undefined) {
if (activatedBy !== "code_change" || !Array.isArray(r.changed) || r.changed.length === 0)
return undefined;
if (r.changed.some((c) => !PROMPT_EPOCH_CHANGES.some((w) => w === c)) || new Set(r.changed).size !== r.changed.length)
return undefined;
changed = [...r.changed];
}
if (r.sourceRevision !== undefined && (layers.center === undefined || typeof r.sourceRevision !== "string" || r.sourceRevision.length === 0 || r.sourceRevision.length > 500))
return undefined;
return {
epoch: r.epoch,
identity: r.identity,
layers,
activatedBy,
...(changed !== undefined ? { changed } : {}),
...(r.sourceRevision !== undefined ? { sourceRevision: r.sourceRevision } : {}),
};
}
export function readStoredPromptEpoch(raw) {
const descriptor = normalizePromptEpoch(raw);
if (descriptor !== undefined)
return { kind: "pin", descriptor };
if (raw === null || typeof raw !== "object")
return undefined;
const r = raw;
if (!RETIRED_DESCRIPTOR_FIELDS.some((f) => f in r))
return undefined;
return { kind: "legacy", centerPinned: isDigest(r.centerArtifactDigest) };
}
function changedLayers(a, b) {
const out = [];
if (a.catalog !== b.catalog)
out.push("catalog");
if (canonical(a.renderers) !== canonical(b.renderers))
out.push("renderers");
if (a.deploy !== b.deploy)
out.push("deploy");
if (a.task !== b.task)
out.push("task");
return out;
}
function descriptorOf(epoch, layers, activatedBy, extra) {
return {
epoch,
identity: promptIdentityOf(layers),
layers,
activatedBy,
...(extra.changed !== undefined && extra.changed.length > 0 ? { changed: [...extra.changed] } : {}),
...(layers.center !== undefined && extra.sourceRevision !== undefined ? { sourceRevision: extra.sourceRevision } : {}),
};
}
export function prepareEpochRecord(stored, layers, ctx) {
if (stored === undefined)
return descriptorOf(1, layers, ctx.priorConversation ? "code_change" : "session_start", ctx);
if (stored.kind === "legacy")
return descriptorOf(1, layers, "code_change", { ...ctx, ...(stored.centerPinned ? { changed: ["published_schema"] } : {}) });
const pinned = stored.descriptor;
if (pinned.identity === promptIdentityOf(layers))
return undefined;
const changed = changedLayers(pinned.layers, layers);
return descriptorOf(pinned.epoch + 1, layers, changed.length > 0 ? "code_change" : "selection_change", { ...ctx, changed });
}
export function selectCompactionEpoch(current, layers, sourceRevision) {
if (current !== undefined && current.identity === promptIdentityOf(layers)) {
const { changed: _recordOnly, ...restated } = current;
return { ...restated, activatedBy: "compaction" };
}
return descriptorOf((current?.epoch ?? 0) + 1, layers, "compaction", sourceRevision !== undefined ? { sourceRevision } : {});
}