| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- /**
- * 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 = 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))
|