claude-flow-novice 2.5.2 → 2.6.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 (46) hide show
  1. package/.claude/agents/CLAUDE.md +740 -978
  2. package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +47 -2
  3. package/.claude/agents/custom/agent-builder.md +637 -0
  4. package/.claude/api-configs/config-current-zai-config.env +62 -0
  5. package/.claude/api-configs/config-test-zai-config.env +62 -0
  6. package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +62 -0
  7. package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +62 -0
  8. package/.claude/artifacts/reflection-merge-logs/cli-agent-spawning-v2.5.2-merge-report.md +61 -0
  9. package/.claude/commands/cfn-loop-epic.md +41 -17
  10. package/.claude/commands/cfn-loop.md +43 -30
  11. package/.claude/commands/custom-routing-activate.md +37 -123
  12. package/.claude/commands/custom-routing-deactivate.md +27 -124
  13. package/.claude/commands/switch-api.md +41 -16
  14. package/.claude/skills/agent-execution/execute-agent.sh +126 -0
  15. package/.claude/skills/redis-coordination/AGENT_LOGGING.md +280 -0
  16. package/.claude/skills/redis-coordination/agent-log.sh +124 -0
  17. package/.claude/skills/redis-coordination/init-swarm.sh +6 -1
  18. package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +62 -5
  19. package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +68 -8
  20. package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +933 -0
  21. package/.claude/skills/redis-coordination/store-epic-context.sh +123 -0
  22. package/.claude/skills/redis-coordination/test-iteration-feedback.sh +320 -0
  23. package/.claude/skills/skill-builder/SKILL.md +910 -0
  24. package/CLAUDE.md +76 -2
  25. package/dist/cli/agent-command.js +151 -0
  26. package/dist/cli/agent-command.js.map +1 -0
  27. package/dist/cli/agent-definition-parser.js +176 -0
  28. package/dist/cli/agent-definition-parser.js.map +1 -0
  29. package/dist/cli/agent-executor.js +176 -0
  30. package/dist/cli/agent-executor.js.map +1 -0
  31. package/dist/cli/agent-prompt-builder.js +188 -0
  32. package/dist/cli/agent-prompt-builder.js.map +1 -0
  33. package/dist/cli/agent-spawn.js +46 -1
  34. package/dist/cli/agent-spawn.js.map +1 -1
  35. package/dist/cli/anthropic-client.js +242 -0
  36. package/dist/cli/anthropic-client.js.map +1 -0
  37. package/dist/cli/cli-agent-context.js +353 -0
  38. package/dist/cli/cli-agent-context.js.map +1 -0
  39. package/dist/cli/cli-agent-context.test.js +451 -0
  40. package/dist/cli/cli-agent-context.test.js.map +1 -0
  41. package/dist/cli/index.js +115 -2
  42. package/dist/cli/index.js.map +1 -1
  43. package/dist/cli/iteration-history.js +188 -0
  44. package/dist/cli/iteration-history.js.map +1 -0
  45. package/package.json +3 -1
  46. package/scripts/switch-api.sh +233 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Iteration History Management
