mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
chore(models): move the opus alias to claude-opus-5
Claude Opus 5 released today — same $5/$25 sticker, 1M context; Opus 4.8 moves to legacy. The pricing table gains a dedicated claude-opus-5 fragment (the claude-opus-4 substring doesn't cover it, so without the row the fleet's Opus usage would silently cost-track as $0 — exactly what test_opus_is_priced now guards).
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **The `opus` alias upgrades from Claude Opus 4.6 to Claude Opus 4.8.** `MODEL_MAP["opus"]` now resolves to `claude-opus-4-8` — the newest Opus tier, at the same price as 4.6 — so every Opus-routed role (PR reviewer, Auditor, Board, CEO, Intake, Secretary) rides it at next spawn. Pricing already covered the id via the `claude-opus-4` fragment; a new `test_opus_is_priced` guard keeps the alias from ever pointing at an unpriced model.
|
- **The `opus` alias upgrades from Claude Opus 4.6 to Claude Opus 5.** `MODEL_MAP["opus"]` now resolves to `claude-opus-5` — the newest Opus tier, released 2026-07-25 at the same $5/$25 price — so every Opus-routed role (PR reviewer, Auditor, Board, CEO, Intake, Secretary) rides it at next spawn. The pricing table gains a dedicated `claude-opus-5` fragment (the `claude-opus-4` substring doesn't cover it — without the row, Opus fleet usage would silently cost-track as $0), and a new `test_opus_is_priced` guard keeps the alias from ever pointing at an unpriced model.
|
||||||
- **Panel dialogs converge on one shape: one disclosure primitive, DialogFooter everywhere, three dialog widths.** `collapsible-section` becomes the single sectioned-disclosure primitive — task dialogs' raw `Collapsible` and create-project's ad-hoc `showAdvanced` both move onto it; every hand-rolled dialog footer becomes `DialogFooter`; dialog widths collapse from ten ad-hoc classes to three named sizes, with deliberate outliers annotated. No behavioral change.
|
- **Panel dialogs converge on one shape: one disclosure primitive, DialogFooter everywhere, three dialog widths.** `collapsible-section` becomes the single sectioned-disclosure primitive — task dialogs' raw `Collapsible` and create-project's ad-hoc `showAdvanced` both move onto it; every hand-rolled dialog footer becomes `DialogFooter`; dialog widths collapse from ten ad-hoc classes to three named sizes, with deliberate outliers annotated. No behavioral change.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ pnpm test
|
|||||||
| RAG Engine | in-house (asyncpg + pgvector, hybrid retrieval) |
|
| RAG Engine | in-house (asyncpg + pgvector, hybrid retrieval) |
|
||||||
| Cache/Queue | Redis |
|
| Cache/Queue | Redis |
|
||||||
| Container Runtime | Docker + Docker Compose |
|
| Container Runtime | Docker + Docker Compose |
|
||||||
| Cloud LLM | Claude API (claude-opus-4-8) + xAI Grok (official `grok` CLI, SuperGrok subscription) + OpenAI (official `codex` CLI, ChatGPT subscription) + Google Gemini (official `gemini` CLI, OAuth login) |
|
| Cloud LLM | Claude API (claude-opus-5) + xAI Grok (official `grok` CLI, SuperGrok subscription) + OpenAI (official `codex` CLI, ChatGPT subscription) + Google Gemini (official `gemini` CLI, OAuth login) |
|
||||||
| Local LLM | Ollama (glm-5.2:cloud for RAG/hybrid retrieval) |
|
| Local LLM | Ollama (glm-5.2:cloud for RAG/hybrid retrieval) |
|
||||||
| Embeddings | qwen3-embedding:0.6b (1024 dim) |
|
| Embeddings | qwen3-embedding:0.6b (1024 dim) |
|
||||||
| Frontend | Next.js 16 + TypeScript + Tailwind + Radix UI (in `panel/`) |
|
| Frontend | Next.js 16 + TypeScript + Tailwind + Radix UI (in `panel/`) |
|
||||||
|
|||||||
@@ -5134,7 +5134,7 @@ The Pydantic/dataclass domain surface of RoboCo — the typed contract the API,
|
|||||||
| `OrchestratorAgentState` | StrEnum | runtime.py:15 | offline/starting/active/waiting_short/waiting_long/idle/stopping |
|
| `OrchestratorAgentState` | StrEnum | runtime.py:15 | offline/starting/active/waiting_short/waiting_long/idle/stopping |
|
||||||
| `AgentInstance` | dataclass | runtime.py:70 | Running Claude Code container record + `usage_session_id` |
|
| `AgentInstance` | dataclass | runtime.py:70 | Running Claude Code container record + `usage_session_id` |
|
||||||
| `SpawnGitContext` | dataclass | runtime.py:28 | Git context for spawn (project_slug, branch, `task_short_id` for worktree) |
|
| `SpawnGitContext` | dataclass | runtime.py:28 | Git context for spawn (project_slug, branch, `task_short_id` for worktree) |
|
||||||
| `MODEL_MAP` | dict | runtime.py:106 | short-name→full Claude id (opus→claude-opus-4-8, sonnet→claude-sonnet-5, haiku→…) |
|
| `MODEL_MAP` | dict | runtime.py:106 | short-name→full Claude id (opus→claude-opus-5, sonnet→claude-sonnet-5, haiku→…) |
|
||||||
| `ROLE_MODEL_MAP` | dict | runtime.py:120 | per-role default tier: developer/qa/documenter/cell_pm/main_pm→sonnet, pr_reviewer/auditor/board/ceo/prompter/secretary→opus. **Haiku retired from every delivery-lifecycle role (#680, 2026-07-24)**: qa/documenter moved haiku→sonnet — haiku can't reliably emit the structured envelopes the lifecycle runs on (`pass_review`'s per-AC `criteria_verified`, `delegate`'s `covers_parent_criteria`, the findings ledger), so a haiku QA/PM claims, gets validation-rejected, idles, respawns, and loops without progress. A structured-verb capability floor (`_below_capability_floor`/`_floor_below_capability`, `roboco/services/llm.py`) additionally upgrades ANY below-floor Anthropic assignment to sonnet at resolution time — from a pin, a plain ROLE row, or a future map edit — so the floor can't be silently reintroduced. Non-Anthropic providers are untouched (an Anthropic-tier floor, not a provider policy). |
|
| `ROLE_MODEL_MAP` | dict | runtime.py:120 | per-role default tier: developer/qa/documenter/cell_pm/main_pm→sonnet, pr_reviewer/auditor/board/ceo/prompter/secretary→opus. **Haiku retired from every delivery-lifecycle role (#680, 2026-07-24)**: qa/documenter moved haiku→sonnet — haiku can't reliably emit the structured envelopes the lifecycle runs on (`pass_review`'s per-AC `criteria_verified`, `delegate`'s `covers_parent_criteria`, the findings ledger), so a haiku QA/PM claims, gets validation-rejected, idles, respawns, and loops without progress. A structured-verb capability floor (`_below_capability_floor`/`_floor_below_capability`, `roboco/services/llm.py`) additionally upgrades ANY below-floor Anthropic assignment to sonnet at resolution time — from a pin, a plain ROLE row, or a future map edit — so the floor can't be silently reintroduced. Non-Anthropic providers are untouched (an Anthropic-tier floor, not a provider policy). |
|
||||||
| `ROLE_EFFORT_MAP` | dict | runtime.py | per-role `CLAUDE_CODE_EFFORT_LEVEL` override injected at spawn; **empty/inert by default** (opt-in per role after verifying the level moves usage) |
|
| `ROLE_EFFORT_MAP` | dict | runtime.py | per-role `CLAUDE_CODE_EFFORT_LEVEL` override injected at spawn; **empty/inert by default** (opt-in per role after verifying the level moves usage) |
|
||||||
| `MODEL_CATALOG` | tuple | llm_catalog.py:67 | Settings-dropdown source of truth; Anthropic entries derived from `MODEL_MAP` |
|
| `MODEL_CATALOG` | tuple | llm_catalog.py:67 | Settings-dropdown source of truth; Anthropic entries derived from `MODEL_MAP` |
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ The Pydantic/dataclass domain surface of RoboCo — the typed contract the API,
|
|||||||
| `OrchestratorAgentState` | StrEnum | runtime.py:15 | offline/starting/active/waiting_short/waiting_long/idle/stopping |
|
| `OrchestratorAgentState` | StrEnum | runtime.py:15 | offline/starting/active/waiting_short/waiting_long/idle/stopping |
|
||||||
| `AgentInstance` | dataclass | runtime.py:70 | Running Claude Code container record + `usage_session_id` |
|
| `AgentInstance` | dataclass | runtime.py:70 | Running Claude Code container record + `usage_session_id` |
|
||||||
| `SpawnGitContext` | dataclass | runtime.py:28 | Git context for spawn (project_slug, branch, `task_short_id` for worktree) |
|
| `SpawnGitContext` | dataclass | runtime.py:28 | Git context for spawn (project_slug, branch, `task_short_id` for worktree) |
|
||||||
| `MODEL_MAP` | dict | runtime.py:106 | short-name→full Claude id (opus→claude-opus-4-8, sonnet→claude-sonnet-5, haiku→…) |
|
| `MODEL_MAP` | dict | runtime.py:106 | short-name→full Claude id (opus→claude-opus-5, sonnet→claude-sonnet-5, haiku→…) |
|
||||||
| `ROLE_MODEL_MAP` | dict | runtime.py:120 | per-role default tier: developer/qa/documenter/cell_pm/main_pm→sonnet, pr_reviewer/auditor/board/ceo/prompter/secretary→opus. **Haiku retired from every delivery-lifecycle role (#680, 2026-07-24)**: qa/documenter moved haiku→sonnet — haiku can't reliably emit the structured envelopes the lifecycle runs on (`pass_review`'s per-AC `criteria_verified`, `delegate`'s `covers_parent_criteria`, the findings ledger), so a haiku QA/PM claims, gets validation-rejected, idles, respawns, and loops without progress. A structured-verb capability floor (`_below_capability_floor`/`_floor_below_capability`, `roboco/services/llm.py`) additionally upgrades ANY below-floor Anthropic assignment to sonnet at resolution time — from a pin, a plain ROLE row, or a future map edit — so the floor can't be silently reintroduced. Non-Anthropic providers are untouched (an Anthropic-tier floor, not a provider policy). |
|
| `ROLE_MODEL_MAP` | dict | runtime.py:120 | per-role default tier: developer/qa/documenter/cell_pm/main_pm→sonnet, pr_reviewer/auditor/board/ceo/prompter/secretary→opus. **Haiku retired from every delivery-lifecycle role (#680, 2026-07-24)**: qa/documenter moved haiku→sonnet — haiku can't reliably emit the structured envelopes the lifecycle runs on (`pass_review`'s per-AC `criteria_verified`, `delegate`'s `covers_parent_criteria`, the findings ledger), so a haiku QA/PM claims, gets validation-rejected, idles, respawns, and loops without progress. A structured-verb capability floor (`_below_capability_floor`/`_floor_below_capability`, `roboco/services/llm.py`) additionally upgrades ANY below-floor Anthropic assignment to sonnet at resolution time — from a pin, a plain ROLE row, or a future map edit — so the floor can't be silently reintroduced. Non-Anthropic providers are untouched (an Anthropic-tier floor, not a provider policy). |
|
||||||
| `ROLE_EFFORT_MAP` | dict | runtime.py | per-role `CLAUDE_CODE_EFFORT_LEVEL` override injected at spawn; **empty/inert by default** (opt-in per role after verifying the level moves usage) |
|
| `ROLE_EFFORT_MAP` | dict | runtime.py | per-role `CLAUDE_CODE_EFFORT_LEVEL` override injected at spawn; **empty/inert by default** (opt-in per role after verifying the level moves usage) |
|
||||||
| `MODEL_CATALOG` | tuple | llm_catalog.py:67 | Settings-dropdown source of truth; Anthropic entries derived from `MODEL_MAP` |
|
| `MODEL_CATALOG` | tuple | llm_catalog.py:67 | Settings-dropdown source of truth; Anthropic entries derived from `MODEL_MAP` |
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ const {
|
|||||||
} = vi.hoisted(() => ({
|
} = vi.hoisted(() => ({
|
||||||
catalog: vi.fn(async () => [
|
catalog: vi.fn(async () => [
|
||||||
{
|
{
|
||||||
model_name: "claude-opus-4-8",
|
model_name: "claude-opus-5",
|
||||||
provider_type: "anthropic",
|
provider_type: "anthropic",
|
||||||
display_name: "Claude Opus 4.8",
|
display_name: "Claude Opus 5",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model_name: "grok-build-0.1",
|
model_name: "grok-build-0.1",
|
||||||
@@ -719,14 +719,14 @@ describe("AIRoutingCard", () => {
|
|||||||
|
|
||||||
const devLow = screen.getByTestId("complexity-select-developer-low");
|
const devLow = screen.getByTestId("complexity-select-developer-low");
|
||||||
fireEvent.click(
|
fireEvent.click(
|
||||||
await within(devLow).findByRole("option", { name: "Claude Opus 4.8" }),
|
await within(devLow).findByRole("option", { name: "Claude Opus 5" }),
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(setComplexityOverride).toHaveBeenCalledWith({
|
expect(setComplexityOverride).toHaveBeenCalledWith({
|
||||||
role: "developer",
|
role: "developer",
|
||||||
complexity: "low",
|
complexity: "low",
|
||||||
model_name: "claude-opus-4-8",
|
model_name: "claude-opus-5",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -764,7 +764,7 @@ describe("AIRoutingCard", () => {
|
|||||||
|
|
||||||
const devLow = screen.getByTestId("complexity-select-developer-low");
|
const devLow = screen.getByTestId("complexity-select-developer-low");
|
||||||
fireEvent.click(
|
fireEvent.click(
|
||||||
await within(devLow).findByRole("option", { name: "Claude Opus 4.8" }),
|
await within(devLow).findByRole("option", { name: "Claude Opus 5" }),
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitFor(() => expect(setComplexityOverride).toHaveBeenCalled());
|
await waitFor(() => expect(setComplexityOverride).toHaveBeenCalled());
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export const DEMO_TEAM_USAGE: TeamUsageRow[] = (
|
|||||||
|
|
||||||
export const DEMO_MODEL_USAGE: ModelUsageSlice[] = (
|
export const DEMO_MODEL_USAGE: ModelUsageSlice[] = (
|
||||||
[
|
[
|
||||||
["claude-opus-4-8", 42.1],
|
["claude-opus-5", 42.1],
|
||||||
["glm-5.2:cloud", 16.8],
|
["glm-5.2:cloud", 16.8],
|
||||||
["grok-build", 7.64],
|
["grok-build", 7.64],
|
||||||
] as Array<[string, number]>
|
] as Array<[string, number]>
|
||||||
|
|||||||
@@ -57,11 +57,14 @@ _ANTHROPIC_FRAGMENTS = ("claude", "opus", "sonnet", "haiku")
|
|||||||
# Cache read is charged at ~10 % of the input price.
|
# Cache read is charged at ~10 % of the input price.
|
||||||
# Cache write is charged at ~25 % of the input price.
|
# Cache write is charged at ~25 % of the input price.
|
||||||
#
|
#
|
||||||
# Match on *substring* of model name so "claude-opus-4-8" and "opus" both
|
# Match on *substring* of model name so "claude-opus-5" and "opus" both
|
||||||
# resolve to the same tier.
|
# resolve to the same tier.
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
_PRICING: list[tuple[str, float, float, float, float]] = [
|
_PRICING: list[tuple[str, float, float, float, float]] = [
|
||||||
# (fragment, input/1M, output/1M, cache_read/1M, cache_write/1M)
|
# (fragment, input/1M, output/1M, cache_read/1M, cache_write/1M)
|
||||||
|
# Opus 5 — same sticker as the Opus 4 family; needs its own fragment
|
||||||
|
# because "claude-opus-4" doesn't substring-match it.
|
||||||
|
("claude-opus-5", 5.00, 25.00, 0.50, 6.25),
|
||||||
# Opus 4 family
|
# Opus 4 family
|
||||||
("claude-opus-4", 5.00, 25.00, 0.50, 6.25),
|
("claude-opus-4", 5.00, 25.00, 0.50, 6.25),
|
||||||
# Sonnet 4 / 3.7 / 3.5 family
|
# Sonnet 4 / 3.7 / 3.5 family
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ the router maps back to the correct pre-seeded provider row.
|
|||||||
|
|
||||||
**Anthropic entries derive from `runtime.MODEL_MAP`** — that's the single
|
**Anthropic entries derive from `runtime.MODEL_MAP`** — that's the single
|
||||||
source of truth for which Claude versions are supported. Bumping a model
|
source of truth for which Claude versions are supported. Bumping a model
|
||||||
version there (e.g. `claude-opus-4-8` → a newer id) updates the
|
version there (e.g. `claude-opus-5` → a newer id) updates the
|
||||||
catalog automatically without a second edit here.
|
catalog automatically without a second edit here.
|
||||||
|
|
||||||
Ollama Cloud entries are hand-maintained because Ollama's cloud tags
|
Ollama Cloud entries are hand-maintained because Ollama's cloud tags
|
||||||
@@ -46,7 +46,7 @@ def _build_anthropic_entries() -> tuple[CatalogEntry, ...]:
|
|||||||
|
|
||||||
Keeps the UI honest: a user picking "Claude Opus" sees exactly which
|
Keeps the UI honest: a user picking "Claude Opus" sees exactly which
|
||||||
underlying Claude Code model id will be used at spawn
|
underlying Claude Code model id will be used at spawn
|
||||||
(e.g. "Claude Opus · claude-opus-4-8"), so version bumps in
|
(e.g. "Claude Opus · claude-opus-5"), so version bumps in
|
||||||
`runtime.MODEL_MAP` are immediately visible.
|
`runtime.MODEL_MAP` are immediately visible.
|
||||||
"""
|
"""
|
||||||
entries: list[CatalogEntry] = []
|
entries: list[CatalogEntry] = []
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class WaitingRecord:
|
|||||||
|
|
||||||
# Model mapping for cost optimization
|
# Model mapping for cost optimization
|
||||||
MODEL_MAP: dict[str, str] = {
|
MODEL_MAP: dict[str, str] = {
|
||||||
"opus": "claude-opus-4-8",
|
"opus": "claude-opus-5",
|
||||||
"sonnet": "claude-sonnet-5",
|
"sonnet": "claude-sonnet-5",
|
||||||
"haiku": "claude-haiku-4-5-20251001",
|
"haiku": "claude-haiku-4-5-20251001",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -565,6 +565,7 @@ class TestProviderAwareness:
|
|||||||
for name in (
|
for name in (
|
||||||
"claude-opus-4-6",
|
"claude-opus-4-6",
|
||||||
"claude-opus-4-8",
|
"claude-opus-4-8",
|
||||||
|
"claude-opus-5",
|
||||||
"claude-fable-5",
|
"claude-fable-5",
|
||||||
"opus",
|
"opus",
|
||||||
"sonnet",
|
"sonnet",
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ def test_build_anthropic_entries_skips_missing_models() -> None:
|
|||||||
# Patch MODEL_MAP to be missing one entry → loop hits the `continue` branch.
|
# Patch MODEL_MAP to be missing one entry → loop hits the `continue` branch.
|
||||||
with patch(
|
with patch(
|
||||||
"roboco.models.llm_catalog.MODEL_MAP",
|
"roboco.models.llm_catalog.MODEL_MAP",
|
||||||
{"opus": "claude-opus-4-8"}, # sonnet+haiku missing
|
{"opus": "claude-opus-5"}, # sonnet+haiku missing
|
||||||
):
|
):
|
||||||
entries = _build_anthropic_entries()
|
entries = _build_anthropic_entries()
|
||||||
# Only one entry survives — opus.
|
# Only one entry survives — opus.
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ def test_sonnet_alias_resolves_to_sonnet_5() -> None:
|
|||||||
assert MODEL_MAP["sonnet"] == "claude-sonnet-5"
|
assert MODEL_MAP["sonnet"] == "claude-sonnet-5"
|
||||||
|
|
||||||
|
|
||||||
def test_opus_alias_resolves_to_opus_4_8() -> None:
|
def test_opus_alias_resolves_to_opus_5() -> None:
|
||||||
# CEO upgrade to the newest Opus tier ("Opus 5" does not exist — the
|
# CEO upgrade to the newest Opus tier (Opus 5, released 2026-07-25).
|
||||||
# Claude 5 family is Fable/Mythos/Sonnet; Opus tops out at 4.8).
|
assert MODEL_MAP["opus"] == "claude-opus-5"
|
||||||
assert MODEL_MAP["opus"] == "claude-opus-4-8"
|
|
||||||
|
|
||||||
|
|
||||||
def test_sonnet_5_is_priced() -> None:
|
def test_sonnet_5_is_priced() -> None:
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ def _spec(**overrides: Any) -> _IntakeRunSpec:
|
|||||||
},
|
},
|
||||||
"session_id": "sess-abc",
|
"session_id": "sess-abc",
|
||||||
"cwd": "/data/workspaces/roboco/board/intake-1",
|
"cwd": "/data/workspaces/roboco/board/intake-1",
|
||||||
"cli_model": "claude-opus-4-8",
|
"cli_model": "claude-opus-5",
|
||||||
"api_url": "http://roboco-orchestrator:8000",
|
"api_url": "http://roboco-orchestrator:8000",
|
||||||
"provider_base_url": None,
|
"provider_base_url": None,
|
||||||
"provider_auth_token": None,
|
"provider_auth_token": None,
|
||||||
@@ -108,7 +108,7 @@ class TestBuildIntakeRunCmd:
|
|||||||
assert "ROBOCO_WORKSPACE=/data/workspaces/roboco/board/intake-1" in cmd
|
assert "ROBOCO_WORKSPACE=/data/workspaces/roboco/board/intake-1" in cmd
|
||||||
assert "ROBOCO_API_URL=http://roboco-orchestrator:8000" in cmd
|
assert "ROBOCO_API_URL=http://roboco-orchestrator:8000" in cmd
|
||||||
assert "ROBOCO_AGENT_ID=intake-1" in cmd
|
assert "ROBOCO_AGENT_ID=intake-1" in cmd
|
||||||
assert "CLAUDE_CODE_SUBAGENT_MODEL=claude-opus-4-8" in cmd
|
assert "CLAUDE_CODE_SUBAGENT_MODEL=claude-opus-5" in cmd
|
||||||
|
|
||||||
def test_mounts_prompt_and_workspaces(self) -> None:
|
def test_mounts_prompt_and_workspaces(self) -> None:
|
||||||
cmd = AgentOrchestrator._build_intake_run_cmd(_spec())
|
cmd = AgentOrchestrator._build_intake_run_cmd(_spec())
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class TestBuildManifestForAgent:
|
|||||||
mock_settings.manifest_host_dir = str(tmp_path)
|
mock_settings.manifest_host_dir = str(tmp_path)
|
||||||
mock_settings.workspaces_root = str(tmp_path / "workspaces")
|
mock_settings.workspaces_root = str(tmp_path / "workspaces")
|
||||||
|
|
||||||
result = _build_manifest_for_agent("be-dev-1", "claude-opus-4-8")
|
result = _build_manifest_for_agent("be-dev-1", "claude-opus-5")
|
||||||
|
|
||||||
assert result is not None
|
assert result is not None
|
||||||
data = json.loads(result.read_text())
|
data = json.loads(result.read_text())
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class TestBuildForRole:
|
|||||||
role=role,
|
role=role,
|
||||||
team="board",
|
team="board",
|
||||||
workspace_path=Path("/tmp/x"),
|
workspace_path=Path("/tmp/x"),
|
||||||
agent_model="claude-opus-4-8",
|
agent_model="claude-opus-5",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert "read_messages" in m.do_tools
|
assert "read_messages" in m.do_tools
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ async def test_log_agent_event_resolves_slug_to_uuid(
|
|||||||
event_type="agent.spawned",
|
event_type="agent.spawned",
|
||||||
agent_slug=slug,
|
agent_slug=slug,
|
||||||
task_id=task_id,
|
task_id=task_id,
|
||||||
details={"container_id": "abc123def456", "model": "claude-opus-4-8"},
|
details={"container_id": "abc123def456", "model": "claude-opus-5"},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Read back the row.
|
# Read back the row.
|
||||||
|
|||||||
@@ -945,7 +945,7 @@ class TestGetRecentSessions:
|
|||||||
row = MagicMock()
|
row = MagicMock()
|
||||||
row.id = sid
|
row.id = sid
|
||||||
row.agent_slug = "product-owner"
|
row.agent_slug = "product-owner"
|
||||||
row.model = "claude-opus-4-8"
|
row.model = "claude-opus-5"
|
||||||
row.started_at = datetime.datetime(2026, 6, 11, 20, 41, tzinfo=datetime.UTC)
|
row.started_at = datetime.datetime(2026, 6, 11, 20, 41, tzinfo=datetime.UTC)
|
||||||
row.ended_at = datetime.datetime(2026, 6, 11, 20, 42, tzinfo=datetime.UTC)
|
row.ended_at = datetime.datetime(2026, 6, 11, 20, 42, tzinfo=datetime.UTC)
|
||||||
row.tokens_input = exp_in
|
row.tokens_input = exp_in
|
||||||
@@ -966,7 +966,7 @@ class TestGetRecentSessions:
|
|||||||
s = out[0]
|
s = out[0]
|
||||||
assert s["id"] == str(sid)
|
assert s["id"] == str(sid)
|
||||||
assert s["agent_slug"] == "product-owner"
|
assert s["agent_slug"] == "product-owner"
|
||||||
assert s["model"] == "claude-opus-4-8"
|
assert s["model"] == "claude-opus-5"
|
||||||
assert s["tokens_input"] == exp_in
|
assert s["tokens_input"] == exp_in
|
||||||
assert s["tokens_output"] == exp_out
|
assert s["tokens_output"] == exp_out
|
||||||
assert s["tokens_cache"] == exp_cr + exp_cw
|
assert s["tokens_cache"] == exp_cr + exp_cw
|
||||||
|
|||||||
Reference in New Issue
Block a user