@vscode/component-explorer-cli 0.2.0 → 0.2.1-1

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.
Files changed (59) hide show
  1. package/dist/_virtual/_build-info.js +1 -1
  2. package/dist/browserPage.d.ts +11 -2
  3. package/dist/browserPage.d.ts.map +1 -1
  4. package/dist/browserPage.js +26 -8
  5. package/dist/browserPage.js.map +1 -1
  6. package/dist/commands/checkStabilityCommand.d.ts.map +1 -1
  7. package/dist/commands/checkStabilityCommand.js +7 -4
  8. package/dist/commands/checkStabilityCommand.js.map +1 -1
  9. package/dist/commands/mcpCommand.d.ts.map +1 -1
  10. package/dist/commands/mcpCommand.js +34 -23
  11. package/dist/commands/mcpCommand.js.map +1 -1
  12. package/dist/commands/screenshotCommand.d.ts.map +1 -1
  13. package/dist/commands/screenshotCommand.js +10 -3
  14. package/dist/commands/screenshotCommand.js.map +1 -1
  15. package/dist/commands/serveCommand.d.ts +2 -0
  16. package/dist/commands/serveCommand.d.ts.map +1 -1
  17. package/dist/commands/serveCommand.js +75 -24
  18. package/dist/commands/serveCommand.js.map +1 -1
  19. package/dist/commands/watchCommand.js +11 -6
  20. package/dist/commands/watchCommand.js.map +1 -1
  21. package/dist/component-explorer-config.schema.json +166 -0
  22. package/dist/componentExplorer.d.ts +14 -3
  23. package/dist/componentExplorer.d.ts.map +1 -1
  24. package/dist/componentExplorer.js +42 -6
  25. package/dist/componentExplorer.js.map +1 -1
  26. package/dist/daemon/DaemonService.d.ts +26 -5
  27. package/dist/daemon/DaemonService.d.ts.map +1 -1
  28. package/dist/daemon/DaemonService.js +61 -20
  29. package/dist/daemon/DaemonService.js.map +1 -1
  30. package/dist/daemon/lifecycle.d.ts +2 -1
  31. package/dist/daemon/lifecycle.d.ts.map +1 -1
  32. package/dist/daemon/lifecycle.js +41 -6
  33. package/dist/daemon/lifecycle.js.map +1 -1
  34. package/dist/daemon/pipeClient.d.ts.map +1 -1
  35. package/dist/daemon/pipeClient.js +2 -0
  36. package/dist/daemon/pipeClient.js.map +1 -1
  37. package/dist/explorerSession.d.ts +3 -3
  38. package/dist/explorerSession.d.ts.map +1 -1
  39. package/dist/explorerSession.js +26 -9
  40. package/dist/explorerSession.js.map +1 -1
  41. package/dist/httpServer.d.ts +12 -6
  42. package/dist/httpServer.d.ts.map +1 -1
  43. package/dist/httpServer.js +104 -18
  44. package/dist/httpServer.js.map +1 -1
  45. package/dist/httpServer.test.d.ts +2 -0
  46. package/dist/httpServer.test.d.ts.map +1 -0
  47. package/dist/mcp/McpServer.d.ts +5 -0
  48. package/dist/mcp/McpServer.d.ts.map +1 -1
  49. package/dist/mcp/McpServer.js +235 -8
  50. package/dist/mcp/McpServer.js.map +1 -1
  51. package/dist/visualCache.d.ts +34 -0
  52. package/dist/visualCache.d.ts.map +1 -0
  53. package/dist/visualCache.js +90 -0
  54. package/dist/visualCache.js.map +1 -0
  55. package/dist/watchConfig.d.ts +50 -4
  56. package/dist/watchConfig.d.ts.map +1 -1
  57. package/dist/watchConfig.js +72 -23
  58. package/dist/watchConfig.js.map +1 -1
  59. package/package.json +1 -1
@@ -1,6 +1,4 @@
1
- import type { IObservable } from '@vscode/observables';
2
1
  import { type ILogger } from './logger.js';
3
- import { SourceTreeId } from './sourceTreeId.js';
4
2
  import { ViteProjectRef } from './viteProjectRef.js';
5
3
  export interface ViteServerOptions {
6
4
  readonly resolveViteFrom?: string;
@@ -13,18 +11,26 @@ export interface ViteServerOptions {
13
11
  readonly pluginProtocolVersion: string;
14
12
  };
15
13
  }
