fix(llm): restore pruned status contract

This commit is contained in:
Tianyi Cui
2026-07-15 23:09:14 +08:00
parent abac7e4f44
commit bb1c8fa27d
9 changed files with 19 additions and 25 deletions

View File

@@ -20,7 +20,7 @@ import { LlmError, assertNever } from '@deepseek-ai/dsh-llm'
*/
export type ReplayEntry =
| { kind: 'chunks'; chunks: StreamChunk[] }
| { kind: 'throw'; chunks: StreamChunk[]; message: string; code: string; status?: number }
| { kind: 'throw'; chunks: StreamChunk[]; message: string; code: string }
| { kind: 'hang' }
/** Resolved plugin configuration. */
@@ -221,7 +221,7 @@ async function* replayEntry(entry: ReplayEntry, signal: AbortSignal | undefined)
if (signal?.aborted) throw new Error('aborted')
yield chunk
}
throw new LlmError(entry.message, entry.code, entry.status)
throw new LlmError(entry.message, entry.code)
case 'hang':
// Replay a stream that stalls until cancelled (mirrors MockAdapter): one
// chunk, then wait for abort and surface it as the consumer expects.

View File

@@ -175,7 +175,7 @@ describe('loadReplayScript', () => {
it('uses the sidecar override when present, ignoring the JSONL', () => {
writeFileSync(file, sessionJsonl([]), 'utf8')
const overrideFile = join(dir, 'replay.override.json')
const override: ReplayEntry[] = [{ kind: 'throw', chunks: [], message: '401', code: 'AUTH', status: 401 }]
const override: ReplayEntry[] = [{ kind: 'throw', chunks: [], message: '401', code: 'AUTH' }]
writeFileSync(overrideFile, JSON.stringify(override), 'utf8')
expect(loadReplayScript({ file, overrideFile })).toEqual(override)
})
@@ -231,12 +231,12 @@ describe('installLlmReplay (through the real waterfall)', () => {
expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(second)
})
it('replays a sidecar throw-entry as an LlmError with code/status, after its prefix chunks', async () => {
it('replays a sidecar throw-entry as an LlmError with its stable code, after its prefix chunks', async () => {
writeFileSync(file, sessionJsonl([]), 'utf8')
const overrideFile = join(dir, 'replay.override.json')
const partial: StreamChunk[] = [{ type: 'block-start', index: 0, blockType: 'text' }]
writeFileSync(overrideFile, JSON.stringify([
{ kind: 'throw', chunks: partial, message: 'unauthorized', code: 'AUTH', status: 401 },
{ kind: 'throw', chunks: partial, message: 'unauthorized', code: 'AUTH' },
]), 'utf8')
const ctx = new Context()
await ctx.plugin(LlmService)
@@ -245,7 +245,7 @@ describe('installLlmReplay (through the real waterfall)', () => {
const seen: StreamChunk[] = []
await expect((async () => {
for await (const c of ctx.llm.stream({ model: 'm', messages: [] })) seen.push(c)
})()).rejects.toMatchObject({ message: 'unauthorized', code: 'AUTH', status: 401 })
})()).rejects.toMatchObject({ message: 'unauthorized', code: 'AUTH' })
expect(seen).toEqual(partial)
})
@@ -350,7 +350,7 @@ describe('installLlmReplay (through the real waterfall)', () => {
const overrideFile = join(dir, 'replay.override.json')
const partial: StreamChunk[] = [{ type: 'block-start', index: 0, blockType: 'text' }]
writeFileSync(overrideFile, JSON.stringify([
{ kind: 'throw', chunks: partial, message: 'unauthorized', code: 'AUTH', status: 401 },
{ kind: 'throw', chunks: partial, message: 'unauthorized', code: 'AUTH' },
]), 'utf8')
const ctx = new Context()
await ctx.plugin(LlmService)