autoforge-ai 0.1.4 → 0.1.6
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/.env.example +17 -41
- package/README.md +5 -29
- package/autonomous_agent_demo.py +11 -1
- package/client.py +9 -12
- package/package.json +1 -1
- package/registry.py +51 -9
- package/server/routers/settings.py +4 -19
- package/server/schemas.py +17 -8
- package/server/services/assistant_chat_session.py +3 -3
- package/server/services/expand_chat_session.py +2 -2
- package/server/services/process_manager.py +1 -1
- package/server/services/spec_chat_session.py +2 -2
- package/start.py +5 -2
- package/ui/dist/assets/{index-CWf0HODJ.js → index-DOPvjpbF.js} +10 -10
- package/ui/dist/index.html +1 -1
package/.env.example
CHANGED
|
@@ -9,11 +9,6 @@
|
|
|
9
9
|
# - webkit: Safari engine
|
|
10
10
|
# - msedge: Microsoft Edge
|
|
11
11
|
# PLAYWRIGHT_BROWSER=firefox
|
|
12
|
-
#
|
|
13
|
-
# PLAYWRIGHT_HEADLESS: Run browser without visible window
|
|
14
|
-
# - true: Browser runs in background, saves CPU (default)
|
|
15
|
-
# - false: Browser opens a visible window (useful for debugging)
|
|
16
|
-
# PLAYWRIGHT_HEADLESS=true
|
|
17
12
|
|
|
18
13
|
# Extra Read Paths (Optional)
|
|
19
14
|
# Comma-separated list of absolute paths for read-only access to external directories.
|
|
@@ -25,56 +20,37 @@
|
|
|
25
20
|
# Google Cloud Vertex AI Configuration (Optional)
|
|
26
21
|
# To use Claude via Vertex AI on Google Cloud Platform, uncomment and set these variables.
|
|
27
22
|
# Requires: gcloud CLI installed and authenticated (run: gcloud auth application-default login)
|
|
28
|
-
# Note: Use @ instead of - in model names (e.g., claude-
|
|
23
|
+
# Note: Use @ instead of - in model names for date-suffixed models (e.g., claude-sonnet-4-5@20250929)
|
|
29
24
|
#
|
|
30
25
|
# CLAUDE_CODE_USE_VERTEX=1
|
|
31
26
|
# CLOUD_ML_REGION=us-east5
|
|
32
27
|
# ANTHROPIC_VERTEX_PROJECT_ID=your-gcp-project-id
|
|
33
|
-
# ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-
|
|
28
|
+
# ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6
|
|
34
29
|
# ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-4-5@20250929
|
|
35
30
|
# ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-3-5-haiku@20241022
|
|
36
31
|
|
|
37
32
|
# ===================
|
|
38
|
-
# Alternative API Providers
|
|
33
|
+
# Alternative API Providers (GLM, Ollama, Kimi, Custom)
|
|
39
34
|
# ===================
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
# UI settings take precedence when api_provider != "claude".
|
|
43
|
-
|
|
44
|
-
# Kimi K2.5 (Moonshot) Configuration (Optional)
|
|
45
|
-
# Get an API key at: https://kimi.com
|
|
46
|
-
#
|
|
47
|
-
# ANTHROPIC_BASE_URL=https://api.kimi.com/coding/
|
|
48
|
-
# ANTHROPIC_API_KEY=your-kimi-api-key
|
|
49
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k2.5
|
|
50
|
-
# ANTHROPIC_DEFAULT_OPUS_MODEL=kimi-k2.5
|
|
51
|
-
# ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.5
|
|
52
|
-
|
|
53
|
-
# GLM/Alternative API Configuration (Optional)
|
|
54
|
-
# To use Zhipu AI's GLM models instead of Claude, uncomment and set these variables.
|
|
55
|
-
# This only affects AutoForge - your global Claude Code settings remain unchanged.
|
|
56
|
-
# Get an API key at: https://z.ai/subscribe
|
|
35
|
+
# Configure via Settings UI (recommended) or set env vars below.
|
|
36
|
+
# When both are set, env vars take precedence.
|
|
57
37
|
#
|
|
38
|
+
# GLM (Zhipu AI):
|
|
58
39
|
# ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
|
|
59
|
-
# ANTHROPIC_AUTH_TOKEN=your-
|
|
60
|
-
# API_TIMEOUT_MS=3000000
|
|
61
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=glm-4.7
|
|
40
|
+
# ANTHROPIC_AUTH_TOKEN=your-glm-api-key
|
|
62
41
|
# ANTHROPIC_DEFAULT_OPUS_MODEL=glm-4.7
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
# Ollama Local Model Configuration (Optional)
|
|
66
|
-
# To use local models via Ollama instead of Claude, uncomment and set these variables.
|
|
67
|
-
# Requires Ollama v0.14.0+ with Anthropic API compatibility.
|
|
68
|
-
# See: https://ollama.com/blog/claude
|
|
42
|
+
# ANTHROPIC_DEFAULT_SONNET_MODEL=glm-4.7
|
|
43
|
+
# ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-4.7
|
|
69
44
|
#
|
|
45
|
+
# Ollama (Local):
|
|
70
46
|
# ANTHROPIC_BASE_URL=http://localhost:11434
|
|
71
|
-
# ANTHROPIC_AUTH_TOKEN=ollama
|
|
72
|
-
# API_TIMEOUT_MS=3000000
|
|
73
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder
|
|
74
47
|
# ANTHROPIC_DEFAULT_OPUS_MODEL=qwen3-coder
|
|
48
|
+
# ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder
|
|
75
49
|
# ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3-coder
|
|
76
50
|
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
# -
|
|
80
|
-
# -
|
|
51
|
+
# Kimi (Moonshot):
|
|
52
|
+
# ANTHROPIC_BASE_URL=https://api.kimi.com/coding/
|
|
53
|
+
# ANTHROPIC_API_KEY=your-kimi-api-key
|
|
54
|
+
# ANTHROPIC_DEFAULT_OPUS_MODEL=kimi-k2.5
|
|
55
|
+
# ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k2.5
|
|
56
|
+
# ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.5
|
package/README.md
CHANGED
|
@@ -326,37 +326,13 @@ When test progress increases, the agent sends:
|
|
|
326
326
|
}
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
###
|
|
329
|
+
### Alternative API Providers (GLM, Ollama, Kimi, Custom)
|
|
330
330
|
|
|
331
|
-
|
|
331
|
+
Alternative providers are configured via the **Settings UI** (gear icon > API Provider). Select your provider, set the base URL, auth token, and model directly in the UI — no `.env` changes needed.
|
|
332
332
|
|
|
333
|
-
|
|
334
|
-
ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
|
|
335
|
-
ANTHROPIC_AUTH_TOKEN=your-zhipu-api-key
|
|
336
|
-
API_TIMEOUT_MS=3000000
|
|
337
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL=glm-4.7
|
|
338
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL=glm-4.7
|
|
339
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-4.5-air
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
This routes AutoForge's API requests through Zhipu's Claude-compatible API, allowing you to use GLM-4.7 and other models. **This only affects AutoForge** - your global Claude Code settings remain unchanged.
|
|
343
|
-
|
|
344
|
-
Get an API key at: https://z.ai/subscribe
|
|
345
|
-
|
|
346
|
-
### Using Ollama Local Models
|
|
347
|
-
|
|
348
|
-
Add these variables to your `.env` file to run agents with local models via Ollama v0.14.0+:
|
|
349
|
-
|
|
350
|
-
```bash
|
|
351
|
-
ANTHROPIC_BASE_URL=http://localhost:11434
|
|
352
|
-
ANTHROPIC_AUTH_TOKEN=ollama
|
|
353
|
-
API_TIMEOUT_MS=3000000
|
|
354
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder
|
|
355
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL=qwen3-coder
|
|
356
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3-coder
|
|
357
|
-
```
|
|
333
|
+
Available providers: **Claude** (default), **GLM** (Zhipu AI), **Ollama** (local models), **Kimi** (Moonshot), **Custom**
|
|
358
334
|
|
|
359
|
-
|
|
335
|
+
For Ollama, install [Ollama v0.14.0+](https://ollama.com), run `ollama serve`, and pull a coding model (e.g., `ollama pull qwen3-coder`). Then select "Ollama" in the Settings UI.
|
|
360
336
|
|
|
361
337
|
### Using Vertex AI
|
|
362
338
|
|
|
@@ -366,7 +342,7 @@ Add these variables to your `.env` file to run agents via Google Cloud Vertex AI
|
|
|
366
342
|
CLAUDE_CODE_USE_VERTEX=1
|
|
367
343
|
CLOUD_ML_REGION=us-east5
|
|
368
344
|
ANTHROPIC_VERTEX_PROJECT_ID=your-gcp-project-id
|
|
369
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-
|
|
345
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6
|
|
370
346
|
ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-4-5@20250929
|
|
371
347
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-3-5-haiku@20241022
|
|
372
348
|
```
|
package/autonomous_agent_demo.py
CHANGED
|
@@ -44,8 +44,10 @@ from dotenv import load_dotenv
|
|
|
44
44
|
# IMPORTANT: Must be called BEFORE importing other modules that read env vars at load time
|
|
45
45
|
load_dotenv()
|
|
46
46
|
|
|
47
|
+
import os
|
|
48
|
+
|
|
47
49
|
from agent import run_autonomous_agent
|
|
48
|
-
from registry import DEFAULT_MODEL, get_project_path
|
|
50
|
+
from registry import DEFAULT_MODEL, get_effective_sdk_env, get_project_path
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
def parse_args() -> argparse.Namespace:
|
|
@@ -195,6 +197,14 @@ def main() -> None:
|
|
|
195
197
|
# Note: Authentication is handled by start.bat/start.sh before this script runs.
|
|
196
198
|
# The Claude SDK auto-detects credentials from ~/.claude/.credentials.json
|
|
197
199
|
|
|
200
|
+
# Apply UI-configured provider settings to this process's environment.
|
|
201
|
+
# This ensures CLI-launched agents respect Settings UI provider config (GLM, Ollama, etc.).
|
|
202
|
+
# Uses setdefault so explicit env vars / .env file take precedence.
|
|
203
|
+
sdk_overrides = get_effective_sdk_env()
|
|
204
|
+
for key, value in sdk_overrides.items():
|
|
205
|
+
if value: # Only set non-empty values (empty values are used to clear conflicts)
|
|
206
|
+
os.environ.setdefault(key, value)
|
|
207
|
+
|
|
198
208
|
# Handle deprecated --parallel flag
|
|
199
209
|
if args.parallel is not None:
|
|
200
210
|
print("WARNING: --parallel is deprecated. Use --concurrency instead.", flush=True)
|
package/client.py
CHANGED
|
@@ -16,7 +16,6 @@ from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
|
|
|
16
16
|
from claude_agent_sdk.types import HookContext, HookInput, HookMatcher, SyncHookJSONOutput
|
|
17
17
|
from dotenv import load_dotenv
|
|
18
18
|
|
|
19
|
-
from env_constants import API_ENV_VARS
|
|
20
19
|
from security import SENSITIVE_DIRECTORIES, bash_security_hook
|
|
21
20
|
|
|
22
21
|
# Load environment variables from .env file if present
|
|
@@ -46,8 +45,9 @@ def convert_model_for_vertex(model: str) -> str:
|
|
|
46
45
|
"""
|
|
47
46
|
Convert model name format for Vertex AI compatibility.
|
|
48
47
|
|
|
49
|
-
Vertex AI uses @ to separate model name from version (e.g., claude-
|
|
50
|
-
while the Anthropic API uses - (e.g., claude-
|
|
48
|
+
Vertex AI uses @ to separate model name from version (e.g., claude-sonnet-4-5@20250929)
|
|
49
|
+
while the Anthropic API uses - (e.g., claude-sonnet-4-5-20250929).
|
|
50
|
+
Models without a date suffix (e.g., claude-opus-4-6) pass through unchanged.
|
|
51
51
|
|
|
52
52
|
Args:
|
|
53
53
|
model: Model name in Anthropic format (with hyphens)
|
|
@@ -61,7 +61,7 @@ def convert_model_for_vertex(model: str) -> str:
|
|
|
61
61
|
return model
|
|
62
62
|
|
|
63
63
|
# Pattern: claude-{name}-{version}-{date} -> claude-{name}-{version}@{date}
|
|
64
|
-
# Example: claude-
|
|
64
|
+
# Example: claude-sonnet-4-5-20250929 -> claude-sonnet-4-5@20250929
|
|
65
65
|
# The date is always 8 digits at the end
|
|
66
66
|
match = re.match(r'^(claude-.+)-(\d{8})$', model)
|
|
67
67
|
if match:
|
|
@@ -449,14 +449,11 @@ def create_client(
|
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
# Build environment overrides for API endpoint configuration
|
|
452
|
-
#
|
|
453
|
-
#
|
|
454
|
-
#
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
value = os.getenv(var)
|
|
458
|
-
if value:
|
|
459
|
-
sdk_env[var] = value
|
|
452
|
+
# Uses get_effective_sdk_env() which reads provider settings from the database,
|
|
453
|
+
# ensuring UI-configured alternative providers (GLM, Ollama, Kimi, Custom) propagate
|
|
454
|
+
# correctly to the Claude CLI subprocess
|
|
455
|
+
from registry import get_effective_sdk_env
|
|
456
|
+
sdk_env = get_effective_sdk_env()
|
|
460
457
|
|
|
461
458
|
# Detect alternative API mode (Ollama, GLM, or Vertex AI)
|
|
462
459
|
base_url = sdk_env.get("ANTHROPIC_BASE_URL", "")
|
package/package.json
CHANGED
package/registry.py
CHANGED
|
@@ -46,10 +46,16 @@ def _migrate_registry_dir() -> None:
|
|
|
46
46
|
# Available models with display names
|
|
47
47
|
# To add a new model: add an entry here with {"id": "model-id", "name": "Display Name"}
|
|
48
48
|
AVAILABLE_MODELS = [
|
|
49
|
-
{"id": "claude-opus-4-
|
|
50
|
-
{"id": "claude-sonnet-4-5-20250929", "name": "Claude Sonnet
|
|
49
|
+
{"id": "claude-opus-4-6", "name": "Claude Opus"},
|
|
50
|
+
{"id": "claude-sonnet-4-5-20250929", "name": "Claude Sonnet"},
|
|
51
51
|
]
|
|
52
52
|
|
|
53
|
+
# Map legacy model IDs to their current replacements.
|
|
54
|
+
# Used by get_all_settings() to auto-migrate stale values on first read after upgrade.
|
|
55
|
+
LEGACY_MODEL_MAP = {
|
|
56
|
+
"claude-opus-4-5-20251101": "claude-opus-4-6",
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
# List of valid model IDs (derived from AVAILABLE_MODELS)
|
|
54
60
|
VALID_MODELS = [m["id"] for m in AVAILABLE_MODELS]
|
|
55
61
|
|
|
@@ -59,7 +65,7 @@ VALID_MODELS = [m["id"] for m in AVAILABLE_MODELS]
|
|
|
59
65
|
_env_default_model = os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL")
|
|
60
66
|
if _env_default_model is not None:
|
|
61
67
|
_env_default_model = _env_default_model.strip()
|
|
62
|
-
DEFAULT_MODEL = _env_default_model or "claude-opus-4-
|
|
68
|
+
DEFAULT_MODEL = _env_default_model or "claude-opus-4-6"
|
|
63
69
|
|
|
64
70
|
# Ensure env-provided DEFAULT_MODEL is in VALID_MODELS for validation consistency
|
|
65
71
|
# (idempotent: only adds if missing, doesn't alter AVAILABLE_MODELS semantics)
|
|
@@ -598,6 +604,9 @@ def get_all_settings() -> dict[str, str]:
|
|
|
598
604
|
"""
|
|
599
605
|
Get all settings as a dictionary.
|
|
600
606
|
|
|
607
|
+
Automatically migrates legacy model IDs (e.g. claude-opus-4-5-20251101 -> claude-opus-4-6)
|
|
608
|
+
on first read after upgrade. This is a one-time silent migration.
|
|
609
|
+
|
|
601
610
|
Returns:
|
|
602
611
|
Dictionary mapping setting keys to values.
|
|
603
612
|
"""
|
|
@@ -606,7 +615,26 @@ def get_all_settings() -> dict[str, str]:
|
|
|
606
615
|
session = SessionLocal()
|
|
607
616
|
try:
|
|
608
617
|
settings = session.query(Settings).all()
|
|
609
|
-
|
|
618
|
+
result = {s.key: s.value for s in settings}
|
|
619
|
+
|
|
620
|
+
# Auto-migrate legacy model IDs
|
|
621
|
+
migrated = False
|
|
622
|
+
for key in ("model", "api_model"):
|
|
623
|
+
old_id = result.get(key)
|
|
624
|
+
if old_id and old_id in LEGACY_MODEL_MAP:
|
|
625
|
+
new_id = LEGACY_MODEL_MAP[old_id]
|
|
626
|
+
setting = session.query(Settings).filter(Settings.key == key).first()
|
|
627
|
+
if setting:
|
|
628
|
+
setting.value = new_id
|
|
629
|
+
setting.updated_at = datetime.now()
|
|
630
|
+
result[key] = new_id
|
|
631
|
+
migrated = True
|
|
632
|
+
logger.info("Migrated setting '%s': %s -> %s", key, old_id, new_id)
|
|
633
|
+
|
|
634
|
+
if migrated:
|
|
635
|
+
session.commit()
|
|
636
|
+
|
|
637
|
+
return result
|
|
610
638
|
finally:
|
|
611
639
|
session.close()
|
|
612
640
|
except Exception as e:
|
|
@@ -624,10 +652,10 @@ API_PROVIDERS: dict[str, dict[str, Any]] = {
|
|
|
624
652
|
"base_url": None,
|
|
625
653
|
"requires_auth": False,
|
|
626
654
|
"models": [
|
|
627
|
-
{"id": "claude-opus-4-
|
|
628
|
-
{"id": "claude-sonnet-4-5-20250929", "name": "Claude Sonnet
|
|
655
|
+
{"id": "claude-opus-4-6", "name": "Claude Opus"},
|
|
656
|
+
{"id": "claude-sonnet-4-5-20250929", "name": "Claude Sonnet"},
|
|
629
657
|
],
|
|
630
|
-
"default_model": "claude-opus-4-
|
|
658
|
+
"default_model": "claude-opus-4-6",
|
|
631
659
|
},
|
|
632
660
|
"kimi": {
|
|
633
661
|
"name": "Kimi K2.5 (Moonshot)",
|
|
@@ -703,7 +731,22 @@ def get_effective_sdk_env() -> dict[str, str]:
|
|
|
703
731
|
sdk_env[var] = value
|
|
704
732
|
return sdk_env
|
|
705
733
|
|
|
706
|
-
sdk_env = {}
|
|
734
|
+
sdk_env: dict[str, str] = {}
|
|
735
|
+
|
|
736
|
+
# Explicitly clear credentials that could leak from the server process env.
|
|
737
|
+
# For providers using ANTHROPIC_AUTH_TOKEN (GLM, Custom), clear ANTHROPIC_API_KEY.
|
|
738
|
+
# For providers using ANTHROPIC_API_KEY (Kimi), clear ANTHROPIC_AUTH_TOKEN.
|
|
739
|
+
# This prevents the Claude CLI from using the wrong credentials.
|
|
740
|
+
auth_env_var = provider.get("auth_env_var", "ANTHROPIC_AUTH_TOKEN")
|
|
741
|
+
if auth_env_var == "ANTHROPIC_AUTH_TOKEN":
|
|
742
|
+
sdk_env["ANTHROPIC_API_KEY"] = ""
|
|
743
|
+
elif auth_env_var == "ANTHROPIC_API_KEY":
|
|
744
|
+
sdk_env["ANTHROPIC_AUTH_TOKEN"] = ""
|
|
745
|
+
|
|
746
|
+
# Clear Vertex AI vars when using non-Vertex alternative providers
|
|
747
|
+
sdk_env["CLAUDE_CODE_USE_VERTEX"] = ""
|
|
748
|
+
sdk_env["CLOUD_ML_REGION"] = ""
|
|
749
|
+
sdk_env["ANTHROPIC_VERTEX_PROJECT_ID"] = ""
|
|
707
750
|
|
|
708
751
|
# Base URL
|
|
709
752
|
base_url = all_settings.get("api_base_url") or provider.get("base_url")
|
|
@@ -713,7 +756,6 @@ def get_effective_sdk_env() -> dict[str, str]:
|
|
|
713
756
|
# Auth token
|
|
714
757
|
auth_token = all_settings.get("api_auth_token")
|
|
715
758
|
if auth_token:
|
|
716
|
-
auth_env_var = provider.get("auth_env_var", "ANTHROPIC_AUTH_TOKEN")
|
|
717
759
|
sdk_env[auth_env_var] = auth_token
|
|
718
760
|
|
|
719
761
|
# Model - set all three tier overrides to the same model
|
|
@@ -7,7 +7,6 @@ Settings are stored in the registry database and shared across all projects.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import mimetypes
|
|
10
|
-
import os
|
|
11
10
|
import sys
|
|
12
11
|
|
|
13
12
|
from fastapi import APIRouter
|
|
@@ -39,19 +38,6 @@ def _parse_yolo_mode(value: str | None) -> bool:
|
|
|
39
38
|
return (value or "false").lower() == "true"
|
|
40
39
|
|
|
41
40
|
|
|
42
|
-
def _is_glm_mode() -> bool:
|
|
43
|
-
"""Check if GLM API is configured via environment variables."""
|
|
44
|
-
base_url = os.getenv("ANTHROPIC_BASE_URL", "")
|
|
45
|
-
# GLM mode is when ANTHROPIC_BASE_URL is set but NOT pointing to Ollama
|
|
46
|
-
return bool(base_url) and not _is_ollama_mode()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _is_ollama_mode() -> bool:
|
|
50
|
-
"""Check if Ollama API is configured via environment variables."""
|
|
51
|
-
base_url = os.getenv("ANTHROPIC_BASE_URL", "")
|
|
52
|
-
return "localhost:11434" in base_url or "127.0.0.1:11434" in base_url
|
|
53
|
-
|
|
54
|
-
|
|
55
41
|
@router.get("/providers", response_model=ProvidersResponse)
|
|
56
42
|
async def get_available_providers():
|
|
57
43
|
"""Get list of available API providers."""
|
|
@@ -116,9 +102,8 @@ async def get_settings():
|
|
|
116
102
|
|
|
117
103
|
api_provider = all_settings.get("api_provider", "claude")
|
|
118
104
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
ollama_mode = api_provider == "ollama" or _is_ollama_mode()
|
|
105
|
+
glm_mode = api_provider == "glm"
|
|
106
|
+
ollama_mode = api_provider == "ollama"
|
|
122
107
|
|
|
123
108
|
return SettingsResponse(
|
|
124
109
|
yolo_mode=_parse_yolo_mode(all_settings.get("yolo_mode")),
|
|
@@ -181,8 +166,8 @@ async def update_settings(update: SettingsUpdate):
|
|
|
181
166
|
# Return updated settings
|
|
182
167
|
all_settings = get_all_settings()
|
|
183
168
|
api_provider = all_settings.get("api_provider", "claude")
|
|
184
|
-
glm_mode = api_provider == "glm"
|
|
185
|
-
ollama_mode = api_provider == "ollama"
|
|
169
|
+
glm_mode = api_provider == "glm"
|
|
170
|
+
ollama_mode = api_provider == "ollama"
|
|
186
171
|
|
|
187
172
|
return SettingsResponse(
|
|
188
173
|
yolo_mode=_parse_yolo_mode(all_settings.get("yolo_mode")),
|
package/server/schemas.py
CHANGED
|
@@ -190,9 +190,12 @@ class AgentStartRequest(BaseModel):
|
|
|
190
190
|
@field_validator('model')
|
|
191
191
|
@classmethod
|
|
192
192
|
def validate_model(cls, v: str | None) -> str | None:
|
|
193
|
-
"""Validate model is in the allowed list."""
|
|
193
|
+
"""Validate model is in the allowed list (Claude) or allow any model for alternative providers."""
|
|
194
194
|
if v is not None and v not in VALID_MODELS:
|
|
195
|
-
|
|
195
|
+
from registry import get_all_settings
|
|
196
|
+
settings = get_all_settings()
|
|
197
|
+
if settings.get("api_provider", "claude") == "claude":
|
|
198
|
+
raise ValueError(f"Invalid model. Must be one of: {VALID_MODELS}")
|
|
196
199
|
return v
|
|
197
200
|
|
|
198
201
|
@field_validator('max_concurrency')
|
|
@@ -411,8 +414,8 @@ class SettingsResponse(BaseModel):
|
|
|
411
414
|
"""Response schema for global settings."""
|
|
412
415
|
yolo_mode: bool = False
|
|
413
416
|
model: str = DEFAULT_MODEL
|
|
414
|
-
glm_mode: bool = False # True
|
|
415
|
-
ollama_mode: bool = False # True
|
|
417
|
+
glm_mode: bool = False # True when api_provider is "glm"
|
|
418
|
+
ollama_mode: bool = False # True when api_provider is "ollama"
|
|
416
419
|
testing_agent_ratio: int = 1 # Regression testing agents (0-3)
|
|
417
420
|
playwright_headless: bool = True
|
|
418
421
|
batch_size: int = 3 # Features per coding agent batch (1-3)
|
|
@@ -571,9 +574,12 @@ class ScheduleCreate(BaseModel):
|
|
|
571
574
|
@field_validator('model')
|
|
572
575
|
@classmethod
|
|
573
576
|
def validate_model(cls, v: str | None) -> str | None:
|
|
574
|
-
"""Validate model is in the allowed list."""
|
|
577
|
+
"""Validate model is in the allowed list (Claude) or allow any model for alternative providers."""
|
|
575
578
|
if v is not None and v not in VALID_MODELS:
|
|
576
|
-
|
|
579
|
+
from registry import get_all_settings
|
|
580
|
+
settings = get_all_settings()
|
|
581
|
+
if settings.get("api_provider", "claude") == "claude":
|
|
582
|
+
raise ValueError(f"Invalid model. Must be one of: {VALID_MODELS}")
|
|
577
583
|
return v
|
|
578
584
|
|
|
579
585
|
|
|
@@ -593,9 +599,12 @@ class ScheduleUpdate(BaseModel):
|
|
|
593
599
|
@field_validator('model')
|
|
594
600
|
@classmethod
|
|
595
601
|
def validate_model(cls, v: str | None) -> str | None:
|
|
596
|
-
"""Validate model is in the allowed list."""
|
|
602
|
+
"""Validate model is in the allowed list (Claude) or allow any model for alternative providers."""
|
|
597
603
|
if v is not None and v not in VALID_MODELS:
|
|
598
|
-
|
|
604
|
+
from registry import get_all_settings
|
|
605
|
+
settings = get_all_settings()
|
|
606
|
+
if settings.get("api_provider", "claude") == "claude":
|
|
607
|
+
raise ValueError(f"Invalid model. Must be one of: {VALID_MODELS}")
|
|
599
608
|
return v
|
|
600
609
|
|
|
601
610
|
|
|
@@ -157,7 +157,7 @@ class AssistantChatSession:
|
|
|
157
157
|
"""
|
|
158
158
|
Manages a read-only assistant conversation for a project.
|
|
159
159
|
|
|
160
|
-
Uses Claude Opus
|
|
160
|
+
Uses Claude Opus with only read-only tools enabled.
|
|
161
161
|
Persists conversation history to SQLite.
|
|
162
162
|
"""
|
|
163
163
|
|
|
@@ -258,11 +258,11 @@ class AssistantChatSession:
|
|
|
258
258
|
system_cli = shutil.which("claude")
|
|
259
259
|
|
|
260
260
|
# Build environment overrides for API configuration
|
|
261
|
-
from registry import get_effective_sdk_env
|
|
261
|
+
from registry import DEFAULT_MODEL, get_effective_sdk_env
|
|
262
262
|
sdk_env = get_effective_sdk_env()
|
|
263
263
|
|
|
264
264
|
# Determine model from SDK env (provider-aware) or fallback to env/default
|
|
265
|
-
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
265
|
+
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL", DEFAULT_MODEL)
|
|
266
266
|
|
|
267
267
|
try:
|
|
268
268
|
logger.info("Creating ClaudeSDKClient...")
|
|
@@ -154,11 +154,11 @@ class ExpandChatSession:
|
|
|
154
154
|
system_prompt = skill_content.replace("$ARGUMENTS", project_path)
|
|
155
155
|
|
|
156
156
|
# Build environment overrides for API configuration
|
|
157
|
-
from registry import get_effective_sdk_env
|
|
157
|
+
from registry import DEFAULT_MODEL, get_effective_sdk_env
|
|
158
158
|
sdk_env = get_effective_sdk_env()
|
|
159
159
|
|
|
160
160
|
# Determine model from SDK env (provider-aware) or fallback to env/default
|
|
161
|
-
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
161
|
+
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL", DEFAULT_MODEL)
|
|
162
162
|
|
|
163
163
|
# Build MCP servers config for feature creation
|
|
164
164
|
mcp_servers = {
|
|
@@ -346,7 +346,7 @@ class AgentProcessManager:
|
|
|
346
346
|
|
|
347
347
|
Args:
|
|
348
348
|
yolo_mode: If True, run in YOLO mode (skip testing agents)
|
|
349
|
-
model: Model to use (e.g., claude-opus-4-
|
|
349
|
+
model: Model to use (e.g., claude-opus-4-6)
|
|
350
350
|
parallel_mode: DEPRECATED - ignored, always uses unified orchestrator
|
|
351
351
|
max_concurrency: Max concurrent coding agents (1-5, default 1)
|
|
352
352
|
testing_agent_ratio: Number of regression testing agents (0-3, default 1)
|
|
@@ -140,11 +140,11 @@ class SpecChatSession:
|
|
|
140
140
|
system_cli = shutil.which("claude")
|
|
141
141
|
|
|
142
142
|
# Build environment overrides for API configuration
|
|
143
|
-
from registry import get_effective_sdk_env
|
|
143
|
+
from registry import DEFAULT_MODEL, get_effective_sdk_env
|
|
144
144
|
sdk_env = get_effective_sdk_env()
|
|
145
145
|
|
|
146
146
|
# Determine model from SDK env (provider-aware) or fallback to env/default
|
|
147
|
-
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
147
|
+
model = sdk_env.get("ANTHROPIC_DEFAULT_OPUS_MODEL") or os.getenv("ANTHROPIC_DEFAULT_OPUS_MODEL", DEFAULT_MODEL)
|
|
148
148
|
|
|
149
149
|
try:
|
|
150
150
|
self.client = ClaudeSDKClient(
|
package/start.py
CHANGED
|
@@ -390,8 +390,11 @@ def run_agent(project_name: str, project_dir: Path) -> None:
|
|
|
390
390
|
print(f"Location: {project_dir}")
|
|
391
391
|
print("-" * 50)
|
|
392
392
|
|
|
393
|
-
# Build the command - pass absolute path
|
|
394
|
-
|
|
393
|
+
# Build the command - pass absolute path and model from settings
|
|
394
|
+
from registry import DEFAULT_MODEL, get_all_settings
|
|
395
|
+
settings = get_all_settings()
|
|
396
|
+
model = settings.get("api_model") or settings.get("model", DEFAULT_MODEL)
|
|
397
|
+
cmd = [sys.executable, "autonomous_agent_demo.py", "--project-dir", str(project_dir.resolve()), "--model", model]
|
|
395
398
|
|
|
396
399
|
# Run the agent with stderr capture to detect auth errors
|
|
397
400
|
# stdout goes directly to terminal for real-time output
|