Merge main into massive-terminal-upgrade

Resolves merge conflicts:
- apps/server/src/routes/terminal/common.ts: Keep randomBytes import, use @automaker/utils for createLogger
- apps/ui/eslint.config.mjs: Use main's explicit globals list with XMLHttpRequest and MediaQueryListEvent additions
- apps/ui/src/components/views/terminal-view.tsx: Keep our terminal improvements (killAllSessions, beforeunload, better error handling)
- apps/ui/src/config/terminal-themes.ts: Keep our search highlight colors for all themes
- apps/ui/src/store/app-store.ts: Keep our terminal settings persistence improvements (merge function)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
SuperComboGamer
2025-12-21 20:27:44 -05:00
393 changed files with 32473 additions and 17974 deletions

View File

@@ -1,23 +1,21 @@
import { describe, it, expect } from "vitest";
import { BaseProvider } from "@/providers/base-provider.js";
import { describe, it, expect } from 'vitest';
import { BaseProvider } from '@/providers/base-provider.js';
import type {
ProviderConfig,
ExecuteOptions,
ProviderMessage,
InstallationStatus,
ModelDefinition,
} from "@/providers/types.js";
} from '@automaker/types';
// Concrete implementation for testing the abstract class
class TestProvider extends BaseProvider {
getName(): string {
return "test-provider";
return 'test-provider';
}
async *executeQuery(
_options: ExecuteOptions
): AsyncGenerator<ProviderMessage> {
yield { type: "text", text: "test response" };
async *executeQuery(_options: ExecuteOptions): AsyncGenerator<ProviderMessage> {
yield { type: 'text', text: 'test response' };
}
async detectInstallation(): Promise<InstallationStatus> {
@@ -25,37 +23,35 @@ class TestProvider extends BaseProvider {
}
getAvailableModels(): ModelDefinition[] {
return [
{ id: "test-model-1", name: "Test Model 1", description: "A test model" },
];
return [{ id: 'test-model-1', name: 'Test Model 1', description: 'A test model' }];
}
}
describe("base-provider.ts", () => {
describe("constructor", () => {
it("should initialize with empty config when none provided", () => {
describe('base-provider.ts', () => {
describe('constructor', () => {
it('should initialize with empty config when none provided', () => {
const provider = new TestProvider();
expect(provider.getConfig()).toEqual({});
});
it("should initialize with provided config", () => {
it('should initialize with provided config', () => {
const config: ProviderConfig = {
apiKey: "test-key",
baseUrl: "https://test.com",
apiKey: 'test-key',
baseUrl: 'https://test.com',
};
const provider = new TestProvider(config);
expect(provider.getConfig()).toEqual(config);
});
it("should call getName() during initialization", () => {
it('should call getName() during initialization', () => {
const provider = new TestProvider();
expect(provider.getName()).toBe("test-provider");
expect(provider.getName()).toBe('test-provider');
});
});
describe("validateConfig", () => {
it("should return valid when config exists", () => {
const provider = new TestProvider({ apiKey: "test" });
describe('validateConfig', () => {
it('should return valid when config exists', () => {
const provider = new TestProvider({ apiKey: 'test' });
const result = provider.validateConfig();
expect(result.valid).toBe(true);
@@ -63,7 +59,7 @@ describe("base-provider.ts", () => {
expect(result.warnings).toHaveLength(0);
});
it("should return invalid when config is undefined", () => {
it('should return invalid when config is undefined', () => {
// Create provider without config
const provider = new TestProvider();
// Manually set config to undefined to test edge case
@@ -72,10 +68,10 @@ describe("base-provider.ts", () => {
const result = provider.validateConfig();
expect(result.valid).toBe(false);
expect(result.errors).toContain("Provider config is missing");
expect(result.errors).toContain('Provider config is missing');
});
it("should return valid for empty config object", () => {
it('should return valid for empty config object', () => {
const provider = new TestProvider({});
const result = provider.validateConfig();
@@ -83,53 +79,53 @@ describe("base-provider.ts", () => {
expect(result.errors).toHaveLength(0);
});
it("should include warnings array in result", () => {
it('should include warnings array in result', () => {
const provider = new TestProvider();
const result = provider.validateConfig();
expect(result).toHaveProperty("warnings");
expect(result).toHaveProperty('warnings');
expect(Array.isArray(result.warnings)).toBe(true);
});
});
describe("supportsFeature", () => {
describe('supportsFeature', () => {
it("should support 'tools' feature", () => {
const provider = new TestProvider();
expect(provider.supportsFeature("tools")).toBe(true);
expect(provider.supportsFeature('tools')).toBe(true);
});
it("should support 'text' feature", () => {
const provider = new TestProvider();
expect(provider.supportsFeature("text")).toBe(true);
expect(provider.supportsFeature('text')).toBe(true);
});
it("should not support unknown features", () => {
it('should not support unknown features', () => {
const provider = new TestProvider();
expect(provider.supportsFeature("vision")).toBe(false);
expect(provider.supportsFeature("mcp")).toBe(false);
expect(provider.supportsFeature("unknown")).toBe(false);
expect(provider.supportsFeature('vision')).toBe(false);
expect(provider.supportsFeature('mcp')).toBe(false);
expect(provider.supportsFeature('unknown')).toBe(false);
});
it("should be case-sensitive", () => {
it('should be case-sensitive', () => {
const provider = new TestProvider();
expect(provider.supportsFeature("TOOLS")).toBe(false);
expect(provider.supportsFeature("Text")).toBe(false);
expect(provider.supportsFeature('TOOLS')).toBe(false);
expect(provider.supportsFeature('Text')).toBe(false);
});
});
describe("getConfig", () => {
it("should return current config", () => {
describe('getConfig', () => {
it('should return current config', () => {
const config: ProviderConfig = {
apiKey: "test-key",
model: "test-model",
apiKey: 'test-key',
model: 'test-model',
};
const provider = new TestProvider(config);
expect(provider.getConfig()).toEqual(config);
});
it("should return same reference", () => {
const config: ProviderConfig = { apiKey: "test" };
it('should return same reference', () => {
const config: ProviderConfig = { apiKey: 'test' };
const provider = new TestProvider(config);
const retrieved1 = provider.getConfig();
@@ -139,31 +135,31 @@ describe("base-provider.ts", () => {
});
});
describe("setConfig", () => {
it("should merge partial config with existing config", () => {
const provider = new TestProvider({ apiKey: "original-key" });
describe('setConfig', () => {
it('should merge partial config with existing config', () => {
const provider = new TestProvider({ apiKey: 'original-key' });
provider.setConfig({ model: "new-model" });
provider.setConfig({ model: 'new-model' });
expect(provider.getConfig()).toEqual({
apiKey: "original-key",
model: "new-model",
apiKey: 'original-key',
model: 'new-model',
});
});
it("should override existing fields", () => {
const provider = new TestProvider({ apiKey: "old-key", model: "old-model" });
it('should override existing fields', () => {
const provider = new TestProvider({ apiKey: 'old-key', model: 'old-model' });
provider.setConfig({ apiKey: "new-key" });
provider.setConfig({ apiKey: 'new-key' });
expect(provider.getConfig()).toEqual({
apiKey: "new-key",
model: "old-model",
apiKey: 'new-key',
model: 'old-model',
});
});
it("should accept empty object", () => {
const provider = new TestProvider({ apiKey: "test" });
it('should accept empty object', () => {
const provider = new TestProvider({ apiKey: 'test' });
const originalConfig = provider.getConfig();
provider.setConfig({});
@@ -171,68 +167,68 @@ describe("base-provider.ts", () => {
expect(provider.getConfig()).toEqual(originalConfig);
});
it("should handle multiple updates", () => {
it('should handle multiple updates', () => {
const provider = new TestProvider();
provider.setConfig({ apiKey: "key1" });
provider.setConfig({ model: "model1" });
provider.setConfig({ baseUrl: "https://test.com" });
provider.setConfig({ apiKey: 'key1' });
provider.setConfig({ model: 'model1' });
provider.setConfig({ baseUrl: 'https://test.com' });
expect(provider.getConfig()).toEqual({
apiKey: "key1",
model: "model1",
baseUrl: "https://test.com",
apiKey: 'key1',
model: 'model1',
baseUrl: 'https://test.com',
});
});
it("should preserve other fields when updating one field", () => {
it('should preserve other fields when updating one field', () => {
const provider = new TestProvider({
apiKey: "key",
model: "model",
baseUrl: "https://test.com",
apiKey: 'key',
model: 'model',
baseUrl: 'https://test.com',
});
provider.setConfig({ model: "new-model" });
provider.setConfig({ model: 'new-model' });
expect(provider.getConfig()).toEqual({
apiKey: "key",
model: "new-model",
baseUrl: "https://test.com",
apiKey: 'key',
model: 'new-model',
baseUrl: 'https://test.com',
});
});
});
describe("abstract methods", () => {
it("should require getName implementation", () => {
describe('abstract methods', () => {
it('should require getName implementation', () => {
const provider = new TestProvider();
expect(typeof provider.getName).toBe("function");
expect(provider.getName()).toBe("test-provider");
expect(typeof provider.getName).toBe('function');
expect(provider.getName()).toBe('test-provider');
});
it("should require executeQuery implementation", async () => {
it('should require executeQuery implementation', async () => {
const provider = new TestProvider();
expect(typeof provider.executeQuery).toBe("function");
expect(typeof provider.executeQuery).toBe('function');
const generator = provider.executeQuery({
prompt: "test",
projectDirectory: "/test",
prompt: 'test',
projectDirectory: '/test',
});
const result = await generator.next();
expect(result.value).toEqual({ type: "text", text: "test response" });
expect(result.value).toEqual({ type: 'text', text: 'test response' });
});
it("should require detectInstallation implementation", async () => {
it('should require detectInstallation implementation', async () => {
const provider = new TestProvider();
expect(typeof provider.detectInstallation).toBe("function");
expect(typeof provider.detectInstallation).toBe('function');
const status = await provider.detectInstallation();
expect(status).toHaveProperty("installed");
expect(status).toHaveProperty('installed');
});
it("should require getAvailableModels implementation", () => {
it('should require getAvailableModels implementation', () => {
const provider = new TestProvider();
expect(typeof provider.getAvailableModels).toBe("function");
expect(typeof provider.getAvailableModels).toBe('function');
const models = provider.getAvailableModels();
expect(Array.isArray(models)).toBe(true);