14
+ export interface HttpServerOptions {
15
+ readonly cmd?: string;
16
+ readonly cwd?: string;
17
+ readonly logger?: ILogger;
18
+ readonly wait?: {
19
+ readonly stdout?: RegExp;
20
+ readonly stderr?: RegExp;
21
+ };
22
+ }
16
23
  export interface ComponentExplorerHttpServerFactory {
17
24
  createViteServer(project: ViteProjectRef, options?: ViteServerOptions): Promise<ComponentExplorerHttpServer>;
18
- createStaticServer(distDir: string): Promise<ComponentExplorerHttpServer>;
25
+ createHttpServer(url: string, options?: HttpServerOptions): Promise<ComponentExplorerHttpServer>;
19
26
  }
20
27
  export interface ComponentExplorerHttpServer {
21
28
  readonly url: string;
22
- readonly isStatic: boolean;
23
- readonly sourceTreeId: IObservable<SourceTreeId>;
29
+ readonly onSourceChange?: (callback: () => void) => void;
24
30
  dispose(): Promise<void>;
25
31
  }
26
32
  export declare class DefaultComponentExplorerHttpServerFactory implements ComponentExplorerHttpServerFactory {
27
33
  createViteServer(project: ViteProjectRef, options?: ViteServerOptions): Promise<ComponentExplorerHttpServer>;
28
- createStaticServer(_distDir: string): Promise<ComponentExplorerHttpServer>;
34
+ createHttpServer(url: string, options?: HttpServerOptions): Promise<ComponentExplorerHttpServer>;
29
35
  }
30
36
  //# sourceMappingURL=httpServer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpServer.d.ts","sourceRoot":"","sources":["../src/httpServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE;QACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;KACvC,CAAC;CACF;AAED,MAAM,WAAW,kCAAkC;IAClD,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC7G,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,qBAAa,yCAA0C,YAAW,kCAAkC;IAC7F,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAI5G,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAGhF"}
