@ticktockbent/charlotte 0.2.0 → 0.4.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 +37 -0
- package/README.md +95 -15
- package/dist/browser/page-manager.d.ts +29 -1
- package/dist/browser/page-manager.d.ts.map +1 -1
- package/dist/browser/page-manager.js +134 -20
- package/dist/browser/page-manager.js.map +1 -1
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +40 -0
- package/dist/cli.js.map +1 -0
- package/dist/dev/dev-mode-state.d.ts +3 -0
- package/dist/dev/dev-mode-state.d.ts.map +1 -1
- package/dist/dev/dev-mode-state.js +5 -0
- package/dist/dev/dev-mode-state.js.map +1 -1
- package/dist/dev/static-server.d.ts +1 -0
- package/dist/dev/static-server.d.ts.map +1 -1
- package/dist/dev/static-server.js +9 -2
- package/dist/dev/static-server.js.map +1 -1
- package/dist/index.js +24 -7
- package/dist/index.js.map +1 -1
- package/dist/renderer/content-extractor.d.ts.map +1 -1
- package/dist/renderer/content-extractor.js +10 -4
- package/dist/renderer/content-extractor.js.map +1 -1
- package/dist/renderer/renderer-pipeline.d.ts.map +1 -1
- package/dist/renderer/renderer-pipeline.js +4 -1
- package/dist/renderer/renderer-pipeline.js.map +1 -1
- package/dist/server.d.ts +13 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53 -12
- package/dist/server.js.map +1 -1
- package/dist/state/artifact-store.d.ts +52 -0
- package/dist/state/artifact-store.d.ts.map +1 -0
- package/dist/state/artifact-store.js +160 -0
- package/dist/state/artifact-store.js.map +1 -0
- package/dist/tools/dev-mode.d.ts +2 -2
- package/dist/tools/dev-mode.d.ts.map +1 -1
- package/dist/tools/dev-mode.js +5 -3
- package/dist/tools/dev-mode.js.map +1 -1
- package/dist/tools/dialog.d.ts +5 -0
- package/dist/tools/dialog.d.ts.map +1 -0
- package/dist/tools/dialog.js +70 -0
- package/dist/tools/dialog.js.map +1 -0
- package/dist/tools/evaluate.d.ts +2 -2
- package/dist/tools/evaluate.d.ts.map +1 -1
- package/dist/tools/evaluate.js +4 -2
- package/dist/tools/evaluate.js.map +1 -1
- package/dist/tools/interaction.d.ts +2 -1
- package/dist/tools/interaction.d.ts.map +1 -1
- package/dist/tools/interaction.js +151 -29
- package/dist/tools/interaction.js.map +1 -1
- package/dist/tools/meta-tool.d.ts +14 -0
- package/dist/tools/meta-tool.d.ts.map +1 -0
- package/dist/tools/meta-tool.js +123 -0
- package/dist/tools/meta-tool.js.map +1 -0
- package/dist/tools/monitoring.d.ts +4 -0
- package/dist/tools/monitoring.d.ts.map +1 -0
- package/dist/tools/monitoring.js +129 -0
- package/dist/tools/monitoring.js.map +1 -0
- package/dist/tools/navigation.d.ts +2 -1
- package/dist/tools/navigation.d.ts.map +1 -1
- package/dist/tools/navigation.js +6 -4
- package/dist/tools/navigation.js.map +1 -1
- package/dist/tools/observation.d.ts +2 -1
- package/dist/tools/observation.d.ts.map +1 -1
- package/dist/tools/observation.js +151 -12
- package/dist/tools/observation.js.map +1 -1
- package/dist/tools/session.d.ts +2 -1
- package/dist/tools/session.d.ts.map +1 -1
- package/dist/tools/session.js +32 -13
- package/dist/tools/session.js.map +1 -1
- package/dist/tools/tool-groups.d.ts +42 -0
- package/dist/tools/tool-groups.d.ts.map +1 -0
- package/dist/tools/tool-groups.js +247 -0
- package/dist/tools/tool-groups.js.map +1 -0
- package/dist/tools/tool-helpers.d.ts +11 -0
- package/dist/tools/tool-helpers.d.ts.map +1 -1
- package/dist/tools/tool-helpers.js +30 -1
- package/dist/tools/tool-helpers.js.map +1 -1
- package/dist/types/config.d.ts +6 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/page-representation.d.ts +8 -0
- package/dist/types/page-representation.d.ts.map +1 -1
- package/dist/utils/wait.js +1 -1
- package/dist/utils/wait.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Charlotte will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.4.0] - 2026-03-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Tiered tool visibility** — Startup profiles control which tools load into the agent's context. `--profile=browse` (default, 22 tools) replaces the previous behavior of loading all 40 tools. Six profiles available: `core` (7), `browse` (22), `interact` (27), `develop` (30), `audit` (13), `full` (40). Granular group selection via `--tools=group1,group2`.
|
|
10
|
+
- **`charlotte:tools` meta-tool** — Runtime tool group management. Agents can list available groups, enable groups to activate tools mid-session, and disable groups to reduce overhead — without restarting the server. Always registered regardless of profile.
|
|
11
|
+
- **Profile benchmark suite** — `npx tsx benchmarks/run-benchmarks.ts --suite profiles` runs tool definition overhead benchmarks across full, browse, and core profiles. Four tests: pure overhead measurement, 5-site browsing session, form interaction, and runtime toggle correctness. Results archived under `benchmarks/results/raw/tiered-profiles-v1/`.
|
|
12
|
+
- **`charlotte:drag`** — Drag an element to another element using mouse primitives (mousedown → intermediate moves → mouseup). Accepts `source_id` and `target_id` element IDs. Closes GAP-01 from the Playwright MCP gap analysis.
|
|
13
|
+
- **Landmark IDs** — Landmarks now have stable hash-based IDs (`rgn-xxxx`) like headings and interactive elements, making them referenceable by tools (e.g., as drag-and-drop targets).
|
|
14
|
+
- **`charlotte:console`** — Retrieve console messages from the active page at all severity levels (log, info, warn, error, debug) with timestamps. Supports level filtering and buffer clearing. Closes GAP-21 from the Playwright MCP gap analysis.
|
|
15
|
+
- **`charlotte:requests`** — Retrieve network request history from the active page with method, status, resource type, and timestamps. Supports filtering by URL pattern, resource type, and minimum status code. Closes GAP-22 from the Playwright MCP gap analysis.
|
|
16
|
+
- **Modifier key clicks** — `charlotte:click` now accepts an optional `modifiers` parameter (`ctrl`, `shift`, `alt`, `meta`, or combinations) for Ctrl+Click, Shift+Click, etc. Works with all click types (left, right, double).
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Pseudo-element content duplication** — `extractFullContent()` was emitting both content-role node names and their StaticText children, causing duplicate text when CSS `::before`/`::after` pseudo-elements were present.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Default startup profile is now `browse` (22 tools) instead of loading all 40 tools. Use `--profile=full` for the previous behavior.
|
|
25
|
+
- PageManager now captures all console messages and all network responses (not just errors). Ring buffers capped at 1000 entries each. Backward-compatible: `getConsoleErrors()` and `getNetworkErrors()` still return only errors for `PageRepresentation.errors`.
|
|
26
|
+
- Static server now binds to `127.0.0.1` instead of `0.0.0.0`, preventing external network access. Directory traversal prevention via `allowedWorkspaceRoot` validation with `fs.realpathSync()`.
|
|
27
|
+
|
|
28
|
+
## [0.3.0] - 2026-02-24
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`charlotte:dialog`** — Accept or dismiss JavaScript dialogs (`alert`, `confirm`, `prompt`, `beforeunload`). Dialogs are captured by PageManager and surfaced as `pending_dialog` in every tool response while blocking. Response includes `dialog_handled` metadata confirming what was resolved. Closes GAP-03 from the Playwright MCP gap analysis.
|
|
33
|
+
- **Dialog-aware action racing** — Interaction tools (`click`, `submit`) now race the action against dialog detection. Clicks that trigger dialogs return immediately with `pending_dialog` instead of hanging for 30s.
|
|
34
|
+
- **`dialog_auto_dismiss` configuration** — New parameter on `charlotte:configure` to auto-handle dialogs without explicit tool calls. Options: `"none"` (default, queue for manual handling), `"accept_alerts"`, `"accept_all"`, `"dismiss_all"`.
|
|
35
|
+
- **Dialog-blocking stub responses** — When a dialog is open, `renderActivePage` returns a minimal stub representation (since `page.title()` hangs while dialogs are blocking). The stub includes `pending_dialog` so agents always know a dialog needs handling.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- `PageManager` now accepts `CharlotteConfig` in its constructor for dialog auto-dismiss configuration.
|
|
40
|
+
- Config initialization moved before `PageManager` creation in `src/index.ts`.
|
|
41
|
+
|
|
5
42
|
## [0.2.0] - 2026-02-22
|
|
6
43
|
|
|
7
44
|
### Changed
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Charlotte takes a different approach. It decomposes each page into a typed, stru
|
|
|
12
12
|
|
|
13
13
|
### Benchmarks
|
|
14
14
|
|
|
15
|
-
Charlotte v0.
|
|
15
|
+
Charlotte v0.4.0 vs Playwright MCP, measured by characters returned per tool call on real websites:
|
|
16
16
|
|
|
17
17
|
**Navigation** (first contact with a page):
|
|
18
18
|
|
|
@@ -25,16 +25,15 @@ Charlotte v0.2.0 vs Playwright MCP, measured by characters returned per tool cal
|
|
|
25
25
|
|
|
26
26
|
Charlotte's `navigate` returns minimal detail by default — landmarks, headings, and interactive element counts grouped by page region. Enough to orient, not enough to overwhelm. On Wikipedia, that's **135x smaller** than Playwright's response.
|
|
27
27
|
|
|
28
|
-
**
|
|
28
|
+
**Tool definition overhead** (invisible cost per API call):
|
|
29
29
|
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
| GitHub repo | 37,628 | 80,190 |
|
|
30
|
+
| Profile | Tools | Def. tokens/call | Savings vs full |
|
|
31
|
+
|:---|---:|---:|---:|
|
|
32
|
+
| full | 40 | 7,187 | — |
|
|
33
|
+
| browse (default) | 22 | 3,727 | **48%** |
|
|
34
|
+
| core | 7 | 1,677 | **77%** |
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
Tool definitions are sent on every API round-trip. With the default `browse` profile, Charlotte carries 48% less definition overhead than loading all 40 tools. Over a 20-call browsing session, that's **38.6% fewer total tokens**. See the [profile benchmark report](docs/charlotte-profile-benchmark-report.md) for full results.
|
|
38
37
|
|
|
39
38
|
**The workflow difference:** Playwright agents receive 61K+ characters every time they look at Hacker News, whether they're reading headlines or looking for a login button. Charlotte agents get 336 characters on arrival, call `find({ type: "link", text: "login" })` to get exactly what they need, and never pay for the rest.
|
|
40
39
|
|
|
@@ -66,7 +65,9 @@ Agents receive landmarks, headings, interactive elements with typed metadata, bo
|
|
|
66
65
|
|
|
67
66
|
**Observation** — `observe` (3 detail levels), `find` (spatial + semantic search), `screenshot`, `diff` (structural comparison against snapshots)
|
|
68
67
|
|
|
69
|
-
**Interaction** — `click`, `type`, `select`, `toggle`, `submit`, `scroll`, `hover`, `key`, `wait_for` (async condition polling)
|
|
68
|
+
**Interaction** — `click`, `type`, `select`, `toggle`, `submit`, `scroll`, `hover`, `drag`, `key`, `wait_for` (async condition polling), `dialog` (accept/dismiss JS dialogs)
|
|
69
|
+
|
|
70
|
+
**Monitoring** — `console` (all severity levels, filtering, timestamps), `requests` (full HTTP history, method/status/resource type filtering)
|
|
70
71
|
|
|
71
72
|
**Session Management** — `tabs`, `tab_open`, `tab_switch`, `tab_close`, `viewport` (device presets), `network` (throttling, URL blocking), `set_cookies`, `get_cookies`, `clear_cookies`, `set_headers`, `configure`
|
|
72
73
|
|
|
@@ -74,6 +75,27 @@ Agents receive landmarks, headings, interactive elements with typed metadata, bo
|
|
|
74
75
|
|
|
75
76
|
**Utilities** — `evaluate` (arbitrary JS execution in page context)
|
|
76
77
|
|
|
78
|
+
## Tool Profiles
|
|
79
|
+
|
|
80
|
+
Charlotte ships 40 tools, but most workflows only need a subset. Startup profiles control which tools load into the agent's context, reducing definition overhead by up to 77%.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
charlotte --profile browse # 22 tools (default) — navigate, observe, interact, tabs
|
|
84
|
+
charlotte --profile core # 7 tools — navigate, observe, find, click, type, submit
|
|
85
|
+
charlotte --profile full # 40 tools — everything
|
|
86
|
+
charlotte --profile interact # 27 tools — full interaction + dialog + evaluate
|
|
87
|
+
charlotte --profile develop # 30 tools — interact + dev_serve, dev_inject, dev_audit
|
|
88
|
+
charlotte --profile audit # 13 tools — navigation + observation + dev_audit + viewport
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Agents can activate more tools mid-session without restarting:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
charlotte:tools enable dev_mode → activates dev_serve, dev_audit, dev_inject
|
|
95
|
+
charlotte:tools disable dev_mode → deactivates them
|
|
96
|
+
charlotte:tools list → see what's loaded
|
|
97
|
+
```
|
|
98
|
+
|
|
77
99
|
## Quick Start
|
|
78
100
|
|
|
79
101
|
### Prerequisites
|
|
@@ -89,6 +111,19 @@ Charlotte is listed on the [MCP Registry](https://registry.modelcontextprotocol.
|
|
|
89
111
|
npm install -g @ticktockbent/charlotte
|
|
90
112
|
```
|
|
91
113
|
|
|
114
|
+
Docker images are available on [Docker Hub](https://hub.docker.com/r/ticktockbent/charlotte) and [GitHub Container Registry](https://github.com/ticktockbent/charlotte/pkgs/container/charlotte):
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Alpine (default, smaller)
|
|
118
|
+
docker pull ticktockbent/charlotte:alpine
|
|
119
|
+
|
|
120
|
+
# Debian (if you need glibc compatibility)
|
|
121
|
+
docker pull ticktockbent/charlotte:debian
|
|
122
|
+
|
|
123
|
+
# Or from GHCR
|
|
124
|
+
docker pull ghcr.io/ticktockbent/charlotte:latest
|
|
125
|
+
```
|
|
126
|
+
|
|
92
127
|
Or install from source:
|
|
93
128
|
|
|
94
129
|
```bash
|
|
@@ -103,9 +138,12 @@ npm run build
|
|
|
103
138
|
Charlotte communicates over stdio using the MCP protocol:
|
|
104
139
|
|
|
105
140
|
```bash
|
|
106
|
-
# If installed globally
|
|
141
|
+
# If installed globally (default browse profile)
|
|
107
142
|
charlotte
|
|
108
143
|
|
|
144
|
+
# With a specific profile
|
|
145
|
+
charlotte --profile core
|
|
146
|
+
|
|
109
147
|
# If installed from source
|
|
110
148
|
npm start
|
|
111
149
|
```
|
|
@@ -213,8 +251,8 @@ Full interactive element list with typed metadata, form structures, and content
|
|
|
213
251
|
"viewport": { "width": 1280, "height": 720 },
|
|
214
252
|
"structure": {
|
|
215
253
|
"landmarks": [
|
|
216
|
-
{ "role": "banner", "label": "Site header", "bounds": { "x": 0, "y": 0, "w": 1280, "h": 64 } },
|
|
217
|
-
{ "role": "main", "label": "Content", "bounds": { "x": 240, "y": 64, "w": 1040, "h": 656 } }
|
|
254
|
+
{ "id": "rgn-b2c1", "role": "banner", "label": "Site header", "bounds": { "x": 0, "y": 0, "w": 1280, "h": 64 } },
|
|
255
|
+
{ "id": "rgn-d4e5", "role": "main", "label": "Content", "bounds": { "x": 240, "y": 64, "w": 1040, "h": 656 } }
|
|
218
256
|
],
|
|
219
257
|
"headings": [{ "level": 1, "text": "Dashboard", "id": "h-1a2b" }],
|
|
220
258
|
"content_summary": "main: 2 headings, 5 links, 1 form"
|
|
@@ -254,6 +292,7 @@ Element IDs are stable across minor DOM mutations. They're generated by hashing
|
|
|
254
292
|
btn-a3f1 (button) inp-c7e2 (text input)
|
|
255
293
|
lnk-d4b9 (link) sel-e8a3 (select)
|
|
256
294
|
chk-f1a2 (checkbox) frm-b1d4 (form)
|
|
295
|
+
rgn-e0d2 (landmark) hdg-0f40 (heading)
|
|
257
296
|
```
|
|
258
297
|
|
|
259
298
|
IDs survive unrelated DOM changes and element reordering within the same container. When an agent navigates at minimal detail (no individual element IDs), it uses `find` to locate elements by text, type, or spatial proximity — the returned elements include IDs ready for interaction.
|
|
@@ -303,11 +342,11 @@ The **Renderer Pipeline** is the core — it calls extractors in order and assem
|
|
|
303
342
|
3. Landmark, heading, interactive element, and content extraction
|
|
304
343
|
4. Element ID generation (hash-based, stable across re-renders)
|
|
305
344
|
|
|
306
|
-
All tools go through `renderActivePage()` which handles snapshots, reload events, and response formatting.
|
|
345
|
+
All tools go through `renderActivePage()` which handles snapshots, reload events, dialog detection, and response formatting.
|
|
307
346
|
|
|
308
347
|
## Sandbox
|
|
309
348
|
|
|
310
|
-
Charlotte includes a test website in `tests/sandbox/` that exercises all
|
|
349
|
+
Charlotte includes a test website in `tests/sandbox/` that exercises all 40 tools without touching the public internet. Serve it locally with:
|
|
311
350
|
|
|
312
351
|
```
|
|
313
352
|
dev_serve({ path: "tests/sandbox" })
|
|
@@ -315,12 +354,50 @@ dev_serve({ path: "tests/sandbox" })
|
|
|
315
354
|
|
|
316
355
|
Four pages cover navigation, forms, interactive elements, delayed content, scroll containers, and more. See [docs/sandbox.md](docs/sandbox.md) for the full page reference and a tool-by-tool exercise checklist.
|
|
317
356
|
|
|
357
|
+
## Known Issues
|
|
358
|
+
|
|
359
|
+
**Tool naming convention** — Charlotte uses `:` as a namespace separator in tool names (e.g., `charlotte:navigate`, `charlotte:observe`). MCP SDK v1.26.0+ logs validation warnings for this character, as the emerging [SEP standard](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/986) restricts tool names to `[A-Za-z0-9_.-]`. This does not affect functionality — all tools work correctly — but produces stderr warnings on server startup. Will be addressed in a future release to comply with the SEP standard.
|
|
360
|
+
|
|
361
|
+
**Iframe content not captured** — Charlotte reads the main frame's accessibility tree only. Content inside iframes (same-origin or cross-origin) is not included in the page representation. See the Roadmap for planned iframe support.
|
|
362
|
+
|
|
363
|
+
**Shadow DOM** — Open shadow DOM works transparently. Chromium's accessibility tree pierces open shadow boundaries, so web components (e.g., GitHub's `<relative-time>`, `<tool-tip>`) render their content into Charlotte's representation without special handling. Closed shadow roots are opaque to the accessibility tree and will not be captured.
|
|
364
|
+
|
|
365
|
+
**No file upload support** — Charlotte identifies `file_input` elements in the page representation but provides no tool to set file paths on them. Workflows that require file uploads cannot be completed.
|
|
366
|
+
|
|
318
367
|
## Roadmap
|
|
319
368
|
|
|
369
|
+
### Interaction Gaps
|
|
370
|
+
|
|
371
|
+
**File Upload** — Add a `charlotte:upload` tool to set file paths on `file_input` elements via Puppeteer's `elementHandle.uploadFile()`. Charlotte already identifies file inputs but cannot act on them.
|
|
372
|
+
|
|
373
|
+
**Batch Form Fill** — Add a `charlotte:fill_form` tool that accepts an array of `{element_id, value}` pairs and fills an entire form in a single tool call, reducing N sequential `type`/`select`/`toggle` calls to one.
|
|
374
|
+
|
|
375
|
+
**Slow Typing** — Add a `slowly` or `character_delay` parameter to `charlotte:type` for character-by-character input. Required for sites with key-by-key event handlers (autocomplete, search-as-you-type, input validation).
|
|
376
|
+
|
|
377
|
+
### Session & Configuration
|
|
378
|
+
|
|
379
|
+
**Connect to Existing Browser** — Add a `--cdp-endpoint` CLI argument so Charlotte can attach to an already-running browser via `puppeteer.connect()` instead of always launching a new instance. Enables working with logged-in sessions and browser extensions.
|
|
380
|
+
|
|
381
|
+
**Persistent Init Scripts** — Add a `--init-script` CLI argument to inject JavaScript on every page load via `page.evaluateOnNewDocument()`. Charlotte's `dev_inject` currently applies CSS/JS once and does not persist across navigations.
|
|
382
|
+
|
|
383
|
+
**Configuration File** — Support a `--config` CLI argument to load settings from a JSON file, simplifying repeatable setups and CI/CD integration.
|
|
384
|
+
|
|
385
|
+
**File Output** — Add an optional `filename` parameter to `screenshot`, `observe`, and future monitoring tools so large responses can be written to disk instead of returned inline, reducing token consumption.
|
|
386
|
+
|
|
387
|
+
**Full Device Emulation** — Extend `charlotte:viewport` to accept named devices (e.g., "iPhone 15") and configure user agent, touch support, and device pixel ratio via CDP, not just viewport dimensions.
|
|
388
|
+
|
|
389
|
+
### Feature Roadmap
|
|
390
|
+
|
|
320
391
|
**Screenshot Artifacts** — Save screenshots as persistent file artifacts rather than only returning inline data, enabling agents to reference and manage captured images across sessions.
|
|
321
392
|
|
|
322
393
|
**Video Recording** — Record interactions as video, capturing the full sequence of agent-driven navigation and manipulation for debugging, documentation, and review.
|
|
323
394
|
|
|
395
|
+
**ARM64 Docker Images** — Add `linux/arm64` platform support to the Docker publish workflow for native performance on Apple Silicon Macs and ARM servers.
|
|
396
|
+
|
|
397
|
+
**Iframe Content Extraction** — Traverse child frames via CDP to include iframe content in the page representation. Currently, Charlotte only reads the main frame's accessibility tree; same-origin and cross-origin iframe content is invisible.
|
|
398
|
+
|
|
399
|
+
See [docs/playwright-mcp-gap-analysis.md](docs/playwright-mcp-gap-analysis.md) for the full gap analysis against Playwright MCP, including lower-priority items (vision tools, testing/verification, tracing, transport, security) and areas where Charlotte has advantages.
|
|
400
|
+
|
|
324
401
|
## Full Specification
|
|
325
402
|
|
|
326
403
|
See [docs/CHARLOTTE_SPEC.md](docs/CHARLOTTE_SPEC.md) for the complete specification including all tool parameters, the page representation format, element identity strategy, and architecture details.
|
|
@@ -332,3 +409,6 @@ See [docs/CHARLOTTE_SPEC.md](docs/CHARLOTTE_SPEC.md) for the complete specificat
|
|
|
332
409
|
## Contributing
|
|
333
410
|
|
|
334
411
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
*Part of a growing suite of literary-named MCP servers. See more at [github.com/TickTockBent](https://github.com/TickTockBent).*
|
|
@@ -1,30 +1,58 @@
|
|
|
1
|
-
import type { Page } from "puppeteer";
|
|
1
|
+
import type { Page, Dialog } from "puppeteer";
|
|
2
2
|
import type { BrowserManager } from "./browser-manager.js";
|
|
3
|
+
import type { PendingDialog } from "../types/page-representation.js";
|
|
4
|
+
import type { CharlotteConfig } from "../types/config.js";
|
|
3
5
|
export interface TabInfo {
|
|
4
6
|
id: string;
|
|
5
7
|
url: string;
|
|
6
8
|
title: string;
|
|
7
9
|
active: boolean;
|
|
8
10
|
}
|
|
11
|
+
export interface ConsoleMessage {
|
|
12
|
+
level: string;
|
|
13
|
+
text: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
}
|
|
16
|
+
export interface NetworkRequest {
|
|
17
|
+
url: string;
|
|
18
|
+
method: string;
|
|
19
|
+
status: number;
|
|
20
|
+
statusText: string;
|
|
21
|
+
resourceType: string;
|
|
22
|
+
timestamp: string;
|
|
23
|
+
}
|
|
9
24
|
export declare class PageManager {
|
|
10
25
|
private pages;
|
|
11
26
|
private activeTabId;
|
|
27
|
+
private config;
|
|
28
|
+
constructor(config?: CharlotteConfig);
|
|
12
29
|
openTab(browserManager: BrowserManager, url?: string): Promise<string>;
|
|
13
30
|
switchTab(tabId: string): Promise<Page>;
|
|
14
31
|
closeTab(tabId: string): Promise<void>;
|
|
15
32
|
listTabs(): Promise<TabInfo[]>;
|
|
16
33
|
getActivePage(): Page;
|
|
17
34
|
getActiveTabId(): string;
|
|
35
|
+
/** Return only error/warn console messages (for PageRepresentation.errors). */
|
|
18
36
|
getConsoleErrors(): Array<{
|
|
19
37
|
level: string;
|
|
20
38
|
text: string;
|
|
21
39
|
}>;
|
|
40
|
+
/** Return only HTTP error responses (status >= 400, for PageRepresentation.errors). */
|
|
22
41
|
getNetworkErrors(): Array<{
|
|
23
42
|
url: string;
|
|
24
43
|
status: number;
|
|
25
44
|
statusText: string;
|
|
26
45
|
}>;
|
|
46
|
+
/** Return all console messages, optionally filtered by level. */
|
|
47
|
+
getConsoleMessages(level?: string): ConsoleMessage[];
|
|
48
|
+
/** Return all network requests, optionally filtered. */
|
|
49
|
+
getNetworkRequests(): NetworkRequest[];
|
|
50
|
+
clearConsoleMessages(): void;
|
|
51
|
+
clearNetworkRequests(): void;
|
|
27
52
|
clearErrors(): void;
|
|
53
|
+
getPendingDialogInfo(): PendingDialog | null;
|
|
54
|
+
getPendingDialog(): Dialog | null;
|
|
55
|
+
clearPendingDialog(): void;
|
|
28
56
|
hasPages(): boolean;
|
|
29
57
|
}
|
|
30
58
|
//# sourceMappingURL=page-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-manager.d.ts","sourceRoot":"","sources":["../../src/browser/page-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"page-manager.d.ts","sourceRoot":"","sources":["../../src/browser/page-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1D,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAoBD,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,CAAC,EAAE,eAAe;IAK9B,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuFtE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcvC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBtC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAapC,aAAa,IAAI,IAAI;IAmBrB,cAAc,IAAI,MAAM;IAUxB,+EAA+E;IAC/E,gBAAgB,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAS1D,uFAAuF;IACvF,gBAAgB,IAAI,KAAK,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IASF,iEAAiE;IACjE,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE;IAUpD,wDAAwD;IACxD,kBAAkB,IAAI,cAAc,EAAE;IAOtC,oBAAoB,IAAI,IAAI;IAQ5B,oBAAoB,IAAI,IAAI;IAQ5B,WAAW,IAAI,IAAI;IASnB,oBAAoB,IAAI,aAAa,GAAG,IAAI;IAM5C,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAMjC,kBAAkB,IAAI,IAAI;IAS1B,QAAQ,IAAI,OAAO;CAGpB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { createDefaultConfig } from "../types/config.js";
|
|
1
2
|
import { CharlotteError, CharlotteErrorCode } from "../types/errors.js";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
4
|
+
const MAX_CONSOLE_MESSAGES = 1000;
|
|
5
|
+
const MAX_NETWORK_REQUESTS = 1000;
|
|
3
6
|
let nextTabIdCounter = 1;
|
|
4
7
|
function generateTabId() {
|
|
5
8
|
return `tab-${nextTabIdCounter++}`;
|
|
@@ -7,33 +10,76 @@ function generateTabId() {
|
|
|
7
10
|
export class PageManager {
|
|
8
11
|
pages = new Map();
|
|
9
12
|
activeTabId = null;
|
|
13
|
+
config;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
// Accept optional config; callers without config get a permissive default
|
|
16
|
+
this.config = config ?? createDefaultConfig();
|
|
17
|
+
}
|
|
10
18
|
async openTab(browserManager, url) {
|
|
11
19
|
const page = await browserManager.newPage();
|
|
12
20
|
const tabId = generateTabId();
|
|
13
21
|
const managedPage = {
|
|
14
22
|
id: tabId,
|
|
15
23
|
page,
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
consoleMessages: [],
|
|
25
|
+
networkRequests: [],
|
|
26
|
+
pendingDialog: null,
|
|
27
|
+
pendingDialogInfo: null,
|
|
18
28
|
};
|
|
19
|
-
// Collect console
|
|
29
|
+
// Collect all console messages
|
|
20
30
|
page.on("console", (msg) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
managedPage.consoleErrors.push({
|
|
24
|
-
level,
|
|
25
|
-
text: msg.text(),
|
|
26
|
-
});
|
|
31
|
+
if (managedPage.consoleMessages.length >= MAX_CONSOLE_MESSAGES) {
|
|
32
|
+
managedPage.consoleMessages.shift();
|
|
27
33
|
}
|
|
34
|
+
managedPage.consoleMessages.push({
|
|
35
|
+
level: msg.type(),
|
|
36
|
+
text: msg.text(),
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
});
|
|
28
39
|
});
|
|
29
|
-
// Collect network
|
|
40
|
+
// Collect all network responses
|
|
30
41
|
page.on("response", (response) => {
|
|
31
|
-
if (
|
|
32
|
-
managedPage.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
if (managedPage.networkRequests.length >= MAX_NETWORK_REQUESTS) {
|
|
43
|
+
managedPage.networkRequests.shift();
|
|
44
|
+
}
|
|
45
|
+
managedPage.networkRequests.push({
|
|
46
|
+
url: response.url(),
|
|
47
|
+
method: response.request().method(),
|
|
48
|
+
status: response.status(),
|
|
49
|
+
statusText: response.statusText(),
|
|
50
|
+
resourceType: response.request().resourceType(),
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// Handle JavaScript dialogs (alert, confirm, prompt, beforeunload)
|
|
55
|
+
page.on("dialog", async (dialog) => {
|
|
56
|
+
const dialogType = dialog.type();
|
|
57
|
+
const autoDismiss = this.config.dialogAutoDismiss;
|
|
58
|
+
logger.info("Dialog appeared", { tabId, type: dialogType, message: dialog.message() });
|
|
59
|
+
// Auto-dismiss logic
|
|
60
|
+
if (autoDismiss === "accept_all" || (autoDismiss === "accept_alerts" && dialogType === "alert")) {
|
|
61
|
+
await dialog.accept();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (autoDismiss === "dismiss_all") {
|
|
65
|
+
await dialog.dismiss();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Queue for manual handling
|
|
69
|
+
managedPage.pendingDialog = dialog;
|
|
70
|
+
managedPage.pendingDialogInfo = {
|
|
71
|
+
type: dialogType,
|
|
72
|
+
message: dialog.message(),
|
|
73
|
+
...(dialogType === "prompt" ? { default_value: dialog.defaultValue() } : {}),
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
// Clear stale dialog references on main-frame navigation only.
|
|
78
|
+
// Subframe navigations (iframes, ads, embeds) must not wipe dialog state.
|
|
79
|
+
page.on("framenavigated", (frame) => {
|
|
80
|
+
if (frame === page.mainFrame()) {
|
|
81
|
+
managedPage.pendingDialog = null;
|
|
82
|
+
managedPage.pendingDialogInfo = null;
|
|
37
83
|
}
|
|
38
84
|
});
|
|
39
85
|
this.pages.set(tabId, managedPage);
|
|
@@ -95,25 +141,93 @@ export class PageManager {
|
|
|
95
141
|
}
|
|
96
142
|
return this.activeTabId;
|
|
97
143
|
}
|
|
144
|
+
/** Return only error/warn console messages (for PageRepresentation.errors). */
|
|
98
145
|
getConsoleErrors() {
|
|
99
146
|
if (!this.activeTabId)
|
|
100
147
|
return [];
|
|
101
148
|
const managedPage = this.pages.get(this.activeTabId);
|
|
102
|
-
|
|
149
|
+
if (!managedPage)
|
|
150
|
+
return [];
|
|
151
|
+
return managedPage.consoleMessages
|
|
152
|
+
.filter((m) => m.level === "error" || m.level === "warn")
|
|
153
|
+
.map(({ level, text }) => ({ level, text }));
|
|
103
154
|
}
|
|
155
|
+
/** Return only HTTP error responses (status >= 400, for PageRepresentation.errors). */
|
|
104
156
|
getNetworkErrors() {
|
|
105
157
|
if (!this.activeTabId)
|
|
106
158
|
return [];
|
|
107
159
|
const managedPage = this.pages.get(this.activeTabId);
|
|
108
|
-
|
|
160
|
+
if (!managedPage)
|
|
161
|
+
return [];
|
|
162
|
+
return managedPage.networkRequests
|
|
163
|
+
.filter((r) => r.status >= 400)
|
|
164
|
+
.map(({ url, status, statusText }) => ({ url, status, statusText }));
|
|
165
|
+
}
|
|
166
|
+
/** Return all console messages, optionally filtered by level. */
|
|
167
|
+
getConsoleMessages(level) {
|
|
168
|
+
if (!this.activeTabId)
|
|
169
|
+
return [];
|
|
170
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
171
|
+
if (!managedPage)
|
|
172
|
+
return [];
|
|
173
|
+
if (level && level !== "all") {
|
|
174
|
+
return managedPage.consoleMessages.filter((m) => m.level === level);
|
|
175
|
+
}
|
|
176
|
+
return [...managedPage.consoleMessages];
|
|
177
|
+
}
|
|
178
|
+
/** Return all network requests, optionally filtered. */
|
|
179
|
+
getNetworkRequests() {
|
|
180
|
+
if (!this.activeTabId)
|
|
181
|
+
return [];
|
|
182
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
183
|
+
if (!managedPage)
|
|
184
|
+
return [];
|
|
185
|
+
return [...managedPage.networkRequests];
|
|
186
|
+
}
|
|
187
|
+
clearConsoleMessages() {
|
|
188
|
+
if (!this.activeTabId)
|
|
189
|
+
return;
|
|
190
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
191
|
+
if (managedPage) {
|
|
192
|
+
managedPage.consoleMessages = [];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
clearNetworkRequests() {
|
|
196
|
+
if (!this.activeTabId)
|
|
197
|
+
return;
|
|
198
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
199
|
+
if (managedPage) {
|
|
200
|
+
managedPage.networkRequests = [];
|
|
201
|
+
}
|
|
109
202
|
}
|
|
110
203
|
clearErrors() {
|
|
111
204
|
if (!this.activeTabId)
|
|
112
205
|
return;
|
|
113
206
|
const managedPage = this.pages.get(this.activeTabId);
|
|
114
207
|
if (managedPage) {
|
|
115
|
-
managedPage.
|
|
116
|
-
managedPage.
|
|
208
|
+
managedPage.consoleMessages = [];
|
|
209
|
+
managedPage.networkRequests = [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
getPendingDialogInfo() {
|
|
213
|
+
if (!this.activeTabId)
|
|
214
|
+
return null;
|
|
215
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
216
|
+
return managedPage?.pendingDialogInfo ?? null;
|
|
217
|
+
}
|
|
218
|
+
getPendingDialog() {
|
|
219
|
+
if (!this.activeTabId)
|
|
220
|
+
return null;
|
|
221
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
222
|
+
return managedPage?.pendingDialog ?? null;
|
|
223
|
+
}
|
|
224
|
+
clearPendingDialog() {
|
|
225
|
+
if (!this.activeTabId)
|
|
226
|
+
return;
|
|
227
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
228
|
+
if (managedPage) {
|
|
229
|
+
managedPage.pendingDialog = null;
|
|
230
|
+
managedPage.pendingDialogInfo = null;
|
|
117
231
|
}
|
|
118
232
|
}
|
|
119
233
|
hasPages() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-manager.js","sourceRoot":"","sources":["../../src/browser/page-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"page-manager.js","sourceRoot":"","sources":["../../src/browser/page-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing for Charlotte.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from index.ts so it can be tested without triggering
|
|
5
|
+
* the main() side effect.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolProfile, ToolGroupName } from "./tools/tool-groups.js";
|
|
8
|
+
export declare function parseCliArgs(argv?: string[]): {
|
|
9
|
+
profile?: ToolProfile;
|
|
10
|
+
toolGroups?: ToolGroupName[];
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAWzE,wBAAgB,YAAY,CAC1B,IAAI,GAAE,MAAM,EAA0B,GACrC;IAAE,OAAO,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAA;CAAE,CA4BzD"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing for Charlotte.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from index.ts so it can be tested without triggering
|
|
5
|
+
* the main() side effect.
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from "./utils/logger.js";
|
|
8
|
+
const VALID_PROFILES = [
|
|
9
|
+
"core", "browse", "interact", "develop", "audit", "full",
|
|
10
|
+
];
|
|
11
|
+
const VALID_GROUPS = [
|
|
12
|
+
"navigation", "observation", "interaction", "session",
|
|
13
|
+
"dev_mode", "dialog", "evaluate", "monitoring",
|
|
14
|
+
];
|
|
15
|
+
export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
16
|
+
const profileArg = argv.find((a) => a.startsWith("--profile="));
|
|
17
|
+
const toolsArg = argv.find((a) => a.startsWith("--tools="));
|
|
18
|
+
if (profileArg && toolsArg) {
|
|
19
|
+
logger.warn("Both --profile and --tools provided; --profile takes precedence");
|
|
20
|
+
}
|
|
21
|
+
if (profileArg) {
|
|
22
|
+
const profile = profileArg.split("=")[1];
|
|
23
|
+
if (!VALID_PROFILES.includes(profile)) {
|
|
24
|
+
throw new Error(`Invalid profile: ${profile}. Valid profiles: ${VALID_PROFILES.join(", ")}`);
|
|
25
|
+
}
|
|
26
|
+
return { profile };
|
|
27
|
+
}
|
|
28
|
+
if (toolsArg) {
|
|
29
|
+
const groups = toolsArg.split("=")[1].split(",");
|
|
30
|
+
for (const group of groups) {
|
|
31
|
+
if (!VALID_GROUPS.includes(group)) {
|
|
32
|
+
throw new Error(`Invalid tool group: ${group}. Valid groups: ${VALID_GROUPS.join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { toolGroups: groups };
|
|
36
|
+
}
|
|
37
|
+
// Default: no profile or groups specified — createServer defaults to browse
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,MAAM,cAAc,GAAkB;IACpC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;CACzD,CAAC;AAEF,MAAM,YAAY,GAAoB;IACpC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS;IACrD,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY;CAC/C,CAAC;AAEF,MAAM,UAAU,YAAY,CAC1B,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAEtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAE5D,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IACjF,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAgB,CAAC;QACxD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,qBAAqB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;QACpE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,mBAAmB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;IAED,4EAA4E;IAC5E,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PageManager } from "../browser/page-manager.js";
|
|
2
2
|
import type { ReloadEvent } from "../types/page-representation.js";
|
|
3
|
+
import type { CharlotteConfig } from "../types/config.js";
|
|
3
4
|
import { type StaticServerInfo } from "./static-server.js";
|
|
4
5
|
export interface DevServeOptions {
|
|
5
6
|
directoryPath: string;
|
|
@@ -10,6 +11,8 @@ export interface DevServeOptions {
|
|
|
10
11
|
usePolling?: boolean;
|
|
11
12
|
}
|
|
12
13
|
export declare class DevModeState {
|
|
14
|
+
private config;
|
|
15
|
+
constructor(config: CharlotteConfig);
|
|
13
16
|
private staticServer;
|
|
14
17
|
private fileWatcher;
|
|
15
18
|
private pendingReloadEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-mode-state.d.ts","sourceRoot":"","sources":["../../src/dev/dev-mode-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,WAAW,CAAC;IACzB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,gBAAgB,CAA8B;IAEhD,YAAY,CAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"dev-mode-state.d.ts","sourceRoot":"","sources":["../../src/dev/dev-mode-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,WAAW,CAAC;IACzB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,eAAe;IAInC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,gBAAgB,CAA8B;IAEhD,YAAY,CAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,gBAAgB,CAAC;IAuBtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,yBAAyB,IAAI,WAAW,GAAG,IAAI;IAM/C,SAAS,IAAI,OAAO;IAIpB,aAAa,IAAI,gBAAgB,GAAG,IAAI;IAIxC,OAAO,CAAC,kBAAkB;CAiD3B"}
|