claude-dev-env 8.46.0 → 8.46.1
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/docs/account-broker.md
CHANGED
|
@@ -27,6 +27,7 @@ The broker stores cached meters, spent marks, and Claude session bindings in one
|
|
|
27
27
|
| `0` | `choose` or `check` found an account, or the job exited successfully. |
|
|
28
28
|
| `3` | No account clears its floor. The decision includes `resets_at`. |
|
|
29
29
|
| `4` | A Claude job stopped with `advisor_blocked`. |
|
|
30
|
+
| `127` | A Codex job timed out, or its command could not start while no Codex roster is configured. |
|
|
30
31
|
| Other command code | `run` returns the command's exit code after a served response. |
|
|
31
32
|
|
|
32
33
|
`run` writes a JSON report with `product`, `command`, `events`, and `final_decision`. A wait report has `final_decision.action` equal to `wait` and a UTC `final_decision.resets_at`.
|
package/package.json
CHANGED
|
@@ -263,7 +263,8 @@ def _attempt_once(context: _RunContext, decision: Decision) -> JobOutcome | None
|
|
|
263
263
|
_record_spent_attempt(context, account, status, COMMAND_MISSING_EXIT_CODE)
|
|
264
264
|
if isinstance(error, subprocess.TimeoutExpired) or not context.all_readings:
|
|
265
265
|
context.report.final_decision = decision
|
|
266
|
-
|
|
266
|
+
final_status = "advisor_blocked" if context.product is Product.CLAUDE else status
|
|
267
|
+
return JobOutcome(COMMAND_MISSING_EXIT_CODE, "", str(error), account.name, tuple(context.all_attempts), final_status, None, None)
|
|
267
268
|
return None
|
|
268
269
|
combined = f"{completion.stdout}{completion.stderr}".casefold()
|
|
269
270
|
is_limited = completion.returncode != 0 and any(
|
|
@@ -435,13 +435,44 @@ def test_should_stop_after_timeout_without_running_job_again(
|
|
|
435
435
|
|
|
436
436
|
assert invoked_homes == ["first"]
|
|
437
437
|
assert outcome.attempts == (("first", "timeout"),)
|
|
438
|
-
assert outcome.status == "
|
|
438
|
+
assert outcome.status == "timeout"
|
|
439
439
|
assert outcome.account_name == "first"
|
|
440
440
|
assert report.final_decision.account.name == "first"
|
|
441
441
|
assert account_broker.main(("choose", "--product", "codex")) == 0
|
|
442
442
|
assert json.loads(capsys.readouterr().out)["decision"]["account"] == "first"
|
|
443
443
|
|
|
444
444
|
|
|
445
|
+
@pytest.mark.parametrize(
|
|
446
|
+
("product", "roster_names", "start_error", "expected_code"),
|
|
447
|
+
(
|
|
448
|
+
(Product.CLAUDE, ("first",), subprocess.TimeoutExpired("job", 1), 4),
|
|
449
|
+
(Product.CODEX, ("first",), subprocess.TimeoutExpired("job", 1), 127),
|
|
450
|
+
(Product.CODEX, (), OSError("missing command"), 127),
|
|
451
|
+
),
|
|
452
|
+
)
|
|
453
|
+
def test_should_exit_four_only_for_a_blocked_claude_job(
|
|
454
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
455
|
+
tmp_path: Path,
|
|
456
|
+
product: Product,
|
|
457
|
+
roster_names: tuple[str, ...],
|
|
458
|
+
start_error: Exception,
|
|
459
|
+
expected_code: int,
|
|
460
|
+
) -> None:
|
|
461
|
+
accounts = tuple(_account(each_name, product) for each_name in roster_names)
|
|
462
|
+
monkeypatch.setitem(account_broker.all_product_adapters, product, _adapter(accounts, {
|
|
463
|
+
each_name: _meters(80, 80) for each_name in roster_names
|
|
464
|
+
}))
|
|
465
|
+
monkeypatch.setattr(account_broker.sys, "stdin", io.TextIOWrapper(io.BytesIO(b""), encoding="utf-8"))
|
|
466
|
+
|
|
467
|
+
def runner(argv: object, **options: object) -> subprocess.CompletedProcess[str]:
|
|
468
|
+
raise start_error
|
|
469
|
+
|
|
470
|
+
with account_broker.override_subprocess_runner(runner):
|
|
471
|
+
code = account_broker.main(("run", "--product", product.value, "--report", str(tmp_path / "report.json"), "--", "job"))
|
|
472
|
+
|
|
473
|
+
assert code == expected_code
|
|
474
|
+
|
|
475
|
+
|
|
445
476
|
def test_should_keep_usage_limited_account_spent_for_later_choices(
|
|
446
477
|
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
|
447
478
|
) -> None:
|