claude-all-config 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE.md +70 -0
  3. package/README.md +133 -0
  4. package/VERSION +1 -0
  5. package/agents/accessibility-reviewer.md +96 -0
  6. package/agents/ai-prompt-optimizer.md +94 -0
  7. package/agents/api-tester.md +102 -0
  8. package/agents/code-generator.md +94 -0
  9. package/agents/code-reviewer.md +47 -0
  10. package/agents/component-generator.md +102 -0
  11. package/agents/doc-generator.md +91 -0
  12. package/agents/migration-generator.md +94 -0
  13. package/agents/performance-analyzer.md +90 -0
  14. package/agents/proactive-mode.md +91 -0
  15. package/agents/readme-generator.md +101 -0
  16. package/agents/security-auditor.md +86 -0
  17. package/agents/terraform-generator.md +94 -0
  18. package/agents/test-generator.md +76 -0
  19. package/bin/agentrouter.json +36 -0
  20. package/bin/ai-chat +20 -0
  21. package/bin/antigravity.json +76 -0
  22. package/bin/api-manager +340 -0
  23. package/bin/claude-launcher +19 -0
  24. package/bin/claude-master +15 -0
  25. package/bin/claude_master.py +295 -0
  26. package/bin/cohere.json +7 -0
  27. package/bin/deepseek.json +44 -0
  28. package/bin/gemini.json +56 -0
  29. package/bin/glm.json +21 -0
  30. package/bin/groq.json +41 -0
  31. package/bin/minimax.json +26 -0
  32. package/bin/mistral.json +7 -0
  33. package/bin/moonshot.json +7 -0
  34. package/bin/ollama.json +36 -0
  35. package/bin/openai.json +46 -0
  36. package/bin/openrouter.json +38 -0
  37. package/bin/perplexity.json +12 -0
  38. package/bin/qwen.json +7 -0
  39. package/bin/switch-provider +73 -0
  40. package/bin/test.json +7 -0
  41. package/bin/xai.json +41 -0
  42. package/claude-all +2707 -0
  43. package/claude-config.json +340 -0
  44. package/claude-suite/REFACTORING_SUMMARY.md +88 -0
  45. package/claude-suite/auth/.antigravity_proxy.py +78 -0
  46. package/claude-suite/auth/__pycache__/openai_auth.cpython-312.pyc +0 -0
  47. package/claude-suite/auth/gemini_auth.py +80 -0
  48. package/claude-suite/auth/openai_auth.py +138 -0
  49. package/claude-suite/backups/claude-all-before-refactor +1075 -0
  50. package/claude-suite/backups/claude-all.backup +840 -0
  51. package/claude-suite/backups/claude-all.original +840 -0
  52. package/claude-suite/models/add-model-manual.sh +588 -0
  53. package/claude-suite/models/add-model.sh +114 -0
  54. package/claude-suite/models/model-switcher.sh +69 -0
  55. package/claude-suite/providers/claude-glm +89 -0
  56. package/claude-suite/providers/claude-glm-wrapper.sh +55 -0
  57. package/claude-suite/providers/claude-minimax +12 -0
  58. package/claude-suite/providers/claude-smart +132 -0
  59. package/claude-suite/providers/xai_chat.sh +56 -0
  60. package/claude-suite/utils/__pycache__/claude_master.cpython-312.pyc +0 -0
  61. package/claude-suite/utils/antigravity_proxy_server.py +168 -0
  62. package/claude-suite/utils/claude-all-help.txt +83 -0
  63. package/claude-suite/utils/claude_master.py +408 -0
  64. package/commands/brainstorm.md +5 -0
  65. package/commands/execute-plan.md +5 -0
  66. package/commands/write-plan.md +5 -0
  67. package/docs/ANTIGRAVITY-SETUP.md +176 -0
  68. package/docs/AUTH_CREDENTIALS.md +54 -0
  69. package/docs/NPM-INSTALLATION.md +166 -0
  70. package/hooks/hooks.json +15 -0
  71. package/hooks/run-hook.cmd +19 -0
  72. package/hooks/session-start.sh +52 -0
  73. package/install.sh +155 -0
  74. package/mcp.json +34 -0
  75. package/model/perplexity.json +12 -0
  76. package/package.json +69 -0
  77. package/plugins/README.md +47 -0
  78. package/plugins/installed_plugins.json +317 -0
  79. package/plugins/known_marketplaces.json +10 -0
  80. package/plugins/marketplace-info/marketplace.json +517 -0
  81. package/postinstall.js +100 -0
  82. package/scripts/antigravity_proxy_server.py +168 -0
  83. package/scripts/get_gemini_api_key.py +96 -0
  84. package/scripts/setup_antigravity_auth.py +171 -0
  85. package/skills/api-development/SKILL.md +11 -0
  86. package/skills/api-development/openapi/api-documentation.yaml +108 -0
  87. package/skills/brainstorming/SKILL.md +54 -0
  88. package/skills/code-quality/SKILL.md +196 -0
  89. package/skills/condition-based-waiting/SKILL.md +120 -0
  90. package/skills/condition-based-waiting/example.ts +158 -0
  91. package/skills/database-development/SKILL.md +11 -0
  92. package/skills/database-development/migrations/migration.template.sql +49 -0
  93. package/skills/defense-in-depth/SKILL.md +127 -0
  94. package/skills/deployment/SKILL.md +11 -0
  95. package/skills/deployment/ci-cd/github-actions.yml +95 -0
  96. package/skills/deployment/docker/Dockerfile.template +39 -0
  97. package/skills/dispatching-parallel-agents/SKILL.md +180 -0
  98. package/skills/documentation-generation/SKILL.md +8 -0
  99. package/skills/documentation-generation/templates/README.template.md +60 -0
  100. package/skills/error-handling/SKILL.md +267 -0
  101. package/skills/executing-plans/SKILL.md +76 -0
  102. package/skills/finishing-a-development-branch/SKILL.md +200 -0
  103. package/skills/frontend-design/frontend-design/SKILL.md +42 -0
  104. package/skills/integration-testing/SKILL.md +13 -0
  105. package/skills/integration-testing/examples/contract-test.py +317 -0
  106. package/skills/integration-testing/examples/e2e-test.js +147 -0
  107. package/skills/integration-testing/examples/test-isolation.md +94 -0
  108. package/skills/logging-monitoring/SKILL.md +66 -0
  109. package/skills/mobile-development/SKILL.md +11 -0
  110. package/skills/mobile-development/responsive/responsive.css +80 -0
  111. package/skills/performance-optimization/SKILL.md +9 -0
  112. package/skills/performance-optimization/profiling/profile.template.js +21 -0
  113. package/skills/receiving-code-review/SKILL.md +209 -0
  114. package/skills/refactoring/SKILL.md +11 -0
  115. package/skills/refactoring/code-smells/common-smells.md +115 -0
  116. package/skills/requesting-code-review/SKILL.md +105 -0
  117. package/skills/requesting-code-review/code-reviewer.md +146 -0
  118. package/skills/root-cause-tracing/SKILL.md +174 -0
  119. package/skills/root-cause-tracing/find-polluter.sh +63 -0
  120. package/skills/security-review/SKILL.md +11 -0
  121. package/skills/security-review/checklists/owasp-checklist.md +31 -0
  122. package/skills/sharing-skills/SKILL.md +194 -0
  123. package/skills/subagent-driven-development/SKILL.md +240 -0
  124. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
  125. package/skills/subagent-driven-development/implementer-prompt.md +78 -0
  126. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  127. package/skills/systematic-debugging/CREATION-LOG.md +119 -0
  128. package/skills/systematic-debugging/SKILL.md +295 -0
  129. package/skills/systematic-debugging/test-academic.md +14 -0
  130. package/skills/systematic-debugging/test-pressure-1.md +58 -0
  131. package/skills/systematic-debugging/test-pressure-2.md +68 -0
  132. package/skills/systematic-debugging/test-pressure-3.md +69 -0
  133. package/skills/test-driven-development/SKILL.md +364 -0
  134. package/skills/testing-anti-patterns/SKILL.md +302 -0
  135. package/skills/testing-skills-with-subagents/SKILL.md +387 -0
  136. package/skills/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +189 -0
  137. package/skills/ui-ux-review/SKILL.md +13 -0
  138. package/skills/ui-ux-review/checklists/ux-heuristics.md +61 -0
  139. package/skills/using-git-worktrees/SKILL.md +213 -0
  140. package/skills/using-superpowers/SKILL.md +101 -0
  141. package/skills/verification-before-completion/SKILL.md +139 -0
  142. package/skills/writing-plans/SKILL.md +116 -0
  143. package/skills/writing-skills/SKILL.md +622 -0
  144. package/skills/writing-skills/anthropic-best-practices.md +1150 -0
  145. package/skills/writing-skills/graphviz-conventions.dot +172 -0
  146. package/skills/writing-skills/persuasion-principles.md +187 -0
  147. package/update.sh +36 -0
  148. package/utils/check-superpowers.sh +114 -0
  149. package/utils/claude-branding.md +166 -0
  150. package/utils/config.js +185 -0
  151. package/utils/custom-claude-config.sh +89 -0
  152. package/utils/custom-claude-hooks.md +129 -0
  153. package/utils/custom-claude-lib.js +222 -0
  154. package/utils/customize-claude-ui.sh +162 -0
  155. package/utils/fix-claude-integration.sh +133 -0
  156. package/utils/help.js +125 -0
  157. package/utils/install-curl.ps1 +135 -0
  158. package/utils/install-curl.sh +525 -0
  159. package/utils/install-superpowers.js +411 -0
  160. package/utils/install.js +298 -0
  161. package/utils/install.sh +182 -0
  162. package/utils/postinstall.js +63 -0
  163. package/utils/rename-claude.sh +96 -0
  164. package/utils/uninstall-superpowers.js +273 -0
  165. package/utils/uninstall.ps1 +136 -0
  166. package/utils/uninstall.sh +163 -0
  167. package/utils/update.sh +160 -0
