The environment section rendered "Model family: Claude Opus 4.6" for
every Anthropic model, so claude-opus-5-5, claude-sonnet-4-6, and any
other Claude model told users it was Opus 4.6.
Render a neutral "Claude" family label followed by the resolved model
ID, and rebuild the system prompt on /model so the line follows a
mid-session switch instead of keeping the startup model.
Models from the OpenAI-compatible providers fell back to
default_sonnet_tier ($3/$15 per MTok), so e.g. gpt-5.4-nano was
estimated at 15x its input price and qwen-plus at about 26x.
Add a table of published rates keyed by model id, matching dated
snapshots and -latest aliases:
- OpenAI standard tier for current gpt-6 / gpt-5.x / gpt-4.1 / gpt-4o
and o-series models (Responses-only pro models are omitted).
- xAI grok-4.x and grok-build. Slugs retired on 2026-05-15 (grok-3,
grok-4-0709, grok-4-fast-*, grok-4-1-fast-*) are billed at grok-4.3
rates, and grok-code-fast-* is served as grok-build.
- DashScope qwen-max, qwen-plus, qwen-flash and kimi-k2.5 at China
(Beijing) rates, which is claw's default DashScope endpoint, with
non-thinking output and the 20% implicit-cache hit rate.
Long-context and higher input tiers use the base rate because usage is
aggregated across requests.
Merge PR #3360 from c01dsummer/claw-code (fix/roadmap-835-838)
Four fixes addressing issues #3361 and #3360:
1. Parallel tool-result pairing (835): The Anthropic Messages API requires all
tool results of a turn to be in a single message. When a turn issued two tool
calls at once, the results were sent in separate messages, causing a 400 error.
Fixed by merging adjacent tool-result-only messages into one.
2. Terminal-scope path limit (836): Correlation keys up to 512 bytes expanded to
1024+ hex characters, exceeding APFS's 1024-byte total path limit. Fixed by
using SHA256 digest (32 hex chars) for path components while storing the full
key in the record for exact matching.
3. Credential hint (838): When ANTHROPIC_BASE_URL points to a non-Anthropic
endpoint (DeepSeek, corporate gateways), the missing-credentials error now
explains that the endpoint expects its own credentials, not Anthropic's.
4. ROADMAP entries: Documents all three fixes with verification details.
All tests pass (370+ for rusty-claude-cli, 240+ for sdk, 122+ for tools, 209+ for
api). Formatting verified with cargo fmt. CI checks approved and passed.
Fixes#3361, #3360
std::env::vars() panics on any non-UTF-8 value. zsh exports a metafied
$_ when the command path contains non-ASCII characters (e.g. 下載), so
claw panicked on startup. Use vars_os() and skip entries that are not
valid UTF-8.
* fix(runtime): update model pricing table to current rates
Align pricing_for_model with the published Anthropic pricing table:
- default_sonnet_tier was $15/$75 (the old Opus rate); it is now the
Sonnet 4.x rate of $3/$15, which is what the `sonnet` alias resolves to.
- Add Sonnet 5 / 5.5, Haiku 5.5, Haiku 3.5, and Fable / Mythos rates.
- Opus 4.5+ is $5/$25 and Opus 5.5 is $4/$20; Opus 4/4.1 keep the $15/$75
tier they are still billed at on Bedrock and Google Cloud.
Versions are parsed from the model id so dated, provider-prefixed, and
Vertex-style ids resolve to the right tier. Haiku 5.5's >100K-token tier
is not modeled because usage is aggregated across requests.
* fix(runtime): add DeepSeek API pricing
DeepSeek models fell back to default_sonnet_tier ($3/$15 per MTok),
overestimating V4 Flash by about 10x on input and 12x on output.
Price the ids served by the DeepSeek API at peak rates: deepseek-v4-pro
at $1.32/$3.96, and deepseek-flash, deepseek-v4-flash and the retired
deepseek-chat / deepseek-reasoner aliases at $0.30/$1.20. Off-peak usage
is billed at half. Other DeepSeek models on third-party hosts keep the
default because their prices vary by host.
push_output_block recorded a thinking event at content_block_start (an
empty placeholder) and the stream loop recorded the full block again at
content_block_stop. The empty duplicate was replayed on the next request
and rejected with 400 "each thinking block must contain thinking".
Only emit the event from the non-streaming path.
The English README migrated the star-history chart/link from
star-history.com / api.star-history.com to star-history.dera.page,
but README.zh.md (last synced at d229a9b) still used the old domains.
Update the 4 URLs so both language versions stay consistent.
The /sandbox status can be 'ok' (with namespace isolation) or 'warn' (in
restricted environments like CI without unshare support). Update the test
to accept either value rather than hard-coding an expectation.
- Update client_integration.rs user-agent assertion to expect version 0.1.5
- Fix output_format_contract.rs /sandbox status expectation from 'warn' to 'ok'
The test explicit_model_provider_hint_controls_runtime_provider_dispatch
was failing when OPENAI_BASE_URL was set in the environment to a non-standard
URL (e.g., api.layofflabs.com). The test expects the OpenAI provider to use
the default base URL (api.openai.com) when no explicit base_url is provided
in the ProviderConfig.
This fix adds an EnvVarGuard struct to the tests module and uses it to
ensure OPENAI_BASE_URL is unset before running the test, preventing
environment pollution from affecting the test result.
Fixes: https://github.com/ultraworkers/claw-code/issues/3345
Co-authored-by: clawdbot <clawdbot@ultraworkers.dev>
- Add SkillOrigin::Bundled variant to support bundled skills registry
- Implement bundled_skill_root() function for discovering bundled skills
- Update skill discovery to include bundled skills from standard install paths
- Create example bundled skills (example-skill, chain-example)
- Add comprehensive tests for bundled skills discovery and metadata
- Bundled skills follow same directory structure as plugins
- Skills can now chain/invoke other skills using standard dispatch mechanisms
- Maintains backward compatibility with existing SkillsDir and LegacyCommandsDir
- Implement OperationRegistry with standard query, control, and event operations
- Add Schema struct for defining input/output schemas
- Add OperationMetadata for rich operation descriptions
- Add Frame methods to extract operation and input from broker requests
- Add comprehensive tests demonstrating the gap and the fix
- Operations can be discovered, validated, and customized
This addresses issue #3321 (Slice 1.2): SDK operation registry & schema validation.
The gap: The original SDK allowed any operation name with no validation.
The fix: A registry-based system that defines valid operations and their schemas.
- Mark SDK wire protocol (Slice 1.1) as implemented (PR #3330)
- Update tool catalog status with read selectors (PR #3332/#3334)
- Add slash commands progress: /tools, /info (PR #3339)
- Document as historical planning reference with current implementation status
- Add PR references and status summary
- All section status notes now reflect merged work as of 2026-10-13
- Resolve .gitignore conflict: include both nix entries and .claude/
- Update AnthropicRuntimeClient::new() test calls to match new signature
- Fix explicit_model_provider_hint test to unset OPENAI_BASE_URL env var
The PermissionMode enum intentionally does not implement PartialOrd
to prevent silent re-ranking of the privilege ladder. Use the explicit
covers() method for privilege comparisons instead of < and >=.
execute_batch already keyed results to original call slots; this makes
that airtight: panicking worker threads resolve to their own index via
a fallback tuple instead of colliding with slot 0, and results are
asserted to follow call order with a regression test that mixes a
workspace-escape read among valid reads at cap=2.
Adds the fan-out bound: parallel-safe calls run in waves of at most
maxParallelToolCalls (default 8, CLAWD_PARALLEL_TOOL_CALLS env, or the
new setting applied via with_max_parallel_tool_calls at runtime build).
Sequential behavior is preserved: allowed_tools checks still run
before dispatch, and ToolSearch stays off the parallel path.
TeamCreate resolves maxConcurrentAgents from the per-team input, then
the maxConcurrentAgents setting, then unlimited (pre-fix behavior).
The cap is persisted in the manifest and registered on a process-wide
gate; agent threads still spawn immediately but block on an RAII slot
before entering their run loop, so manifest/task-claim semantics are
unchanged. TeamDelete forgets the gate so queued agents drain and no
stale team entries accumulate. Includes a gate regression test.
Adds optional positive-integer parsing for the two new fan-out caps
next to subagentModel, in both camelCase and snake_case forms. Zero
parses as unset; non-numeric values are a named config error. Covered
by three regression tests mirroring the subagentModel test style.
Review fixes for PR #3250:
1. Restore workspace-level unsafe_code = "forbid" (was downgraded to
"warn" for TUI support). The per-crate [lints.rust] unsafe_code =
"allow" on rusty-claude-cli already overrides it where needed.
2. Fix TaskClaim TOCTOU race in claim_task(). Replace exists()-then-write
with OpenOptions::create_new(true) which atomically fails if the lock
file already exists, eliminating the race window between the check and
the write.
3. Remove TUI scaffolding deps (ratatui, tui-textarea, gag, crossbeam-channel,
libc, unicode-width) and the /tui slash command spec — these belong in
a future TUI PR and are unused in the current source.
Also updates the provider chain precedence test to reflect the new behavior
where the caller's resolved model is the chain primary.
Co-Authored-By: Claw <noreply@openclaw.ai>
Adds 3 unit tests covering the original silent-drop bug:
- camelCase 'subagentModel' key reads end-to-end
- snake_case 'subagent_model' key reads end-to-end
- blank value returns None (falls back to default model)
Requested by @1716775457damn in PR review.
Restores the fix from @Offwhite-Del that was lost during rebase.
Unknown models now return None so preflight skips the context-window
check and lets the API enforce its own limits.
Port the agent-team enhancement layer onto upstream/main so the model
can spin up coordinated sub-agent teams for parallel work.
subagentModel config wiring (fix):
- Add subagent_model field to RuntimeFeatureConfig + RuntimeConfig::subagent_model()
accessor so the subagentModel setting (already validated by config_validate.rs)
is now actually read and stored.
- Agent tool's resolve_agent_model falls back to subagentModel from config
when no explicit model is passed.
Provider namespace separation:
- New 'custom-openai' provider kind with dedicated env vars
(CLAWCUSTOMOPENAI_API_KEY / CLAWCUSTOMOPENAI_BASE_URL)
- /setup wizard saves kind: 'custom-openai' for option 5
- Bare model name normalized to 'custom/' prefix to avoid proxy 404s
- Sub-agents inherit /setup-saved provider config via inject_config_as_env_fallbacks
Parallel tool execution:
- Override execute_batch to classify read-only tools as parallel-safe
and run them concurrently via std::thread::scope
- Results return in original model order
Team coordination layer:
- AgentMessage, TaskClaim, TeamStatus tools + shared mailbox directory
- Mode presets (tiny/1x ... mega/6x) + enriched TeamCreate/Agent descriptions
- Background team watcher
- /team slash command: on/off/status/toggle
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>