Merge latest master into codex/llm-error-recovery-rfc
# Conflicts: # docs/architecture.md # docs/config-catalog.md # docs/cordis-catalog/events.md # docs/event-producer-consumer.md # docs/module-graph.md # docs/persistence-catalog.md # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/agent-loop/src/loop.ts # packages/core/agent/src/types.ts # packages/examples/agent-spine-demo/README.md # packages/examples/stdio-demo/README.md # packages/examples/stdio-demo/src/index.ts # packages/llm/llm-deepseek/README.md # packages/llm/llm-deepseek/src/adapter.ts # packages/llm/llm-deepseek/tests/adapter.spec.ts # packages/llm/llm/README.md # packages/llm/llm/src/error.ts # packages/llm/llm/tests/service.spec.ts # packages/sandbox/sandbox-policy/tsconfig.json # packages/ui/stdio/README.md # packages/ui/stdio/src/index.ts # packages/ui/stdio/tests/stdio.spec.ts # packages/ui/tui/src/index.ts # pnpm-lock.yaml # website/zh-CN/api/harness/events.md # website/zh-CN/api/harness/llm.md
This commit is contained in:
@@ -159,23 +159,42 @@ export class DeepSeekAdapter extends LlmAdapter {
|
||||
|
||||
private async * request(options: GenerateOptions, signal: AbortSignal): AsyncIterable<StreamChunk> {
|
||||
const body = serializeRequest(options, this.options.defaults ?? {})
|
||||
// Prepared outside the try so the TRANSPORT label below covers exactly the
|
||||
// transport boundary, never a serialization failure.
|
||||
const payload = JSON.stringify(body)
|
||||
const headers = {
|
||||
'authorization': `Bearer ${this.options.apiKey}`,
|
||||
'content-type': 'application/json',
|
||||
'accept': 'text/event-stream',
|
||||
...attributionHeaders(),
|
||||
...options.sessionId !== undefined
|
||||
? { 'x-deepseek-harness-session-id': String(options.sessionId) }
|
||||
: {},
|
||||
}
|
||||
|
||||
// TODO(http): adopt the Cordis HTTP service when shared transport configuration
|
||||
// outweighs its additional runtime dependencies.
|
||||
const response = await fetch(`${this.options.baseURL}/chat/completions`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'authorization': `Bearer ${this.options.apiKey}`,
|
||||
'content-type': 'application/json',
|
||||
'accept': 'text/event-stream',
|
||||
...attributionHeaders(),
|
||||
...options.sessionId !== undefined
|
||||
? { 'x-deepseek-harness-session-id': String(options.sessionId) }
|
||||
: {},
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal,
|
||||
})
|
||||
let response: Response
|
||||
try {
|
||||
response = await fetch(`${this.options.baseURL}/chat/completions`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: payload,
|
||||
signal,
|
||||
})
|
||||
} catch (error: unknown) {
|
||||
// The outer stream distinguishes caller cancellation and watchdog expiry.
|
||||
if (signal.aborted) throw error
|
||||
// fetch wraps every transport failure (DNS, refused connection, TLS,
|
||||
// proxy) in a bare `TypeError: fetch failed` whose actionable detail
|
||||
// lives on `cause`. Wrapping with the endpoint and chaining the cause
|
||||
// lets `errorChain` render the full diagnosis at every reporting seam.
|
||||
throw new LlmError(
|
||||
`DeepSeek API request to ${this.options.baseURL} failed`,
|
||||
'TRANSPORT',
|
||||
{ cause: error },
|
||||
)
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
let message = `DeepSeek API error (HTTP ${response.status})`
|
||||
|
||||
Reference in New Issue
Block a user