mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:30:42 +00:00
fix(providers): bound native fetch timeouts
This commit is contained in:
@@ -35,6 +35,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Providers/Ollama: move memory embeddings to Ollama's current `/api/embed` endpoint with batched `input` requests while preserving vector normalization and custom provider auth/header overrides. Fixes #39983. Thanks @sskkcc and @LiudengZhang.
|
||||
- Providers/Ollama: route local web search through Ollama's signed `/api/experimental/web_search` daemon proxy, use hosted `/api/web_search` directly for `ollama.com`, and keep `OLLAMA_API_KEY` scoped to cloud fallback auth. Fixes #69132. Thanks @yoon1012 and @hyspacex.
|
||||
- Providers/Ollama: accept OpenAI SDK-style `baseURL` as an alias for `baseUrl` across discovery, streaming, setup pulls, embeddings, and web search so remote Ollama hosts are not silently ignored. Fixes #62533; supersedes #62549. Thanks @Julien-BKK and @Linux2010.
|
||||
- Providers/PDF/Ollama: add bounded network timeouts for Ollama model pulls and native Anthropic/Gemini PDF analysis requests so unresponsive provider endpoints no longer hang sessions indefinitely. Fixes #54142; supersedes #54144 and #54145. Thanks @jinduwang1001-max and @arkyu2077.
|
||||
- Memory/doctor: treat Ollama memory embeddings as key-optional so `openclaw doctor` no longer warns about a missing API key when the gateway reports embeddings are ready. Fixes #46584. Thanks @fengly78.
|
||||
- Agents/Ollama: apply provider-owned replay turn normalization to native Ollama chat so Cloud models no longer reject non-alternating replay history in agent/Gateway runs. Fixes #71697. Thanks @ismael-81.
|
||||
- Control UI/Ollama: show the resolved configured thinking default in chat and session thinking dropdowns so inherited `adaptive`/per-model thinking config no longer appears as `Default (off)` or a generic inherit value. Fixes #72407. Thanks @NotecAG.
|
||||
|
||||
@@ -417,6 +417,9 @@ describe("ollama setup", () => {
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(fetchMock.mock.calls[1][0]).toContain("/api/pull");
|
||||
const pullInit = fetchMock.mock.calls[1][1];
|
||||
expect(pullInit?.signal).toBeInstanceOf(AbortSignal);
|
||||
expect(pullInit?.signal?.aborted).toBe(false);
|
||||
});
|
||||
|
||||
it("skips pull when model is already available", async () => {
|
||||
|
||||
@@ -42,6 +42,7 @@ const OLLAMA_SUGGESTED_MODELS_LOCAL = [OLLAMA_DEFAULT_MODEL];
|
||||
const OLLAMA_SUGGESTED_MODELS_CLOUD = ["kimi-k2.5:cloud", "minimax-m2.7:cloud", "glm-5.1:cloud"];
|
||||
const OLLAMA_CONTEXT_ENRICH_LIMIT = 200;
|
||||
const OLLAMA_CLOUD_MAX_DISCOVERED_MODELS = 500;
|
||||
const OLLAMA_PULL_REQUEST_TIMEOUT_MS = 30_000;
|
||||
|
||||
type OllamaSetupOptions = {
|
||||
customBaseUrl?: string;
|
||||
@@ -172,6 +173,7 @@ async function pullOllamaModelCore(params: {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name: modelName }),
|
||||
},
|
||||
timeoutMs: OLLAMA_PULL_REQUEST_TIMEOUT_MS,
|
||||
policy: buildOllamaBaseUrlSsrFPolicy(baseUrl),
|
||||
auditContext: "ollama-setup.pull",
|
||||
});
|
||||
|
||||
@@ -78,6 +78,8 @@ describe("native PDF provider API calls", () => {
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
const [url, opts] = fetchMock.mock.calls[0];
|
||||
expect(url).toContain("/v1/messages");
|
||||
expect(opts.signal).toBeInstanceOf(AbortSignal);
|
||||
expect(opts.signal.aborted).toBe(false);
|
||||
const body = JSON.parse(opts.body);
|
||||
expect(body.model).toBe("claude-opus-4-6");
|
||||
expect(body.messages[0].content).toHaveLength(2);
|
||||
@@ -132,6 +134,8 @@ describe("native PDF provider API calls", () => {
|
||||
const [url, opts] = fetchMock.mock.calls[0];
|
||||
expect(url).toContain("generateContent");
|
||||
expect(url).toContain("gemini-2.5-pro");
|
||||
expect(opts.signal).toBeInstanceOf(AbortSignal);
|
||||
expect(opts.signal.aborted).toBe(false);
|
||||
const body = JSON.parse(opts.body);
|
||||
expect(body.contents[0].parts).toHaveLength(2);
|
||||
expect(body.contents[0].parts[0].inline_data.mime_type).toBe("application/pdf");
|
||||
|
||||
@@ -12,6 +12,8 @@ type PdfInput = {
|
||||
filename?: string;
|
||||
};
|
||||
|
||||
const NATIVE_PDF_PROVIDER_FETCH_TIMEOUT_MS = 120_000;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Anthropic – native PDF via Messages API
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -74,6 +76,7 @@ export async function anthropicAnalyzePdf(params: {
|
||||
max_tokens: params.maxTokens ?? 4096,
|
||||
messages: [{ role: "user", content }],
|
||||
}),
|
||||
signal: AbortSignal.timeout(NATIVE_PDF_PROVIDER_FETCH_TIMEOUT_MS),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -158,6 +161,7 @@ export async function geminiAnalyzePdf(params: {
|
||||
body: JSON.stringify({
|
||||
contents: [{ role: "user", parts }],
|
||||
}),
|
||||
signal: AbortSignal.timeout(NATIVE_PDF_PROVIDER_FETCH_TIMEOUT_MS),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
|
||||
Reference in New Issue
Block a user