@sightmap/mcp 0.5.1 → 0.6.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/README.md CHANGED
@@ -57,6 +57,18 @@ Walks an author through writing a Sightmap Enhancement Proposal (SEP), the match
57
57
 
58
58
  **Why this exists:** SEPs require coordinated edits across three trees (`seps/`, `spec/`, `conformance/`). The track encodes the order, the dependencies, and the user check-in points so neither the author nor the agent can short-circuit them. Pattern adapted from Archcore's `architecture_track`.
59
59
 
60
+ ## Running curation-only (no browser)
61
+
62
+ If you're integrating with a tool that already drives the browser
63
+ (Subtext, agent-browser, or a custom harness), you only need sightmap's
64
+ curation surface — not its Playwright wrapping. Spawn with `--curate-only`:
65
+
66
+ sightmap-mcp --sightmap-dir .sightmap --curate-only
67
+
68
+ Only the `sightmap_list_views`, `sightmap_get_view`, `sightmap_update_view`,
69
+ `sightmap_check`, `sightmap_init_project`, and `sightmap_match` tools are
70
+ registered. No `@playwright/mcp` subprocess is launched.
71
+
60
72
  ## Usage
61
73
 
62
74
  ```sh
@@ -73,6 +85,8 @@ sightmap-mcp \
73
85
  Default: .sightmap
74
86
  --curate-root <path> Writable .sightmap/ for curation tools.
75
87
  Default: the first --sightmap-dir.
88
+ --curate-only Register only curation tools; do not spawn
89
+ an upstream browser MCP.
76
90
  --upstream-command <cmd> Command to spawn the upstream MCP server. Default: npx
77
91
  -- <args...> Args for the upstream command.
78
92
  Default: -y @playwright/mcp@latest
package/dist/cli.js CHANGED
@@ -54,7 +54,11 @@ import { readFileSync, realpathSync } from "fs";
54
54
  import { fileURLToPath } from "url";
55
55
 
56
56
  // src/server.ts
57
- import { match as sightmapMatch4 } from "@sightmap/sightmap";
57
+ import {
58
+ match as sightmapMatch2,
59
+ resolveSightmapAct,
60
+ buildInPageEvalFunction
61
+ } from "@sightmap/sightmap";
58
62
 
59
63
  // src/tools/match.ts
60
64
  import { match as sightmapMatch } from "@sightmap/sightmap";
@@ -87,72 +91,20 @@ function handleSightmapMatch(sightmap, input) {
87
91
  }
88
92
 
89
93
  // src/tools/snapshot.ts
90
- import { match as sightmapMatch2 } from "@sightmap/sightmap";
94
+ import {
95
+ enrichSnapshot
96
+ } from "@sightmap/sightmap";
91
97
  function buildSightmapSnapshotResponse(opts) {
92
- const { sightmap, currentUrl, ariaSnapshotText, inPageMatches } = opts;
93
- const result = sightmapMatch2(sightmap, { url: currentUrl });
94
- const inPageByName = /* @__PURE__ */ new Map();
95
- for (const m of inPageMatches) inPageByName.set(m.name, m);
96
- const components = result.components.map((c) => {
97
- const inPage = inPageByName.get(c.name);
98
- return {
99
- name: c.name,
100
- selector: c.selector,
101
- memory: c.memory ?? [],
102
- scope: c.scope,
103
- matchCount: inPage?.matchCount ?? 0,
104
- ...inPage?.samplePosition !== void 0 ? { samplePosition: inPage.samplePosition } : {}
105
- };
98
+ const enriched = enrichSnapshot({
99
+ sightmap: opts.sightmap,
100
+ currentUrl: opts.currentUrl,
101
+ inPageMatches: opts.inPageMatches
106
102
  });
107
- return {
108
- view: result.view ? {
109
- name: result.view.name,
110
- route: result.view.route,
111
- memory: result.view.memory ?? []
112
- } : null,
113
- components,
114
- memory: result.memory ?? [],
115
- ariaSnapshot: ariaSnapshotText
116
- };
117
- }
118
-
119
- // src/tools/act.ts
120
- function resolveSightmapAct(sightmap, input) {
121
- const found = findComponentByName(sightmap, input.componentName);
122
- if (found === null) {
123
- return {
124
- kind: "error",
125
- message: `Component "${input.componentName}" not found in the loaded sightmap.`
126
- };
127
- }
128
- const selectors = Array.isArray(found.selector) ? found.selector : [];
129
- if (selectors.length === 0) {
130
- return {
131
- kind: "error",
132
- message: `Component "${input.componentName}" has no selector \u2014 cannot dispatch an action.`
133
- };
134
- }
135
- return {
136
- kind: "ok",
137
- componentName: input.componentName,
138
- selector: selectors[0],
139
- allSelectors: selectors
140
- };
141
- }
142
- function findComponentByName(sightmap, name) {
143
- for (const c of sightmap.globalComponents) {
144
- if (c.name === name) return c;
145
- }
146
- for (const v of sightmap.views) {
147
- for (const c of v.components ?? []) {
148
- if (c.name === name) return c;
149
- }
150
- }
151
- return null;
103
+ return { ...enriched, ariaSnapshot: opts.ariaSnapshotText };
152
104
  }
153
105
 
154
106
  // src/tools/network.ts
155
- import { match as sightmapMatch3 } from "@sightmap/sightmap";
107
+ import { annotateNetworkRequests } from "@sightmap/sightmap";
156
108
  function parseNetworkRequestsText(text) {
157
109
  const lines = text.split(/\r?\n/);
158
110
  const requests = [];
@@ -169,18 +121,6 @@ function parseNetworkRequestsText(text) {
169
121
  }
170
122
  return requests;
171
123
  }
172
- function annotateNetworkRequests(sightmap, requests) {
173
- return requests.map((req) => {
174
- const result = sightmapMatch3(sightmap, { url: req.url, method: req.method });
175
- const first = result.requests[0];
176
- if (first === void 0) return req;
177
- const annotated = { ...req, sightmapName: first.name };
178
- if (first.memory && first.memory.length > 0) {
179
- annotated.sightmapMemory = first.memory;
180
- }
181
- return annotated;
182
- });
183
- }
184
124
 
185
125
  // src/tools/curate/list.ts
186
126
  function handleListViews(sightmap, input) {
@@ -966,7 +906,7 @@ var SightmapMcpServer = class {
966
906
  }
967
907
  const ariaSnapshotText = snapResult.content.map((b) => b.text).join("\n");
968
908
  const currentUrl = parsePageUrl(ariaSnapshotText) ?? "";
969
- const matchResult = sightmapMatch4(this.sightmap, { url: currentUrl });
909
+ const matchResult = sightmapMatch2(this.sightmap, { url: currentUrl });
970
910
  const componentSelectors = matchResult.components.map((c) => ({
971
911
  name: c.name,
972
912
  selector: c.selector
@@ -1110,43 +1050,6 @@ function parsePageUrl(text) {
1110
1050
  const m = /Page URL:\s*(\S+)/.exec(text);
1111
1051
  return m?.[1] ?? null;
1112
1052
  }
1113
- function buildInPageEvalFunction(components) {
1114
- const componentsJson = JSON.stringify(components);
1115
- return `() => {
1116
- const components = ${componentsJson};
1117
- const matches = components.map((c) => {
1118
- const selectors = c.selector || [];
1119
- const seen = new Set();
1120
- const elements = [];
1121
- for (const sel of selectors) {
1122
- try {
1123
- const found = document.querySelectorAll(sel);
1124
- for (const el of Array.from(found)) {
1125
- if (!seen.has(el)) {
1126
- seen.add(el);
1127
- elements.push(el);
1128
- }
1129
- }
1130
- } catch {
1131
- // Invalid selector \u2014 skip silently.
1132
- }
1133
- }
1134
- const first = elements[0];
1135
- let samplePosition;
1136
- if (first && typeof first.getBoundingClientRect === "function") {
1137
- const r = first.getBoundingClientRect();
1138
- samplePosition = { x: r.x, y: r.y, width: r.width, height: r.height };
1139
- }
1140
- return {
1141
- name: c.name,
1142
- selector: selectors,
1143
- matchCount: elements.length,
1144
- samplePosition,
1145
- };
1146
- });
1147
- return { url: window.location.href, matches };
1148
- }`;
1149
- }
1150
1053
  function parseInPageEvalResult(text) {
1151
1054
  const afterResult = text.split(/^###\s*Result/im)[1] ?? text;
1152
1055
  const start = afterResult.indexOf("{");