From ca7c3e571ef1f26b1ac4a52a800d566a147a1783 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Thu, 2 Apr 2026 23:37:50 -0700 Subject: [PATCH] =?UTF-8?q?fix(cowork-service):=20audit=20H.7=20=E2=80=94?= =?UTF-8?q?=20fix=20LLM=20timeout,=20harden=20test=20mocks,=20add=20Ollama?= =?UTF-8?q?=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug fixes from systematic review of H.7 LLM router wiring: - lib/llm-router.ts: remove RUST_RUNTIME_TIMEOUT_MS (300s IPC timeout) override — let LlmRouter use its built-in 30s default, appropriate for cloud API calls - server.test.ts: add debug/error to appMock.log — prevents fragile failures if any startup path hits those log levels - server.test.ts: add OLLAMA_URL + OLLAMA_MODELS to config mock New feature: - config.ts: add OLLAMA_URL + OLLAMA_MODELS env vars for local Ollama support - server.ts: wire Ollama env vars into initLlmRouter() — set OLLAMA_MODELS=model1,model2 to auto-add local Ollama as a provider 57 tests passing, 9 test files, typecheck clean --- .../AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log | 8 ++++---- services/cowork-service/src/lib/config.ts | 4 ++++ services/cowork-service/src/lib/llm-router.ts | 4 ++-- services/cowork-service/src/server.test.ts | 4 +++- services/cowork-service/src/server.ts | 4 ++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log index 5f187673..c001720f 100644 --- a/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log +++ b/__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/.last-refresh.log @@ -1,9 +1,9 @@ -Last refresh: 2026-04-03T06:00:06Z (2026-04-02 23:00:06 PDT) -Cascade conversations: 50 (297M) +Last refresh: 2026-04-03T06:28:08Z (2026-04-02 23:28:08 PDT) +Cascade conversations: 50 (298M) Memories: 121 Implicit context: 20 -Code tracker dirs: 106 -File edit history: 4222 entries +Code tracker dirs: 103 +File edit history: 4225 entries Workspace storage: 37 workspaces Repo docs: 7 files across 2 repos Repo workflows: 54 files across 12 repos diff --git a/services/cowork-service/src/lib/config.ts b/services/cowork-service/src/lib/config.ts index 9724a030..f3ef2a93 100644 --- a/services/cowork-service/src/lib/config.ts +++ b/services/cowork-service/src/lib/config.ts @@ -29,6 +29,10 @@ const envSchema = baseBackendConfigSchema.extend({ // Anthropic (passed through to Rust runtime) ANTHROPIC_API_KEY: z.string().optional(), + // LLM Router — local Ollama support (H.7) + OLLAMA_URL: z.string().default('http://localhost:11434/v1'), + OLLAMA_MODELS: z.string().optional(), + // Ecosystem toggles TELEMETRY_ENABLED: z.coerce.boolean().default(false), FEATURE_FLAGS_ENABLED: z.coerce.boolean().default(false), diff --git a/services/cowork-service/src/lib/llm-router.ts b/services/cowork-service/src/lib/llm-router.ts index 2f40746c..831dbb02 100644 --- a/services/cowork-service/src/lib/llm-router.ts +++ b/services/cowork-service/src/lib/llm-router.ts @@ -10,7 +10,6 @@ */ import { LlmRouter, createLocalOllamaProvider, type ProviderConfig, type TelemetryEntry } from '@bytelyst/llm-router'; -import { config } from './config.js'; let _router: LlmRouter | null = null; @@ -47,9 +46,10 @@ export function initLlmRouter(opts?: LlmRouterOptions): LlmRouter { // If no explicit providers, use defaults (cloud free-tier providers) const routerConfig = providers.length > 0 ? { providers } : undefined; + // Use LlmRouter's built-in 30s timeout — appropriate for cloud LLM API calls. + // (config.RUST_RUNTIME_TIMEOUT_MS is 300s and only for IPC, not HTTP.) _router = new LlmRouter({ ...routerConfig, - timeoutMs: config.RUST_RUNTIME_TIMEOUT_MS, onTelemetry: opts?.onTelemetry, }); diff --git a/services/cowork-service/src/server.test.ts b/services/cowork-service/src/server.test.ts index c1fe4e0d..9ffad68b 100644 --- a/services/cowork-service/src/server.test.ts +++ b/services/cowork-service/src/server.test.ts @@ -8,7 +8,7 @@ const appMock = { register: vi.fn(async () => undefined), inject: vi.fn(), get: vi.fn(), - log: { info: vi.fn(), warn: vi.fn() }, + log: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() }, addHook: vi.fn(), }; @@ -32,6 +32,8 @@ vi.mock('./lib/config.js', () => ({ RUST_RUNTIME_TIMEOUT_MS: 300_000, JWT_SECRET: 'test-secret', ANTHROPIC_API_KEY: undefined, + OLLAMA_URL: 'http://localhost:11434/v1', + OLLAMA_MODELS: undefined, }, })); vi.mock('./lib/product-config.js', () => ({ diff --git a/services/cowork-service/src/server.ts b/services/cowork-service/src/server.ts index c4665564..1f64b150 100644 --- a/services/cowork-service/src/server.ts +++ b/services/cowork-service/src/server.ts @@ -73,8 +73,12 @@ try { } // Initialize LLM router (best-effort — works without API keys in dev) +// Set OLLAMA_MODELS=model1,model2 to add local Ollama as a provider. +const ollamaModels = config.OLLAMA_MODELS?.split(',').map(s => s.trim()).filter(Boolean); try { const llm = initLlmRouter({ + ollamaModels, + ollamaBaseUrl: config.OLLAMA_URL, onTelemetry: (entry) => app.log.debug({ llmTelemetry: entry }, 'llm-router event'), }); app.log.info({ providers: llm.getProviders() }, 'LLM router initialized');