fix(server,sdk): unwrap params.request on chat methods; drop hand-rolled chat client #141

Open
timur wants to merge 1 commit from development_align_chat_drop_sdk_specs into development
Owner

Closes #140, closes #139.

#140 — chat handler unwraps params["request"]

The chat domain spec declares each method's params as a single named field ({"name": "request", "schema": ChatRequest}), per OpenRPC named-params convention. The chat handlers were reading params flat (params.get("model") directly), so macro-generated clients sending {"jsonrpc":"2.0","method":"ai.chat","params":{"request":{...}}} got 'model' parameter required.

Added unwrap_request_param() in crates/hero_aibroker_server/src/api_openrpc/chat/handlers.rs: takes params["request"] when it's a JSON object, else passes through unchanged. Applied to ai.chat, ai.messages, ai.responses, ai.completions. Spec + handler now agree; both wrapped and flat inputs work (the latter for legacy callers).

#139 — SDK consumes server specs directly; drop hand-rolled chat client

hero_aibroker_sdk::chat::Client was a hand-rolled wrapper around OpenRpcTransport that bypassed the macro-generated client to send ChatRequest flat. With #140 fixing the underlying mismatch, the chat domain now uses the same domain_client!() pattern as the other 9 domains. Net delete in lib.rs: ~50 LOC.

Lifted as crate-level / module-level helpers (not bound to a hand-rolled struct anymore):

  • crate::extract_chat_content(v) — pull a content string out of an ai.chat response envelope.
  • chat::MessageContent::text(s)V0(Value::String(s)) builder.
  • chat::Client::ai_chat_content(req) — convenience: send a ChatRequest, get back the assistant's content as a String.

PromptBuilder and the verify example switched to the macro-generated shape: client.ai_chat(AiChatInput { request: ChatRequest }).

