feat: persistent Gemini ACP provider + status spinner
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / typecheck (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / package (pull_request) Has been cancelled

Replace per-call gemini CLI spawning (~10s cold start each time) with
persistent ACP (Agent Client Protocol) subprocess. First call absorbs
the cold start, subsequent calls are near-instant over JSON-RPC stdio.

- Add AcpClient: manages persistent gemini --experimental-acp subprocess
  with lazy init, auto-restart on crash/timeout, NDJSON framing
- Add GeminiAcpProvider: LlmProvider wrapper with serial queue for
  concurrent calls, same interface as GeminiCliProvider
- Add dispose() to LlmProvider interface + disposeAll() to registry
- Wire provider disposal into mcplocal shutdown handler
- Add status command spinner with progressive output and color-coded
  LLM health check results (green checkmark/red cross)
- 25 new tests (17 ACP client + 8 provider)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michal
2026-02-24 23:52:04 +00:00
parent 848868d45f
commit 11da8b1fbf
12 changed files with 1102 additions and 140 deletions

View File

@@ -25,7 +25,7 @@ describe('createProviderFromConfig', () => {
expect(registry.getActive()).toBeNull();
});
it('creates gemini-cli provider', async () => {
it('creates gemini-cli provider using ACP', async () => {
const store = mockSecretStore();
const registry = await createProviderFromConfig(
{ provider: 'gemini-cli', model: 'gemini-2.5-flash', binaryPath: '/usr/bin/gemini' },
@@ -33,6 +33,8 @@ describe('createProviderFromConfig', () => {
);
expect(registry.getActive()).not.toBeNull();
expect(registry.getActive()!.name).toBe('gemini-cli');
// ACP provider has dispose method
expect(typeof registry.getActive()!.dispose).toBe('function');
});
it('creates ollama provider', async () => {