remnote-mcp-server 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +82 -28
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +9 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -2
- package/dist/config.js +210 -10
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +61 -0
- package/dist/daemon.js +735 -0
- package/dist/daemon.js.map +1 -0
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/remnote-cli/cli.js +4 -0
- package/dist/remnote-cli/cli.js.map +1 -1
- package/dist/remnote-cli/client/mcp-server-client.js +7 -1
- package/dist/remnote-cli/client/mcp-server-client.js.map +1 -1
- package/dist/remnote-cli/commands/content-input.d.ts +0 -12
- package/dist/remnote-cli/commands/content-input.js +0 -20
- package/dist/remnote-cli/commands/content-input.js.map +1 -1
- package/dist/remnote-cli/commands/create.js +3 -3
- package/dist/remnote-cli/commands/create.js.map +1 -1
- package/dist/remnote-cli/commands/journal.js +3 -0
- package/dist/remnote-cli/commands/journal.js.map +1 -1
- package/dist/remnote-cli/commands/read.js +20 -2
- package/dist/remnote-cli/commands/read.js.map +1 -1
- package/dist/remnote-cli/commands/search.js +24 -5
- package/dist/remnote-cli/commands/search.js.map +1 -1
- package/dist/remnote-cli/commands/update.js +5 -24
- package/dist/remnote-cli/commands/update.js.map +1 -1
- package/dist/remnote-cli/commands/write-actions.d.ts +4 -0
- package/dist/remnote-cli/commands/write-actions.js +123 -0
- package/dist/remnote-cli/commands/write-actions.js.map +1 -0
- package/dist/schemas/remnote-schemas.d.ts +33 -10
- package/dist/schemas/remnote-schemas.js +58 -16
- package/dist/schemas/remnote-schemas.js.map +1 -1
- package/dist/tools/index.d.ts +1264 -12
- package/dist/tools/index.js +157 -47
- package/dist/tools/index.js.map +1 -1
- package/dist/websocket-server.d.ts +5 -0
- package/dist/websocket-server.js +64 -10
- package/dist/websocket-server.js.map +1 -1
- package/mcpb/remnote-local/README.md +4 -3
- package/mcpb/remnote-local/manifest.json +30 -28
- package/mcpb/remnote-local/package.json +1 -1
- package/mcpb/remnote-local/remnote-local.mcpb +0 -0
- package/mcpb/remnote-local/server/fallback-tools.generated.js +323 -0
- package/mcpb/remnote-local/server/index.js +7 -122
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,62 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.0] - 2026-05-15
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add split RemNote write tools: `remnote_insert_children`, `remnote_replace_children`, and `remnote_update_tags`, plus
|
|
15
|
+
matching `remnote-cli` commands for ordered child insertion, destructive child replacement, and exact-ID tag mutation.
|
|
16
|
+
- Add exact-ID tag assignment to `remnote_append_journal` and `remnote-cli journal --tag-ids`.
|
|
17
|
+
- Add `remnote-mcp-server daemon` lifecycle commands for detached background startup, status, logs, graceful shutdown,
|
|
18
|
+
duplicate-start protection, stable log routing, and macOS `launchd` login persistence.
|
|
19
|
+
- Add `~/.remnote-mcp-server/config.toml` for persistent server and daemon defaults, including ports, host, log levels,
|
|
20
|
+
file logs, and WebSocket request/response JSON Lines logs.
|
|
21
|
+
- Add end-user validation guidance for MCP setup checks, including a zero-config agent validation prompt.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Change `tags` output metadata to preserve exact tag Rem IDs plus names as `{ tagRemId, name }` objects.
|
|
26
|
+
- Change `remnote_search_by_tag` and `remnote-cli search-by-tag --tag-id` to search by exact tag Rem ID instead of tag
|
|
27
|
+
name or alias lookup.
|
|
28
|
+
- Update `remnote_get_playbook` guidance for the split write tools and exact-ID tag fields without expanding the
|
|
29
|
+
playbook shape.
|
|
30
|
+
- Limit `remnote_update_note` and `remnote-cli update` to metadata title updates so child and tag writes use focused
|
|
31
|
+
non-duplicative interfaces.
|
|
32
|
+
- Change `remnote_create_note` and `remnote-cli create` to use exact tag Rem IDs via `tagRemIds` / `--tag-ids` instead
|
|
33
|
+
of name-based `tags` / `--tags`.
|
|
34
|
+
- Generate MCPB manifest tools and fallback tool metadata from the canonical server tool definitions instead of
|
|
35
|
+
maintaining those copies by hand.
|
|
36
|
+
- Add daemon startup, status, log, and macOS persistence pointers to installation, configuration, and troubleshooting
|
|
37
|
+
docs.
|
|
38
|
+
- Make daemon lifecycle commands launchd-aware on macOS when the LaunchAgent is installed, and document the shared
|
|
39
|
+
control surface.
|
|
40
|
+
- Update agent-assisted live integration safeguards so agents preflight port `3001`, refuse to run when an existing
|
|
41
|
+
server is listening, and use `run-agent-integration-test.sh --preflight-only` for the same guard as real live runs.
|
|
42
|
+
- Clarify setup documentation for the official bridge plugin, compatible `remnote-mcp-server` versions, and explicit
|
|
43
|
+
`remnote-mcp-server` versus `remnote-cli` documentation targets.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- Fix OpenAI/Codex tool registration compatibility by removing top-level JSON Schema composition keywords from
|
|
48
|
+
advertised MCP tool input schemas while keeping server-side validation strict.
|
|
49
|
+
- Align MCPB manifest and fallback tool metadata with the split write tools so local Claude Desktop/MCPB clients no
|
|
50
|
+
longer see stale `remnote_update_note` content/tag fields or name-based create tags.
|
|
51
|
+
- Tighten runtime validation for split child insertion and tag updates while keeping advertised MCP JSON schemas
|
|
52
|
+
client-compatible.
|
|
53
|
+
|
|
54
|
+
## [0.14.2] - 2026-05-08
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- Reject RemNote bridge WebSocket connections that do not send a compatible bridge `hello.version`, with a clearer
|
|
59
|
+
disconnect reason and server log message pointing users to `MCP/OpenClaw Automation Bridge`.
|
|
60
|
+
- Added prominent README troubleshooting guidance for wrong or incompatible RemNote Marketplace plugin installs,
|
|
61
|
+
including the related `quentintou/remnote-mcp-bridge#8` report.
|
|
62
|
+
- Updated Claude Desktop / Cowork setup docs to clarify that local MCPB works for Cowork in the Claude Desktop app
|
|
63
|
+
when desktop extensions are enabled, while remote connectors remain required for web/mobile, cloud-hosted clients,
|
|
64
|
+
and managed deployments without local MCPB.
|
|
65
|
+
|
|
10
66
|
## [0.14.1] - 2026-05-08
|
|
11
67
|
|
|
12
68
|
### Added
|
package/README.md
CHANGED
|
@@ -9,7 +9,19 @@ MCP server and CLI package that bridges AI agents, local scripts, and coding har
|
|
|
9
9
|
[RemNote](https://remnote.com/) via the [RemNote Automation Bridge
|
|
10
10
|
plugin](https://github.com/robert7/remnote-mcp-bridge).
|
|
11
11
|
|
|
12
|
-
>
|
|
12
|
+
> **Connection issue? Check the RemNote bridge plugin and server versions first.** Use the official
|
|
13
|
+
> **MCP/OpenClaw Automation Bridge** by Robert Spiegel in RemNote, and run a compatible `remnote-mcp-server` on the same
|
|
14
|
+
> `0.x` minor line (for example, `0.15.x` with `0.15.x`). Wrong plugin flavors or mismatched versions can disconnect
|
|
15
|
+
> with a `1008` compatibility message. If Marketplace and npm releases are temporarily out of sync, pin the matching
|
|
16
|
+
> server package or run matching bridge/server checkouts from source. Start with the
|
|
17
|
+
> [version compatibility guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/bridge-consumer-version-compatibility.md),
|
|
18
|
+
> [plugin install guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/install-plugin-via-marketplace-beginner.md),
|
|
19
|
+
> [local plugin guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/development-run-plugin-locally.md), and
|
|
20
|
+
> [server installation guide](docs/guides/installation.md).
|
|
21
|
+
> After setup, see the [agent validation prompts](docs/agent-validation-prompts/README.md) to verify that your chosen AI
|
|
22
|
+
> agent can use the installed RemNote MCP tools end to end.
|
|
23
|
+
> If the guides do not resolve your problem, [open an issue](https://github.com/robert7/remnote-mcp-server/issues) with
|
|
24
|
+
> the relevant versions, setup path, observed behavior, and exact error/status message.
|
|
13
25
|
|
|
14
26
|
## What is This?
|
|
15
27
|
|
|
@@ -58,17 +70,19 @@ The server acts as a bridge:
|
|
|
58
70
|
**Multi-Agent Support:** Multiple AI agents can connect simultaneously to the same RemNote knowledge base. Each agent
|
|
59
71
|
gets its own MCP session while sharing the WebSocket bridge.
|
|
60
72
|
|
|
61
|
-
**Remote Access:** By default, the server binds to localhost (127.0.0.1) for local AI agents.
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
**Remote Access:** By default, the server binds to localhost (127.0.0.1) for local AI agents. Claude Desktop and Claude
|
|
74
|
+
Cowork can use the bundled local MCPB extension when desktop extensions are enabled. Cloud-based clients, web/mobile
|
|
75
|
+
surfaces, and managed Claude deployments without local MCPB require remote access—use tunneling tools like ngrok to
|
|
76
|
+
expose the HTTP endpoint securely. The WebSocket connection always stays local for security. See
|
|
77
|
+
[Remote Access Guide](docs/guides/remote-access.md) for setup.
|
|
64
78
|
|
|
65
79
|
## Features
|
|
66
80
|
|
|
67
81
|
- **Create Notes & Flashcards** - Create simple notes, hierarchical markdown trees, or RemNote-native flashcards
|
|
68
|
-
- **Search Knowledge Base** - Run full-text searches or tag
|
|
82
|
+
- **Search Knowledge Base** - Run full-text searches or exact tag Rem ID searches with ancestor context
|
|
69
83
|
- **Read Notes** - Retrieve note content in markdown or structured form with configurable traversal depth
|
|
70
|
-
- **Update Notes** - Modify titles,
|
|
71
|
-
- **Journal Entries** - Append timestamped daily entries
|
|
84
|
+
- **Update Notes** - Modify titles, insert or replace hierarchical content, and manage tags by exact Rem ID
|
|
85
|
+
- **Journal Entries** - Append timestamped daily entries with hierarchical markdown content and optional exact tag Rem IDs
|
|
72
86
|
- **Agent Playbook** - Return built-in navigation and safety guidance for MCP clients
|
|
73
87
|
- **Connection Status** - Check server and plugin connection health
|
|
74
88
|
|
|
@@ -92,9 +106,10 @@ remnote-mcp-stdio --version
|
|
|
92
106
|
|
|
93
107
|
### 2. Install the RemNote Plugin
|
|
94
108
|
|
|
95
|
-
Install the [
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
Install the official [MCP/OpenClaw Automation Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) in your
|
|
110
|
+
RemNote app. If installing from the RemNote Marketplace, verify the plugin name and author; similarly named
|
|
111
|
+
`MCP Bridge` variants may be incompatible with this server and cause connection loops or `1008` disconnects. Configure
|
|
112
|
+
the plugin to connect to `ws://127.0.0.1:3002`.
|
|
98
113
|
|
|
99
114
|
### 3. Start the Server
|
|
100
115
|
|
|
@@ -105,17 +120,35 @@ remnote-mcp-server
|
|
|
105
120
|
Expected output:
|
|
106
121
|
|
|
107
122
|
```text
|
|
108
|
-
RemNote MCP Server
|
|
123
|
+
RemNote MCP Server v<version> listening { wsPort: 3002, httpPort: 3001 }
|
|
109
124
|
```
|
|
110
125
|
|
|
111
126
|
Keep this terminal running.
|
|
112
127
|
|
|
128
|
+
For a background server that survives terminal close and writes to a stable log file:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
remnote-mcp-server daemon start
|
|
132
|
+
remnote-mcp-server daemon status
|
|
133
|
+
remnote-mcp-server daemon logs
|
|
134
|
+
remnote-mcp-server daemon stop
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Daemon state and logs default to `~/.remnote-mcp-server/`. On macOS, install a login LaunchAgent for restart/login
|
|
138
|
+
persistence:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
remnote-mcp-server daemon install-launchd
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
After installing the LaunchAgent, `remnote-mcp-server daemon status|start|stop|restart` controls the launchd service.
|
|
145
|
+
|
|
113
146
|
### 4. Configure Your AI Client
|
|
114
147
|
|
|
115
148
|
- [Configuration Guide](docs/guides/configuration.md) - Overview and generic setup
|
|
116
149
|
- [Codex TUI / Codex.app](docs/guides/configuration-codex.md) - HTTP MCP, stdio proxy, and `remnote-cli` skill setup
|
|
117
|
-
- [Claude Desktop Local MCPB](docs/guides/configuration-claude-desktop-local-mcpb.md) - Preferred local
|
|
118
|
-
- [Claude Desktop / Cowork](docs/guides/configuration-claude-desktop-cowork.md) - Remote connector setup when local MCPB is not applicable
|
|
150
|
+
- [Claude Desktop / Cowork Local MCPB](docs/guides/configuration-claude-desktop-local-mcpb.md) - Preferred local desktop setup, no public HTTPS required
|
|
151
|
+
- [Claude Desktop / Cowork Remote Connector](docs/guides/configuration-claude-desktop-cowork.md) - Remote connector setup when local MCPB is not applicable
|
|
119
152
|
- [Claude Code CLI](docs/guides/configuration-claude-code-CLI.md) - Claude Code local MCP setup
|
|
120
153
|
- [ChatGPT](docs/guides/configuration-chatgpt.md) - ChatGPT Apps configuration
|
|
121
154
|
- [Accomplish](docs/guides/configuration-accomplish.md) - Accomplish (Openwork) configuration
|
|
@@ -137,10 +170,11 @@ Keep this terminal running.
|
|
|
137
170
|
|
|
138
171
|
### Usage
|
|
139
172
|
|
|
140
|
-
- **[
|
|
141
|
-
- **[remnote-cli Command Reference](docs/guides/cli-command-reference.md)** - Shell command reference for the bundled CLI
|
|
173
|
+
- **[remnote-mcp-server Command Reference](docs/guides/remnote-mcp-server-command-reference.md)** - Server executable, daemon, and launchd options
|
|
174
|
+
- **[remnote-cli Command Reference](docs/guides/remnote-cli-command-reference.md)** - Shell command reference for the bundled CLI
|
|
142
175
|
- **[MCP Tools Reference](docs/guides/tools-reference.md)** - Detailed reference for all 9 RemNote tools
|
|
143
|
-
- **[Remote Access Setup](docs/guides/remote-access.md)** - Expose server for
|
|
176
|
+
- **[Remote Access Setup](docs/guides/remote-access.md)** - Expose server for cloud clients or remote connector flows
|
|
177
|
+
(ngrok, etc.)
|
|
144
178
|
|
|
145
179
|
### Help & Advanced
|
|
146
180
|
|
|
@@ -150,21 +184,26 @@ Keep this terminal running.
|
|
|
150
184
|
### Development
|
|
151
185
|
|
|
152
186
|
- **[Development Setup](docs/guides/development-setup.md)** - Contributing guide for developers
|
|
187
|
+
- **[Testing Strategy](docs/guides/testing-strategy.md)** - Three-level testing model: local quality checks, maintainer
|
|
188
|
+
live integration, and end-user agent validation
|
|
153
189
|
- **[Integration Testing](docs/guides/integration-testing.md)** - Canonical shared workflow for updating and running MCP server + CLI integration coverage against live RemNote
|
|
154
190
|
- **[Publishing Guide](docs/npm-publishing.md)** - npm publishing process (maintainers only)
|
|
155
191
|
|
|
156
192
|
## Available MCP Tools
|
|
157
193
|
|
|
158
|
-
| Tool | Description
|
|
159
|
-
|
|
160
|
-
| `remnote_create_note` | Create notes, markdown trees, or flashcards with
|
|
161
|
-
| `remnote_search` | Search knowledge base with full-text search
|
|
162
|
-
| `remnote_search_by_tag` | Search by tag with ancestor-context resolution |
|
|
163
|
-
| `remnote_read_note` | Read note by ID with metadata and markdown or structured content
|
|
164
|
-
| `remnote_update_note` | Update title
|
|
165
|
-
| `
|
|
194
|
+
| Tool | Description |
|
|
195
|
+
|---------------------------|-----------------------------------------------------------------------------|
|
|
196
|
+
| `remnote_create_note` | Create notes, markdown trees, or flashcards with optional exact tag Rem IDs |
|
|
197
|
+
| `remnote_search` | Search knowledge base with full-text search, parent context, and optional tag IDs/names |
|
|
198
|
+
| `remnote_search_by_tag` | Search by exact tag Rem ID with ancestor-context resolution |
|
|
199
|
+
| `remnote_read_note` | Read note by ID with metadata, optional tag IDs/names, and markdown or structured content |
|
|
200
|
+
| `remnote_update_note` | Update title |
|
|
201
|
+
| `remnote_insert_children` | Insert child Rems at deterministic positions |
|
|
202
|
+
| `remnote_replace_children` | Replace direct children when destructive replacement is enabled |
|
|
203
|
+
| `remnote_update_tags` | Add or remove tags by exact tag Rem ID |
|
|
204
|
+
| `remnote_append_journal` | Append hierarchical content to today's daily document with optional tag Rem IDs |
|
|
166
205
|
| `remnote_read_table` | Read Advanced Table columns, rows, and typed property metadata |
|
|
167
|
-
| `remnote_get_playbook` | Get recommended MCP usage/navigation playbook
|
|
206
|
+
| `remnote_get_playbook` | Get recommended MCP usage/navigation playbook |
|
|
168
207
|
| `remnote_status` | Check connection status and statistics |
|
|
169
208
|
|
|
170
209
|
Tools that declare an `outputSchema` return MCP `structuredContent` plus a JSON `content` text block for compatibility.
|
|
@@ -181,7 +220,8 @@ See the [Tools Reference](docs/guides/tools-reference.md) for detailed usage and
|
|
|
181
220
|
|
|
182
221
|
- **[Claude Code CLI](https://claude.com/claude-code)** - Local terminal-based agent
|
|
183
222
|
- **Codex TUI / Codex.app** - Local OpenAI coding agent clients
|
|
184
|
-
- **Claude Desktop / Cowork** -
|
|
223
|
+
- **Claude Desktop / Cowork** - Local MCPB clients when desktop extensions are enabled, or remote connector clients
|
|
224
|
+
when local MCPB is not applicable
|
|
185
225
|
- **[Accomplish](https://github.com/accomplish-ai/accomplish)** - Task-based MCP client (formerly Openwork)
|
|
186
226
|
- **Any MCP client** supporting Streamable HTTP transport
|
|
187
227
|
- **Any local MCP client** supporting stdio transport through `remnote-mcp-stdio`
|
|
@@ -233,7 +273,21 @@ remnote-mcp-server --http-port 3003 --ws-port 3004
|
|
|
233
273
|
|
|
234
274
|
After changing ports, update your MCP client configuration and RemNote plugin settings.
|
|
235
275
|
|
|
236
|
-
|
|
276
|
+
### Background Daemon
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
remnote-mcp-server daemon start
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
- Default log: `~/.remnote-mcp-server/remnote-mcp-server.log`
|
|
283
|
+
- Duplicate starts are treated as already running when the daemon PID is alive.
|
|
284
|
+
- If the configured HTTP or WebSocket port is already occupied, startup fails before spawning a second server.
|
|
285
|
+
- Use `remnote-mcp-server daemon stop` for graceful shutdown.
|
|
286
|
+
- Use `remnote-mcp-server daemon install-launchd` on macOS to keep the server running across login and unexpected
|
|
287
|
+
exits.
|
|
288
|
+
- When launchd is installed, the same `daemon status/start/stop/restart` commands control the launchd service.
|
|
289
|
+
|
|
290
|
+
See [remnote-mcp-server Command Reference](docs/guides/remnote-mcp-server-command-reference.md) for all options.
|
|
237
291
|
|
|
238
292
|
## Troubleshooting
|
|
239
293
|
|
|
@@ -283,7 +337,7 @@ See the [Development Setup Guide](docs/guides/development-setup.md) for complete
|
|
|
283
337
|
|
|
284
338
|
Pull requests that affect bridge-consumer behavior should follow the shared PR rules in the bridge repo: [Pull Request Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/pull-request-guide.md). In particular, keep bridge and server-package behavior aligned for shared functionality changes.
|
|
285
339
|
|
|
286
|
-
For the
|
|
340
|
+
For the three-level testing model and links to each verification path, see the [Testing Strategy](docs/guides/testing-strategy.md).
|
|
287
341
|
|
|
288
342
|
## Related Projects
|
|
289
343
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export interface CliOptions {
|
|
2
|
+
config?: string;
|
|
2
3
|
wsPort?: number;
|
|
3
4
|
httpPort?: number;
|
|
4
5
|
httpHost?: string;
|
|
@@ -13,7 +14,7 @@ export declare function getBundledMcpbPath(): string;
|
|
|
13
14
|
/**
|
|
14
15
|
* Handle utility commands that do not start the MCP server.
|
|
15
16
|
*/
|
|
16
|
-
export declare function handleUtilityCommand(argv?: string[]): boolean
|
|
17
|
+
export declare function handleUtilityCommand(argv?: string[]): Promise<boolean>;
|
|
17
18
|
/**
|
|
18
19
|
* Parse CLI arguments and return typed options
|
|
19
20
|
*/
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { handleDaemonCommand, isDaemonCommand } from './daemon.js';
|
|
4
5
|
const require = createRequire(import.meta.url);
|
|
5
6
|
const packageJson = require('../package.json');
|
|
6
7
|
const validLogLevels = ['debug', 'info', 'warn', 'error'];
|
|
@@ -11,8 +12,13 @@ export function getBundledMcpbPath() {
|
|
|
11
12
|
/**
|
|
12
13
|
* Handle utility commands that do not start the MCP server.
|
|
13
14
|
*/
|
|
14
|
-
export function handleUtilityCommand(argv = process.argv) {
|
|
15
|
+
export async function handleUtilityCommand(argv = process.argv) {
|
|
15
16
|
if (argv[2] !== MCPB_PATH_COMMAND) {
|
|
17
|
+
if (isDaemonCommand(argv)) {
|
|
18
|
+
const result = await handleDaemonCommand(argv);
|
|
19
|
+
process.exitCode = result.exitCode;
|
|
20
|
+
return result.handled;
|
|
21
|
+
}
|
|
16
22
|
return false;
|
|
17
23
|
}
|
|
18
24
|
console.log(getBundledMcpbPath());
|
|
@@ -27,10 +33,11 @@ export function parseCliArgs() {
|
|
|
27
33
|
.name('remnote-mcp-server')
|
|
28
34
|
.description('MCP server bridge for RemNote knowledge base')
|
|
29
35
|
.version(packageJson.version)
|
|
30
|
-
.addHelpText('after', '\nCommands:\n mcpb-path Print the bundled Claude Desktop MCPB extension path')
|
|
36
|
+
.addHelpText('after', '\nCommands:\n mcpb-path Print the bundled Claude Desktop MCPB extension path\n daemon <action> Manage background server lifecycle and macOS launchd persistence')
|
|
31
37
|
.option('--ws-port <number>', 'WebSocket port (default: 3002, env: REMNOTE_WS_PORT)', parsePort)
|
|
32
38
|
.option('--http-port <number>', 'HTTP MCP port (default: 3001, env: REMNOTE_HTTP_PORT)', parsePort)
|
|
33
39
|
.option('--http-host <host>', 'HTTP server bind address (default: 127.0.0.1, env: REMNOTE_HTTP_HOST). Use 0.0.0.0 for Docker/VPS deployments', validateHost)
|
|
40
|
+
.option('--config <path>', 'TOML config file path (default: ~/.remnote-mcp-server/config.toml)')
|
|
34
41
|
.option('--log-level <level>', `Console log level: ${validLogLevels.join(', ')} (default: info)`, validateLogLevel)
|
|
35
42
|
.option('--log-level-file <level>', `File log level (default: same as --log-level)`, validateLogLevel)
|
|
36
43
|
.option('--verbose', 'Shorthand for --log-level debug')
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -11,8 +11,20 @@ export interface ServerConfig {
|
|
|
11
11
|
responseLog?: string;
|
|
12
12
|
prettyLogs: boolean;
|
|
13
13
|
}
|
|
14
|
+
export interface ConfigFileOptions {
|
|
15
|
+
server?: Partial<Omit<CliOptions, 'config'>>;
|
|
16
|
+
daemon?: {
|
|
17
|
+
logFile?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface ConfigLoadOptions {
|
|
21
|
+
homeDir?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const CONFIG_FILE_NAME = "config.toml";
|
|
14
24
|
/**
|
|
15
25
|
* Merge CLI options with environment variables and apply defaults
|
|
16
|
-
* Precedence: CLI > Environment Variables > Defaults
|
|
26
|
+
* Precedence: CLI > Environment Variables > Config File > Defaults
|
|
17
27
|
*/
|
|
18
|
-
export declare function getConfig(cliOptions: CliOptions): ServerConfig;
|
|
28
|
+
export declare function getConfig(cliOptions: CliOptions, loadOptions?: ConfigLoadOptions): ServerConfig;
|
|
29
|
+
export declare function loadConfigFileOptions(configPath?: string, loadOptions?: ConfigLoadOptions): ConfigFileOptions;
|
|
30
|
+
export declare function parseConfigToml(source: string, filePath?: string): ConfigFileOptions;
|
package/dist/config.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export const CONFIG_FILE_NAME = 'config.toml';
|
|
1
5
|
/**
|
|
2
6
|
* Merge CLI options with environment variables and apply defaults
|
|
3
|
-
* Precedence: CLI > Environment Variables > Defaults
|
|
7
|
+
* Precedence: CLI > Environment Variables > Config File > Defaults
|
|
4
8
|
*/
|
|
5
|
-
export function getConfig(cliOptions) {
|
|
9
|
+
export function getConfig(cliOptions, loadOptions = {}) {
|
|
10
|
+
const homeDir = loadOptions.homeDir ?? homedir();
|
|
11
|
+
const configFile = loadConfigFileOptions(cliOptions.config, loadOptions);
|
|
12
|
+
const configOptions = configFile.server ?? {};
|
|
6
13
|
// Apply verbose flag override
|
|
7
|
-
let logLevel = cliOptions.logLevel
|
|
14
|
+
let logLevel = cliOptions.logLevel ?? (configOptions.verbose ? 'debug' : configOptions.logLevel) ?? 'info';
|
|
8
15
|
if (cliOptions.verbose) {
|
|
9
16
|
logLevel = 'debug';
|
|
10
17
|
}
|
|
@@ -17,18 +24,30 @@ export function getConfig(cliOptions) {
|
|
|
17
24
|
throw new Error(`Invalid HTTP port: ${cliOptions.httpPort}. Must be between 1 and 65535.`);
|
|
18
25
|
}
|
|
19
26
|
// Get ports with CLI > env > default precedence
|
|
20
|
-
const wsPort = cliOptions.wsPort
|
|
21
|
-
|
|
27
|
+
const wsPort = cliOptions.wsPort ??
|
|
28
|
+
parseOptionalPortEnv(process.env.REMNOTE_WS_PORT) ??
|
|
29
|
+
configOptions.wsPort ??
|
|
30
|
+
3002;
|
|
31
|
+
const httpPort = cliOptions.httpPort ??
|
|
32
|
+
parseOptionalPortEnv(process.env.REMNOTE_HTTP_PORT) ??
|
|
33
|
+
configOptions.httpPort ??
|
|
34
|
+
3001;
|
|
22
35
|
// Get hosts with CLI > env > default precedence
|
|
23
36
|
// SECURITY: WebSocket ALWAYS binds to localhost, regardless of env var or CLI option
|
|
24
37
|
const wsHost = '127.0.0.1';
|
|
25
|
-
const httpHost = cliOptions.httpHost
|
|
38
|
+
const httpHost = cliOptions.httpHost ?? process.env.REMNOTE_HTTP_HOST ?? configOptions.httpHost ?? '127.0.0.1';
|
|
26
39
|
// Validate port conflicts
|
|
27
40
|
if (wsPort === httpPort) {
|
|
28
41
|
throw new Error(`WebSocket port and HTTP port cannot be the same (both set to ${wsPort})`);
|
|
29
42
|
}
|
|
43
|
+
const logFileOption = cliOptions.logFile ?? configOptions.logFile;
|
|
44
|
+
const logFile = logFileOption ? resolveTilde(logFileOption, homeDir) : undefined;
|
|
45
|
+
const requestLogOption = cliOptions.requestLog ?? configOptions.requestLog;
|
|
46
|
+
const requestLog = requestLogOption ? resolveTilde(requestLogOption, homeDir) : undefined;
|
|
47
|
+
const responseLogOption = cliOptions.responseLog ?? configOptions.responseLog;
|
|
48
|
+
const responseLog = responseLogOption ? resolveTilde(responseLogOption, homeDir) : undefined;
|
|
30
49
|
// File log level defaults to console log level if not specified
|
|
31
|
-
const logLevelFile = cliOptions.logLevelFile
|
|
50
|
+
const logLevelFile = cliOptions.logLevelFile ?? configOptions.logLevelFile ?? (logFile ? logLevel : undefined);
|
|
32
51
|
// Pretty logs in development (when using pino-pretty)
|
|
33
52
|
const prettyLogs = process.stdout.isTTY === true;
|
|
34
53
|
return {
|
|
@@ -38,10 +57,191 @@ export function getConfig(cliOptions) {
|
|
|
38
57
|
httpHost,
|
|
39
58
|
logLevel,
|
|
40
59
|
logLevelFile,
|
|
41
|
-
logFile
|
|
42
|
-
requestLog
|
|
43
|
-
responseLog
|
|
60
|
+
logFile,
|
|
61
|
+
requestLog,
|
|
62
|
+
responseLog,
|
|
44
63
|
prettyLogs,
|
|
45
64
|
};
|
|
46
65
|
}
|
|
66
|
+
export function loadConfigFileOptions(configPath, loadOptions = {}) {
|
|
67
|
+
const homeDir = loadOptions.homeDir ?? homedir();
|
|
68
|
+
const resolvedPath = resolveTilde(configPath ?? join('~', '.remnote-mcp-server', CONFIG_FILE_NAME), homeDir);
|
|
69
|
+
const explicitPath = configPath !== undefined;
|
|
70
|
+
if (!existsSync(resolvedPath)) {
|
|
71
|
+
if (explicitPath) {
|
|
72
|
+
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
73
|
+
}
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
return parseConfigToml(readFileSync(resolvedPath, 'utf8'), resolvedPath);
|
|
77
|
+
}
|
|
78
|
+
export function parseConfigToml(source, filePath = CONFIG_FILE_NAME) {
|
|
79
|
+
const config = {};
|
|
80
|
+
let section;
|
|
81
|
+
source.split(/\r?\n/).forEach((rawLine, index) => {
|
|
82
|
+
const lineNumber = index + 1;
|
|
83
|
+
const line = stripTomlComment(rawLine).trim();
|
|
84
|
+
if (!line) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const sectionMatch = line.match(/^\[([A-Za-z0-9_-]+)\]$/);
|
|
88
|
+
if (sectionMatch) {
|
|
89
|
+
const parsedSection = sectionMatch[1];
|
|
90
|
+
if (parsedSection !== 'server' && parsedSection !== 'daemon') {
|
|
91
|
+
throw new Error(`${filePath}:${lineNumber}: Unknown config section [${parsedSection}]`);
|
|
92
|
+
}
|
|
93
|
+
section = parsedSection;
|
|
94
|
+
config[section] ??= {};
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!section) {
|
|
98
|
+
throw new Error(`${filePath}:${lineNumber}: Config values must be under [server] or [daemon]`);
|
|
99
|
+
}
|
|
100
|
+
const keyValueMatch = line.match(/^([A-Za-z][A-Za-z0-9_]*)\s*=\s*(.+)$/);
|
|
101
|
+
if (!keyValueMatch) {
|
|
102
|
+
throw new Error(`${filePath}:${lineNumber}: Invalid TOML assignment`);
|
|
103
|
+
}
|
|
104
|
+
const [, key, rawValue] = keyValueMatch;
|
|
105
|
+
const value = parseTomlValue(rawValue.trim(), filePath, lineNumber);
|
|
106
|
+
assignConfigValue(config, section, key, value, filePath, lineNumber);
|
|
107
|
+
});
|
|
108
|
+
return config;
|
|
109
|
+
}
|
|
110
|
+
function assignConfigValue(config, section, key, value, filePath, lineNumber) {
|
|
111
|
+
if (section === 'daemon') {
|
|
112
|
+
if (key !== 'logFile') {
|
|
113
|
+
throw new Error(`${filePath}:${lineNumber}: Unknown daemon config key "${key}"`);
|
|
114
|
+
}
|
|
115
|
+
config.daemon ??= {};
|
|
116
|
+
config.daemon.logFile = expectString(value, filePath, lineNumber, key);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
config.server ??= {};
|
|
120
|
+
switch (key) {
|
|
121
|
+
case 'wsPort':
|
|
122
|
+
config.server.wsPort = expectPort(value, filePath, lineNumber, key);
|
|
123
|
+
return;
|
|
124
|
+
case 'httpPort':
|
|
125
|
+
config.server.httpPort = expectPort(value, filePath, lineNumber, key);
|
|
126
|
+
return;
|
|
127
|
+
case 'httpHost':
|
|
128
|
+
config.server.httpHost = validateHost(expectString(value, filePath, lineNumber, key), filePath, lineNumber);
|
|
129
|
+
return;
|
|
130
|
+
case 'logLevel':
|
|
131
|
+
config.server.logLevel = validateLogLevel(expectString(value, filePath, lineNumber, key), filePath, lineNumber);
|
|
132
|
+
return;
|
|
133
|
+
case 'logLevelFile':
|
|
134
|
+
config.server.logLevelFile = validateLogLevel(expectString(value, filePath, lineNumber, key), filePath, lineNumber);
|
|
135
|
+
return;
|
|
136
|
+
case 'verbose':
|
|
137
|
+
config.server.verbose = expectBoolean(value, filePath, lineNumber, key);
|
|
138
|
+
return;
|
|
139
|
+
case 'logFile':
|
|
140
|
+
config.server.logFile = expectString(value, filePath, lineNumber, key);
|
|
141
|
+
return;
|
|
142
|
+
case 'requestLog':
|
|
143
|
+
config.server.requestLog = expectString(value, filePath, lineNumber, key);
|
|
144
|
+
return;
|
|
145
|
+
case 'responseLog':
|
|
146
|
+
config.server.responseLog = expectString(value, filePath, lineNumber, key);
|
|
147
|
+
return;
|
|
148
|
+
default:
|
|
149
|
+
throw new Error(`${filePath}:${lineNumber}: Unknown server config key "${key}"`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function parseOptionalPortEnv(value) {
|
|
153
|
+
if (value === undefined) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return parseInt(value, 10);
|
|
157
|
+
}
|
|
158
|
+
function parseTomlValue(value, filePath, lineNumber) {
|
|
159
|
+
if (value === 'true') {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
if (value === 'false') {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
if (/^-?\d+$/.test(value)) {
|
|
166
|
+
return Number(value);
|
|
167
|
+
}
|
|
168
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
169
|
+
return value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
|
170
|
+
}
|
|
171
|
+
throw new Error(`${filePath}:${lineNumber}: Unsupported TOML value`);
|
|
172
|
+
}
|
|
173
|
+
function stripTomlComment(line) {
|
|
174
|
+
let inString = false;
|
|
175
|
+
let escaped = false;
|
|
176
|
+
for (let i = 0; i < line.length; i += 1) {
|
|
177
|
+
const char = line[i];
|
|
178
|
+
if (escaped) {
|
|
179
|
+
escaped = false;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (char === '\\' && inString) {
|
|
183
|
+
escaped = true;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (char === '"') {
|
|
187
|
+
inString = !inString;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (char === '#' && !inString) {
|
|
191
|
+
return line.slice(0, i);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return line;
|
|
195
|
+
}
|
|
196
|
+
function expectString(value, filePath, lineNumber, key) {
|
|
197
|
+
if (typeof value !== 'string') {
|
|
198
|
+
throw new Error(`${filePath}:${lineNumber}: Config key "${key}" must be a string`);
|
|
199
|
+
}
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
function expectBoolean(value, filePath, lineNumber, key) {
|
|
203
|
+
if (typeof value !== 'boolean') {
|
|
204
|
+
throw new Error(`${filePath}:${lineNumber}: Config key "${key}" must be a boolean`);
|
|
205
|
+
}
|
|
206
|
+
return value;
|
|
207
|
+
}
|
|
208
|
+
function expectPort(value, filePath, lineNumber, key) {
|
|
209
|
+
if (typeof value !== 'number') {
|
|
210
|
+
throw new Error(`${filePath}:${lineNumber}: Config key "${key}" must be a number`);
|
|
211
|
+
}
|
|
212
|
+
if (value < 1 || value > 65535) {
|
|
213
|
+
throw new Error(`${filePath}:${lineNumber}: Config key "${key}" must be between 1 and 65535`);
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
function validateLogLevel(value, filePath, lineNumber) {
|
|
218
|
+
const normalized = value.toLowerCase();
|
|
219
|
+
if (!['debug', 'info', 'warn', 'error'].includes(normalized)) {
|
|
220
|
+
throw new Error(`${filePath}:${lineNumber}: Invalid log level "${value}"`);
|
|
221
|
+
}
|
|
222
|
+
return normalized;
|
|
223
|
+
}
|
|
224
|
+
function validateHost(value, filePath, lineNumber) {
|
|
225
|
+
if (value === 'localhost' || value === '127.0.0.1' || value === '0.0.0.0') {
|
|
226
|
+
return value;
|
|
227
|
+
}
|
|
228
|
+
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
229
|
+
if (!ipv4Pattern.test(value)) {
|
|
230
|
+
throw new Error(`${filePath}:${lineNumber}: Invalid HTTP host "${value}"`);
|
|
231
|
+
}
|
|
232
|
+
const octets = value.split('.').map(Number);
|
|
233
|
+
if (octets.some((octet) => octet < 0 || octet > 255)) {
|
|
234
|
+
throw new Error(`${filePath}:${lineNumber}: Invalid HTTP host "${value}"`);
|
|
235
|
+
}
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
function resolveTilde(pathValue, homeDir) {
|
|
239
|
+
if (pathValue === '~') {
|
|
240
|
+
return homeDir;
|
|
241
|
+
}
|
|
242
|
+
if (pathValue.startsWith('~/')) {
|
|
243
|
+
return join(homeDir, pathValue.slice(2));
|
|
244
|
+
}
|
|
245
|
+
return pathValue;
|
|
246
|
+
}
|
|
47
247
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA2BjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,UAAsB,EACtB,cAAiC,EAAE;IAEnC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC;IACjD,MAAM,UAAU,GAAG,qBAAqB,CAAC,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC;IAE9C,8BAA8B;IAC9B,IAAI,QAAQ,GACV,UAAU,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC;IAC9F,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;IAED,0CAA0C;IAC1C,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,2BAA2B,UAAU,CAAC,MAAM,gCAAgC,CAAC,CAAC;IAChG,CAAC;IACD,IACE,UAAU,CAAC,QAAQ,KAAK,SAAS;QACjC,CAAC,UAAU,CAAC,QAAQ,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,GAAG,KAAK,CAAC,EACxD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,UAAU,CAAC,QAAQ,gCAAgC,CAAC,CAAC;IAC7F,CAAC;IAED,gDAAgD;IAChD,MAAM,MAAM,GACV,UAAU,CAAC,MAAM;QACjB,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QACjD,aAAa,CAAC,MAAM;QACpB,IAAI,CAAC;IACP,MAAM,QAAQ,GACZ,UAAU,CAAC,QAAQ;QACnB,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACnD,aAAa,CAAC,QAAQ;QACtB,IAAI,CAAC;IAEP,gDAAgD;IAChD,qFAAqF;IACrF,MAAM,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,QAAQ,GACZ,UAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,aAAa,CAAC,QAAQ,IAAI,WAAW,CAAC;IAEhG,0BAA0B;IAC1B,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,gEAAgE,MAAM,GAAG,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC;IAClE,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,MAAM,gBAAgB,GAAG,UAAU,CAAC,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC;IAC3E,MAAM,UAAU,GAAG,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,MAAM,iBAAiB,GAAG,UAAU,CAAC,WAAW,IAAI,aAAa,CAAC,WAAW,CAAC;IAC9E,MAAM,WAAW,GAAG,iBAAiB,CAAC,CAAC,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7F,gEAAgE;IAChE,MAAM,YAAY,GAChB,UAAU,CAAC,YAAY,IAAI,aAAa,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAE5F,sDAAsD;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;IAEjD,OAAO;QACL,MAAM;QACN,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,YAAY;QACZ,OAAO;QACP,UAAU;QACV,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,UAAmB,EACnB,cAAiC,EAAE;IAEnC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC;IACjD,MAAM,YAAY,GAAG,YAAY,CAC/B,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,qBAAqB,EAAE,gBAAgB,CAAC,EAChE,OAAO,CACR,CAAC;IACF,MAAM,YAAY,GAAG,UAAU,KAAK,SAAS,CAAC;IAE9C,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,eAAe,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,QAAQ,GAAG,gBAAgB;IACzE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,OAAwC,CAAC;IAE7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/C,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC1D,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;gBAC7D,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,6BAA6B,aAAa,GAAG,CAAC,CAAC;YAC1F,CAAC;YACD,OAAO,GAAG,aAAa,CAAC;YACxB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,IAAI,UAAU,oDAAoD,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACzE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,2BAA2B,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,aAAa,CAAC;QACxC,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CACxB,MAAyB,EACzB,OAA4B,EAC5B,GAAW,EACX,KAAgC,EAChC,QAAgB,EAChB,UAAkB;IAElB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,gCAAgC,GAAG,GAAG,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC;IACrB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,QAAQ;YACX,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACpE,OAAO;QACT,KAAK,UAAU;YACb,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACtE,OAAO;QACT,KAAK,UAAU;YACb,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,YAAY,CACnC,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,EAC9C,QAAQ,EACR,UAAU,CACX,CAAC;YACF,OAAO;QACT,KAAK,UAAU;YACb,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,gBAAgB,CACvC,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,EAC9C,QAAQ,EACR,UAAU,CACX,CAAC;YACF,OAAO;QACT,KAAK,cAAc;YACjB,MAAM,CAAC,MAAM,CAAC,YAAY,GAAG,gBAAgB,CAC3C,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,EAC9C,QAAQ,EACR,UAAU,CACX,CAAC;YACF,OAAO;QACT,KAAK,SAAS;YACZ,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACxE,OAAO;QACT,KAAK,SAAS;YACZ,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACvE,OAAO;QACT,KAAK,YAAY;YACf,MAAM,CAAC,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC1E,OAAO;QACT,KAAK,aAAa;YAChB,MAAM,CAAC,MAAM,CAAC,WAAW,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC3E,OAAO;QACT;YACE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,gCAAgC,GAAG,GAAG,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,cAAc,CACrB,KAAa,EACb,QAAgB,EAChB,UAAkB;IAElB,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,0BAA0B,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,QAAQ,GAAG,CAAC,QAAQ,CAAC;YACrB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CACnB,KAAgC,EAChC,QAAgB,EAChB,UAAkB,EAClB,GAAW;IAEX,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,iBAAiB,GAAG,oBAAoB,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CACpB,KAAgC,EAChC,QAAgB,EAChB,UAAkB,EAClB,GAAW;IAEX,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,iBAAiB,GAAG,qBAAqB,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CACjB,KAAgC,EAChC,QAAgB,EAChB,UAAkB,EAClB,GAAW;IAEX,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,iBAAiB,GAAG,oBAAoB,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,iBAAiB,GAAG,+BAA+B,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,QAAgB,EAAE,UAAkB;IAC3E,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,wBAAwB,KAAK,GAAG,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,QAAgB,EAAE,UAAkB;IACvE,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,yBAAyB,CAAC;IAC9C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,wBAAwB,KAAK,GAAG,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,UAAU,wBAAwB,KAAK,GAAG,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,SAAiB,EAAE,OAAe;IACtD,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|