mirror of
https://github.com/instructkr/claw-code.git
synced 2026-10-30 00:00:22 +08:00
feat(team): team enhancements, subagentModel, parallel tool exec
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>
This commit is contained in:
1 parent
76fe2e9f46
commit
7aa00a2798
15 files changed
+3021
-552
No files matched your search
@@ -180,6 +180,49 @@ impl ApiError {
|
||||
}
|
||||
}
|
||||
|
||||
/// HTTP status code for an `Api` error, if any. Used by callers (e.g. the
|
||||
/// sub-agent provider chain) to decide whether to advance to the next
|
||||
/// configured model — a 404 "model not found" on the primary should fall
|
||||
/// through to the next fallback rather than killing the whole chain.
|
||||
#[must_use]
|
||||
pub fn status_code(&self) -> Option<reqwest::StatusCode> {
|
||||
match self {
|
||||
Self::Api { status, .. } => Some(*status),
|
||||
Self::RetriesExhausted { last_error, .. } => last_error.status_code(),
|
||||
Self::MissingCredentials { .. }
|
||||
| Self::ContextWindowExceeded { .. }
|
||||
| Self::ExpiredOAuthToken
|
||||
| Self::Auth(_)
|
||||
| Self::InvalidApiKeyEnv(_)
|
||||
| Self::Http(_)
|
||||
| Self::Io(_)
|
||||
| Self::Json { .. }
|
||||
| Self::InvalidSseFrame(_)
|
||||
| Self::BackoffOverflow { .. }
|
||||
| Self::RequestBodySizeExceeded { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Response body (best-effort) for an `Api` error, if any.
|
||||
#[must_use]
|
||||
pub fn response_body(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Api { body, .. } => Some(body.as_str()),
|
||||
Self::RetriesExhausted { last_error, .. } => last_error.response_body(),
|
||||
Self::MissingCredentials { .. }
|
||||
| Self::ContextWindowExceeded { .. }
|
||||
| Self::ExpiredOAuthToken
|
||||
| Self::Auth(_)
|
||||
| Self::InvalidApiKeyEnv(_)
|
||||
| Self::Http(_)
|
||||
| Self::Io(_)
|
||||
| Self::Json { .. }
|
||||
| Self::InvalidSseFrame(_)
|
||||
| Self::BackoffOverflow { .. }
|
||||
| Self::RequestBodySizeExceeded { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn safe_failure_class(&self) -> &'static str {
|
||||
match self {
|
||||
|
||||
@@ -30,8 +30,9 @@ pub use providers::openai_compat::{
|
||||
};
|
||||
pub use providers::{
|
||||
detect_provider_kind, max_tokens_for_model, max_tokens_for_model_with_override,
|
||||
model_family_identity_for, model_family_identity_for_kind, provider_diagnostics_for_model,
|
||||
resolve_model_alias, ProviderDiagnostics, ProviderKind,
|
||||
model_family_identity_for, model_family_identity_for_kind, model_token_limit,
|
||||
provider_diagnostics_for_model, resolve_model_alias, ModelTokenLimit, ProviderDiagnostics,
|
||||
ProviderKind,
|
||||
};
|
||||
pub use sse::{parse_frame, SseParser};
|
||||
pub use types::{
|
||||
|
||||
@@ -683,13 +683,15 @@ pub fn model_token_limit(model: &str) -> Option<ModelTokenLimit> {
|
||||
max_output_tokens: 8_192,
|
||||
context_window_tokens: 131_072,
|
||||
}),
|
||||
"qwen-max" => Some(ModelTokenLimit {
|
||||
max_output_tokens: 8_192,
|
||||
// Qwen models via DashScope / OpenAI-compat
|
||||
"qwen3.6-35b-fast" | "qwen3-235b-a22b" | "qwen-max" | "qwen-plus" | "qwen-turbo"
|
||||
| "qwen-qwq" => Some(ModelTokenLimit {
|
||||
max_output_tokens: 16_384,
|
||||
context_window_tokens: 131_072,
|
||||
}),
|
||||
"qwen-plus" => Some(ModelTokenLimit {
|
||||
max_output_tokens: 8_192,
|
||||
context_window_tokens: 131_072,
|
||||
"glm-5.1-fast" => Some(ModelTokenLimit {
|
||||
max_output_tokens: 16_384,
|
||||
context_window_tokens: 200_000,
|
||||
}),
|
||||
// Groq compound systems are exposed through an OpenAI-compatible API
|
||||
// but cap completions at 8,192 output tokens. Without this metadata
|
||||
|
||||
Reference in new issue
Block a user