Ensure parallel tool results finish before follow-ups, preserve warping
status across exchanges, clean up streams before crosscheck reviews, and
restore terminal focus when conversations complete. Remove temporary
debug
logging.
- Gate server requests on available credentials
- Run local child agents directly without a parent run ID
- Include command IDs in Bedrock context and recognize transfer tools
Add the 'Crosscheck Work' experiment to the Agents settings. When enabled,
a reviewer sub-agent is spawned after the main agent finishes a turn (with
no pending tool calls). The reviewer critiques the output using a dedicated
system prompt focused on correctness, simplicity, and code quality. If the
reviewer does not respond with 'LGTM!', its feedback is injected as a
synthetic user query back to the main agent, which must address it. This
loop continues until the reviewer approves or max iterations is reached.
Components:
- Feature flag: CrosscheckWork (enabled in DOGFOOD_FLAGS)
- Settings: agents.experiments.crosscheck_enabled,
agents.experiments.crosscheck_model_id,
agents.experiments.crosscheck_max_iterations
- Settings UI: new 'Experiments' subpage under Agents
- Crosscheck module: app/src/ai/crosscheck/ with prompt, reviewer model
- Controller integration: hooks into AfterStreamFinished when no actions
are queued, triggers reviewer, handles feedback injection
- Provider support: OpenAI-compatible and Bedrock direct invocation
- Safety: max iteration guard, error handling, reset on new user query
- Sanitize tool_use_id values in OpenAI request conversion to match
Bedrock's required pattern ^[a-zA-Z0-9_-]+$. Fixes 400 errors when
LiteLLM proxies to Bedrock and tool IDs contain invalid characters.
- Parse cache usage stats from LiteLLM/OpenAI responses
(prompt_tokens_details.cached_tokens, cache_read_input_tokens,
cache_creation_input_tokens) and propagate to token usage tracking.
- Hide cache-o-meter in session status bar when provider doesn't report
cache data (LiteLLM/OpenAI), instead of showing misleading 0% stats.
- Update cost estimation to account for cache read/write pricing tiers.
typescript-language-server requires a valid TypeScript installation to
function. Previously, no initializationOptions were sent during the LSP
initialize request, causing the server to fail with:
'Could not find a valid TypeScript installation. Please ensure that
the typescript dependency is installed in the workspace or that a
valid tsserver.path is specified.'
This fix:
- Adds initializationOptions.tsserver.path resolution that searches for
TypeScript in: workspace node_modules, global npm install, and npx cache
- Wires initialization_options into the LSP startup flow via LSPServerType
- Updates the install step to proactively install TypeScript globally if
not found locally
When a skill was invoked on a clean slate (no conversation history),
the request sent to the AI provider contained only a system prompt
with zero user messages, causing Bedrock/LiteLLM to reject it with:
'Invalid Message bedrock requires at least one non-system message'
Root cause: extract_new_input_messages() had no handler for
Type::InvokeSkill, so it fell through to the _ => {} wildcard and
produced zero ConversationMessage results.
Fix adds InvokeSkill handling to three functions:
- extract_new_input_messages(): generates a User message with the
skill name and content wrapped in <skill-instructions> tags
- extract_input_messages(): persists the InvokeSkill as a proper
api::Message in task history for conversation continuity
- extract_user_query_text(): returns '/<skill-name>' for the
UserQuery proto event used in conversation title generation
- Load global rules (AIFact/AIMemory) from local CloudModel and inject
them into the Bedrock/OpenAI system prompt as a '## Global Rules' section
when memory is enabled.
- Fix rule seeding: always re-seed predefined rules when the CloudModel has
none, regardless of the has_seeded_predefined_rules flag (handles case
where flag was set but rules never persisted due to prior missing owner).
- Rename /context slash command to /copy-context: dumps the full context
window (global rules, progressive summary, message history) to the
clipboard for debugging.
Previously, predefined rules (11 system-defined behavioral rules) were
only seeded when the user navigated to the Rules settings page, and
required a cloud-authenticated owner to create cloud objects.
Since Galaxy operates without Warp cloud auth:
1. personal_drive() now returns a synthetic local owner
('local-galaxy-user') when not authenticated, allowing cloud objects
(rules, etc.) to be created and stored locally in SQLite.
2. seed_predefined_rules_if_needed() runs at app startup (after
CloudModel and UpdateManager are initialized) to seed rules on
first launch without requiring the user to visit settings.
Rules are now visible in Galaxy Drive > Rules on first launch.
The previous implementation only used the standard OpenAI /models
endpoint which often lacks context window and capability metadata,
causing a blind 200K fallback for all models.
Now fetch_openai_models_from_endpoint tries LiteLLM's /model/info
endpoint first, which returns rich metadata:
- max_input_tokens (e.g. 1,000,000 for Sonnet 4.6)
- max_output_tokens (e.g. 128,000 for max models)
- supports_vision
- supports_function_calling
- underlying model path (for provider detection)
Falls back to /models if /model/info is unavailable (e.g. non-LiteLLM
OpenAI-compatible endpoints).
This ensures the model picker and context window configuration reflect
the actual capabilities of the configured models.
Galaxy should never call Warp's cloud API for AI. This is a policy
requirement. All model availability is now determined exclusively by
locally configured providers (Bedrock and/or OpenAI/LiteLLM).
Changes:
- Disable refresh_authed_models, refresh_public_models, refresh_available_models
(now no-ops with debug log)
- Disable on_server_update and update_feature_model_choices
- Disable get_cached_models (no stale server models restored from cache)
- Replace ModelsByFeature::default() with minimal placeholder that gets
stripped by inject_bedrock_models/inject_openai_models
- Make inject_bedrock_models strip Unknown placeholders unconditionally
- Make default_llm_info() return a static fallback instead of panicking
when no models are configured (prevents null reference crashes)
- Add has_any_provider_models() for UI to check provider availability
- Make ProviderConfig::None return a user-friendly error instead of
calling Warp's cloud API (the previous fallback behavior)
Safety: if no providers are enabled, the system gracefully returns an
error message rather than crashing or silently calling Warp's servers.