claude.fish

  1# SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2#
  3# SPDX-License-Identifier: Unlicense
  4
  5# Claude Code agent definition for synu
  6# Provides model configuration for routing through Synthetic API
  7
  8# Source cache functions
  9source (status dirname)/../_synu_cache.fish
 10
 11# Fallback defaults (used when no cache entry exists)
 12set -g _synu_claude_fallback_opus "hf:moonshotai/Kimi-K2-Thinking"
 13set -g _synu_claude_fallback_sonnet "hf:zai-org/GLM-4.6"
 14set -g _synu_claude_fallback_haiku "hf:deepseek-ai/DeepSeek-V3.1-Terminus"
 15set -g _synu_claude_fallback_agent "hf:zai-org/GLM-4.6"
 16
 17function _synu_claude_default --description "Get default model: _synu_claude_default slot"
 18    set -l slot $argv[1]
 19    set -l cached (_synu_cache_get claude $slot)
 20    if test $status -eq 0
 21        echo $cached
 22    else
 23        set -l var_name _synu_claude_fallback_$slot
 24        echo $$var_name
 25    end
 26end
 27
 28function _synu_agent_claude_flags --description "Return argparse-compatible flag specification"
 29    echo "L/large="
 30    echo "l/light="
 31    echo "o/opus="
 32    echo "s/sonnet="
 33    echo "H/haiku="
 34    echo "a/agent="
 35end
 36
 37function _synu_agent_claude_env_vars --description "Return list of environment variables set by configure"
 38    echo ANTHROPIC_BASE_URL
 39    echo ANTHROPIC_AUTH_TOKEN
 40    echo ANTHROPIC_DEFAULT_OPUS_MODEL
 41    echo ANTHROPIC_DEFAULT_SONNET_MODEL
 42    echo ANTHROPIC_DEFAULT_HAIKU_MODEL
 43    echo CLAUDE_CODE_SUBAGENT_MODEL
 44    echo CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
 45end
 46
 47function _synu_agent_claude_configure --description "Configure Claude Code environment variables"
 48    # Parse flags passed from main synu
 49    argparse 'L/large=' 'l/light=' 'o/opus=' 's/sonnet=' 'H/haiku=' 'a/agent=' -- $argv
 50    or return 1
 51
 52    # Start with defaults (from cache or fallback)
 53    set -l opus_model (_synu_claude_default opus)
 54    set -l sonnet_model (_synu_claude_default sonnet)
 55    set -l haiku_model (_synu_claude_default haiku)
 56    set -l subagent_model (_synu_claude_default agent)
 57
 58    # Apply group overrides
 59    if set -q _flag_large
 60        set opus_model $_flag_large
 61        set sonnet_model $_flag_large
 62        set subagent_model $_flag_large
 63    end
 64
 65    if set -q _flag_light
 66        set haiku_model $_flag_light
 67    end
 68
 69    # Apply specific overrides (take precedence over groups)
 70    if set -q _flag_opus
 71        set opus_model $_flag_opus
 72    end
 73    if set -q _flag_sonnet
 74        set sonnet_model $_flag_sonnet
 75    end
 76    if set -q _flag_haiku
 77        set haiku_model $_flag_haiku
 78    end
 79    if set -q _flag_agent
 80        set subagent_model $_flag_agent
 81    end
 82
 83    # Export environment variables for Claude Code
 84    set -gx ANTHROPIC_BASE_URL "https://api.synthetic.new/anthropic"
 85    set -gx ANTHROPIC_AUTH_TOKEN $SYNTHETIC_API_KEY
 86    set -gx ANTHROPIC_DEFAULT_OPUS_MODEL $opus_model
 87    set -gx ANTHROPIC_DEFAULT_SONNET_MODEL $sonnet_model
 88    set -gx ANTHROPIC_DEFAULT_HAIKU_MODEL $haiku_model
 89    set -gx CLAUDE_CODE_SUBAGENT_MODEL $subagent_model
 90    set -gx CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 1
 91end
 92
 93function _synu_agent_claude_interactive --description "Interactive model selection using gum"
 94    # Check for gum
 95    if not command -q gum
 96        echo "Error: gum is required for interactive mode. Install: https://github.com/charmbracelet/gum" >&2
 97        return 1
 98    end
 99
