feat: upgrade to hero_service template codegen pattern (#44) #46
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue-44-template-pattern-upgrade"
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?
Closes #44. Migrates hero_logic from the older OSchema codegen path onto the canonical hero_service template (hero_skills#261 / hero_rpc#55).
What changed
New shared crate
crates/hero_logic_types/build.rswith the newOschemaBuildConfigshape:schemas_dir,sdk_dir,client_crate_dir,server_crate_dir,server_types_crate,sdk_types_crate,with_wasm,with_python_sdk,with_rhai. Mirrors the hero_service template exactly.../hero_logic_server/src/logic/; routes typed client wrappers + WASM-compat types to../hero_logic_sdk/src/logic/.hero_logic_server/src/lib.rsto restore the hand-writtenengine,seed,services,tracing_layersibling modules the codegen would otherwise strip; and patches the emittedopenrpc.json(info.titlecolon + missingserversblock) so theopenrpc_client!macro accepts it.Server bootstrap (
crates/hero_logic_server/src/main.rs)OServerConfig::new()+server.run().awaitwithHeroLifecycle::new(name, repo, package)+OServer::run_cli(lifecycle, |server, contexts, ...| async move { ... }). Domain registration, banner, socket prep, seed-flow spawn, and shutdown all run inside the closure.build.rs(moved into the shared types crate).SDK (
crates/hero_logic_sdk/)hero_rpc_derive+hero_rpc_openrpc→hero_rpc_client+herolib_otoml+herolib_sid+ (still)hero_rpc_derivefor the local macro path.src/logic/{types,osis_client_generated,mod}.rsnow auto-emitted by codegen. ContainsLogicClient(HTTP/WASM client built onOsisClient) — the canonical SDK consumer surface for browser/Dioxus/mobile.src/local_client.rs—openrpc_client!macro wrapping the codegen-emittedopenrpc.jsonto produceLogicServiceClientfor in-tree Unix-socket consumers (CLI + admin). Co-exists withLogicClientso consumers pick their transport.src/python_source.rs— hand-writtendecode_python_sourceb64-prefix helper preserved across regens via the SDK builder's auto-discovery.Admin (
crates/hero_logic_admin/)src/rpc_client.rsentirely.AppState::client: LogicRpcClientfield removed. NewAppState::rpc_call(method, params)helper routes raw RPC calls through the typed SDK's underlyingOpenRpcTransport(viaLogicServiceClient::transport()). Same per-call reconnect semantics, no separate transport.routes.rsmigrated fromstate.client.rpc_call(...)→state.rpc_call(...). Typed SDK calls (sdk.logic_service_*()) unchanged.Workspace
crates/hero_logic_server/schemas/to top-levelschemas/.hero_lifecycle,hero_rpc_client,herolib_otoml.hero_logic_types,hero_logic_sdk.hero_logic_sdkdepends onhero_logic_typesto force build-order serialisation (the macro reads docs/logic/openrpc.json which hero_logic_types' build.rs writes + patches).JS / Python SDK targets
sdk/js/andsdk/python/by the new build config (with_python_sdk()+js()is implicit when target is Server).with_rhai().Out of scope
Per the issue body: no hero_rpc2 trait-macro migration (separate follow-up). No domain-code refactor (
engine,seed,services,tracing_layer, admin templates, CLI clap tree, 19 hand-writtenlogicservice.*methods).Acceptance
build.rsuses the newOschemaBuildConfigshapeHeroLifecycle + OServer::run_clihero_logic_typescrate consumed by_server+_sdkadmin/src/rpc_client.rsdeleted; admin uses typed SDK wrappers throughoutpython_sourceb64-prefix helper preservedcargo build --workspacefinishes clean (1 unused-imports warning in codegen-emittedtypes_generated.rs— upstream concern)lab infocheck:3 crate(s) clean, 0 with issues, 0 finding(s) totalRecommended follow-ups (upstream)
Three small hero_rpc generator fixes would eliminate the build.rs post-process hack in this PR:
info.titlewithout a colon (e.g.LogicServiceinstead ofLogicService:logic) soopenrpc_client!'s identifier derivation accepts it.serversblock inopenrpc.jsonfor service projects so the macro'sconnect()resolves to the right Unix socket out of the box.generate_server_lib_rsauto-discover hand-written sibling modules the waygenerate_sdk_lib_rsalready does (via//! @sdk-feature:doc-comment markers), so consumers with extra modules likeengine/seeddon't need a build.rs post-process step to restore them after regen.🤖 Generated with Claude Code
Phase 1–3 of the template-pattern migration. See PR description for details. - New crates/hero_logic_types/ shared crate owns build.rs with the new OschemaBuildConfig shape (sdk_dir, client_crate_dir, server_crate_dir, server_types_crate, sdk_types_crate, with_wasm, with_python_sdk, with_rhai). Generated types live here, consumed by both _server and _sdk. Build.rs post-processes hero_logic_server's lib.rs to restore the hand-written engine/seed/services/tracing_layer modules the codegen would otherwise strip. - Schemas moved to top-level schemas/logic/; docs to top-level docs/. - hero_logic_server: main.rs migrated to HeroLifecycle + OServer::run_cli closure pattern. lib.rs becomes thin (re-exports the generated logic domain via hero_logic_types). src/logic/{core,server}/ flattened to src/logic/ to match the codegen's flat per-domain layout when server_crate_dir is set. - hero_logic_sdk: deps swapped for hero_rpc_client + herolib_otoml + herolib_sid + base64. Old hand-written generated/ deleted in favor of codegen-emitted src/logic/{types,osis_client_generated,mod}.rs. decode_python_source preserved as src/python_source.rs (auto-discovered by the SDK builder and re-emitted into the auto-generated lib.rs). - JS / Python SDK targets emit alongside Rust into top-level sdk/. REMAINING: - admin/src/rpc_client.rs deletion + routes.rs migration to typed wrappers; CLI migration too. Blocked on a hand-written LocalLogicClient that wraps OpenRpcTransport::unix_socket because OsisClient is HTTP-only (hero_rpc upstream gap — would need a new_unix() constructor for the one-line typed-client path). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Smoke-testing the migration surfaced two gaps that prevented the macro-derived `LogicServiceClient::connect()` from resolving the Unix socket path: 1. The OSchema-generated `openrpc.json` omits a `servers` block, so the macro's default `connect()` falls through with an empty URL and fails at builder time. Patch the spec in hero_logic_types' build.rs to inject: "servers": [{"name": "hero_logic", "url": "unix://${HERO_SOCKET_DIR}/hero_logic/rpc.sock"}] so the macro generates a `connect()` that resolves through `herolib_core::base::resolve_socket_path_with_override`. Upstream fix belongs in hero_rpc_generator's openrpc emitter (alongside the `info.title` colon fix from the prior commit). 2. Add `hero_logic_types` as a workspace dep on `hero_logic_sdk` so cargo serialises the SDK build after build.rs writes/patches the spec. Without this edge a clean parallel build races and the `openrpc_client!` macro reads a stale or pre-patch spec. 3. Add `herolib_core` to the SDK's deps — the macro now emits a call to `resolve_socket_path_with_override` so the crate has to resolve. Smoke verified: - `hero_logic_server` boots, registers logic domain, binds rpc.sock. - `hero_logic search`, `hero_logic workflow versions <sid>` succeed end-to-end through the typed `LogicServiceClient`. - `hero_logic play start` reaches the server (rejects at app-level with "Missing required input 'model'" — application logic, not a transport failure). - `hero_logic_admin` boots, binds admin.sock, renders /health, /workflows, /plays. - `AppState::rpc_call` raw-call helper (replacement for the deleted `LogicRpcClient`) routes successfully through the typed SDK's underlying `OpenRpcTransport`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>info.titlewithout colon (openrpc_client!macro rejects it) #91serversblock inopenrpc.jsonsoopenrpc_client!::connect()resolves to the service's Unix socket #92generate_server_lib_rsshould auto-discover hand-written sibling modules (mirrorsgenerate_sdk_lib_rs) #93