3
+ *
4
+ * Loads and formats iteration history from Redis for CLI-spawned agents.
5
+ * Enables agents to learn from previous attempts and feedback.
6
+ *
7
+ * Storage Pattern:
8
+ * swarm:${TASK_ID}:${AGENT_ID}:result:iteration-${N} → Result text + confidence
9
+ * swarm:${TASK_ID}:${AGENT_ID}:feedback:iteration-${N} → Validator feedback
10
+ *
11
+ * Sprint 3 - Phase 2 Implementation
12
+ */ import { execSync } from 'child_process';
13
+ /**
14
+ * Load iteration history for an agent from Redis
15
+ *
16
+ * @param taskId - Task identifier
17
+ * @param agentId - Agent identifier
18
+ * @param currentIteration - Current iteration number (loads 1 to N-1)
19
+ * @returns Array of iteration results
20
+ */ export async function loadIterationHistory(taskId, agentId, currentIteration) {
21
+ const history = [];
22
+ // Load previous iterations (1 to currentIteration - 1)
23
+ for(let i = 1; i < currentIteration; i++){
24
+ try {
25
+ // Load result data
26
+ const resultKey = `swarm:${taskId}:${agentId}:result:iteration-${i}`;
27
+ const resultJson = execSync(`redis-cli get "${resultKey}"`, {
28
+ encoding: 'utf8'
29
+ }).trim();
30
+ if (resultJson === '(nil)' || !resultJson) {
31
+ continue;
32
+ }
33
+ const resultData = JSON.parse(resultJson);
34
+ // Load feedback data (may not exist for all iterations)
35
+ const feedbackKey = `swarm:${taskId}:${agentId}:feedback:iteration-${i}`;
36
+ let feedback;
37
+ try {
38
+ const feedbackJson = execSync(`redis-cli get "${feedbackKey}"`, {
39
+ encoding: 'utf8'
40
+ }).trim();
41
+ if (feedbackJson !== '(nil)' && feedbackJson) {
42
+ const feedbackData = JSON.parse(feedbackJson);
43
+ feedback = feedbackData.feedback || feedbackData.comments;
44
+ }
45
+ } catch (err) {
46
+ // Feedback may not exist for this iteration
47
+ feedback = undefined;
48
+ }
49
+ history.push({
50
+ iteration: i,
51
+ result: resultData.result || resultData.output || '',
52
+ confidence: resultData.confidence || 0,
53
+ timestamp: resultData.timestamp || new Date().toISOString(),
54
+ feedback
55
+ });
56
+ } catch (err) {
57
+ console.error(`[iteration-history] Failed to load iteration ${i}:`, err);
58
+ // Continue loading other iterations
59
+ }
60
+ }
61
+ return history;
62
+ }
63
+ /**
64
+ * Store iteration result in Redis
65
+ *
66
+ * @param taskId - Task identifier
67
+ * @param agentId - Agent identifier
68
+ * @param iteration - Iteration number
69
+ * @param result - Result text/output
70
+ * @param confidence - Confidence score (0.0-1.0)
71
+ */ export async function storeIterationResult(taskId, agentId, iteration, result, confidence) {
72
+ const resultKey = `swarm:${taskId}:${agentId}:result:iteration-${iteration}`;
73
+ const resultData = {
74
+ result,
75
+ confidence,
76
+ timestamp: new Date().toISOString(),
77
+ iteration
78
+ };
79
+ const resultJson = JSON.stringify(resultData);
80
+ try {
81
+ // Store with 24 hour TTL
82
+ execSync(`redis-cli setex "${resultKey}" 86400 '${resultJson.replace(/'/g, "'\\''")}'`, {
83
+ encoding: 'utf8'
84
+ });
85
+ console.log(`[iteration-history] Stored result for iteration ${iteration}`);
86
+ } catch (err) {
87
+ console.error(`[iteration-history] Failed to store result:`, err);
88
+ throw err;
89
+ }
90
+ }
91
+ /**
92
+ * Format iteration history as markdown for system prompt
93
+ *
94
+ * @param history - Array of iteration results
95
+ * @param currentIteration - Current iteration number
96
+ * @returns Formatted markdown string
97
+ */ export function formatIterationHistory(history, currentIteration) {
98
+ if (history.length === 0) {
99
+ return `## Current Iteration: ${currentIteration}
100
+
101
+ This is your first attempt at this task. No previous iteration history available.
102
+ `;
103
+ }
104
+ const sections = [];
105
+ sections.push('## Iteration History');
106
+ sections.push('');
107
+ sections.push('Learn from your previous attempts and feedback:');
108
+ sections.push('');
109
+ // Format each iteration
110
+ for (const iter of history){
111
+ sections.push(`### Iteration ${iter.iteration}`);
112
+ sections.push('');
113
+ sections.push('**Result:**');
114
+ sections.push(iter.result.substring(0, 500)); // Truncate to 500 chars
115
+ if (iter.result.length > 500) {
116
+ sections.push('... (truncated)');
117
+ }
118
+ sections.push('');
119
+ if (iter.feedback) {
120
+ sections.push('**Feedback from Validators:**');
121
+ sections.push(iter.feedback);
122
+ sections.push('');
123
+ }
124
+ sections.push(`**Confidence:** ${iter.confidence.toFixed(2)}`);
125
+ sections.push(`**Timestamp:** ${iter.timestamp}`);
126
+ sections.push('');
127
+ sections.push('---');
128
+ sections.push('');
129
+ }
130
+ // Add current iteration context
131
+ sections.push(`## Current Iteration: ${currentIteration}`);
132
+ sections.push('');
133
+ if (history.length > 0) {
134
+ const lastIteration = history[history.length - 1];
135
+ if (lastIteration.feedback) {
136
+ sections.push('**Your Task:** Address the feedback from the previous iteration:');
137
+ sections.push('');
138
+ sections.push(lastIteration.feedback);
139
+ sections.push('');
140
+ } else {
141
+ sections.push(`**Your Task:** Improve upon iteration ${lastIteration.iteration} (confidence: ${lastIteration.confidence.toFixed(2)})`);
142
+ sections.push('');
143
+ }
144
+ }
145
+ return sections.join('\n');
146
+ }
147
+ /**
148
+ * Check if iteration history exists for an agent
149
+ *
150
+ * @param taskId - Task identifier
151
+ * @param agentId - Agent identifier
152
+ * @returns True if any iteration history exists
153
+ */ export async function hasIterationHistory(taskId, agentId) {
154
+ try {
155
+ const pattern = `swarm:${taskId}:${agentId}:result:iteration-*`;
156
+ const keys = execSync(`redis-cli --scan --pattern "${pattern}"`, {
157
+ encoding: 'utf8'
158
+ }).trim();
159
+ return keys.length > 0;
160
+ } catch (err) {
161
+ return false;
162
+ }
163
+ }
164
+ /**
165
+ * Get the latest iteration number for an agent
166
+ *
167
+ * @param taskId - Task identifier
168
+ * @param agentId - Agent identifier
169
+ * @returns Latest iteration number (0 if no history)
170
+ */ export async function getLatestIteration(taskId, agentId) {
171
+ try {
172
+ const pattern = `swarm:${taskId}:${agentId}:result:iteration-*`;
173
+ const keys = execSync(`redis-cli --scan --pattern "${pattern}"`, {
174
+ encoding: 'utf8'
175
+ }).trim().split('\n').filter((k)=>k.length > 0);
176
+ if (keys.length === 0) return 0;
177
+ // Extract iteration numbers and find max
178
+ const iterations = keys.map((key)=>{
179
+ const match = key.match(/iteration-(\d+)$/);
180
+ return match ? parseInt(match[1], 10) : 0;
181
+ });
182
+ return Math.max(...iterations);
183
+ } catch (err) {
184
+ return 0;
185
+ }
186
+ }
187
+
188
+ //# sourceMappingURL=iteration-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/iteration-history.ts"],"sourcesContent":["/**\r\n * Iteration History Management\r\n *\r\n * Loads and formats iteration history from Redis for CLI-spawned agents.\r\n * Enables agents to learn from previous attempts and feedback.\r\n *\r\n * Storage Pattern:\r\n * swarm:${TASK_ID}:${AGENT_ID}:result:iteration-${N} → Result text + confidence\r\n * swarm:${TASK_ID}:${AGENT_ID}:feedback:iteration-${N} → Validator feedback\r\n *\r\n * Sprint 3 - Phase 2 Implementation\r\n */\r\n\r\nimport { execSync } from 'child_process';\r\n\r\nexport interface IterationResult {\r\n iteration: number;\r\n result: string;\r\n confidence: number;\r\n timestamp: string;\r\n feedback?: string;\r\n}\r\n\r\n/**\r\n * Load iteration history for an agent from Redis\r\n *\r\n * @param taskId - Task identifier\r\n * @param agentId - Agent identifier\r\n * @param currentIteration - Current iteration number (loads 1 to N-1)\r\n * @returns Array of iteration results\r\n */\r\nexport async function loadIterationHistory(\r\n taskId: string,\r\n agentId: string,\r\n currentIteration: number\r\n): Promise<IterationResult[]> {\r\n const history: IterationResult[] = [];\r\n\r\n // Load previous iterations (1 to currentIteration - 1)\r\n for (let i = 1; i < currentIteration; i++) {\r\n try {\r\n // Load result data\r\n const resultKey = `swarm:${taskId}:${agentId}:result:iteration-${i}`;\r\n const resultJson = execSync(`redis-cli get \"${resultKey}\"`, { encoding: 'utf8' }).trim();\r\n\r\n if (resultJson === '(nil)' || !resultJson) {\r\n // No result for this iteration (shouldn't happen in normal flow)\r\n continue;\r\n }\r\n\r\n const resultData = JSON.parse(resultJson);\r\n\r\n // Load feedback data (may not exist for all iterations)\r\n const feedbackKey = `swarm:${taskId}:${agentId}:feedback:iteration-${i}`;\r\n let feedback: string | undefined;\r\n\r\n try {\r\n const feedbackJson = execSync(`redis-cli get \"${feedbackKey}\"`, { encoding: 'utf8' }).trim();\r\n if (feedbackJson !== '(nil)' && feedbackJson) {\r\n const feedbackData = JSON.parse(feedbackJson);\r\n feedback = feedbackData.feedback || feedbackData.comments;\r\n }\r\n } catch (err) {\r\n // Feedback may not exist for this iteration\r\n feedback = undefined;\r\n }\r\n\r\n history.push({\r\n iteration: i,\r\n result: resultData.result || resultData.output || '',\r\n confidence: resultData.confidence || 0,\r\n timestamp: resultData.timestamp || new Date().toISOString(),\r\n feedback\r\n });\r\n } catch (err) {\r\n console.error(`[iteration-history] Failed to load iteration ${i}:`, err);\r\n // Continue loading other iterations\r\n }\r\n }\r\n\r\n return history;\r\n}\r\n\r\n/**\r\n * Store iteration result in Redis\r\n *\r\n * @param taskId - Task identifier\r\n * @param agentId - Agent identifier\r\n * @param iteration - Iteration number\r\n * @param result - Result text/output\r\n * @param confidence - Confidence score (0.0-1.0)\r\n */\r\nexport async function storeIterationResult(\r\n taskId: string,\r\n agentId: string,\r\n iteration: number,\r\n result: string,\r\n confidence: number\r\n): Promise<void> {\r\n const resultKey = `swarm:${taskId}:${agentId}:result:iteration-${iteration}`;\r\n const resultData = {\r\n result,\r\n confidence,\r\n timestamp: new Date().toISOString(),\r\n iteration\r\n };\r\n\r\n const resultJson = JSON.stringify(resultData);\r\n\r\n try {\r\n // Store with 24 hour TTL\r\n execSync(`redis-cli setex \"${resultKey}\" 86400 '${resultJson.replace(/'/g, \"'\\\\''\")}'`, {\r\n encoding: 'utf8'\r\n });\r\n console.log(`[iteration-history] Stored result for iteration ${iteration}`);\r\n } catch (err) {\r\n console.error(`[iteration-history] Failed to store result:`, err);\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Format iteration history as markdown for system prompt\r\n *\r\n * @param history - Array of iteration results\r\n * @param currentIteration - Current iteration number\r\n * @returns Formatted markdown string\r\n */\r\nexport function formatIterationHistory(\r\n history: IterationResult[],\r\n currentIteration: number\r\n): string {\r\n if (history.length === 0) {\r\n return `## Current Iteration: ${currentIteration}\r\n\r\nThis is your first attempt at this task. No previous iteration history available.\r\n`;\r\n }\r\n\r\n const sections: string[] = [];\r\n\r\n sections.push('## Iteration History');\r\n sections.push('');\r\n sections.push('Learn from your previous attempts and feedback:');\r\n sections.push('');\r\n\r\n // Format each iteration\r\n for (const iter of history) {\r\n sections.push(`### Iteration ${iter.iteration}`);\r\n sections.push('');\r\n\r\n sections.push('**Result:**');\r\n sections.push(iter.result.substring(0, 500)); // Truncate to 500 chars\r\n if (iter.result.length > 500) {\r\n sections.push('... (truncated)');\r\n }\r\n sections.push('');\r\n\r\n if (iter.feedback) {\r\n sections.push('**Feedback from Validators:**');\r\n sections.push(iter.feedback);\r\n sections.push('');\r\n }\r\n\r\n sections.push(`**Confidence:** ${iter.confidence.toFixed(2)}`);\r\n sections.push(`**Timestamp:** ${iter.timestamp}`);\r\n sections.push('');\r\n sections.push('---');\r\n sections.push('');\r\n }\r\n\r\n // Add current iteration context\r\n sections.push(`## Current Iteration: ${currentIteration}`);\r\n sections.push('');\r\n\r\n if (history.length > 0) {\r\n const lastIteration = history[history.length - 1];\r\n if (lastIteration.feedback) {\r\n sections.push('**Your Task:** Address the feedback from the previous iteration:');\r\n sections.push('');\r\n sections.push(lastIteration.feedback);\r\n sections.push('');\r\n } else {\r\n sections.push(`**Your Task:** Improve upon iteration ${lastIteration.iteration} (confidence: ${lastIteration.confidence.toFixed(2)})`);\r\n sections.push('');\r\n }\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n/**\r\n * Check if iteration history exists for an agent\r\n *\r\n * @param taskId - Task identifier\r\n * @param agentId - Agent identifier\r\n * @returns True if any iteration history exists\r\n */\r\nexport async function hasIterationHistory(\r\n taskId: string,\r\n agentId: string\r\n): Promise<boolean> {\r\n try {\r\n const pattern = `swarm:${taskId}:${agentId}:result:iteration-*`;\r\n const keys = execSync(`redis-cli --scan --pattern \"${pattern}\"`, { encoding: 'utf8' }).trim();\r\n return keys.length > 0;\r\n } catch (err) {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get the latest iteration number for an agent\r\n *\r\n * @param taskId - Task identifier\r\n * @param agentId - Agent identifier\r\n * @returns Latest iteration number (0 if no history)\r\n */\r\nexport async function getLatestIteration(\r\n taskId: string,\r\n agentId: string\r\n): Promise<number> {\r\n try {\r\n const pattern = `swarm:${taskId}:${agentId}:result:iteration-*`;\r\n const keys = execSync(`redis-cli --scan --pattern \"${pattern}\"`, { encoding: 'utf8' })\r\n .trim()\r\n .split('\\n')\r\n .filter((k) => k.length > 0);\r\n\r\n if (keys.length === 0) return 0;\r\n\r\n // Extract iteration numbers and find max\r\n const iterations = keys.map((key) => {\r\n const match = key.match(/iteration-(\\d+)$/);\r\n return match ? parseInt(match[1], 10) : 0;\r\n });\r\n\r\n return Math.max(...iterations);\r\n } catch (err) {\r\n return 0;\r\n }\r\n}\r\n"],"names":["execSync","loadIterationHistory","taskId","agentId","currentIteration","history","i","resultKey","resultJson","encoding","trim","resultData","JSON","parse","feedbackKey","feedback","feedbackJson","feedbackData","comments","err","undefined","push","iteration","result","output","confidence","timestamp","Date","toISOString","console","error","storeIterationResult","stringify","replace","log","formatIterationHistory","length","sections","iter","substring","toFixed","lastIteration","join","hasIterationHistory","pattern","keys","getLatestIteration","split","filter","k","iterations","map","key","match","parseInt","Math","max"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-novice",
3
- "version": "2.5.2",
3
+ "version": "2.6.0",
4
4
  "description": "AI agent orchestration framework with skills-based coordination, Redis pub/sub, and CFN Loop validation",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -67,11 +67,13 @@
