mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-03-17 02:43:09 +00:00
Merge pull request #190 from nogataka/feature/azure-claude-provider
feat: add Azure Anthropic (Claude) provider support
This commit is contained in:
@@ -30,11 +30,18 @@
|
|||||||
# ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-3-5-haiku@20241022
|
# ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-3-5-haiku@20241022
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Alternative API Providers (GLM, Ollama, Kimi, Custom)
|
# Alternative API Providers (Azure, GLM, Ollama, Kimi, Custom)
|
||||||
# ===================
|
# ===================
|
||||||
# Configure via Settings UI (recommended) or set env vars below.
|
# Configure via Settings UI (recommended) or set env vars below.
|
||||||
# When both are set, env vars take precedence.
|
# When both are set, env vars take precedence.
|
||||||
#
|
#
|
||||||
|
# Azure Anthropic (Claude):
|
||||||
|
# ANTHROPIC_BASE_URL=https://your-resource.services.ai.azure.com/anthropic
|
||||||
|
# ANTHROPIC_API_KEY=your-azure-api-key
|
||||||
|
# ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6
|
||||||
|
# ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-4-5
|
||||||
|
# ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5
|
||||||
|
#
|
||||||
# GLM (Zhipu AI):
|
# GLM (Zhipu AI):
|
||||||
# ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
|
# ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
|
||||||
# ANTHROPIC_AUTH_TOKEN=your-glm-api-key
|
# ANTHROPIC_AUTH_TOKEN=your-glm-api-key
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ def create_client(
|
|||||||
is_vertex = sdk_env.get("CLAUDE_CODE_USE_VERTEX") == "1"
|
is_vertex = sdk_env.get("CLAUDE_CODE_USE_VERTEX") == "1"
|
||||||
is_alternative_api = bool(base_url) or is_vertex
|
is_alternative_api = bool(base_url) or is_vertex
|
||||||
is_ollama = "localhost:11434" in base_url or "127.0.0.1:11434" in base_url
|
is_ollama = "localhost:11434" in base_url or "127.0.0.1:11434" in base_url
|
||||||
|
is_azure = "services.ai.azure.com" in base_url
|
||||||
model = convert_model_for_vertex(model)
|
model = convert_model_for_vertex(model)
|
||||||
if sdk_env:
|
if sdk_env:
|
||||||
print(f" - API overrides: {', '.join(sdk_env.keys())}")
|
print(f" - API overrides: {', '.join(sdk_env.keys())}")
|
||||||
@@ -351,8 +352,10 @@ def create_client(
|
|||||||
print(f" - Vertex AI Mode: Using GCP project '{project_id}' with model '{model}' in region '{region}'")
|
print(f" - Vertex AI Mode: Using GCP project '{project_id}' with model '{model}' in region '{region}'")
|
||||||
elif is_ollama:
|
elif is_ollama:
|
||||||
print(" - Ollama Mode: Using local models")
|
print(" - Ollama Mode: Using local models")
|
||||||
|
elif is_azure:
|
||||||
|
print(f" - Azure Mode: Using {base_url}")
|
||||||
elif "ANTHROPIC_BASE_URL" in sdk_env:
|
elif "ANTHROPIC_BASE_URL" in sdk_env:
|
||||||
print(f" - GLM Mode: Using {sdk_env['ANTHROPIC_BASE_URL']}")
|
print(f" - Alternative API: Using {sdk_env['ANTHROPIC_BASE_URL']}")
|
||||||
|
|
||||||
# Create a wrapper for bash_security_hook that passes project_dir via context
|
# Create a wrapper for bash_security_hook that passes project_dir via context
|
||||||
async def bash_hook_with_context(input_data, tool_use_id=None, context=None):
|
async def bash_hook_with_context(input_data, tool_use_id=None, context=None):
|
||||||
|
|||||||
12
registry.py
12
registry.py
@@ -676,6 +676,18 @@ API_PROVIDERS: dict[str, dict[str, Any]] = {
|
|||||||
],
|
],
|
||||||
"default_model": "glm-4.7",
|
"default_model": "glm-4.7",
|
||||||
},
|
},
|
||||||
|
"azure": {
|
||||||
|
"name": "Azure Anthropic (Claude)",
|
||||||
|
"base_url": "",
|
||||||
|
"requires_auth": True,
|
||||||
|
"auth_env_var": "ANTHROPIC_API_KEY",
|
||||||
|
"models": [
|
||||||
|
{"id": "claude-opus-4-6", "name": "Claude Opus"},
|
||||||
|
{"id": "claude-sonnet-4-5", "name": "Claude Sonnet"},
|
||||||
|
{"id": "claude-haiku-4-5", "name": "Claude Haiku"},
|
||||||
|
],
|
||||||
|
"default_model": "claude-opus-4-6",
|
||||||
|
},
|
||||||
"ollama": {
|
"ollama": {
|
||||||
"name": "Ollama (Local)",
|
"name": "Ollama (Local)",
|
||||||
"base_url": "http://localhost:11434",
|
"base_url": "http://localhost:11434",
|
||||||
|
|||||||
@@ -83,8 +83,10 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSaveCustomBaseUrl = () => {
|
const handleSaveCustomBaseUrl = () => {
|
||||||
if (customBaseUrlInput.trim() && !updateSettings.isPending) {
|
const effectiveBaseUrl = customBaseUrlInput || settings?.api_base_url || ''
|
||||||
updateSettings.mutate({ api_base_url: customBaseUrlInput.trim() })
|
if (effectiveBaseUrl.trim() && !updateSettings.isPending) {
|
||||||
|
updateSettings.mutate({ api_base_url: effectiveBaseUrl.trim() })
|
||||||
|
setCustomBaseUrlInput('')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +104,12 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
|||||||
const currentProviderInfo: ProviderInfo | undefined = providers.find(p => p.id === currentProvider)
|
const currentProviderInfo: ProviderInfo | undefined = providers.find(p => p.id === currentProvider)
|
||||||
const isAlternativeProvider = currentProvider !== 'claude'
|
const isAlternativeProvider = currentProvider !== 'claude'
|
||||||
const showAuthField = isAlternativeProvider && currentProviderInfo?.requires_auth
|
const showAuthField = isAlternativeProvider && currentProviderInfo?.requires_auth
|
||||||
const showBaseUrlField = currentProvider === 'custom'
|
const showBaseUrlField = currentProvider === 'custom' || currentProvider === 'azure'
|
||||||
const showCustomModelInput = currentProvider === 'custom' || currentProvider === 'ollama'
|
const showCustomModelInput = currentProvider === 'custom' || currentProvider === 'ollama'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||||
<DialogContent aria-describedby={undefined} className="sm:max-w-sm max-h-[85vh] overflow-y-auto">
|
<DialogContent aria-describedby={undefined} className="sm:max-w-lg max-h-[90vh] overflow-y-auto">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex items-center gap-2">
|
<DialogTitle className="flex items-center gap-2">
|
||||||
Settings
|
Settings
|
||||||
@@ -289,22 +291,38 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
|||||||
{showBaseUrlField && (
|
{showBaseUrlField && (
|
||||||
<div className="space-y-2 pt-1">
|
<div className="space-y-2 pt-1">
|
||||||
<Label className="text-sm">Base URL</Label>
|
<Label className="text-sm">Base URL</Label>
|
||||||
<div className="flex gap-2">
|
{settings.api_base_url && !customBaseUrlInput && (
|
||||||
<input
|
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||||
type="text"
|
<ShieldCheck size={14} className="text-green-500" />
|
||||||
value={customBaseUrlInput || settings.api_base_url || ''}
|
<span className="truncate">{settings.api_base_url}</span>
|
||||||
onChange={(e) => setCustomBaseUrlInput(e.target.value)}
|
<Button
|
||||||
placeholder="https://api.example.com/v1"
|
variant="ghost"
|
||||||
className="flex-1 py-1.5 px-3 text-sm border rounded-md bg-background"
|
size="sm"
|
||||||
/>
|
className="h-auto py-0.5 px-2 text-xs shrink-0"
|
||||||
<Button
|
onClick={() => setCustomBaseUrlInput(settings.api_base_url || ' ')}
|
||||||
size="sm"
|
>
|
||||||
onClick={handleSaveCustomBaseUrl}
|
Change
|
||||||
disabled={!customBaseUrlInput.trim() || isSaving}
|
</Button>
|
||||||
>
|
</div>
|
||||||
Save
|
)}
|
||||||
</Button>
|
{(!settings.api_base_url || customBaseUrlInput) && (
|
||||||
</div>
|
<div className="flex gap-2">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={customBaseUrlInput.trim()}
|
||||||
|
onChange={(e) => setCustomBaseUrlInput(e.target.value)}
|
||||||
|
placeholder={currentProvider === 'azure' ? 'https://your-resource.services.ai.azure.com/anthropic' : 'https://api.example.com/v1'}
|
||||||
|
className="flex-1 py-1.5 px-3 text-sm border rounded-md bg-background"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
onClick={handleSaveCustomBaseUrl}
|
||||||
|
disabled={!customBaseUrlInput.trim() || isSaving}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user