UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

102 lines (101 loc) • 4.24 kB
import { createHash } from "node:crypto"; import { canonical } from "./epoch.js"; export const PREFIX_INPUT_CLASSIFICATION = { provider: "cache-identity", modelId: "cache-identity", artifactDigest: "cache-identity", promptProfile: "cache-identity", fableMitigations: "cache-identity", layoutGroups: "cache-identity", stableSystemText: "cache-identity", toolWire: "cache-identity", thinkingLevel: "cache-identity", maxTokens: "cache-identity", hasOutputSchema: "cache-identity", sessionId: "proven-irrelevant", taskId: "proven-irrelevant", turn: "volatile-no-reuse", cacheRead: "volatile-no-reuse", }; const sha = (text) => `sha256:${createHash("sha256").update(text, "utf8").digest("hex")}`; export const LOWERING_VERSION = "sema-lowering@1"; export function loweringRecordFor(api) { if (api.startsWith("anthropic")) { return { version: LOWERING_VERSION, form: "anthropic-blocks", intentionalDivergences: [ "system rides top-level `system` blocks (cache_control on the layout boundary), not a system message", "reasoning replays via provider-native thinking blocks", ], }; } if (api.startsWith("openai")) { return { version: LOWERING_VERSION, form: "openai-merged", intentionalDivergences: [ "multi-block system layouts merge into ONE system message (block boundaries erased — no per-block cache_control on this wire)", "reasoning-content replay is provider-dialect dependent (loss: some dialects drop replayed reasoning)", ], }; } return { version: LOWERING_VERSION, form: "other", intentionalDivergences: ["unknown wire family — lowering fidelity unverified"] }; } function identityOf(e) { return sha(canonical(e)); } export function buildTurnPromptSnapshot(raw, api, promptHasher) { const promptSha = promptHasher ?? sha; const lowering = loweringRecordFor(api); let requestPolicy = { thinkingLevel: raw.thinkingLevel, maxTokens: (raw.maxTokens ?? null), hasOutputSchema: raw.hasOutputSchema }; const elements = { provider: raw.provider, modelId: raw.modelId, artifactDigest: raw.artifactDigest, policyDigest: sha(canonical({ promptProfile: raw.promptProfile, fableMitigations: raw.fableMitigations })), layoutDigest: sha(canonical(raw.layoutGroups)), stableSystemDigest: promptSha(raw.stableSystemText), toolWireDigest: sha(canonical(raw.toolWire.map((t) => ({ name: t.name, description: t.description, parameters: t.parameters })))), requestPolicyDigest: sha(canonical(requestPolicy)), loweringVersion: `${lowering.version}/${lowering.form}/${api}`, }; const bump = () => { const next = identityOf(elements); if (next === snapshot.cacheIdentity) return; snapshot.cacheIdentity = next; snapshot.onChange?.(snapshot); }; const snapshot = { elements, cacheIdentity: "", lowering, refreshTools(toolWire) { elements.toolWireDigest = sha(canonical(toolWire.map((t) => ({ name: t.name, description: t.description, parameters: t.parameters })))); bump(); }, refreshStableSystem(stableSystemText, artifactDigest) { elements.stableSystemDigest = promptSha(stableSystemText); if (artifactDigest !== undefined) elements.artifactDigest = artifactDigest; bump(); }, refreshRequestPolicy(p) { requestPolicy = { ...requestPolicy, ...(p.thinkingLevel !== undefined ? { thinkingLevel: p.thinkingLevel } : {}), ...(p.maxTokens !== undefined ? { maxTokens: p.maxTokens } : {}), }; elements.requestPolicyDigest = sha(canonical(requestPolicy)); bump(); }, refreshModel(m) { elements.provider = m.provider; elements.modelId = m.modelId; bump(); }, }; snapshot.cacheIdentity = identityOf(elements); return snapshot; }