
.claude/setting içinde yer alıyor (araç ayrıcalıklarını da verdim, böylece Enter’a basmak gerekmiyor). Setting içinde key’i rastgele doldurabilirsiniz. Doldurmanız gereken sadece iki alan var: biri deno kodundaki kendi key’iniz, diğeri setting içindeki deploy sonrası dev bilgisi."
Deno:
// Deno Deploy Claude to OpenAI API Proxy Server with Load Balancing & Tool Call Auto-Fix
// Converts Claude API format to OpenAI compatible format for Vercel AI Gateway
// Includes automatic detection and conversion of tool calls from text format
// --- Interfaces ---
interface ClaudeMessage {
role: "user" | "assistant";
content: string | Array<{ type: string; text?: string; [key: string]: any }>;
}
interface ClaudeRequest {
model: string;
messages: ClaudeMessage[];
max_tokens?: number;
temperature?: number;
tools?: any[];
tool_choice?: any;
[key: string]: any;
}
interface OpenAIMessage {
role: "user" | "assistant" | "system";
content: string;
}
interface OpenAIRequest {
model: string;
messages: OpenAIMessage[];
max_tokens?: number;
temperature?: number;
tools?: any[];
tool_choice?: any;
[key: string]: any;
}
interface ToolCallDetectionResult {
success: boolean;
toolCalls?: any[];
error?: string;
mixedContent?: boolean;
textContent?: string;
}
// --- Constants with Load Balancing ---
const VERCEL_API_URL = "https://api.v0.dev/v1/chat/completions";
// 多个API密钥用于负载均衡
const VERCEL_API_KEYS = [
"v1:team_xxxxxxxx",
"v1:team_xxxxxxxx",
"v1:team_xxxxxxxx",
"v1:team_xxxxxxxx",
"v1:team_xxxxxxxx"
];
// Model mapping
const MODEL_MAPPING: { [key: string]: string } = {
"claude-3-5-haiku-20241022": "v0-1.5-md",
"claude-sonnet-4-20250514": "v0-1.5-md",
"claude-opus-4-20250514": "v0-1.5-lg",
};
// --- Enhanced Load Balancing Manager with Background Cleanup ---
class ApiKeyManager {
private keys: string[];
private currentIndex: number = 0;
private failedKeys: Map<string, number> = new Map();
private failureCount: Map<string, number> = new Map(); // 失败计数器
private readonly FAILURE_TIMEOUT = 172800000; // 失败后2天重试 (2 * 24 * 60 * 60 * 1000)
private globalRecoveryUsed: boolean = false; // 全局恢复是否已使用
private cleanupInterval: number;
constructor(keys: string[]) {
this.keys = keys;
console.log(`🔑 Initialized API Key Manager with ${keys.length} keys`);
// 启动后台清理任务,每小时执行一次
this.cleanupInterval = setInterval(() => {
this.cleanupExpiredKeys();
}, 3600000); // 1小时
}
// 后台清理过期密钥
private cleanupExpiredKeys() {
const now = Date.now();
let cleanedCount = 0;
for (const [key, failTime] of this.failedKeys.entries()) {
if (now - failTime > this.FAILURE_TIMEOUT) {
this.failedKeys.delete(key);
this.failureCount.delete(key);
cleanedCount++;
console.log(`🧹 Background cleanup restored key: ${key.substring(0, 8)}...`);
}
}
if (cleanedCount > 0) {
console.log(`🧹 Background cleanup completed: ${cleanedCount} keys restored`);
}
}
// 获取多个可用密钥用于并行重试
getAvailableKeys(count: number = 3): string[] {
const availableKeys = this.keys.filter(key => !this.failedKeys.has(key));
if (availableKeys.length === 0) {
if (!this.globalRecoveryUsed) {
console.warn("⚠️ All keys are failed, performing one-time global recovery");
this.failedKeys.clear();
this.failureCount.clear();
this.globalRecoveryUsed = true;
return this.keys.slice(0, Math.min(count, this.keys.length));
} else {
// 收集所有失败原因
const failureReasons = Array.from(this.failedKeys.entries()).map(([key, _]) => {
const failCount = this.failureCount.get(key) || 0;
return `${key.substring(0, 8)}...: ${failCount} failures`;
});
const errorMessage = `All API keys are unavailable. Failure details: ${failureReasons.join(', ')}`;
console.error(`❌ ${errorMessage}`);
throw new Error(errorMessage);
}
}
// 从当前索引开始轮询选择
const result: string[] = [];
for (let i = 0; i < Math.min(count, availableKeys.length); i++) {
const key = availableKeys[(this.currentIndex + i) % availableKeys.length];
result.push(key);
}
this.currentIndex += result.length;
console.log(`🔑 Selected ${result.length} keys for parallel retry (${availableKeys.length}/${this.keys.length} available)`);
return result;
}
getKey(): string {
// 简化版本,直接获取第一个可用密钥
return this.getAvailableKeys(1)[0];
}
markKeyAsFailed(key: string, error?: string) {
// 增加失败计数
const currentCount = this.failureCount.get(key) || 0;
const newCount = currentCount + 1;
this.failureCount.set(key, newCount);
console.warn(`⚠️ Key failure ${newCount}/3: ${key.substring(0, 8)}... Error: ${error || 'Unknown'}`);
// 只有失败3次才真正标记为不可用
if (newCount >= 3) {
this.failedKeys.set(key, Date.now());
console.error(`❌ Key marked as failed after 3 attempts: ${key.substring(0, 8)}...`);
}
}
getStats() {
const available = this.keys.length - this.failedKeys.size;
return {
total: this.keys.length,
available,
failed: this.failedKeys.size
};
}
// 清理资源
destroy() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
}
}
const keyManager = new ApiKeyManager(VERCEL_API_KEYS);
// --- Tool Call Detection and Conversion Functions ---
function detectAndConvertToolCalls(text: string): ToolCallDetectionResult {
try {
// 方法1:尝试直接解析整个文本为JSON工具调用
const parsed = JSON.parse(text);
if (parsed.type === "tool_use" && parsed.name) {
console.log("🔧 Detected complete tool_use JSON in text");
return {
success: true,
toolCalls: [{
type: "tool_use",
id: parsed.id || `tool_json_${Date.now()}`,
name: parsed.name,
input: parsed.input || {}
}]
};
}
// 检查是否为工具调用数组
if (Array.isArray(parsed) && parsed.length > 0 && parsed[0].type === "tool_use") {
console.log("🔧 Detected tool_use array in text");
return {
success: true,
toolCalls: parsed.map(tool => ({
type: "tool_use",
id: tool.id || `tool_${Date.now()}`,
name: tool.name,
input: tool.input || {}
}))
};
}
} catch (e) {
// 继续尝试其他方法
}
// 方法1.5:检测 antml:function_calls XML 格式
const xmlMatch = text.match(/<function_calls>(.*?)<\/antml:function_calls>/s);
if (xmlMatch) {
try {
const invokeMatches = xmlMatch[1].match(/<invoke name="([^"]+)">(.*?)<\/antml:invoke>/gs);
if (invokeMatches) {
console.log("🔧 Detected antml:function_calls XML format");
const toolCalls = invokeMatches.map((invokeMatch, index) => {
const nameMatch = invokeMatch.match(/name="([^"]+)"/);
const paramMatches = invokeMatch.match(/<parameter name="([^"]+)">(.*?)<\/antml:parameter>/gs);
if (nameMatch) {
const input: any = {};
if (paramMatches) {
paramMatches.forEach(paramMatch => {
const paramNameMatch = paramMatch.match(/name="([^"]+)"/);
const paramValueMatch = paramMatch.match(/<parameter[^>]*>(.*?)<\/antml:parameter>/s);
if (paramNameMatch && paramValueMatch) {
input[paramNameMatch[1]] = paramValueMatch[1].trim();
}
});
}
return {
type: "tool_use",
id: `tool_xml_${Date.now()}_${index}`,
name: nameMatch[1],
input
};
}
return null;
}).filter(Boolean);
if (toolCalls.length > 0) {
return { success: true, toolCalls };
}
}
} catch (e) {
console.error("❌ Failed to parse antml:function_calls:", e.message);
}
}
// 方法2:改进的JSON解析 - 支持嵌套大括号
function extractBalancedJson(text: string, startPos: number): string | null {
let braceCount = 0;
let inString = false;
let escaped = false;
for (let i = startPos; i < text.length; i++) {
const char = text[i];
if (escaped) {
escaped = false;
continue;
}
if (char === '\\') {
escaped = true;
continue;
}
if (char === '"') {
inString = !inString;
continue;
}
if (!inString) {
if (char === '{') {
braceCount++;
} else if (char === '}') {
braceCount--;
if (braceCount === 0) {
return text.substring(startPos, i + 1);
}
}
}
}
return null;
}
const toolCalls: any[] = [];
let idCounter = 0;
// 查找所有包含工具调用标识的位置
const searchPatterns = ['"type":\s*"tool_use"', '"name":\s*"[^"]+"'];
for (const pattern of searchPatterns) {
const regex = new RegExp(pattern, 'g');
let match;
while ((match = regex.exec(text)) !== null) {
// 向前查找最近的 {
let bracePos = match.index;
while (bracePos > 0 && text[bracePos] !== '{') {
bracePos--;
}
if (text[bracePos] === '{') {
const jsonStr = extractBalancedJson(text, bracePos);
if (jsonStr) {
try {
const parsed = JSON.parse(jsonStr);
if ((parsed.type === "tool_use" || parsed.name) && parsed.name) {
// 检查是否已经添加过这个工具调用
const exists = toolCalls.some(tc =>
tc.name === parsed.name &&
JSON.stringify(tc.input) === JSON.stringify(parsed.input || {})
);
if (!exists) {
toolCalls.push({
type: "tool_use",
id: parsed.id || `tool_${Date.now()}_${++idCounter}`,
name: parsed.name,
input: parsed.input || {}
});
}
}
} catch (e) {
// JSON解析失败,继续搜索
}
}
}
}
}
if (toolCalls.length > 0) {
console.log(`🔧 Extracted ${toolCalls.length} tool calls using improved parsing`);
return { success: true, toolCalls };
}
// 方法3:原有的正则表达式作为后备
const toolPatterns = [
// 完整的工具调用模式
/\{[^{}]*"type"\s*:\s*"tool_use"[^{}]*"name"\s*:\s*"[^"]+"[^{}]*\}/g,
// 简化的工具调用模式
/\{[^{}]*"name"\s*:\s*"[^"]+"[^{}]*"input"\s*:\s*\{[^{}]*\}[^{}]*\}/g
];
for (const pattern of toolPatterns) {
const matches = text.match(pattern);
if (matches && matches.length > 0) {
try {
const toolCalls = matches.map(match => {
try {
const toolData = JSON.parse(match);
return {
type: "tool_use",
id: toolData.id || `tool_regex_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
name: toolData.name,
input: toolData.input || {}
};
} catch (e) {
// 如果解析失败,尝试提取关键信息
const nameMatch = match.match(/"name"\s*:\s*"([^"]+)"/);
const inputMatch = match.match(/"input"\s*:\s*(\{[^}]*\})/);
if (nameMatch) {
return {
type: "tool_use",
id: `tool_fallback_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
name: nameMatch[1],
input: inputMatch ? JSON.parse(inputMatch[1]) : {}
};
}
return null;
}
}).filter(Boolean);
if (toolCalls.length > 0) {
console.log(`🔧 Extracted ${toolCalls.length} tool calls using regex pattern`);
return { success: true, toolCalls };
}
} catch (parseError) {
console.error("❌ Failed to parse extracted tool calls:", parseError.message);
}
}
}
// 方法4:检查是否包含工具调用关键词但格式混乱
if (text.includes('"type":"tool_use"') || text.includes('<function_calls>') ||
text.includes('<invoke') ||
(text.includes('"name":') && text.includes('"input":'))) {
console.warn("⚠️ Detected tool call keywords but failed to parse - may be malformed");
return {
success: false,
error: "Tool call detected but format is malformed",
mixedContent: true,
textContent: text
};
}
return { success: false, error: "No tool calls detected" };
}
// --- Main Conversion Functions ---
function convertClaudeToOpenAI(claudeRequest: ClaudeRequest): OpenAIRequest {
console.log("🔄 Converting Claude request to OpenAI format");
// 1. 转换 messages
const openaiMessages: OpenAIMessage[] = claudeRequest.messages.map(msg => ({
role: msg.role,
content: Array.isArray(msg.content)
? msg.content.map(c => c.text || JSON.stringify(c)).join('\n')
: msg.content
}));
// 2. 映射 model
const openaiModel = MODEL_MAPPING[claudeRequest.model] || "anthropic/claude-4-sonnet";
console.log(`🔄 Model mapping: ${claudeRequest.model} -> ${openaiModel}`);
// 3. 转换 tools 数组
let openaiTools = undefined;
if (claudeRequest.tools && claudeRequest.tools.length > 0) {
console.log(`🔧 Converting ${claudeRequest.tools.length} tools from Claude to OpenAI format`);
openaiTools = claudeRequest.tools.map(tool => {
const openaiTool = {
type: "function",
function: {
name: tool.name,
description: tool.description,
parameters: tool.input_schema
}
};
console.log(`🔧 Converted tool: ${tool.name}`);
return openaiTool;
});
}
// 4. 处理 tool_choice
let openaiToolChoice = undefined;
if (claudeRequest.tool_choice) {
console.log("🔧 Converting tool_choice:", claudeRequest.tool_choice);
if (claudeRequest.tool_choice === "auto") {
openaiToolChoice = "auto";
} else if (claudeRequest.tool_choice === "any") {
openaiToolChoice = "required";
} else if (typeof claudeRequest.tool_choice === "object" && claudeRequest.tool_choice.type === "tool") {
openaiToolChoice = {
type: "function",
function: { name: claudeRequest.tool_choice.name }
};
}
}
// 5. 构建最终的 OpenAI 请求对象 (非流式处理)
const result = {
model: openaiModel,
messages: openaiMessages,
max_tokens: claudeRequest.max_tokens || 4096,
temperature: claudeRequest.temperature || 0.7,
stream: false, // 强制非流式处理
...(openaiTools && { tools: openaiTools }),
...(openaiToolChoice && { tool_choice: openaiToolChoice })
};
console.log(`✅ Conversion to OpenAI format completed (non-streaming)`);
return result;
}
// --- Enhanced OpenAI to Claude Conversion with Auto-Fix ---
function convertOpenAIToClaude(openaiResponse: any): any {
console.log("🔄 Converting OpenAI response to Claude format");
if (openaiResponse.choices && openaiResponse.choices[0]) {
const choice = openaiResponse.choices[0];
// 方法1:检查标准的 tool_calls
if (choice.message?.tool_calls && choice.message.tool_calls.length > 0) {
console.log("✅ Found standard tool_calls, converting to Claude format");
return {
id: openaiResponse.id || `msg_${Date.now()}`,
type: "message",
role: "assistant",
content: choice.message.tool_calls.map((call: any) => ({
type: "tool_use",
id: call.id,
name: call.function.name,
input: JSON.parse(call.function.arguments)
})),
model: openaiResponse.model,
stop_reason: "tool_use",
stop_sequence: null,
usage: openaiResponse.usage ? {
input_tokens: openaiResponse.usage.prompt_tokens,
output_tokens: openaiResponse.usage.completion_tokens
} : undefined
};
}
// 方法2:检测和修复text格式中的工具调用
const messageContent = choice.message?.content;
if (typeof messageContent === 'string' && messageContent.trim()) {
const toolDetection = detectAndConvertToolCalls(messageContent);
if (toolDetection.success && toolDetection.toolCalls) {
console.log("🔧 AUTO-FIXED: Converted tool call from text format to proper JSON");
console.log(`🔧 Detected ${toolDetection.toolCalls.length} tool call(s)`);
return {
id: openaiResponse.id || `msg_${Date.now()}`,
type: "message",
role: "assistant",
content: toolDetection.toolCalls,
model: openaiResponse.model,
stop_reason: "tool_use", // 关键:修正stop_reason
stop_sequence: null,
usage: openaiResponse.usage ? {
input_tokens: openaiResponse.usage.prompt_tokens,
output_tokens: openaiResponse.usage.completion_tokens
} : undefined
};
}
// 如果检测到工具调用但解析失败,记录警告
if (toolDetection.mixedContent) {
console.warn("⚠️ Detected tool call in text but failed to parse - treating as mixed content");
// 可以选择返回混合内容或纯文本,这里选择纯文本
}
}
// 方法3:处理普通文本响应
console.log("📝 Processing as standard text response");
return {
id: openaiResponse.id || `msg_${Date.now()}`,
type: "message",
role: "assistant",
content: [{
type: "text",
text: messageContent || ""
}],
model: openaiResponse.model,
stop_reason: choice.finish_reason === "stop" ? "end_turn" : choice.finish_reason,
stop_sequence: null,
usage: openaiResponse.usage ? {
input_tokens: openaiResponse.usage.prompt_tokens,
output_tokens: openaiResponse.usage.completion_tokens
} : undefined
};
}
return openaiResponse;
}
// --- Enhanced Request with Parallel Retry ---
async function makeRequestWithParallelRetry(openaiRequest: OpenAIRequest, maxConcurrent: number = 3): Promise<Response> {
const availableKeys = keyManager.getAvailableKeys(maxConcurrent);
console.log(`🚀 Starting parallel retry with ${availableKeys.length} keys`);
// 创建并行请求
const requestPromises = availableKeys.map(async (key, index) => {
try {
console.log(`🚀 Parallel request ${index + 1} with key: ${key.substring(0, 8)}...`);
const response = await fetch(VERCEL_API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${key}`
},
body: JSON.stringify(openaiRequest)
});
if (response.ok) {
console.log(`✅ Parallel request ${index + 1} successful`);
return { success: true, response, key };
} else {
const errorText = await response.text();
const error = `HTTP ${response.status}: ${errorText}`;
// 特定错误码标记密钥失败
if (response.status === 401 || response.status === 403) {
keyManager.markKeyAsFailed(key, `HTTP ${response.status}`);
}
console.error(`❌ Parallel request ${index + 1} failed: ${error}`);
return {
success: false,
error,
key,
response: new Response(errorText, {
status: response.status,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
}
})
};
}
} catch (error) {
keyManager.markKeyAsFailed(key, error.message);
console.error(`❌ Parallel request ${index + 1} failed with exception: ${error.message}`);
return { success: false, error: error.message, key };
}
});
try {
// 等待第一个成功的响应
const results = await Promise.allSettled(requestPromises);
// 查找第一个成功的结果
for (const result of results) {
if (result.status === 'fulfilled' && result.value.success) {
console.log(`✅ Parallel retry succeeded with key: ${result.value.key.substring(0, 8)}...`);
return result.value.response;
}
}
// 如果所有请求都失败,返回第一个错误响应
for (const result of results) {
if (result.status === 'fulfilled' && result.value.response) {
console.error(`❌ All parallel requests failed, returning first error response`);
return result.value.response;
}
}
// 如果没有响应对象,抛出异常
const errors = results.map((r, i) =>
r.status === 'fulfilled' ? r.value.error : `Request ${i + 1}: ${r.reason}`
).join('; ');
throw new Error(`All parallel requests failed. Errors: ${errors}`);
} catch (error) {
console.error(`❌ Parallel retry error: ${error.message}`);
throw error;
}
}
// --- Fallback: Sequential Request with Retry ---
async function makeRequestWithRetry(openaiRequest: OpenAIRequest, maxRetries: number = 3): Promise<Response> {
let lastError: string = "";
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const selectedKey = keyManager.getKey();
try {
console.log(`🚀 Sequential attempt ${attempt}/${maxRetries} with key: ${selectedKey.substring(0, 8)}...`);
const response = await fetch(VERCEL_API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${selectedKey}`
},
body: JSON.stringify(openaiRequest)
});
if (response.ok) {
console.log(`✅ Sequential request successful on attempt ${attempt}`);
return response;
}
const errorText = await response.text();
lastError = `HTTP ${response.status}: ${errorText}`;
if (response.status === 401 || response.status === 403) {
keyManager.markKeyAsFailed(selectedKey, `HTTP ${response.status}`);
}
console.error(`❌ Sequential attempt ${attempt} failed: ${lastError}`);
if (attempt === maxRetries) {
return new Response(errorText, {
status: response.status,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
}
});
}
} catch (error) {
lastError = error.message;
keyManager.markKeyAsFailed(selectedKey, error.message);
console.error(`❌ Sequential attempt ${attempt} failed with exception: ${lastError}`);
if (attempt === maxRetries) {
throw error;
}
}
// 短暂延迟后重试
await new Promise(resolve => setTimeout(resolve, 500));
}
throw new Error(`All ${maxRetries} sequential attempts failed. Last error: ${lastError}`);
}
// --- Main Request Handler ---
async function handleRequest(request: Request): Promise<Response> {
const url = new URL(request.url);
if (request.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, x-api-key, anthropic-version"
}
});
}
if (url.pathname === "/health") {
const stats = keyManager.getStats();
return new Response(JSON.stringify({
status: "OK",
keyStats: stats,
timestamp: new Date().toISOString(),
features: {
loadBalancing: true,
autoToolCallFix: true,
streaming: false,
parallelRetry: true,
backgroundCleanup: true
}
}), {
status: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
});
}
if (url.pathname === "/v1/messages" && request.method === "POST") {
try {
const claudeRequest: ClaudeRequest = await request.json();
console.log("📥 Received Claude request");
console.log(`📊 Model: ${claudeRequest.model}, Tools: ${claudeRequest.tools?.length || 0}`);
const openaiRequest = convertClaudeToOpenAI(claudeRequest);
// 使用并行重试机制的请求函数(优先)
const response = await makeRequestWithParallelRetry(openaiRequest);
if (!response.ok) {
return response; // 已经在 makeRequestWithParallelRetry 中处理过错误响应
}
// 处理非流式响应
console.log("📦 Processing non-streaming response");
const openaiResponse = await response.json();
const claudeResponse = convertOpenAIToClaude(openaiResponse);
console.log("📤 Sending Claude response");
return new Response(JSON.stringify(claudeResponse), {
status: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
});
} catch (error) {
console.error("❌ Request processing error:", error);
const stats = keyManager.getStats();
return new Response(JSON.stringify({
error: {
type: "proxy_error",
message: `Proxy error: ${error.message}`,
keyStats: stats
}
}), {
status: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
});
}
}
return new Response("Not Found. Use /v1/messages for API calls.", { status: 404 });
}
// --- Deno Deploy Export ---
export default {
fetch: handleRequest,
};Claude Setting.{
"env": {
"HTTP_PROXY": "http://127.0.0.1:10808",
"HTTPS_PROXY": "http://127.0.0.1:10808",
"ANTHROPIC_API_KEY": "sk-123",
"ANTHROPIC_BASE_URL": "https://xxxxxx.dev"
},
"permissions": {
"allow": [
"Bash(*)",
"Edit(*)",
"MultiEdit(*)",
"NotebookEdit(*)",
"WebFetch(*)",
"WebSearch(*)",
"List(*)",
"Write(*)"
],
"deny": []
}
}Claude.MD
Sen Claude Code’sun, Anthropic tarafından geliştirilen bir AI programlama asistanısın ve Claude 4 modeline dayalısın.Kimlik Özellikleri
- Terminal ve komut satırı ortamlarında çalışmaya özelsin
- Dosyaları doğrudan düzenleyebilir, komut çalıştırabilir ve Git işlemleri gerçekleştirebilirsin
- Sadece öneri vermekle kalmayıp aktif şekilde hareket edebilen bir agentic programlama aracısın
- Tüm proje yapısını ve kod tabanı bağlamını anlıyorsun
- Unix felsefesine uyumlu, birleştirilebilir ve scriptlenebilir yeteneklere sahipsin
Çalışma Şekli
- Doğal dil ile talimat alıp yürütme planı oluşturursun
- Dosya sistemi üzerinde doğrudan işlem yapar ve terminal komutlarını çalıştırırsın
- MCP entegrasyonu ile dış araçları desteklersin
- Kurumsal ortamda güvenlik, gizlilik ve uyumluluk sağlar
Temel Sorumluluklar
Claude Code kimliğini koruyarak odaklanmalısın:- Kod yazımı, hata ayıklama ve optimizasyon
- Proje yapısı analizi ve iyileştirme
- Git iş akışı yönetimi
- Geliştirme araçları entegrasyonu ve otomasyon
KRİTİK: Araç çağırma formatı zorunluluğu
Claude Code, araç çağırırken belirli XML formatını kullanır. Araç çağrısı gerektiğinde, aşağıdaki formata kesinlikle uyulmalıdır:Tek araç çağrısı
Birden fazla araç çağrısı
<function_calls> <invoke name="Read"> <parameter name="file_path">c:\path o ile1.ts</parameter> </invoke> <invoke name="Edit"> <parameter name="file_path">c:\path o ile2.ts</parameter> <parameter name="old_string">old content</parameter> <parameter name="new_string">new content</parameter> </invoke> </function_calls> Araç çağırma örnekleri Dosya okuma: <function_calls> <invoke name="Read"> <parameter name="file_path">src/components/Button.tsx</parameter> </invoke> </function_calls> Dosya düzenleme: <function_calls> <invoke name="Edit"> <parameter name="file_path">src/utils/helper.ts</parameter> <parameter name="old_string">export function oldFunction() {} </parameter> <parameter name="new_string">export function newFunction() {}</parameter> </invoke> </function_calls> Komut çalıştırma: <function_calls> <invoke name="Bash"> <parameter name="command">npm install</parameter> <parameter name="description">Paket bağımlılıklarını yükle</parameter> </invoke> </function_calls> Dosya arama: <function_calls> <invoke name="Grep"> <parameter name="pattern">function.useState</parameter> <parameter name="glob">.tsx</parameter> <parameter name="output_mode">content</parameter> </invoke> </function_calls> Temel format kuralları:- XML yapısı: Tüm araç çağrıları <function_calls> ile çevrelenmelidir
- invoke etiketi: Her araç çağrısı <invoke name="ToolName"> ile yapılmalıdır
- parameter etiketi: Tüm parametreler <parameter name="param_name">value</parameter> ile belirtilmelidir
- Tam kapanış: Tüm etiketler doğru şekilde kapatılmalıdır
- Ekstra metin yok: Araç çağrısı bloğunda başka metin veya açıklama bulunamaz
Optimizasyon gerektiren noktalar:
- Akış (streaming) çıktısı: Bunu bir türlü hayata geçiremedim. Deno kodunun bir versiyonunda akış şeklinde çıktı almayı başardım ve curl ile sorguladığında akışlı yanıt alınabiliyor. Ancak CC içinde akış tanınmıyor, hep normal (akışsız) yanıt dönüyor.
- Prompt ve deno kodu, hatalı araç çağrısı kullanımını düzeltmiş olsa da bazen yine hata çıkabiliyor; yani doğrudan metin çıktısı veriyor, araç çağrısı yapmıyor. (Yine de çoğu durumda artık bu sorun yaşanmıyor; olursa tekrar denetlettirmek yeterli.)

