Skip to content

fix(ai): unchud model routing#4273

Merged
ehayes2000 merged 1 commit into
mainfrom
ehayes2000/macro-2001-choreai-unchud-model-routing-env-vars
Jun 24, 2026
Merged

fix(ai): unchud model routing#4273
ehayes2000 merged 1 commit into
mainfrom
ehayes2000/macro-2001-choreai-unchud-model-routing-env-vars

Conversation

@ehayes2000

Copy link
Copy Markdown
Contributor

No description provided.

@macro-application

Copy link
Copy Markdown

@ehayes2000 ehayes2000 changed the title fix(ai): unchud routing fix(ai): unchud model routing Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 154dab31-fad0-4c8f-832c-79d3215c97b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adopts a provider/model identifier convention (e.g., anthropic/claude-haiku-4-5, openai/gpt-5) throughout the stack. On the Rust side, a new Model<'a> struct parses these strings, AnthropicModel<'a> and OpenAiModel<'a> are refactored to hold it directly (removing regex-based ModelId newtypes), and ModelRouter replaces the previous AllModelsRouter/AnthropicRouter/OpenAiRouter composition with a single struct that dispatches on the provider segment and manages a process-wide singleton. Streaming is consolidated into drive_stream inside router.rs. The GET /chats/models endpoint is fully removed: its ModelAccess/ModelsResponse domain types, ModelAccessService::list_models, HTTP handler, Axum route wiring, Swagger registration, and OpenAPI spec entry are all deleted. The frontend drops useModelsQuery and cognitionApiServiceClient.getModels(), updates the Model constant and lookup tables to use the new identifier format, and derives model picker options statically from the enum. Code generation scripts are updated to remove the models-binary invocation path.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No description was provided by the author. Although minimal, the changeset impacts are substantial and span frontend/backend model routing, which would benefit from explanation. Consider adding a description explaining: the motivation for switching to provider/model format, how the new routing works, and any migration notes for consumers of these APIs.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title follows conventional commits format (fix:) and is well under 72 characters (29 chars). It clearly summarizes the main change: refactoring the AI model routing system.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
rust/cloud-storage/agent/src/model/types.rs (1)

26-26: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use a char pattern to satisfy clippy.

split_once('/') avoids the clippy::single_char_pattern lint, which is warn-by-default and may fail just clippy if warnings are denied.