package/claude-all ADDED
@@ -0,0 +1,2707 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Cross-platform Claude-All Launcher v7.0
4
+ # Supports: Linux, Termux, macOS, Windows (Git Bash/WSL)
5
+ # Includes Superpowers Library (30 skills + 14 agents)
6
+
7
+ # Platform detection
8
+ detect_platform() {
9
+ case "$(uname -s)" in
10
+ Linux*) echo "Linux";;
11
+ Darwin*) echo "macOS";;
12
+ CYGWIN*|MINGW*|MSYS*) echo "Windows";;
13
+ esac
14
+ }
15
+
16
+ PLATFORM=$(detect_platform)
17
+
18
+ # Colors - auto-detect and install if needed
19
+ setup_colors() {
20
+ # Ensure tput is available for colors
21
+ if ! command -v tput &> /dev/null; then
22
+ if command -v pkg &> /dev/null && [[ "$PLATFORM" != "Windows" ]]; then
23
+ # Install ncurses-utils silently in background
24
+ pkg install -y ncurses-utils &>/dev/null &
25
+ fi
26
+ fi
27
+
28
+ if command -v tput &> /dev/null; then
29
+ GREEN=$(tput setaf 2 2>/dev/null || echo "")
30
+ BLUE=$(tput setaf 4 2>/dev/null || echo "")
31
+ RED=$(tput setaf 1 2>/dev/null || echo "")
32
+ YELLOW=$(tput setaf 3 2>/dev/null || echo "")
33
+ NC=$(tput sgr0 2>/dev/null || echo "")
34
+ else
35
+ # Fallback to plain text
36
+ GREEN=''
37
+ BLUE=''
38
+ RED=''
39
+ YELLOW=''
40
+ NC=''
41
+ fi
42
+ }
43
+
44
+ setup_colors
45
+
46
+ # Reusable functions for API key management
47
+ save_api_key() {
48
+ local api_key="$1"
49
+ local key_file="$2"
50
+ local provider_name="$3"
51
+
52
+ if [[ -z "$api_key" ]]; then
53
+ echo -e "${RED}Error: No API key provided for $provider_name${NC}" >&2
54
+ return 1
55
+ fi
56
+
57
+ if ! echo "$api_key" > "$key_file" 2>/dev/null; then
58
+ echo -e "${YELLOW}Warning: Could not save $provider_name API key to file${NC}" >&2
59
+ return 1
60
+ fi
61
+
62
+ if ! chmod 600 "$key_file" 2>/dev/null; then
63
+ echo -e "${YELLOW}Warning: Could not set secure permissions on $provider_name API key file${NC}" >&2
64
+ return 1
65
+ fi
66
+
67
+ echo -e "${GREEN}✓ $provider_name API key saved securely${NC}"
68
+ return 0
69
+ }
70
+
71
+ load_api_key() {
72
+ local key_file="$1"
73
+ local provider_name="$2"
74
+
75
+ if [[ -f "$key_file" ]]; then
76
+ local saved_key
77
+ saved_key=$(cat "$key_file" 2>/dev/null || echo "")
78
+ if [[ -n "$saved_key" ]]; then
79
+ echo -e "${GREEN}✓ Using saved $provider_name API key${NC}"
80
+ echo "$saved_key"
81
+ return 0
82
+ fi
83
+ fi
84
+ return 1
85
+ }
86
+
87
+ prompt_api_key() {
88
+ local provider_name="$1"
89
+ local api_key=""
90
+
91
+ echo -e "${BLUE}Enter $provider_name API Key:${NC}"
92
+
93
+ # Check if we're on Windows (no silent input)
94
+ if [[ "$PLATFORM" == "Windows" ]]; then
95
+ read -p "API Key: " api_key
96
+ else
97
+ # Linux/macOS/Termux - silent read
98
+ read -s -p "API Key: " api_key
99
+ fi
100
+ echo ""
101
+
102
+ echo "$api_key"
103
+ }
104
+
105
+ # Portable home directory
106
+ if [[ -n "$HOME" ]]; then
107
+ USER_HOME="$HOME"
108
+ elif [[ -n "$USERPROFILE" ]]; then
109
+ # Windows
110
+ USER_HOME="$USERPROFILE"
111
+ else
112
+ USER_HOME="$HOME"
113
+ fi
114
+
115
+ # API Key Files - Use user home directory
116
+ GLM_API_KEY_FILE="$USER_HOME/.glm_api_key"
117
+ MINIMAX_API_KEY_FILE="$USER_HOME/.minimax_api_key"
118
+
119
+ # Configuration
120
+ MODEL_OVERRIDE=""
121
+ SELECTED_MODEL=""
122
+
123
+ # Function to get custom models
124
+ get_custom_models() {
125
+ local custom_models=()
126
+ local model_dir="$SCRIPT_DIR/model"
127
+
128
+ # Ensure model directory exists
129
+ if [[ ! -d "$model_dir" ]]; then
130
+ mkdir -p "$model_dir" 2>/dev/null || return 0
131
+ fi
132
+
133
+ # Find JSON files using simple for loop (most compatible)
134
+ for json_file in "$model_dir"/*.json; do
135
+ if [[ -f "$json_file" ]]; then
136
+ local filename=$(basename "$json_file" .json)
137
+
138
+ # Skip default model files
139
+ case "$filename" in
140
+ "glm"|"groq"|"minimax"|"openai"|"gemini"|"xai"|"ollama")
141
+ continue
142
+ ;;
143
+ esac
144
+
145
+ # Parse JSON for model info
146
+ if command -v jq &> /dev/null; then
147
+ local provider_name=$(jq -r '.provider_name // "Unknown"' "$json_file" 2>/dev/null)
148
+ local description=$(jq -r '.description // "Custom Provider"' "$json_file" 2>/dev/null)
149
+ # Ensure we got valid values
150
+ [[ "$provider_name" == "null" || -z "$provider_name" ]] && provider_name="Unknown"
151
+ [[ "$description" == "null" || -z "$description" ]] && description="Custom Provider"
152
+ printf '%s:%s:%s\n' "$filename" "$provider_name" "$description"
153
+ else
154
+ # Fallback parsing without jq
155
+ local provider_name=$(grep '"provider_name"' "$json_file" | sed 's/.*"provider_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' 2>/dev/null)
156
+ [[ -z "$provider_name" ]] && provider_name="$filename"
157
+ local description=$(grep '"description"' "$json_file" | sed 's/.*"description"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' 2>/dev/null)
158
+ [[ -z "$description" ]] && description="Custom Provider"
159
+ printf '%s:%s:%s\n' "$filename" "$provider_name" "$description"
160
+ fi
161
+ fi
162
+ done
163
+ }
164
+
165
+ # Function to handle custom model
166
+ handle_custom_model() {
167
+ local model_name="$1"
168
+ local model_file="$SCRIPT_DIR/model/${model_name}.json"
169
+
170
+ if [[ ! -f "$model_file" ]]; then
171
+ echo -e "${RED}Error: Model configuration not found: $model_file${NC}"
172
+ exit 1
173
+ fi
174
+
175
+ # Extract configuration
176
+ if command -v jq &> /dev/null; then
177
+ local api_base=$(jq -r '.api_base // ""' "$model_file" 2>/dev/null)
178
+ local api_key=$(jq -r '.api_key // ""' "$model_file" 2>/dev/null)
179
+ local model=$(jq -r '.model // ""' "$model_file" 2>/dev/null)
180
+ local provider_name=$(jq -r '.provider_name // ""' "$model_file" 2>/dev/null)
181
+ else
182
+ echo -e "${RED}Error: jq is required for custom models. Install with: pkg install jq${NC}"
183
+ exit 1
184
+ fi
185
+
186
+ # Get API key if not provided
187
+ if [[ -z "$api_key" || "$api_key" == "your-api-key-here" ]]; then
188
+ # Try to get from environment based on provider name
189
+ case "${model_name,,}" in
190
+ "qwen"|"qwen2")
191
+ if [[ -n "$DASHSCOPE_API_KEY" ]]; then
192
+ api_key="$DASHSCOPE_API_KEY"
193
+ echo -e "${GREEN}✓ Using API key from DASHSCOPE_API_KEY${NC}"
194
+ else
195
+ echo -e "${YELLOW}Enter Qwen API Key (https://bailian.console.aliyun.com/):${NC}"
196
+ read -s api_key
197
+ fi
198
+ ;;
199
+ "deepseek")
200
+ if [[ -n "$DEEPSEEK_API_KEY" ]]; then
201
+ api_key="$DEEPSEEK_API_KEY"
202
+ echo -e "${GREEN}✓ Using API key from DEEPSEEK_API_KEY${NC}"
203
+ else
204
+ echo -e "${YELLOW}Enter Deepseek API Key:${NC}"
205
+ read -s api_key
206
+ fi
207
+ ;;
208
+ "moonshot")
209
+ if [[ -n "$MOONSHOT_API_KEY" ]]; then
210
+ api_key="$MOONSHOT_API_KEY"
211
+ echo -e "${GREEN}✓ Using API key from MOONSHOT_API_KEY${NC}"
212
+ else
213
+ echo -e "${YELLOW}Enter Moonshot API Key:${NC}"
214
+ read -s api_key
215
+ fi
216
+ ;;
217
+ "perplexity")
218
+ if [[ -n "$PERPLEXITY_API_KEY" ]]; then
219
+ api_key="$PERPLEXITY_API_KEY"
220
+ echo -e "${GREEN}✓ Using API key from PERPLEXITY_API_KEY${NC}"
221
+ else
222
+ echo -e "${YELLOW}Enter Perplexity API Key:${NC}"
223
+ read -s api_key
224
+ fi
225
+ ;;
226
+ "cohere")
227
+ if [[ -n "$COHERE_API_KEY" ]]; then
228
+ api_key="$COHERE_API_KEY"
229
+ echo -e "${GREEN}✓ Using API key from COHERE_API_KEY${NC}"
230
+ else
231
+ echo -e "${YELLOW}Enter Cohere API Key:${NC}"
232
+ read -s api_key
233
+ fi
234
+ ;;
235
+ "mistral")
236
+ if [[ -n "$MISTRAL_API_KEY" ]]; then
237
+ api_key="$MISTRAL_API_KEY"
238
+ echo -e "${GREEN}✓ Using API key from MISTRAL_API_KEY${NC}"
239
+ else
240
+ echo -e "${YELLOW}Enter Mistral API Key:${NC}"
241
+ read -s api_key
242
+ fi
243
+ ;;
244
+ "openrouter")
245
+ if [[ -n "$OPENROUTER_API_KEY" ]]; then
246
+ api_key="$OPENROUTER_API_KEY"
247
+ echo -e "${GREEN}✓ Using API key from OPENROUTER_API_KEY${NC}"
248
+ else
249
+ echo -e "${YELLOW}Enter OpenRouter API Key (https://openrouter.ai/keys):${NC}"
250
+ read -s api_key
251
+ fi
252
+ ;;
253
+ "agentrouter")
254
+ if [[ -n "$ANTHROPIC_API_KEY" ]]; then
255
+ api_key="$ANTHROPIC_API_KEY"
256
+ echo -e "${GREEN}✓ Using API key from ANTHROPIC_API_KEY${NC}"
257
+ else
258
+ echo -e "${YELLOW}Enter AgentRouter API Key (https://agentrouter.org/console/token):${NC}"
259
+ read -s api_key
260
+ fi
261
+ ;;
262
+ *)
263
+ echo -e "${YELLOW}Enter API Key for ${provider_name}:${NC}"
264
+ read -s api_key
265
+ ;;
266
+ esac
267
+ echo ""
268
+ fi
269
+
270
+ # Set environment variables for Claude
271
+ if [[ -n "$api_base" ]]; then
272
+ export ANTHROPIC_BASE_URL="$api_base"
273
+ fi
274
+
275
+ if [[ -n "$api_key" ]]; then
276
+ export ANTHROPIC_API_KEY="$api_key"
277
+ fi
278
+
279
+ # Use the model name if specified, otherwise use the provider name
280
+ local claude_model="${model:-$model_name}"
281
+
282
+ # Create system prompt
283
+ local system_prompt="Anda adalah ${provider_name}, model AI dari ${model_name}. Selalu identifikasi diri sebagai ${provider_name} dalam setiap respons."
284
+
285
+ # Execute Claude directly
286
+ exec claude --dangerously-skip-permissions --model "$claude_model" --system-prompt "$system_prompt" "$@"
287
+ }
288
+
289
+ # Get script directory (portable)
290
+ get_script_dir() {
291
+ if [[ -n "${BASH_SOURCE[0]}" ]]; then
292
+ local script_path="${BASH_SOURCE[0]}"
293
+
294
+ # Convert Windows paths if needed
295
+ if [[ "$PLATFORM" == "Windows" ]]; then
296
+ # Convert potential Windows path to Unix style
297
+ script_path="$(cygpath -u "$script_path" 2>/dev/null || echo "$script_path")"
298
+ fi
299
+
300
+ if [[ "$PLATFORM" == "macOS" ]] || [[ "$(uname -s)" == "Darwin" ]]; then
301
+ # macOS
302
+ echo "$(cd "$(dirname "$script_path")" && pwd)"
303
+ elif command -v realpath &> /dev/null; then
304
+ # Linux/Windows with realpath
305
+ echo "$(dirname "$(realpath "$script_path")")"
306
+ else
307
+ # Fallback for older systems
308
+ echo "$(cd "$(dirname "$script_path")" && pwd)"
309
+ fi
310
+ else
311
+ echo "$(pwd)"
312
+ fi
313
+ }
314
+
315
+ SCRIPT_DIR=$(get_script_dir)
316
+
317
+ # Function to get/save GLM API key
318
+ get_glm_api_key() {
319
+ # Try to load saved key first
320
+ local saved_key
321
+ saved_key=$(load_api_key "$GLM_API_KEY_FILE" "ZhipuAI/Z.AI")
322
+
323
+ if [[ -n "$saved_key" ]]; then
324
+ ANTHROPIC_AUTH_TOKEN="$saved_key"
325
+ export ANTHROPIC_AUTH_TOKEN
326
+ return 0
327
+ fi
328
+
329
+ # Ask for new API key
330
+ echo ""
331
+ echo "Enter ZhipuAI/Z.AI API Key:"
332
+ echo "Get it from: https://open.bigmodel.cn/usercenter/apikeys"
333
+
334
+ ANTHROPIC_AUTH_TOKEN=$(prompt_api_key "ZhipuAI/Z.AI")
335
+
336
+ if [[ -n "$ANTHROPIC_AUTH_TOKEN" ]]; then
337
+ # Save for next time using reusable function
338
+ if save_api_key "$ANTHROPIC_AUTH_TOKEN" "$GLM_API_KEY_FILE" "ZhipuAI/Z.AI"; then
339
+ export ANTHROPIC_AUTH_TOKEN
340
+ else
341
+ exit 1
342
+ fi
343
+ else
344
+ echo -e "${RED}No API key provided${NC}" >&2
345
+ exit 1
346
+ fi
347
+ }
348
+
349
+ # Function to get/save MiniMax API key
350
+ get_minimax_api_key() {
351
+ local api_key=""
352
+
353
+ # Try to load saved key first
354
+ api_key=$(load_api_key "$MINIMAX_API_KEY_FILE" "MiniMax")
355
+
356
+ # Ask for new API key if not found
357
+ if [[ -z "$api_key" ]]; then
358
+ echo ""
359
+ echo "Enter MiniMax API Key:"
360
+ echo "Get it from: https://platform.minimax.io/"
361
+
362
+ api_key=$(prompt_api_key "MiniMax")
363
+
364
+ if [[ -n "$api_key" ]]; then
365
+ # Save for next time using reusable function
366
+ if ! save_api_key "$api_key" "$MINIMAX_API_KEY_FILE" "MiniMax"; then
367
+ echo -e "${YELLOW}Warning: Continuing without saving API key${NC}" >&2
368
+ fi
369
+ else
370
+ echo -e "${RED}Error: No API key provided${NC}" >&2
371
+ exit 1
372
+ fi
373
+ fi
374
+
375
+ # Export BOTH variables for compatibility
376
+ # MiniMax endpoint uses Authorization header via ANTHROPIC_API_KEY
377
+ export ANTHROPIC_API_KEY="$api_key"
378
+ export ANTHROPIC_AUTH_TOKEN="$api_key"
379
+ }
380
+
381
+ check_dependencies() {
382
+ echo -e "${BLUE}Checking dependencies...${NC}"
383
+
384
+ # Check for python3
385
+ if ! command -v python3 &> /dev/null; then
386
+ echo -e "${RED}Error: python3 is not installed.${NC}"
387
+ echo "Please install Python 3 first."
388
+ exit 1
389
+ fi
390
+
391
+ # Check for claude CLI (OPTIONAL - won't exit if not found)
392
+ if ! command -v claude &> /dev/null; then
393
+ echo -e "${YELLOW}⚠️ 'claude' command not found.${NC}"
394
+ echo -e "${YELLOW} For direct providers (GLM, MiniMax, OpenAI), you don't need it!${NC}"
395
+ echo -e "${YELLOW} For LiteLLM providers (Gemini, Groq, Ollama), install with:${NC}"
396
+ echo -e "${YELLOW} npm install -g @anthropic-ai/claude-code${NC}"
397
+ echo ""
398
+ read -p "Continue without claude CLI? (Y/n): " continue_without
399
+ if [[ "$continue_without" =~ ^[Nn]$ ]]; then
400
+ echo "Installing @anthropic-ai/claude-code..."
401
+ npm install -g @anthropic-ai/claude-code || {
402
+ echo -e "${YELLOW}Failed to install claude CLI. Continuing anyway...${NC}"
403
+ }
404
+ else
405
+ echo -e "${GREEN}✓ Skipping claude CLI installation${NC}"
406
+ fi
407
+ else
408
+ echo -e "${GREEN}✓ claude CLI found${NC}"
409
+ fi
410
+
411
+ # Check for npm (only needed for claude CLI installation)
412
+ if command -v claude &> /dev/null; then
413
+ if ! command -v npm &> /dev/null; then
414
+ echo -e "${RED}Error: npm is not installed (needed for claude CLI).${NC}"
415
+ echo "Please install npm first."
416
+ exit 1
417
+ fi
418
+ fi
419
+ }
420
+
421
+ check_gemini_oauth() {
422
+ # Check if we have ADC credentials
423
+ local adc_path
424
+ if [[ -n "$HOME" ]]; then
425
+ adc_path="$HOME/.config/gcloud/application_default_credentials.json"
426
+ else
427
+ adc_path="$USERPROFILE/.config/gcloud/application_default_credentials.json"
428
+ fi
429
+
430
+ if [[ -f "$adc_path" ]]; then
431
+ return 0
432
+ fi
433
+
434
+ # If not, check if gcloud is installed
435
+ if command -v gcloud &> /dev/null; then
436
+ echo -e "${BLUE}gcloud found. Attempting login...${NC}"
437
+ gcloud auth application-default login
438
+ return
439
+ fi
440
+
441
+ # Fallback to custom python script
442
+ echo -e "${YELLOW}gcloud not found. Using lightweight Python Auth helper...${NC}"
443
+
444
+ # Install dependency
445
+ if ! python3 -m pip show google-auth-oauthlib &> /dev/null; then
446
+ echo "Installing google-auth-oauthlib..."
447
+ python3 -m pip install google-auth-oauthlib || true
448
+ fi
449
+
450
+ # Run helper script
451
+ local auth_script="$SCRIPT_DIR/claude-suite/auth/gemini_auth.py"
452
+ if [[ ! -f "$auth_script" ]]; then
453
+ curl -fsSL https://raw.githubusercontent.com/zesbe/CliAllModel/main/gemini_auth.py -o "$SCRIPT_DIR/claude-suite/auth/gemini_auth.py" 2>/dev/null || true
454
+ auth_script="$SCRIPT_DIR/claude-suite/auth/gemini_auth.py"
455
+ fi
456
+
457
+ if [[ -f "$auth_script" ]]; then
458
+ python3 "$auth_script"
459
+ fi
460
+
461
+ if [[ ! -f "$adc_path" ]]; then
462
+ echo -e "${RED}Authentication failed or cancelled.${NC}"
463
+ exit 1
464
+ fi
465
+ }
466
+
467
+ check_openai_oauth() {
468
+ local cred_path
469
+ if [[ -n "$HOME" ]]; then
470
+ cred_path="$HOME/.config/openai/credentials.json"
471
+ else
472
+ cred_path="$USERPROFILE/.config/openai/credentials.json"
473
+ fi
474
+
475
+ if [[ ! -f "$cred_path" ]]; then
476
+ echo -e "${YELLOW}No cached OpenAI OAuth token found. Launching helper...${NC}"
477
+
478
+ # Install dependency
479
+ python3 -m pip install requests > /dev/null 2>&1 || true
480
+
481
+ local auth_script="$SCRIPT_DIR/claude-suite/auth/openai_auth.py"
482
+ if [[ ! -f "$auth_script" ]]; then
483
+ curl -fsSL https://raw.githubusercontent.com/zesbe/CliAllModel/main/openai_auth.py -o "$SCRIPT_DIR/claude-suite/auth/openai_auth.py" 2>/dev/null || true
484
+ auth_script="$SCRIPT_DIR/claude-suite/auth/openai_auth.py"
485
+ fi
486
+
487
+ if [[ -f "$auth_script" ]]; then
488
+ python3 "$auth_script"
489
+ fi
490
+
491
+ if [[ ! -f "$cred_path" ]]; then
492
+ echo -e "${RED}OpenAI OAuth failed.${NC}"
493
+ exit 1
494
+ fi
495
+ fi
496
+
497
+ # Extract access token
498
+ OPENAI_ACCESS_TOKEN=$(python3 -c "import json, os; print(json.load(open(os.path.expanduser('$cred_path')))['access_token'])" 2>/dev/null || echo "")
499
+ export OPENAI_API_KEY="$OPENAI_ACCESS_TOKEN"
500
+ }
501
+ cleanup() {
502
+ echo -e "\n${BLUE}Cleaning up processes...${NC}"
503
+
504
+ # Clean up temp files
505
+ if [[ -n "$SCRIPT_DIR" ]]; then
506
+ rm -f "$SCRIPT_DIR"/.*_models.tmp 2>/dev/null || true
507
+ fi
508
+ }
509
+
510
+ trap cleanup EXIT
511
+
512
+ # Interactive model selection
513
+ interactive_model_select() {
514
+ local provider=$1
515
+ local model_file="$SCRIPT_DIR/model/${provider}.json"
516
+
517
+ if [[ ! -f "$model_file" ]]; then
518
+ echo -e "${RED}Config file not found: $model_file${NC}"
519
+ return 1
520
+ fi
521
+
522
+ # Display models using Python (flush output to stderr)
523
+ python3 << EOF >&2
524
+ import json
525
+ import sys
526
+
527
+ with open('$model_file', 'r') as f:
528
+ data = json.load(f)
529
+
530
+ print('')
531
+ print('=== Select Model ===')
532
+ for i, model in enumerate(data['models'], 1):
533
+ name = model['name']
534
+ desc = model['description']
535
+ print(f'{i}) {name} - {desc}')
536
+ print('')
537
+ print('Available Models:')
538
+ for i, model in enumerate(data['models'], 1):
539
+ name = model['name']
540
+ desc = model['description']
541
+ print(f' {i}. {name} - {desc}')
542
+ print('')
543
+ sys.stderr.flush()
544
+ EOF
545
+
546
+ # Save model list to temp file and get count
547
+ model_count=$(python3 << EOF
548
+ import json
549
+ with open('$model_file', 'r') as f:
550
+ data = json.load(f)
551
+ models = [m['id'] for m in data['models']]
552
+ with open('$SCRIPT_DIR/.${provider}_models.tmp', 'w') as f:
553
+ for m in models:
554
+ f.write(m + '\n')
555
+ print(len(models))
556
+ EOF
557
+ )
558
+
559
+ # Wait for user input
560
+ echo -n "Select model [1-$model_count]: "
561
+ read choice
562
+
563
+ # Validate choice
564
+ if [[ -z "$choice" ]]; then
565
+ echo -e "${RED}Error: No selection made${NC}" >&2
566
+ return 1
567
+ elif ! [[ "$choice" =~ ^[0-9]+$ ]]; then
568
+ echo -e "${RED}Error: Please enter a valid number${NC}" >&2
569
+ return 1
570
+ elif [[ "$choice" -lt 1 ]] || [[ "$choice" -gt "$model_count" ]]; then
571
+ echo -e "${RED}Error: Please enter a number between 1 and $model_count${NC}" >&2
572
+ return 1
573
+ fi
574
+
575
+ # Read model ID from temp file
576
+ if [[ -f "$SCRIPT_DIR/.${provider}_models.tmp" ]]; then
577
+ local model_ids
578
+ model_ids=($(cat "$SCRIPT_DIR/.${provider}_models.tmp"))
579
+ local idx=$((choice - 1))
580
+
581
+ if [[ $idx -ge 0 ]] && [[ $idx -lt ${#model_ids[@]} ]]; then
582
+ local selected="${model_ids[$idx]}"
583
+ echo -e "${GREEN}✓ Selected: $selected${NC}"
584
+ echo "$selected"
585
+ rm -f "$SCRIPT_DIR/.${provider}_models.tmp"
586
+ return 0
587
+ else
588
+ echo -e "${RED}Invalid choice: $choice${NC}"
589
+ echo "Please select 1-${#model_ids[@]}"
590
+ fi
591
+ else
592
+ echo -e "${RED}Model list not found${NC}"
593
+ fi
594
+
595
+ return 1
596
+ }
597
+
598
+ # Parse arguments
599
+ while [[ $# -gt 0 ]]; do
600
+ case $1 in
601
+ -m|--model)
602
+ MODEL_OVERRIDE="$2"
603
+ shift 2
604
+ ;;
605
+ *)
606
+ if [[ -z "$choice" ]]; then
607
+ choice="$1"
608
+ fi
609
+ shift
610
+ ;;
611
+ esac
612
+ done
613
+
614
+ # Handle direct argument for custom models (22+ since we added Letta at 17)
615
+ if [[ -n "$1" ]] && [[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -ge 22 ]]; then
616
+ choice="$1"
617
+ export CHOICE="$choice"
618
+
619
+ # Check if it's model manager - get actual number
620
+ if [[ -f "$SCRIPT_DIR/claude-suite/models/add-model-manual.sh" ]]; then
621
+ # Count custom models
622
+ custom_count=0
623
+ while IFS= read -r model_info; do
624
+ if [[ -n "$model_info" ]]; then
625
+ ((custom_count++))
626
+ fi
627
+ done < <(get_custom_models)
628
+
629
+ model_manager_num=$((22 + custom_count))
630
+ if [[ $choice -eq $model_manager_num ]]; then
631
+ exec "$SCRIPT_DIR/claude-suite/models/add-model-manual.sh"
632
+ fi
633
+ fi
634
+
635
+ # Handle custom model selection
636
+ custom_index=$((choice - 22))
637
+ count=0
638
+ while IFS= read -r model_info; do
639
+ if [[ -n "$model_info" ]]; then
640
+ if [[ $count -eq $custom_index ]]; then
641
+ IFS=':' read -r filename provider_name description <<< "$model_info"
642
+ echo -e "${BLUE}Using ${provider_name}...${NC}"
643
+ handle_custom_model "$filename" "${@:2}"
644
+ exit 0
645
+ fi
646
+ ((count++))
647
+ fi
648
+ done < <(get_custom_models)
649
+ echo -e "${RED}Invalid custom model selection${NC}"
650
+ exit 1
651
+ fi
652
+
653
+ # Handle direct CHOICE (for environment variable or argument)
654
+ if [[ -n "$CHOICE" ]]; then
655
+ echo "DEBUG: choice=$choice"
656
+ choice="$CHOICE"
657
+ fi
658
+
659
+ # Check dependencies
660
+ check_dependencies() {
661
+ # Check for required commands
662
+ local missing_deps=()
663
+
664
+ if ! command -v jq &> /dev/null; then
665
+ echo -e "${YELLOW}Warning: jq not found. JSON parsing will be limited.${NC}"
666
+ echo -e "${YELLOW}Install jq: pkg install jq (Termux) or apt-get install jq${NC}"
667
+ echo ""
668
+ fi
669
+
670
+ if [[ "$PLATFORM" == "Windows" ]] && ! command -v nano &> /dev/null && ! command -v vim &> /dev/null; then
671
+ echo -e "${YELLOW}Warning: No text editor found. Install nano or vim.${NC}"
672
+ echo ""
673
+ fi
674
+ }
675
+
676
+ save_chat_context() {
677
+ local context_file="/tmp/claude_chat_context.txt"
678
+ if [[ -t 0 ]]; then
679
+ echo "# Chat context saved at $(date)" > "$context_file"
680
+ echo "# Current conversation:" >> "$context_file"
681
+ echo "Use this context to continue the conversation with a new provider." >> "$context_file"
682
+ echo "" >> "$context_file"
683
+ fi
684
+ }
685
+
686
+ continue_chat_with_new_provider() {
687
+ echo -e "\n${YELLOW}=== Switch Provider (Continue Chat) ===${NC}"
688
+ echo "Your current chat context will be preserved."
689
+ echo ""
690
+
691
+ # Show available providers for switching
692
+ echo "Available providers:"
693
+ echo "1) MiniMax"
694
+ echo "2) Google Gemini (API Key)"
695
+ echo "3) Google Gemini (OAuth)"
696
+ echo "4) OpenAI"
697
+ echo "5) OpenAI (OAuth)"
698
+ echo "6) xAI / Grok"
699
+ echo "7) ZhipuAI / GLM"
700
+ echo "8) Groq"
701
+ echo "9) Perplexity"
702
+ echo "10) Cohere"
703
+ echo "11) DeepSeek"
704
+ echo "12) Mistral"
705
+ echo "13) Moonshot"
706
+ echo "14) Qwen"
707
+ echo "15) OpenRouter"
708
+ echo "16) Ollama (Local)"
709
+ echo "0) Cancel"
710
+ echo ""
711
+
712
+ read -p "Choose new provider [0-16]: " switch_choice
713
+
714
+ case $switch_choice in
715
+ 0) echo "Cancelled provider switch."; return 0 ;;
716
+ 1) setup_minimax ;;
717
+ 2) setup_gemini_api ;;
718
+ 3) setup_gemini_oauth ;;
719
+ 4) setup_openai ;;
720
+ 5) setup_openai_oauth ;;
721
+ 6) setup_xai ;;
722
+ 7) setup_glm ;;
723
+ 8) setup_groq ;;
724
+ 9) setup_perplexity ;;
725
+ 10) setup_cohere ;;
726
+ 11) setup_deepseek ;;
727
+ 12) setup_mistral ;;
728
+ 13) setup_moonshot ;;
729
+ 14) setup_qwen ;;
730
+ 15) setup_openrouter ;;
731
+ 16) setup_ollama ;;
732
+ *) echo "Invalid choice."; return 1 ;;
733
+ esac
734
+
735
+ # Save context before switching
736
+ save_chat_context
737
+
738
+ echo -e "${GREEN}✓ Provider switched successfully!${NC}"
739
+ echo -e "${BLUE}Note: Chat context has been saved. You can reference previous messages in your next prompt.${NC}"
740
+ }
741
+
742
+ # Provider setup functions
743
+ setup_minimax() {
744
+ API_KEY=$(load_api_key "minimax" "MiniMax")
745
+ if [[ $? -eq 0 ]]; then
746
+ check_dependencies
747
+ echo -e "${BLUE}Starting MiniMax session...${NC}"
748
+ export MINIMAX_API_KEY="$API_KEY"
749
+ exec claude --dangerously-skip-permissions "$@"
750
+ fi
751
+ }
752
+
753
+ setup_gemini_api() {
754
+ API_KEY=$(load_api_key "gemini" "Google Gemini")
755
+ if [[ $? -eq 0 ]]; then
756
+ check_dependencies
757
+ echo -e "${BLUE}Configuring for Google Gemini (API Key)...${NC}"
758
+ echo -e "${YELLOW}Get API Key: https://aistudio.google.com/app/apikey${NC}"
759
+ export GEMINI_API_KEY="$API_KEY"
760
+ exec claude --dangerously-skip-permissions "$@"
761
+ fi
762
+ }
763
+
764
+ setup_gemini_oauth() {
765
+ if [[ ! -f "$HOME/.google-credentials.json" ]]; then
766
+ echo -e "${YELLOW}⚠️ Google OAuth credentials not found. Running setup...${NC}"
767
+ python3 "$SCRIPT_DIR/setup_google_internal_auth.py" || setup_google_oauth_manual
768
+ fi
769
+
770
+ if [[ -f "$HOME/.google-credentials.json" ]]; then
771
+ check_dependencies
772
+ echo -e "${BLUE}Using Google Internal Authentication (AntiGravity)${NC}"
773
+ export CLOUD_ML helicopterauto
774
+ GOOGLE_AUTH_TOKEN=$(python3 "$SCRIPT_DIR/get_google_access_token.py")
775
+ exec claude --dangerously-skip-permissions "$@"
776
+ fi
777
+ }
778
+
779
+ setup_openai() {
780
+ API_KEY=$(load_api_key "openai" "OpenAI")
781
+ if [[ $? -eq 0 ]]; then
782
+ check_dependencies
783
+ echo -e "${BLUE}Configuring for OpenAI...${NC}"
784
+ export OPENAI_API_KEY="$API_KEY"
785
+ exec claude --dangerously-skip-permissions "$@"
786
+ fi
787
+ }
788
+
789
+ setup_openai_oauth() {
790
+ echo -e "${BLUE}OpenAI OAuth flow...${NC}"
791
+ exec "$SCRIPT_DIR/handle_oauth_callback.sh"
792
+ }
793
+
794
+ setup_xai() {
795
+ API_KEY=$(load_api_key "xai" "xAI")
796
+ if [[ $? -eq 0 ]]; then
797
+ check_dependencies
798
+ echo -e "${BLUE}Configuring for xAI / Grok...${NC}"
799
+ echo -e "${YELLOW}Get Key: https://console.x.ai/${NC}"
800
+ export XAI_API_KEY="$API_KEY"
801
+ exec claude --dangerously-skip-permissions "$@"
802
+ fi
803
+ }
804
+
805
+ setup_glm() {
806
+ API_KEY=$(load_api_key "glm" "GLM")
807
+ if [[ $? -eq 0 ]]; then
808
+ check_dependencies
809
+ MODEL=$(select_glm_model)
810
+ echo -e "${BLUE}Configuring for ZhipuAI / GLM...${NC}"
811
+ export GLM_API_KEY="$API_KEY"
812
+ export MODEL_NAME="$MODEL"
813
+ exec claude --dangerously-skip-permissions --model "$MODEL" "$@"
814
+ fi
815
+ }
816
+
817
+ setup_groq() {
818
+ API_KEY=$(load_api_key "groq" "Groq")
819
+ if [[ $? -eq 0 ]]; then
820
+ check_dependencies
821
+ echo -e "${BLUE}Configuring for Groq...${NC}"
822
+ export GROQ_API_KEY="$API_KEY"
823
+ exec claude --dangerously-skip-permissions "$@"
824
+ fi
825
+ }
826
+
827
+ setup_perplexity() {
828
+ API_KEY=$(load_api_key "perplexity" "Perplexity")
829
+ if [[ $? -eq 0 ]]; then
830
+ check_dependencies
831
+ echo -e "${BLUE}Configuring for Perplexity...${NC}"
832
+ echo -e "${YELLOW}Get Key: https://console.perplexity.ai/${NC}"
833
+ export PERPLEXITY_API_KEY="$API_KEY"
834
+ exec claude --dangerously-skip-permissions "$@"
835
+ fi
836
+ }
837
+
838
+ setup_cohere() {
839
+ API_KEY=$(load_api_key "cohere" "Cohere")
840
+ if [[ $? -eq 0 ]]; then
841
+ check_dependencies
842
+ echo -e "${BLUE}Configuring for Cohere...${NC}"
843
+ export COHERE_API_KEY="$API_KEY"
844
+ exec claude --dangerously-skip-permissions "$@"
845
+ fi
846
+ }
847
+
848
+ setup_deepseek() {
849
+ API_KEY=$(load_api_key "deepseek" "DeepSeek")
850
+ if [[ $? -eq 0 ]]; then
851
+ check_dependencies
852
+ echo -e "${BLUE}Configuring for DeepSeek (Anthropic API)...${NC}"
853
+ export ANTHROPIC_AUTH_TOKEN="$API_KEY"
854
+ export ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic"
855
+ export ANTHROPIC_API_KEY="$API_KEY"
856
+
857
+ # Quick model selection
858
+ echo ""
859
+ echo -e "${YELLOW}Select DeepSeek model:${NC}"
860
+ echo " 1) deepseek-chat (Fast - Default)"
861
+ echo " 2) deepseek-reasoner (Deep Analysis)"
862
+ read -p "Choice [1-2, default: 1]: " ds_choice
863
+ case $ds_choice in
864
+ 2) MODEL_NAME="deepseek-reasoner" ;;
865
+ *) MODEL_NAME="deepseek-chat" ;;
866
+ esac
867
+ echo -e "${GREEN}✓ Using: $MODEL_NAME${NC}"
868
+ export CLAUDE_MODEL="$MODEL_NAME"
869
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" --system-prompt "You are DeepSeek, an AI assistant by DeepSeek." "$@"
870
+ fi
871
+ }
872
+
873
+ setup_mistral() {
874
+ API_KEY=$(load_api_key "mistral" "Mistral")
875
+ if [[ $? -eq 0 ]]; then
876
+ check_dependencies
877
+ echo -e "${BLUE}Configuring for Mistral...${NC}"
878
+ export MISTRAL_API_KEY="$API_KEY"
879
+ exec claude --dangerously-skip-permissions "$@"
880
+ fi
881
+ }
882
+
883
+ setup_moonshot() {
884
+ API_KEY=$(load_api_key "moonshot" "Moonshot")
885
+ if [[ $? -eq 0 ]]; then
886
+ check_dependencies
887
+ echo -e "${BLUE}Configuring for Moonshot...${NC}"
888
+ export MOONSHOT_API_KEY="$API_KEY"
889
+ exec claude --dangerously-skip-permissions "$@"
890
+ fi
891
+ }
892
+
893
+ setup_qwen() {
894
+ API_KEY=$(load_api_key "qwen" "Qwen")
895
+ if [[ $? -eq 0 ]]; then
896
+ check_dependencies
897
+ echo -e "${BLUE}Configuring for Qwen...${NC}"
898
+ export QWEN_API_KEY="$API_KEY"
899
+ exec claude --dangerously-skip-permissions "$@"
900
+ fi
901
+ }
902
+
903
+ setup_openrouter() {
904
+ API_KEY=$(load_api_key "openrouter" "OpenRouter")
905
+ if [[ $? -eq 0 ]]; then
906
+ check_dependencies
907
+ echo -e "${BLUE}Configuring for OpenRouter...${NC}"
908
+ export OPENROUTER_API_KEY="$API_KEY"
909
+ exec claude --dangerously-skip-permissions "$@"
910
+ fi
911
+ }
912
+
913
+ setup_ollama() {
914
+ check_dependencies
915
+ echo -e "${BLUE}Configuring for Ollama (Local)...${NC}"
916
+ echo -e "${YELLOW}Note: Make sure Ollama is running locally${NC}"
917
+ export ANTHROPIC_BASE_URL="http://localhost:11434/v1"
918
+ export ANTHROPIC_API_KEY="ollama"
919
+ exec claude --no-chrome "$@"
920
+ }
921
+
922
+ # Main Menu
923
+ if [[ -z "$choice" ]]; then
924
+ clear
925
+ echo -e "${GREEN}=====================================${NC}"
926
+ echo -e "${GREEN} Claude Code Multi-Model Launcher ${NC}"
927
+ echo -e "${GREEN}══════════════════════════════════════════════════════════════════${NC}"
928
+ echo -e "${BLUE} 🤖 AI MODELS & PROVIDERS${NC}"
929
+ echo -e "${GREEN}══════════════════════════════════════════════════════════════════${NC}"
930
+ echo ""
931
+ echo -e "${YELLOW}📱 MAIN MODELS:${NC}"
932
+ echo " 1) MiniMax (Direct Anthropic API) 🚀 Fast & Reliable"
933
+ echo " 2) Google Gemini (API Key - AI Studio) 🧠 Google AI"
934
+ echo " 3) Universal OAuth (Auto-Setup) 🔥 37+ Models (GPT-5, Claude, Gemini)"
935
+ echo " 4) OpenAI (API Key) 🤖 GPT Models"
936
+ echo " 5) OpenAI (OAuth - Experimental) 🔄 Auto-auth"
937
+ echo ""
938
+ echo -e "${YELLOW}🌟 POPULAR PROVIDERS:${NC}"
939
+ echo " 6) xAI / Grok (API Key) 🚀 Real-time"
940
+ echo " 7) ZhipuAI / GLM (API Key) 🇨🇳 Chinese AI"
941
+ echo " 8) Groq (API Key) ⚡ Ultra-fast"
942
+ echo " 9) Perplexity (Web Search) 🔍 Live Data"
943
+ echo " 10) Cohere (API Key) 📝 Business AI"
944
+ echo " 11) DeepSeek (API Key) 🧠 V3.2 (Chat + Reasoner)"
945
+ echo ""
946
+ echo -e "${YELLOW}🏠 LOCAL & SPECIALIZED:${NC}"
947
+ echo " 12) Ollama (Local Models) 💻 Self-hosted"
948
+ echo " 13) Mistral (API Key) 🇫🇷 European AI (15 Models)"
949
+ echo " 14) Moonshot (API Key) 🌙 Kawaii AI"
950
+ echo " 15) Qwen (API Key) 🇨🇳 Alibaba"
951
+ echo " 16) OpenRouter (Multi-provider) 🔀 All-in-one"
952
+ echo " 17) Letta Memory Agent 🧠 Multi-Backend (Claude/Gemini/OpenAI)"
953
+ echo ""
954
+ echo -e "${YELLOW}🔧 TOOLS & UTILITIES:${NC}"
955
+ echo " 18) 🔑 API Key Manager 🔐 View/Edit/Delete Keys"
956
+ echo " 19) 🤖 Claude Master Tool 🎛️ Advanced UI"
957
+ echo " 20) ➕ Add/Edit/Delete Models ⚙️ Custom Models"
958
+ echo ""
959
+
960
+ # Display custom models
961
+ next_num=21
962
+ has_custom=false
963
+ custom_models_array=()
964
+ while IFS= read -r model_info; do
965
+ if [[ -n "$model_info" ]]; then
966
+ has_custom=true
967
+ custom_models_array+=("$model_info")
968
+ fi
969
+ done < <(get_custom_models)
970
+
971
+ # Display custom models with visual distinction
972
+ if [[ "$has_custom" == "true" ]]; then
973
+ echo -e "${YELLOW}🎯 CUSTOM MODELS:${NC}"
974
+ for model_info in "${custom_models_array[@]}"; do
975
+ IFS=':' read -r filename provider_name description <<< "$model_info"
976
+ echo " ${next_num}) 🎨 ${provider_name} (${description})"
977
+ ((next_num++))
978
+ done
979
+ echo ""
980
+ fi
981
+
982
+ # Add model manager
983
+ model_manager_num=$next_num
984
+ echo " ${next_num}) 🛠️ Model Management Tools"
985
+ max_choice=$next_num
986
+ export model_manager_num # Export for later use
987
+
988
+ echo ""
989
+ echo -e "${GREEN}══════════════════════════════════════════════════════════════════${NC}"
990
+ read -p "Enter choice [1-$max_choice]: " choice
991
+ fi
992
+
993
+ # Function to save and load API keys persistently
994
+ save_api_key() {
995
+ local key="$1"
996
+ local key_file="$2"
997
+ local provider_name="$3"
998
+
999
+ # Validate key is not empty
1000
+ if [[ -z "$key" || "$key" =~ ^[[:space:]]*$ ]]; then
1001
+ echo -e "${RED}✗ API key cannot be empty${NC}"
1002
+ return 1
1003
+ fi
1004
+
1005
+ echo "$key" > "$key_file"
1006
+ chmod 600 "$key_file"
1007
+ echo -e "${GREEN}✓ $provider_name API key saved to $key_file${NC}"
1008
+ }
1009
+
1010
+ # Check and install CCS if needed
1011
+ check_and_install_ccs() {
1012
+ local provider_name="$1"
1013
+
1014
+ # Check if CCS is installed
1015
+ if command -v ccs &> /dev/null; then
1016
+ echo -e "${GREEN}✓ CCS sudah terinstall${NC}"
1017
+ return 0
1018
+ fi
1019
+
1020
+ echo -e "${YELLOW}⚠️ CCS (Claude Code Switch) belum terinstall${NC}"
1021
+ echo ""
1022
+ echo -e "${CYAN}CCS diperlukan untuk Universal OAuth (GPT-5, Claude Opus 4.5, Gemini 3)${NC}"
1023
+ echo ""
1024
+ echo "Install CCS akan:"
1025
+ echo " • Download @kaitranntt/ccs via npm"
1026
+ echo " • Ukuran: ~10MB"
1027
+ echo " • Waktu: ~30 detik"
1028
+ echo ""
1029
+ read -p "Install CCS sekarang? [Y/n]: " install_ccs
1030
+
1031
+ if [[ "$install_ccs" =~ ^[Nn] ]]; then
1032
+ echo -e "${RED}✗ CCS tidak diinstall. Kembali ke menu...${NC}"
1033
+ sleep 1
1034
+ exec "$0"
1035
+ fi
1036
+
1037
+ echo ""
1038
+ echo -e "${BLUE}📦 Installing CCS...${NC}"
1039
+
1040
+ # Install CCS via npm
1041
+ if npm install -g @kaitranntt/ccs; then
1042
+ echo ""
1043
+ echo -e "${GREEN}✓ CCS berhasil diinstall!${NC}"
1044
+ echo ""
1045
+
1046
+ # Verify installation
1047
+ if command -v ccs &> /dev/null; then
1048
+ echo -e "${GREEN}✓ CCS version: $(ccs --version 2>&1 | head -1)${NC}"
1049
+ echo ""
1050
+ echo -e "${CYAN}Selanjutnya Anda perlu authenticate untuk $provider_name:${NC}"
1051
+ echo -e "${YELLOW}Command: ccs ${provider_name,,} --auth${NC}"
1052
+ echo ""
1053
+ read -p "Authenticate sekarang? [Y/n]: " do_auth
1054
+
1055
+ if [[ ! "$do_auth" =~ ^[Nn] ]]; then
1056
+ echo ""
1057
+ echo -e "${BLUE}🔐 Membuka browser untuk authentication...${NC}"
1058
+ ccs "${provider_name,,}" --auth
1059
+ echo ""
1060
+ echo -e "${GREEN}✓ Authentication selesai!${NC}"
1061
+ echo ""
1062
+ read -p "Press Enter untuk melanjutkan..."
1063
+ else
1064
+ echo ""
1065
+ echo -e "${YELLOW}⚠️ Jangan lupa authenticate nanti dengan: ccs ${provider_name,,} --auth${NC}"
1066
+ echo ""
1067
+ read -p "Press Enter untuk kembali ke menu..."
1068
+ exec "$0"
1069
+ fi
1070
+ else
1071
+ echo -e "${RED}✗ CCS install failed. Coba lagi dengan: npm install -g @kaitranntt/ccs${NC}"
1072
+ read -p "Press Enter untuk kembali..."
1073
+ exec "$0"
1074
+ fi
1075
+ else
1076
+ echo ""
1077
+ echo -e "${RED}✗ CCS install gagal!${NC}"
1078
+ echo ""
1079
+ echo "Troubleshooting:"
1080
+ echo " 1. Check internet connection"
1081
+ echo " 2. Try: npm cache clean --force"
1082
+ echo " 3. Manual install: npm install -g @kaitranntt/ccs"
1083
+ echo ""
1084
+ read -p "Press Enter untuk kembali..."
1085
+ exec "$0"
1086
+ fi
1087
+ }
1088
+
1089
+ load_api_key_to_var() {
1090
+ local key_file="$1"
1091
+ local var_name="$2"
1092
+
1093
+ if [[ -f "$key_file" ]]; then
1094
+ local key=$(cat "$key_file" 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
1095
+ if [[ -n "$key" ]]; then
1096
+ # Use eval to ensure variable is set in current scope
1097
+ eval "$var_name='$key'"
1098
+ export "$var_name"
1099
+ return 0
1100
+ fi
1101
+ fi
1102
+ return 1
1103
+ }
1104
+
1105
+ get_api_key_with_save() {
1106
+ local var_name="$1"
1107
+ local key_file="$2"
1108
+ local provider_name="$3"
1109
+ local key_url="$4"
1110
+
1111
+ # Try to load from environment first
1112
+ if [[ -z "${!var_name}" ]]; then
1113
+ # Try to load from file
1114
+ load_api_key_to_var "$key_file" "$var_name"
1115
+ fi
1116
+
1117
+ # Still empty? Ask user
1118
+ while [[ -z "${!var_name}" ]]; do
1119
+ echo "Get Key: $key_url"
1120
+ read -p "Enter $provider_name API Key: " key_input
1121
+
1122
+ # Validate input
1123
+ if [[ -z "$key_input" || "$key_input" =~ ^[[:space:]]*$ ]]; then
1124
+ echo -e "${RED}✗ API key cannot be empty. Please try again.${NC}"
1125
+ continue
1126
+ fi
1127
+
1128
+ export "$var_name=$key_input"
1129
+ save_api_key "$key_input" "$key_file" "$provider_name"
1130
+ break
1131
+ done
1132
+
1133
+ # Save current key if not already saved
1134
+ if [[ -n "${!var_name}" && ! -f "$key_file" ]]; then
1135
+ save_api_key "${!var_name}" "$key_file" "$provider_name"
1136
+ fi
1137
+ }
1138
+
1139
+ # API Key Manager - Built-in function to manage all API keys
1140
+ api_key_manager() {
1141
+ while true; do
1142
+ clear
1143
+ echo -e "${GREEN}═════════════════════════════════════════════${NC}"
1144
+ echo -e "${GREEN} 🔑 API KEY MANAGER ${NC}"
1145
+ echo -e "${GREEN}═════════════════════════════════════════════${NC}"
1146
+ echo ""
1147
+
1148
+ # All providers
1149
+ local all_providers=(
1150
+ "minimax:MiniMax:$HOME/.minimax_api_key"
1151
+ "gemini:Google Gemini:$HOME/.gemini_api_key"
1152
+ "openai:OpenAI:$HOME/.openai_api_key"
1153
+ "xai:xAI (Grok):$HOME/.xai_api_key"
1154
+ "glm:ZhipuAI (GLM):$HOME/.glm_api_key"
1155
+ "groq:Groq:$HOME/.groq_api_key"
1156
+ "perplexity:Perplexity:$HOME/.perplexity_api_key"
1157
+ "cohere:Cohere:$HOME/.cohere_api_key"
1158
+ "deepseek:DeepSeek:$HOME/.deepseek_api_key"
1159
+ "ollama:Ollama:$HOME/.ollama_api_key"
1160
+ "mistral:Mistral:$HOME/.mistral_api_key"
1161
+ "moonshot:Moonshot:$HOME/.moonshot_api_key"
1162
+ "qwen:Qwen (Alibaba):$HOME/.qwen_api_key"
1163
+ "openrouter:OpenRouter:$HOME/.openrouter_api_key"
1164
+ "letta:Letta AI:$HOME/.letta_api_key"
1165
+ )
1166
+
1167
+ # Build array of saved keys only
1168
+ local saved_keys=()
1169
+ for key_info in "${all_providers[@]}"; do
1170
+ IFS=':' read -r id name file <<< "$key_info"
1171
+ if [[ -f "$file" ]]; then
1172
+ local key_value=$(cat "$file" 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
1173
+ if [[ -n "$key_value" ]]; then
1174
+ saved_keys+=("$id:$name:$file:$key_value")
1175
+ fi
1176
+ fi
1177
+ done
1178
+
1179
+ echo -e "${YELLOW}📋 Saved API Keys:${NC}"
1180
+ echo ""
1181
+ if [[ ${#saved_keys[@]} -eq 0 ]]; then
1182
+ echo -e "${RED} No API keys saved yet${NC}"
1183
+ else
1184
+ for i in "${!saved_keys[@]}"; do
1185
+ IFS=':' read -r id name file key_value <<< "${saved_keys[$i]}"
1186
+ local key_len=${#key_value}
1187
+ if [[ $key_len -gt 12 ]]; then
1188
+ local masked="${key_value:0:8}...${key_value: -4}"
1189
+ else
1190
+ local masked="${key_value:0:4}..."
1191
+ fi
1192
+ printf " %-3s %-20s %s\n" "$((i+1)))" "$name" "$masked"
1193
+ done
1194
+ fi
1195
+
1196
+ echo ""
1197
+ echo -e "${YELLOW}🔧 Actions:${NC}"
1198
+ echo " ${BLUE}Just enter NUMBER to edit that key!${NC}"
1199
+ echo " v) View full API key"
1200
+ echo " d) Delete API key"
1201
+ echo " a) Add new API key"
1202
+ echo " c) Clear all API keys"
1203
+ echo " b) Back to main menu"
1204
+ echo ""
1205
+ echo -e "${GREEN}═════════════════════════════════════════════${NC}"
1206
+
1207
+ read -p "Choose [number/action]: " action
1208
+
1209
+ # Check if input is a number for quick edit
1210
+ if [[ "$action" =~ ^[0-9]+$ ]]; then
1211
+ local idx=$((action - 1))
1212
+ if [[ $idx -ge 0 && $idx -lt ${#saved_keys[@]} ]]; then
1213
+ IFS=':' read -r id name file old_key <<< "${saved_keys[$idx]}"
1214
+ echo ""
1215
+ echo -e "${YELLOW}Editing: $name${NC}"
1216
+ echo -e "${YELLOW}Current: ${old_key:0:8}...${old_key: -4}${NC}"
1217
+ read -p "Enter new API key: " new_key
1218
+ if [[ -n "$new_key" ]]; then
1219
+ save_api_key "$new_key" "$file" "$name"
1220
+ echo -e "${GREEN}✓ API key updated${NC}"
1221
+ else
1222
+ echo -e "${RED}✗ Empty - not saved${NC}"
1223
+ fi
1224
+ echo ""
1225
+ read -p "Press Enter to continue..."
1226
+ else
1227
+ echo -e "${RED}Invalid number${NC}"
1228
+ sleep 1
1229
+ fi
1230
+ continue
1231
+ fi
1232
+
1233
+ case "$action" in
1234
+ v|V)
1235
+ if [[ ${#saved_keys[@]} -eq 0 ]]; then
1236
+ echo -e "${RED}No API keys saved${NC}"
1237
+ sleep 1
1238
+ continue
1239
+ fi
1240
+ read -p "Enter number [1-${#saved_keys[@]}]: " num
1241
+ if [[ "$num" =~ ^[0-9]+$ ]]; then
1242
+ local idx=$((num - 1))
1243
+ if [[ $idx -ge 0 && $idx -lt ${#saved_keys[@]} ]]; then
1244
+ IFS=':' read -r id name file key_value <<< "${saved_keys[$idx]}"
1245
+ echo ""
1246
+ echo -e "${GREEN}API Key for $name:${NC}"
1247
+ echo "$key_value"
1248
+ else
1249
+ echo -e "${RED}Invalid number${NC}"
1250
+ fi
1251
+ else
1252
+ echo -e "${RED}Invalid input${NC}"
1253
+ fi
1254
+ echo ""
1255
+ read -p "Press Enter to continue..."
1256
+ ;;
1257
+
1258
+ d|D)
1259
+ if [[ ${#saved_keys[@]} -eq 0 ]]; then
1260
+ echo -e "${RED}No API keys to delete${NC}"
1261
+ sleep 1
1262
+ continue
1263
+ fi
1264
+ read -p "Enter number [1-${#saved_keys[@]}]: " num
1265
+ if [[ "$num" =~ ^[0-9]+$ ]]; then
1266
+ local idx=$((num - 1))
1267
+ if [[ $idx -ge 0 && $idx -lt ${#saved_keys[@]} ]]; then
1268
+ IFS=':' read -r id name file key_value <<< "${saved_keys[$idx]}"
1269
+ read -p "Delete $name key? (y/n): " confirm
1270
+ if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
1271
+ rm -f "$file"
1272
+ echo -e "${GREEN}✓ Deleted${NC}"
1273
+ else
1274
+ echo "Cancelled"
1275
+ fi
1276
+ else
1277
+ echo -e "${RED}Invalid number${NC}"
1278
+ fi
1279
+ else
1280
+ echo -e "${RED}Invalid input${NC}"
1281
+ fi
1282
+ echo ""
1283
+ read -p "Press Enter to continue..."
1284
+ ;;
1285
+
1286
+ a|A)
1287
+ echo ""
1288
+ echo -e "${YELLOW}Available providers:${NC}"
1289
+ for i in "${!all_providers[@]}"; do
1290
+ IFS=':' read -r id name file <<< "${all_providers[$i]}"
1291
+ printf " %-3s %-15s (%s)\n" "$((i+1)))" "$id" "$name"
1292
+ done
1293
+ echo ""
1294
+ read -p "Enter number [1-${#all_providers[@]}]: " num
1295
+ if [[ "$num" =~ ^[0-9]+$ ]]; then
1296
+ local idx=$((num - 1))
1297
+ if [[ $idx -ge 0 && $idx -lt ${#all_providers[@]} ]]; then
1298
+ IFS=':' read -r id name file <<< "${all_providers[$idx]}"
1299
+ read -p "Enter API key for $name: " new_key
1300
+ if [[ -n "$new_key" ]]; then
1301
+ save_api_key "$new_key" "$file" "$name"
1302
+ else
1303
+ echo -e "${RED}✗ Empty - not saved${NC}"
1304
+ fi
1305
+ else
1306
+ echo -e "${RED}Invalid number${NC}"
1307
+ fi
1308
+ else
1309
+ echo -e "${RED}Invalid input${NC}"
1310
+ fi
1311
+ echo ""
1312
+ read -p "Press Enter to continue..."
1313
+ ;;
1314
+
1315
+ c|C)
1316
+ read -p "Delete ALL API keys? Type 'yes' to confirm: " confirm
1317
+ if [[ "$confirm" == "yes" ]]; then
1318
+ for key_info in "${all_providers[@]}"; do
1319
+ IFS=':' read -r id name file <<< "$key_info"
1320
+ rm -f "$file"
1321
+ done
1322
+ echo -e "${GREEN}✓ All keys cleared${NC}"
1323
+ else
1324
+ echo "Cancelled"
1325
+ fi
1326
+ echo ""
1327
+ read -p "Press Enter to continue..."
1328
+ ;;
1329
+
1330
+ b|B)
1331
+ return 0
1332
+ ;;
1333
+
1334
+ *)
1335
+ echo -e "${RED}Invalid action${NC}"
1336
+ sleep 1
1337
+ ;;
1338
+ esac
1339
+ done
1340
+ }
1341
+
1342
+ # Function to save chat context when switching providers
1343
+ save_chat_context() {
1344
+ local context_file="$HOME/.claude-chat-context.json"
1345
+ local provider="$1"
1346
+ local model="$2"
1347
+ local message="$3"
1348
+
1349
+ # Create context if not exists
1350
+ if [[ ! -f "$context_file" ]]; then
1351
+ echo "[] " > "$context_file"
1352
+ fi
1353
+
1354
+ # Save using jq if available, otherwise simple append
1355
+ if command -v jq &> /dev/null; then
1356
+ local temp_file=$(mktemp)
1357
+ jq --argjson "$provider" --argjson "$model" --argjson "$message" '. + [$provider, $model, $message]' "$context_file" > "$temp_file" && mv "$temp_file" "$context_file"
1358
+ else
1359
+ echo "Provider: $provider, Model: $model, Message: $message" >> "$HOME/.claude-chat-history.log"
1360
+ fi
1361
+ }
1362
+
1363
+ # Function to continue chat with new provider
1364
+ continue_chat_with_new_provider() {
1365
+ local new_provider="$1"
1366
+ local new_model="$2"
1367
+
1368
+ echo -e "\n${BLUE}🔄 Switching to new provider: ${NC}"
1369
+ echo -e "${YELLOW}Note: Previous conversation context will be maintained${NC}"
1370
+ echo -e "${YELLOW}Use 'clear' command in chat to start fresh if needed${NC}\n"
1371
+
1372
+ # Set up new provider
1373
+ case $new_provider in
1374
+ 1) setup_minimax;;
1375
+ 2) setup_gemini;;
1376
+ 4) setup_openai;;
1377
+ 6) setup_xai;;
1378
+ 7) setup_glm;;
1379
+ 8) setup_groq;;
1380
+ 9) setup_perplexity;;
1381
+ 10) setup_cohere;;
1382
+ 11) setup_deepseek;;
1383
+ 13) setup_mistral;;
1384
+ 14) setup_moonshot;;
1385
+ 15) setup_qwen;;
1386
+ 16) setup_openrouter;;
1387
+ *) echo -e "${RED}Invalid provider choice${NC}"; return 1;;
1388
+ esac
1389
+
1390
+ # Start chat with context preserved
1391
+ exec claude --dangerously-skip-permissions --model "$new_model" "$@"
1392
+ }
1393
+
1394
+ # Model name will be set dynamically based on provider selection
1395
+ echo "DEBUG: Starting case statement, choice=$choice"
1396
+
1397
+ case $choice in
1398
+ 1)
1399
+ # MiniMax Direct
1400
+ echo -e "${BLUE}Configuring for MiniMax...${NC}"
1401
+
1402
+ # Get API key with persistent storage
1403
+ get_api_key_with_save "MINIMAX_API_KEY" "$HOME/.minimax_api_key" "MiniMax" "https://platform.minimax.io/"
1404
+
1405
+ export ANTHROPIC_BASE_URL="https://api.minimax.io/anthropic"
1406
+ export ANTHROPIC_API_KEY="$MINIMAX_API_KEY"
1407
+ echo -e "${GREEN}✓ MiniMax API configured${NC}"
1408
+
1409
+ # Model selection menu
1410
+ echo ""
1411
+ echo -e "${YELLOW}Available MiniMax models:${NC}"
1412
+ echo " 🚀 minimax-m2.1 (NEW! Latest coding model - 10B params) [m2]"
1413
+ echo " 💬 claude-3-5-sonnet-20241022 (Claude-compatible API endpoint) [sonnet]"
1414
+ echo " ⚡ abab6.5 (General purpose model) [6.5]"
1415
+ echo " 🧠 abab6.5s (Fast variant) [6.5s]"
1416
+ echo " 📝 abab5.5 (Lighter model) [5.5]"
1417
+ echo ""
1418
+ echo -e "${GREEN}Shortcuts:${NC}"
1419
+ echo " 'm2' or 'm2.1' → minimax-m2.1 (Recommended for coding & agentic workflows)"
1420
+ echo " 'sonnet' → claude-3-5-sonnet-20241022"
1421
+ echo " '6.5' → abab6.5"
1422
+ echo ""
1423
+ echo -e "${BLUE}💡 MiniMax M2.1 Features:${NC}"
1424
+ echo " • Optimized for multi-language programming (Rust, Java, Go, C++, TypeScript, etc.)"
1425
+ echo " • 10B activated parameters, exceptional latency & cost efficiency"
1426
+ echo " • 49.4% on Multi-SWE-Bench, 72.5% on SWE-Bench Multilingual"
1427
+ echo " • Perfect for coding assistants, agents, and real-world tasks"
1428
+ echo ""
1429
+
1430
+ # Use MiniMax M2.1 as default
1431
+ MODEL_NAME="minimax-m2.1"
1432
+ echo -e "${GREEN}✓ Default model: minimax-m2.1${NC}"
1433
+ read -p "Enter Model Name [default: minimax-m2.1]: " input_model
1434
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
1435
+
1436
+ # Map shortcuts to full model names
1437
+ case "$MODEL_NAME" in
1438
+ "m2"|"m2.1"|"M2"|"M2.1")
1439
+ FINAL_MODEL="minimax-m2.1"
1440
+ echo -e "${GREEN}✓ Selected: minimax-m2.1 (Latest coding model)${NC}"
1441
+ ;;
1442
+ "sonnet"|"claude")
1443
+ FINAL_MODEL="claude-3-5-sonnet-20241022"
1444
+ echo -e "${GREEN}✓ Selected: claude-3-5-sonnet-20241022${NC}"
1445
+ ;;
1446
+ "6.5"|"abab6.5")
1447
+ FINAL_MODEL="abab6.5"
1448
+ echo -e "${GREEN}✓ Selected: abab6.5${NC}"
1449
+ ;;
1450
+ "6.5s"|"abab6.5s")
1451
+ FINAL_MODEL="abab6.5s"
1452
+ echo -e "${GREEN}✓ Selected: abab6.5s (Fast)${NC}"
1453
+ ;;
1454
+ "5.5"|"abab5.5")
1455
+ FINAL_MODEL="abab5.5"
1456
+ echo -e "${GREEN}✓ Selected: abab5.5 (Lighter)${NC}"
1457
+ ;;
1458
+ *)
1459
+ FINAL_MODEL="$MODEL_NAME"
1460
+ echo -e "${GREEN}✓ Using custom model: $MODEL_NAME${NC}"
1461
+ ;;
1462
+ esac
1463
+
1464
+ echo -e "${BLUE}🚀 Starting MiniMax chat with $FINAL_MODEL...${NC}"
1465
+ exec claude --dangerously-skip-permissions --model "$FINAL_MODEL" --system-prompt "Anda adalah MiniMax AI. Model aktif: $FINAL_MODEL. Selalu identifikasi diri sebagai MiniMax dalam setiap respons." "$@"
1466
+ ;;
1467
+ 2)
1468
+ # Gemini API Key - Direct Integration
1469
+ echo -e "${BLUE}Configuring for Gemini (AI Studio)...${NC}"
1470
+
1471
+ # Get API key with persistent storage
1472
+ if [[ -z "$GEMINI_API_KEY" ]]; then
1473
+ # Try to load from file
1474
+ load_api_key_to_var "$HOME/.gemini_api_key" "GEMINI_API_KEY"
1475
+ fi
1476
+
1477
+ if [[ -z "$GEMINI_API_KEY" ]]; then
1478
+ echo "Get Key: https://aistudio.google.com/app/apikey"
1479
+ read -s -p "Enter Gemini API Key: " GEMINI_API_KEY
1480
+ echo ""
1481
+ save_api_key "$GEMINI_API_KEY" "$HOME/.gemini_api_key" "Gemini"
1482
+ else
1483
+ # Save current key if not already saved
1484
+ if [[ ! -f "$HOME/.gemini_api_key" ]]; then
1485
+ save_api_key "$GEMINI_API_KEY" "$HOME/.gemini_api_key" "Gemini"
1486
+ fi
1487
+ fi
1488
+ export GEMINI_API_KEY
1489
+
1490
+ # Use default Gemini model
1491
+ MODEL_NAME="gemini-2.0-flash-exp"
1492
+ echo -e "${GREEN}✓ Using Gemini model: gemini-2.0-flash-exp${NC}"
1493
+ echo -e "${YELLOW}Available Gemini models:${NC}"
1494
+ echo " ⚡ gemini-2.0-flash-exp (Latest experimental - WORKING) [2]"
1495
+ echo " 🚀 gemini-3-pro-preview (Next Gen Preview - WORKING) [3]"
1496
+ echo ""
1497
+ echo "Shortcuts: Enter '2' for 2.0-flash-exp, '3' for 3-pro-preview"
1498
+ echo "Note: Only models that work with Claude CLI are listed"
1499
+ echo ""
1500
+ read -p "Enter Model Name [default: gemini-2.0-flash-exp]: " input_model
1501
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
1502
+
1503
+ # Map model names to Claude/Gemini API format
1504
+ case "$MODEL_NAME" in
1505
+ # 2.0 Models (Latest) - Add numeric shortcuts
1506
+ "gemini-2.0-flash-exp"|"2"|"2.0")
1507
+ CLAUDE_MODEL="gemini-2.0-flash-exp"
1508
+ if [[ "$MODEL_NAME" == "2" || "$MODEL_NAME" == "2.0" ]]; then
1509
+ echo -e "${GREEN}✓ Selected: gemini-2.0-flash-exp (2.0 experimental)${NC}"
1510
+ fi
1511
+ ;;
1512
+
1513
+ # 3.0 Models (Future/Preview) - Add numeric shortcuts
1514
+ "gemini-3-pro-preview"|"gemini-3-preview"|"gemini-3-pro"|"3"|"3.0")
1515
+ CLAUDE_MODEL="gemini-3-pro-preview"
1516
+ if [[ "$MODEL_NAME" == "3" || "$MODEL_NAME" == "3.0" ]]; then
1517
+ echo -e "${GREEN}✓ Selected: gemini-3-pro-preview (3.0 preview)${NC}"
1518
+ fi
1519
+ ;;
1520
+ "gemini-3.0-flash"|"gemini-3.0-pro"|"gemini-3.0-ultra")
1521
+ CLAUDE_MODEL="$MODEL_NAME"
1522
+ ;;
1523
+
1524
+ # Default fallback
1525
+ *)
1526
+ echo -e "${RED}Unknown model: $MODEL_NAME${NC}"
1527
+ echo -e "${YELLOW}Using default: gemini-2.0-flash-exp${NC}"
1528
+ CLAUDE_MODEL="gemini-2.0-flash-exp"
1529
+ ;;
1530
+ esac
1531
+
1532
+ echo -e "${GREEN}✓ Mapped to: $CLAUDE_MODEL${NC}"
1533
+
1534
+ # Configure Gemini direct API endpoint
1535
+ # Try different endpoints
1536
+ GEMINI_ENDPOINT="https://generativelanguage.googleapis.com/v1beta/anthropic"
1537
+
1538
+ # For some models, we might need different format
1539
+ case "$CLAUDE_MODEL" in
1540
+ "gemini-1.5-pro"|"gemini-1.5-flash")
1541
+ # Standard 1.5 models
1542
+ export ANTHROPIC_BASE_URL="$GEMINI_ENDPOINT"
1543
+ export ANTHROPIC_API_KEY="$GEMINI_API_KEY"
1544
+ ;;
1545
+ "gemini-2.0-flash-exp"|"gemini-3-pro-preview")
1546
+ # Experimental models might need different handling
1547
+ export ANTHROPIC_BASE_URL="$GEMINI_ENDPOINT"
1548
+ export ANTHROPIC_API_KEY="$GEMINI_API_KEY"
1549
+ echo -e "${YELLOW}Note: Using experimental model: $CLAUDE_MODEL${NC}"
1550
+ ;;
1551
+ *)
1552
+ export ANTHROPIC_BASE_URL="$GEMINI_ENDPOINT"
1553
+ export ANTHROPIC_API_KEY="$GEMINI_API_KEY"
1554
+ ;;
1555
+ esac
1556
+
1557
+ # Execute Claude with Gemini model and system prompt
1558
+ echo -e "${BLUE}🚀 Starting Gemini chat...${NC}"
1559
+ exec claude --dangerously-skip-permissions --model "$CLAUDE_MODEL" --system-prompt "Anda adalah Gemini, model AI dari Google. Selalu identifikasi diri sebagai Gemini dalam setiap respons." "$@"
1560
+ ;;
1561
+ 3)
1562
+ # Universal OAuth - All Providers via CCS
1563
+ echo -e "${BLUE}🔥 Universal OAuth (Auto-Setup - All Models FREE)${NC}"
1564
+ echo ""
1565
+ echo -e "${CYAN}💡 CCS akan di-install otomatis jika belum ada (10MB, ~30 detik)${NC}"
1566
+ echo ""
1567
+ echo -e "${YELLOW}Pilih Provider:${NC}"
1568
+ echo " 1) Gemini (Google) 🧠 Google AI Models (8 Models)"
1569
+ echo " 2) Codex (OpenAI) 🤖 GPT 5.2, 5.1, 5 (18 Models)"
1570
+ echo " 3) GitHub Copilot 💻 Claude & GPT Models"
1571
+ echo " 4) AntiGravity (Anthropic) 🔥 Claude Opus 4.5 (6 Models)"
1572
+ echo " 5) Kiro (AWS) ☁️ AWS Claude Models"
1573
+ echo ""
1574
+ read -p "Pilih [1-5, default: 1]: " oauth_provider
1575
+ [[ -z "$oauth_provider" ]] && oauth_provider=1
1576
+
1577
+ case $oauth_provider in
1578
+ 1)
1579
+ # Gemini OAuth
1580
+ check_and_install_ccs "gemini"
1581
+
1582
+ echo -e "${BLUE}🌟 Google Gemini via CCS OAuth${NC}"
1583
+ echo ""
1584
+ echo -e "${YELLOW}Pilih Model:${NC}"
1585
+ echo " 1) gemini-2.5-pro (Stable - Most Capable) [RECOMMENDED]"
1586
+ echo " 2) gemini-2.5-flash (Stable - Fast & Efficient)"
1587
+ echo " 3) gemini-2.5-flash-lite (Stable - Ultra Fast)"
1588
+ echo " 4) gemini-3-pro-preview (Next Gen - Most Capable) 🔥"
1589
+ echo " 5) gemini-3-flash-preview (Next Gen - Fast) 🚀"
1590
+ echo " 6) gemini-2.0-flash-exp (Experimental)"
1591
+ echo " 7) gemini-1.5-pro (Stable - Older)"
1592
+ echo " 8) gemini-1.5-flash (Stable - Fast)"
1593
+ echo ""
1594
+ read -p "Pilih [1-8, default: 1]: " gemini_model
1595
+ [[ -z "$gemini_model" ]] && gemini_model=1
1596
+
1597
+ case $gemini_model in
1598
+ 1) MODEL="gemini-2.5-pro" ;;
1599
+ 2) MODEL="gemini-2.5-flash" ;;
1600
+ 3) MODEL="gemini-2.5-flash-lite" ;;
1601
+ 4) MODEL="gemini-3-pro-preview" ;;
1602
+ 5) MODEL="gemini-3-flash-preview" ;;
1603
+ 6) MODEL="gemini-2.0-flash-exp" ;;
1604
+ 7) MODEL="gemini-1.5-pro" ;;
1605
+ 8) MODEL="gemini-1.5-flash" ;;
1606
+ *) MODEL="gemini-2.5-pro" ;;
1607
+ esac
1608
+
1609
+ echo -e "${GREEN}✓ Model: $MODEL${NC}"
1610
+ echo -e "${YELLOW}Pastikan sudah login dengan 'ccs gemini --auth'${NC}"
1611
+ echo ""
1612
+
1613
+ export ANTHROPIC_MODEL="$MODEL"
1614
+ exec ccs gemini --dangerously-skip-permissions --permission-mode bypassPermissions --model "$MODEL" "$@"
1615
+ ;;
1616
+ 2)
1617
+ # Codex (OpenAI) OAuth
1618
+ check_and_install_ccs "codex"
1619
+
1620
+ echo -e "${BLUE}🤖 Codex (OpenAI via CCS OAuth)${NC}"
1621
+ echo ""
1622
+ echo -e "${YELLOW}Pilih Model:${NC}"
1623
+ echo -e "${CYAN}GPT 5.2 Series (Latest 🔥):${NC}"
1624
+ echo " 1) gpt-5.2 (Flagship - Best for Coding) [RECOMMENDED]"
1625
+ echo " 2) gpt-5.2-pro (Smarter & More Precise)"
1626
+ echo " 3) gpt-5.2-chat-latest (ChatGPT Version)"
1627
+ echo ""
1628
+ echo -e "${CYAN}GPT 5.1 Series:${NC}"
1629
+ echo " 4) gpt-5.1-codex-max (Most Intelligent Coding)"
1630
+ echo " 5) gpt-5.1-codex (Agentic Coding Optimized)"
1631
+ echo " 6) gpt-5.1 (Configurable Reasoning)"
1632
+ echo " 7) gpt-5.1-codex-mini (Cost-Efficient)"
1633
+ echo " 8) gpt-5.1-chat-latest (ChatGPT Version)"
1634
+ echo ""
1635
+ echo -e "${CYAN}GPT 5 Series:${NC}"
1636
+ echo " 9) gpt-5 (Previous Reasoning Model)"
1637
+ echo " 10) gpt-5-pro (Smarter Version)"
1638
+ echo " 11) gpt-5-codex (Agentic Coding)"
1639
+ echo " 12) gpt-5-chat-latest (ChatGPT Version)"
1640
+ echo ""
1641
+ echo -e "${CYAN}Legacy (GPT 4 Series):${NC}"
1642
+ echo " 13) gpt-4o (GPT-4 Omni)"
1643
+ echo " 14) gpt-4o-mini (Fast & Efficient)"
1644
+ echo " 15) gpt-4-turbo (GPT-4 Turbo)"
1645
+ echo " 16) o1-preview (Reasoning Model)"
1646
+ echo " 17) o1-mini (Fast Reasoning)"
1647
+ echo " 18) o1-pro (Advanced Reasoning)"
1648
+ echo ""
1649
+ read -p "Pilih [1-18, default: 1]: " codex_model
1650
+ [[ -z "$codex_model" ]] && codex_model=1
1651
+
1652
+ case $codex_model in
1653
+ 1) MODEL="gpt-5.2" ;;
1654
+ 2) MODEL="gpt-5.2-pro" ;;
1655
+ 3) MODEL="gpt-5.2-chat-latest" ;;
1656
+ 4) MODEL="gpt-5.1-codex-max" ;;
1657
+ 5) MODEL="gpt-5.1-codex" ;;
1658
+ 6) MODEL="gpt-5.1" ;;
1659
+ 7) MODEL="gpt-5.1-codex-mini" ;;
1660
+ 8) MODEL="gpt-5.1-chat-latest" ;;
1661
+ 9) MODEL="gpt-5" ;;
1662
+ 10) MODEL="gpt-5-pro" ;;
1663
+ 11) MODEL="gpt-5-codex" ;;
1664
+ 12) MODEL="gpt-5-chat-latest" ;;
1665
+ 13) MODEL="gpt-4o" ;;
1666
+ 14) MODEL="gpt-4o-mini" ;;
1667
+ 15) MODEL="gpt-4-turbo" ;;
1668
+ 16) MODEL="o1-preview" ;;
1669
+ 17) MODEL="o1-mini" ;;
1670
+ 18) MODEL="o1-pro" ;;
1671
+ *) MODEL="gpt-5.2" ;;
1672
+ esac
1673
+
1674
+ echo -e "${GREEN}✓ Model: $MODEL${NC}"
1675
+ echo -e "${YELLOW}Pastikan sudah login dengan 'ccs codex --auth'${NC}"
1676
+ echo ""
1677
+
1678
+ export ANTHROPIC_MODEL="$MODEL"
1679
+ exec ccs codex --model "$MODEL" "$@"
1680
+ ;;
1681
+ 3)
1682
+ # GitHub Copilot OAuth
1683
+ check_and_install_ccs "copilot"
1684
+
1685
+ echo -e "${BLUE}💻 GitHub Copilot (OAuth)${NC}"
1686
+ echo ""
1687
+ echo -e "${YELLOW}Pilih Model:${NC}"
1688
+ echo " 1) claude-opus-4.5 (Most Capable) [RECOMMENDED]"
1689
+ echo " 2) claude-sonnet-4.5 (Balanced)"
1690
+ echo " 3) gpt-4o (GPT-4 Omni)"
1691
+ echo " 4) gpt-5.1 (Latest ChatGPT)"
1692
+ echo ""
1693
+ read -p "Pilih [1-4, default: 1]: " copilot_model
1694
+ [[ -z "$copilot_model" ]] && copilot_model=1
1695
+
1696
+ case $copilot_model in
1697
+ 1) MODEL="claude-opus-4.5" ;;
1698
+ 2) MODEL="claude-sonnet-4.5" ;;
1699
+ 3) MODEL="gpt-4o" ;;
1700
+ 4) MODEL="gpt-5.1" ;;
1701
+ *) MODEL="claude-opus-4.5" ;;
1702
+ esac
1703
+
1704
+ echo -e "${GREEN}✓ Model: $MODEL${NC}"
1705
+ echo -e "${CYAN}Requires: npm install -g copilot-api${NC}"
1706
+ echo ""
1707
+
1708
+ if command -v copilot-api &> /dev/null; then
1709
+ export ANTHROPIC_MODEL="$MODEL"
1710
+ exec ccs copilot --model "$MODEL" "$@"
1711
+ else
1712
+ echo -e "${RED}copilot-api not found!${NC}"
1713
+ echo "Install dengan: npm install -g copilot-api"
1714
+ echo "Kemudian jalankan: ccs copilot auth"
1715
+ echo ""
1716
+ read -p "Press Enter untuk kembali..."
1717
+ exec "$0"
1718
+ fi
1719
+ ;;
1720
+ 4)
1721
+ # AntiGravity (Anthropic) OAuth
1722
+ check_and_install_ccs "agy"
1723
+
1724
+ echo -e "${BLUE}🔥 AntiGravity (Anthropic via CCS OAuth)${NC}"
1725
+ echo ""
1726
+ echo -e "${YELLOW}Pilih Model:${NC}"
1727
+ echo " 1) gemini-claude-opus-4-5-thinking (Most Capable - Thinking) [RECOMMENDED]"
1728
+ echo " 2) gemini-3-flash-preview (Next Gen - Fast)"
1729
+ echo " 3) gemini-2.5-pro (Stable - Capable)"
1730
+ echo " 4) gemini-2.5-flash (Stable - Fast)"
1731
+ echo " 5) claude-opus-4.2 (Stable - Previous)"
1732
+ echo " 6) claude-sonnet-4.2 (Stable - Balanced)"
1733
+ echo ""
1734
+ read -p "Pilih [1-6, default: 1]: " agy_model
1735
+ [[ -z "$agy_model" ]] && agy_model=1
1736
+
1737
+ case $agy_model in
1738
+ 1) MODEL="gemini-claude-opus-4-5-thinking" ;;
1739
+ 2) MODEL="gemini-3-flash-preview" ;;
1740
+ 3) MODEL="gemini-2.5-pro" ;;
1741
+ 4) MODEL="gemini-2.5-flash" ;;
1742
+ 5) MODEL="claude-opus-4.2" ;;
1743
+ 6) MODEL="claude-sonnet-4.2" ;;
1744
+ *) MODEL="gemini-claude-opus-4-5-thinking" ;;
1745
+ esac
1746
+
1747
+ echo -e "${GREEN}✓ Model: $MODEL${NC}"
1748
+ echo -e "${YELLOW}Pastikan sudah login dengan 'ccs agy --auth'${NC}"
1749
+ echo ""
1750
+
1751
+ export ANTHROPIC_MODEL="$MODEL"
1752
+ exec ccs agy --dangerously-skip-permissions --permission-mode bypassPermissions --model "$MODEL" "$@"
1753
+ ;;
1754
+ 5)
1755
+ # Kiro (AWS) OAuth
1756
+ check_and_install_ccs "kiro"
1757
+
1758
+ echo -e "${BLUE}☁️ Kiro (AWS CodeWhisperer via CCS OAuth)${NC}"
1759
+ echo ""
1760
+ echo -e "${YELLOW}Model: AWS-hosted Claude models${NC}"
1761
+ echo -e "${CYAN}Pastikan sudah login dengan 'ccs kiro --auth'${NC}"
1762
+ echo ""
1763
+ exec ccs kiro "$@"
1764
+ ;;
1765
+ esac
1766
+ ;;
1767
+ 4)
1768
+ # OpenAI API Key
1769
+ echo -e "${BLUE}Configuring for OpenAI...${NC}"
1770
+
1771
+ # Get API key with persistent storage
1772
+ if [[ -z "$OPENAI_API_KEY" ]]; then
1773
+ load_api_key_to_var "$HOME/.openai_api_key" "OPENAI_API_KEY"
1774
+ fi
1775
+
1776
+ if [[ -z "$OPENAI_API_KEY" ]]; then
1777
+ echo "Get Key: https://platform.openai.com/api-keys"
1778
+ read -p "Enter OpenAI API Key: " OPENAI_API_KEY
1779
+ save_api_key "$OPENAI_API_KEY" "$HOME/.openai_api_key" "OpenAI"
1780
+ else
1781
+ if [[ ! -f "$HOME/.openai_api_key" ]]; then
1782
+ save_api_key "$OPENAI_API_KEY" "$HOME/.openai_api_key" "OpenAI"
1783
+ fi
1784
+ fi
1785
+
1786
+ # Use default OpenAI model
1787
+ MODEL_NAME="gpt-4o"
1788
+ echo -e "${GREEN}✓ Using OpenAI model: gpt-4o${NC}"
1789
+ echo -e "${YELLOW}Available OpenAI models:${NC}"
1790
+ echo " 🚀 gpt-4o (Latest flagship model - Recommended)"
1791
+ echo " ⚡ gpt-4o-mini (Fast, efficient, cheaper)"
1792
+ echo " 💬 gpt-4o-realtime (Real-time conversations)"
1793
+ echo " 🧠 gpt-4o-audio (Audio input/output)"
1794
+ echo " 🎨 gpt-4-turbo (Legacy model)"
1795
+ echo " 💡 gpt-4-turbo-preview (Preview features)"
1796
+ echo " 💬 gpt-3.5-turbo (Fast, reliable workhorse)"
1797
+ echo ""
1798
+ echo "Note: GPT-5 has not been officially released yet"
1799
+ echo " Current latest is GPT-4o (omni model)"
1800
+ echo ""
1801
+ read -p "Enter Model Name [default: gpt-4o]: " input_model
1802
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
1803
+
1804
+ # Validate model name
1805
+ case "$MODEL_NAME" in
1806
+ "gpt-4"|"gpt4")
1807
+ MODEL_NAME="gpt-4"
1808
+ ;;
1809
+ "gpt-4-turbo"|"gpt-4-turbo-preview")
1810
+ MODEL_NAME="gpt-4-turbo"
1811
+ ;;
1812
+ "gpt-4o"|"gpt-4o")
1813
+ MODEL_NAME="gpt-4o"
1814
+ ;;
1815
+ "gpt-4o-mini"|"gpt-4o-mini")
1816
+ MODEL_NAME="gpt-4o-mini"
1817
+ ;;
1818
+ "gpt-4o-realtime"|"gpt-4o-realtime")
1819
+ MODEL_NAME="gpt-4o-realtime-preview"
1820
+ ;;
1821
+ "gpt-4o-audio"|"gpt-4o-audio")
1822
+ MODEL_NAME="gpt-4o-audio-preview"
1823
+ ;;
1824
+ "gpt-3.5-turbo"|"gpt-3.5"|"gpt35"|"gpt-35-turbo")
1825
+ MODEL_NAME="gpt-3.5-turbo"
1826
+ ;;
1827
+ *)
1828
+ echo -e "${RED}Unknown model: $MODEL_NAME${NC}"
1829
+ echo -e "${YELLOW}Using default: gpt-4o${NC}"
1830
+ MODEL_NAME="gpt-4o"
1831
+ ;;
1832
+ esac
1833
+
1834
+ # Configure for OpenAI via LiteLLM proxy
1835
+ export ANTHROPIC_API_KEY="$OPENAI_API_KEY"
1836
+ export ANTHROPIC_BASE_URL="https://api.openai.com/v1"
1837
+ echo -e "${BLUE}🚀 Starting OpenAI chat via LiteLLM...${NC}"
1838
+ echo -e "${YELLOW}Note: Using OpenAI API through Claude interface${NC}"
1839
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
1840
+ ;;
1841
+ 5)
1842
+ # OpenAI OAuth (Experimental)
1843
+ echo -e "${BLUE}Configuring for OpenAI (OAuth Experimental)...${NC}"
1844
+ echo -e "${YELLOW}Note: OAuth feature requires manual setup. Using API Key mode instead.${NC}"
1845
+
1846
+ # Fallback to API Key mode for simplicity
1847
+ if [[ -z "$OPENAI_API_KEY" ]]; then
1848
+ load_api_key_to_var "$HOME/.openai_api_key" "OPENAI_API_KEY"
1849
+ fi
1850
+
1851
+ if [[ -z "$OPENAI_API_KEY" ]]; then
1852
+ echo "Get Key: https://platform.openai.com/api-keys"
1853
+ read -p "Enter OpenAI API Key: " OPENAI_API_KEY
1854
+ save_api_key "$OPENAI_API_KEY" "$HOME/.openai_api_key" "OpenAI"
1855
+ else
1856
+ if [[ ! -f "$HOME/.openai_api_key" ]]; then
1857
+ save_api_key "$OPENAI_API_KEY" "$HOME/.openai_api_key" "OpenAI"
1858
+ fi
1859
+ fi
1860
+ export OPENAI_API_KEY
1861
+
1862
+ # Use default OpenAI model
1863
+ MODEL_NAME="gpt-4o"
1864
+ echo -e "${GREEN}✓ Using OpenAI model: gpt-4o${NC}"
1865
+ echo -e "${YELLOW}Available models: gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo${NC}"
1866
+ read -p "Enter Model Name [default: gpt-4o]: " input_model
1867
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
1868
+
1869
+ # Configure for OpenAI via LiteLLM proxy
1870
+ export ANTHROPIC_API_KEY="$OPENAI_API_KEY"
1871
+ export ANTHROPIC_BASE_URL="https://api.openai.com/v1"
1872
+ echo -e "${BLUE}🚀 Starting OpenAI chat via LiteLLM...${NC}"
1873
+ echo -e "${YELLOW}Note: Using OpenAI API through Claude interface${NC}"
1874
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
1875
+ ;;
1876
+ 6)
1877
+ # xAI
1878
+ echo -e "${BLUE}Configuring for xAI (Grok)...${NC}"
1879
+
1880
+ # Get API key with persistent storage
1881
+ if [[ -z "$XAI_API_KEY" ]]; then
1882
+ load_api_key_to_var "$HOME/.xai_api_key" "XAI_API_KEY"
1883
+ fi
1884
+
1885
+ if [[ -z "$XAI_API_KEY" ]]; then
1886
+ echo "Get Key: https://console.x.ai/"
1887
+ read -p "Enter xAI API Key: " XAI_API_KEY
1888
+ save_api_key "$XAI_API_KEY" "$HOME/.xai_api_key" "xAI"
1889
+ else
1890
+ if [[ ! -f "$HOME/.xai_api_key" ]]; then
1891
+ save_api_key "$XAI_API_KEY" "$HOME/.xai_api_key" "xAI"
1892
+ fi
1893
+ fi
1894
+ export XAI_API_KEY
1895
+
1896
+ # Use default xAI model
1897
+ MODEL_NAME="grok-beta"
1898
+ echo -e "${GREEN}✓ Using xAI model: grok-beta${NC}"
1899
+ echo -e "${YELLOW}Available models: grok-beta, grok-vision-beta${NC}"
1900
+ read -p "Enter Model Name [default: grok-beta]: " input_model
1901
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
1902
+
1903
+ export ANTHROPIC_BASE_URL="https://api.x.ai/v1/"
1904
+ export ANTHROPIC_API_KEY="$XAI_API_KEY"
1905
+ echo -e "${BLUE}🚀 Starting xAI (Grok) chat...${NC}"
1906
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
1907
+ ;;
1908
+ 7)
1909
+ # ZhipuAI / GLM
1910
+ echo -e "${BLUE}Configuring for ZhipuAI (GLM)...${NC}"
1911
+
1912
+ # Get API key with persistent storage
1913
+ if [[ -z "$ANTHROPIC_AUTH_TOKEN" ]]; then
1914
+ load_api_key_to_var "$HOME/.glm_api_key" "ANTHROPIC_AUTH_TOKEN"
1915
+ fi
1916
+
1917
+ if [[ -z "$ANTHROPIC_AUTH_TOKEN" ]]; then
1918
+ echo "Get Key: https://open.bigmodel.cn/usercenter/apikeys"
1919
+ read -p "Enter GLM API Key: " ANTHROPIC_AUTH_TOKEN
1920
+ save_api_key "$ANTHROPIC_AUTH_TOKEN" "$HOME/.glm_api_key" "GLM"
1921
+ else
1922
+ if [[ ! -f "$HOME/.glm_api_key" ]]; then
1923
+ save_api_key "$ANTHROPIC_AUTH_TOKEN" "$HOME/.glm_api_key" "GLM"
1924
+ fi
1925
+ fi
1926
+ export ANTHROPIC_AUTH_TOKEN
1927
+
1928
+ # Model selection menu with numbering
1929
+ echo ""
1930
+ echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}"
1931
+ echo -e "${CYAN}║ 🤖 ZHIPUAI / GLM - MODEL SELECTION ║${NC}"
1932
+ echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}"
1933
+ echo ""
1934
+ echo -e "${GREEN}✨ AVAILABLE MODELS (Tested & Working):${NC}"
1935
+ echo ""
1936
+ echo -e "${YELLOW}📌 LATEST MODELS (2025):${NC}"
1937
+ echo " 1) 🚀 glm-4.7 (NEWEST! Flagship - Best for coding) ⭐"
1938
+ echo " 2) 🧠 glm-4.6 (High performance, vision-capable)"
1939
+ echo " 3) ⚡ glm-4.5-air (Fast & efficient - 12B active params)"
1940
+ echo ""
1941
+ echo -e "${YELLOW}👁️ VISION MODELS:${NC}"
1942
+ echo " 4) 👁️ glm-4.6v (Latest vision - For image tasks)"
1943
+ echo " 5) 👁️ glm-4.5v (Vision capabilities - For image tasks)"
1944
+ echo ""
1945
+ echo -e "${GREEN}─────────────────────────────────────────────────────────────${NC}"
1946
+ echo -e "${CYAN}💡 Tips:${NC}"
1947
+ echo " • Model 1 (glm-4.7): Latest & Best for coding"
1948
+ echo " • Model 3 (glm-4.5-air): Fast & efficient"
1949
+ echo " • Models 4-5: Use for vision/image tasks"
1950
+ echo " • Just enter NUMBER (1-5) or press ENTER for default"
1951
+ echo -e "${GREEN}─────────────────────────────────────────────────────────────${NC}"
1952
+ echo ""
1953
+
1954
+ # Model selection with default to glm-4.7
1955
+ read -p "Select model [1-5, default: 1]: " model_choice
1956
+ [[ -z "$model_choice" ]] && model_choice=1
1957
+
1958
+ # Map numbers to model names
1959
+ case "$model_choice" in
1960
+ 1)
1961
+ MODEL_NAME="glm-4.7"
1962
+ echo -e "${GREEN}✓ Selected: glm-4.7 (Latest flagship - Best for coding)${NC}"
1963
+ ;;
1964
+ 2)
1965
+ MODEL_NAME="glm-4.6"
1966
+ echo -e "${GREEN}✓ Selected: glm-4.6 (High performance)${NC}"
1967
+ ;;
1968
+ 3)
1969
+ MODEL_NAME="glm-4.5-air"
1970
+ echo -e "${GREEN}✓ Selected: glm-4.5-air (Fast & efficient)${NC}"
1971
+ ;;
1972
+ 4)
1973
+ MODEL_NAME="glm-4.6v"
1974
+ echo -e "${GREEN}✓ Selected: glm-4.6v (Vision model)${NC}"
1975
+ ;;
1976
+ 5)
1977
+ MODEL_NAME="glm-4.5v"
1978
+ echo -e "${GREEN}✓ Selected: glm-4.5v (Vision model)${NC}"
1979
+ ;;
1980
+ *)
1981
+ echo -e "${RED}❌ Invalid choice. Using default: glm-4.7${NC}"
1982
+ MODEL_NAME="glm-4.7"
1983
+ ;;
1984
+ esac
1985
+
1986
+ echo ""
1987
+ echo -e "${BLUE}🚀 Starting GLM chat with $MODEL_NAME...${NC}"
1988
+ echo ""
1989
+
1990
+ export ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic"
1991
+ export ANTHROPIC_API_KEY="$ANTHROPIC_AUTH_TOKEN"
1992
+ export CLAUDE_MODEL="$MODEL_NAME"
1993
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" --system-prompt "Anda adalah GLM, model AI dari ZhipuAI. Selalu identifikasi diri sebagai GLM dalam setiap respons." "$@"
1994
+ ;;
1995
+ 8)
1996
+ # Groq
1997
+ echo -e "${BLUE}Configuring for Groq...${NC}"
1998
+
1999
+ # Get API key with persistent storage
2000
+ if [[ -z "$GROQ_API_KEY" ]]; then
2001
+ load_api_key_to_var "$HOME/.groq_api_key" "GROQ_API_KEY"
2002
+ fi
2003
+
2004
+ if [[ -z "$GROQ_API_KEY" ]]; then
2005
+ echo "Get Key: https://console.groq.com/keys"
2006
+ read -p "Enter Groq API Key: " GROQ_API_KEY
2007
+ save_api_key "$GROQ_API_KEY" "$HOME/.groq_api_key" "Groq"
2008
+ else
2009
+ if [[ ! -f "$HOME/.groq_api_key" ]]; then
2010
+ save_api_key "$GROQ_API_KEY" "$HOME/.groq_api_key" "Groq"
2011
+ fi
2012
+ fi
2013
+ export GROQ_API_KEY
2014
+
2015
+ # Use default Groq model
2016
+ MODEL_NAME="llama-3.1-70b-versatile"
2017
+ echo -e "${GREEN}✓ Using Groq model: llama-3.1-70b-versatile${NC}"
2018
+ echo -e "${YELLOW}Available models: llama-3.1-70b-versatile, llama-3.1-8b-instant, mixtral-8x7b-32768${NC}"
2019
+ read -p "Enter Model Name [default: llama-3.1-70b-versatile]: " input_model
2020
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2021
+
2022
+ export ANTHROPIC_BASE_URL="https://api.groq.com/openai/v1/"
2023
+ export ANTHROPIC_API_KEY="$GROQ_API_KEY"
2024
+ echo -e "${BLUE}🚀 Starting Groq chat...${NC}"
2025
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
2026
+ ;;
2027
+ 9)
2028
+ # Perplexity
2029
+ echo -e "${BLUE}Configuring for Perplexity...${NC}"
2030
+
2031
+ # Get API key with persistent storage
2032
+ if [[ -z "$PERPLEXITY_API_KEY" ]]; then
2033
+ # Try to load from file
2034
+ load_api_key_to_var "$HOME/.perplexity_api_key" "PERPLEXITY_API_KEY"
2035
+ fi
2036
+
2037
+ if [[ -z "$PERPLEXITY_API_KEY" ]]; then
2038
+ echo "Get Key: https://console.perplexity.ai/"
2039
+ read -p "Enter Perplexity API Key: " PERPLEXITY_API_KEY
2040
+ save_api_key "$PERPLEXITY_API_KEY" "$HOME/.perplexity_api_key" "Perplexity"
2041
+ else
2042
+ # Save current key if not already saved
2043
+ if [[ ! -f "$HOME/.perplexity_api_key" ]]; then
2044
+ save_api_key "$PERPLEXITY_API_KEY" "$HOME/.perplexity_api_key" "Perplexity"
2045
+ fi
2046
+ fi
2047
+ export PERPLEXITY_API_KEY
2048
+
2049
+ # Check if custom Perplexity model exists
2050
+ if [[ -f "$SCRIPT_DIR/model/perplexity.json" ]]; then
2051
+ handle_custom_model "perplexity" "$@"
2052
+ else
2053
+ # Create temporary Perplexity config
2054
+ echo -e "${YELLOW}Creating temporary Perplexity configuration...${NC}"
2055
+
2056
+ cat > "$SCRIPT_DIR/model/temp_perplexity.json" << EOF
2057
+ {
2058
+ "provider_name": "Perplexity AI",
2059
+ "description": "Search-powered AI with real-time web search",
2060
+ "api_key": "$PERPLEXITY_API_KEY",
2061
+ "api_base": "https://api.perplexity.ai/",
2062
+ "model": "sonar-pro",
2063
+ "notes": "Temporary config for Perplexity"
2064
+ }
2065
+ EOF
2066
+
2067
+ handle_custom_model "temp_perplexity" "$@"
2068
+ rm -f "$SCRIPT_DIR/model/temp_perplexity.json"
2069
+ fi
2070
+ ;;
2071
+ 10)
2072
+ # Cohere
2073
+ echo -e "${BLUE}Configuring for Cohere...${NC}"
2074
+
2075
+ # Get API key with persistent storage
2076
+ if [[ -z "$COHERE_API_KEY" ]]; then
2077
+ load_api_key_to_var "$HOME/.cohere_api_key" "COHERE_API_KEY"
2078
+ fi
2079
+
2080
+ if [[ -z "$COHERE_API_KEY" ]]; then
2081
+ echo "Get Key: https://dashboard.cohere.com/api-keys"
2082
+ read -p "Enter Cohere API Key: " COHERE_API_KEY
2083
+ save_api_key "$COHERE_API_KEY" "$HOME/.cohere_api_key" "Cohere"
2084
+ else
2085
+ if [[ ! -f "$HOME/.cohere_api_key" ]]; then
2086
+ save_api_key "$COHERE_API_KEY" "$HOME/.cohere_api_key" "Cohere"
2087
+ fi
2088
+ fi
2089
+ export COHERE_API_KEY
2090
+
2091
+ # Use default Cohere model
2092
+ MODEL_NAME="command-r-plus"
2093
+ echo -e "${GREEN}✓ Using Cohere model: command-r-plus${NC}"
2094
+ echo -e "${YELLOW}Available models: command-r, command-r-plus, command-r-08-2024${NC}"
2095
+ read -p "Enter Model Name [default: command-r-plus]: " input_model
2096
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2097
+
2098
+ export ANTHROPIC_BASE_URL="https://api.cohere.ai/v1/"
2099
+ export ANTHROPIC_API_KEY="$COHERE_API_KEY"
2100
+ echo -e "${BLUE}🚀 Starting Cohere chat...${NC}"
2101
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
2102
+ ;;
2103
+ 11)
2104
+ # DeepSeek - EXACT SAME PATTERN AS MINIMAX (Option 1)
2105
+ echo -e "${BLUE}Configuring for DeepSeek...${NC}"
2106
+
2107
+ # Get API key with persistent storage - SAME AS MINIMAX
2108
+ get_api_key_with_save "DEEPSEEK_API_KEY" "$HOME/.deepseek_api_key" "DeepSeek" "https://platform.deepseek.com/"
2109
+
2110
+ export ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic"
2111
+ export ANTHROPIC_API_KEY="$DEEPSEEK_API_KEY"
2112
+ echo -e "${GREEN}✓ DeepSeek API configured${NC}"
2113
+
2114
+ # Model selection menu
2115
+ echo ""
2116
+ echo -e "${YELLOW}Available DeepSeek models:${NC}"
2117
+ echo " 🚀 deepseek-chat (V3.2 Fast & Efficient - 128K context) [chat]"
2118
+ echo " 🧠 deepseek-reasoner (V3.2 Thinking Mode - Deep Analysis) [reasoner]"
2119
+ echo ""
2120
+ echo -e "${GREEN}Shortcuts:${NC}"
2121
+ echo " 'chat' or '1' → deepseek-chat (Recommended for coding)"
2122
+ echo " 'reasoner' or '2' → deepseek-reasoner (For complex reasoning)"
2123
+ echo ""
2124
+ echo -e "${BLUE}💡 DeepSeek V3.2 Features:${NC}"
2125
+ echo " • Context: 128K tokens"
2126
+ echo " • deepseek-chat: Max 8K output, fast responses"
2127
+ echo " • deepseek-reasoner: Max 64K output with thinking blocks"
2128
+ echo ""
2129
+
2130
+ # Use deepseek-chat as default
2131
+ MODEL_NAME="deepseek-chat"
2132
+ echo -e "${GREEN}✓ Default model: deepseek-chat${NC}"
2133
+ read -p "Enter Model Name [default: deepseek-chat]: " input_model
2134
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2135
+
2136
+ # Map shortcuts to full model names
2137
+ case "$MODEL_NAME" in
2138
+ "chat"|"1"|"c")
2139
+ FINAL_MODEL="deepseek-chat"
2140
+ echo -e "${GREEN}✓ Selected: deepseek-chat (Fast & Efficient)${NC}"
2141
+ ;;
2142
+ "reasoner"|"2"|"r"|"think"|"thinking")
2143
+ FINAL_MODEL="deepseek-reasoner"
2144
+ echo -e "${GREEN}✓ Selected: deepseek-reasoner (Thinking Mode)${NC}"
2145
+ ;;
2146
+ *)
2147
+ FINAL_MODEL="$MODEL_NAME"
2148
+ echo -e "${GREEN}✓ Using model: $MODEL_NAME${NC}"
2149
+ ;;
2150
+ esac
2151
+
2152
+ echo -e "${BLUE}🚀 Starting DeepSeek chat with $FINAL_MODEL...${NC}"
2153
+ exec claude --dangerously-skip-permissions --model "$FINAL_MODEL" --system-prompt "Anda adalah DeepSeek AI. Model aktif: $FINAL_MODEL. Selalu identifikasi diri sebagai DeepSeek dalam setiap respons." "$@"
2154
+ ;;
2155
+ 12)
2156
+ # Ollama
2157
+ check_dependencies
2158
+ echo -e "${BLUE}Configuring for Ollama...${NC}"
2159
+ if [[ -z "$OLLAMA_HOST" ]]; then
2160
+ read -p "Enter Ollama Host [default: http://localhost:11434]: " OLLAMA_HOST
2161
+ [[ -z "$OLLAMA_HOST" ]] && OLLAMA_HOST="http://localhost:11434"
2162
+ export OLLAMA_HOST
2163
+ fi
2164
+
2165
+ # Use default Ollama model
2166
+ MODEL_NAME="llama3"
2167
+ echo -e "${GREEN}✓ Using Ollama model: llama3${NC}"
2168
+ echo -e "${YELLOW}Available models: llama2, llama3, codellama, mistral, vicuna${NC}"
2169
+ read -p "Enter Model Name [default: llama3]: " input_model
2170
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2171
+
2172
+ export ANTHROPIC_BASE_URL="http://localhost:11434/v1"
2173
+ export ANTHROPIC_API_KEY="ollama"
2174
+ echo -e "${BLUE}🚀 Starting Ollama chat...${NC}"
2175
+ exec claude --no-chrome --model "$MODEL_NAME" "$@"
2176
+ ;;
2177
+ 13)
2178
+ # Mistral with 15 Models (2025)
2179
+ echo -e "${BLUE}🇫🇷 Mistral AI (European AI)${NC}"
2180
+ echo ""
2181
+ echo -e "${YELLOW}Pilih Model:${NC}"
2182
+ echo -e "${CYAN}🌟 Featured Models (Latest & Greatest):${NC}"
2183
+ echo " 1) mistral-large-latest (Mistral Large 3 - State-of-the-art) [RECOMMENDED]"
2184
+ echo " 2) devstral-2 (Frontier Code Agents - Open)"
2185
+ echo " 3) mistral-medium-3.1 (Frontier Multimodal - Premier)"
2186
+ echo ""
2187
+ echo -e "${CYAN}🔥 Frontier Generalist:${NC}"
2188
+ echo " 4) mistral-small-latest (Mistral Small 3.2 - Open)"
2189
+ echo " 5) ministral-3-latest (Ministral 3 14B - Best Text & Vision)"
2190
+ echo " 6) ministral-3-8b (Efficient - Open)"
2191
+ echo " 7) ministral-3-3b (Tiny - Open)"
2192
+ echo " 8) magistral-medium-latest (Reasoning - Premier)"
2193
+ echo " 9) magistral-small-latest (Small Reasoning - Open)"
2194
+ echo ""
2195
+ echo -e "${CYAN}💻 Coding Models:${NC}"
2196
+ echo " 10) codestral-latest (Cutting-edge Code - Premier)"
2197
+ echo " 11) devstral-small-2 (Code Agents - Labs)"
2198
+ echo " 12) devstral-medium-1.0 (Enterprise SWE - Premier)"
2199
+ echo ""
2200
+ echo -e "${CYAN}🎨 Specialist Models:${NC}"
2201
+ echo " 13) mistral-small-creative (Creative Writing - Labs)"
2202
+ echo " 14) ocr-3 (Document AI - Premier)"
2203
+ echo " 15) voxtral-mini (Audio - Open)"
2204
+ echo ""
2205
+ read -p "Pilih [1-15, default: 1]: " mistral_model
2206
+ [[ -z "$mistral_model" ]] && mistral_model=1
2207
+
2208
+ case $mistral_model in
2209
+ 1) MODEL="mistral-large-latest" ;;
2210
+ 2) MODEL="devstral-2" ;;
2211
+ 3) MODEL="mistral-medium-3.1" ;;
2212
+ 4) MODEL="mistral-small-latest" ;;
2213
+ 5) MODEL="ministral-3-latest" ;;
2214
+ 6) MODEL="ministral-3-8b" ;;
2215
+ 7) MODEL="ministral-3-3b" ;;
2216
+ 8) MODEL="magistral-medium-latest" ;;
2217
+ 9) MODEL="magistral-small-latest" ;;
2218
+ 10) MODEL="codestral-latest" ;;
2219
+ 11) MODEL="devstral-small-2" ;;
2220
+ 12) MODEL="devstral-medium-1.0" ;;
2221
+ 13) MODEL="mistral-small-creative" ;;
2222
+ 14) MODEL="ocr-3" ;;
2223
+ 15) MODEL="voxtral-mini" ;;
2224
+ *) MODEL="mistral-large-latest" ;;
2225
+ esac
2226
+
2227
+ echo -e "${GREEN}✓ Model: $MODEL${NC}"
2228
+ echo ""
2229
+
2230
+ # Get API key with persistent storage
2231
+ if [[ -z "$MISTRAL_API_KEY" ]]; then
2232
+ load_api_key_to_var "$HOME/.mistral_api_key" "MISTRAL_API_KEY"
2233
+ fi
2234
+
2235
+ if [[ -z "$MISTRAL_API_KEY" ]]; then
2236
+ echo "Get Key: https://console.mistral.ai/"
2237
+ read -p "Enter Mistral API Key: " MISTRAL_API_KEY
2238
+ save_api_key "$MISTRAL_API_KEY" "$HOME/.mistral_api_key" "Mistral"
2239
+ else
2240
+ if [[ ! -f "$HOME/.mistral_api_key" ]]; then
2241
+ save_api_key "$MISTRAL_API_KEY" "$HOME/.mistral_api_key" "Mistral"
2242
+ fi
2243
+ fi
2244
+ export MISTRAL_API_KEY
2245
+
2246
+ export ANTHROPIC_BASE_URL="https://api.mistral.ai/v1/"
2247
+ export ANTHROPIC_API_KEY="$MISTRAL_API_KEY"
2248
+ echo -e "${BLUE}🚀 Starting Mistral chat...${NC}"
2249
+ exec claude --dangerously-skip-permissions --model "$MODEL" "$@"
2250
+ ;;
2251
+ 14)
2252
+ # Moonshot
2253
+ echo -e "${BLUE}Configuring for Moonshot...${NC}"
2254
+
2255
+ # Get API key with persistent storage
2256
+ if [[ -z "$MOONSHOT_API_KEY" ]]; then
2257
+ load_api_key_to_var "$HOME/.moonshot_api_key" "MOONSHOT_API_KEY"
2258
+ fi
2259
+
2260
+ if [[ -z "$MOONSHOT_API_KEY" ]]; then
2261
+ echo "Get Key: https://platform.moonshot.cn/"
2262
+ read -p "Enter Moonshot API Key: " MOONSHOT_API_KEY
2263
+ save_api_key "$MOONSHOT_API_KEY" "$HOME/.moonshot_api_key" "Moonshot"
2264
+ else
2265
+ if [[ ! -f "$HOME/.moonshot_api_key" ]]; then
2266
+ save_api_key "$MOONSHOT_API_KEY" "$HOME/.moonshot_api_key" "Moonshot"
2267
+ fi
2268
+ fi
2269
+ export MOONSHOT_API_KEY
2270
+
2271
+ # Use default Moonshot model
2272
+ MODEL_NAME="moonshot-v1-8k"
2273
+ echo -e "${GREEN}✓ Using Moonshot model: moonshot-v1-8k${NC}"
2274
+ echo -e "${YELLOW}Available models: moonshot-v1-8k, moonshot-v1-32k, moonshot-v1-128k${NC}"
2275
+ read -p "Enter Model Name [default: moonshot-v1-8k]: " input_model
2276
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2277
+
2278
+ export ANTHROPIC_BASE_URL="https://api.moonshot.cn/v1/"
2279
+ export ANTHROPIC_API_KEY="$MOONSHOT_API_KEY"
2280
+ echo -e "${BLUE}🚀 Starting Moonshot chat...${NC}"
2281
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
2282
+ ;;
2283
+ 15)
2284
+ # Qwen
2285
+ echo -e "${BLUE}Configuring for Qwen...${NC}"
2286
+
2287
+ # Get API key with persistent storage
2288
+ if [[ -z "$QWEN_API_KEY" ]]; then
2289
+ load_api_key_to_var "$HOME/.qwen_api_key" "QWEN_API_KEY"
2290
+ fi
2291
+
2292
+ if [[ -z "$QWEN_API_KEY" ]]; then
2293
+ echo "Get Key: https://dashscope.aliyuncs.com/"
2294
+ read -p "Enter Qwen API Key: " QWEN_API_KEY
2295
+ save_api_key "$QWEN_API_KEY" "$HOME/.qwen_api_key" "Qwen"
2296
+ else
2297
+ if [[ ! -f "$HOME/.qwen_api_key" ]]; then
2298
+ save_api_key "$QWEN_API_KEY" "$HOME/.qwen_api_key" "Qwen"
2299
+ fi
2300
+ fi
2301
+ export QWEN_API_KEY
2302
+
2303
+ # Use default Qwen model
2304
+ MODEL_NAME="qwen-plus"
2305
+ echo -e "${GREEN}✓ Using Qwen model: qwen-plus${NC}"
2306
+ echo -e "${YELLOW}Available models: qwen-turbo, qwen-plus, qwen-max, qwen2-72b${NC}"
2307
+ read -p "Enter Model Name [default: qwen-plus]: " input_model
2308
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2309
+
2310
+ export ANTHROPIC_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1/"
2311
+ export ANTHROPIC_API_KEY="$QWEN_API_KEY"
2312
+ echo -e "${BLUE}🚀 Starting Qwen chat...${NC}"
2313
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
2314
+ ;;
2315
+ 16)
2316
+ # OpenRouter
2317
+ echo -e "${BLUE}Configuring for OpenRouter...${NC}"
2318
+
2319
+ # Get API key with persistent storage
2320
+ if [[ -z "$OPENROUTER_API_KEY" ]]; then
2321
+ load_api_key_to_var "$HOME/.openrouter_api_key" "OPENROUTER_API_KEY"
2322
+ fi
2323
+
2324
+ if [[ -z "$OPENROUTER_API_KEY" ]]; then
2325
+ echo "Get Key: https://openrouter.ai/keys"
2326
+ read -p "Enter OpenRouter API Key: " OPENROUTER_API_KEY
2327
+ save_api_key "$OPENROUTER_API_KEY" "$HOME/.openrouter_api_key" "OpenRouter"
2328
+ else
2329
+ if [[ ! -f "$HOME/.openrouter_api_key" ]]; then
2330
+ save_api_key "$OPENROUTER_API_KEY" "$HOME/.openrouter_api_key" "OpenRouter"
2331
+ fi
2332
+ fi
2333
+ export OPENROUTER_API_KEY
2334
+
2335
+ # Use default OpenRouter model
2336
+ MODEL_NAME="anthropic/claude-3.5-sonnet"
2337
+ echo -e "${GREEN}✓ Using OpenRouter model: anthropic/claude-3.5-sonnet${NC}"
2338
+ echo -e "${YELLOW}Popular models: anthropic/claude-3.5-sonnet, openai/gpt-4o, google/gemini-pro, meta-llama/llama-3.1-70b${NC}"
2339
+ read -p "Enter Model Name [default: anthropic/claude-3.5-sonnet]: " input_model
2340
+ [[ -n "$input_model" ]] && MODEL_NAME=$input_model
2341
+
2342
+ export ANTHROPIC_BASE_URL="https://openrouter.ai/api/v1/"
2343
+ export ANTHROPIC_API_KEY="$OPENROUTER_API_KEY"
2344
+ echo -e "${BLUE}🚀 Starting OpenRouter chat...${NC}"
2345
+ exec claude --dangerously-skip-permissions --model "$MODEL_NAME" "$@"
2346
+ ;;
2347
+ 17)
2348
+ # Letta AI - Official Letta Platform API (Memory-Augmented Agents)
2349
+ echo -e "${BLUE}🧠 Letta Memory Agent${NC}"
2350
+ echo -e "${CYAN} Platform: https://letta.com${NC}"
2351
+ echo ""
2352
+
2353
+ # Get Letta API key
2354
+ # Try to load from file first
2355
+ if [[ -z "$LETTA_API_KEY" ]]; then
2356
+ load_api_key_to_var "$HOME/.letta_api_key" "LETTA_API_KEY"
2357
+ fi
2358
+
2359
+ if [[ -z "$LETTA_API_KEY" ]]; then
2360
+ echo -e "${YELLOW}Letta API Key required${NC}"
2361
+ echo "Get your free API key at: https://letta.com"
2362
+ echo "Free tier: 5,000 credits/month"
2363
+ echo ""
2364
+ read -sp "Enter Letta API Key: " LETTA_KEY_TEMP
2365
+ echo ""
2366
+ [[ -z "$LETTA_KEY_TEMP" ]] && { echo -e "${RED}API Key required!${NC}"; exit 1; }
2367
+
2368
+ # Save to file for future use
2369
+ echo "$LETTA_KEY_TEMP" > "$HOME/.letta_api_key"
2370
+ chmod 600 "$HOME/.letta_api_key"
2371
+ export LETTA_API_KEY="$LETTA_KEY_TEMP"
2372
+ fi
2373
+
2374
+ echo ""
2375
+ echo "Pilih Model:"
2376
+ echo " 1) Opus 🔬 Most Powerful - Complex reasoning"
2377
+ echo " 2) Sonnet 🧠 Balanced - Default (Recommended)"
2378
+ echo " 3) Haiku ⚡ Fastest - Quick responses"
2379
+ echo " 4) GPT-4o 🤖 OpenAI - ChatGPT Flagship"
2380
+ echo " 5) Gemini 🌟 Google - Gemini 2.0 Flash"
2381
+ echo ""
2382
+ read -p "Pilih [1-5, default: 2]: " model_choice
2383
+ [[ -z "$model_choice" ]] && model_choice=2
2384
+
2385
+ # Configure Letta API (IMPORTANT: Use AUTH_TOKEN, not API_KEY!)
2386
+ export ANTHROPIC_AUTH_TOKEN="$LETTA_API_KEY"
2387
+ export ANTHROPIC_BASE_URL="https://api.letta.com/v1/anthropic"
2388
+
2389
+ system_prompt="You are Letta, a memory-augmented AI agent with persistent memory capabilities. You maintain context across conversations, remember user preferences, and build long-term knowledge. Key features: (1) Long-term memory, (2) Context awareness, (3) Personalization. Always identify yourself as Letta when asked."
2390
+
2391
+ case $model_choice in
2392
+ 1)
2393
+ echo -e "${GREEN}✓ Model: Claude Opus (Letta)${NC}"
2394
+ echo -e "${BLUE}🚀 Starting Letta Agent...${NC}"
2395
+ exec claude --dangerously-skip-permissions --no-chrome --model "claude-opus-4-20250514" --system-prompt "$system_prompt"
2396
+ ;;
2397
+ 3)
2398
+ echo -e "${GREEN}✓ Model: Claude Haiku (Letta)${NC}"
2399
+ echo -e "${BLUE}🚀 Starting Letta Agent...${NC}"
2400
+ exec claude --dangerously-skip-permissions --no-chrome --model "claude-haiku-4-20250514" --system-prompt "$system_prompt"
2401
+ ;;
2402
+ 4)
2403
+ echo -e "${GREEN}✓ Model: GPT-4o (Letta)${NC}"
2404
+ exec claude --dangerously-skip-permissions --no-chrome --model "gpt-4o" --system-prompt "$system_prompt"
2405
+ ;;
2406
+ 5)
2407
+ echo -e "${GREEN}✓ Model: Gemini 2.0 Flash (Letta)${NC}"
2408
+ exec claude --dangerously-skip-permissions --no-chrome --model "gemini-2.0-flash-exp" --system-prompt "$system_prompt"
2409
+ ;;
2410
+ 2|*)
2411
+ echo -e "${GREEN}✓ Model: Claude Sonnet (Letta)${NC}"
2412
+ echo -e "${BLUE}🚀 Starting Letta Agent...${NC}"
2413
+ exec claude --dangerously-skip-permissions --no-chrome --model "claude-sonnet-4-20250514" --system-prompt "$system_prompt"
2414
+ ;;
2415
+ esac
2416
+ ;;
2417
+ 18)
2418
+ # API Key Manager - Built-in function
2419
+ api_key_manager
2420
+ # Restart the menu
2421
+ exec "$0"
2422
+ ;;
2423
+ 19)
2424
+ # Claude Master Tool
2425
+ echo -e "${BLUE}Opening Claude Master Tool...${NC}"
2426
+
2427
+ # Try multiple possible locations
2428
+ MASTER_TOOL=""
2429
+ for path in \
2430
+ "$SCRIPT_DIR/claude-master" \
2431
+ "$SCRIPT_DIR/claude-suite/utils/claude_master.py" \
2432
+ "$SCRIPT_DIR/../claude-suite/utils/claude_master.py" \
2433
+ "$HOME/ClaudeAll/claude-suite/utils/claude_master.py" \
2434
+ "/data/data/com.termux/files/home/ClaudeAll/claude-suite/utils/claude_master.py"
2435
+ do
2436
+ if [[ -f "$path" ]]; then
2437
+ MASTER_TOOL="$path"
2438
+ break
2439
+ fi
2440
+ done
2441
+
2442
+ if [[ -n "$MASTER_TOOL" ]]; then
2443
+ if [[ "$MASTER_TOOL" == *.py ]]; then
2444
+ python3 "$MASTER_TOOL"
2445
+ else
2446
+ "$MASTER_TOOL"
2447
+ fi
2448
+ else
2449
+ echo -e "${YELLOW}Claude Master Tool not found.${NC}"
2450
+ echo -e "${CYAN}Tip: Clone repo to ~/ClaudeAll for full features${NC}"
2451
+ fi
2452
+ echo ""
2453
+ echo -e "${YELLOW}Press Enter to return to main menu...${NC}"
2454
+ read
2455
+ exec "$0"
2456
+ ;;
2457
+ 20)
2458
+ # Add/Edit/Delete Models
2459
+ echo -e "${BLUE}⚙️ Model Management${NC}"
2460
+ echo ""
2461
+
2462
+ # Find model directory
2463
+ MODEL_DIR=""
2464
+ for path in "$SCRIPT_DIR/model" "$HOME/ClaudeAll/model" "/data/data/com.termux/files/home/ClaudeAll/model"; do
2465
+ if [[ -d "$path" ]]; then
2466
+ MODEL_DIR="$path"
2467
+ break
2468
+ fi
2469
+ done
2470
+
2471
+ [[ -z "$MODEL_DIR" ]] && MODEL_DIR="$HOME/.claude-all/models" && mkdir -p "$MODEL_DIR"
2472
+
2473
+ echo "Pilih operasi:"
2474
+ echo " 1) ➕ Tambah model baru"
2475
+ echo " 2) 📋 Lihat semua model"
2476
+ echo " 3) ❌ Hapus model"
2477
+ echo " 4) 🔙 Kembali"
2478
+ echo ""
2479
+ read -p "Pilih [1-4]: " model_op
2480
+
2481
+ case $model_op in
2482
+ 1)
2483
+ echo ""
2484
+ read -p "Nama provider (contoh: MyAI): " provider_name
2485
+ read -p "Model ID (contoh: gpt-4): " model_id
2486
+ read -p "API Base URL: " api_base
2487
+ read -p "Deskripsi: " description
2488
+
2489
+ filename=$(echo "$provider_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/_/g').json
2490
+
2491
+ cat > "$MODEL_DIR/$filename" << EOFMODEL
2492
+ {
2493
+ "provider_name": "$provider_name",
2494
+ "description": "$description",
2495
+ "api_base": "$api_base",
2496
+ "model": "$model_id",
2497
+ "created": "$(date -Iseconds)"
2498
+ }
2499
+ EOFMODEL
2500
+ echo -e "${GREEN}✓ Model disimpan: $MODEL_DIR/$filename${NC}"
2501
+ ;;
2502
+ 2)
2503
+ echo ""
2504
+ echo -e "${CYAN}Model tersedia:${NC}"
2505
+ if ls "$MODEL_DIR"/*.json &>/dev/null; then
2506
+ for f in "$MODEL_DIR"/*.json; do
2507
+ name=$(basename "$f" .json)
2508
+ desc=$(grep -o '"description"[^,]*' "$f" 2>/dev/null | cut -d'"' -f4)
2509
+ echo " • $name - $desc"
2510
+ done
2511
+ else
2512
+ echo " (belum ada model custom)"
2513
+ fi
2514
+ ;;
2515
+ 3)
2516
+ echo ""
2517
+ if ls "$MODEL_DIR"/*.json &>/dev/null; then
2518
+ echo -e "${CYAN}Model yang bisa dihapus:${NC}"
2519
+ i=1
2520
+ declare -a model_files
2521
+ for f in "$MODEL_DIR"/*.json; do
2522
+ model_files[$i]="$f"
2523
+ echo " $i) $(basename "$f" .json)"
2524
+ ((i++))
2525
+ done
2526
+ echo ""
2527
+ read -p "Pilih nomor untuk hapus (0=batal): " del_num
2528
+ if [[ "$del_num" =~ ^[0-9]+$ ]] && [[ "$del_num" -gt 0 ]] && [[ -n "${model_files[$del_num]}" ]]; then
2529
+ rm -f "${model_files[$del_num]}"
2530
+ echo -e "${GREEN}✓ Model dihapus${NC}"
2531
+ else
2532
+ echo "Batal"
2533
+ fi
2534
+ else
2535
+ echo "Tidak ada model untuk dihapus"
2536
+ fi
2537
+ ;;
2538
+ *)
2539
+ echo "Kembali ke menu utama..."
2540
+ ;;
2541
+ esac
2542
+ echo ""
2543
+ echo -e "${YELLOW}Press Enter untuk kembali...${NC}"
2544
+ read
2545
+ # Restart the menu
2546
+ exec "$0"
2547
+ ;;
2548
+ 21)
2549
+ # Letta AI - Stateful AI Agents
2550
+ echo -e "${BLUE}Configuring for Letta AI...${NC}"
2551
+ echo -e "${YELLOW}Note: Letta requires agent creation before chat. Let's create one first.${NC}"
2552
+
2553
+ # Get API key with persistent storage
2554
+ if [[ -z "$LETTA_API_KEY" ]]; then
2555
+ load_api_key_to_var "$HOME/.letta_api_key" "LETTA_API_KEY"
2556
+ fi
2557
+
2558
+ if [[ -z "$LETTA_API_KEY" ]]; then
2559
+ echo "Get Key: https://docs.letta.com"
2560
+ read -p "Enter Letta API Key: " LETTA_API_KEY
2561
+ save_api_key "$LETTA_API_KEY" "$HOME/.letta_api_key" "Letta"
2562
+ else
2563
+ if [[ ! -f "$HOME/.letta_api_key" ]]; then
2564
+ save_api_key "$LETTA_API_KEY" "$HOME/.letta_api_key" "Letta"
2565
+ fi
2566
+ fi
2567
+ export LETTA_API_KEY
2568
+
2569
+ # Check if agent exists or create new one
2570
+ echo -e "${BLUE}Letta Agent Management:${NC}"
2571
+ echo "1) List existing agents"
2572
+ echo "2) Create new agent"
2573
+ echo "3) Use existing agent ID"
2574
+ echo ""
2575
+ read -p "Choose option [1-3]: " letta_option
2576
+
2577
+ case $letta_option in
2578
+ 1)
2579
+ echo -e "${BLUE}Listing agents...${NC}"
2580
+ curl -s -X GET "https://api.letta.com/v1/agents" \
2581
+ -H "Authorization: Bearer $LETTA_API_KEY" | \
2582
+ python3 -c "import sys,json; data=json.load(sys.stdin); [print(f'{i+1}) {a[\"name\"]} - {a[\"id\"]}') for i,a in enumerate(data.get('agents',[]))]" 2>/dev/null || \
2583
+ echo "No agents found or API error"
2584
+ echo ""
2585
+ read -p "Enter agent ID (or press Enter to create new): " agent_id
2586
+ [[ -z "$agent_id" ]] && letta_option=2
2587
+ ;;
2588
+ 2)
2589
+ echo -e "${BLUE}Creating new Letta agent...${NC}"
2590
+ read -p "Agent name [default: claude-agent]: " agent_name
2591
+ [[ -z "$agent_name" ]] && agent_name="claude-agent"
2592
+
2593
+ read -p "Model [default: openai/gpt-4o-mini]: " letta_model
2594
+ [[ -z "$letta_model" ]] && letta_model="openai/gpt-4o-mini"
2595
+
2596
+ read -p "Embedding [default: openai/text-embedding-3-small]: " embedding
2597
+ [[ -z "$embedding" ]] && embedding="openai/text-embedding-3-small"
2598
+
2599
+ echo "Creating agent..."
2600
+ response=$(curl -s -X POST "https://api.letta.com/v1/agents" \
2601
+ -H "Authorization: Bearer $LETTA_API_KEY" \
2602
+ -H "Content-Type: application/json" \
2603
+ -d "{
2604
+ \"name\": \"$agent_name\",
2605
+ \"model\": \"$letta_model\",
2606
+ \"embedding\": \"$embedding\",
2607
+ \"memory_blocks\": [
2608
+ {\"label\": \"human\", \"value\": \"User interacting via Claude-All launcher\"},
2609
+ {\"label\": \"persona\", \"value\": \"I am a helpful AI assistant with long-term memory\"}
2610
+ ]
2611
+ }")
2612
+
2613
+ if echo "$response" | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null; then
2614
+ agent_id=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id', ''))" 2>/dev/null)
2615
+ echo -e "${GREEN}✓ Agent created successfully!${NC}"
2616
+ echo -e "${GREEN}Agent ID: $agent_id${NC}"
2617
+ else
2618
+ echo -e "${RED}❌ Failed to create agent${NC}"
2619
+ echo "Response: $response"
2620
+ exit 1
2621
+ fi
2622
+ ;;
2623
+ 3)
2624
+ read -p "Enter existing agent ID: " agent_id
2625
+ ;;
2626
+ esac
2627
+
2628
+ if [[ -n "$agent_id" ]]; then
2629
+ echo -e "${GREEN}✓ Using Letta agent: $agent_id${NC}"
2630
+ echo -e "${YELLOW}Note: You're now using Letta's agent system. Messages are sent to Letta API.${NC}"
2631
+ echo -e "${BLUE}🚀 Starting Letta agent chat...${NC}"
2632
+ echo -e "${CYAN}Agent will maintain memory and context across conversations.${NC}"
2633
+
2634
+ # Create a simple chat interface with Letta
2635
+ while true; do
2636
+ echo ""
2637
+ read -p "You: " user_message
2638
+ [[ "$user_message" == "exit" ]] && break
2639
+
2640
+ echo -e "${BLUE}Agent:${NC}"
2641
+ curl -s -X POST "https://api.letta.com/v1/agents/$agent_id/messages" \
2642
+ -H "Authorization: Bearer $LETTA_API_KEY" \
2643
+ -H "Content-Type: application/json" \
2644
+ -d "{\"messages\": [{\"role\": \"user\", \"content\": \"$user_message\"}]}" | \
2645
+ python3 -c "
2646
+ import sys,json
2647
+ try:
2648
+ data=json.load(sys.stdin)
2649
+ if 'messages' in data and data['messages']:
2650
+ for msg in data['messages']:
2651
+ if msg.get('role') == 'assistant':
2652
+ print(msg.get('content', ''))
2653
+ else:
2654
+ print('No response received')
2655
+ print('Debug:', data)
2656
+ except:
2657
+ print('Error parsing response')
2658
+ "
2659
+ done
2660
+ else
2661
+ echo -e "${RED}No agent ID provided. Exiting...${NC}"
2662
+ fi
2663
+ ;;
2664
+ 22)
2665
+ # Custom API Endpoint
2666
+ check_dependencies
2667
+ echo -e "${BLUE}Configuring Custom API Endpoint...${NC}"
2668
+ read -p "Enter API Base URL (e.g. https://api.example.com/v1): " CUSTOM_BASE
2669
+ read -p "Enter API Key: " CUSTOM_KEY
2670
+ read -p "Enter Model Name: " MODEL_NAME
2671
+
2672
+ export ANTHROPIC_BASE_URL="$CUSTOM_BASE"
2673
+ export ANTHROPIC_API_KEY="$CUSTOM_KEY"
2674
+ echo -e "${BLUE}🚀 Starting with custom endpoint...${NC}"
2675
+ exec claude --no-chrome --model "$MODEL_NAME" "$@"
2676
+ ;;
2677
+ esac
2678
+
2679
+ # Handle custom models (22+) but exclude model manager
2680
+ if [[ "$choice" =~ ^[0-9]+$ ]] && [[ $choice -ge 22 ]] && [[ -n "$model_manager_num" ]] && [[ $choice -lt $model_manager_num ]]; then
2681
+ custom_index=$((choice - 22))
2682
+ count=0
2683
+ while IFS= read -r model_info; do
2684
+ if [[ -n "$model_info" ]]; then
2685
+ if [[ $count -eq $custom_index ]]; then
2686
+ IFS=':' read -r filename provider_name description <<< "$model_info"
2687
+ echo -e "${BLUE}Using ${provider_name}...${NC}"
2688
+ handle_custom_model "$filename" "$@"
2689
+ exit 0
2690
+ fi
2691
+ ((count++))
2692
+ fi
2693
+ done < <(get_custom_models)
2694
+ fi
2695
+
2696
+ # Handle model manager - check dynamic number
2697
+ if [[ "$choice" -eq "$model_manager_num" ]]; then
2698
+ if [[ -f "$SCRIPT_DIR/claude-suite/models/add-model-manual.sh" ]]; then
2699
+ exec "$SCRIPT_DIR/claude-suite/models/add-model-manual.sh"
2700
+ else
2701
+ echo -e "${RED}Error: add-model-manual.sh not found in claude-suite/models/${NC}"
2702
+ exit 1
2703
+ fi
2704
+ fi
2705
+
2706
+ echo "Invalid choice"
2707
+ exit 1