feat: complete rebranding to Gemini Nexus with improved UI, proxies and documentation
This commit is contained in:
1 parent
e524a340cb
commit
433dccbaa9
108 files changed
+1004
-1139
No files matched your search
@@ -0,0 +1,179 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { transformClaudeRequestIn } from '../lib/geminiNexus/ClaudeRequestMapper';
|
||||
import { ClaudeRequest } from '../lib/geminiNexus/types';
|
||||
import { SignatureStore } from '../lib/geminiNexus/SignatureStore';
|
||||
|
||||
/**
|
||||
* Gemini Nexus Core Features Verification
|
||||
*
|
||||
* This test suite verifies the critical "Gemini Nexus" enhancements ported from the Manager project.
|
||||
* Primarily focuses on:
|
||||
* 1. Identity Injection (Safety & Branding)
|
||||
* 2. Gemini 3 Pro Compatibility (Stability Fixes)
|
||||
* 3. Model Routing Logic (Business Rules)
|
||||
*/
|
||||
describe('Gemini Nexus Core Features (Business Logic)', () => {
|
||||
beforeEach(() => {
|
||||
// Clear global signature store before each test
|
||||
SignatureStore.clear();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
const BASE_REQUEST: ClaudeRequest = {
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
messages: [{ role: 'user', content: 'Hello' }],
|
||||
max_tokens: 100,
|
||||
stream: true,
|
||||
};
|
||||
|
||||
describe('Feature: Identity Injection (Branding & Safety)', () => {
|
||||
it('should inject Gemini Nexus identity when system prompt is missing', () => {
|
||||
const result = transformClaudeRequestIn({ ...BASE_REQUEST }, 'test-project');
|
||||
|
||||
const parts = result.request.systemInstruction?.parts || [];
|
||||
const identityPart = parts.find((p) => p.text.includes('You are Gemini Nexus'));
|
||||
|
||||
expect(identityPart).toBeDefined();
|
||||
expect(identityPart?.text).toContain('[IDENTITY_PATCH]');
|
||||
});
|
||||
|
||||
it('should NOT inject Gemini Nexus identity if user already provided it', () => {
|
||||
// User explicitly providing the identity string
|
||||
const result = transformClaudeRequestIn(
|
||||
{
|
||||
...BASE_REQUEST,
|
||||
system: 'You are Gemini Nexus, the best AI.',
|
||||
},
|
||||
'test-project',
|
||||
);
|
||||
|
||||
const parts = result.request.systemInstruction?.parts || [];
|
||||
// Should verify we don't have TWO identity blocks
|
||||
// The injected one starts with "--- [IDENTITY_PATCH] ---"
|
||||
const injectedPart = parts.find((p) => p.text.includes('[IDENTITY_PATCH]'));
|
||||
|
||||
expect(injectedPart).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should inject before user system prompt if user prompt does NOT have identity', () => {
|
||||
const result = transformClaudeRequestIn(
|
||||
{
|
||||
...BASE_REQUEST,
|
||||
system: 'Be concise.',
|
||||
},
|
||||
'test-project',
|
||||
);
|
||||
|
||||
const parts = result.request.systemInstruction?.parts || [];
|
||||
expect(parts.length).toBeGreaterThanOrEqual(2);
|
||||
expect(parts[0].text).toContain('Gemini Nexus');
|
||||
expect(parts[parts.length - 1].text).toContain('Be concise');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: Gemini 3 Pro Stability Fix ', () => {
|
||||
// Situation: User enables thinking, calls a tool, but NO thought signature exists.
|
||||
// Result: Google API would return 400.
|
||||
// Fix: We must silently disable thinking for this request.
|
||||
it('should disable thinking mode if function calls exist but NO signature', () => {
|
||||
const requestWithTools = {
|
||||
...BASE_REQUEST,
|
||||
// Maps to a gemini-3 model potentially
|
||||
model: 'gemini-3.1-pro-preview',
|
||||
tools: [{ name: 'get_weather' }], // Mock tool structure
|
||||
thinking: { type: 'enabled', budget_tokens: 1000 },
|
||||
} as any;
|
||||
|
||||
const result = transformClaudeRequestIn(requestWithTools, 'test-project');
|
||||
|
||||
// Should detect missing signature and remove thinking config
|
||||
expect(result.request.generationConfig?.thinkingConfig).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should KEEP thinking mode if function calls exist AND valid signature exists in Store', () => {
|
||||
// Pre-fill a valid signature
|
||||
SignatureStore.store('valid_signature_string_longer_than_10_chars');
|
||||
|
||||
const requestWithTools = {
|
||||
...BASE_REQUEST,
|
||||
model: 'gemini-3.1-pro-preview',
|
||||
tools: [{ name: 'get_weather' }],
|
||||
thinking: { type: 'enabled', budget_tokens: 1000 },
|
||||
} as any;
|
||||
|
||||
const result = transformClaudeRequestIn(requestWithTools, 'test-project');
|
||||
|
||||
// Should keep thinking config
|
||||
expect(result.request.generationConfig?.thinkingConfig).toBeDefined();
|
||||
});
|
||||
|
||||
it('should KEEP thinking mode if NO function calls exist (pure thinking)', () => {
|
||||
const requestPureThinking = {
|
||||
...BASE_REQUEST,
|
||||
model: 'gemini-3.1-pro-preview',
|
||||
// No tools
|
||||
thinking: { type: 'enabled', budget_tokens: 1000 },
|
||||
} as any;
|
||||
|
||||
const result = transformClaudeRequestIn(requestPureThinking, 'test-project');
|
||||
|
||||
// Should keep thinking config
|
||||
expect(result.request.generationConfig?.thinkingConfig).toBeDefined();
|
||||
});
|
||||
|
||||
it('should auto-enable thinking for gemini-3-flash even without explicit thinking config', () => {
|
||||
const result = transformClaudeRequestIn(
|
||||
{
|
||||
...BASE_REQUEST,
|
||||
model: 'gemini-3-flash',
|
||||
thinking: undefined,
|
||||
} as any,
|
||||
'test-project',
|
||||
);
|
||||
|
||||
expect(result.request.generationConfig?.thinkingConfig).toBeDefined();
|
||||
expect(result.request.generationConfig?.thinkingConfig?.includeThoughts).toBe(true);
|
||||
});
|
||||
|
||||
it('should inject flash sentinel thoughtSignature for tool_use without cached signature', () => {
|
||||
const requestWithToolUse = {
|
||||
...BASE_REQUEST,
|
||||
model: 'gemini-3-flash',
|
||||
thinking: undefined,
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool_use',
|
||||
id: 'call_1',
|
||||
name: 'get_weather',
|
||||
input: { location: 'Beijing' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
} as any;
|
||||
|
||||
const result = transformClaudeRequestIn(requestWithToolUse, 'test-project');
|
||||
const part = result.request.contents?.[0]?.parts?.[0] as any;
|
||||
expect(part?.thoughtSignature).toBe('skip_thought_signature_validator');
|
||||
});
|
||||
|
||||
it('should keep mixed tools for gemini 2.x+ when both function and web search are requested', () => {
|
||||
const mixedToolsRequest = {
|
||||
...BASE_REQUEST,
|
||||
model: 'gemini-2.0-flash-online',
|
||||
tools: [{ name: 'get_weather' }, { name: 'web_search' }],
|
||||
} as any;
|
||||
|
||||
const result = transformClaudeRequestIn(mixedToolsRequest, 'test-project');
|
||||
const tools = result.request.tools || [];
|
||||
const hasFunctions = tools.some((tool: any) => Array.isArray(tool.functionDeclarations));
|
||||
const hasGoogleSearch = tools.some((tool: any) => tool.googleSearch);
|
||||
|
||||
expect(hasFunctions).toBe(true);
|
||||
expect(hasGoogleSearch).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user