refactor(monorepo): added typescript templates into extension-template#3
Conversation
a443a35 to
9d605d8
Compare
agent-of-mkmeral
left a comment
There was a problem hiding this comment.
Tested end-to-end (cloned, ran npm run check — 7/7 pass; ran setup-template.ts with all 5 components via pexpect, post-setup npm run check — 7/7 pass). Three concrete fixes worth landing inline:
🟡 1. Stale npm run prepare in setup output + README
The package.json exposes npm run check (per the PR description, intentionally to dodge the npm prepare lifecycle hook). But setup-template.ts:352 and README.md both still tell users to run npm run prepare. Reproduced after setup:
$ npm run prepare
npm error Missing script: "prepare"
Fix:
// setup-template.ts
console.log(' 3. Run checks: npm run check')And same edit in typescript/README.md Next steps.
🟡 2. Setup leaves the other language behind
After running typescript/setup-template.ts for a TS-only project, the user's repo still has python/, python/pyproject.toml (with monorepo tag_regex/root=".."), .github/workflows/{ci,publish}-python.yml, and a top-level README.md that markets both languages. The Python setup script has the symmetric problem (leaves typescript/ + TS workflows).
The top-level README hand-waves this ("you can keep both subprojects... or delete the directory you don't need"), but for the 95% single-language case this is real manual cleanup most users will skip — their repo ends up shipping cruft.
Suggested: add a final prompt in each setup script:
Drop the other language from this repo? (y/n) [y]:
If yes: delete sibling dir + sibling workflows, rewrite top-level README.md to a single-language template, strip tag_regex/root from pyproject.toml (Python case).
🟢 3. @strands-agents/sdk >=0.1.0 peerDep — version doesn't exist on npm yet
The PR description already flags this. Just worth a one-line note in typescript/README.md so early adopters know npm install will currently fail until SDK ships, and to bump once it does.
Other observations (non-blocking)
replacementsordering comment in setup-template.ts is critical and well-noted — verified it works (file renamesession-manager.ts→google-session-manager.tshappens correctly becausesession-managerruns beforeTemplateXxx).- Hatch-vcs
root=".."+tag_regex="^python-v(?P<version>.+)$"+relative_to="pyproject.toml"is the right incantation for a monorepo —relative_tois required whenrootis non-default, comment captures that. - TS uses real SDK types (
Model,Plugin,SnapshotStorage,ConversationManager) not stubs — nice. TheSnapshotStoragevsSessionManagersplit is documented well insession-manager.ts. - CI scoping via
paths:+working-directory:is correct — verified. - 5499-line
package-lock.jsonshipped intentionally pins reproducible setup; fine but unusual for a template.
Net: direction is right (single canonical template, dual-language symmetry, clean tag-prefix release scheme). Worth landing the 3 fixes above before merging or as an immediate follow-up so the post-Use this template UX is actually clean.
I think this is the main blocker
should we scope to |
|
There are some options:
|
|
I think the latter is the best. After the script is run, I want the repo to look "beautiful" :D so it should look like a proper TS or Python repo (whatever customer chooses) |
9d605d8 to
4d6dd77
Compare
6b69c26 to
e54a3be
Compare
agent-of-mkmeral
left a comment
There was a problem hiding this comment.
Re-review on e54a3be — hoist-to-root works, two leftover bugs in post-hoist README
TL;DR: The new hoistToRoot() / hoistWorkflows() / stripMonorepoFromReadme() flow (and Python equivalent) addresses the main blocker from the previous round — verified end-to-end on both languages. Two small bugs remain: post-hoist README still tells users to cd typescript (or cd python) and run npm run setup / python setup_template.py, which no longer exist after hoist. SDK peerDep range now scoped to >=1.0.0 <2.0.0 ✓.
📝 Full re-review (click to expand)
What I tested
Cloned poshinchen:refactor/monorepo-python-typescript@e54a3be, ran both setup scripts end-to-end via pexpect with all 5 components selected and dropSibling=y:
- TypeScript:
npm ci→npm run check(7/7 pass) →npx tsx setup-template.ts(full hoist) →npm run checkpost-hoist (7/7 pass ✓) - Python:
python3 setup_template.py(full hoist) — pyproject.toml de-monorepoized, workflows hoisted, top-level files cleaned up.
✅ What got fixed since previous review
| Previous finding | Status |
|---|---|
Stale npm run prepare in setup output / README |
✅ Fixed — now says npm run check |
| Setup leaves the other language behind | ✅ Fixed — dropSibling prompt + full hoist-to-root in both scripts |
@strands-agents/sdk >=0.1.0 peerDep |
✅ Scoped to >=1.0.0 <2.0.0 (per @mkmeral's suggestion) |
The hoist functions are well-factored — stripMonorepoFromReadme() rewrites the per-language README's monorepo-aware bits (LICENSE link ../LICENSE → LICENSE, typescript-v0.1.0 → v0.1.0, removes "This is the TypeScript half of the…" line), hoistWorkflows() strips paths: filters and working-directory: defaults from the workflows before renaming, and hoistToRoot() does the directory swap + chdir. After running, the resulting repo looks like a real single-language template — no monorepo, typescript-v, python-v, tag_regex, or root = ".." references anywhere. 👏
🟡 New findings — 2 small bugs
Bug 1: Post-hoist README still says `cd your-repo-name/{typescript,python}`
After hoist, README.md (now at repo root) still has:
TypeScript (typescript/README.md → root after hoist), L28:
git clone https://github.com/testuser/your-repo-name
cd your-repo-name/typescript # ← directory no longer existsPython (python/README.md → root after hoist), L28:
cd your-repo-name/python # ← directory no longer existsUsers will follow this and immediately hit cd: no such file or directory.
Suggested fix: add to stripMonorepoFromReadme() (TS side, mirror in Python):
next = next.replace(/cd your-repo-name\/typescript\s*\n/g, '\n')
// Python equivalent
next = next.replace(/cd your-repo-name\/python\s*\n/g, '\n')Or more robustly, swap the entire cd your-repo-name/{lang} line for cd your-repo-name.
Bug 2: Post-hoist README "Run the setup script" section is now stale (script self-deleted)
The setup script self-destructs (correct), but the README still walks users through running it:
TypeScript README L30-37 (post-hoist):
### 2. Run the setup script
…
```bash
npm install
npm run setup # ← script and `setup` script entry both gone
**Python README L31-36 (post-hoist):**
2. Run the setup script
…
python setup_template.py # ← file deleted
Users see this section after the script has already removed itself. Confusing on first read.
**Suggested fix:** in `stripMonorepoFromReadme()`, also strip the entire `### N. Run the setup script` section between `### 2.` and the next `###` heading. Renumber subsequent sections, or just delete steps 2 and renumber 3 → 2. Same on the Python side.
Alternative: have the setup script print a one-liner to README's top saying "This repo was generated from `extension-template`. To re-customize, see [original template]…" and remove the "Getting started" → "Run the setup script" sections altogether.
</details>
### 🟢 Minor — observations on the open threads
Quoting the 4 unresolved review threads from @notowen333 since they're worth thinking through:
- **L310 "do we need to maintain this by hand?"** (the `replacements` map): Yes, this is the source of truth for "what gets renamed during setup." Hard to avoid declaratively listing class/file names since they're spread across multiple files. Could be derived from a `COMPONENTS` schema that knows its own class/file names, but it's only ~20 lines and tightly coupled to the template content — IMO fine as-is.
- **L1 "clean this file up, entrypoint at top"**: Reasonable. Current order is helpers → `main()` at L271 → `main()` invocation at L467. Moving `main()` to the top (with helper functions below) would improve scanability for first-time readers. Not blocking.
- **L33 "shouldn't this just clone the template?"**: I think the implicit question is *why is this not a `degit`/`create-strands-extension` style scaffolder?* The current approach (template repo + post-clone setup script) is closer to `create-react-app` ejection — works with GitHub's "Use this template" button, no external tooling. Would be worth a follow-up if/when there's a `create-strands-*` CLI, but this is a sensible v1.
- **publish-typescript.yml "Did we test this workflow?"**: PR description's test plan checkbox `[ ] Verify TS workflow runs on a draft tag (typescript-v0.0.0-test) once NPM_TOKEN is configured` is still unchecked — would address this directly.
### Net
✅ **Direction is right and ship-ready** modulo the 2 small README bugs above (15-line fix in `stripMonorepoFromReadme` on each side). The hoist-to-root flow gets you to mkmeral's stated goal — "After the script is run, I want the repo to look beautiful" — which it now genuinely does. Verified the resulting repo has zero monorepo cruft, tests still pass, workflows still resolve, and `pyproject.toml`/`package.json` look like normal single-language packages.
**Suggested order:** land the 2 README fixes inline, then merge.
</details>
---
Repro artifacts at `/tmp/work/setup-test-v2` (TS post-hoist) and `/tmp/work/py-test-v2` (Python post-hoist).
e54a3be to
7257c03
Compare
7257c03 to
da06ee1
Compare
Summary
Restructures
extension-template-pythoninto a language-agnostic monorepoextension-template/that hosts both Python and TypeScript templates side-by-side.Existing Python files move under
python/unchanged, a paralleltypescript/template is added with the same five extension-point skeletons, an interactive setup script, and CI/publish workflows.What's in the diff
Layout
pyproject.toml,setup_template.py,src/strands_template/,tests/,README.md) relocate topython/viagit mv(no content changes other than minor README/setup-script tweaks for the new path).typescript/sibling holds the equivalent template.README.mdintroduces both subprojects.TypeScript template (
typescript/)@strands-agents/sdktypes:src/tool.ts—tool()factory + Zod schemasrc/model.ts—Modelsubclass withstream(),updateConfig,getConfigsrc/plugin.ts—Pluginimpl with hook + self-contained toolsrc/session-manager.ts—SnapshotStorageimpl (the TS SDK's customization point for session persistence;SessionManageris consumed as-is)src/conversation-manager.ts—ConversationManagersubclass withreduce()setup-template.ts— Node port ofsetup_template.py, runs vianpm run setup(usestsx). Same UX: prompts for package name, components, author info; renames/rewrites/deletes accordingly; prunes setup-only entries frompackage.json; self-destructs.sdk-typescript: npm + plaintscbuild, vitest, ESLint flat config, Prettier, strict tsconfig (NodeNext, ES2022,exactOptionalPropertyTypes, etc.). Aggregate script isnpm run checkto avoid thepreparelifecycle-hook collision.CI/publish
ci.yml/publish.ymlrenamed toci-python.yml/publish-python.yml, scoped viapaths:filters andworking-directory: python. Hatch-vcs is configured to strip apython-vtag prefix.ci-typescript.yml(Node 20 & 22 matrix) andpublish-typescript.yml(publishes ontypescript-v*tags viaNPM_TOKEN).Test plan
python/**paths.cd typescript && npm install && npm run checkpasses locally (format, lint, type-check, test — 5 files / 7 tests).npm run setupend-to-end exercised: scaffolds a new package, deletes unselected components, removes setup-only deps and the script itself.typescript-v0.0.0-test) onceNPM_TOKENis configured.Notes for reviewers
extension-template-python→extension-templateto match the on-disk directory rename. Workflow paths and the new root README assume that name; if you'd rather keep the repo name, only README copy needs adjusting.extension-template/python/README still describes the same UX users had before, with a one-line note pointing at the monorepo root.@strands-agents/sdk >=0.1.0andzod ^4.1.12. Bump the lower bound if the SDK ships a different first stable version.