100    # Fetch available models
101    set -l models_json (gum spin --spinner dot --title "Fetching models..." -- \
102        curl -s -H "Authorization: Bearer $SYNTHETIC_API_KEY" \
103        "https://api.synthetic.new/openai/v1/models")
104    or return 1
105
106    set -l model_names (echo $models_json | jq -r '.data[].name')
107    or return 1
108
109    # Get current models for display
110    set -l current_opus_id (_synu_claude_default opus)
111    set -l current_sonnet_id (_synu_claude_default sonnet)
112    set -l current_haiku_id (_synu_claude_default haiku)
113    set -l current_agent_id (_synu_claude_default agent)
114    set -l current_opus_name (echo $models_json | \
115        jq -r --arg id "$current_opus_id" '.data[] | select(.id == $id) | .name // "unknown"')
116    set -l current_sonnet_name (echo $models_json | \
117        jq -r --arg id "$current_sonnet_id" '.data[] | select(.id == $id) | .name // "unknown"')
118    set -l current_haiku_name (echo $models_json | \
119        jq -r --arg id "$current_haiku_id" '.data[] | select(.id == $id) | .name // "unknown"')
120    set -l current_agent_name (echo $models_json | \
121        jq -r --arg id "$current_agent_id" '.data[] | select(.id == $id) | .name // "unknown"')
122
123    # Prompt for groups vs individual
124    set -l mode (gum choose --limit 1 --header "How do you want to select models?" \
125        "Groups" "Individual models")
126    or return 1
127
128    # Build flags array
129    set -l flags
130
131    if test "$mode" = "Groups"
132        # Select which groups to override
133        set -l groups (gum choose --no-limit \
134            --header "Which group(s) do you want to override?" \
135            "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")
136        or return 1
137
138        for group in $groups
139            if test "$group" = "Large (Opus, Sonnet, Sub-agent)"
140                set -l model_name (printf "%s\n" $model_names | \
141                    gum filter --limit 1 --header "Select model for Large group (opus: $current_opus_id, sonnet: $current_sonnet_id, agent: $current_agent_id)" \
142                    --placeholder "Filter models...")
143                or return 1
144                set -l model_id (echo $models_json | \
145                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
146                if test -n "$model_id"
147                    set flags $flags --large=$model_id
148                end
149            else if test "$group" = "Light (Haiku)"
150                set -l model_name (printf "%s\n" $model_names | \
151                    gum filter --limit 1 --header "Select model for Light group (haiku: $current_haiku_id)" \
152                    --placeholder "Filter models...")
153                or return 1
154                set -l model_id (echo $models_json | \
155                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
156                if test -n "$model_id"
157                    set flags $flags --light=$model_id
158                end
159            end
160        end
161    else
162        # Select which individual models to override
163        set -l models (gum choose --no-limit \
164            --header "Which model(s) do you want to override?" \
165            "Opus" "Sonnet" "Haiku" "Sub-agent")
166        or return 1
167
168        for model_type in $models
169            switch $model_type
170                case "Opus"
171                    set -l model_name (printf "%s\n" $model_names | \
172                        gum filter --limit 1 --header "Select Opus model (current: $current_opus_id)" \
173                        --placeholder "Filter models...")
174                    or return 1
175                    set -l model_id (echo $models_json | \
176                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
177                    if test -n "$model_id"
178                        set flags $flags --opus=$model_id
179                    end
180                case "Sonnet"
181                    set -l model_name (printf "%s\n" $model_names | \
182                        gum filter --limit 1 --header "Select Sonnet model (current: $current_sonnet_id)" \
183                        --placeholder "Filter models...")
184                    or return 1
185                    set -l model_id (echo $models_json | \
186                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
187                    if test -n "$model_id"
188                        set flags $flags --sonnet=$model_id
189                    end
190                case "Haiku"
191                    set -l model_name (printf "%s\n" $model_names | \
192                        gum filter --limit 1 --header "Select Haiku model (current: $current_haiku_id)" \
193                        --placeholder "Filter models...")
194                    or return 1
195                    set -l model_id (echo $models_json | \
196                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
197                    if test -n "$model_id"
198                        set flags $flags --haiku=$model_id
199                    end
200                case "Sub-agent"
201                    set -l model_name (printf "%s\n" $model_names | \
202                        gum filter --limit 1 --header "Select Sub-agent model (current: $current_agent_id)" \
203                        --placeholder "Filter models...")
204                    or return 1
205                    set -l model_id (echo $models_json | \
206                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
207                    if test -n "$model_id"
208                        set flags $flags --agent=$model_id
209                    end
210            end
211        end
212    end
213
214    # Offer to save as defaults
215    if test (count $flags) -gt 0
216        if gum confirm "Save as default for 'claude'?"
217            for flag in $flags
218                # Parse --key=value format
219                set -l parts (string match -r -- '^--([^=]+)=(.+)$' $flag)
220                if test -n "$parts[2]"
221                    set -l key $parts[2]
222                    set -l value $parts[3]
223                    # Expand group flags to individual slots
224                    switch $key
225                        case large
226                            _synu_cache_set claude opus $value
227                            _synu_cache_set claude sonnet $value
228                            _synu_cache_set claude agent $value
229                        case light
230                            _synu_cache_set claude haiku $value
231                        case '*'
232                            _synu_cache_set claude $key $value
233                    end
234                end
235            end
236        end
237    end
238
239    # Output flags for caller to use (one per line for proper array capture)
240    printf '%s\n' $flags
241end