UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

255 lines (254 loc) • 12.9 kB
import { DEFAULT_CHARS_PER_TOKEN, estimateContextTokens } from "../../internal/harness.js"; import { TOOL_TURN_REPAIR_DROPS } from "../../internal/llm.js"; import { clearStaleToolResults, createClearedProjectionLedger, dropEmptyFailureAssistants, editBudget, replayClearedProjection, resolveTriggerWindow } from "../context-edit.js"; import { guardBudget, insertTrimNotice, protectGitFrame, trimToBudget } from "../context-guard.js"; import { AGGREGATE_MEDIA_BUDGET_BYTES, capAggregateMediaBytes } from "../media-byte-cap.js"; import { capAggregateToolResults } from "../tool-result-budget.js"; import { createOffloadPersist } from "../tool-result-store.js"; import { emitTrace } from "../trace.js"; import { deliverEngineNotice } from "../types.js"; import { applyGitFrameGuard } from "./git-status-frame.js"; import { applyContextShrinkToReadFileState } from "../../tools/fs/index.js"; import { rosterToolName } from "../tool-roster.js"; import { createToolTurnRepairSeat } from "./tool-turn-repair-seat.js"; export function prepareContextLane(input) { const { model, deps, sessionId, runId, hostTaskId, offloadStore, toolRosterDeltas, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, readFileState } = input; const toolNameOf = (recorded) => rosterToolName(toolRosterDeltas.current, recorded); const contextOverlay = input.contextOverlay ?? (() => undefined); const requestGeometry = () => { const current = harness.getModel(); const overlay = contextOverlay(); return { editAt: editBudget(current, overlay), guardAt: guardBudget(current, overlay), charsPerToken: current.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN }; }; const microCompact = buildMicroCompactState(deps, model, sessionId, runId, offloadStore, microCompactKnob, contextOverlay()); const charsPerToken = model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN; const announceRepairs = createToolTurnRepairSeat((notice) => deps.onNotice?.(notice), { sessionId, runId }); harness.onToolTurnRepaired = (repairs) => { if (repairs.some((repair) => TOOL_TURN_REPAIR_DROPS[repair.form])) requestLossyRef.current = true; announceRepairs(repairs); }; harness.on("context", async ({ messages, recheck, signal }) => { batchHaltRef.current = undefined; const pendingProjectionObservations = []; try { const { editAt, guardAt, charsPerToken: cpt } = requestGeometry(); const healed = dropEmptyFailureAssistants(messages); const replay = replayClearedProjection(healed, microCompact.ledger); const replayed = replay.messages; const capped = await capAggregateToolResults(replayed, { store: offloadStore, toolNameOf, sessionId, onCapped: (info) => pendingProjectionObservations.push(() => emitTrace(deps.tracer, () => ({ kind: "tool_result.capped", version: 1, taskId: hostTaskId, ...(info.tool !== undefined ? { tool: info.tool } : {}), sizeChars: info.sizeChars, storeFallback: info.storeFallback, ts: Date.now(), }))), }); const mediaCapped = capAggregateMediaBytes(capped, { limitBytes: deps.mediaByteCapBytes ?? AGGREGATE_MEDIA_BUDGET_BYTES, onStripped: (info) => { const onMediaStripped = deps.onMediaStripped; if (onMediaStripped !== undefined) pendingProjectionObservations.push(() => onMediaStripped(info)); }, }); let ccPass; const edited = microCompact.machine === "off" ? mediaCapped : clearStaleToolResults(mediaCapped, { budgetTokens: editAt, toolNameOf, clearSource: replayed, onCleared: (pass) => { ccPass = pass; }, anchoredTotalTokens: estimateContextTokens(mediaCapped, cpt).tokens, charsPerToken: cpt, ...(offloadStore ? { offload: { persist: createOffloadPersist(offloadStore, sessionId, deps.onNotice), }, } : {}), }); if (ccPass !== undefined) { recordFrontierClears({ pass: ccPass, index: replay.index, edited, ledger: microCompact.ledger, tracer: deps.tracer, taskId: hostTaskId, trigger: "frontier", ...(readFileState !== undefined ? { readFileState } : {}) }); } const chain = await runGuardChain({ edited, replayed, index: replay.index, microCompact, guardAt, charsPerToken: cpt, offloadStore, sessionId, taskId: hostTaskId, deps, trimPressureRef, recheck, signal, toolNameOf, pendingProjectionObservations, ...(readFileState !== undefined ? { readFileState } : {}), }); if ("earlyReturn" in chain) { return chain.earlyReturn; } const { working, trimDroppedMessages } = chain; let trimmed = chain.trimmed; trimmed = applyGitFrameGuard({ before: working, trimmed, budgetTokens: guardAt, ref: gitStatusRef, charsPerToken: cpt, onDegrade: (message) => { try { deps.onError?.(new Error(message), { phase: "degraded", sessionId, classification: "env-git-snapshot" }); } catch { } }, }); if (postureFrameRef.protectedText !== undefined) { const kept = protectGitFrame(working, trimmed, guardAt, { protectedText: postureFrameRef.protectedText }, cpt); if (kept.action === "kept" || kept.action === "reinserted") trimmed = kept.messages; } if (postureFrameRef.unwritten !== undefined) { let at = trimmed.length; while (at > 0 && trimmed[at - 1].role === "user") at--; trimmed = [...trimmed.slice(0, at), { role: "user", content: [{ type: "text", text: postureFrameRef.unwritten }], timestamp: Date.now(), engineMinted: true }, ...trimmed.slice(at)]; } requestLossyRef.current = replayed !== healed || capped !== replayed || mediaCapped !== capped || edited !== mediaCapped || working !== edited || trimDroppedMessages || gitStatusRef.overBudgetShrunk === true; microCompact.projectionRef.current = { messages: trimmed, keyOf: replay.index.keyOf }; return { messages: trimmed }; } finally { flushProjectionObservations(pendingProjectionObservations); } }); return { microCompact, charsPerToken }; } function buildMicroCompactState(deps, model, sessionId, runId, offloadStore, knob, overlay) { const triggerWindow = resolveTriggerWindow(model, overlay); if (triggerWindow.clamped) { deliverEngineNotice(deps.onNotice, { code: "config.autocompact_window_clamped", message: `model "${model.id}" declares autoCompactTokens=${triggerWindow.declaredAutoCompactTokens} ABOVE its physical window ` + `${triggerWindow.physicalWindow}; the autocompact window only ever LOWERS the trigger-side geometry, so the value was ` + `clamped to the physical window — fix the model config (declare a value at or below the physical window, or omit it)`, detail: { modelId: model.id, declaredAutoCompactTokens: triggerWindow.declaredAutoCompactTokens, physicalWindow: triggerWindow.physicalWindow, sessionId, runId, }, }); } return { machine: knob.machine, clearOnRejection: knob.clearOnRejection, ledger: createClearedProjectionLedger(), projectionRef: {}, inTurnCompactionRef: {}, ...(offloadStore ? { offloadPersist: createOffloadPersist(offloadStore, sessionId, deps.onNotice) } : {}), }; } export function landStaleResultClears(args) { const clearedToolCallIds = []; for (const c of args.cleared) { args.ledger.entries.set(c.key, { marker: c.marker, groupCount: c.groupCount, fp: c.fp }); if (c.toolCallId !== undefined) clearedToolCallIds.push(c.toolCallId); } if (args.readFileState !== undefined) { applyContextShrinkToReadFileState(args.readFileState, { kind: "tool-results-cleared", clearedToolCallIds }); } } function recordFrontierClears(args) { const landed = []; for (const { index } of args.pass.clears) { const at = args.index.keyAt(index); const clearedMsg = args.edited[index]; const markerText = clearedMsg.content?.[0]?.text; if (at !== undefined && typeof markerText === "string") { landed.push({ key: at.key, marker: markerText, groupCount: at.groupCount, fp: at.fp, ...(typeof clearedMsg.toolCallId === "string" ? { toolCallId: clearedMsg.toolCallId } : {}), }); } } landStaleResultClears({ ledger: args.ledger, cleared: landed, ...(args.readFileState !== undefined ? { readFileState: args.readFileState } : {}) }); emitTrace(args.tracer, () => ({ kind: "context.mc_clear", version: 1, taskId: args.taskId, clearedCount: args.pass.clears.length, tokensSavedEstimate: args.pass.tokensSavedEstimate, trigger: args.trigger, ts: Date.now(), })); } function flushProjectionObservations(pending) { for (const fire of pending.splice(0)) { try { fire(); } catch { } } } export async function runGuardChain(args) { const { edited, microCompact, guardAt, charsPerToken, deps, taskId } = args; const applyGuardTrim = (view, anchoredTotal) => { let trimmed = trimToBudget(view, guardAt, anchoredTotal, charsPerToken); const dropped = trimmed.length < view.length; if (dropped) { args.trimPressureRef.droppedMessages = true; const droppedCount = view.length - trimmed.length; trimmed = insertTrimNotice(trimmed); emitTrace(deps.tracer, () => ({ kind: "context.trim", version: 1, taskId, dropped: droppedCount, ts: Date.now(), })); } return { trimmed, dropped }; }; let working = edited; let anchoredWorking = estimateContextTokens(working, charsPerToken).tokens; if (microCompact.machine === "off" && anchoredWorking > guardAt) { let blockingPass; const blockingEdited = clearStaleToolResults(working, { budgetTokens: guardAt, toolNameOf: args.toolNameOf, clearSource: args.replayed, onCleared: (pass) => { blockingPass = pass; }, anchoredTotalTokens: anchoredWorking, charsPerToken, ...(args.offloadStore ? { offload: { persist: createOffloadPersist(args.offloadStore, args.sessionId, deps.onNotice) } } : {}), }); if (blockingPass !== undefined) { recordFrontierClears({ pass: blockingPass, index: args.index, edited: blockingEdited, ledger: microCompact.ledger, tracer: deps.tracer, taskId, trigger: "blocking", ...(args.readFileState !== undefined ? { readFileState: args.readFileState } : {}) }); working = blockingEdited; anchoredWorking = estimateContextTokens(working, charsPerToken).tokens; } } if (anchoredWorking > guardAt && args.recheck !== true) { const compacted = (await microCompact.inTurnCompactionRef.current?.(args.signal, anchoredWorking)) === true; if (compacted) { args.pendingProjectionObservations.length = 0; return { earlyReturn: { messages: working, adoptSessionRebuild: true } }; } if (args.signal?.aborted === true) { args.pendingProjectionObservations.length = 0; return { working, trimmed: working, trimDroppedMessages: false }; } } const t = applyGuardTrim(working, anchoredWorking); return { working, trimmed: t.trimmed, trimDroppedMessages: t.dropped }; }