@ticktockbent/charlotte 0.2.0 → 0.3.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 +14 -0
- package/README.md +69 -4
- package/dist/browser/page-manager.d.ts +8 -1
- package/dist/browser/page-manager.d.ts.map +1 -1
- package/dist/browser/page-manager.js +57 -0
- package/dist/browser/page-manager.js.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -1
- 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/dialog.d.ts +4 -0
- package/dist/tools/dialog.d.ts.map +1 -0
- package/dist/tools/dialog.js +68 -0
- package/dist/tools/dialog.js.map +1 -0
- package/dist/tools/interaction.d.ts.map +1 -1
- package/dist/tools/interaction.js +32 -3
- package/dist/tools/interaction.js.map +1 -1
- package/dist/tools/observation.d.ts.map +1 -1
- package/dist/tools/observation.js +145 -8
- package/dist/tools/observation.js.map +1 -1
- package/dist/tools/session.d.ts.map +1 -1
- package/dist/tools/session.js +19 -2
- package/dist/tools/session.js.map +1 -1
- 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 +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +1 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/page-representation.d.ts +7 -0
- package/dist/types/page-representation.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Charlotte will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-02-24
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`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.
|
|
10
|
+
- **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.
|
|
11
|
+
- **`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"`.
|
|
12
|
+
- **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.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `PageManager` now accepts `CharlotteConfig` in its constructor for dialog auto-dismiss configuration.
|
|
17
|
+
- Config initialization moved before `PageManager` creation in `src/index.ts`.
|
|
18
|
+
|
|
5
19
|
## [0.2.0] - 2026-02-22
|
|
6
20
|
|
|
7
21
|
### 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.3.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
|
|
|
@@ -66,7 +66,7 @@ Agents receive landmarks, headings, interactive elements with typed metadata, bo
|
|
|
66
66
|
|
|
67
67
|
**Observation** — `observe` (3 detail levels), `find` (spatial + semantic search), `screenshot`, `diff` (structural comparison against snapshots)
|
|
68
68
|
|
|
69
|
-
**Interaction** — `click`, `type`, `select`, `toggle`, `submit`, `scroll`, `hover`, `key`, `wait_for` (async condition polling)
|
|
69
|
+
**Interaction** — `click`, `type`, `select`, `toggle`, `submit`, `scroll`, `hover`, `key`, `wait_for` (async condition polling), `dialog` (accept/dismiss JS dialogs)
|
|
70
70
|
|
|
71
71
|
**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
72
|
|
|
@@ -89,6 +89,19 @@ Charlotte is listed on the [MCP Registry](https://registry.modelcontextprotocol.
|
|
|
89
89
|
npm install -g @ticktockbent/charlotte
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
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):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Alpine (default, smaller)
|
|
96
|
+
docker pull ticktockbent/charlotte:alpine
|
|
97
|
+
|
|
98
|
+
# Debian (if you need glibc compatibility)
|
|
99
|
+
docker pull ticktockbent/charlotte:debian
|
|
100
|
+
|
|
101
|
+
# Or from GHCR
|
|
102
|
+
docker pull ghcr.io/ticktockbent/charlotte:latest
|
|
103
|
+
```
|
|
104
|
+
|
|
92
105
|
Or install from source:
|
|
93
106
|
|
|
94
107
|
```bash
|
|
@@ -303,11 +316,11 @@ The **Renderer Pipeline** is the core — it calls extractors in order and assem
|
|
|
303
316
|
3. Landmark, heading, interactive element, and content extraction
|
|
304
317
|
4. Element ID generation (hash-based, stable across re-renders)
|
|
305
318
|
|
|
306
|
-
All tools go through `renderActivePage()` which handles snapshots, reload events, and response formatting.
|
|
319
|
+
All tools go through `renderActivePage()` which handles snapshots, reload events, dialog detection, and response formatting.
|
|
307
320
|
|
|
308
321
|
## Sandbox
|
|
309
322
|
|
|
310
|
-
Charlotte includes a test website in `tests/sandbox/` that exercises all
|
|
323
|
+
Charlotte includes a test website in `tests/sandbox/` that exercises all 33 tools without touching the public internet. Serve it locally with:
|
|
311
324
|
|
|
312
325
|
```
|
|
313
326
|
dev_serve({ path: "tests/sandbox" })
|
|
@@ -315,12 +328,64 @@ dev_serve({ path: "tests/sandbox" })
|
|
|
315
328
|
|
|
316
329
|
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
330
|
|
|
331
|
+
## Known Issues
|
|
332
|
+
|
|
333
|
+
**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.
|
|
334
|
+
|
|
335
|
+
**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.
|
|
336
|
+
|
|
337
|
+
**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.
|
|
338
|
+
|
|
339
|
+
**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.
|
|
340
|
+
|
|
341
|
+
**No drag-and-drop support** — There is no tool for drag-and-drop interactions. Kanban boards, sortable lists, slider handles, and file drop zones cannot be automated.
|
|
342
|
+
|
|
343
|
+
**Console and network monitoring are error-only** — Charlotte captures console errors and failed network requests in the page representation, but does not expose a dedicated tool for retrieving all console messages or all network requests. Agents debugging JavaScript or API issues have limited visibility.
|
|
344
|
+
|
|
318
345
|
## Roadmap
|
|
319
346
|
|
|
347
|
+
### Interaction Gaps
|
|
348
|
+
|
|
349
|
+
**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.
|
|
350
|
+
|
|
351
|
+
**Drag and Drop** — Add a `charlotte:drag` tool for element-to-element drag-and-drop using Puppeteer mouse primitives. Covers kanban boards, sortable lists, sliders, and drop zones.
|
|
352
|
+
|
|
353
|
+
**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.
|
|
354
|
+
|
|
355
|
+
**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).
|
|
356
|
+
|
|
357
|
+
**Click Modifiers** — Add a `modifiers` parameter (`ctrl`, `shift`, `alt`, `meta`) to `charlotte:click` for Ctrl+Click (open in new tab), Shift+Click (range select), and similar patterns.
|
|
358
|
+
|
|
359
|
+
### Monitoring
|
|
360
|
+
|
|
361
|
+
**Console Message Retrieval** — Add a `charlotte:console` tool to retrieve all console messages (not just errors) with level filtering. Charlotte already listens to console events internally but only surfaces errors in the page representation.
|
|
362
|
+
|
|
363
|
+
**Network Request Monitoring** — Add a `charlotte:requests` tool to retrieve all network requests (not just failures) with filtering options. Enables agents to debug API calls and resource loading.
|
|
364
|
+
|
|
365
|
+
### Session & Configuration
|
|
366
|
+
|
|
367
|
+
**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.
|
|
368
|
+
|
|
369
|
+
**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.
|
|
370
|
+
|
|
371
|
+
**Configuration File** — Support a `--config` CLI argument to load settings from a JSON file, simplifying repeatable setups and CI/CD integration.
|
|
372
|
+
|
|
373
|
+
**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.
|
|
374
|
+
|
|
375
|
+
**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.
|
|
376
|
+
|
|
377
|
+
### Feature Roadmap
|
|
378
|
+
|
|
320
379
|
**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
380
|
|
|
322
381
|
**Video Recording** — Record interactions as video, capturing the full sequence of agent-driven navigation and manipulation for debugging, documentation, and review.
|
|
323
382
|
|
|
383
|
+
**ARM64 Docker Images** — Add `linux/arm64` platform support to the Docker publish workflow for native performance on Apple Silicon Macs and ARM servers.
|
|
384
|
+
|
|
385
|
+
**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.
|
|
386
|
+
|
|
387
|
+
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.
|
|
388
|
+
|
|
324
389
|
## Full Specification
|
|
325
390
|
|
|
326
391
|
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.
|
|
@@ -1,5 +1,7 @@
|
|
|
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;
|
|
@@ -9,6 +11,8 @@ export interface TabInfo {
|
|
|
9
11
|
export declare class PageManager {
|
|
10
12
|
private pages;
|
|
11
13
|
private activeTabId;
|
|
14
|
+
private config;
|
|
15
|
+
constructor(config?: CharlotteConfig);
|
|
12
16
|
openTab(browserManager: BrowserManager, url?: string): Promise<string>;
|
|
13
17
|
switchTab(tabId: string): Promise<Page>;
|
|
14
18
|
closeTab(tabId: string): Promise<void>;
|
|
@@ -25,6 +29,9 @@ export declare class PageManager {
|
|
|
25
29
|
statusText: string;
|
|
26
30
|
}>;
|
|
27
31
|
clearErrors(): void;
|
|
32
|
+
getPendingDialogInfo(): PendingDialog | null;
|
|
33
|
+
getPendingDialog(): Dialog | null;
|
|
34
|
+
clearPendingDialog(): void;
|
|
28
35
|
hasPages(): boolean;
|
|
29
36
|
}
|
|
30
37
|
//# 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;AAiBD,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;IA+EtE,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,gBAAgB,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAM1D,gBAAgB,IAAI,KAAK,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAMF,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,3 +1,4 @@
|
|
|
1
|
+
import { createDefaultConfig } from "../types/config.js";
|
|
1
2
|
import { CharlotteError, CharlotteErrorCode } from "../types/errors.js";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
3
4
|
let nextTabIdCounter = 1;
|
|
@@ -7,6 +8,11 @@ function generateTabId() {
|
|
|
7
8
|
export class PageManager {
|
|
8
9
|
pages = new Map();
|
|
9
10
|
activeTabId = null;
|
|
11
|
+
config;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
// Accept optional config; callers without config get a permissive default
|
|
14
|
+
this.config = config ?? createDefaultConfig();
|
|
15
|
+
}
|
|
10
16
|
async openTab(browserManager, url) {
|
|
11
17
|
const page = await browserManager.newPage();
|
|
12
18
|
const tabId = generateTabId();
|
|
@@ -15,6 +21,8 @@ export class PageManager {
|
|
|
15
21
|
page,
|
|
16
22
|
consoleErrors: [],
|
|
17
23
|
networkErrors: [],
|
|
24
|
+
pendingDialog: null,
|
|
25
|
+
pendingDialogInfo: null,
|
|
18
26
|
};
|
|
19
27
|
// Collect console errors
|
|
20
28
|
page.on("console", (msg) => {
|
|
@@ -36,6 +44,34 @@ export class PageManager {
|
|
|
36
44
|
});
|
|
37
45
|
}
|
|
38
46
|
});
|
|
47
|
+
// Handle JavaScript dialogs (alert, confirm, prompt, beforeunload)
|
|
48
|
+
page.on("dialog", async (dialog) => {
|
|
49
|
+
const dialogType = dialog.type();
|
|
50
|
+
const autoDismiss = this.config.dialogAutoDismiss;
|
|
51
|
+
logger.info("Dialog appeared", { tabId, type: dialogType, message: dialog.message() });
|
|
52
|
+
// Auto-dismiss logic
|
|
53
|
+
if (autoDismiss === "accept_all" || (autoDismiss === "accept_alerts" && dialogType === "alert")) {
|
|
54
|
+
await dialog.accept();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (autoDismiss === "dismiss_all") {
|
|
58
|
+
await dialog.dismiss();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Queue for manual handling
|
|
62
|
+
managedPage.pendingDialog = dialog;
|
|
63
|
+
managedPage.pendingDialogInfo = {
|
|
64
|
+
type: dialogType,
|
|
65
|
+
message: dialog.message(),
|
|
66
|
+
...(dialogType === "prompt" ? { default_value: dialog.defaultValue() } : {}),
|
|
67
|
+
timestamp: new Date().toISOString(),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
// Clear stale dialog references on navigation
|
|
71
|
+
page.on("framenavigated", () => {
|
|
72
|
+
managedPage.pendingDialog = null;
|
|
73
|
+
managedPage.pendingDialogInfo = null;
|
|
74
|
+
});
|
|
39
75
|
this.pages.set(tabId, managedPage);
|
|
40
76
|
this.activeTabId = tabId;
|
|
41
77
|
if (url) {
|
|
@@ -116,6 +152,27 @@ export class PageManager {
|
|
|
116
152
|
managedPage.networkErrors = [];
|
|
117
153
|
}
|
|
118
154
|
}
|
|
155
|
+
getPendingDialogInfo() {
|
|
156
|
+
if (!this.activeTabId)
|
|
157
|
+
return null;
|
|
158
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
159
|
+
return managedPage?.pendingDialogInfo ?? null;
|
|
160
|
+
}
|
|
161
|
+
getPendingDialog() {
|
|
162
|
+
if (!this.activeTabId)
|
|
163
|
+
return null;
|
|
164
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
165
|
+
return managedPage?.pendingDialog ?? null;
|
|
166
|
+
}
|
|
167
|
+
clearPendingDialog() {
|
|
168
|
+
if (!this.activeTabId)
|
|
169
|
+
return;
|
|
170
|
+
const managedPage = this.pages.get(this.activeTabId);
|
|
171
|
+
if (managedPage) {
|
|
172
|
+
managedPage.pendingDialog = null;
|
|
173
|
+
managedPage.pendingDialogInfo = null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
119
176
|
hasPages() {
|
|
120
177
|
return this.pages.size > 0;
|
|
121
178
|
}
|
|
@@ -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/index.js
CHANGED
|
@@ -6,26 +6,30 @@ import { CDPSessionManager } from "./browser/cdp-session.js";
|
|
|
6
6
|
import { RendererPipeline } from "./renderer/renderer-pipeline.js";
|
|
7
7
|
import { ElementIdGenerator } from "./renderer/element-id-generator.js";
|
|
8
8
|
import { SnapshotStore } from "./state/snapshot-store.js";
|
|
9
|
+
import { ArtifactStore } from "./state/artifact-store.js";
|
|
9
10
|
import { createDefaultConfig } from "./types/config.js";
|
|
10
11
|
import { createServer } from "./server.js";
|
|
11
12
|
import { DevModeState } from "./dev/dev-mode-state.js";
|
|
12
13
|
import { logger } from "./utils/logger.js";
|
|
13
14
|
async function main() {
|
|
14
15
|
logger.info("Charlotte starting");
|
|
16
|
+
// Initialize config first (needed by PageManager for dialog handling)
|
|
17
|
+
const config = createDefaultConfig();
|
|
15
18
|
// Initialize browser
|
|
16
19
|
const browserManager = new BrowserManager();
|
|
17
20
|
await browserManager.launch();
|
|
18
21
|
// Initialize page management
|
|
19
|
-
const pageManager = new PageManager();
|
|
22
|
+
const pageManager = new PageManager(config);
|
|
20
23
|
// Open a default tab
|
|
21
24
|
await pageManager.openTab(browserManager);
|
|
22
25
|
// Initialize renderer pipeline
|
|
23
26
|
const cdpSessionManager = new CDPSessionManager();
|
|
24
27
|
const elementIdGenerator = new ElementIdGenerator();
|
|
25
28
|
const rendererPipeline = new RendererPipeline(cdpSessionManager, elementIdGenerator);
|
|
26
|
-
// Initialize state management
|
|
27
|
-
const config = createDefaultConfig();
|
|
28
29
|
const snapshotStore = new SnapshotStore(config.snapshotDepth);
|
|
30
|
+
// Initialize screenshot artifact store
|
|
31
|
+
const artifactStore = new ArtifactStore(config.screenshotDir);
|
|
32
|
+
await artifactStore.initialize();
|
|
29
33
|
// Initialize dev mode state
|
|
30
34
|
const devModeState = new DevModeState();
|
|
31
35
|
// Create and configure MCP server
|
|
@@ -35,6 +39,7 @@ async function main() {
|
|
|
35
39
|
rendererPipeline,
|
|
36
40
|
elementIdGenerator,
|
|
37
41
|
snapshotStore,
|
|
42
|
+
artifactStore,
|
|
38
43
|
config,
|
|
39
44
|
devModeState,
|
|
40
45
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAElC,qBAAqB;IACrB,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC5C,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;IAE9B,6BAA6B;IAC7B,MAAM,WAAW,GAAG,IAAI,WAAW,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { PageManager } from "./browser/page-manager.js";
|
|
|
4
4
|
import type { RendererPipeline } from "./renderer/renderer-pipeline.js";
|
|
5
5
|
import type { ElementIdGenerator } from "./renderer/element-id-generator.js";
|
|
6
6
|
import type { SnapshotStore } from "./state/snapshot-store.js";
|
|
7
|
+
import type { ArtifactStore } from "./state/artifact-store.js";
|
|
7
8
|
import type { CharlotteConfig } from "./types/config.js";
|
|
8
9
|
import type { DevModeState } from "./dev/dev-mode-state.js";
|
|
9
10
|
export interface ServerDeps {
|
|
@@ -12,6 +13,7 @@ export interface ServerDeps {
|
|
|
12
13
|
rendererPipeline: RendererPipeline;
|
|
13
14
|
elementIdGenerator: ElementIdGenerator;
|
|
14
15
|
snapshotStore: SnapshotStore;
|
|
16
|
+
artifactStore: ArtifactStore;
|
|
15
17
|
config: CharlotteConfig;
|
|
16
18
|
devModeState?: DevModeState;
|
|
17
19
|
}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAuCxD"}
|
package/dist/server.js
CHANGED
|
@@ -3,12 +3,13 @@ import { registerEvaluateTools } from "./tools/evaluate.js";
|
|
|
3
3
|
import { registerNavigationTools } from "./tools/navigation.js";
|
|
4
4
|
import { registerObservationTools } from "./tools/observation.js";
|
|
5
5
|
import { registerInteractionTools } from "./tools/interaction.js";
|
|
6
|
+
import { registerDialogTools } from "./tools/dialog.js";
|
|
6
7
|
import { registerSessionTools } from "./tools/session.js";
|
|
7
8
|
import { registerDevModeTools } from "./tools/dev-mode.js";
|
|
8
9
|
export function createServer(deps) {
|
|
9
10
|
const server = new McpServer({
|
|
10
11
|
name: "charlotte",
|
|
11
|
-
version: "0.
|
|
12
|
+
version: "0.3.0",
|
|
12
13
|
}, {
|
|
13
14
|
capabilities: {
|
|
14
15
|
tools: {},
|
|
@@ -26,12 +27,14 @@ export function createServer(deps) {
|
|
|
26
27
|
rendererPipeline: deps.rendererPipeline,
|
|
27
28
|
elementIdGenerator: deps.elementIdGenerator,
|
|
28
29
|
snapshotStore: deps.snapshotStore,
|
|
30
|
+
artifactStore: deps.artifactStore,
|
|
29
31
|
config: deps.config,
|
|
30
32
|
devModeState: deps.devModeState,
|
|
31
33
|
};
|
|
32
34
|
registerNavigationTools(server, toolDeps);
|
|
33
35
|
registerObservationTools(server, toolDeps);
|
|
34
36
|
registerInteractionTools(server, toolDeps);
|
|
37
|
+
registerDialogTools(server, toolDeps);
|
|
35
38
|
registerSessionTools(server, toolDeps);
|
|
36
39
|
registerDevModeTools(server, toolDeps);
|
|
37
40
|
return server;
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAc3D,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,yBAAyB;IACzB,qBAAqB,CAAC,MAAM,EAAE;QAC5B,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE;KACtD,CAAC,CAAC;IAEH,+DAA+D;IAC/D,MAAM,QAAQ,GAAG;QACf,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;QAC3C,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,YAAY,EAAE,IAAI,CAAC,YAAY;KAChC,CAAC;IAEF,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEvC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface ScreenshotArtifact {
|
|
2
|
+
id: string;
|
|
3
|
+
filename: string;
|
|
4
|
+
path: string;
|
|
5
|
+
format: "png" | "jpeg" | "webp";
|
|
6
|
+
mimeType: string;
|
|
7
|
+
size: number;
|
|
8
|
+
selector?: string;
|
|
9
|
+
url: string;
|
|
10
|
+
title: string;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Manages persistent screenshot artifacts on disk.
|
|
15
|
+
* Screenshots are stored as image files with a companion JSON index
|
|
16
|
+
* for metadata that survives across sessions.
|
|
17
|
+
*/
|
|
18
|
+
export declare class ArtifactStore {
|
|
19
|
+
private artifacts;
|
|
20
|
+
private _screenshotDir;
|
|
21
|
+
constructor(screenshotDir?: string);
|
|
22
|
+
get screenshotDir(): string;
|
|
23
|
+
/** Create the storage directory and load any existing index. */
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Update the screenshot directory at runtime.
|
|
27
|
+
* Initializes the new directory without moving existing files.
|
|
28
|
+
*/
|
|
29
|
+
setScreenshotDir(dir: string): Promise<void>;
|
|
30
|
+
/** Save a screenshot to disk and track it. */
|
|
31
|
+
save(data: Buffer, metadata: {
|
|
32
|
+
format: "png" | "jpeg" | "webp";
|
|
33
|
+
selector?: string;
|
|
34
|
+
url: string;
|
|
35
|
+
title: string;
|
|
36
|
+
}): Promise<ScreenshotArtifact>;
|
|
37
|
+
/** List all tracked artifacts, newest first. */
|
|
38
|
+
list(): ScreenshotArtifact[];
|
|
39
|
+
/** Get artifact metadata by ID. */
|
|
40
|
+
get(id: string): ScreenshotArtifact | undefined;
|
|
41
|
+
/** Read the raw file bytes for an artifact. */
|
|
42
|
+
readFile(id: string): Promise<Buffer | null>;
|
|
43
|
+
/** Delete a screenshot artifact from disk and the index. */
|
|
44
|
+
delete(id: string): Promise<boolean>;
|
|
45
|
+
/** Number of tracked artifacts. */
|
|
46
|
+
get count(): number;
|
|
47
|
+
private generateId;
|
|
48
|
+
private get indexPath();
|
|
49
|
+
private loadIndex;
|
|
50
|
+
private saveIndex;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=artifact-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/state/artifact-store.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAcD;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,cAAc,CAAS;gBAEnB,aAAa,CAAC,EAAE,MAAM;IAKlC,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,gEAAgE;IAC1D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC;;;OAGG;IACG,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,8CAA8C;IACxC,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QACR,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,kBAAkB,CAAC;IA4B9B,gDAAgD;IAChD,IAAI,IAAI,kBAAkB,EAAE;IAM5B,mCAAmC;IACnC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI/C,+CAA+C;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAalD,4DAA4D;IACtD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB1C,mCAAmC;IACnC,IAAI,KAAK,IAAI,MAAM,CAElB;IAID,OAAO,CAAC,UAAU;IAOlB,OAAO,KAAK,SAAS,GAEpB;YAEa,SAAS;YAoCT,SAAS;CAcxB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as crypto from "node:crypto";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
const INDEX_FILE = ".charlotte-screenshots.json";
|
|
7
|
+
/**
|
|
8
|
+
* Manages persistent screenshot artifacts on disk.
|
|
9
|
+
* Screenshots are stored as image files with a companion JSON index
|
|
10
|
+
* for metadata that survives across sessions.
|
|
11
|
+
*/
|
|
12
|
+
export class ArtifactStore {
|
|
13
|
+
artifacts = new Map();
|
|
14
|
+
_screenshotDir;
|
|
15
|
+
constructor(screenshotDir) {
|
|
16
|
+
this._screenshotDir =
|
|
17
|
+
screenshotDir ?? path.join(os.tmpdir(), "charlotte-screenshots");
|
|
18
|
+
}
|
|
19
|
+
get screenshotDir() {
|
|
20
|
+
return this._screenshotDir;
|
|
21
|
+
}
|
|
22
|
+
/** Create the storage directory and load any existing index. */
|
|
23
|
+
async initialize() {
|
|
24
|
+
await fs.mkdir(this._screenshotDir, { recursive: true });
|
|
25
|
+
await this.loadIndex();
|
|
26
|
+
logger.info("Artifact store initialized", { dir: this._screenshotDir });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Update the screenshot directory at runtime.
|
|
30
|
+
* Initializes the new directory without moving existing files.
|
|
31
|
+
*/
|
|
32
|
+
async setScreenshotDir(dir) {
|
|
33
|
+
this._screenshotDir = dir;
|
|
34
|
+
this.artifacts.clear();
|
|
35
|
+
await this.initialize();
|
|
36
|
+
}
|
|
37
|
+
/** Save a screenshot to disk and track it. */
|
|
38
|
+
async save(data, metadata) {
|
|
39
|
+
const id = this.generateId();
|
|
40
|
+
const ext = metadata.format === "jpeg" ? "jpg" : metadata.format;
|
|
41
|
+
const filename = `${id}.${ext}`;
|
|
42
|
+
const filePath = path.join(this._screenshotDir, filename);
|
|
43
|
+
await fs.writeFile(filePath, data);
|
|
44
|
+
const artifact = {
|
|
45
|
+
id,
|
|
46
|
+
filename,
|
|
47
|
+
path: filePath,
|
|
48
|
+
format: metadata.format,
|
|
49
|
+
mimeType: `image/${metadata.format}`,
|
|
50
|
+
size: data.length,
|
|
51
|
+
selector: metadata.selector,
|
|
52
|
+
url: metadata.url,
|
|
53
|
+
title: metadata.title,
|
|
54
|
+
timestamp: new Date().toISOString(),
|
|
55
|
+
};
|
|
56
|
+
this.artifacts.set(id, artifact);
|
|
57
|
+
await this.saveIndex();
|
|
58
|
+
logger.info("Screenshot saved", { id, filename, size: data.length });
|
|
59
|
+
return artifact;
|
|
60
|
+
}
|
|
61
|
+
/** List all tracked artifacts, newest first. */
|
|
62
|
+
list() {
|
|
63
|
+
return Array.from(this.artifacts.values()).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
64
|
+
}
|
|
65
|
+
/** Get artifact metadata by ID. */
|
|
66
|
+
get(id) {
|
|
67
|
+
return this.artifacts.get(id);
|
|
68
|
+
}
|
|
69
|
+
/** Read the raw file bytes for an artifact. */
|
|
70
|
+
async readFile(id) {
|
|
71
|
+
const artifact = this.artifacts.get(id);
|
|
72
|
+
if (!artifact)
|
|
73
|
+
return null;
|
|
74
|
+
try {
|
|
75
|
+
return await fs.readFile(artifact.path);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// File may have been deleted externally
|
|
79
|
+
this.artifacts.delete(id);
|
|
80
|
+
await this.saveIndex();
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Delete a screenshot artifact from disk and the index. */
|
|
85
|
+
async delete(id) {
|
|
86
|
+
const artifact = this.artifacts.get(id);
|
|
87
|
+
if (!artifact)
|
|
88
|
+
return false;
|
|
89
|
+
try {
|
|
90
|
+
await fs.unlink(artifact.path);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// File already gone — still clean up index
|
|
94
|
+
}
|
|
95
|
+
this.artifacts.delete(id);
|
|
96
|
+
await this.saveIndex();
|
|
97
|
+
logger.info("Screenshot deleted", { id });
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
/** Number of tracked artifacts. */
|
|
101
|
+
get count() {
|
|
102
|
+
return this.artifacts.size;
|
|
103
|
+
}
|
|
104
|
+
// ── Private helpers ──
|
|
105
|
+
generateId() {
|
|
106
|
+
const now = new Date();
|
|
107
|
+
const datePart = now.toISOString().replace(/[-:T]/g, "").slice(0, 14);
|
|
108
|
+
const rand = crypto.randomBytes(3).toString("hex");
|
|
109
|
+
return `ss-${datePart}-${rand}`;
|
|
110
|
+
}
|
|
111
|
+
get indexPath() {
|
|
112
|
+
return path.join(this._screenshotDir, INDEX_FILE);
|
|
113
|
+
}
|
|
114
|
+
async loadIndex() {
|
|
115
|
+
try {
|
|
116
|
+
const raw = await fs.readFile(this.indexPath, "utf-8");
|
|
117
|
+
const entries = JSON.parse(raw);
|
|
118
|
+
for (const meta of entries) {
|
|
119
|
+
const ext = meta.format === "jpeg" ? "jpg" : meta.format;
|
|
120
|
+
const filename = `${meta.id}.${ext}`;
|
|
121
|
+
const filePath = path.join(this._screenshotDir, filename);
|
|
122
|
+
// Verify the file still exists
|
|
123
|
+
try {
|
|
124
|
+
const stat = await fs.stat(filePath);
|
|
125
|
+
this.artifacts.set(meta.id, {
|
|
126
|
+
id: meta.id,
|
|
127
|
+
filename,
|
|
128
|
+
path: filePath,
|
|
129
|
+
format: meta.format,
|
|
130
|
+
mimeType: `image/${meta.format}`,
|
|
131
|
+
size: stat.size,
|
|
132
|
+
selector: meta.selector,
|
|
133
|
+
url: meta.url,
|
|
134
|
+
title: meta.title,
|
|
135
|
+
timestamp: meta.timestamp,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// File missing — skip
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
logger.info("Loaded artifact index", { count: this.artifacts.size });
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// No index yet — fresh start
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async saveIndex() {
|
|
149
|
+
const entries = Array.from(this.artifacts.values()).map((a) => ({
|
|
150
|
+
id: a.id,
|
|
151
|
+
format: a.format,
|
|
152
|
+
selector: a.selector,
|
|
153
|
+
url: a.url,
|
|
154
|
+
title: a.title,
|
|
155
|
+
timestamp: a.timestamp,
|
|
156
|
+
}));
|
|
157
|
+
await fs.writeFile(this.indexPath, JSON.stringify(entries, null, 2));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=artifact-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-store.js","sourceRoot":"","sources":["../../src/state/artifact-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAyB5C,MAAM,UAAU,GAAG,6BAA6B,CAAC;AAEjD;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAChB,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IAClD,cAAc,CAAS;IAE/B,YAAY,aAAsB;QAChC,IAAI,CAAC,cAAc;YACjB,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,UAAU;QACd,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,GAAW;QAChC,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,IAAI,CACR,IAAY,EACZ,QAKC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjE,MAAM,QAAQ,GAAG,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAE1D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAuB;YACnC,EAAE;YACF,QAAQ;YACR,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,SAAS,QAAQ,CAAC,MAAM,EAAE;YACpC,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,GAAG,EAAE,QAAQ,CAAC,GAAG;YACjB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAEvB,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC7C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAC5E,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;YACxC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAE5B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mCAAmC;IACnC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,wBAAwB;IAEhB,UAAU;QAChB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnD,OAAO,MAAM,QAAQ,IAAI,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,IAAY,SAAS;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM,OAAO,GAAmB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAEhD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;gBACzD,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;gBAE1D,+BAA+B;gBAC/B,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;wBAC1B,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,QAAQ;wBACR,IAAI,EAAE,QAAQ;wBACd,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,QAAQ,EAAE,SAAS,IAAI,CAAC,MAAM,EAAE;wBAChC,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,GAAG,EAAE,IAAI,CAAC,GAAG;wBACb,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;qBAC1B,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;YACH,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,OAAO,GAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CACrE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACN,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,CAAC,CAAC,SAAS;SACvB,CAAC,CACH,CAAC;QAEF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;CACF"}
|