Restructure SDK outputs into top-level sdk/{rust,python,rhai,js}/ #70

Closed
opened 2026-05-19 16:46:59 +00:00 by timur · 2 comments
Owner

Problem

Generated SDK output is inconsistent. In a scaffolded service (e.g. hero_service):

  • Rust SDK lives at crates/<name>_sdk/ (workspace member)
  • Rhai bindings live at crates/<name>_rhai/ (workspace member)
  • JS SDK lives at sdk/js/ (loose files, not a crate)
  • Python SDK isn't emitted at all for scaffolded services, despite the codegen path existing (#60 verified it works for recipe_sdk_rpc2)

Four different homes for the same conceptual thing.

Expected

One umbrella with one folder per language target:

sdk/
├── rust/    # the Rust SDK crate (was crates/<name>_sdk)
├── rhai/    # the Rhai bindings crate (was crates/<name>_rhai)
├── python/  # Python SDK package
└── js/      # TS/JS package

Keeping the Rust + Rhai crates as members of the top workspace stays fine — they just live under sdk/rust/ and sdk/rhai/ instead of crates/. The crates/ directory keeps only the binaries + core lib (hero_<name>, _server, _admin, _examples).

What to do

  • Move scaffolder output: _sdksdk/rust/, _rhaisdk/rhai/. Update workspace member paths + buildenv.sh + tests.
  • Wire Python emitter into the scaffolder (the rails landed in #60). Output to sdk/python/.
  • Move existing JS emitter output from loose sdk/js/*.js to a proper package shape (sdk/js/package.json + sources).
  • Update generated workspace Cargo.toml, hero_service_scaffold.md skill, and the recipe_server example.

Acceptance

  • A fresh scaffold produces sdk/{rust,rhai,python,js}/; none of the SDK output lives under crates/.
  • cargo build --workspace still clean.
  • lab infocheck clean.
  • hero_service template repo regenerated to match (or updated in-place).
## Problem Generated SDK output is inconsistent. In a scaffolded service (e.g. `hero_service`): - Rust SDK lives at `crates/<name>_sdk/` (workspace member) - Rhai bindings live at `crates/<name>_rhai/` (workspace member) - JS SDK lives at `sdk/js/` (loose files, not a crate) - Python SDK isn't emitted at all for scaffolded services, despite the codegen path existing (#60 verified it works for `recipe_sdk_rpc2`) Four different homes for the same conceptual thing. ## Expected One umbrella with one folder per language target: ``` sdk/ ├── rust/ # the Rust SDK crate (was crates/<name>_sdk) ├── rhai/ # the Rhai bindings crate (was crates/<name>_rhai) ├── python/ # Python SDK package └── js/ # TS/JS package ``` Keeping the Rust + Rhai crates as members of the top workspace stays fine — they just live under `sdk/rust/` and `sdk/rhai/` instead of `crates/`. The `crates/` directory keeps only the binaries + core lib (`hero_<name>`, `_server`, `_admin`, `_examples`). ## What to do - Move scaffolder output: `_sdk` → `sdk/rust/`, `_rhai` → `sdk/rhai/`. Update workspace member paths + buildenv.sh + tests. - Wire Python emitter into the scaffolder (the rails landed in #60). Output to `sdk/python/`. - Move existing JS emitter output from loose `sdk/js/*.js` to a proper package shape (`sdk/js/package.json` + sources). - Update generated workspace `Cargo.toml`, `hero_service_scaffold.md` skill, and the recipe_server example. ## Acceptance - A fresh scaffold produces `sdk/{rust,rhai,python,js}/`; none of the SDK output lives under `crates/`. - `cargo build --workspace` still clean. - `lab infocheck` clean. - `hero_service` template repo regenerated to match (or updated in-place). ## Related - Surfaces from feedback on the [hero_service](https://forge.ourworld.tf/lhumina_code/hero_service) bootstrap (issue #261).
Author
Owner

Picked this up. Working in branch issue-70-sdk-restructure at worktree /tmp/hero_rpc_70 against origin/development.

Scope plan:

  1. Scaffolder: move _sdksdk/rust/ and _rhaisdk/rhai/ (workspace member paths + scaffolded build.rs client_crate_dir + examples crate path).
  2. Wire .with_python_sdk() into the scaffolded build.rs so a fresh scaffold also produces sdk/python/.
  3. JS emitter: write to sdk/js/src/types_generated.js + emit a minimal sdk/js/package.json.
  4. Regenerate example/recipe_server/ against the new layout (Cargo.toml workspace, in-tree patches, build.rs paths, regenerate SDK trees).
  5. Acceptance: cargo build --workspace clean, lab infocheck clean, <hero-api-docs> still resolves.

The hero_service_scaffold.md skill update + hero_service template repo regen will land as separate PRs (in hero_skills and hero_service respectively) — out of scope for this hero_rpc PR but referenced from the description.

Picked this up. Working in branch `issue-70-sdk-restructure` at worktree `/tmp/hero_rpc_70` against `origin/development`. Scope plan: 1. Scaffolder: move `_sdk` → `sdk/rust/` and `_rhai` → `sdk/rhai/` (workspace member paths + scaffolded `build.rs` `client_crate_dir` + examples crate path). 2. Wire `.with_python_sdk()` into the scaffolded `build.rs` so a fresh scaffold also produces `sdk/python/`. 3. JS emitter: write to `sdk/js/src/types_generated.js` + emit a minimal `sdk/js/package.json`. 4. Regenerate `example/recipe_server/` against the new layout (Cargo.toml workspace, in-tree patches, build.rs paths, regenerate SDK trees). 5. Acceptance: `cargo build --workspace` clean, `lab infocheck` clean, `<hero-api-docs>` still resolves. The `hero_service_scaffold.md` skill update + `hero_service` template repo regen will land as separate PRs (in `hero_skills` and `hero_service` respectively) — out of scope for this hero_rpc PR but referenced from the description.
Author
Owner

PR #89 is up against development: #89

All acceptance checks green:

  • Fresh scaffold produces sdk/{rust,rhai,python,js}/ (covered by new test_scaffold_unified_sdk_layout + test_scaffold_build_rs_opts_into_python_and_sdk_rust).
  • crates/ keeps only binaries + core lib + examples — no SDK output left under it.
  • cargo build --workspace clean (1 pre-existing unused-imports warning, untouched).
  • cargo test -p hero_rpc_generator --lib — 131 passed.
  • lab infocheck — identical to development (4 clean, 2 with pre-existing §5 boilerplate findings in crates/generator + crates/hero_lifecycle, unrelated to #70).
  • <hero-api-docs> still resolves — docs/openrpc.json regeneration intact and recipes_admin/src/main.rs still include_str!s it.

Drive-by fix included: the Python emitter was double-prefixing hero_ when sdk_types_crate("hero_<svc>") was set (the value the scaffolder always emits), so it was writing to sdk/python/hero_hero_<svc>_sdk/. The leading prefix is now stripped before being re-applied; new test covers both bare and prefixed inputs.

Follow-ups (out of scope here, will land separately as the task spec called out):

  • hero_skillshero_service_scaffold.md skill update PR.
  • hero_service template repo — regen PR.
PR #89 is up against `development`: https://forge.ourworld.tf/lhumina_code/hero_rpc/pulls/89 All acceptance checks green: * Fresh scaffold produces `sdk/{rust,rhai,python,js}/` (covered by new `test_scaffold_unified_sdk_layout` + `test_scaffold_build_rs_opts_into_python_and_sdk_rust`). * `crates/` keeps only binaries + core lib + examples — no SDK output left under it. * `cargo build --workspace` clean (1 pre-existing unused-imports warning, untouched). * `cargo test -p hero_rpc_generator --lib` — 131 passed. * `lab infocheck` — identical to `development` (4 clean, 2 with pre-existing §5 boilerplate findings in `crates/generator` + `crates/hero_lifecycle`, unrelated to #70). * `<hero-api-docs>` still resolves — `docs/openrpc.json` regeneration intact and `recipes_admin/src/main.rs` still `include_str!`s it. Drive-by fix included: the Python emitter was double-prefixing `hero_` when `sdk_types_crate("hero_<svc>")` was set (the value the scaffolder always emits), so it was writing to `sdk/python/hero_hero_<svc>_sdk/`. The leading prefix is now stripped before being re-applied; new test covers both bare and prefixed inputs. Follow-ups (out of scope here, will land separately as the task spec called out): * `hero_skills` — `hero_service_scaffold.md` skill update PR. * `hero_service` template repo — regen PR.
timur closed this issue 2026-05-20 09:35:44 +00:00
Sign in to join this conversation.
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_rpc#70
No description provided.