feat: Claude Agent SDK backend + clean-room PostgresSessionStore (v2.7.5)
Lands the lean-SDK direction (boocode_code_review_v2 §1 #9) behind a flag. Adds @anthropic-ai/claude-agent-sdk@0.3.159 (Commercial Terms, runtime dep). - PostgresSessionStore: clean-room impl of the SDK's real SessionStore type over a new claude_session_entries table. Typechecks against the SDK type; 8 DB-integration tests. - ClaudeSdkBackend (implements AgentBackend): one warm query() per (chat,claude) in streaming-input mode via a pushable async-iterable pump, sessionStore + resume continuity, pure mapSdkMessage->AgentEvent, session_id from init, usage/cost onto agent_sessions (backend CHECK gains 'claude_sdk'). - Routing env-gated by CLAUDE_SDK_BACKEND (default off) -> PTY path UNCHANGED. - Built against real SDK 0.3.159 types (install paid off: partial=stream_event needing includePartialMessages, MessageParam, result error arm). - Fix latent test-infra deadlock: serialize DB suites (fileParallelism:false). Coder 269 passing default / 290 with DB; tsc clean vs SDK types; builds clean. LIVE pump + resume + actual claude turn need a host smoke (CLAUDE_SDK_BACKEND=1 + claude binary + auth). zod peer-dep wants ^4 (workspace 3.25). Builds on v2.7.4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { shouldUseClaudeSdk, claudeSdkBackendEnabled } from '../claude-sdk-routing.js';
|
||||
|
||||
/**
|
||||
* Env-flagged routing for the warm Claude-SDK backend. With CLAUDE_SDK_BACKEND off
|
||||
* (the production default) every claude task falls through to the unchanged PTY path;
|
||||
* with it on, only chat-tab claude tasks (session_id + chat_id) route to the SDK.
|
||||
*/
|
||||
const ON = { CLAUDE_SDK_BACKEND: '1' } as NodeJS.ProcessEnv;
|
||||
const OFF = {} as NodeJS.ProcessEnv;
|
||||
|
||||
describe('claudeSdkBackendEnabled', () => {
|
||||
it('is false when unset or falsy', () => {
|
||||
expect(claudeSdkBackendEnabled({} as NodeJS.ProcessEnv)).toBe(false);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: '' } as NodeJS.ProcessEnv)).toBe(false);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: '0' } as NodeJS.ProcessEnv)).toBe(false);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: 'false' } as NodeJS.ProcessEnv)).toBe(false);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: 'off' } as NodeJS.ProcessEnv)).toBe(false);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: 'no' } as NodeJS.ProcessEnv)).toBe(false);
|
||||
});
|
||||
|
||||
it('is true for any other truthy value', () => {
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: '1' } as NodeJS.ProcessEnv)).toBe(true);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: 'true' } as NodeJS.ProcessEnv)).toBe(true);
|
||||
expect(claudeSdkBackendEnabled({ CLAUDE_SDK_BACKEND: 'on' } as NodeJS.ProcessEnv)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldUseClaudeSdk', () => {
|
||||
it('is always false while the env flag is off — production claude stays on PTY', () => {
|
||||
expect(shouldUseClaudeSdk({ agent: 'claude', session_id: 's1', chat_id: 'c1' }, OFF)).toBe(false);
|
||||
});
|
||||
|
||||
it('routes a chat-tab claude task to the SDK when the flag is on', () => {
|
||||
expect(shouldUseClaudeSdk({ agent: 'claude', session_id: 's1', chat_id: 'c1' }, ON)).toBe(true);
|
||||
});
|
||||
|
||||
it('only applies to the claude agent', () => {
|
||||
expect(shouldUseClaudeSdk({ agent: 'qwen', session_id: 's1', chat_id: 'c1' }, ON)).toBe(false);
|
||||
expect(shouldUseClaudeSdk({ agent: 'opencode', session_id: 's1', chat_id: 'c1' }, ON)).toBe(false);
|
||||
expect(shouldUseClaudeSdk({ agent: null, session_id: 's1', chat_id: 'c1' }, ON)).toBe(false);
|
||||
});
|
||||
|
||||
it('requires both session_id and chat_id (session-less creators stay one-shot)', () => {
|
||||
expect(shouldUseClaudeSdk({ agent: 'claude', session_id: null, chat_id: null }, ON)).toBe(false);
|
||||
expect(shouldUseClaudeSdk({ agent: 'claude', session_id: 's1', chat_id: null }, ON)).toBe(false);
|
||||
expect(shouldUseClaudeSdk({ agent: 'claude', session_id: null, chat_id: 'c1' }, ON)).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user