Add server.request_timeout config option (default: 600 seconds).
Previously hardcoded to 120 seconds which caused timeouts for
complex Opus queries.
Set to 0 to disable timeout entirely.
Closes #78
server:
port: 3000
host: "0.0.0.0"
+ # request_timeout: 600 # Seconds (0 = no timeout, default: 600)
# Providers - API endpoints
# Can be cloud (OpenAI, Anthropic, Azure) or self-hosted (vLLM, LiteLLM proxy, etc.)
server:
port: 3000
host: "0.0.0.0"
+ request_timeout: 600
```
| Option | Default | Description |
|--------|---------|-------------|
| `port` | `3000` | HTTP port |
| `host` | `0.0.0.0` | Bind address |
+| `request_timeout` | `600` | Request timeout in seconds (0 = no timeout) |
## Dashboard
const ServerSchema = z.object({
port: z.coerce.number().int().min(1).max(65535).default(3000),
host: z.string().default("0.0.0.0"),
+ request_timeout: z.coerce.number().int().min(0).default(600),
});
const LoggingSchema = z.object({
export type LocalProviderConfig = z.infer<typeof LocalProviderSchema>;
export type MaskingConfig = z.infer<typeof MaskingSchema>;
export type SecretsDetectionConfig = z.infer<typeof SecretsDetectionSchema>;
+export type ServerConfig = z.infer<typeof ServerSchema>;
/**
* Replaces ${VAR} and ${VAR:-default} patterns with environment variable values
-export const REQUEST_TIMEOUT_MS = 120_000;
export const HEALTH_CHECK_TIMEOUT_MS = 5_000;
* Anthropic client - simple functions for Anthropic Messages API
*/
-import type { AnthropicProviderConfig } from "../../config";
-import { REQUEST_TIMEOUT_MS } from "../../constants/timeouts";
+import { type AnthropicProviderConfig, getConfig } from "../../config";
import { ProviderError } from "../errors";
import type { AnthropicRequest, AnthropicResponse } from "./types";
headers["anthropic-beta"] = clientHeaders.beta;
}
+ const timeoutMs = getConfig().server.request_timeout * 1000;
const response = await fetch(`${baseUrl}/v1/messages`, {
method: "POST",
headers,
body: JSON.stringify(request),
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
+ signal: timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined,
});
if (!response.ok) {
* Used in route mode for PII-containing requests (no masking needed)
*/
-import type { LocalProviderConfig } from "../config";
-import { HEALTH_CHECK_TIMEOUT_MS, REQUEST_TIMEOUT_MS } from "../constants/timeouts";
+import { getConfig, type LocalProviderConfig } from "../config";
+import { HEALTH_CHECK_TIMEOUT_MS } from "../constants/timeouts";
import type { AnthropicResult } from "./anthropic/client";
import type { AnthropicRequest, AnthropicResponse } from "./anthropic/types";
import { ProviderError, type ProviderResult } from "./openai/client";
}
const isStreaming = request.stream ?? false;
+ const timeoutMs = getConfig().server.request_timeout * 1000;
const response = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify({ ...request, model: config.model, stream: isStreaming }),
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
+ signal: timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined,
});
if (!response.ok) {
}
const isStreaming = request.stream ?? false;
+ const timeoutMs = getConfig().server.request_timeout * 1000;
const response = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify({ ...request, model: config.model, stream: isStreaming }),
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
+ signal: timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined,
});
if (!response.ok) {
* OpenAI client - simple functions for OpenAI API
*/
-import type { OpenAIProviderConfig } from "../../config";
-import { REQUEST_TIMEOUT_MS } from "../../constants/timeouts";
+import { getConfig, type OpenAIProviderConfig } from "../../config";
import { ProviderError } from "../errors";
import type { OpenAIRequest, OpenAIResponse } from "./types";
delete body.max_tokens;
}
+ const timeoutMs = getConfig().server.request_timeout * 1000;
const response = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify(body),
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
+ signal: timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined,
});
if (!response.ok) {