feat(team): dynamic agent type list + fix warmup race skipping preset_context#208
Merged
Conversation
5 tasks
5f98f06 to
9c183f5
Compare
Align with old TS architecture: hard whitelist (claude/codex/gemini/aionrs/codebuddy) always passes, non-whitelisted agents dynamically qualify by having MCP capabilities persisted from ACP handshake. Centralizes TEAM_CAPABLE_BACKENDS in aionui-common, eliminating 3 duplicated copies and the manual sync requirement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expose team eligibility as a boolean on `/api/agents` so the frontend can filter team-capable agents without hardcoding a whitelist or parsing agent_capabilities JSON. Computed at hydrate time from hard whitelist + persisted MCP capability declarations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9c183f5 to
5c55ff5
Compare
…tion The first-message injection (team guide prompt, skill index) was gated on `is_brand_new` which checked `session_id.is_none() && !is_opened()`. When warmup and messages arrived concurrently, warmup could mark the session as opened before messages checked the flag, causing the preset context to never be injected into the first user prompt. Replace the racy check with a dedicated `needs_first_message_injection` flag on AcpSession that is consumed exactly once by the first real prompt, independent of session open state. Resumed sessions (restored session_id from DB) consume the flag at restore time since their prior conversation history already contains the injected context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TCP404
added a commit
that referenced
this pull request
May 14, 2026
Replace the `needs_first_message_injection` flag introduced by #208 with a proper hook-chain dispatcher. The old flag conflated two orthogonal concerns (session-opened state vs. first-prompt decoration) and required a reverse-of-intention `take` in `set_session_id` to cancel its default-true value on resume paths. Core changes - New `crate::capability::prompt_pipeline`: `PromptPipeline` + `PreSendHook` / `PostRecvHook` traits + `PromptCtx` borrow slice. - New `crate::manager::acp::hooks`: `SessionNewPreludeHook` and `ModelIdentityReminderHook` as thin adapters over existing `inject_first_message_prefix` / `render_model_identity_reminder`. - `AcpSession`: drop `needs_first_message_injection` (default true), add `pending_session_new_prelude` (default false) with explicit `mark_*` / `take_*`. Flag is set by `open_session_new` on success; resume paths never touch it. - `AcpAgentManager`: gains a `pipeline` field constructed with the two built-in hooks; `ensure_session_and_send` collapses to a single `pipeline.pre_send` call. `set_session_id` no longer drains any flag. - `agent_session_flow::prompt_existing_session`: drop the inline `take_pending_model_notice` + `render_prompt_content` block now that `ModelIdentityReminderHook` owns that transformation. UI plumbing - New `AgentStreamEvent::AcpPromptHookWarning(Value)` variant and `aionui_api_types::AcpPromptHookWarningPayload` struct, so hook failures can surface as non-blocking toasts via the existing stream channel. `emit_hook_warning` helper is in place; a future refactor that surfaces a fallible boundary in `inject_first_message_prefix` will wire it up. Regression tests - `tests/prompt_pipeline_integration.rs` adds the coverage #207/#208 should have had: brand-new first prompt injects preset_context; second prompt is passthrough; resume path does not inject; `set_pending_model_notice` triggers reminder once; both flags at once produce `<system-reminder>` outside `[Assistant Rules]`; hook-warning end-to-end skeleton is `#[ignore]`'d with unlock condition documented. Workspace hygiene - Bump exhaustive match arms for the new event variant in `aionui-channel::message_service` and the test helper in `acp_agent_integration`. - Minor pre-existing clippy cleanups surfaced under `-D warnings` across the workspace (`assert!(x)` over `assert_eq!(x, true)`, `io::Error::other`, targeted `#[allow]` for approx_constant test fixtures, etc.).
7 tasks
TCP404
added a commit
that referenced
this pull request
May 14, 2026
…#262) Replace the `needs_first_message_injection` flag introduced by #208 with a proper hook-chain dispatcher. The old flag conflated two orthogonal concerns (session-opened state vs. first-prompt decoration) and required a reverse-of-intention `take` in `set_session_id` to cancel its default-true value on resume paths. Core changes - New `crate::capability::prompt_pipeline`: `PromptPipeline` + `PreSendHook` / `PostRecvHook` traits + `PromptCtx` borrow slice. - New `crate::manager::acp::hooks`: `SessionNewPreludeHook` and `ModelIdentityReminderHook` as thin adapters over existing `inject_first_message_prefix` / `render_model_identity_reminder`. - `AcpSession`: drop `needs_first_message_injection` (default true), add `pending_session_new_prelude` (default false) with explicit `mark_*` / `take_*`. Flag is set by `open_session_new` on success; resume paths never touch it. - `AcpAgentManager`: gains a `pipeline` field constructed with the two built-in hooks; `ensure_session_and_send` collapses to a single `pipeline.pre_send` call. `set_session_id` no longer drains any flag. - `agent_session_flow::prompt_existing_session`: drop the inline `take_pending_model_notice` + `render_prompt_content` block now that `ModelIdentityReminderHook` owns that transformation. UI plumbing - New `AgentStreamEvent::AcpPromptHookWarning(Value)` variant and `aionui_api_types::AcpPromptHookWarningPayload` struct, so hook failures can surface as non-blocking toasts via the existing stream channel. `emit_hook_warning` helper is in place; a future refactor that surfaces a fallible boundary in `inject_first_message_prefix` will wire it up. Regression tests - `tests/prompt_pipeline_integration.rs` adds the coverage #207/#208 should have had: brand-new first prompt injects preset_context; second prompt is passthrough; resume path does not inject; `set_pending_model_notice` triggers reminder once; both flags at once produce `<system-reminder>` outside `[Assistant Rules]`; hook-warning end-to-end skeleton is `#[ignore]`'d with unlock condition documented. Workspace hygiene - Bump exhaustive match arms for the new event variant in `aionui-channel::message_service` and the test helper in `acp_agent_integration`. - Minor pre-existing clippy cleanups surfaced under `-D warnings` across the workspace (`assert!(x)` over `assert_eq!(x, true)`, `io::Error::other`, targeted `#[allow]` for approx_constant test fixtures, etc.).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
team_capablecomputed field to AgentMetadata responseBug Fix Detail
PR #207 introduced eager session opening via
warmup_session(). When warmup and the first message arrived concurrently, warmup marked the session asopenedbeforeensure_session_and_send()checkedis_brand_new, causing it to skip preset_context injection entirely. The solo agent never received the team guide prompt, so it skipped the "recommend lineup → wait for confirmation" flow and directly calledaion_create_team.Fix: Replace the racy
is_brand_newcheck with a dedicatedneeds_first_message_injectionflag onAcpSessionthat is consumed exactly once by the first real prompt, independent of session open state.Test plan
cargo nextest run --workspace— 5432 passedcargo clippy --workspace -- -D warnings— cleancargo fmt --all -- --check— clean🤖 Generated with Claude Code