@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 +14 -0
- package/dist/cli.js +15 -112
- package/dist/cli.js.map +1 -1
- package/dist/index.js +15 -112
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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 {
|
|
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 {
|
|
94
|
+
import {
|
|
95
|
+
enrichSnapshot
|
|
96
|
+
} from "@sightmap/sightmap";
|
|
91
97
|
function buildSightmapSnapshotResponse(opts) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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 {
|
|
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 =
|
|
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("{");
|