Merge branch 'v0.9.0rc' into remove-sandbox-as-it-is-broken

This commit is contained in:
webdevcody
2026-01-07 15:01:31 -05:00
115 changed files with 8734 additions and 401 deletions

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useEffect, useState } from 'react';
import { Feature, ThinkingLevel, useAppStore } from '@/store/app-store';
import {
@@ -8,7 +9,6 @@ import {
} from '@/lib/agent-context-parser';
import { cn } from '@/lib/utils';
import {
Cpu,
Brain,
ListTodo,
Sparkles,
@@ -20,6 +20,7 @@ import {
} from 'lucide-react';
import { getElectronAPI } from '@/lib/electron';
import { SummaryDialog } from './summary-dialog';
import { getProviderIconForModel } from '@/components/ui/provider-icon';
/**
* Formats thinking level for compact display
@@ -109,7 +110,10 @@ export function AgentInfoPanel({
<div className="mb-3 space-y-2 overflow-hidden">
<div className="flex items-center gap-2 text-[11px] flex-wrap">
<div className="flex items-center gap-1 text-[var(--status-info)]">
<Cpu className="w-3 h-3" />
{(() => {
const ProviderIcon = getProviderIconForModel(feature.model);
return <ProviderIcon className="w-3 h-3" />;
})()}
<span className="font-medium">{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
{feature.thinkingLevel && feature.thinkingLevel !== 'none' ? (
@@ -133,7 +137,10 @@ export function AgentInfoPanel({
{/* Model & Phase */}
<div className="flex items-center gap-2 text-[11px] flex-wrap">
<div className="flex items-center gap-1 text-[var(--status-info)]">
<Cpu className="w-3 h-3" />
{(() => {
const ProviderIcon = getProviderIconForModel(feature.model);
return <ProviderIcon className="w-3 h-3" />;
})()}
<span className="font-medium">{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
{agentInfo.currentPhase && (

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { Feature } from '@/store/app-store';
import { Button } from '@/components/ui/button';
import {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useEffect, useMemo, useState } from 'react';
import { Feature, useAppStore } from '@/store/app-store';
import { cn } from '@/lib/utils';

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { Feature } from '@/store/app-store';
import { GitBranch, GitPullRequest, ExternalLink } from 'lucide-react';

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useState } from 'react';
import { Feature } from '@/store/app-store';
import { cn } from '@/lib/utils';
@@ -18,12 +19,12 @@ import {
MoreVertical,
ChevronDown,
ChevronUp,
Cpu,
GitFork,
} from 'lucide-react';
import { CountUpTimer } from '@/components/ui/count-up-timer';
import { formatModelName, DEFAULT_MODEL } from '@/lib/agent-context-parser';
import { DeleteConfirmDialog } from '@/components/ui/delete-confirm-dialog';
import { getProviderIconForModel } from '@/components/ui/provider-icon';
interface CardHeaderProps {
feature: Feature;
@@ -109,12 +110,17 @@ export function CardHeaderSection({
Spawn Sub-Task
</DropdownMenuItem>
{/* Model info in dropdown */}
<div className="px-2 py-1.5 text-[10px] text-muted-foreground border-t mt-1 pt-1.5">
<div className="flex items-center gap-1">
<Cpu className="w-3 h-3" />
<span>{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
</div>
{(() => {
const ProviderIcon = getProviderIconForModel(feature.model);
return (
<div className="px-2 py-1.5 text-[10px] text-muted-foreground border-t mt-1 pt-1.5">
<div className="flex items-center gap-1">
<ProviderIcon className="w-3 h-3" />
<span>{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
</div>
);
})()}
</DropdownMenuContent>
</DropdownMenu>
</div>
@@ -288,12 +294,17 @@ export function CardHeaderSection({
Spawn Sub-Task
</DropdownMenuItem>
{/* Model info in dropdown */}
<div className="px-2 py-1.5 text-[10px] text-muted-foreground border-t mt-1 pt-1.5">
<div className="flex items-center gap-1">
<Cpu className="w-3 h-3" />
<span>{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
</div>
{(() => {
const ProviderIcon = getProviderIconForModel(feature.model);
return (
<div className="px-2 py-1.5 text-[10px] text-muted-foreground border-t mt-1 pt-1.5">
<div className="flex items-center gap-1">
<ProviderIcon className="w-3 h-3" />
<span>{formatModelName(feature.model ?? DEFAULT_MODEL)}</span>
</div>
</div>
);
})()}
</DropdownMenuContent>
</DropdownMenu>
</div>

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import React, { memo, useLayoutEffect, useState } from 'react';
import { useDraggable } from '@dnd-kit/core';
import { cn } from '@/lib/utils';

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { Feature } from '@/store/app-store';
import { AgentTaskInfo } from '@/lib/agent-context-parser';
import {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useState, useEffect } from 'react';
import { createLogger } from '@automaker/utils/logger';
import {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import {
Dialog,
DialogContent,

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useState, useEffect } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Feature } from '@/store/app-store';

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useState, useEffect } from 'react';
import { createLogger } from '@automaker/utils/logger';
import {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useCallback } from 'react';
import {
Feature,

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { useMemo, useCallback } from 'react';
import { Feature, useAppStore } from '@/store/app-store';
import { resolveDependencies, getBlockingDependencies } from '@automaker/dependency-resolver';

View File

@@ -1,6 +1,6 @@
import type { ModelAlias, ThinkingLevel } from '@/store/app-store';
import type { ModelProvider } from '@automaker/types';
import { CURSOR_MODEL_MAP } from '@automaker/types';
import type { ModelAlias } from '@/store/app-store';
import type { ModelProvider, ThinkingLevel, ReasoningEffort } from '@automaker/types';
import { CURSOR_MODEL_MAP, CODEX_MODEL_MAP } from '@automaker/types';
import { Brain, Zap, Scale, Cpu, Rocket, Sparkles } from 'lucide-react';
export type ModelOption = {
@@ -51,9 +51,64 @@ export const CURSOR_MODELS: ModelOption[] = Object.entries(CURSOR_MODEL_MAP).map
);
/**
* All available models (Claude + Cursor)
* Codex/OpenAI models
* Official models from https://developers.openai.com/codex/models/
*/
export const ALL_MODELS: ModelOption[] = [...CLAUDE_MODELS, ...CURSOR_MODELS];
export const CODEX_MODELS: ModelOption[] = [
{
id: CODEX_MODEL_MAP.gpt52Codex,
label: 'GPT-5.2-Codex',
description: 'Most advanced agentic coding model (default for ChatGPT users).',
badge: 'Premium',
provider: 'codex',
hasThinking: true,
},
{
id: CODEX_MODEL_MAP.gpt5Codex,
label: 'GPT-5-Codex',
description: 'Purpose-built for Codex CLI (default for CLI users).',
badge: 'Balanced',
provider: 'codex',
hasThinking: true,
},
{
id: CODEX_MODEL_MAP.gpt5CodexMini,
label: 'GPT-5-Codex-Mini',
description: 'Faster workflows for code Q&A and editing.',
badge: 'Speed',
provider: 'codex',
hasThinking: false,
},
{
id: CODEX_MODEL_MAP.codex1,
label: 'Codex-1',
description: 'o3-based model optimized for software engineering.',
badge: 'Premium',
provider: 'codex',
hasThinking: true,
},
{
id: CODEX_MODEL_MAP.codexMiniLatest,
label: 'Codex-Mini-Latest',
description: 'o4-mini-based model for faster workflows.',
badge: 'Balanced',
provider: 'codex',
hasThinking: false,
},
{
id: CODEX_MODEL_MAP.gpt5,
label: 'GPT-5',
description: 'GPT-5 base flagship model.',
badge: 'Balanced',
provider: 'codex',
hasThinking: true,
},
];
/**
* All available models (Claude + Cursor + Codex)
*/
export const ALL_MODELS: ModelOption[] = [...CLAUDE_MODELS, ...CURSOR_MODELS, ...CODEX_MODELS];
export const THINKING_LEVELS: ThinkingLevel[] = ['none', 'low', 'medium', 'high', 'ultrathink'];
@@ -65,6 +120,28 @@ export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
ultrathink: 'Ultra',
};
/**
* Reasoning effort levels for Codex/OpenAI models
* All models support reasoning effort levels
*/
export const REASONING_EFFORT_LEVELS: ReasoningEffort[] = [
'none',
'minimal',
'low',
'medium',
'high',
'xhigh',
];
export const REASONING_EFFORT_LABELS: Record<ReasoningEffort, string> = {
none: 'None',
minimal: 'Min',
low: 'Low',
medium: 'Med',
high: 'High',
xhigh: 'XHigh',
};
// Profile icon mapping
export const PROFILE_ICONS: Record<string, React.ComponentType<{ className?: string }>> = {
Brain,

View File

@@ -1,13 +1,15 @@
// @ts-nocheck
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { Brain, Bot, Terminal, AlertTriangle } from 'lucide-react';
import { Brain, AlertTriangle } from 'lucide-react';
import { AnthropicIcon, CursorIcon, OpenAIIcon } from '@/components/ui/provider-icon';
import { cn } from '@/lib/utils';
import type { ModelAlias } from '@/store/app-store';
import { useAppStore } from '@/store/app-store';
import { useSetupStore } from '@/store/setup-store';
import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@automaker/types';
import type { ModelProvider } from '@automaker/types';
import { CLAUDE_MODELS, CURSOR_MODELS, ModelOption } from './model-constants';
import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS, ModelOption } from './model-constants';
interface ModelSelectorProps {
selectedModel: string; // Can be ModelAlias or "cursor-{id}"
@@ -21,13 +23,16 @@ export function ModelSelector({
testIdPrefix = 'model-select',
}: ModelSelectorProps) {
const { enabledCursorModels, cursorDefaultModel } = useAppStore();
const { cursorCliStatus } = useSetupStore();
const { cursorCliStatus, codexCliStatus } = useSetupStore();
const selectedProvider = getModelProvider(selectedModel);
// Check if Cursor CLI is available
const isCursorAvailable = cursorCliStatus?.installed && cursorCliStatus?.auth?.authenticated;
// Check if Codex CLI is available
const isCodexAvailable = codexCliStatus?.installed && codexCliStatus?.auth?.authenticated;
// Filter Cursor models based on enabled models from global settings
const filteredCursorModels = CURSOR_MODELS.filter((model) => {
// Extract the cursor model ID from the prefixed ID (e.g., "cursor-auto" -> "auto")
@@ -39,6 +44,9 @@ export function ModelSelector({
if (provider === 'cursor' && selectedProvider !== 'cursor') {
// Switch to Cursor's default model (from global settings)
onModelSelect(`${PROVIDER_PREFIXES.cursor}${cursorDefaultModel}`);
} else if (provider === 'codex' && selectedProvider !== 'codex') {
// Switch to Codex's default model (gpt-5.2)
onModelSelect('gpt-5.2');
} else if (provider === 'claude' && selectedProvider !== 'claude') {
// Switch to Claude's default model
onModelSelect('sonnet');
@@ -62,7 +70,7 @@ export function ModelSelector({
)}
data-testid={`${testIdPrefix}-provider-claude`}
>
<Bot className="w-4 h-4" />
<AnthropicIcon className="w-4 h-4" />
Claude
</button>
<button
@@ -76,9 +84,23 @@ export function ModelSelector({
)}
data-testid={`${testIdPrefix}-provider-cursor`}
>
<Terminal className="w-4 h-4" />
<CursorIcon className="w-4 h-4" />
Cursor CLI
</button>
<button
type="button"
onClick={() => handleProviderChange('codex')}
className={cn(
'flex-1 px-3 py-2 rounded-md border text-sm font-medium transition-colors flex items-center justify-center gap-2',
selectedProvider === 'codex'
? 'bg-primary text-primary-foreground border-primary'
: 'bg-background hover:bg-accent border-border'
)}
data-testid={`${testIdPrefix}-provider-codex`}
>
<OpenAIIcon className="w-4 h-4" />
Codex CLI
</button>
</div>
</div>
@@ -136,7 +158,7 @@ export function ModelSelector({
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
<Terminal className="w-4 h-4 text-primary" />
<CursorIcon className="w-4 h-4 text-primary" />
Cursor Model
</Label>
<span className="text-[11px] px-2 py-0.5 rounded-full border border-amber-500/40 text-amber-600 dark:text-amber-400">
@@ -188,6 +210,67 @@ export function ModelSelector({
</div>
</div>
)}
{/* Codex Models */}
{selectedProvider === 'codex' && (
<div className="space-y-3">
{/* Warning when Codex CLI is not available */}
{!isCodexAvailable && (
<div className="flex items-start gap-2 p-3 rounded-lg bg-amber-500/10 border border-amber-500/20">
<AlertTriangle className="w-4 h-4 text-amber-400 mt-0.5 shrink-0" />
<div className="text-sm text-amber-400">
Codex CLI is not installed or authenticated. Configure it in Settings AI
Providers.
</div>
</div>
)}
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
<OpenAIIcon className="w-4 h-4 text-primary" />
Codex Model
</Label>
<span className="text-[11px] px-2 py-0.5 rounded-full border border-emerald-500/40 text-emerald-600 dark:text-emerald-400">
CLI
</span>
</div>
<div className="flex flex-col gap-2">
{CODEX_MODELS.map((option) => {
const isSelected = selectedModel === option.id;
return (
<button
key={option.id}
type="button"
onClick={() => onModelSelect(option.id)}
title={option.description}
className={cn(
'w-full px-3 py-2 rounded-md border text-sm font-medium transition-colors flex items-center justify-between',
isSelected
? 'bg-primary text-primary-foreground border-primary'
: 'bg-background hover:bg-accent border-border'
)}
data-testid={`${testIdPrefix}-${option.id}`}
>
<span>{option.label}</span>
{option.badge && (
<Badge
variant="outline"
className={cn(
'text-xs',
isSelected
? 'border-primary-foreground/50 text-primary-foreground'
: 'border-muted-foreground/50 text-muted-foreground'
)}
>
{option.badge}
</Badge>
)}
</button>
);
})}
</div>
</div>
)}
</div>
);
}

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { Button } from '@/components/ui/button';
import { RefreshCw, Globe, Loader2, CircleDot, GitPullRequest } from 'lucide-react';
import { cn } from '@/lib/utils';