1
+ {"version":3,"file":"httpServer.d.ts","sourceRoot":"","sources":["../src/httpServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE;QACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;KACvC,CAAC;CACF;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE;QACf,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACF;AAED,MAAM,WAAW,kCAAkC;IAClD,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC7G,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACjG;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACzD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,qBAAa,yCAA0C,YAAW,kCAAkC;IAC7F,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAI5G,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAGtG"}
@@ -1,29 +1,116 @@
1
- import './external/vscode-observables/observables/dist/observableInternal/index.js';
2
- import { observableValue } from './external/vscode-observables/observables/dist/observableInternal/observables/observableValue.js';
3
- import './external/vscode-observables/observables/dist/observableInternal/debugLocation.js';
4
- import './external/vscode-observables/observables/dist/observableInternal/observables/derived.js';
5
- import './external/vscode-observables/observables/dist/observableInternal/utils/utils.js';
6
- import './external/vscode-observables/observables/dist/observableInternal/observables/observableFromEvent.js';
7
1
  import { nullLogger } from './logger.js';
8
- import { SourceTreeId } from './sourceTreeId.js';
9
2
 
10
3
  class DefaultComponentExplorerHttpServerFactory {
11
4
  async createViteServer(project, options) {
12
5
  return ViteComponentExplorerHttpServer.create(project, options);
13
6
  }
14
- async createStaticServer(_distDir) {
15
- throw new Error('Static server not yet implemented');
7
+ async createHttpServer(url, options) {
8
+ return HttpComponentExplorerServer.create(url, options);
16
9
  }
17
10
  }
11
+ class HttpComponentExplorerServer {
12
+ url;
13
+ _process;
14
+ static async create(urlTemplate, options) {
15
+ let proc;
16
+ let vars = {};
17
+ if (options?.cmd) {
18
+ const log = options.logger ?? nullLogger;
19
+ log.debug(`Starting HTTP server: ${options.cmd}`);
20
+ log.debug(`HTTP server cwd: ${options.cwd ?? process.cwd()}`);
21
+ const { spawn } = await import('node:child_process');
22
+ proc = spawn(options.cmd, { shell: true, stdio: 'pipe', cwd: options.cwd });
23
+ proc.on('error', (e) => log.log(`HTTP server process error: ${e.message}`));
24
+ proc.on('exit', (code) => log.debug(`HTTP server process exited (code=${code})`));
25
+ if (options.wait?.stdout || options.wait?.stderr) {
26
+ vars = await waitForOutputPattern(proc, options.wait, log);
27
+ }
28
+ else {
29
+ proc.stdout?.on('data', (d) => log.trace(d.toString().trimEnd()));
30
+ proc.stderr?.on('data', (d) => log.trace(d.toString().trimEnd()));
31
+ }
32
+ }
33
+ const url = resolveUrlTemplate(urlTemplate, vars);
34
+ return new HttpComponentExplorerServer(url, proc);
35
+ }
36
+ constructor(url, _process) {
37
+ this.url = url;
38
+ this._process = _process;
39
+ }
40
+ async dispose() {
41
+ if (this._process && !this._process.killed) {
42
+ this._process.kill();
43
+ }
44
+ }
45
+ }
46
+ function resolveUrlTemplate(template, vars) {
47
+ return template.replace(/\$\{var:([^}]+)\}/g, (match, name) => {
48
+ if (!(name in vars)) {
49
+ throw new Error(`Unresolved variable \${var:${name}} in URL. Available: ${Object.keys(vars).join(', ') || '(none)'}`);
50
+ }
51
+ return vars[name];
52
+ });
53
+ }
54
+ const _stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '').replace(/\x1b\].*?\x07/g, '');
55
+ function waitForOutputPattern(proc, wait, log) {
56
+ return new Promise((resolve, reject) => {
57
+ let resolved = false;
58
+ const vars = {};
59
+ let pendingCount = (wait.stdout ? 1 : 0) + (wait.stderr ? 1 : 0);
60
+ const buffers = { stdout: '', stderr: '' };
61
+ const tryResolve = () => {
62
+ if (resolved || pendingCount > 0) {
63
+ return;
64
+ }
65
+ resolved = true;
66
+ proc.stdout?.on('data', (d) => log.trace(d.toString().trimEnd()));
67
+ proc.stderr?.on('data', (d) => log.trace(d.toString().trimEnd()));
68
+ resolve(vars);
69
+ };
70
+ const makeHandler = (stream, pattern) => {
71
+ const handler = (d) => {
72
+ const text = d.toString();
73
+ log.trace(text.trimEnd());
74
+ buffers[stream] += _stripAnsi(text);
75
+ const m = pattern.exec(buffers[stream]);
76
+ if (m) {
77
+ log.debug(`${stream} pattern matched: ${JSON.stringify(m.groups ?? {})}`);
78
+ proc[stream]?.off('data', handler);
79
+ Object.assign(vars, m.groups ?? {});
80
+ pendingCount--;
81
+ tryResolve();
82
+ }
83
+ };
84
+ return handler;
85
+ };
86
+ if (wait.stdout) {
87
+ proc.stdout?.on('data', makeHandler('stdout', wait.stdout));
88
+ }
89
+ else {
90
+ proc.stdout?.on('data', (d) => log.trace(d.toString().trimEnd()));
91
+ }
92
+ if (wait.stderr) {
93
+ proc.stderr?.on('data', makeHandler('stderr', wait.stderr));
94
+ }
95
+ else {
96
+ proc.stderr?.on('data', (d) => log.trace(d.toString().trimEnd()));
97
+ }
98
+ proc.on('exit', (code) => {
99
+ if (!resolved) {
100
+ const details = [wait.stdout ? `stdout buffer:\n${buffers.stdout}` : '', wait.stderr ? `stderr buffer:\n${buffers.stderr}` : ''].filter(Boolean).join('\n');
101
+ reject(new Error(`HTTP server process exited (code=${code}) before output matched wait patterns.\n${details}`));
102
+ }
103
+ });
104
+ });
105
+ }
18
106
  class ViteComponentExplorerHttpServer {
19
107
  _server;
20
108
  url;
21
- sourceTreeId;
22
- isStatic = false;
23
- constructor(_server, url, sourceTreeId) {
109
+ onSourceChange;
110
+ constructor(_server, url, onSourceChange) {
24
111
  this._server = _server;
25
112
  this.url = url;
26
- this.sourceTreeId = sourceTreeId;
113
+ this.onSourceChange = onSourceChange;
27
114
  }
28
115
  static async create(project, options) {
29
116
  const log = options?.logger ?? nullLogger;
@@ -116,11 +203,10 @@ class ViteComponentExplorerHttpServer {
116
203
  const resolvedUrls = server.resolvedUrls;
117
204
  const url = resolvedUrls?.local[0] ?? `http://localhost:${server.httpServer?.address()?.port}`;
118
205
  log.debug(`Vite server started: ${url}`);
119
- const treeId = observableValue('sourceTreeId', new SourceTreeId(Date.now().toString()));
120
- server.watcher.on('change', () => {
121
- treeId.set(new SourceTreeId(Date.now().toString()), undefined);
122
- });
123
- return new ViteComponentExplorerHttpServer(server, url.replace(/\/$/, ''), treeId);
206
+ const onSourceChange = (callback) => {
207
+ server.watcher.on('change', callback);
208
+ };
209
+ return new ViteComponentExplorerHttpServer(server, url.replace(/\/$/, ''), onSourceChange);
124
210
  }
125
211
  async dispose() {
126
212
  await this._server.close();
@@ -1 +1 @@
1
- {"version":3,"file":"httpServer.js","sources":["../src/httpServer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpServer.js","sources":["../src/httpServer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=httpServer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpServer.test.d.ts","sourceRoot":"","sources":["../src/httpServer.test.ts"],"names":[],"mappings":""}
@@ -18,6 +18,7 @@ export declare class ComponentExplorerMcpServer extends Disposable {
18
18
  static create(daemon: IObservable<DaemonConnection | undefined>, options?: McpServerOptions): Promise<ComponentExplorerMcpServer>;
19
19
  private readonly _mcp;
20
20
  private readonly _watchList;
21
+ private readonly _imageLru;
21
22
  private readonly _taskManager;
22
23
  private readonly _taskLastReportedIndex;
23
24
  private readonly _pollFn?;
@@ -50,6 +51,8 @@ export declare class ComponentExplorerMcpServer extends Disposable {
50
51
  private _registerScreenshot;
51
52
  private _registerCompareScreenshot;
52
53
  private _registerApproveDiff;
54
+ private _registerReviewVisual;
55
+ private _registerCheckVisuals;
53
56
  private _registerEvaluateJs;
54
57
  private _registerDebugReloadPage;
55
58
  private _registerWatchAdd;
@@ -67,5 +70,7 @@ export declare class ComponentExplorerMcpServer extends Disposable {
67
70
  private _registerCheckStability;
68
71
  private _registerCheckTask;
69
72
  private _registerCancelTask;
73
+ private _registerDebugGetImageByHash;
74
+ private _registerDebugSetBrowserVisibility;
70
75
  }
71
76
  //# sourceMappingURL=McpServer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"McpServer.d.ts","sourceRoot":"","sources":["../../src/mcp/McpServer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAW,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,4BAA4B,CAAC;AAqE7E,qBAAa,gBAAgB;IAEhB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC;IAD1D,OAAO,CAAC,MAAM,CAAS;gBACF,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC;IAC1D,IAAI,OAAO,IAAI,OAAO,CAAwB;IAC9C,SAAS,IAAI,IAAI;CACjB;AAWD,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,0BAA2B,SAAQ,UAAU;IAsBxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB;WArBtB,MAAM,CAClB,MAAM,EAAE,WAAW,CAAC,gBAAgB,GAAG,SAAS,CAAC,EACjD,OAAO,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,0BAA0B,CAAC;IAOtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA6B;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAwB;IAC3D,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,2BAA2B,CAA8B;IAEjE,OAAO;YAmBO,gBAAgB;IAqB9B,OAAO,CAAC,cAAc;YAMR,cAAc;IAkB5B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;YAE1B,WAAW;IA8BzB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,2BAA2B;IAKnC,OAAO,CAAC,0BAA0B;IAKlC,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,0BAA0B;YAOpB,gBAAgB;IAmB9B,OAAO,CAAC,iCAAiC;YAW3B,oBAAoB;IAelC,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,qBAAqB;IA8B7B,OAAO,CAAC,mBAAmB;IAoF3B,OAAO,CAAC,0BAA0B;IA8FlC,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,mBAAmB;IAsC3B,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,qBAAqB;IA2E7B,OAAO,CAAC,sBAAsB;YAgEhB,oBAAoB;IA6ClC,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,qBAAqB;IAuB7B,OAAO,CAAC,yBAAyB;IAwBjC,OAAO,CAAC,eAAe;IAkFvB,OAAO,CAAC,uBAAuB;IA+F/B,OAAO,CAAC,kBAAkB;IAoD1B,OAAO,CAAC,mBAAmB;CAoB3B"}
1
+ {"version":3,"file":"McpServer.d.ts","sourceRoot":"","sources":["../../src/mcp/McpServer.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,35 @@ import { TaskManager } from './TaskManager.js';
14
14
  // ---------------------------------------------------------------------------
15
15
  // Client-local state
16
16
  // ---------------------------------------------------------------------------
17
+ class ImageLruCache {
18
+ _maxSize;
19
+ _entries = [];
20
+ constructor(_maxSize = 10) {
21
+ this._maxSize = _maxSize;
22
+ }
23
+ put(hash, image) {
24
+ const idx = this._entries.findIndex(e => e.hash === hash);
25
+ if (idx !== -1) {
26
+ this._entries.splice(idx, 1);
27
+ }
28
+ this._entries.unshift({ hash, image });
29
+ if (this._entries.length > this._maxSize) {
30
+ this._entries.length = this._maxSize;
31
+ }
32
+ }
33
+ get(hash) {
34
+ const idx = this._entries.findIndex(e => e.hash === hash);
35
+ if (idx === -1) {
36
+ return undefined;
37
+ }
38
+ const [entry] = this._entries.splice(idx, 1);
39
+ this._entries.unshift(entry);
40
+ return entry.image;
41
+ }
42
+ keys() {
43
+ return this._entries.map(e => e.hash);
44
+ }
45
+ }
17
46
  class WatchList {
18
47
  _fixtureIds = new Set();
19
48
  _hashes = new Map();
@@ -101,6 +130,7 @@ class ComponentExplorerMcpServer extends Disposable {
101
130
  }
102
131
  _mcp;
103
132
  _watchList = new WatchList();
133
+ _imageLru = new ImageLruCache(10);
104
134
  _taskManager = new TaskManager();
105
135
  _taskLastReportedIndex = new Map();
106
136
  _pollFn;
@@ -337,6 +367,8 @@ class ComponentExplorerMcpServer extends Disposable {
337
367
  this._registerScreenshot();
338
368
  this._registerCompareScreenshot();
339
369
  this._registerApproveDiff();
370
+ this._registerReviewVisual();
371
+ this._registerCheckVisuals();
340
372
  this._registerEvaluateJs();
341
373
  this._registerDebugReloadPage();
342
374
  this._registerWatchAdd();
@@ -353,6 +385,8 @@ class ComponentExplorerMcpServer extends Disposable {
353
385
  this._registerCheckStability();
354
386
  this._registerCheckTask();
355
387
  this._registerCancelTask();
388
+ this._registerDebugGetImageByHash();
389
+ this._registerDebugSetBrowserVisibility();
356
390
  }
357
391
  _registerListFixtures() {
358
392
  this._mcp.registerTool('list_fixtures', {
@@ -369,14 +403,17 @@ class ComponentExplorerMcpServer extends Disposable {
369
403
  this._log('debug', { type: 'tool-call', tool: 'list_fixtures', sessionName });
370
404
  return this._withSourceTreeRetry(async () => {
371
405
  const sourceTreeId = args.sourceTreeId ?? this._sourceTreeId(sessionName);
372
- const allFixtures = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
373
- const filtered = this._filterFixtures(allFixtures, args.fixtureIdPattern, args.labelPattern);
406
+ const listResult = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
407
+ const filtered = this._filterFixtures(listResult.fixtures, args.fixtureIdPattern, args.labelPattern);
374
408
  if ('error' in filtered) {
375
409
  return { content: [{ type: 'text', text: filtered.error }], isError: true };
376
410
  }
377
- return {
378
- content: [{ type: 'text', text: JSON.stringify(filtered.fixtures, null, 2) }],
379
- };
411
+ const content = [];
412
+ if (listResult.loadError) {
413
+ content.push({ type: 'text', text: `Warning: Fixture loading encountered an error: ${listResult.loadError}\nThe fixture list may be incomplete.` });
414
+ }
415
+ content.push({ type: 'text', text: JSON.stringify(filtered.fixtures, null, 2) });
416
+ return { content };
380
417
  });
381
418
  }));
382
419
  }
@@ -406,6 +443,10 @@ class ComponentExplorerMcpServer extends Disposable {
406
443
  });
407
444
  const r = result;
408
445
  this._updateSessionSourceTreeId(sessionName, r.sourceTreeId);
446
+ // Cache image for debug_get_image_by_hash
447
+ if (r.hash && r.image) {
448
+ this._imageLru.put(r.hash, r.image);
449
+ }
409
450
  const info = {
410
451
  hash: r.hash,
411
452
  sourceTreeId: r.sourceTreeId,
@@ -425,6 +466,23 @@ class ComponentExplorerMcpServer extends Disposable {
425
466
  if (r.isStable !== undefined) {
426
467
  info.isStable = r.isStable;
427
468
  }
469
+ // Visual review status
470
+ if (r.hash) {
471
+ try {
472
+ const listResult = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
473
+ const fixture = listResult.fixtures.find(f => f.fixtureId === args.fixtureId);
474
+ const descriptions = fixture?.expectedVisualDescriptions ?? [];
475
+ const review = await daemon.methods.visualReview.getStatus({
476
+ fixtureId: args.fixtureId,
477
+ expectedVisualDescriptions: [...descriptions],
478
+ screenshotHash: r.hash,
479
+ });
480
+ info.review = review;
481
+ }
482
+ catch {
483
+ // Visual review not available — ignore
484
+ }
485
+ }
428
486
  const content = [];
429
487
  if (r.isStable === false && r.stabilityScreenshots) {
430
488
  // Not stable: return all distinct screenshots
@@ -545,6 +603,130 @@ class ComponentExplorerMcpServer extends Disposable {
545
603
  tool.disable();
546
604
  this._multiSessionTools.push(tool);
547
605
  }
606
+ _registerReviewVisual() {
607
+ this._mcp.registerTool('review_visual', {
608
+ description: 'Approve or reject a fixture\'s screenshot based on its expectedVisualDescriptions. ' +
609
+ 'You must take a screenshot first and pass the resulting hash. ' +
610
+ 'On approve, caches (expectedVisualDescriptions, screenshotHash) so future runs auto-approve.',
611
+ inputSchema: {
612
+ fixtureId: z.string().describe('The fixture ID'),
613
+ screenshotHash: z.string().describe('The screenshot hash (from a prior screenshot tool call)'),
614
+ verdict: z.enum(['approve', 'reject']).describe('Whether the visual matches expectations'),
615
+ comment: z.string().describe('Reason for the verdict'),
616
+ sessionName: z.string().optional().describe('Session name (defaults to first session)'),
617
+ sourceTreeId: z.string().optional().describe('Source tree ID (defaults to latest known)'),
618
+ },
619
+ }, async (args) => this._withDaemon(async (daemon) => {
620
+ const sessionName = args.sessionName ?? this._defaultSessionName();
621
+ this._log('debug', { type: 'tool-call', tool: 'review_visual', fixtureId: args.fixtureId, verdict: args.verdict });
622
+ return this._withSourceTreeRetry(async () => {
623
+ const sourceTreeId = args.sourceTreeId ?? this._sourceTreeId(sessionName);
624
+ // Get fixture descriptions
625
+ const listResult = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
626
+ const fixture = listResult.fixtures.find(f => f.fixtureId === args.fixtureId);
627
+ if (!fixture) {
628
+ return { content: [{ type: 'text', text: `Fixture not found: ${args.fixtureId}` }], isError: true };
629
+ }
630
+ if (fixture.expectedVisualDescriptions.length === 0) {
631
+ return { content: [{ type: 'text', text: `Fixture ${args.fixtureId} has no expectedVisualDescriptions — nothing to review.` }], isError: true };
632
+ }
633
+ if (args.verdict === 'approve') {
634
+ await daemon.methods.visualReview.approve({
635
+ fixtureId: args.fixtureId,
636
+ expectedVisualDescriptions: [...fixture.expectedVisualDescriptions],
637
+ screenshotHash: args.screenshotHash,
638
+ comment: args.comment,
639
+ });
640
+ return {
641
+ content: [{ type: 'text', text: `Approved: ${args.fixtureId} (hash: ${args.screenshotHash})` }],
642
+ };
643
+ }
644
+ else {
645
+ return {
646
+ content: [{ type: 'text', text: JSON.stringify({
647
+ fixtureId: args.fixtureId,
648
+ verdict: 'rejected',
649
+ comment: args.comment,
650
+ screenshotHash: args.screenshotHash,
651
+ expectedVisualDescriptions: fixture.expectedVisualDescriptions,
652
+ }, null, 2) }],
653
+ };
654
+ }
655
+ });
656
+ }));
657
+ }
658
+ _registerCheckVisuals() {
659
+ this._mcp.registerTool('check_visuals', {
660
+ description: 'Batch check visual review status for fixtures that have expectedVisualDescription. ' +
661
+ 'Returns lists of approved, needs-review, and no-expectation fixtures.',
662
+ inputSchema: {
663
+ fixtureIdPattern: z.string().optional().describe('RegExp to filter fixtures by fixture ID'),
664
+ labelPattern: z.string().optional().describe('RegExp to filter fixtures by label'),
665
+ sessionName: z.string().optional().describe('Session name (defaults to first session)'),
666
+ sourceTreeId: z.string().optional().describe('Source tree ID (defaults to latest known)'),
667
+ },
668
+ annotations: { readOnlyHint: true },
669
+ }, async (args) => this._withDaemon(async (daemon) => {
670
+ const sessionName = args.sessionName ?? this._defaultSessionName();
671
+ this._log('debug', { type: 'tool-call', tool: 'check_visuals', sessionName });
672
+ return this._withSourceTreeRetry(async () => {
673
+ const sourceTreeId = args.sourceTreeId ?? this._sourceTreeId(sessionName);
674
+ const listResult = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
675
+ if (listResult.loadError) {
676
+ return { content: [{ type: 'text', text: `Error: Fixture loading failed: ${listResult.loadError}\nThe fixture list may be incomplete.` }], isError: true };
677
+ }
678
+ const filtered = this._filterFixtures(listResult.fixtures, args.fixtureIdPattern, args.labelPattern);
679
+ if ('error' in filtered) {
680
+ return { content: [{ type: 'text', text: filtered.error }], isError: true };
681
+ }
682
+ const approved = [];
683
+ const needsReview = [];
684
+ const noExpectation = [];
685
+ // Take screenshots for all fixtures with expectations
686
+ const withExpectations = filtered.fixtures.filter(f => f.expectedVisualDescriptions.length > 0);
687
+ const withoutExpectations = filtered.fixtures.filter(f => f.expectedVisualDescriptions.length === 0);
688
+ for (const f of withoutExpectations) {
689
+ noExpectation.push(f.fixtureId);
690
+ }
691
+ for (const f of withExpectations) {
692
+ try {
693
+ const screenshotResult = await daemon.methods.screenshots.take({
694
+ fixtureId: f.fixtureId, sessionName, sourceTreeId, includeImage: true,
695
+ });
696
+ const hash = screenshotResult.hash;
697
+ const image = screenshotResult.image;
698
+ if (hash && image) {
699
+ this._imageLru.put(hash, image);
700
+ }
701
+ if (!hash) {
702
+ needsReview.push({ fixtureId: f.fixtureId, reason: 'screenshot-failed' });
703
+ continue;
704
+ }
705
+ const review = await daemon.methods.visualReview.getStatus({
706
+ fixtureId: f.fixtureId,
707
+ expectedVisualDescriptions: [...f.expectedVisualDescriptions],
708
+ screenshotHash: hash,
709
+ });
710
+ if (review === 'no-expectations') {
711
+ noExpectation.push(f.fixtureId);
712
+ }
713
+ else if (typeof review === 'object' && review.status === 'approved') {
714
+ approved.push({ fixtureId: f.fixtureId, screenshotHash: hash });
715
+ }
716
+ else {
717
+ needsReview.push({ fixtureId: f.fixtureId, screenshotHash: hash, reason: 'needs-review' });
718
+ }
719
+ }
720
+ catch {
721
+ needsReview.push({ fixtureId: f.fixtureId, reason: 'error' });
722
+ }
723
+ }
724
+ return {
725
+ content: [{ type: 'text', text: JSON.stringify({ approved, needsReview, noExpectation }, null, 2) }],
726
+ };
727
+ });
728
+ }));
729
+ }
548
730
  _registerEvaluateJs() {
549
731
  this._mcp.registerTool('evaluate_js', {
550
732
  description: 'Evaluate a JavaScript expression in the browser page where fixtures are rendered, for debugging purposes. ' +
@@ -1005,13 +1187,16 @@ class ComponentExplorerMcpServer extends Disposable {
1005
1187
  this._log('debug', { type: 'tool-call', tool: 'check_stability', sessionName, fixtureIdPattern: args.fixtureIdPattern, labelPattern: args.labelPattern });
1006
1188
  return this._withSourceTreeRetry(async () => {
1007
1189
  const sourceTreeId = args.sourceTreeId ?? this._sourceTreeId(sessionName);
1008
- const allFixtures = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
1009
- const filtered = this._filterFixtures(allFixtures, args.fixtureIdPattern, args.labelPattern);
1190
+ const listResult = await daemon.methods.fixtures.list({ sessionName, sourceTreeId });
1191
+ if (listResult.loadError) {
1192
+ return { content: [{ type: 'text', text: `Error: Fixture loading failed: ${listResult.loadError}\nThe fixture list may be incomplete.` }], isError: true };
1193
+ }
1194
+ const filtered = this._filterFixtures(listResult.fixtures, args.fixtureIdPattern, args.labelPattern);
1010
1195
  if ('error' in filtered) {
1011
1196
  return { content: [{ type: 'text', text: filtered.error }], isError: true };
1012
1197
  }
1013
1198
  const fixtures = filtered.fixtures;
1014
- this._log('info', { type: 'check-stability-start', total: fixtures.length, filtered: allFixtures.length - fixtures.length });
1199
+ this._log('info', { type: 'check-stability-start', total: fixtures.length, filtered: listResult.fixtures.length - fixtures.length });
1015
1200
  const task = this._taskManager.startTask(async (report, signal) => {
1016
1201
  const results = [];
1017
1202
  report({ completed: 0, total: fixtures.length, partialResult: results });
@@ -1138,6 +1323,48 @@ class ComponentExplorerMcpServer extends Disposable {
1138
1323
  };
1139
1324
  });
1140
1325
  }
1326
+ _registerDebugGetImageByHash() {
1327
+ this._mcp.registerTool('debug_get_image_by_hash', {
1328
+ description: 'Retrieve a recently-taken screenshot image by its hash. ' +
1329
+ 'Keeps the last ~10 images in an LRU cache. ' +
1330
+ 'Useful for debugging when screenshot hashes behave unexpectedly.',
1331
+ inputSchema: {
1332
+ hash: z.string().describe('The screenshot hash to look up'),
1333
+ },
1334
+ annotations: { readOnlyHint: true },
1335
+ }, async (args) => {
1336
+ const image = this._imageLru.get(args.hash);
1337
+ if (!image) {
1338
+ return {
1339
+ content: [{ type: 'text', text: `No cached image for hash '${args.hash}'. Available hashes: ${this._imageLru.keys().join(', ') || '(none)'}` }],
1340
+ isError: true,
1341
+ };
1342
+ }
1343
+ return {
1344
+ content: [
1345
+ { type: 'text', text: `Image for hash: ${args.hash}` },
1346
+ { type: 'image', data: image, mimeType: 'image/png' },
1347
+ ],
1348
+ };
1349
+ });
1350
+ }
1351
+ _registerDebugSetBrowserVisibility() {
1352
+ this._mcp.registerTool('debug_set_browser_visibility', {
1353
+ description: 'Show or hide the browser window used for rendering fixtures. ' +
1354
+ 'Only use this tool when the user explicitly asks to show or hide the browser. ' +
1355
+ 'Do not call this tool automatically or as part of other workflows. ' +
1356
+ 'Note: changing visibility closes the current browser instance, so the next screenshot or evaluate_js call will relaunch it.',
1357
+ inputSchema: {
1358
+ visible: z.boolean().describe('true to show the browser window (headed mode), false to hide it (headless mode)'),
1359
+ },
1360
+ annotations: { destructiveHint: true },
1361
+ }, async (args) => this._withDaemon(async (daemon) => {
1362
+ await daemon.methods.setBrowserVisibility({ visible: args.visible });
1363
+ return {
1364
+ content: [{ type: 'text', text: `Browser is now ${args.visible ? 'visible (headed)' : 'hidden (headless)'}.` }],
1365
+ };
1366
+ }));
1367
+ }
1141
1368
  }
1142
1369
 
1143
1370
  export { ComponentExplorerMcpServer, DaemonConnection };