fix: npm keyboard, Enter submit, and duplicate helper spawn - #11
Conversation
npm keyboard (Bug 1): the host's Solid compile transform skips any path under node_modules, so raw src/*.tsx published to npm never got compiled and no onMount/keymap handlers ran — every hotkey was dead. Add a per-file Babel build (scripts/build.ts) that pre-compiles src -> dist with OpenTUI's transformSolidSource, keeping @opentui/* and solid-js as external bare imports. Publish dist instead of src, move those runtime libs to optional peerDependencies, and add a prepack hook so npm pack / publish always builds first. create-task Enter (Bug 2): most terminals send bare CR for both Enter and Ctrl+Enter, so Ctrl+Enter could never submit. Plain Enter now submits from every field; Ctrl+J inserts a newline in the description. double intake (Bug 3): a duplicate plugin load in a worktree gave each module copy its own in-memory guard, so two session.updated events could both spawn intake. Share helperEntryClaims and sessionLocks on globalThis and claim the spawn (intakeOutcome: "pending") inside the serialized metadata lock before creating the child; a failed spawn clears the claim so retries still work.
Mirror the intake dedupe onto the validator path: onEnterReview now
claims the spawn via claimHelperSpawn("validator") inside the serialized
metadata lock, and spawnValidator no longer writes validatorOutcome
itself, so a duplicate plugin load can't spawn two validators.
Route build.ts's summary log to stderr so the prepack build during
npm pack --dry-run --json doesn't corrupt the JSON package:check parses.
Greptile SummaryThis PR fixes npm packaging, create-task keyboard input, and duplicate helper spawning. The main changes are:
Confidence Score: 4/5This change is close, but the npm peer range can produce a broken supported install. The helper-spawn and keyboard changes are covered by focused tests. The packaging change has one current runtime contract issue: the compiled output relies on OpenTUI runtime-plugin support while package.json accepts older peers. package.json
What T-Rex did
|
| Filename | Overview |
|---|---|
| package.json | Switches published entrypoints to prebuilt dist and peers OpenTUI/Solid; peer floors are too low for the new precompiled runtime-plugin output. |
| scripts/build.ts | Adds per-file Babel/Solid build to dist with OpenTUI/Solid host runtime import rewrites. |
| scripts/package-check.ts | Expands package validation to build dist, check compiled Solid output, install with host peers, and ensure host deps are not bundled. |
| src/create-task.tsx | Changes create-task keyboard behavior so Enter submits and Ctrl+J/linefeed/Shift+Return insert description newlines. |
| src/server.ts | Shares in-memory helper entry claims across module copies and claims helper spawns inside serialized metadata updates. |
| src/session-api.ts | Moves session locks to globalThis and adds atomic helper-spawn claiming via patchKaganWhen. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
package.json:69-72
**Raise peer floors**
The published package now ships precompiled `dist` output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with `@opentui/*@0.3.4`. The runtime-plugin exports and JSX runtime support used by the compiled output are a `0.4.x` API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.
Reviews (2): Last reviewed commit: "fix: support packed production plugin in..." | Re-trigger Greptile
Adversarial-review follow-ups on the npm/keyboard/intake fixes:
- server.ts: widen the intake and validator try/catch to cover resolveTaskRefs,
worktreeDiffs, and the check commands. A throw in that pre-spawn work
previously left {role}Outcome:"pending" with no session, so every later
event returned early and the helper never retried (permanent lockout,
flagged by Greptile). Any pre-spawn throw now routes through
handleHelperFailure, which clears the claim. Regression tests for both paths.
- create-task.tsx: Ctrl+J now inserts a newline in the description on Kitty
terminals too. Kitty reports Ctrl+J as {name:"j",ctrl}, not linefeed, so the
old fall-through did nothing there; insert via descriptionRef.newLine() for
ctrl+j, linefeed, and shift+return.
- build.ts: compile with public babel presets instead of importing OpenTUI's
private scripts/solid-transform.js, which could vanish on any OpenTUI upgrade.
- package.json: peer floor >=0.3.4 (matches @opencode-ai/plugin's own range);
dev pins aligned to the host's @OpenTui 0.4.3 / solid-js 1.9.10.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
| "@opentui/core": ">=0.3.4", | ||
| "@opentui/keymap": ">=0.3.4", | ||
| "@opentui/solid": ">=0.3.4", | ||
| "solid-js": ">=1.9.10" |
There was a problem hiding this comment.
Raise peer floors
The published package now ships precompiled dist output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with @opentui/*@0.3.4. The runtime-plugin exports and JSX runtime support used by the compiled output are a 0.4.x API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: package.json
Line: 69-72
Comment:
**Raise peer floors**
The published package now ships precompiled `dist` output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with `@opentui/*@0.3.4`. The runtime-plugin exports and JSX runtime support used by the compiled output are a `0.4.x` API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.
How can I resolve this? If you propose a fix, please make it concise.|
🎉 This PR is included in version 0.2.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
Three independent bugs surfaced when kagan is installed from npm (vs. the local dev snapshot), plus their fixes:
node_modules, so publishing rawsrc/*.tsxmeant the plugin's components were never Solid-compiled — noonMountran, so no key handlers registered. Now we pre-compilesrc→distper-file with OpenTUI's owntransformSolidSource(scripts/build.ts), keeping@opentui/*andsolid-jsas external bare imports the host provides. Publishdistinstead ofsrc, move those runtime libs to optionalpeerDependencies, and add aprepackhook sonpm pack/publish always builds first.session.updatedevents could both spawn a helper. SharehelperEntryClaimsandsessionLocksonglobalThis, and claim the spawn ({role}Outcome: "pending") inside the serialized metadata lock before creating the child. A failed spawn clears the claim so retries still work. Applied to both the intake and validator paths.Test plan
bun run check— prettier, oxlint, tsc, 641 tests pass, build,package:checkdist/is Solid-compiled (no raw JSX;@opentui/*/solid-jsexternal), no bundled host deps in the packed tarballnpm pack→ install undernode_modules/@kagan-sh/kaganwith host peers → open the board and confirm arrows/Tab/Enter workNotes / follow-ups
scripts/build.tsimports OpenTUI's non-exportedscripts/solid-transform.js— works today, brittle across OpenTUI upgrades.@opentui 0.4.2while the peer floor is>=0.4.3;AGENTS.mdmay still say "never pre-transform" — doc/version follow-ups.