@sightmap/mcp 0.6.0 → 0.8.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/dist/cli.js +590 -19
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +583 -12
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -103,7 +103,14 @@ declare class SightmapMcpServer {
|
|
|
103
103
|
private callSightmapMatch;
|
|
104
104
|
private callSightmapGetView;
|
|
105
105
|
private callSightmapInitProject;
|
|
106
|
+
private callSightmapRuntimeSnapshot;
|
|
107
|
+
private callSightmapProposeView;
|
|
108
|
+
private callSightmapProposeComponent;
|
|
109
|
+
private callSightmapReviewProposals;
|
|
110
|
+
private callSightmapCommitProposals;
|
|
111
|
+
private callSightmapAddView;
|
|
106
112
|
private callSightmapUpdateView;
|
|
113
|
+
private callSightmapDeleteView;
|
|
107
114
|
private callSightmapCheck;
|
|
108
115
|
private callSightmapListViews;
|
|
109
116
|
}
|
package/dist/index.js
CHANGED
|
@@ -191,6 +191,22 @@ async function handleUpdateView(input) {
|
|
|
191
191
|
if (input.patch.memory_replace) {
|
|
192
192
|
after.memory = [...input.patch.memory_replace];
|
|
193
193
|
}
|
|
194
|
+
if (input.patch.name !== void 0) {
|
|
195
|
+
after.name = input.patch.name;
|
|
196
|
+
}
|
|
197
|
+
if (input.patch.route !== void 0) {
|
|
198
|
+
after.route = input.patch.route;
|
|
199
|
+
}
|
|
200
|
+
if (input.patch.components !== void 0) {
|
|
201
|
+
const seen = /* @__PURE__ */ new Set();
|
|
202
|
+
for (const c2 of input.patch.components) {
|
|
203
|
+
if (seen.has(c2.name)) {
|
|
204
|
+
throw new Error(`duplicate component name in patch: ${c2.name}`);
|
|
205
|
+
}
|
|
206
|
+
seen.add(c2.name);
|
|
207
|
+
}
|
|
208
|
+
after.components = input.patch.components;
|
|
209
|
+
}
|
|
194
210
|
const nextViews = [...views];
|
|
195
211
|
nextViews[idx] = after;
|
|
196
212
|
const nextDoc = stripFragmentBrand(parsed);
|
|
@@ -210,23 +226,108 @@ function stripFragmentBrand(input) {
|
|
|
210
226
|
return out;
|
|
211
227
|
}
|
|
212
228
|
|
|
229
|
+
// src/tools/curate/add.ts
|
|
230
|
+
import { writeFile as writeFile2, readFile as readFile4, readdir as readdir2 } from "fs/promises";
|
|
231
|
+
import { resolve, join as join2 } from "path";
|
|
232
|
+
import {
|
|
233
|
+
format as format2,
|
|
234
|
+
canonicalize as canonicalize2
|
|
235
|
+
} from "@sightmap/sightmap";
|
|
236
|
+
async function handleAddView(input) {
|
|
237
|
+
await ensureNotExists(input.sightmapDir, input.view.name);
|
|
238
|
+
const filename = input.file ?? kebab(input.view.name) + ".yaml";
|
|
239
|
+
const path = join2(input.sightmapDir, filename);
|
|
240
|
+
const doc = {
|
|
241
|
+
version: 1,
|
|
242
|
+
views: [input.view]
|
|
243
|
+
};
|
|
244
|
+
const out = format2(doc);
|
|
245
|
+
const c = canonicalize2(out, { file: path });
|
|
246
|
+
const text = c.kind === "canonical" ? c.text : out;
|
|
247
|
+
await writeFile2(path, text, "utf8");
|
|
248
|
+
return { ok: true, file: path, written: input.view };
|
|
249
|
+
}
|
|
250
|
+
async function ensureNotExists(dir, name) {
|
|
251
|
+
let files;
|
|
252
|
+
try {
|
|
253
|
+
files = await readdir2(dir);
|
|
254
|
+
} catch {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
for (const f of files) {
|
|
258
|
+
if (!f.endsWith(".yaml")) continue;
|
|
259
|
+
const text = await readFile4(resolve(dir, f), "utf8");
|
|
260
|
+
if (new RegExp(`(^|\\n)\\s*-\\s+name:\\s+${escapeRe(name)}(\\s|$)`).test(text)) {
|
|
261
|
+
throw new Error(`view "${name}" already exists in ${f}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function kebab(s) {
|
|
266
|
+
return s.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
267
|
+
}
|
|
268
|
+
function escapeRe(s) {
|
|
269
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/tools/curate/remove.ts
|
|
273
|
+
import { readFile as readFile5, writeFile as writeFile3, unlink, readdir as readdir3 } from "fs/promises";
|
|
274
|
+
import { resolve as resolve2 } from "path";
|
|
275
|
+
import {
|
|
276
|
+
parse as parse4,
|
|
277
|
+
format as format3,
|
|
278
|
+
canonicalize as canonicalize3
|
|
279
|
+
} from "@sightmap/sightmap";
|
|
280
|
+
async function handleDeleteView(input) {
|
|
281
|
+
const entries = await readdir3(input.sightmapDir);
|
|
282
|
+
for (const entry of entries) {
|
|
283
|
+
if (!entry.endsWith(".yaml")) continue;
|
|
284
|
+
const path = resolve2(input.sightmapDir, entry);
|
|
285
|
+
const text = await readFile5(path, "utf8");
|
|
286
|
+
const parsed = parse4(text, { sourceFile: path });
|
|
287
|
+
const views = parsed.views ?? [];
|
|
288
|
+
const idx = views.findIndex((v) => v.name === input.name);
|
|
289
|
+
if (idx < 0) continue;
|
|
290
|
+
const remaining = views.filter((_, i) => i !== idx);
|
|
291
|
+
if (remaining.length === 0) {
|
|
292
|
+
await unlink(path);
|
|
293
|
+
return { ok: true, file: path, fileDeleted: true };
|
|
294
|
+
}
|
|
295
|
+
const nextDoc = stripFragmentBrand2(parsed);
|
|
296
|
+
nextDoc.views = remaining;
|
|
297
|
+
const out = format3(nextDoc);
|
|
298
|
+
const c = canonicalize3(out, { file: path });
|
|
299
|
+
const finalText = c.kind === "canonical" ? c.text : out;
|
|
300
|
+
await writeFile3(path, finalText, "utf8");
|
|
301
|
+
return { ok: true, file: path, fileDeleted: false };
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`view "${input.name}" not found in ${input.sightmapDir}`);
|
|
304
|
+
}
|
|
305
|
+
function stripFragmentBrand2(input) {
|
|
306
|
+
const out = {};
|
|
307
|
+
for (const k of Object.keys(input)) {
|
|
308
|
+
if (k === "__brand" || k === "__sourceFile") continue;
|
|
309
|
+
out[k] = input[k];
|
|
310
|
+
}
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
313
|
+
|
|
213
314
|
// src/tools/curate/init.ts
|
|
214
|
-
import { mkdir, writeFile as
|
|
215
|
-
import { join as
|
|
315
|
+
import { mkdir, writeFile as writeFile4, access } from "fs/promises";
|
|
316
|
+
import { join as join3 } from "path";
|
|
216
317
|
|
|
217
318
|
// src/curate/scaffolder.ts
|
|
218
|
-
import { format as
|
|
319
|
+
import { format as format4, canonicalize as canonicalize4 } from "@sightmap/sightmap";
|
|
219
320
|
function makeStarterSightmap() {
|
|
220
|
-
const text =
|
|
221
|
-
const c =
|
|
321
|
+
const text = format4({ version: 1 });
|
|
322
|
+
const c = canonicalize4(text, { file: "app.yaml" });
|
|
222
323
|
return c.kind === "canonical" ? c.text : text;
|
|
223
324
|
}
|
|
224
325
|
|
|
225
326
|
// src/tools/curate/init.ts
|
|
226
327
|
async function handleInitProject(input) {
|
|
227
328
|
const root = input.dir ?? process.cwd();
|
|
228
|
-
const sightmapDir =
|
|
229
|
-
const appFile =
|
|
329
|
+
const sightmapDir = join3(root, ".sightmap");
|
|
330
|
+
const appFile = join3(sightmapDir, "app.yaml");
|
|
230
331
|
if (input.force !== true) {
|
|
231
332
|
let exists = false;
|
|
232
333
|
try {
|
|
@@ -241,10 +342,127 @@ async function handleInitProject(input) {
|
|
|
241
342
|
}
|
|
242
343
|
}
|
|
243
344
|
await mkdir(sightmapDir, { recursive: true });
|
|
244
|
-
await
|
|
345
|
+
await writeFile4(appFile, makeStarterSightmap(), "utf8");
|
|
245
346
|
return { ok: true, files: [appFile] };
|
|
246
347
|
}
|
|
247
348
|
|
|
349
|
+
// src/tools/runtime/snapshot.ts
|
|
350
|
+
async function handleRuntimeSnapshot(input) {
|
|
351
|
+
if (input.source.kind === "endpoint") {
|
|
352
|
+
const res = await fetch(input.source.url);
|
|
353
|
+
if (res.status === 404) {
|
|
354
|
+
let detail = "";
|
|
355
|
+
try {
|
|
356
|
+
const body = await res.json();
|
|
357
|
+
detail = body.error ?? "";
|
|
358
|
+
} catch {
|
|
359
|
+
}
|
|
360
|
+
throw new Error(
|
|
361
|
+
`no snapshot cached yet at ${input.source.url}${detail ? `: ${detail}` : ""}`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
if (!res.ok) {
|
|
365
|
+
throw new Error(`snapshot fetch failed: HTTP ${res.status}`);
|
|
366
|
+
}
|
|
367
|
+
const snapshot = await res.json();
|
|
368
|
+
return { ok: true, snapshot, source: input.source };
|
|
369
|
+
}
|
|
370
|
+
throw new Error(
|
|
371
|
+
"browser-driven snapshot capture is not implemented in 1.0-rc; use { kind: 'endpoint' } with the Vite plugin endpoint instead"
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/tools/propose/store.ts
|
|
376
|
+
var ProposalStore = class {
|
|
377
|
+
views = [];
|
|
378
|
+
components = [];
|
|
379
|
+
nextId = 1;
|
|
380
|
+
mintId(prefix) {
|
|
381
|
+
return `${prefix}_${this.nextId++}`;
|
|
382
|
+
}
|
|
383
|
+
appendView(p) {
|
|
384
|
+
const v = { id: this.mintId("v"), ...p };
|
|
385
|
+
this.views.push(v);
|
|
386
|
+
return v;
|
|
387
|
+
}
|
|
388
|
+
appendComponent(p) {
|
|
389
|
+
const c = { id: this.mintId("c"), ...p };
|
|
390
|
+
this.components.push(c);
|
|
391
|
+
return c;
|
|
392
|
+
}
|
|
393
|
+
review() {
|
|
394
|
+
return { views: [...this.views], components: [...this.components] };
|
|
395
|
+
}
|
|
396
|
+
commit(input = {}) {
|
|
397
|
+
if (!input.ids) {
|
|
398
|
+
const out = this.review();
|
|
399
|
+
this.views = [];
|
|
400
|
+
this.components = [];
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
const selected = new Set(input.ids);
|
|
404
|
+
const consumedViews = this.views.filter((v) => selected.has(v.id));
|
|
405
|
+
const consumedComponents = this.components.filter((c) => selected.has(c.id));
|
|
406
|
+
this.views = this.views.filter((v) => !selected.has(v.id));
|
|
407
|
+
this.components = this.components.filter((c) => !selected.has(c.id));
|
|
408
|
+
return { views: consumedViews, components: consumedComponents };
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
var proposalStore = new ProposalStore();
|
|
412
|
+
|
|
413
|
+
// src/tools/propose/view.ts
|
|
414
|
+
async function handleProposeView(input) {
|
|
415
|
+
const v = proposalStore.appendView(input);
|
|
416
|
+
return { ok: true, id: v.id };
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// src/tools/propose/component.ts
|
|
420
|
+
async function handleProposeComponent(input) {
|
|
421
|
+
const c = proposalStore.appendComponent(input);
|
|
422
|
+
return { ok: true, id: c.id };
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/tools/propose/review.ts
|
|
426
|
+
async function handleReviewProposals() {
|
|
427
|
+
return proposalStore.review();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/tools/propose/commit.ts
|
|
431
|
+
async function handleCommitProposals(input) {
|
|
432
|
+
if (input.dry_run === true) {
|
|
433
|
+
const peek = proposalStore.review();
|
|
434
|
+
const selectedIds = input.ids ? new Set(input.ids) : null;
|
|
435
|
+
const filtered = {
|
|
436
|
+
views: selectedIds ? peek.views.filter((v) => selectedIds.has(v.id)) : peek.views,
|
|
437
|
+
components: selectedIds ? peek.components.filter((c) => selectedIds.has(c.id)) : peek.components
|
|
438
|
+
};
|
|
439
|
+
return { ok: true, committed: filtered, writes: [] };
|
|
440
|
+
}
|
|
441
|
+
const consumed = proposalStore.commit(
|
|
442
|
+
input.ids ? { ids: input.ids } : {}
|
|
443
|
+
);
|
|
444
|
+
const writes = [];
|
|
445
|
+
for (const v of consumed.views) {
|
|
446
|
+
const r = await handleAddView({
|
|
447
|
+
sightmapDir: input.sightmapDir,
|
|
448
|
+
view: {
|
|
449
|
+
name: v.name ?? deriveName(v.route),
|
|
450
|
+
route: v.route,
|
|
451
|
+
components: [],
|
|
452
|
+
...v.intent !== void 0 ? { intent: v.intent } : {},
|
|
453
|
+
...v.memory_notes && v.memory_notes.length > 0 ? { memory: v.memory_notes } : {}
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
writes.push({ kind: "view", file: r.file });
|
|
457
|
+
}
|
|
458
|
+
return { ok: true, committed: consumed, writes };
|
|
459
|
+
}
|
|
460
|
+
function deriveName(route) {
|
|
461
|
+
const parts = route.replace(/^\/+|\/+$/g, "").split("/").filter((p) => p.length > 0);
|
|
462
|
+
const last = parts[parts.length - 1] ?? "Index";
|
|
463
|
+
return last.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\s+/g, "");
|
|
464
|
+
}
|
|
465
|
+
|
|
248
466
|
// src/prompts/sepTrack.ts
|
|
249
467
|
var VALID_PHASES = ["draft", "spec", "fixture", "verify"];
|
|
250
468
|
function buildDraftPhase(args) {
|
|
@@ -502,7 +720,7 @@ var SIGHTMAP_INIT_PROJECT = {
|
|
|
502
720
|
};
|
|
503
721
|
var SIGHTMAP_UPDATE_VIEW = {
|
|
504
722
|
name: "sightmap_update_view",
|
|
505
|
-
description: "Apply a
|
|
723
|
+
description: "Apply a patch to a view's fields. Accepts both semantic edits (description, intent, memory_append/memory_replace) and structural edits (name, route, components). Memory edits use either `memory_append` (default) or `memory_replace` \u2014 pass exactly one. Components is a full array replacement; use sightmap_add_view/sightmap_delete_view for whole-view lifecycle.",
|
|
506
724
|
inputSchema: {
|
|
507
725
|
type: "object",
|
|
508
726
|
properties: {
|
|
@@ -513,7 +731,22 @@ var SIGHTMAP_UPDATE_VIEW = {
|
|
|
513
731
|
description: { type: "string" },
|
|
514
732
|
intent: { type: "string" },
|
|
515
733
|
memory_append: { type: "array", items: { type: "string" } },
|
|
516
|
-
memory_replace: { type: "array", items: { type: "string" } }
|
|
734
|
+
memory_replace: { type: "array", items: { type: "string" } },
|
|
735
|
+
name: { type: "string" },
|
|
736
|
+
route: { type: "string" },
|
|
737
|
+
components: {
|
|
738
|
+
type: "array",
|
|
739
|
+
items: {
|
|
740
|
+
type: "object",
|
|
741
|
+
properties: {
|
|
742
|
+
name: { type: "string" },
|
|
743
|
+
selector: { type: "string" },
|
|
744
|
+
memory: { type: "array", items: { type: "string" } }
|
|
745
|
+
},
|
|
746
|
+
required: ["name", "selector"],
|
|
747
|
+
additionalProperties: true
|
|
748
|
+
}
|
|
749
|
+
}
|
|
517
750
|
},
|
|
518
751
|
additionalProperties: false
|
|
519
752
|
}
|
|
@@ -522,6 +755,131 @@ var SIGHTMAP_UPDATE_VIEW = {
|
|
|
522
755
|
additionalProperties: false
|
|
523
756
|
}
|
|
524
757
|
};
|
|
758
|
+
var SIGHTMAP_ADD_VIEW = {
|
|
759
|
+
name: "sightmap_add_view",
|
|
760
|
+
description: "Create a new view in a new .yaml file. Filename defaults to kebab(view.name) + '.yaml' unless overridden via `file`. Rejects names that collide with an existing view.",
|
|
761
|
+
inputSchema: {
|
|
762
|
+
type: "object",
|
|
763
|
+
properties: {
|
|
764
|
+
view: {
|
|
765
|
+
type: "object",
|
|
766
|
+
properties: {
|
|
767
|
+
name: { type: "string" },
|
|
768
|
+
route: { type: "string" },
|
|
769
|
+
description: { type: "string" },
|
|
770
|
+
memory: { type: "array", items: { type: "string" } },
|
|
771
|
+
components: {
|
|
772
|
+
type: "array",
|
|
773
|
+
items: {
|
|
774
|
+
type: "object",
|
|
775
|
+
properties: {
|
|
776
|
+
name: { type: "string" },
|
|
777
|
+
selector: { type: "string" },
|
|
778
|
+
memory: { type: "array", items: { type: "string" } }
|
|
779
|
+
},
|
|
780
|
+
required: ["name", "selector"],
|
|
781
|
+
additionalProperties: true
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
},
|
|
785
|
+
required: ["name", "route"],
|
|
786
|
+
additionalProperties: true
|
|
787
|
+
},
|
|
788
|
+
file: {
|
|
789
|
+
type: "string",
|
|
790
|
+
description: "Optional filename hint (relative to the curate root). Defaults to kebab(view.name) + '.yaml'."
|
|
791
|
+
}
|
|
792
|
+
},
|
|
793
|
+
required: ["view"],
|
|
794
|
+
additionalProperties: false
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
var SIGHTMAP_RUNTIME_SNAPSHOT = {
|
|
798
|
+
name: "sightmap_runtime_snapshot",
|
|
799
|
+
description: "Fetch the live SightmapSnapshot from a running Vite dev server's /__sightmap__/snapshot.json endpoint. Pass { source: { kind: 'endpoint', url: 'http://localhost:5173/__sightmap__/snapshot.json' } }. The browser-driven (kind: 'browser') mode is reserved for future Playwright bridge support.",
|
|
800
|
+
inputSchema: {
|
|
801
|
+
type: "object",
|
|
802
|
+
properties: {
|
|
803
|
+
source: {
|
|
804
|
+
type: "object",
|
|
805
|
+
properties: {
|
|
806
|
+
kind: { type: "string", enum: ["endpoint", "browser"] },
|
|
807
|
+
url: { type: "string" },
|
|
808
|
+
routes: { type: "array", items: { type: "string" } }
|
|
809
|
+
},
|
|
810
|
+
required: ["kind", "url"],
|
|
811
|
+
additionalProperties: false
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
required: ["source"],
|
|
815
|
+
additionalProperties: false
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
var SIGHTMAP_PROPOSE_VIEW = {
|
|
819
|
+
name: "sightmap_propose_view",
|
|
820
|
+
description: "Stage a proposed view from runtime observation. Does NOT write disk. Use sightmap_commit_proposals to persist.",
|
|
821
|
+
inputSchema: {
|
|
822
|
+
type: "object",
|
|
823
|
+
properties: {
|
|
824
|
+
route: { type: "string", description: "URL path for the observed view (e.g., '/dashboard')." },
|
|
825
|
+
name: { type: "string", description: "Optional display name. If omitted, derived from route at commit time." },
|
|
826
|
+
intent: { type: "string", description: "Optional one-liner describing the view's purpose." },
|
|
827
|
+
observed: { type: "string", description: "Free-form note about what was observed on this view." },
|
|
828
|
+
observed_components: { type: "array", items: { type: "string" } },
|
|
829
|
+
memory_notes: { type: "array", items: { type: "string" } }
|
|
830
|
+
},
|
|
831
|
+
required: ["route"],
|
|
832
|
+
additionalProperties: false
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
var SIGHTMAP_PROPOSE_COMPONENT = {
|
|
836
|
+
name: "sightmap_propose_component",
|
|
837
|
+
description: "Stage a proposed component observation. Does NOT write disk.",
|
|
838
|
+
inputSchema: {
|
|
839
|
+
type: "object",
|
|
840
|
+
properties: {
|
|
841
|
+
name: { type: "string", description: "Component name (e.g., 'KpiCard')." },
|
|
842
|
+
selector_candidate: { type: "string", description: "Best-guess CSS selector for the component." },
|
|
843
|
+
observed_routes: { type: "array", items: { type: "string" } },
|
|
844
|
+
notes: { type: "array", items: { type: "string" } }
|
|
845
|
+
},
|
|
846
|
+
required: ["name"],
|
|
847
|
+
additionalProperties: false
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
var SIGHTMAP_REVIEW_PROPOSALS = {
|
|
851
|
+
name: "sightmap_review_proposals",
|
|
852
|
+
description: "Return the current staged proposals (views + components).",
|
|
853
|
+
inputSchema: {
|
|
854
|
+
type: "object",
|
|
855
|
+
properties: {},
|
|
856
|
+
additionalProperties: false
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
var SIGHTMAP_COMMIT_PROPOSALS = {
|
|
860
|
+
name: "sightmap_commit_proposals",
|
|
861
|
+
description: "Promote staged proposals to disk via add_view. Pass dry_run:true to preview without consuming the queue. Pass ids:[...] to commit a selection only.",
|
|
862
|
+
inputSchema: {
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: {
|
|
865
|
+
ids: { type: "array", items: { type: "string" }, description: "Optional subset of proposal ids to commit. Omit to commit everything." },
|
|
866
|
+
dry_run: { type: "boolean", description: "If true, preview without consuming the queue and without writing." }
|
|
867
|
+
},
|
|
868
|
+
additionalProperties: false
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
var SIGHTMAP_DELETE_VIEW = {
|
|
872
|
+
name: "sightmap_delete_view",
|
|
873
|
+
description: "Delete a view by name. If the containing .yaml file has only this view, the file is removed; otherwise the view is spliced out and the file rewritten.",
|
|
874
|
+
inputSchema: {
|
|
875
|
+
type: "object",
|
|
876
|
+
properties: {
|
|
877
|
+
name: { type: "string" }
|
|
878
|
+
},
|
|
879
|
+
required: ["name"],
|
|
880
|
+
additionalProperties: false
|
|
881
|
+
}
|
|
882
|
+
};
|
|
525
883
|
var SIGHTMAP_CHECK = {
|
|
526
884
|
name: "sightmap_check",
|
|
527
885
|
description: "Validate the loaded sightmap. level='schema' returns only schema-level diagnostics (parse errors, schema failures, merge collisions). level='quality' (default) also runs lint rules: duplicate routes, route shadowing, selector syntax, unknown source attributions. Returns an array of diagnostics; an empty array means clean.",
|
|
@@ -628,8 +986,15 @@ var SightmapMcpServer = class {
|
|
|
628
986
|
SIGHTMAP_LIST_VIEWS,
|
|
629
987
|
SIGHTMAP_GET_VIEW,
|
|
630
988
|
SIGHTMAP_CHECK,
|
|
989
|
+
SIGHTMAP_ADD_VIEW,
|
|
631
990
|
SIGHTMAP_UPDATE_VIEW,
|
|
632
|
-
|
|
991
|
+
SIGHTMAP_DELETE_VIEW,
|
|
992
|
+
SIGHTMAP_INIT_PROJECT,
|
|
993
|
+
SIGHTMAP_RUNTIME_SNAPSHOT,
|
|
994
|
+
SIGHTMAP_PROPOSE_VIEW,
|
|
995
|
+
SIGHTMAP_PROPOSE_COMPONENT,
|
|
996
|
+
SIGHTMAP_REVIEW_PROPOSALS,
|
|
997
|
+
SIGHTMAP_COMMIT_PROPOSALS
|
|
633
998
|
];
|
|
634
999
|
}
|
|
635
1000
|
/** Full async list including upstream-proxied tools, if configured. */
|
|
@@ -639,8 +1004,15 @@ var SightmapMcpServer = class {
|
|
|
639
1004
|
SIGHTMAP_LIST_VIEWS,
|
|
640
1005
|
SIGHTMAP_GET_VIEW,
|
|
641
1006
|
SIGHTMAP_CHECK,
|
|
1007
|
+
SIGHTMAP_ADD_VIEW,
|
|
642
1008
|
SIGHTMAP_UPDATE_VIEW,
|
|
643
|
-
|
|
1009
|
+
SIGHTMAP_DELETE_VIEW,
|
|
1010
|
+
SIGHTMAP_INIT_PROJECT,
|
|
1011
|
+
SIGHTMAP_RUNTIME_SNAPSHOT,
|
|
1012
|
+
SIGHTMAP_PROPOSE_VIEW,
|
|
1013
|
+
SIGHTMAP_PROPOSE_COMPONENT,
|
|
1014
|
+
SIGHTMAP_REVIEW_PROPOSALS,
|
|
1015
|
+
SIGHTMAP_COMMIT_PROPOSALS
|
|
644
1016
|
];
|
|
645
1017
|
if (this.upstream !== void 0) {
|
|
646
1018
|
own.push(SIGHTMAP_SNAPSHOT, SIGHTMAP_ACT, SIGHTMAP_NETWORK_REQUESTS);
|
|
@@ -678,10 +1050,24 @@ var SightmapMcpServer = class {
|
|
|
678
1050
|
return this.callSightmapGetView(args);
|
|
679
1051
|
case "sightmap_check":
|
|
680
1052
|
return this.callSightmapCheck(args);
|
|
1053
|
+
case "sightmap_add_view":
|
|
1054
|
+
return this.callSightmapAddView(args);
|
|
681
1055
|
case "sightmap_update_view":
|
|
682
1056
|
return this.callSightmapUpdateView(args);
|
|
1057
|
+
case "sightmap_delete_view":
|
|
1058
|
+
return this.callSightmapDeleteView(args);
|
|
683
1059
|
case "sightmap_init_project":
|
|
684
1060
|
return this.callSightmapInitProject(args);
|
|
1061
|
+
case "sightmap_runtime_snapshot":
|
|
1062
|
+
return this.callSightmapRuntimeSnapshot(args);
|
|
1063
|
+
case "sightmap_propose_view":
|
|
1064
|
+
return this.callSightmapProposeView(args);
|
|
1065
|
+
case "sightmap_propose_component":
|
|
1066
|
+
return this.callSightmapProposeComponent(args);
|
|
1067
|
+
case "sightmap_review_proposals":
|
|
1068
|
+
return this.callSightmapReviewProposals();
|
|
1069
|
+
case "sightmap_commit_proposals":
|
|
1070
|
+
return this.callSightmapCommitProposals(args);
|
|
685
1071
|
case "sightmap_snapshot":
|
|
686
1072
|
return this.callSightmapSnapshot();
|
|
687
1073
|
case "sightmap_act":
|
|
@@ -924,6 +1310,168 @@ var SightmapMcpServer = class {
|
|
|
924
1310
|
return errorResult(err instanceof Error ? err.message : String(err));
|
|
925
1311
|
}
|
|
926
1312
|
}
|
|
1313
|
+
async callSightmapRuntimeSnapshot(args) {
|
|
1314
|
+
const source = args["source"];
|
|
1315
|
+
if (source === null || typeof source !== "object" || Array.isArray(source)) {
|
|
1316
|
+
return errorResult(
|
|
1317
|
+
"sightmap_runtime_snapshot: required argument `source` (object) is missing."
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
const s = source;
|
|
1321
|
+
if (s["kind"] !== "endpoint" && s["kind"] !== "browser") {
|
|
1322
|
+
return errorResult(
|
|
1323
|
+
"sightmap_runtime_snapshot: `source.kind` must be 'endpoint' or 'browser'."
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
if (typeof s["url"] !== "string" || s["url"].length === 0) {
|
|
1327
|
+
return errorResult(
|
|
1328
|
+
"sightmap_runtime_snapshot: `source.url` (string) is required."
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
const input = s["kind"] === "endpoint" ? { source: { kind: "endpoint", url: s["url"] } } : {
|
|
1332
|
+
source: {
|
|
1333
|
+
kind: "browser",
|
|
1334
|
+
url: s["url"],
|
|
1335
|
+
...Array.isArray(s["routes"]) ? { routes: s["routes"].filter((r) => typeof r === "string") } : {}
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
try {
|
|
1339
|
+
const result = await handleRuntimeSnapshot(input);
|
|
1340
|
+
return {
|
|
1341
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1342
|
+
};
|
|
1343
|
+
} catch (err) {
|
|
1344
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
async callSightmapProposeView(args) {
|
|
1348
|
+
if (typeof args["route"] !== "string" || args["route"].length === 0) {
|
|
1349
|
+
return errorResult(
|
|
1350
|
+
"sightmap_propose_view: required argument `route` (string) is missing or empty."
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
const input = { route: args["route"] };
|
|
1354
|
+
if (typeof args["name"] === "string") input.name = args["name"];
|
|
1355
|
+
if (typeof args["intent"] === "string") input.intent = args["intent"];
|
|
1356
|
+
if (typeof args["observed"] === "string") input.observed = args["observed"];
|
|
1357
|
+
if (Array.isArray(args["observed_components"])) {
|
|
1358
|
+
input.observed_components = args["observed_components"].filter(
|
|
1359
|
+
(s) => typeof s === "string"
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
if (Array.isArray(args["memory_notes"])) {
|
|
1363
|
+
input.memory_notes = args["memory_notes"].filter(
|
|
1364
|
+
(s) => typeof s === "string"
|
|
1365
|
+
);
|
|
1366
|
+
}
|
|
1367
|
+
try {
|
|
1368
|
+
const result = await handleProposeView(input);
|
|
1369
|
+
return {
|
|
1370
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1371
|
+
};
|
|
1372
|
+
} catch (err) {
|
|
1373
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
async callSightmapProposeComponent(args) {
|
|
1377
|
+
if (typeof args["name"] !== "string" || args["name"].length === 0) {
|
|
1378
|
+
return errorResult(
|
|
1379
|
+
"sightmap_propose_component: required argument `name` (string) is missing or empty."
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
const input = { name: args["name"] };
|
|
1383
|
+
if (typeof args["selector_candidate"] === "string") {
|
|
1384
|
+
input.selector_candidate = args["selector_candidate"];
|
|
1385
|
+
}
|
|
1386
|
+
if (Array.isArray(args["observed_routes"])) {
|
|
1387
|
+
input.observed_routes = args["observed_routes"].filter(
|
|
1388
|
+
(s) => typeof s === "string"
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
if (Array.isArray(args["notes"])) {
|
|
1392
|
+
input.notes = args["notes"].filter(
|
|
1393
|
+
(s) => typeof s === "string"
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
try {
|
|
1397
|
+
const result = await handleProposeComponent(input);
|
|
1398
|
+
return {
|
|
1399
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1400
|
+
};
|
|
1401
|
+
} catch (err) {
|
|
1402
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
async callSightmapReviewProposals() {
|
|
1406
|
+
try {
|
|
1407
|
+
const result = await handleReviewProposals();
|
|
1408
|
+
return {
|
|
1409
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1410
|
+
};
|
|
1411
|
+
} catch (err) {
|
|
1412
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
async callSightmapCommitProposals(args) {
|
|
1416
|
+
if (this.curateRoot === void 0) {
|
|
1417
|
+
return errorResult(
|
|
1418
|
+
"sightmap_commit_proposals: no writable sightmap dir configured (pass --curate-root or --sightmap-dir)."
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
const input = { sightmapDir: this.curateRoot };
|
|
1422
|
+
if (Array.isArray(args["ids"])) {
|
|
1423
|
+
input.ids = args["ids"].filter(
|
|
1424
|
+
(s) => typeof s === "string"
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
if (args["dry_run"] === true) input.dry_run = true;
|
|
1428
|
+
try {
|
|
1429
|
+
const result = await handleCommitProposals(input);
|
|
1430
|
+
return {
|
|
1431
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1432
|
+
};
|
|
1433
|
+
} catch (err) {
|
|
1434
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
async callSightmapAddView(args) {
|
|
1438
|
+
if (this.curateRoot === void 0) {
|
|
1439
|
+
return errorResult(
|
|
1440
|
+
"sightmap_add_view: no writable sightmap dir configured (pass --curate-root or --sightmap-dir)."
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
if (args["view"] === null || typeof args["view"] !== "object" || Array.isArray(args["view"])) {
|
|
1444
|
+
return errorResult(
|
|
1445
|
+
"sightmap_add_view: required argument `view` (object) is missing."
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
const view = args["view"];
|
|
1449
|
+
if (typeof view["name"] !== "string" || view["name"].length === 0) {
|
|
1450
|
+
return errorResult(
|
|
1451
|
+
"sightmap_add_view: `view.name` (string) is required."
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
if (typeof view["route"] !== "string" || view["route"].length === 0) {
|
|
1455
|
+
return errorResult(
|
|
1456
|
+
"sightmap_add_view: `view.route` (string) is required."
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1459
|
+
const input = {
|
|
1460
|
+
sightmapDir: this.curateRoot,
|
|
1461
|
+
view
|
|
1462
|
+
};
|
|
1463
|
+
if (typeof args["file"] === "string" && args["file"].length > 0) {
|
|
1464
|
+
input.file = args["file"];
|
|
1465
|
+
}
|
|
1466
|
+
try {
|
|
1467
|
+
const result = await handleAddView(input);
|
|
1468
|
+
return {
|
|
1469
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1470
|
+
};
|
|
1471
|
+
} catch (err) {
|
|
1472
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
927
1475
|
async callSightmapUpdateView(args) {
|
|
928
1476
|
if (this.curateRoot === void 0) {
|
|
929
1477
|
return errorResult(
|
|
@@ -953,6 +1501,29 @@ var SightmapMcpServer = class {
|
|
|
953
1501
|
return errorResult(err instanceof Error ? err.message : String(err));
|
|
954
1502
|
}
|
|
955
1503
|
}
|
|
1504
|
+
async callSightmapDeleteView(args) {
|
|
1505
|
+
if (this.curateRoot === void 0) {
|
|
1506
|
+
return errorResult(
|
|
1507
|
+
"sightmap_delete_view: no writable sightmap dir configured (pass --curate-root or --sightmap-dir)."
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
if (typeof args["name"] !== "string" || args["name"].length === 0) {
|
|
1511
|
+
return errorResult(
|
|
1512
|
+
"sightmap_delete_view: required argument `name` (string) is missing or empty."
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
try {
|
|
1516
|
+
const result = await handleDeleteView({
|
|
1517
|
+
sightmapDir: this.curateRoot,
|
|
1518
|
+
name: args["name"]
|
|
1519
|
+
});
|
|
1520
|
+
return {
|
|
1521
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1522
|
+
};
|
|
1523
|
+
} catch (err) {
|
|
1524
|
+
return errorResult(err instanceof Error ? err.message : String(err));
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
956
1527
|
async callSightmapCheck(args) {
|
|
957
1528
|
const input = {};
|
|
958
1529
|
if (args["level"] === "schema" || args["level"] === "quality") {
|