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:MiniMaxAI/MiniMax-M2"
14set -g _synu_claude_fallback_haiku "hf:deepseek-ai/DeepSeek-V3.1-Terminus"
15set -g _synu_claude_fallback_agent "hf:MiniMaxAI/MiniMax-M2"
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 # Prompt for groups vs individual
110 set -l mode (gum choose --limit 1 --header "How do you want to select models?" \
111 "Groups" "Individual models")
112 or return 1
113
114 # Build flags array
115 set -l flags
116
117 if test "$mode" = "Groups"
118 # Select which groups to override
119 set -l groups (gum choose --no-limit \
120 --header "Which group(s) do you want to override?" \
121 "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")
122 or return 1
123
124 for group in $groups
125 if test "$group" = "Large (Opus, Sonnet, Sub-agent)"
126 set -l model_name (printf "%s\n" $model_names | \
127 gum filter --limit 1 --header "Select model for Large group" \
128 --placeholder "Filter models...")
129 or return 1
130 set -l model_id (echo $models_json | \
131 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
132 if test -n "$model_id"
133 set flags $flags --large=$model_id
134 end
135 else if test "$group" = "Light (Haiku)"
136 set -l model_name (printf "%s\n" $model_names | \
137 gum filter --limit 1 --header "Select model for Light group" \
138 --placeholder "Filter models...")
139 or return 1
140 set -l model_id (echo $models_json | \
141 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
142 if test -n "$model_id"
143 set flags $flags --light=$model_id
144 end
145 end
146 end
147 else
148 # Select which individual models to override
149 set -l models (gum choose --no-limit \
150 --header "Which model(s) do you want to override?" \
151 "Opus" "Sonnet" "Haiku" "Sub-agent")
152 or return 1
153
154 for model_type in $models
155 switch $model_type
156 case "Opus"
157 set -l model_name (printf "%s\n" $model_names | \
158 gum filter --limit 1 --header "Select Opus model" \
159 --placeholder "Filter models...")
160 or return 1
161 set -l model_id (echo $models_json | \
162 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
163 if test -n "$model_id"
164 set flags $flags --opus=$model_id
165 end
166 case "Sonnet"
167 set -l model_name (printf "%s\n" $model_names | \
168 gum filter --limit 1 --header "Select Sonnet model" \
169 --placeholder "Filter models...")
170 or return 1
171 set -l model_id (echo $models_json | \
172 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
173 if test -n "$model_id"
174 set flags $flags --sonnet=$model_id
175 end
176 case "Haiku"
177 set -l model_name (printf "%s\n" $model_names | \
178 gum filter --limit 1 --header "Select Haiku model" \
179 --placeholder "Filter models...")
180 or return 1
181 set -l model_id (echo $models_json | \
182 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
183 if test -n "$model_id"
184 set flags $flags --haiku=$model_id
185 end
186 case "Sub-agent"
187 set -l model_name (printf "%s\n" $model_names | \
188 gum filter --limit 1 --header "Select Sub-agent model" \
189 --placeholder "Filter models...")
190 or return 1
191 set -l model_id (echo $models_json | \
192 jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
193 if test -n "$model_id"
194 set flags $flags --agent=$model_id
195 end
196 end
197 end
198 end
199
200 # Offer to save as defaults
201 if test (count $flags) -gt 0
202 if gum confirm "Save as default for 'claude'?"
203 for flag in $flags
204 # Parse --key=value format
205 set -l parts (string match -r -- '^--([^=]+)=(.+)$' $flag)
206 if test -n "$parts[2]"
207 set -l key $parts[2]
208 set -l value $parts[3]
209 # Expand group flags to individual slots
210 switch $key
211 case large
212 _synu_cache_set claude opus $value
213 _synu_cache_set claude sonnet $value
214 _synu_cache_set claude agent $value
215 case light
216 _synu_cache_set claude haiku $value
217 case '*'
218 _synu_cache_set claude $key $value
219 end
220 end
221 end
222 end
223 end
224
225 # Output flags for caller to use
226 echo $flags
227end