fix(cowork-service): audit H.7 — fix LLM timeout, harden test mocks, add Ollama config
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
This commit is contained in:
parent
f542160784
commit
ca7c3e571e
@ -1,9 +1,9 @@
|
|||||||
Last refresh: 2026-04-03T06:00:06Z (2026-04-02 23:00:06 PDT)
|
Last refresh: 2026-04-03T06:28:08Z (2026-04-02 23:28:08 PDT)
|
||||||
Cascade conversations: 50 (297M)
|
Cascade conversations: 50 (298M)
|
||||||
Memories: 121
|
Memories: 121
|
||||||
Implicit context: 20
|
Implicit context: 20
|
||||||
Code tracker dirs: 106
|
Code tracker dirs: 103
|
||||||
File edit history: 4222 entries
|
File edit history: 4225 entries
|
||||||
Workspace storage: 37 workspaces
|
Workspace storage: 37 workspaces
|
||||||
Repo docs: 7 files across 2 repos
|
Repo docs: 7 files across 2 repos
|
||||||
Repo workflows: 54 files across 12 repos
|
Repo workflows: 54 files across 12 repos
|
||||||
|
|||||||
@ -29,6 +29,10 @@ const envSchema = baseBackendConfigSchema.extend({
|
|||||||
// Anthropic (passed through to Rust runtime)
|
// Anthropic (passed through to Rust runtime)
|
||||||
ANTHROPIC_API_KEY: z.string().optional(),
|
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
|
// Ecosystem toggles
|
||||||
TELEMETRY_ENABLED: z.coerce.boolean().default(false),
|
TELEMETRY_ENABLED: z.coerce.boolean().default(false),
|
||||||
FEATURE_FLAGS_ENABLED: z.coerce.boolean().default(false),
|
FEATURE_FLAGS_ENABLED: z.coerce.boolean().default(false),
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { LlmRouter, createLocalOllamaProvider, type ProviderConfig, type TelemetryEntry } from '@bytelyst/llm-router';
|
import { LlmRouter, createLocalOllamaProvider, type ProviderConfig, type TelemetryEntry } from '@bytelyst/llm-router';
|
||||||
import { config } from './config.js';
|
|
||||||
|
|
||||||
let _router: LlmRouter | null = null;
|
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)
|
// If no explicit providers, use defaults (cloud free-tier providers)
|
||||||
const routerConfig = providers.length > 0 ? { providers } : undefined;
|
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({
|
_router = new LlmRouter({
|
||||||
...routerConfig,
|
...routerConfig,
|
||||||
timeoutMs: config.RUST_RUNTIME_TIMEOUT_MS,
|
|
||||||
onTelemetry: opts?.onTelemetry,
|
onTelemetry: opts?.onTelemetry,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const appMock = {
|
|||||||
register: vi.fn(async () => undefined),
|
register: vi.fn(async () => undefined),
|
||||||
inject: vi.fn(),
|
inject: vi.fn(),
|
||||||
get: 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(),
|
addHook: vi.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,6 +32,8 @@ vi.mock('./lib/config.js', () => ({
|
|||||||
RUST_RUNTIME_TIMEOUT_MS: 300_000,
|
RUST_RUNTIME_TIMEOUT_MS: 300_000,
|
||||||
JWT_SECRET: 'test-secret',
|
JWT_SECRET: 'test-secret',
|
||||||
ANTHROPIC_API_KEY: undefined,
|
ANTHROPIC_API_KEY: undefined,
|
||||||
|
OLLAMA_URL: 'http://localhost:11434/v1',
|
||||||
|
OLLAMA_MODELS: undefined,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
vi.mock('./lib/product-config.js', () => ({
|
vi.mock('./lib/product-config.js', () => ({
|
||||||
|
|||||||
@ -73,8 +73,12 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize LLM router (best-effort — works without API keys in dev)
|
// 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 {
|
try {
|
||||||
const llm = initLlmRouter({
|
const llm = initLlmRouter({
|
||||||
|
ollamaModels,
|
||||||
|
ollamaBaseUrl: config.OLLAMA_URL,
|
||||||
onTelemetry: (entry) => app.log.debug({ llmTelemetry: entry }, 'llm-router event'),
|
onTelemetry: (entry) => app.log.debug({ llmTelemetry: entry }, 'llm-router event'),
|
||||||
});
|
});
|
||||||
app.log.info({ providers: llm.getProviders() }, 'LLM router initialized');
|
app.log.info({ providers: llm.getProviders() }, 'LLM router initialized');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user