hero_browser_server: oschema-first migration (issue #309 Step 1) #40
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_browser!40
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "development_mahmoud"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Migrates
hero_browser_serverfrom the legacy hand-rolled JSON-RPC stack (service_base!()+ hand-built axum router + 47-armmatchdispatcher + hand-writtenopenrpc.json) to the oschema-firstopenrpc_server!pattern, per the platform migration (lhumina_code/home#309, Step 1 / backend). The MCP tool surface (server.rs, rmcp#[tool]s) is a separate surface and is untouched.What changed
development(herolib_macros/herolib_oschema_server/async-trait); existing code compiles unchanged.oschema/main/(00_types/80_inputs/90_rpc), singlemaindomain (model B). No[rootobject](the Chrome pool owns browser/page identity). Output types mirror thehero_browser_corestructs; dynamic JS/cookie/accessibility results are typedstr(noany). Required ids/args are required (the dispatch rejects their absence); only true defaults stay optional.src/rpc/main_impl.rs), bridging onto the existing dispatch (Step-1 manual mapping, zero behavior drift).serve_domains_with(extra, svc): the runtime serves the typedmaindomain onrpc.sock+ TCP 8884;extracarries only the custom routes (MCP/mcp, REST/api/*, SSE screenshot stream, OAuth/MCP probes). Chrome-pool graceful shutdown preserved.openrpc/openrpc_main.jsoncovers all 47 methods (drops the fakerpc.health/rpc.discover; addsjs_evaluate_async+page_wait_for_network_idlethe old spec omitted)./mcp/openrpcnow serves the generated spec (single source of truth).openrpc.rsremoved. Build is warning-clean; server tests + SDK doctest pass.Verified live (build #15)
browser_create → "<uuid>",browser_list/destroy,browser_list_sessionsreturn typed shapes on/api/main/rpcover bothrpc.sockand TCP 8884; MCPinitializeon :8884 = 200; REST/api/sessions= 200;lab infocheck+--info --jsonclean.Consumer-visible change
The canonical RPC path is now
/api/main/rpc(+/api/rpc); the bare/rpcis gone (standard model B). The hero_components admin was updated to usedomain="main"(separate PR ondevelopment).Independent review
A team-lead review flagged a red workspace (broken CLI/SDK doctest) + an optional-vs-required contract drift + a dual-spec smell — all fixed in this branch (commits
896f26d,bf0d4c5,44c5581,8cc0f92).Not in this PR (follow-ups)
hero_tests_createpattern.hero_browser_app(dormant Dioxus user UI) still POSTs to/rpcand uses stale method names — separate frontend fix.🤖 Generated with Claude Code
Phase B — typed trait impl for all 47 methods (compiler-enforced completeness), in src/rpc/main_impl.rs over the shared AppState (Chrome pool + activity log). Each method bridges onto the existing rpc_handler dispatch via small helpers (raw/params_of/field/field_str/out): builds a JsonRpcRequest, runs the legacy dispatch, and adapts its {key: value} wrapper into the typed Output. The browser-automation logic in hero_browser_core is unchanged (Step-1 manual mapping, zero behavior drift). element_info converts the core's tuple attributes [[name,value]] -> [{name,value}]; the dynamic JS/cookie/accessibility results are surfaced as JSON strings (schema types them str). Not yet served — serve_domains_with rewiring lands in Phase C, which resolves the current dead-code warnings.Complete the consumer propagation the migration's Phase D requires: - The generated client is HeroBrowserServiceClient (was HeroBrowserMCPClient); rpc.health was dropped (health is the runtime's GET /health.json), so the CLI 'health' command now uses a browser_list round-trip as the liveness probe. - browser_list now returns a bare [str] -> transparent BrowserListOutput, so read r.value (was r.browsers). - Update the SDK doctest to the new client name, the nested BrowserCreateInput { input: BrowserCreate { .. } }, and the transparent .value output. cargo build (server/sdk/cli/core/admin) + cargo test -p hero_browser_sdk --doc are green.Review MAJOR-1: the schema advertised browser_id/page_id (and url/selector/text/ value/name/key/expression/width/height/file_path) as optional, but the dispatch rejects their absence with -32602 — a contract lie. Per oschema_best_practices ("optionals only where absent != empty"), these are now required across the input structs (PageRef/ElementRef/JsCall and the per-method inputs) and the two bare-scalar methods (browser_destroy, browser_get_session_activity). Only genuinely-defaulted params keep '?': browser_create overrides, create-time url, full_page, timeout_ms, screenshot path, cookie domain/path, mobile device_scale_factor, dialog prompt_text. Verified against every 'missing X' check in rpc_handler. Regenerated spec; server/sdk/cli build green.hero_browser migrated to the oschema stack (single `main` domain). Update the Dioxus app to the new wire so its live views work again: - rpc.rs: POST /rpc -> /api/main/rpc; rename the stale method names to the server's verbatim ones (browser_list -> browser_list_sessions, browser_activity -> browser_get_activity, browser_session_activity -> browser_get_session_activity); SessionsResponse.browsers -> .sessions to match the server's SessionsResponse {sessions, count, max}. - sessions.rs/app.rs: follow the .sessions rename; backend health probe -> /hero_browser/rpc/health.json (the Model B health endpoint). - guide.rs: refresh the Integration Guide's endpoint + RPC-method listing and load the API Docs spec from /api/main/openrpc.json.Completes the Step 1 SDK migration. The SDK was still generating its client with the legacy `herolib_derive` macro (hero_macros_previous), which prefixed service-block method names (`hero_browser_service.browser_create`) while the server's `openrpc_server!` (hero_lib) registers them verbatim — so every typed call 404'd. Switch the SDK to hero_lib's `herolib_macros::openrpc_client!` (same family as the server) in the directory/bundle form, so client + server agree on verbatim names served at `/api/main/rpc`. - sdk: herolib_derive -> herolib_macros; bundle form (openrpc_client!("../hero_browser_server/oschema/", service="hero_browser")). Drops the legacy herolib_derive workspace dep and the stale generated artifact. - cli + test: consume the bundle API (HeroBrowserClient::connect().main()). - core: element get_value unwraps the JSON string literal from evaluate(), so element_get_value returns the bare value (`hi`) not its JSON encoding (`"hi"`). - test/ai: env probes now skip (not fail) when the optional resource is absent. Phase E suite is green end-to-end against the live server (build #25): basic/functional/extended/perf/admin all pass; ai passes/skips.