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.
- package/.claude/agents/CLAUDE.md +740 -978
- package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +47 -2
- package/.claude/agents/custom/agent-builder.md +637 -0
- package/.claude/api-configs/config-current-zai-config.env +62 -0
- package/.claude/api-configs/config-test-zai-config.env +62 -0
- package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +62 -0
- package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +62 -0
- package/.claude/artifacts/reflection-merge-logs/cli-agent-spawning-v2.5.2-merge-report.md +61 -0
- package/.claude/commands/cfn-loop-epic.md +41 -17
- package/.claude/commands/cfn-loop.md +43 -30
- package/.claude/commands/custom-routing-activate.md +37 -123
- package/.claude/commands/custom-routing-deactivate.md +27 -124
- package/.claude/commands/switch-api.md +41 -16
- package/.claude/skills/agent-execution/execute-agent.sh +126 -0
- package/.claude/skills/redis-coordination/AGENT_LOGGING.md +280 -0
- package/.claude/skills/redis-coordination/agent-log.sh +124 -0
- package/.claude/skills/redis-coordination/init-swarm.sh +6 -1
- package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +62 -5
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +68 -8
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +933 -0
- package/.claude/skills/redis-coordination/store-epic-context.sh +123 -0
- package/.claude/skills/redis-coordination/test-iteration-feedback.sh +320 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/CLAUDE.md +76 -2
- package/dist/cli/agent-command.js +151 -0
- package/dist/cli/agent-command.js.map +1 -0
- package/dist/cli/agent-definition-parser.js +176 -0
- package/dist/cli/agent-definition-parser.js.map +1 -0
- package/dist/cli/agent-executor.js +176 -0
- package/dist/cli/agent-executor.js.map +1 -0
- package/dist/cli/agent-prompt-builder.js +188 -0
- package/dist/cli/agent-prompt-builder.js.map +1 -0
- package/dist/cli/agent-spawn.js +46 -1
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/anthropic-client.js +242 -0
- package/dist/cli/anthropic-client.js.map +1 -0
- package/dist/cli/cli-agent-context.js +353 -0
- package/dist/cli/cli-agent-context.js.map +1 -0
- package/dist/cli/cli-agent-context.test.js +451 -0
- package/dist/cli/cli-agent-context.test.js.map +1 -0
- package/dist/cli/index.js +115 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/iteration-history.js +188 -0
- package/dist/cli/iteration-history.js.map +1 -0
- package/package.json +3 -1
- 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.
|
|
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
|