Merge remote-tracking branch 'origin/master' into worktree/pr628-merge-20260727

# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md
#	docs/architecture.i18n.yaml
#	docs/config-catalog.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/llm-streaming.md
#	docs/core-data-structures/llm-streaming.zh.md
#	docs/event-producer-consumer.md
#	docs/module-graph.md
#	examples/headless-agent/tests/headless.snapshot.ts
#	packages/compact/compact-basic/tests/compact-loop-repro.spec.ts
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/src/loop.ts
#	packages/examples/agent-spine-demo/README.md
#	packages/llm/README.md
#	packages/llm/llm-deepseek/src/adapter.ts
#	packages/llm/llm-pi-ai/src/adapter.ts
#	packages/llm/llm-retry/README.md
#	packages/llm/llm/README.md
#	packages/llm/llm/src/index.ts
#	packages/llm/llm/tests/service.spec.ts
#	packages/support/llm-replay/src/index.ts
#	packages/support/llm-replay/tests/llm-replay.spec.ts
This commit is contained in:
Tianyi Cui
2026-07-27 22:44:43 +08:00
2019 changed files with 66577 additions and 16794 deletions

View File

@@ -13,9 +13,9 @@ import { decodeStorageRecord } from '@deepseek-ai/dsh-session'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
import type {
GenerateOptions,
LlmModelContext,
LlmModelInfo,
LlmProviderInfo,
LlmResolvedModelInfo,
ResolvedRetryPolicy,
RetryPolicyConfig,
StreamChunk,
@@ -69,10 +69,11 @@ export interface ReplayConfig {
*/
file: string
/**
* Optional `ReplayEntry[]` sidecar that REPLACES the derived script for the
* PRIMARY session. Used by the two single-session scenarios not expressible as
* `assistant/chunk` (pure throw-before-chunk, cancel/hang). Absent for normal
* and nested scenarios.
* Optional sidecar for the PRIMARY session: a bare `ReplayEntry[]` replaces
* the derived script; `{ patches }` keeps it and swaps the named call
* indexes ({@link ReplayOverrideDoc}). Used by single-session scenarios not
* expressible as `assistant/chunk` (throw-before-chunk, cancel/hang,
* injected transient failures). Absent for normal and nested scenarios.
*/
overrideFile?: string
/**
@@ -210,26 +211,157 @@ export function deriveReplayScript(events: SessionEvent[]): ReplayEntry[] {
}
/**
* Build the replay script for the PRIMARY session: the sidecar override if
* present, otherwise the script derived from the recorded session JSONL.
* Fail-loud if the JSONL fixture is missing (the scenario was never recorded) —
* never silently returns an empty script, so a coverage hole can't masquerade
* as a passing replay.
* One positional patch in an augmentation sidecar: replaces the derived
* entry at call index `at` (0-based) with `entry`, or appends when `at`
* equals the derived length (an extra recorded-after-the-fact call, e.g. the
* retry attempt following an injected transient throw).
*/
export interface ReplayOverridePatch {
/** 0-based call index into the derived script; == length appends. */
at: number
/** The replacement (or appended) entry at that call position. */
entry: ReplayEntry
}
/**
* Override sidecar document: either a whole-script replacement (a
* bare `ReplayEntry[]`) or the augmentation form `{ patches }`, which keeps
* the JSONL-derived script and swaps only the named call indexes — the shape
* for "turn N errors, everything else replays as recorded".
*/
export type ReplayOverrideDoc = ReplayEntry[] | { patches: ReplayOverridePatch[] }
const REPLAY_CHUNK_TYPES = new Set<StreamChunk['type']>([
'block-start',
'text-delta',
'reasoning-delta',
'tool-call-delta',
'block-end',
'usage',
'finish',
])
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
function hasExactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
return Object.keys(value).length === keys.length && keys.every(key => Object.hasOwn(value, key))
}
function invalidOverride(file: string, location: string, detail: string): never {
throw new Error(`llm-replay: invalid override ${file}: ${location} ${detail}`)
}
function readChunks(value: unknown, file: string, location: string): StreamChunk[] {
if (!Array.isArray(value)) invalidOverride(file, location, 'chunks must be an array')
for (const [index, chunk] of value.entries()) {
if (!isRecord(chunk)
|| typeof chunk['type'] !== 'string'
|| !REPLAY_CHUNK_TYPES.has(chunk['type'] as StreamChunk['type'])) {
invalidOverride(file, `${location}.chunks[${index}]`, 'must have a known StreamChunk type')
}
}
return value as StreamChunk[]
}
function readReplayEntry(value: unknown, file: string, location: string): ReplayEntry {
if (!isRecord(value)) invalidOverride(file, location, 'must be an object')
switch (value['kind']) {
case 'chunks': {
if (!hasExactKeys(value, ['kind', 'chunks'])) invalidOverride(file, location, 'has invalid chunks-entry fields')
return { kind: 'chunks', chunks: readChunks(value['chunks'], file, location) }
}
case 'throw': {
if (!hasExactKeys(value, ['kind', 'chunks', 'message', 'code'])) {
invalidOverride(file, location, 'has invalid throw-entry fields')
}
if (typeof value['message'] !== 'string' || value['message'].length === 0) {
invalidOverride(file, location, 'message must be a non-empty string')
}
if (typeof value['code'] !== 'string' || value['code'].length === 0) {
invalidOverride(file, location, 'code must be a non-empty string')
}
return {
kind: 'throw',
chunks: readChunks(value['chunks'], file, location),
message: value['message'],
code: value['code'],
}
}
case 'hang': {
const readyFile = value['readyFile']
const keys = readyFile === undefined ? ['kind'] : ['kind', 'readyFile']
if (!hasExactKeys(value, keys)) invalidOverride(file, location, 'has invalid hang-entry fields')
if (readyFile !== undefined && (typeof readyFile !== 'string' || readyFile.length === 0)) {
invalidOverride(file, location, 'readyFile must be a non-empty string')
}
return { kind: 'hang', ...(readyFile === undefined ? {} : { readyFile }) }
}
default:
return invalidOverride(file, location, `has unknown kind ${JSON.stringify(value['kind'])}`)
}
}
function readOverrideDoc(value: unknown, file: string): ReplayOverrideDoc {
if (Array.isArray(value)) return value.map((entry, index) => readReplayEntry(entry, file, `entry ${index}`))
if (!isRecord(value) || !hasExactKeys(value, ['patches']) || !Array.isArray(value['patches'])) {
return invalidOverride(file, 'document', 'must be a ReplayEntry[] or { patches: [...] }')
}
return {
patches: value['patches'].map((value, index): ReplayOverridePatch => {
const location = `patch ${index}`
if (!isRecord(value) || !hasExactKeys(value, ['at', 'entry'])) {
return invalidOverride(file, location, 'must contain exactly at and entry')
}
const at = value['at']
if (typeof at !== 'number' || !Number.isSafeInteger(at) || at < 0) {
return invalidOverride(file, location, 'at must be a non-negative safe integer')
}
return { at, entry: readReplayEntry(value['entry'], file, `${location}.entry`) }
}),
}
}
/**
* Load the PRIMARY session's replay script: the sidecar override when present
* (whole-script replacement or `{ patches }` augmentation over the derived
* script), else the script derived from the session JSONL (fail-loud when the
* fixture is missing).
* @param config - the fixture paths; only `file` and `overrideFile` are consulted.
* @returns the primary session's replay entries.
* @returns the resolved primary-session script.
*/
export function loadReplayScript(config: ReplayConfig): ReplayEntry[] {
if (config.overrideFile !== undefined && existsSync(config.overrideFile)) {
const parsed: unknown = JSON.parse(readFileSync(config.overrideFile, 'utf8'))
if (!Array.isArray(parsed)) {
throw new Error(`llm-replay: override is not a JSON array: ${config.overrideFile}`)
const doc = readOverrideDoc(JSON.parse(readFileSync(config.overrideFile, 'utf8')) as unknown, config.overrideFile)
if (Array.isArray(doc)) return doc
const script = deriveScriptFromFile(config.file)
const derivedLength = script.length
const seenIndexes = new Set<number>()
for (const patch of doc.patches) {
if (patch.at > derivedLength) {
throw new Error(
`llm-replay: override patch index ${String(patch.at)} out of range `
+ `(derived script has ${derivedLength} call(s); == length appends): ${config.overrideFile}`,
)
}
if (seenIndexes.has(patch.at)) {
throw new Error(`llm-replay: duplicate override patch index ${patch.at}: ${config.overrideFile}`)
}
seenIndexes.add(patch.at)
script[patch.at] = patch.entry
}
return parsed as ReplayEntry[]
return script
}
if (!existsSync(config.file)) {
throw new Error(`llm-replay: fixture not found: ${config.file} — run \`pnpm run test:snapshot:record\` first`)
return deriveScriptFromFile(config.file)
}
/** Derive the primary script from the session JSONL, failing loud on a missing fixture. */
function deriveScriptFromFile(file: string): ReplayEntry[] {
if (!existsSync(file)) {
throw new Error(`llm-replay: fixture not found: ${file} — run \`pnpm run test:snapshot:record\` first`)
}
return deriveReplayScript(parseSessionLog(readFileSync(config.file, 'utf8')))
return deriveReplayScript(parseSessionLog(readFileSync(file, 'utf8')))
}
/**
@@ -313,12 +445,20 @@ class ReplayAdapter extends LlmAdapter {
})))
}
override resolveModelContext(provider: string, model: string): Promise<LlmModelContext | undefined> {
override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
const configured = this.providers.get(provider)
/* v8 ignore next -- LlmService only asks about routes registered from this same map. */
if (configured === undefined) return Promise.resolve(undefined)
const contextWindow = configured.models?.find(candidate => candidate.id === model)?.contextWindow
return Promise.resolve(contextWindow === undefined ? undefined : { contextWindow })
if (configured === undefined) return Promise.resolve({ provider, id: model, name: model })
const configuredModel = configured.models?.find(candidate => candidate.id === model)
return Promise.resolve({
provider,
id: model,
name: configuredModel?.name ?? model,
...configuredModel?.description === undefined ? {} : { description: configuredModel.description },
...configuredModel?.contextWindow === undefined
? {}
: { context: { contextWindow: configuredModel.contextWindow } },
})
}
override stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
@@ -378,9 +518,8 @@ async function* replayEntry(entry: ReplayEntry, signal: AbortSignal | undefined,
})
/* v8 ignore next -- unreachable: the hang promise only ever rejects (on abort), never resolves; control never reaches here */
return
/* v8 ignore next -- sidecar entries are validated before they reach the closed local union. */
default:
// Closed local union: an unknown kind means malformed (hand-edited or
// drifted) sidecar data — fail loud with a runtime diagnostic.
return assertNever(entry, 'llm-replay replay entry')
}
}