67
67
  "portal:status": "./scripts/portal-status.sh"
68
68
  },
69
69
  "dependencies": {
70
+ "@anthropic-ai/sdk": "^0.67.0",
70
71
  "ajv": "^8.17.1",
71
72
  "better-sqlite3": "^12.4.1",
72
73
  "chalk": "^4.1.2",
73
74
  "commander": "^11.1.0",
74
75
  "dotenv": "^17.2.3",
76
+ "glob": "^11.0.3",
75
77
  "lodash": "^4.17.21",
76
78
  "redis": "^5.8.3",
77
79
  "socket.io": "^4.8.1",
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env bash
2
+ ##############################################################################
3
+ # Claude API Switcher - Main Chat & Task Tool Provider Routing
4
+ #
5
+ # Usage: scripts/switch-api.sh [zai|max|status]
6
+ #
7
+ # What it does:
8
+ # - zai: Main Chat + Task tool use Z.ai (add env vars to settings.json)
9
+ # - max: Main Chat + Task tool use Anthropic (remove env vars, requires re-login)
10
+ # - CLI: Always uses Z.ai (controlled by .env CLAUDE_API_PROVIDER=zai)
11
+ #
12
+ # Settings file: .claude/settings.json (project local)
13
+ ##############################################################################
14
+
15
+ set -euo pipefail
16
+
17
+ SETTINGS_FILE=".claude/settings.json"
18
+ BACKUP_DIR=".claude/backups"
19
+
20
+ # Create backup directory
21
+ mkdir -p "$BACKUP_DIR"
22
+
23
+ # Colors
24
+ RED='\033[0;31m'
25
+ GREEN='\033[0;32m'
26
+ YELLOW='\033[1;33m'
27
+ BLUE='\033[0;34m'
28
+ NC='\033[0m' # No Color
29
+
30
+ ##############################################################################
31
+ # Display current configuration
32
+ ##############################################################################
33
+ show_status() {
34
+ echo -e "${BLUE}═══════════════════════════════════════${NC}"
35
+ echo -e "${BLUE} Claude API Provider Status${NC}"
36
+ echo -e "${BLUE}═══════════════════════════════════════${NC}"
37
+ echo ""
38
+
39
+ if [ ! -f "$SETTINGS_FILE" ]; then
40
+ echo -e "${YELLOW}⚠️ Settings file not found${NC}"
41
+ echo " File: $SETTINGS_FILE"
42
+ echo ""
43
+ return
44
+ fi
45
+
46
+ # Check for Z.ai env vars in settings
47
+ if grep -q "ANTHROPIC_BASE_URL" "$SETTINGS_FILE" 2>/dev/null; then
48
+ BASE_URL=$(jq -r '.env.ANTHROPIC_BASE_URL // empty' "$SETTINGS_FILE" 2>/dev/null || echo "")
49
+
50
+ if [[ "$BASE_URL" == *"z.ai"* ]]; then
51
+ echo -e "${GREEN}✓ Main Chat/Task Tool:${NC} Z.ai"
52
+ echo " Base URL: $BASE_URL"
53
+ echo " Cost: \$0.50/1M tokens"
54
+ else
55
+ echo -e "${GREEN}✓ Main Chat/Task Tool:${NC} Custom"
56
+ echo " Base URL: $BASE_URL"
57
+ fi
58
+ else
59
+ echo -e "${GREEN}✓ Main Chat/Task Tool:${NC} Anthropic (default)"
60
+ echo " Cost: \$15/1M tokens (Claude Max subscription)"
61
+ echo " Status: Requires 'claude login'"
62
+ fi
63
+
64
+ # Check CLI routing (.env)
65
+ if grep -q "CLAUDE_API_PROVIDER=zai" .env 2>/dev/null; then
66
+ echo -e "${GREEN}✓ CLI Agents:${NC} Z.ai (from .env)"
67
+ echo " Cost: \$0.50/1M tokens"
68
+ else
69
+ echo -e "${YELLOW}⚠️ CLI Agents:${NC} Anthropic (default)"
70
+ echo " Set CLAUDE_API_PROVIDER=zai in .env for cost savings"
71
+ fi
72
+
73
+ echo ""
74
+ echo -e "${BLUE}Combined Architecture:${NC}"
75
+ echo " Main Chat → Task tool → Coordinator (uses Main Chat provider)"
76
+ echo " Coordinator → CLI spawn → Workers (uses CLI .env provider)"
77
+ echo ""
78
+ }
79
+
80
+ ##############################################################################
81
+ # Switch to Z.ai for Main Chat and Task Tool
82
+ ##############################################################################
83
+ switch_to_zai() {
84
+ echo -e "${BLUE}Switching Main Chat/Task Tool to Z.ai...${NC}"
85
+ echo ""
86
+
87
+ # Backup current settings
88
+ if [ -f "$SETTINGS_FILE" ]; then
89
+ BACKUP_NAME="settings-$(date +%Y%m%d-%H%M%S)-before-zai.json"
90
+ cp "$SETTINGS_FILE" "$BACKUP_DIR/$BACKUP_NAME"
91
+ echo -e "${GREEN}✓${NC} Backed up: $BACKUP_DIR/$BACKUP_NAME"
92
+ fi
93
+
94
+ # Read current settings or create empty object
95
+ if [ -f "$SETTINGS_FILE" ]; then
96
+ CURRENT_SETTINGS=$(cat "$SETTINGS_FILE")
97
+ else
98
+ CURRENT_SETTINGS='{}'
99
+ fi
100
+
101
+ # Add Z.ai env vars to settings
102
+ NEW_SETTINGS=$(echo "$CURRENT_SETTINGS" | jq '. + {
103
+ "env": (.env // {}) + {
104
+ "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
105
+ "ANTHROPIC_AUTH_TOKEN": "cca13d09dcd6407183efe9e24c804cca.QO8R0JxF4fucsoWL"
106
+ }
107
+ }')
108
+
109
+ echo "$NEW_SETTINGS" > "$SETTINGS_FILE"
110
+
111
+ echo ""
112
+ echo -e "${GREEN}═══════════════════════════════════════${NC}"
113
+ echo -e "${GREEN}✓ Switched to Z.ai${NC}"
114
+ echo -e "${GREEN}═══════════════════════════════════════${NC}"
115
+ echo ""
116
+ echo -e "${GREEN}Main Chat + Task Tool:${NC} Z.ai"
117
+ echo " • All Task() spawned agents use Z.ai"
118
+ echo " • Cost: \$0.50/1M tokens (97% savings)"
119
+ echo " • No login required"
120
+ echo ""
121
+ echo -e "${BLUE}CLI Agents:${NC} Z.ai (from .env)"
122
+ echo " • CLAUDE_API_PROVIDER=zai in .env"
123
+ echo " • Independent from Main Chat routing"
124
+ echo ""
125
+ echo -e "${YELLOW}Next Steps:${NC}"
126
+ echo " 1. Restart Claude desktop (if running)"
127
+ echo " 2. Test: /cfn-loop \"Test task\""
128
+ echo " 3. Verify logs show: Provider: zai"
129
+ echo ""
130
+ }
131
+
132
+ ##############################################################################
133
+ # Switch to Anthropic Max for Main Chat and Task Tool
134
+ ##############################################################################
135
+ switch_to_max() {
136
+ echo -e "${BLUE}Switching Main Chat/Task Tool to Anthropic...${NC}"
137
+ echo ""
138
+
139
+ # Backup current settings
140
+ if [ -f "$SETTINGS_FILE" ]; then
141
+ BACKUP_NAME="settings-$(date +%Y%m%d-%H%M%S)-before-max.json"
142
+ cp "$SETTINGS_FILE" "$BACKUP_DIR/$BACKUP_NAME"
143
+ echo -e "${GREEN}✓${NC} Backed up: $BACKUP_DIR/$BACKUP_NAME"
144
+ fi
145
+
146
+ # Read current settings
147
+ if [ -f "$SETTINGS_FILE" ]; then
148
+ CURRENT_SETTINGS=$(cat "$SETTINGS_FILE")
149
+ else
150
+ echo -e "${YELLOW}⚠️ No settings file found, nothing to change${NC}"
151
+ echo ""
152
+ return
153
+ fi
154
+
155
+ # Remove Z.ai env vars
156
+ NEW_SETTINGS=$(echo "$CURRENT_SETTINGS" | jq 'del(.env.ANTHROPIC_BASE_URL, .env.ANTHROPIC_AUTH_TOKEN)')
157
+
158
+ echo "$NEW_SETTINGS" > "$SETTINGS_FILE"
159
+
160
+ echo ""
161
+ echo -e "${GREEN}═══════════════════════════════════════${NC}"
162
+ echo -e "${GREEN}✓ Switched to Anthropic${NC}"
163
+ echo -e "${GREEN}═══════════════════════════════════════${NC}"
164
+ echo ""
165
+ echo -e "${GREEN}Main Chat + Task Tool:${NC} Anthropic (official)"
166
+ echo " • Uses Claude Max subscription"
167
+ echo " • Cost: \$15/1M tokens (or \$0 with unlimited plan)"
168
+ echo " • ${RED}Requires re-login${NC}: Run 'claude login'"
169
+ echo ""
170
+ echo -e "${BLUE}CLI Agents:${NC} Z.ai (from .env)"
171
+ echo " • CLAUDE_API_PROVIDER=zai in .env"
172
+ echo " • ${GREEN}Unchanged${NC} - CLI still uses Z.ai for cost savings"
173
+ echo ""
174
+ echo -e "${YELLOW}Next Steps:${NC}"
175
+ echo " 1. Run: ${BLUE}claude login${NC}"
176
+ echo " 2. Authenticate with Anthropic"
177
+ echo " 3. Restart Claude desktop"
178
+ echo " 4. Test: Main Chat should work"
179
+ echo ""
180
+ echo -e "${YELLOW}Combined Savings:${NC}"
181
+ echo " • Main Chat: \$15/1M (high quality)"
182
+ echo " • CLI Workers: \$0.50/1M (cost optimized)"
183
+ echo " • Overall: 88% savings vs all-Anthropic"
184
+ echo ""
185
+ }
186
+
187
+ ##############################################################################
188
+ # Main command handler
189
+ ##############################################################################
190
+ case "${1:-status}" in
191
+ status|current|"")
192
+ show_status
193
+ ;;
194
+
195
+ zai|z.ai)
196
+ switch_to_zai
197
+ show_status
198
+ ;;
199
+
200
+ max|claude|anthropic)
201
+ switch_to_max
202
+ show_status
203
+ ;;
204
+
205
+ help|--help|-h)
206
+ echo "Claude API Switcher"
207
+ echo ""
208
+ echo "Usage: $0 [command]"
209
+ echo ""
210
+ echo "Commands:"
211
+ echo " status Show current API configuration (default)"
212
+ echo " zai Switch Main Chat/Task tool to Z.ai"
213
+ echo " max Switch Main Chat/Task tool to Anthropic"
214
+ echo ""
215
+ echo "Examples:"
216
+ echo " $0 # Show current status"
217
+ echo " $0 zai # Use Z.ai for Main Chat"
218
+ echo " $0 max # Use Anthropic for Main Chat (requires re-login)"
219
+ echo ""
220
+ echo "Notes:"
221
+ echo " • CLI agents always use Z.ai (from .env CLAUDE_API_PROVIDER=zai)"
222
+ echo " • Main Chat routing affects Task() spawned agents"
223
+ echo " • Settings file: .claude/settings.json"
224
+ echo " • Backups saved to: .claude/backups/"
225
+ echo ""
226
+ ;;
227
+
228
+ *)
229
+ echo -e "${RED}Unknown command: $1${NC}"
230
+ echo "Run '$0 help' for usage"
231
+ exit 1
232
+ ;;
233
+ esac