Uh oh!
There was an error while loading. Please reload this page.
feat: hot reload native Caplets integrations - #37
Conversation
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR extracts a shared CapletsEngine to centralize config reload, file watching, backend manager coordination, and tool execution. CapletsRuntime and NativeCapletsService delegate to the engine; Pi dynamically syncs Caplet tools via tool-change events; OpenCode recomputes system guidance from current registered tools. Docs, tests, and a changeset are included. ChangesNative Hot Reload Integrations
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
|
| Filename | Overview |
|---|---|
| packages/core/src/engine.ts | Extracts CapletsEngine with reload lifecycle, debounced watchers, recursive directory tree watching, and listener notification; logic is correct and well-tested. |
| packages/core/src/native/service.ts | Thin DefaultNativeCapletsService wrapper over CapletsEngine; all public methods delegate correctly. |
| packages/core/src/runtime.ts | CapletsRuntime now stores unsubscribeReload and calls it in close(); reconcileTools correctly adds, updates, and removes MCP tools on each reload event. |
| packages/pi/src/index.ts | Adds hot-reload via onToolsChanged; knownCapletTools is now pre-seeded from active tools to deactivate stale tools on first sync. Re-registration relies on Pi using the latest duplicate-name registration. |
| packages/opencode/src/index.ts | system.transform calls service.listTools() live filtered by a frozen registeredToolNames snapshot. Unconditional push of nativeCapletsSystemGuidance injects Caplets boilerplate even when no tools are active. |
Sequence Diagram
sequenceDiagram
participant FS as FileSystem Watcher
participant Engine as CapletsEngine
participant Service as NativeCapletsService
participant Pi as Pi Extension
participant OC as OpenCode Plugin
Note over Engine: watch=true (default)
FS->>Engine: file change event
Engine->>Engine: scheduleReload() (debounced)
Engine->>Engine: reloadUntilSettled()
Engine->>Engine: reloadOnce(): load new config
Engine->>Engine: update registry + invalidate backends
Engine->>Engine: emitReload(prev, next)
par Pi Integration
Engine->>Service: onReload listener(listTools())
Service->>Pi: onToolsChanged(syncTools)
Pi->>Pi: update registeredCapletToolSignatures
Pi->>Pi: registerTool() for new/changed tools
Pi->>Pi: setActiveTools([nonCaplets, ...nextCapletTools])
and OpenCode Integration
Note over OC: No onToolsChanged subscription
OC->>Service: listTools() called live on each system.transform
OC->>OC: filter by registeredToolNames snapshot
OC->>OC: push guidance to system prompt
end
Reviews (3): Last reviewed commit: "fix: address follow-up hot reload review..." | Re-trigger Greptile
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/pi/src/index.ts`:
- Around line 63-68: piToolSignature currently serializes only visible metadata
(title, description, promptGuidance) so changes to the backing caplet id
(caplet.caplet captured in createPiTool) are ignored and re-registration can be
skipped; update piToolSignature to include the backing caplet id (use the
caplet.caplet identifier) in the returned JSON signature so syncTools sees
changes to the execution target and triggers re-registration (refer to
piToolSignature and createPiTool to locate where the caplet id must be added).
In `@packages/pi/test/pi.test.ts`:
- Around line 396-406: The mockPiApi currently makes setActiveTools a no-op so
getActiveTools always returns the initial snapshot; modify mockPiApi so it keeps
mutable internal state (e.g., let currentActive = activeTools) and implement
setActiveTools as a vi.fn that updates that state (e.g., currentActive =
newList) and make getActiveTools return currentActive; ensure registerTool still
pushes into registered and other mocks remain vi.fn wrappers so tests see
read-after-write behavior across successive calls to
setActiveTools/getActiveTools.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d68e59f4-3738-4580-b3f4-63fad4832a1d
📒 Files selected for processing (4)
packages/core/src/engine.tspackages/core/src/runtime.tspackages/pi/src/index.tspackages/pi/test/pi.test.ts
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
Verification
Summary by CodeRabbit
New Features
Documentation
Tests
Chores