-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: hot reload caplets serve config #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
44311d5
feat: hot reload caplets serve config
ian-pascoe 3c6f247
fix: address hot reload review feedback
ian-pascoe 835f24d
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] 7a4c46c
fix: formatting
ian-pascoe b1ecf0d
fix: drain pending hot reload events
ian-pascoe c7f40e4
fix: tighten hot reload review edge cases
ian-pascoe 60c0f5e
fix: ignore stale downstream callbacks
ian-pascoe 319e038
fix: reject stale downstream configs
ian-pascoe a0eb44b
fix: keep reload reconciliation after invalidation errors
ian-pascoe ec278be
fix: keep caplet watchers and close pending connects
ian-pascoe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "caplets": minor | ||
| --- | ||
|
|
||
| # Hot reload serve config | ||
|
|
||
| Add default hot reload for `caplets serve`, including live config and Caplet file reconciliation without restarting the MCP process. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| # Hot Reload Implementation Plan | ||
|
|
||
| > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. | ||
|
|
||
| **Goal:** Make normal `caplets serve` reload config and Caplet file changes without restarting the Caplets MCP process. | ||
|
|
||
| **Architecture:** Introduce an in-process runtime controller that owns the MCP server, registered top-level tool handles, the current registry, backend managers, and filesystem watchers. Reloads parse the effective config exactly as startup does, update registered MCP tools through `RegisteredTool` handles, invalidate only affected backend caches, and keep the last known-good config active when a reload fails. | ||
|
|
||
| **Tech Stack:** TypeScript, Node.js `fs.watch`, `@modelcontextprotocol/sdk` `McpServer.registerTool`, Vitest. | ||
|
|
||
| --- | ||
|
|
||
| ## Task 1: Runtime Controller | ||
|
|
||
| **Files:** | ||
|
|
||
| - Create: `src/runtime.ts` | ||
| - Modify: `src/index.ts` | ||
| - Test: `test/runtime.test.ts` | ||
|
|
||
| - [ ] Add `CapletsRuntime` that creates `McpServer`, `ServerRegistry`, `DownstreamManager`, `OpenApiManager`, and `GraphQLManager`. | ||
| - [ ] Track registered top-level Caplet tools in a `Map<string, RegisteredTool>`. | ||
| - [ ] Register initial enabled Caplets during startup. | ||
| - [ ] Keep `src/index.ts` as a small CLI/server entrypoint. | ||
|
|
||
| ## Task 2: Reload Reconciliation | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `src/runtime.ts` | ||
| - Modify: `src/downstream.ts` | ||
| - Modify: `src/openapi.ts` | ||
| - Modify: `src/graphql.ts` | ||
| - Test: `test/runtime.test.ts`, `test/downstream.test.ts`, `test/openapi.test.ts`, `test/graphql.test.ts` | ||
|
|
||
| - [ ] On reload, call existing `loadConfig()` with the same resolved paths used at startup. | ||
| - [ ] Add new Caplets with `registerTool`. | ||
| - [ ] Update existing Caplets with `RegisteredTool.update`. | ||
| - [ ] Remove missing or disabled Caplets with `RegisteredTool.remove`. | ||
| - [ ] Add `DownstreamManager.closeServer(serverId)`. | ||
| - [ ] Add `OpenApiManager.invalidate(serverId)` and `GraphQLManager.invalidate(serverId)`. | ||
| - [ ] Invalidate or close only backends whose normalized config changed. | ||
| - [ ] Keep serving the previous registry and tools if reload parsing or validation fails. | ||
|
|
||
| ## Task 3: Filesystem Watching | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `src/runtime.ts` | ||
| - Test: `test/runtime.test.ts` | ||
|
|
||
| - [ ] Watch the effective user config file, project config file, user Caplets root, and trusted project Caplets root. | ||
| - [ ] Use dependency-free `fs.watch` with a 250 ms debounce. | ||
| - [ ] Watch directories so new, renamed, and deleted Markdown Caplet files are detected. | ||
| - [ ] Recreate watchers after every successful reload because roots can change with `CAPLETS_CONFIG`. | ||
| - [ ] Close all watchers during runtime shutdown. | ||
|
|
||
| ## Task 4: Documentation | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `README.md` | ||
|
|
||
| - [ ] Document that `caplets serve` hot reloads config and Caplet file changes by default. | ||
| - [ ] Document last known-good behavior for invalid edits. | ||
| - [ ] Document that changed or removed MCP-backed Caplets close only their affected downstream connection. | ||
| - [ ] Keep `pnpm dev` documented as source rebuild/restart tooling, separate from runtime config hot reload. | ||
|
|
||
| ## Task 5: Verification | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify tests as needed. | ||
|
|
||
| - [ ] Run targeted tests for runtime reload and manager invalidation. | ||
| - [ ] Run `pnpm format:check`. | ||
| - [ ] Run `pnpm lint`. | ||
| - [ ] Run `pnpm typecheck`. | ||
| - [ ] Run `pnpm schema:check`. | ||
| - [ ] Run `pnpm test`. | ||
| - [ ] Run `pnpm build`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.