♻️ Proposed tweak
-            .split_once("/")
+            .split_once('/')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/cloud-storage/agent/src/model/types.rs` at line 26, The split_once
method call is using a string pattern "/" instead of a character pattern, which
triggers the clippy::single_char_pattern lint warning. Replace the string
literal "/" with a character literal '/' in the split_once call to satisfy
clippy and avoid potential lint failures.
js/app/packages/core/component/AI/component/input/ChatInput.tsx (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

createEffect here triggers a state update rather than syncing an external system.

This effect's sole job is to call input.setModel(...) when the selected id is stale — i.e. it derives/repairs reactive state, which the SolidJS convention explicitly steers away from. Prefer wrapping the setter (validate-on-set) or exposing a derived "effective model" rather than reconciling via an effect.

As per path instructions: "Avoid createEffect in SolidJs. Only use for syncing with external/imperative systems... Do not use to derive state or trigger updates—use a derived signal or wrap the setter instead".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@js/app/packages/core/component/AI/component/input/ChatInput.tsx` around lines
58 - 65, The createEffect hook is being used to derive and update state (calling
input.setModel) rather than syncing with an external system, which violates
SolidJS conventions. Replace this effect by either wrapping the input.setModel
setter function itself to validate that the model id exists in modelOptions
before updating, or by creating a derived signal that computes the effective
model (returning the current model if valid, or the first option if stale) and
using that derived signal throughout the component instead of the raw model
signal.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@js/app/scripts/generate-api-schema.ts`:
- Around line 49-52: The conditional block in buildOpenApiBinaries() that adds
the gen_tool_schemas binary to binArgs when document_cognition_service is
included is redundant because generate-dcs-tools.ts independently builds and
runs its own copy of this binary. Remove the entire if statement that checks if
crateNames.includes("document_cognition_service") and the subsequent
binArgs.push calls for the gen_tool_schemas binary, consolidating the build
responsibility entirely to generate-dcs-tools.ts.

In `@rust/cloud-storage/agent/src/model/router.rs`:
- Around line 337-348: The FinalResponse branch in the stream handling code is
emitting a duplicate StreamPart::Usage that is already being sent by
StreamBridge::on_stream_completion_response_finish, causing DCS consumers to
receive usage information twice. Remove the yield Ok(StreamPart::Usage(...))
call from this FinalResponse match arm while keeping the recorder.record() call
intact, since usage recording is still needed here even though the stream part
emission should happen only in the other path.
- Around line 258-260: The route_or_default method currently returns a routed
model but discards information about whether the default fallback was used,
causing callers to record and prompt with the requested model id even when the
default Anthropic model is actually being used. Modify the route_or_default
method to return the effective/actual model that will be used (indicating
whether the requested model was successfully routed or if the default was used
as a fallback), and ensure callers use this returned effective model id for
usage recording and per-session model prompts instead of the originally
requested id.
- Around line 41-45: The environment variable name in the ApiKeys struct field
creates a mismatch between code expectations and infrastructure provisioning.
The env_var! macro transforms OpenAiApiKey into OPEN_AI_API_KEY (with underscore
between OPEN and AI), but the Pulumi infrastructure provides openai_api_key
without the underscore. To fix this, either rename the OpenAiApiKey field in the
ApiKeys struct to OpenaiApiKey (which will transform to OPENAI_API_KEY matching
the infrastructure provisioning), or update the Pulumi configuration files to
provision the variable as open_ai_api_key instead. Ensure consistency so that
ModelRouter::shared() can successfully initialize ApiKeys::new() during startup.

In `@rust/cloud-storage/agent/src/model/types.rs`:
- Around line 4-18: Add documentation comments to all public items in the Model
struct to comply with the #![deny(missing_docs)] requirement. Add a doc comment
above the Model struct itself explaining its purpose, then add doc comments
above each of the public fields (provider and name) describing what they
represent, and finally add doc comments above each of the public accessor
methods (provider() and name()) explaining what they return. Ensure each doc
comment uses the standard Rust documentation format starting with three forward
slashes (///).

---

Nitpick comments:
In `@js/app/packages/core/component/AI/component/input/ChatInput.tsx`:
- Around line 58-65: The createEffect hook is being used to derive and update
state (calling input.setModel) rather than syncing with an external system,
which violates SolidJS conventions. Replace this effect by either wrapping the
input.setModel setter function itself to validate that the model id exists in
modelOptions before updating, or by creating a derived signal that computes the
effective model (returning the current model if valid, or the first option if
stale) and using that derived signal throughout the component instead of the raw
model signal.

In `@rust/cloud-storage/agent/src/model/types.rs`:
- Line 26: The split_once method call is using a string pattern "/" instead of a
character pattern, which triggers the clippy::single_char_pattern lint warning.
Replace the string literal "/" with a character literal '/' in the split_once
call to satisfy clippy and avoid potential lint failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e689060-3240-4faa-b0a5-5521e0ddcd9e

📥 Commits

Reviewing files that changed from the base of the PR and between b5d9529 and 70eb614.

⛔ Files ignored due to path filters (7)
  • flake.lock is excluded by !**/*.lock
  • js/app/packages/service-clients/service-cognition/generated/client.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-cognition/generated/schemas/index.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-cognition/generated/schemas/model.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-cognition/generated/schemas/modelAccess.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-cognition/generated/schemas/modelsResponse.ts is excluded by !**/generated/**
  • js/bun.lock is excluded by !**/*.lock, !**/bun.lock
📒 Files selected for processing (35)
  • js/app/packages/core/component/AI/component/debug/HttpStream.tsx
  • js/app/packages/core/component/AI/component/input/ChatInput.tsx
  • js/app/packages/core/component/AI/constant/model.ts
  • js/app/packages/queries/chat.ts
  • js/app/packages/service-clients/service-cognition/client.ts
  • js/app/packages/service-clients/service-cognition/openapi.json
  • js/app/scripts/generate-api-schema.ts
  • js/app/scripts/generate-dcs-models.ts
  • js/app/scripts/generate-dcs-types.ts
  • rust/cloud-storage/agent/src/agent_loop.rs
  • rust/cloud-storage/agent/src/completion.rs
  • rust/cloud-storage/agent/src/error.rs
  • rust/cloud-storage/agent/src/lib.rs
  • rust/cloud-storage/agent/src/model/anthropic.rs
  • rust/cloud-storage/agent/src/model/mod.rs
  • rust/cloud-storage/agent/src/model/openai.rs
  • rust/cloud-storage/agent/src/model/predefined_model.rs
  • rust/cloud-storage/agent/src/model/router.rs
  • rust/cloud-storage/agent/src/model/router/anthropic.rs
  • rust/cloud-storage/agent/src/model/router/openai.rs
  • rust/cloud-storage/agent/src/model/router/test.rs
  • rust/cloud-storage/agent/src/model/test.rs
  • rust/cloud-storage/agent/src/model/types.rs
  • rust/cloud-storage/agent/src/provider_env.rs
  • rust/cloud-storage/chat/src/domain/models/mod.rs
  • rust/cloud-storage/chat/src/domain/models/model_access.rs
  • rust/cloud-storage/chat/src/domain/ports/model_access.rs
  • rust/cloud-storage/chat/src/domain/service/model_access.rs
  • rust/cloud-storage/chat/src/domain/service/model_access/test.rs
  • rust/cloud-storage/chat/src/inbound/http/mod.rs
  • rust/cloud-storage/chat/src/inbound/http/models.rs
  • rust/cloud-storage/document_cognition_service/Cargo.toml
  • rust/cloud-storage/document_cognition_service/src/api/chats/mod.rs
  • rust/cloud-storage/document_cognition_service/src/api/swagger.rs
  • rust/cloud-storage/document_cognition_service/src/models_bin.rs
💤 Files with no reviewable changes (16)
  • rust/cloud-storage/agent/src/model/router/test.rs
  • js/app/packages/queries/chat.ts
  • js/app/scripts/generate-dcs-types.ts
  • js/app/scripts/generate-dcs-models.ts
  • rust/cloud-storage/agent/src/model/router/anthropic.rs
  • rust/cloud-storage/chat/src/inbound/http/mod.rs
  • rust/cloud-storage/document_cognition_service/Cargo.toml
  • rust/cloud-storage/agent/src/model/router/openai.rs
  • rust/cloud-storage/agent/src/provider_env.rs
  • js/app/packages/service-clients/service-cognition/client.ts
  • rust/cloud-storage/document_cognition_service/src/models_bin.rs
  • rust/cloud-storage/chat/src/inbound/http/models.rs
  • rust/cloud-storage/chat/src/domain/service/model_access/test.rs
  • rust/cloud-storage/agent/src/model/test.rs
  • js/app/packages/service-clients/service-cognition/openapi.json
  • rust/cloud-storage/chat/src/domain/models/model_access.rs

Comment thread js/app/scripts/generate-api-schema.ts Outdated
Comment thread rust/cloud-storage/agent/src/model/router.rs
Comment thread rust/cloud-storage/agent/src/model/router.rs
Comment thread rust/cloud-storage/agent/src/model/router.rs
Comment thread rust/cloud-storage/agent/src/model/types.rs
@ehayes2000 ehayes2000 force-pushed the ehayes2000/macro-2001-choreai-unchud-model-routing-env-vars branch 6 times, most recently from 37cdb95 to 8ebf130 Compare June 24, 2026 15:43
@ehayes2000 ehayes2000 force-pushed the ehayes2000/macro-2001-choreai-unchud-model-routing-env-vars branch from 8ebf130 to 21a3b97 Compare June 24, 2026 15:44
@ehayes2000 ehayes2000 merged commit 9476d1d into main Jun 24, 2026
26 checks passed
@ehayes2000 ehayes2000 deleted the ehayes2000/macro-2001-choreai-unchud-model-routing-env-vars branch June 24, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant