mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
Merge pull request #9795 from Fatty911/docs/chunk-idle-timeout-silent-dropout
docs(cli): propagate chunkTimeout to streamText and document provider options
This commit is contained in:
@@ -388,6 +388,7 @@ You can also set options that apply to all models from a provider:
|
||||
| `apiKey` | `string` | API key (supports `{env:VAR}` syntax) |
|
||||
| `baseURL` | `string` | Override the provider's base API URL |
|
||||
| `timeout` | `number \| false` | Request timeout in milliseconds. Defaults to `300000` (5 minutes); set to `false` to disable |
|
||||
| `chunkTimeout` | `number` | Timeout in milliseconds between streamed response chunks. If no chunk arrives within this window, the request is aborted and retried. This catches silent provider dropouts where the TCP connection stays open but SSE streaming stops. Recommended: `15000`–`30000` (15–30 seconds) for providers with unreliable streaming. |
|
||||
|
||||
## Filtering Available Models
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ModelMessage } from "ai"
|
||||
import * as Stream from "effect/Stream"
|
||||
import type { LLMEvent } from "@opencode-ai/llm"
|
||||
import type { Logger } from "@opencode-ai/core/util/log"
|
||||
import type { Provider } from "@/provider/provider"
|
||||
import { KiloSessionOverflow } from "./overflow"
|
||||
|
||||
@@ -16,6 +17,22 @@ export namespace KiloLLM {
|
||||
)
|
||||
}
|
||||
|
||||
export function timeout(input: {
|
||||
options: Record<string, unknown>
|
||||
fallback?: Record<string, unknown>
|
||||
log?: Pick<Logger, "debug">
|
||||
}): { timeout?: { chunkMs: number } } {
|
||||
const value =
|
||||
typeof input.options["chunkTimeout"] === "number"
|
||||
? input.options["chunkTimeout"]
|
||||
: typeof input.fallback?.["chunkTimeout"] === "number"
|
||||
? input.fallback["chunkTimeout"]
|
||||
: undefined
|
||||
if (!value) return {}
|
||||
input.log?.debug("chunk idle timeout configured", { chunkTimeout: value })
|
||||
return { timeout: { chunkMs: value } }
|
||||
}
|
||||
|
||||
export function needsEstimate(input: { model: Provider.Model; configured: number | undefined }) {
|
||||
return input.configured !== undefined && input.configured > 0 && input.model.limit.context > 0
|
||||
}
|
||||
|
||||
@@ -373,6 +373,7 @@ const live: Layer.Layer<
|
||||
toolChoice: input.toolChoice,
|
||||
maxOutputTokens: prepared.params.maxOutputTokens,
|
||||
abortSignal: input.abort,
|
||||
...KiloLLM.timeout({ options: prepared.params.options, fallback: item.options, log: l }), // kilocode_change
|
||||
headers: prepared.headers,
|
||||
maxRetries: input.retries ?? 0,
|
||||
messages: prepared.messages,
|
||||
|
||||
@@ -3,6 +3,39 @@ import { Effect, Stream } from "effect"
|
||||
import { LLMEvent } from "@opencode-ai/llm"
|
||||
import { KiloLLM } from "@/kilocode/session/llm"
|
||||
|
||||
describe("kilocode.session.llm.timeout", () => {
|
||||
test("uses prepared options before the provider fallback", () => {
|
||||
const result = KiloLLM.timeout({
|
||||
options: { chunkTimeout: 15_000 },
|
||||
fallback: { chunkTimeout: 30_000 },
|
||||
})
|
||||
|
||||
expect(result).toEqual({ timeout: { chunkMs: 15_000 } })
|
||||
})
|
||||
|
||||
test("uses the provider fallback when prepared options omit the timeout", () => {
|
||||
const result = KiloLLM.timeout({
|
||||
options: {},
|
||||
fallback: { chunkTimeout: 30_000 },
|
||||
})
|
||||
|
||||
expect(result).toEqual({ timeout: { chunkMs: 30_000 } })
|
||||
})
|
||||
|
||||
test("uses the provider fallback when the prepared value is not a number", () => {
|
||||
const result = KiloLLM.timeout({
|
||||
options: { chunkTimeout: "15_000" },
|
||||
fallback: { chunkTimeout: 30_000 },
|
||||
})
|
||||
|
||||
expect(result).toEqual({ timeout: { chunkMs: 30_000 } })
|
||||
})
|
||||
|
||||
test("omits the timeout when it is not configured", () => {
|
||||
expect(KiloLLM.timeout({ options: {} })).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe("kilocode.session.llm.text", () => {
|
||||
test("joins text delta events", async () => {
|
||||
const out = await Effect.runPromise(
|
||||
|
||||
Reference in New Issue
Block a user