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,6 +1,6 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
describe("sdk-options.ts", () => {
describe('sdk-options.ts', () => {
let originalEnv: NodeJS.ProcessEnv;
beforeEach(() => {
@@ -12,34 +12,34 @@ describe("sdk-options.ts", () => {
process.env = originalEnv;
});
describe("TOOL_PRESETS", () => {
it("should export readOnly tools", async () => {
const { TOOL_PRESETS } = await import("@/lib/sdk-options.js");
expect(TOOL_PRESETS.readOnly).toEqual(["Read", "Glob", "Grep"]);
describe('TOOL_PRESETS', () => {
it('should export readOnly tools', async () => {
const { TOOL_PRESETS } = await import('@/lib/sdk-options.js');
expect(TOOL_PRESETS.readOnly).toEqual(['Read', 'Glob', 'Grep']);
});
it("should export specGeneration tools", async () => {
const { TOOL_PRESETS } = await import("@/lib/sdk-options.js");
expect(TOOL_PRESETS.specGeneration).toEqual(["Read", "Glob", "Grep"]);
it('should export specGeneration tools', async () => {
const { TOOL_PRESETS } = await import('@/lib/sdk-options.js');
expect(TOOL_PRESETS.specGeneration).toEqual(['Read', 'Glob', 'Grep']);
});
it("should export fullAccess tools", async () => {
const { TOOL_PRESETS } = await import("@/lib/sdk-options.js");
expect(TOOL_PRESETS.fullAccess).toContain("Read");
expect(TOOL_PRESETS.fullAccess).toContain("Write");
expect(TOOL_PRESETS.fullAccess).toContain("Edit");
expect(TOOL_PRESETS.fullAccess).toContain("Bash");
it('should export fullAccess tools', async () => {
const { TOOL_PRESETS } = await import('@/lib/sdk-options.js');
expect(TOOL_PRESETS.fullAccess).toContain('Read');
expect(TOOL_PRESETS.fullAccess).toContain('Write');
expect(TOOL_PRESETS.fullAccess).toContain('Edit');
expect(TOOL_PRESETS.fullAccess).toContain('Bash');
});
it("should export chat tools matching fullAccess", async () => {
const { TOOL_PRESETS } = await import("@/lib/sdk-options.js");
it('should export chat tools matching fullAccess', async () => {
const { TOOL_PRESETS } = await import('@/lib/sdk-options.js');
expect(TOOL_PRESETS.chat).toEqual(TOOL_PRESETS.fullAccess);
});
});
describe("MAX_TURNS", () => {
it("should export turn presets", async () => {
const { MAX_TURNS } = await import("@/lib/sdk-options.js");
describe('MAX_TURNS', () => {
it('should export turn presets', async () => {
const { MAX_TURNS } = await import('@/lib/sdk-options.js');
expect(MAX_TURNS.quick).toBe(50);
expect(MAX_TURNS.standard).toBe(100);
expect(MAX_TURNS.extended).toBe(250);
@@ -47,71 +47,67 @@ describe("sdk-options.ts", () => {
});
});
describe("getModelForUseCase", () => {
it("should return explicit model when provided", async () => {
const { getModelForUseCase } = await import("@/lib/sdk-options.js");
const result = getModelForUseCase("spec", "claude-sonnet-4-20250514");
expect(result).toBe("claude-sonnet-4-20250514");
describe('getModelForUseCase', () => {
it('should return explicit model when provided', async () => {
const { getModelForUseCase } = await import('@/lib/sdk-options.js');
const result = getModelForUseCase('spec', 'claude-sonnet-4-20250514');
expect(result).toBe('claude-sonnet-4-20250514');
});
it("should use environment variable for spec model", async () => {
process.env.AUTOMAKER_MODEL_SPEC = "claude-sonnet-4-20250514";
const { getModelForUseCase } = await import("@/lib/sdk-options.js");
const result = getModelForUseCase("spec");
expect(result).toBe("claude-sonnet-4-20250514");
it('should use environment variable for spec model', async () => {
process.env.AUTOMAKER_MODEL_SPEC = 'claude-sonnet-4-20250514';
const { getModelForUseCase } = await import('@/lib/sdk-options.js');
const result = getModelForUseCase('spec');
expect(result).toBe('claude-sonnet-4-20250514');
});
it("should use default model for spec when no override", async () => {
it('should use default model for spec when no override', async () => {
delete process.env.AUTOMAKER_MODEL_SPEC;
delete process.env.AUTOMAKER_MODEL_DEFAULT;
const { getModelForUseCase } = await import("@/lib/sdk-options.js");
const result = getModelForUseCase("spec");
expect(result).toContain("claude");
const { getModelForUseCase } = await import('@/lib/sdk-options.js');
const result = getModelForUseCase('spec');
expect(result).toContain('claude');
});
it("should fall back to AUTOMAKER_MODEL_DEFAULT", async () => {
it('should fall back to AUTOMAKER_MODEL_DEFAULT', async () => {
delete process.env.AUTOMAKER_MODEL_SPEC;
process.env.AUTOMAKER_MODEL_DEFAULT = "claude-sonnet-4-20250514";
const { getModelForUseCase } = await import("@/lib/sdk-options.js");
const result = getModelForUseCase("spec");
expect(result).toBe("claude-sonnet-4-20250514");
process.env.AUTOMAKER_MODEL_DEFAULT = 'claude-sonnet-4-20250514';
const { getModelForUseCase } = await import('@/lib/sdk-options.js');
const result = getModelForUseCase('spec');
expect(result).toBe('claude-sonnet-4-20250514');
});
});
describe("createSpecGenerationOptions", () => {
it("should create options with spec generation settings", async () => {
describe('createSpecGenerationOptions', () => {
it('should create options with spec generation settings', async () => {
const { createSpecGenerationOptions, TOOL_PRESETS, MAX_TURNS } =
await import("@/lib/sdk-options.js");
await import('@/lib/sdk-options.js');
const options = createSpecGenerationOptions({ cwd: "/test/path" });
const options = createSpecGenerationOptions({ cwd: '/test/path' });
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(MAX_TURNS.maximum);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.specGeneration]);
expect(options.permissionMode).toBe("default");
expect(options.permissionMode).toBe('default');
});
it("should include system prompt when provided", async () => {
const { createSpecGenerationOptions } = await import(
"@/lib/sdk-options.js"
);
it('should include system prompt when provided', async () => {
const { createSpecGenerationOptions } = await import('@/lib/sdk-options.js');
const options = createSpecGenerationOptions({
cwd: "/test/path",
systemPrompt: "Custom prompt",
cwd: '/test/path',
systemPrompt: 'Custom prompt',
});
expect(options.systemPrompt).toBe("Custom prompt");
expect(options.systemPrompt).toBe('Custom prompt');
});
it("should include abort controller when provided", async () => {
const { createSpecGenerationOptions } = await import(
"@/lib/sdk-options.js"
);
it('should include abort controller when provided', async () => {
const { createSpecGenerationOptions } = await import('@/lib/sdk-options.js');
const abortController = new AbortController();
const options = createSpecGenerationOptions({
cwd: "/test/path",
cwd: '/test/path',
abortController,
});
@@ -119,42 +115,73 @@ describe("sdk-options.ts", () => {
});
});
describe("createFeatureGenerationOptions", () => {
it("should create options with feature generation settings", async () => {
describe('createFeatureGenerationOptions', () => {
it('should create options with feature generation settings', async () => {
const { createFeatureGenerationOptions, TOOL_PRESETS, MAX_TURNS } =
await import("@/lib/sdk-options.js");
await import('@/lib/sdk-options.js');
const options = createFeatureGenerationOptions({ cwd: "/test/path" });
const options = createFeatureGenerationOptions({ cwd: '/test/path' });
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(MAX_TURNS.quick);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.readOnly]);
});
});
describe("createSuggestionsOptions", () => {
it("should create options with suggestions settings", async () => {
const { createSuggestionsOptions, TOOL_PRESETS, MAX_TURNS } = await import(
"@/lib/sdk-options.js"
);
describe('createSuggestionsOptions', () => {
it('should create options with suggestions settings', async () => {
const { createSuggestionsOptions, TOOL_PRESETS, MAX_TURNS } =
await import('@/lib/sdk-options.js');
const options = createSuggestionsOptions({ cwd: "/test/path" });
const options = createSuggestionsOptions({ cwd: '/test/path' });
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(MAX_TURNS.extended);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.readOnly]);
});
it('should include systemPrompt when provided', async () => {
const { createSuggestionsOptions } = await import('@/lib/sdk-options.js');
const options = createSuggestionsOptions({
cwd: '/test/path',
systemPrompt: 'Custom prompt',
});
expect(options.systemPrompt).toBe('Custom prompt');
});
it('should include abortController when provided', async () => {
const { createSuggestionsOptions } = await import('@/lib/sdk-options.js');
const abortController = new AbortController();
const options = createSuggestionsOptions({
cwd: '/test/path',
abortController,
});
expect(options.abortController).toBe(abortController);
});
it('should include outputFormat when provided', async () => {
const { createSuggestionsOptions } = await import('@/lib/sdk-options.js');
const options = createSuggestionsOptions({
cwd: '/test/path',
outputFormat: { type: 'json' },
});
expect(options.outputFormat).toEqual({ type: 'json' });
});
});
describe("createChatOptions", () => {
it("should create options with chat settings", async () => {
const { createChatOptions, TOOL_PRESETS, MAX_TURNS } = await import(
"@/lib/sdk-options.js"
);
describe('createChatOptions', () => {
it('should create options with chat settings', async () => {
const { createChatOptions, TOOL_PRESETS, MAX_TURNS } = await import('@/lib/sdk-options.js');
const options = createChatOptions({ cwd: "/test/path" });
const options = createChatOptions({ cwd: '/test/path' });
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(MAX_TURNS.standard);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.chat]);
expect(options.sandbox).toEqual({
@@ -163,41 +190,38 @@ describe("sdk-options.ts", () => {
});
});
it("should prefer explicit model over session model", async () => {
const { createChatOptions, getModelForUseCase } = await import(
"@/lib/sdk-options.js"
);
it('should prefer explicit model over session model', async () => {
const { createChatOptions, getModelForUseCase } = await import('@/lib/sdk-options.js');
const options = createChatOptions({
cwd: "/test/path",
model: "claude-opus-4-20250514",
sessionModel: "claude-haiku-3-5-20241022",
cwd: '/test/path',
model: 'claude-opus-4-20250514',
sessionModel: 'claude-haiku-3-5-20241022',
});
expect(options.model).toBe("claude-opus-4-20250514");
expect(options.model).toBe('claude-opus-4-20250514');
});
it("should use session model when explicit model not provided", async () => {
const { createChatOptions } = await import("@/lib/sdk-options.js");
it('should use session model when explicit model not provided', async () => {
const { createChatOptions } = await import('@/lib/sdk-options.js');
const options = createChatOptions({
cwd: "/test/path",
sessionModel: "claude-sonnet-4-20250514",
cwd: '/test/path',
sessionModel: 'claude-sonnet-4-20250514',
});
expect(options.model).toBe("claude-sonnet-4-20250514");
expect(options.model).toBe('claude-sonnet-4-20250514');
});
});
describe("createAutoModeOptions", () => {
it("should create options with auto mode settings", async () => {
const { createAutoModeOptions, TOOL_PRESETS, MAX_TURNS } = await import(
"@/lib/sdk-options.js"
);
describe('createAutoModeOptions', () => {
it('should create options with auto mode settings', async () => {
const { createAutoModeOptions, TOOL_PRESETS, MAX_TURNS } =
await import('@/lib/sdk-options.js');
const options = createAutoModeOptions({ cwd: "/test/path" });
const options = createAutoModeOptions({ cwd: '/test/path' });
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(MAX_TURNS.maximum);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.fullAccess]);
expect(options.sandbox).toEqual({
@@ -205,34 +229,92 @@ describe("sdk-options.ts", () => {
autoAllowBashIfSandboxed: true,
});
});
it('should include systemPrompt when provided', async () => {
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
const options = createAutoModeOptions({
cwd: '/test/path',
systemPrompt: 'Custom prompt',
});
expect(options.systemPrompt).toBe('Custom prompt');
});
it('should include abortController when provided', async () => {
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
const abortController = new AbortController();
const options = createAutoModeOptions({
cwd: '/test/path',
abortController,
});
expect(options.abortController).toBe(abortController);
});
});
describe("createCustomOptions", () => {
it("should create options with custom settings", async () => {
const { createCustomOptions } = await import("@/lib/sdk-options.js");
describe('createCustomOptions', () => {
it('should create options with custom settings', async () => {
const { createCustomOptions } = await import('@/lib/sdk-options.js');
const options = createCustomOptions({
cwd: "/test/path",
cwd: '/test/path',
maxTurns: 10,
allowedTools: ["Read", "Write"],
allowedTools: ['Read', 'Write'],
sandbox: { enabled: true },
});
expect(options.cwd).toBe("/test/path");
expect(options.cwd).toBe('/test/path');
expect(options.maxTurns).toBe(10);
expect(options.allowedTools).toEqual(["Read", "Write"]);
expect(options.allowedTools).toEqual(['Read', 'Write']);
expect(options.sandbox).toEqual({ enabled: true });
});
it("should use defaults when optional params not provided", async () => {
const { createCustomOptions, TOOL_PRESETS, MAX_TURNS } = await import(
"@/lib/sdk-options.js"
);
it('should use defaults when optional params not provided', async () => {
const { createCustomOptions, TOOL_PRESETS, MAX_TURNS } = await import('@/lib/sdk-options.js');
const options = createCustomOptions({ cwd: "/test/path" });
const options = createCustomOptions({ cwd: '/test/path' });
expect(options.maxTurns).toBe(MAX_TURNS.maximum);
expect(options.allowedTools).toEqual([...TOOL_PRESETS.readOnly]);
});
it('should include sandbox when provided', async () => {
const { createCustomOptions } = await import('@/lib/sdk-options.js');
const options = createCustomOptions({
cwd: '/test/path',
sandbox: { enabled: true, autoAllowBashIfSandboxed: false },
});
expect(options.sandbox).toEqual({
enabled: true,
autoAllowBashIfSandboxed: false,
});
});
it('should include systemPrompt when provided', async () => {
const { createCustomOptions } = await import('@/lib/sdk-options.js');
const options = createCustomOptions({
cwd: '/test/path',
systemPrompt: 'Custom prompt',
});
expect(options.systemPrompt).toBe('Custom prompt');
});
it('should include abortController when provided', async () => {
const { createCustomOptions } = await import('@/lib/sdk-options.js');
const abortController = new AbortController();
const options = createCustomOptions({
cwd: '/test/path',
abortController,
});
expect(options.abortController).toBe(abortController);
});
});
});