diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 469adb450..2b2136782 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -269,12 +269,12 @@ jobs: working-directory: packages/${{ matrix.package }} run: | echo "Dry run - would publish @agent-relay/${{ matrix.package }}" - npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} + npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} --ignore-scripts - name: Publish to NPM if: github.event.inputs.dry_run != 'true' working-directory: packages/${{ matrix.package }} - run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} + run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} --ignore-scripts # Publish SDK only (when selected) publish-sdk-only: @@ -305,12 +305,12 @@ jobs: - name: Dry run check if: github.event.inputs.dry_run == 'true' working-directory: packages/sdk - run: npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} + run: npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} --ignore-scripts - name: Publish SDK to NPM if: github.event.inputs.dry_run != 'true' working-directory: packages/sdk - run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} + run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} --ignore-scripts # Publish main package publish-main: @@ -356,11 +356,11 @@ jobs: if: github.event.inputs.dry_run == 'true' run: | echo "Dry run - would publish agent-relay@${{ needs.build.outputs.new_version }}" - npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} + npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} --ignore-scripts - name: Publish to NPM if: github.event.inputs.dry_run != 'true' - run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} + run: npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} --ignore-scripts # Create git tag and release create-release: diff --git a/packages/dashboard/ui/react-components/SpawnModal.tsx b/packages/dashboard/ui/react-components/SpawnModal.tsx index f1ef6441e..888747f3f 100644 --- a/packages/dashboard/ui/react-components/SpawnModal.tsx +++ b/packages/dashboard/ui/react-components/SpawnModal.tsx @@ -43,13 +43,50 @@ export interface SpawnModalProps { } /** Model options for Claude agents */ -const CLAUDE_MODEL_OPTIONS = [ - { value: 'sonnet', label: 'Sonnet', description: 'Fast and capable (default)' }, - { value: 'opus', label: 'Opus', description: 'Most capable, slower' }, - { value: 'haiku', label: 'Haiku', description: 'Fastest, lightweight' }, -] as const; +const CLAUDE_MODEL_OPTIONS: { value: string; label: string }[] = [ + { value: 'sonnet', label: 'Sonnet' }, + { value: 'opus', label: 'Opus' }, + { value: 'haiku', label: 'Haiku' }, +]; + +type ClaudeModel = string; + +/** Model options for Cursor agents */ +const CURSOR_MODEL_OPTIONS: { value: string; label: string }[] = [ + { value: 'opus-4.5-thinking', label: 'Claude 4.5 Opus (Thinking)' }, + { value: 'opus-4.5', label: 'Claude 4.5 Opus' }, + { value: 'sonnet-4.5', label: 'Claude 4.5 Sonnet' }, + { value: 'sonnet-4.5-thinking', label: 'Claude 4.5 Sonnet (Thinking)' }, + { value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' }, + { value: 'gpt-5.2-codex-high', label: 'GPT-5.2 Codex High' }, + { value: 'gpt-5.2-codex-low', label: 'GPT-5.2 Codex Low' }, + { value: 'gpt-5.2-codex-xhigh', label: 'GPT-5.2 Codex Extra High' }, + { value: 'gpt-5.2-codex-fast', label: 'GPT-5.2 Codex Fast' }, + { value: 'gpt-5.2-codex-high-fast', label: 'GPT-5.2 Codex High Fast' }, + { value: 'gpt-5.2-codex-low-fast', label: 'GPT-5.2 Codex Low Fast' }, + { value: 'gpt-5.2-codex-xhigh-fast', label: 'GPT-5.2 Codex Extra High Fast' }, + { value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' }, + { value: 'gpt-5.1-codex-max-high', label: 'GPT-5.1 Codex Max High' }, + { value: 'gpt-5.2', label: 'GPT-5.2' }, + { value: 'gpt-5.2-high', label: 'GPT-5.2 High' }, + { value: 'gpt-5.1-high', label: 'GPT-5.1 High' }, + { value: 'gemini-3-pro', label: 'Gemini 3 Pro' }, + { value: 'gemini-3-flash', label: 'Gemini 3 Flash' }, + { value: 'composer-1', label: 'Composer 1' }, + { value: 'grok', label: 'Grok' }, +]; + +type CursorModel = string; -type ClaudeModel = typeof CLAUDE_MODEL_OPTIONS[number]['value']; +/** Model options for Codex agents */ +const CODEX_MODEL_OPTIONS: { value: string; label: string }[] = [ + { value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' }, + { value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' }, + { value: 'gpt-5.1-codex-mini', label: 'GPT-5.1 Codex Mini' }, + { value: 'gpt-5.2', label: 'GPT-5.2' }, +]; + +type CodexModel = string; const AGENT_TEMPLATES = [ { @@ -68,6 +105,7 @@ const AGENT_TEMPLATES = [ description: 'OpenAI Codex agent', icon: '⚡', providerId: 'codex', // Backend uses 'openai', but we check for both + supportsModelSelection: true, }, { id: 'gemini', @@ -100,6 +138,7 @@ const AGENT_TEMPLATES = [ description: 'Cursor AI agent', icon: '📝', providerId: 'cursor', + supportsModelSelection: true, }, { id: 'custom', @@ -125,6 +164,8 @@ export function SpawnModal({ const [name, setName] = useState(''); const [customCommand, setCustomCommand] = useState(''); const [selectedModel, setSelectedModel] = useState('sonnet'); + const [selectedCursorModel, setSelectedCursorModel] = useState('opus-4.5-thinking'); + const [selectedCodexModel, setSelectedCodexModel] = useState('gpt-5.2-codex'); const [cwd, setCwd] = useState(''); const [team, setTeam] = useState(''); const [isShadow, setIsShadow] = useState(false); @@ -134,17 +175,25 @@ export function SpawnModal({ const [localError, setLocalError] = useState(null); const nameInputRef = useRef(null); - // Build effective command, including model flag for Claude + // Build effective command, always including model flag for Claude, Cursor, and Codex const effectiveCommand = useMemo(() => { if (selectedTemplate.id === 'custom') { return customCommand; } - // For Claude, append model flag if not default (sonnet) - if (selectedTemplate.id === 'claude' && selectedModel !== 'sonnet') { + // For Claude, always append model flag + if (selectedTemplate.id === 'claude') { return `${selectedTemplate.command} --model ${selectedModel}`; } + // For Cursor, always append model flag + if (selectedTemplate.id === 'cursor') { + return `${selectedTemplate.command} --model ${selectedCursorModel}`; + } + // For Codex, always append model flag + if (selectedTemplate.id === 'codex') { + return `${selectedTemplate.command} --model ${selectedCodexModel}`; + } return selectedTemplate.command; - }, [selectedTemplate, customCommand, selectedModel]); + }, [selectedTemplate, customCommand, selectedModel, selectedCursorModel, selectedCodexModel]); const shadowMode = useMemo(() => deriveShadowMode(effectiveCommand), [effectiveCommand]); @@ -234,6 +283,8 @@ export function SpawnModal({ setName(''); setCustomCommand(''); setSelectedModel('sonnet'); + setSelectedCursorModel('opus-4.5-thinking'); + setSelectedCodexModel('gpt-5.2-codex'); setCwd(''); setTeam(''); setIsShadow(false); @@ -362,27 +413,66 @@ export function SpawnModal({ {/* Model Selection (Claude only) */} {selectedTemplate.id === 'claude' && (
- -
+ + +
+ )} + + {/* Model Selection (Cursor only) */} + {selectedTemplate.id === 'cursor' && ( +
+ + +
+ )} + + {/* Model Selection (Codex only) */} + {selectedTemplate.id === 'codex' && ( +
+ +
)}