The two allOf schemas that previously blocked the macro (TranscriptionVerbose in speech, memory.search result item in memory) were already inlined upstream — grep -c '"allOf"' specs/*.json is 0 across all 10 server specs. The SDK's old filtered copies (crates/hero_aibroker_sdk/specs/) were already removed before this PR.

Verification

  • cargo build clean for both hero_aibroker_server and hero_aibroker_sdk
  • cargo test -p hero_aibroker_sdk --doc — 3/3 compile-ok
  • cargo clippy -p hero_aibroker_sdk --no-deps -- -D warnings — clean
  • Live RPC round-triplab --release --bin hero_aibroker_server --force --install + lab --stop hero_aibroker_server + lab --release --start, then cargo run -p hero_aibroker_examples --example verify_127_chat returns real Groq output: content: "verified", full OpenAI envelope intact. Confirms the macro-generated client sends spec-shape {"request":{...}} params and the handler unwraps them correctly.

🤖 Generated with Claude Code

Closes #140, closes #139. ## #140 — chat handler unwraps `params["request"]` The chat domain spec declares each method's params as a single named field (`{"name": "request", "schema": ChatRequest}`), per OpenRPC named-params convention. The chat handlers were reading params flat (`params.get("model")` directly), so macro-generated clients sending `{"jsonrpc":"2.0","method":"ai.chat","params":{"request":{...}}}` got `'model' parameter required`. Added `unwrap_request_param()` in `crates/hero_aibroker_server/src/api_openrpc/chat/handlers.rs`: takes `params["request"]` when it's a JSON object, else passes through unchanged. Applied to `ai.chat`, `ai.messages`, `ai.responses`, `ai.completions`. Spec + handler now agree; both wrapped and flat inputs work (the latter for legacy callers). ## #139 — SDK consumes server specs directly; drop hand-rolled chat client `hero_aibroker_sdk::chat::Client` was a hand-rolled wrapper around `OpenRpcTransport` that bypassed the macro-generated client to send `ChatRequest` flat. With #140 fixing the underlying mismatch, the chat domain now uses the same `domain_client!()` pattern as the other 9 domains. Net delete in `lib.rs`: ~50 LOC. Lifted as crate-level / module-level helpers (not bound to a hand-rolled struct anymore): - `crate::extract_chat_content(v)` — pull a content string out of an `ai.chat` response envelope. - `chat::MessageContent::text(s)` — `V0(Value::String(s))` builder. - `chat::Client::ai_chat_content(req)` — convenience: send a `ChatRequest`, get back the assistant's content as a `String`. `PromptBuilder` and the verify example switched to the macro-generated shape: `client.ai_chat(AiChatInput { request: ChatRequest })`. The two `allOf` schemas that previously blocked the macro (`TranscriptionVerbose` in speech, `memory.search` result item in memory) were already inlined upstream — `grep -c '"allOf"' specs/*.json` is 0 across all 10 server specs. The SDK's old filtered copies (`crates/hero_aibroker_sdk/specs/`) were already removed before this PR. ## Verification - `cargo build` clean for both `hero_aibroker_server` and `hero_aibroker_sdk` - `cargo test -p hero_aibroker_sdk --doc` — 3/3 compile-ok - `cargo clippy -p hero_aibroker_sdk --no-deps -- -D warnings` — clean - **Live RPC round-trip** — `lab --release --bin hero_aibroker_server --force --install` + `lab --stop hero_aibroker_server` + `lab --release --start`, then `cargo run -p hero_aibroker_examples --example verify_127_chat` returns real Groq output: `content: "verified"`, full OpenAI envelope intact. Confirms the macro-generated client sends spec-shape `{"request":{...}}` params and the handler unwraps them correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(server,sdk): unwrap params.request on chat methods; drop hand-rolled chat client (closes #139, #140)
Some checks failed
Build and Test / build-and-test (pull_request) Failing after 1m11s
e12dd1eea9
#140 — server-side: chat domain spec declares each method's params as a
single named field {"name": "request", "schema": ChatRequest}, but the
chat handlers were reading params flat (params.get("model") directly).
Add an unwrap_request_param() helper that takes params["request"] when
it's a JSON object, else falls through unchanged. Applied to ai.chat,
ai.messages, ai.responses, ai.completions. Spec and handler are now
aligned; macro-generated clients round-trip cleanly.

#139 — SDK: drop the hand-rolled chat::Client::ai_chat wrapper that
existed only to work around the spec/handler mismatch above. The chat
domain now uses the same macro-generated client as the other 9 domains
via the domain_client!() macro. Net delete in lib.rs: ~50 LOC.

Kept as helpers (lifted out of the chat module since they aren't
specific to a hand-rolled client):
- crate::extract_chat_content(v) — pull a content string out of an
  ai.chat response envelope.
- chat::MessageContent::text(s) — V0(Value::String(s)) builder.
- chat::Client::ai_chat_content(req) — convenience: send ChatRequest,
  get back the assistant's content as a String.

prompt::PromptBuilder switches to the macro-generated shape:
client.ai_chat(AiChatInput { request: ChatRequest }). The verify_127_chat
example uses the same shape; the doc string updated to explain that the
spec-shape wire format is now what we test.

Verification:
- cargo build hero_aibroker_server / hero_aibroker_sdk — clean
- cargo test -p hero_aibroker_sdk --doc — 3/3
- cargo clippy -p hero_aibroker_sdk --no-deps -- -D warnings — clean
- lab --release --bin hero_aibroker_server --force --install + restart
  via lab --start, then cargo run -p hero_aibroker_examples --example
  verify_127_chat: real Groq round-trip returns "verified" with the full
  OpenAI envelope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Some checks failed
Build and Test / build-and-test (pull_request) Failing after 1m11s
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin development_align_chat_drop_sdk_specs:development_align_chat_drop_sdk_specs
git switch development_align_chat_drop_sdk_specs

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch development
git merge --no-ff development_align_chat_drop_sdk_specs
git switch development_align_chat_drop_sdk_specs
git rebase development
git switch development
git merge --ff-only development_align_chat_drop_sdk_specs
git switch development_align_chat_drop_sdk_specs
git rebase development
git switch development
git merge --no-ff development_align_chat_drop_sdk_specs
git switch development
git merge --squash development_align_chat_drop_sdk_specs
git switch development
git merge --ff-only development_align_chat_drop_sdk_specs
git switch development
git merge development_align_chat_drop_sdk_specs
git push origin development
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_aibroker!141
No description provided.