autoforge-ai 0.1.16 → 0.1.17

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.
@@ -176,14 +176,14 @@ Authentication:
176
176
  "--testing-batch-size",
177
177
  type=int,
178
178
  default=3,
179
- help="Number of features per testing batch (1-5, default: 3)",
179
+ help="Number of features per testing batch (1-15, default: 3)",
180
180
  )
181
181
 
182
182
  parser.add_argument(
183
183
  "--batch-size",
184
184
  type=int,
185
185
  default=3,
186
- help="Max features per coding agent batch (1-3, default: 3)",
186
+ help="Max features per coding agent batch (1-15, default: 3)",
187
187
  )
188
188
 
189
189
  return parser.parse_args()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autoforge-ai",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Autonomous coding agent with web UI - build complete apps with AI",
5
5
  "license": "AGPL-3.0",
6
6
  "bin": {
@@ -131,7 +131,7 @@ def _dump_database_state(feature_dicts: list[dict], label: str = ""):
131
131
  MAX_PARALLEL_AGENTS = 5
132
132
  MAX_TOTAL_AGENTS = 10
133
133
  DEFAULT_CONCURRENCY = 3
134
- DEFAULT_TESTING_BATCH_SIZE = 3 # Number of features per testing batch (1-5)
134
+ DEFAULT_TESTING_BATCH_SIZE = 3 # Number of features per testing batch (1-15)
135
135
  POLL_INTERVAL = 5 # seconds between checking for ready features
136
136
  MAX_FEATURE_RETRIES = 3 # Maximum times to retry a failed feature
137
137
  INITIALIZER_TIMEOUT = 1800 # 30 minutes timeout for initializer
@@ -168,7 +168,7 @@ class ParallelOrchestrator:
168
168
  yolo_mode: Whether to run in YOLO mode (skip testing agents entirely)
169
169
  testing_agent_ratio: Number of regression testing agents to maintain (0-3).
170
170
  0 = disabled, 1-3 = maintain that many testing agents running independently.
171
- testing_batch_size: Number of features to include per testing session (1-5).
171
+ testing_batch_size: Number of features to include per testing session (1-15).
172
172
  Each testing agent receives this many features to regression test.
173
173
  on_output: Callback for agent output (feature_id, line)
174
174
  on_status: Callback for agent status changes (feature_id, status)
@@ -178,8 +178,8 @@ class ParallelOrchestrator:
178
178
  self.model = model
179
179
  self.yolo_mode = yolo_mode
180
180
  self.testing_agent_ratio = min(max(testing_agent_ratio, 0), 3) # Clamp 0-3
181
- self.testing_batch_size = min(max(testing_batch_size, 1), 5) # Clamp 1-5
182
- self.batch_size = min(max(batch_size, 1), 3) # Clamp 1-3
181
+ self.testing_batch_size = min(max(testing_batch_size, 1), 15) # Clamp 1-15
182
+ self.batch_size = min(max(batch_size, 1), 15) # Clamp 1-15
183
183
  self.on_output = on_output
184
184
  self.on_status = on_status
185
185
 
@@ -17,11 +17,11 @@ from ..utils.project_helpers import get_project_path as _get_project_path
17
17
  from ..utils.validation import validate_project_name
18
18
 
19
19
 
20
- def _get_settings_defaults() -> tuple[bool, str, int, bool, int]:
20
+ def _get_settings_defaults() -> tuple[bool, str, int, bool, int, int]:
21
21
  """Get defaults from global settings.
22
22
 
23
23
  Returns:
24
- Tuple of (yolo_mode, model, testing_agent_ratio, playwright_headless, batch_size)
24
+ Tuple of (yolo_mode, model, testing_agent_ratio, playwright_headless, batch_size, testing_batch_size)
25
25
  """
26
26
  import sys
27
27
  root = Path(__file__).parent.parent.parent
@@ -47,7 +47,12 @@ def _get_settings_defaults() -> tuple[bool, str, int, bool, int]:
47
47
  except (ValueError, TypeError):
48
48
  batch_size = 3
49
49
 
50
- return yolo_mode, model, testing_agent_ratio, playwright_headless, batch_size
50
+ try:
51
+ testing_batch_size = int(settings.get("testing_batch_size", "3"))
52
+ except (ValueError, TypeError):
53
+ testing_batch_size = 3
54
+
55
+ return yolo_mode, model, testing_agent_ratio, playwright_headless, batch_size, testing_batch_size
51
56
 
52
57
 
53
58
  router = APIRouter(prefix="/api/projects/{project_name}/agent", tags=["agent"])
@@ -96,7 +101,7 @@ async def start_agent(
96
101
  manager = get_project_manager(project_name)
97
102
 
98
103
  # Get defaults from global settings if not provided in request
99
- default_yolo, default_model, default_testing_ratio, playwright_headless, default_batch_size = _get_settings_defaults()
104
+ default_yolo, default_model, default_testing_ratio, playwright_headless, default_batch_size, default_testing_batch_size = _get_settings_defaults()
100
105
 
101
106
  yolo_mode = request.yolo_mode if request.yolo_mode is not None else default_yolo
102
107
  model = request.model if request.model else default_model
@@ -104,6 +109,7 @@ async def start_agent(
104
109
  testing_agent_ratio = request.testing_agent_ratio if request.testing_agent_ratio is not None else default_testing_ratio
105
110
 
106
111
  batch_size = default_batch_size
112
+ testing_batch_size = default_testing_batch_size
107
113
 
108
114
  success, message = await manager.start(
109
115
  yolo_mode=yolo_mode,
@@ -112,6 +118,7 @@ async def start_agent(
112
118
  testing_agent_ratio=testing_agent_ratio,
113
119
  playwright_headless=playwright_headless,
114
120
  batch_size=batch_size,
121
+ testing_batch_size=testing_batch_size,
115
122
  )
116
123
 
117
124
  # Notify scheduler of manual start (to prevent auto-stop during scheduled window)
@@ -113,6 +113,7 @@ async def get_settings():
113
113
  testing_agent_ratio=_parse_int(all_settings.get("testing_agent_ratio"), 1),
114
114
  playwright_headless=_parse_bool(all_settings.get("playwright_headless"), default=True),
115
115
  batch_size=_parse_int(all_settings.get("batch_size"), 3),
116
+ testing_batch_size=_parse_int(all_settings.get("testing_batch_size"), 3),
116
117
  api_provider=api_provider,
117
118
  api_base_url=all_settings.get("api_base_url"),
118
119
  api_has_auth_token=bool(all_settings.get("api_auth_token")),
@@ -138,6 +139,9 @@ async def update_settings(update: SettingsUpdate):
138
139
  if update.batch_size is not None:
139
140
  set_setting("batch_size", str(update.batch_size))
140
141
 
142
+ if update.testing_batch_size is not None:
143
+ set_setting("testing_batch_size", str(update.testing_batch_size))
144
+
141
145
  # API provider settings
142
146
  if update.api_provider is not None:
143
147
  old_provider = get_setting("api_provider", "claude")
@@ -177,6 +181,7 @@ async def update_settings(update: SettingsUpdate):
177
181
  testing_agent_ratio=_parse_int(all_settings.get("testing_agent_ratio"), 1),
178
182
  playwright_headless=_parse_bool(all_settings.get("playwright_headless"), default=True),
179
183
  batch_size=_parse_int(all_settings.get("batch_size"), 3),
184
+ testing_batch_size=_parse_int(all_settings.get("testing_batch_size"), 3),
180
185
  api_provider=api_provider,
181
186
  api_base_url=all_settings.get("api_base_url"),
182
187
  api_has_auth_token=bool(all_settings.get("api_auth_token")),
package/server/schemas.py CHANGED
@@ -444,7 +444,8 @@ class SettingsResponse(BaseModel):
444
444
  ollama_mode: bool = False # True when api_provider is "ollama"
445
445
  testing_agent_ratio: int = 1 # Regression testing agents (0-3)
446
446
  playwright_headless: bool = True
447
- batch_size: int = 3 # Features per coding agent batch (1-3)
447
+ batch_size: int = 3 # Features per coding agent batch (1-15)
448
+ testing_batch_size: int = 3 # Features per testing agent batch (1-15)
448
449
  api_provider: str = "claude"
449
450
  api_base_url: str | None = None
450
451
  api_has_auth_token: bool = False # Never expose actual token
@@ -463,7 +464,8 @@ class SettingsUpdate(BaseModel):
463
464
  model: str | None = None
464
465
  testing_agent_ratio: int | None = None # 0-3
465
466
  playwright_headless: bool | None = None
466
- batch_size: int | None = None # Features per agent batch (1-3)
467
+ batch_size: int | None = None # Features per agent batch (1-15)
468
+ testing_batch_size: int | None = None # Features per testing agent batch (1-15)
467
469
  api_provider: str | None = None
468
470
  api_base_url: str | None = Field(None, max_length=500)
469
471
  api_auth_token: str | None = Field(None, max_length=500) # Write-only, never returned
@@ -500,8 +502,15 @@ class SettingsUpdate(BaseModel):
500
502
  @field_validator('batch_size')
501
503
  @classmethod
502
504
  def validate_batch_size(cls, v: int | None) -> int | None:
503
- if v is not None and (v < 1 or v > 3):
504
- raise ValueError("batch_size must be between 1 and 3")
505
+ if v is not None and (v < 1 or v > 15):
506
+ raise ValueError("batch_size must be between 1 and 15")
507
+ return v
508
+
509
+ @field_validator('testing_batch_size')
510
+ @classmethod
511
+ def validate_testing_batch_size(cls, v: int | None) -> int | None:
512
+ if v is not None and (v < 1 or v > 15):
513
+ raise ValueError("testing_batch_size must be between 1 and 15")
505
514
  return v
506
515
 
507
516
 
@@ -374,6 +374,7 @@ class AgentProcessManager:
374
374
  testing_agent_ratio: int = 1,
375
375
  playwright_headless: bool = True,
376
376
  batch_size: int = 3,
377
+ testing_batch_size: int = 3,
377
378
  ) -> tuple[bool, str]:
378
379
  """
379
380
  Start the agent as a subprocess.
@@ -440,6 +441,9 @@ class AgentProcessManager:
440
441
  # Add --batch-size flag for multi-feature batching
441
442
  cmd.extend(["--batch-size", str(batch_size)])
442
443
 
444
+ # Add --testing-batch-size flag for testing agent batching
445
+ cmd.extend(["--testing-batch-size", str(testing_batch_size)])
446
+
443
447
  # Apply headless setting to .playwright/cli.config.json so playwright-cli
444
448
  # picks it up (the only mechanism it supports for headless control)
445
449
  self._apply_playwright_headless(playwright_headless)