Instead of a hardcoded model name (which forces LM Studio to JIT-swap your loaded model out — and fails when a big model already fills memory), resolve the model at request time: an explicit env override wins, else ask the server which model is *loaded* (LM Studio's native /api/v0/models), else the first non-embedding model, else a default. Reginald now uses whatever you load, no config churn. - main/model.ts: resolveLoadedModel() drives both model:status and model:chat; COMMITEA_MODEL_SMALL still overrides. - useChat exposes the resolved model id; the panel header shows it (google/gemma-4-26b-a4b-qat → "gemma-4-26b-a4b · local"). - live-reginald e2e: header assertion relaxed to the loaded model; timeouts raised for a slow big local model (~2 calls/turn + a reconcile). Verified: 14 fixture e2e green; live e2e drives the app against the loaded gemma-4-26b — "What now?" → "You should work on #2 … on the critical path, unblocks #33 and #4" (the real scheduler pick), header shows the live model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.6 KiB
TypeScript
34 lines
1.6 KiB
TypeScript
import { dirname, join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { _electron as electron, expect, test } from '@playwright/test'
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
const MAIN = join(here, '..', 'out', 'main', 'index.js')
|
|
|
|
// Opt-in (GITEA_LIVE=1 + COMMITEA_MODEL_LIVE=1 + a local model on :1234). Launches
|
|
// WITHOUT COMMITEA_E2E so Reginald runs the real agent loop against the real repo.
|
|
test.describe('live Reginald', () => {
|
|
test('answers a question by consulting the real project', async () => {
|
|
test.skip(!process.env.GITEA_LIVE || !process.env.COMMITEA_MODEL_LIVE, 'live model test — opt-in')
|
|
test.setTimeout(300_000) // a big local model is slow: ~2 calls/turn + a reconcile
|
|
const app = await electron.launch({ args: [MAIN], env: { ...process.env } })
|
|
const win = await app.firstWindow()
|
|
await win.waitForLoadState('domcontentloaded')
|
|
|
|
// model configured → the live greeting + header (the loaded model, not the scripted demo)
|
|
await expect(win.getByText(/· local$/)).toBeVisible({ timeout: 20000 })
|
|
await expect(win.getByText(/I check the real board before I answer/)).toBeVisible()
|
|
|
|
const composer = win.getByPlaceholder(/Tell me what to do/)
|
|
await composer.fill('What should I work on right now?')
|
|
await composer.press('Enter')
|
|
|
|
// the agent loop ran end-to-end: it consulted the project, then answered
|
|
await expect(win.getByText(/consulted the project/)).toBeVisible({ timeout: 240_000 })
|
|
await win.screenshot({ path: join(here, '.artifacts', 'screens', 'live-reginald.png'), fullPage: true, animations: 'disabled' })
|
|
|
|
await app.close()
|
|
})
|
|
})
|