/** * Package-owned request-reconstruction invariant for loop-built LLM calls. * @module @deepseek-ai/dsh-agent-loop/invariant */ import type { Context } from 'cordis' import { isAgentLoopRequest, type GenerateOptions } from '@deepseek-ai/dsh-llm' import type { InvariantFailure, InvariantInstaller } from '@deepseek-ai/dsh-invariants' import { Session, SessionId, foldRequestHeader } from '@deepseek-ai/dsh-session' const PACKAGE_NAME = '@deepseek-ai/dsh-agent-loop' /** Cordis companion plugin name. */ export const name = 'agent-loop-invariant' /** Service required before the companion can reserve package ownership. */ export const inject = ['invariants'] /** Install the request-reconstruction contribution into its child registration fiber. */ const install: InvariantInstaller = Object.assign((ctx: Context, fail: InvariantFailure) => { // Prepend prevents a short-circuiting replay listener from silencing the // check; correctness itself comes from the sequence-bounded reconstruction. ctx.on('llm/stream', (options: GenerateOptions, next) => { if (!isAgentLoopRequest(options)) return next() if (!Object.isFrozen(options)) fail('a loop-built request must be frozen') if (options.sessionId === undefined) fail('a loop-built request must carry a session id') const session = ctx.sessions.get(options.sessionId) if (!session) fail(`a loop-built request must carry a live session id, got "${String(options.sessionId)}"`) if (!Object.isFrozen(options.messages)) { fail('a loop-built request must carry a frozen messages array') } const events = session.events let boundary = -1 for (let index = events.length - 1; index >= 0; index -= 1) { if (events[index]?.type === 'step/start') { boundary = index break } } if (boundary === -1) { return fail('a loop-built request with no step/start in its session log') } const header = foldRequestHeader(events) if (header === undefined) { return fail('a loop-built request with no request/header event in its session log') } const rebuilt = new Session( SessionId(`${String(session.id)}-invariant-rebuild`), structuredClone(events.slice(0, boundary)), ) const expected = [...header.messagePrefix ?? [], ...rebuilt.deriveMessages()] if (JSON.stringify(options.messages) !== JSON.stringify(expected)) { fail(`llm request for session "${String(session.id)}" diverges from the boundary derivation (log-reconstruction desync)`) } const headerMatches = options.model === header.config.model && options.system === header.system && options.temperature === header.config.temperature && options.maxTokens === header.config.maxTokens && JSON.stringify(options.stop) === JSON.stringify(header.config.stop) && JSON.stringify(options.tools ?? []) === JSON.stringify(header.tools ?? []) if (!headerMatches) { fail(`llm request for session "${String(session.id)}" diverges from the folded request header`) } return next() }, { global: true, prepend: true }) }, { inject: ['sessions'] }) /** * Register the agent-loop invariant companion. * @param ctx - Cordis context carrying the invariant service. * @returns the installed registration's disposer after setup succeeds. */ export const apply = (ctx: Context): Promise<() => void> => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))