vskill 1.2.4 → 1.2.7

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 (114) hide show
  1. package/README.md +51 -3
  2. package/agents.json +6 -1
  3. package/dist/agents/agents-registry.d.ts +43 -16
  4. package/dist/agents/agents-registry.js +119 -33
  5. package/dist/agents/agents-registry.js.map +1 -1
  6. package/dist/agents/global-dirs.d.ts +19 -0
  7. package/dist/agents/global-dirs.js +53 -0
  8. package/dist/agents/global-dirs.js.map +1 -0
  9. package/dist/audit/fix-suggestions.js +6 -0
  10. package/dist/audit/fix-suggestions.js.map +1 -1
  11. package/dist/commands/add-github-bundle.d.ts +29 -0
  12. package/dist/commands/add-github-bundle.js +135 -0
  13. package/dist/commands/add-github-bundle.js.map +1 -0
  14. package/dist/commands/add-lockfile.d.ts +2 -0
  15. package/dist/commands/add-lockfile.js +1 -1
  16. package/dist/commands/add-lockfile.js.map +1 -1
  17. package/dist/commands/add.d.ts +5 -7
  18. package/dist/commands/add.js +207 -111
  19. package/dist/commands/add.js.map +1 -1
  20. package/dist/commands/audit-webmcp.d.ts +25 -0
  21. package/dist/commands/audit-webmcp.js +167 -0
  22. package/dist/commands/audit-webmcp.js.map +1 -0
  23. package/dist/commands/doctor.d.ts +69 -0
  24. package/dist/commands/doctor.js +760 -0
  25. package/dist/commands/doctor.js.map +1 -0
  26. package/dist/commands/remove.js +43 -8
  27. package/dist/commands/remove.js.map +1 -1
  28. package/dist/commands/scan.js +1 -1
  29. package/dist/commands/scan.js.map +1 -1
  30. package/dist/commands/update.js +12 -4
  31. package/dist/commands/update.js.map +1 -1
  32. package/dist/discovery/github-skill-bundle.d.ts +74 -0
  33. package/dist/discovery/github-skill-bundle.js +323 -0
  34. package/dist/discovery/github-skill-bundle.js.map +1 -0
  35. package/dist/eval/skill-scanner.js +7 -1
  36. package/dist/eval/skill-scanner.js.map +1 -1
  37. package/dist/eval-server/install-skill-routes.js +10 -3
  38. package/dist/eval-server/install-skill-routes.js.map +1 -1
  39. package/dist/eval-server/remove-skill-routes.js +262 -29
  40. package/dist/eval-server/remove-skill-routes.js.map +1 -1
  41. package/dist/eval-server/studio-privacy.js +2 -3
  42. package/dist/eval-server/studio-privacy.js.map +1 -1
  43. package/dist/eval-server/utils/scan-install-locations.js +22 -3
  44. package/dist/eval-server/utils/scan-install-locations.js.map +1 -1
  45. package/dist/eval-ui/assets/{CreateSkillPage-BUrgworx.js → CreateSkillPage-CXDd6gDN.js} +1 -1
  46. package/dist/eval-ui/assets/{FindSkillsPalette-BstJ22TI.js → FindSkillsPalette-DQ6uGhFP.js} +2 -2
  47. package/dist/eval-ui/assets/{SearchPaletteCore-Dagnc-E7.js → SearchPaletteCore-DpHCf0mf.js} +1 -1
  48. package/dist/eval-ui/assets/{SkillDetailPanel-DnujVk6g.js → SkillDetailPanel-BjHFjGxg.js} +1 -1
  49. package/dist/eval-ui/assets/{UpdateDropdown-B7D2vXrm.js → UpdateDropdown-Cn4Vsq5d.js} +1 -1
  50. package/dist/eval-ui/assets/main-BmB7Zj9I.js +86 -0
  51. package/dist/eval-ui/index.html +1 -1
  52. package/dist/index.js +34 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/installer/bundle-files.d.ts +39 -2
  55. package/dist/installer/bundle-files.js +80 -10
  56. package/dist/installer/bundle-files.js.map +1 -1
  57. package/dist/installer/canonical.d.ts +39 -4
  58. package/dist/installer/canonical.js +178 -24
  59. package/dist/installer/canonical.js.map +1 -1
  60. package/dist/installer/multi-install.d.ts +11 -2
  61. package/dist/installer/multi-install.js +41 -9
  62. package/dist/installer/multi-install.js.map +1 -1
  63. package/dist/installer/transformers/index.d.ts +8 -0
  64. package/dist/installer/yaml-safe-mutate.js +48 -2
  65. package/dist/installer/yaml-safe-mutate.js.map +1 -1
  66. package/dist/lib/github-fetch.js +2 -0
  67. package/dist/lib/github-fetch.js.map +1 -1
  68. package/dist/lib/private-source.d.ts +8 -0
  69. package/dist/lib/private-source.js +16 -2
  70. package/dist/lib/private-source.js.map +1 -1
  71. package/dist/scanner/hidden-content.d.ts +47 -0
  72. package/dist/scanner/hidden-content.js +904 -0
  73. package/dist/scanner/hidden-content.js.map +1 -0
  74. package/dist/scanner/installer-hosts.d.ts +26 -0
  75. package/dist/scanner/installer-hosts.js +92 -0
  76. package/dist/scanner/installer-hosts.js.map +1 -0
  77. package/dist/scanner/judge-guard.d.ts +119 -0
  78. package/dist/scanner/judge-guard.js +481 -0
  79. package/dist/scanner/judge-guard.js.map +1 -0
  80. package/dist/scanner/patterns.d.ts +12 -0
  81. package/dist/scanner/patterns.js +353 -113
  82. package/dist/scanner/patterns.js.map +1 -1
  83. package/dist/scanner/repo-scanner.d.ts +4 -0
  84. package/dist/scanner/repo-scanner.js +4 -1
  85. package/dist/scanner/repo-scanner.js.map +1 -1
  86. package/dist/scanner/tier1.js +37 -7
  87. package/dist/scanner/tier1.js.map +1 -1
  88. package/dist/scanner/tier2-llm.d.ts +22 -4
  89. package/dist/scanner/tier2-llm.js +163 -23
  90. package/dist/scanner/tier2-llm.js.map +1 -1
  91. package/dist/scanner/types.d.ts +8 -0
  92. package/dist/webmcp/args.d.ts +34 -0
  93. package/dist/webmcp/args.js +87 -0
  94. package/dist/webmcp/args.js.map +1 -0
  95. package/dist/webmcp/attribution.d.ts +38 -0
  96. package/dist/webmcp/attribution.js +141 -0
  97. package/dist/webmcp/attribution.js.map +1 -0
  98. package/dist/webmcp/enumerate.d.ts +81 -0
  99. package/dist/webmcp/enumerate.js +436 -0
  100. package/dist/webmcp/enumerate.js.map +1 -0
  101. package/dist/webmcp/format.d.ts +9 -0
  102. package/dist/webmcp/format.js +105 -0
  103. package/dist/webmcp/format.js.map +1 -0
  104. package/dist/webmcp/merge.d.ts +49 -0
  105. package/dist/webmcp/merge.js +167 -0
  106. package/dist/webmcp/merge.js.map +1 -0
  107. package/dist/webmcp/score.d.ts +70 -0
  108. package/dist/webmcp/score.js +586 -0
  109. package/dist/webmcp/score.js.map +1 -0
  110. package/dist/webmcp/types.d.ts +92 -0
  111. package/dist/webmcp/types.js +8 -0
  112. package/dist/webmcp/types.js.map +1 -0
  113. package/package.json +1 -1
  114. package/dist/eval-ui/assets/main-DjA5gpjV.js +0 -86
@@ -0,0 +1,34 @@
1
+ import { type Severity } from "./types.js";
2
+ export interface AuditWebmcpRawOptions {
3
+ urlsFile?: string;
4
+ json?: boolean;
5
+ out?: string;
6
+ concurrency?: string | number;
7
+ timeout?: string | number;
8
+ failOn?: string;
9
+ executablePath?: string;
10
+ }
11
+ export interface AuditWebmcpOptions {
12
+ urls: string[];
13
+ json: boolean;
14
+ out?: string;
15
+ /** "jsonl" when the run covers more than one URL or --out ends in .jsonl. */
16
+ outFormat: "json" | "jsonl";
17
+ concurrency: number;
18
+ timeoutMs: number;
19
+ failOn?: Severity;
20
+ executablePath?: string;
21
+ }
22
+ export declare const DEFAULT_CONCURRENCY = 4;
23
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
24
+ export declare class ArgError extends Error {
25
+ }
26
+ /** One URL per line; blank lines and # comments (whole-line or trailing " #") are ignored. */
27
+ export declare function parseUrlList(text: string): string[];
28
+ /** Accept "example.com" as https://example.com/; reject anything that is not http(s). */
29
+ export declare function normalizeUrl(input: string): string;
30
+ /**
31
+ * Combine positional URLs and --urls-file contents (already read) into
32
+ * validated options. Throws ArgError with a user-facing message.
33
+ */
34
+ export declare function resolveOptions(positional: string[], raw: AuditWebmcpRawOptions, urlsFileText?: string): AuditWebmcpOptions;
@@ -0,0 +1,87 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill audit-webmcp -- argument parsing (pure, unit-tested).
3
+ // ---------------------------------------------------------------------------
4
+ import { SEVERITIES } from "./types.js";
5
+ export const DEFAULT_CONCURRENCY = 4;
6
+ export const DEFAULT_TIMEOUT_MS = 30_000;
7
+ export class ArgError extends Error {
8
+ }
9
+ /** One URL per line; blank lines and # comments (whole-line or trailing " #") are ignored. */
10
+ export function parseUrlList(text) {
11
+ const out = [];
12
+ for (const raw of text.split(/\r?\n/)) {
13
+ let line = raw.trim();
14
+ if (!line || line.startsWith("#"))
15
+ continue;
16
+ const hash = line.search(/\s#/);
17
+ if (hash !== -1)
18
+ line = line.slice(0, hash).trim();
19
+ if (line)
20
+ out.push(line);
21
+ }
22
+ return out;
23
+ }
24
+ /** Accept "example.com" as https://example.com/; reject anything that is not http(s). */
25
+ export function normalizeUrl(input) {
26
+ const s = input.trim();
27
+ const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(s) ? s : `https://${s}`;
28
+ let u;
29
+ try {
30
+ u = new URL(withScheme);
31
+ }
32
+ catch {
33
+ throw new ArgError(`Invalid URL: ${input}`);
34
+ }
35
+ if (u.protocol !== "http:" && u.protocol !== "https:") {
36
+ throw new ArgError(`Only http(s) URLs can be audited: ${input}`);
37
+ }
38
+ if (!u.hostname)
39
+ throw new ArgError(`Invalid URL: ${input}`);
40
+ return u.toString();
41
+ }
42
+ function positiveInt(name, v, fallback) {
43
+ if (v === undefined || v === "")
44
+ return fallback;
45
+ const n = typeof v === "number" ? v : Number(v);
46
+ if (!Number.isInteger(n) || n <= 0)
47
+ throw new ArgError(`Invalid ${name} value: ${v}. Must be a positive integer.`);
48
+ return n;
49
+ }
50
+ /**
51
+ * Combine positional URLs and --urls-file contents (already read) into
52
+ * validated options. Throws ArgError with a user-facing message.
53
+ */
54
+ export function resolveOptions(positional, raw, urlsFileText) {
55
+ const inputs = [...positional, ...(urlsFileText !== undefined ? parseUrlList(urlsFileText) : [])];
56
+ const urls = [];
57
+ for (const i of inputs) {
58
+ const u = normalizeUrl(i);
59
+ if (!urls.includes(u))
60
+ urls.push(u);
61
+ }
62
+ if (urls.length === 0) {
63
+ throw new ArgError("No URLs to audit. Pass URLs as arguments or use --urls-file <path>.");
64
+ }
65
+ let failOn;
66
+ if (raw.failOn !== undefined) {
67
+ const s = raw.failOn.toLowerCase();
68
+ if (!SEVERITIES.includes(s)) {
69
+ throw new ArgError(`Invalid --fail-on severity: ${raw.failOn}. Valid: ${SEVERITIES.join(", ")}`);
70
+ }
71
+ failOn = s;
72
+ }
73
+ const concurrency = positiveInt("--concurrency", raw.concurrency, DEFAULT_CONCURRENCY);
74
+ const timeoutMs = positiveInt("--timeout", raw.timeout, DEFAULT_TIMEOUT_MS);
75
+ const outFormat = urls.length > 1 || /\.jsonl$/i.test(raw.out ?? "") ? "jsonl" : "json";
76
+ return {
77
+ urls,
78
+ json: !!raw.json,
79
+ out: raw.out,
80
+ outFormat,
81
+ concurrency: Math.min(concurrency, urls.length),
82
+ timeoutMs,
83
+ failOn,
84
+ executablePath: raw.executablePath,
85
+ };
86
+ }
87
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/webmcp/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { RegistrarKind } from "./types.js";
2
+ /** Platform markers detected in the page (see enumerate.ts detectPlatforms). */
3
+ export type PlatformMarker = "shopify";
4
+ export interface PlatformHost {
5
+ platform: string;
6
+ marker: PlatformMarker;
7
+ host: string;
8
+ /** Only scripts under this path are the platform's own code. */
9
+ pathPrefix: string;
10
+ }
11
+ /**
12
+ * Hosting platforms whose own scripts register WebMCP tools on merchant
13
+ * pages. Add an entry only after seeing it in a scan, and keep the path
14
+ * prefix narrow: cdn.shopify.com/extensions/ holds third-party app code and
15
+ * cdn.shopify.com/s/files/ holds any merchant's uploads.
16
+ */
17
+ export declare const PLATFORM_HOSTS: PlatformHost[];
18
+ /** Public npm CDNs: the page author picks the package and version. */
19
+ export declare const LIBRARY_CDN_HOSTS: string[];
20
+ export interface Attribution {
21
+ kind: RegistrarKind;
22
+ /** Platform name for kind "platform". */
23
+ platform?: string;
24
+ /** Package (name@version, or gh/owner/repo@ref) for kind "library", when the URL names one. */
25
+ package?: string;
26
+ }
27
+ /** The package a public-CDN URL loads, as the URL spells it (e.g. "simple-webmcp@0.3.0"). */
28
+ export declare function libraryPackage(url: string): string | undefined;
29
+ /**
30
+ * True when a package spec has no exact version (no @version, or a tag such
31
+ * as @latest). A full commit SHA on a gh/ spec counts as pinned.
32
+ */
33
+ export declare function isUnpinned(pkg: string): boolean;
34
+ /**
35
+ * Classify the script that registered a tool. Returns null when the script
36
+ * URL is unknown or not http(s).
37
+ */
38
+ export declare function classifyRegistrar(registeredBy: string | undefined | null, pageUrl: string | undefined | null, platforms?: readonly string[]): Attribution | null;
@@ -0,0 +1,141 @@
1
+ // ---------------------------------------------------------------------------
2
+ // vskill audit-webmcp -- who registered a tool. Pure module: no browser.
3
+ //
4
+ // first-party the script is on the page's own site (registrable domain)
5
+ // platform the page runs on a hosting platform and the script is that
6
+ // platform's own code (PLATFORM_HOSTS: host + path prefix,
7
+ // and only when the page carries the platform's marker)
8
+ // library the script comes from a public npm CDN (unpkg, jsDelivr,
9
+ // esm.sh, cdnjs, jspm, Skypack): a library the page author
10
+ // chose to load
11
+ // third-party any other site. It may still be the site's own asset domain
12
+ // (assets.targetimg1.com on target.com); we cannot tell.
13
+ // ---------------------------------------------------------------------------
14
+ import { siteOf } from "./score.js";
15
+ /**
16
+ * Hosting platforms whose own scripts register WebMCP tools on merchant
17
+ * pages. Add an entry only after seeing it in a scan, and keep the path
18
+ * prefix narrow: cdn.shopify.com/extensions/ holds third-party app code and
19
+ * cdn.shopify.com/s/files/ holds any merchant's uploads.
20
+ */
21
+ export const PLATFORM_HOSTS = [
22
+ // Shopify storefront WebMCP (seen 2026-10: 92 stores serve it from their own
23
+ // domain under /cdn/shopifycloud/, cotopaxi.com from cdn.shopify.com).
24
+ { platform: "Shopify", marker: "shopify", host: "cdn.shopify.com", pathPrefix: "/shopifycloud/" },
25
+ ];
26
+ /** Public npm CDNs: the page author picks the package and version. */
27
+ export const LIBRARY_CDN_HOSTS = [
28
+ "unpkg.com",
29
+ "cdn.jsdelivr.net",
30
+ "fastly.jsdelivr.net",
31
+ "gcore.jsdelivr.net",
32
+ "esm.sh",
33
+ "esm.run",
34
+ "cdnjs.cloudflare.com",
35
+ "ga.jspm.io",
36
+ "jspm.dev",
37
+ "cdn.skypack.dev",
38
+ ];
39
+ /** name or name@version from path segments starting at a package name (handles @scope/name). */
40
+ function packageAt(segs, i) {
41
+ const first = segs[i];
42
+ if (!first)
43
+ return undefined;
44
+ if (first.startsWith("@")) {
45
+ const second = segs[i + 1];
46
+ return second ? `${first}/${second}` : undefined;
47
+ }
48
+ return first;
49
+ }
50
+ /** The package a public-CDN URL loads, as the URL spells it (e.g. "simple-webmcp@0.3.0"). */
51
+ export function libraryPackage(url) {
52
+ let u;
53
+ try {
54
+ u = new URL(url);
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ const host = u.hostname.toLowerCase();
60
+ const segs = u.pathname.split("/").filter(Boolean).map((s) => {
61
+ try {
62
+ return decodeURIComponent(s);
63
+ }
64
+ catch {
65
+ return s;
66
+ }
67
+ });
68
+ if (host.endsWith("jsdelivr.net")) {
69
+ if (segs[0] === "npm")
70
+ return packageAt(segs, 1);
71
+ if (segs[0] === "gh" && segs[1] && segs[2])
72
+ return `gh/${segs[1]}/${segs[2]}`;
73
+ return undefined;
74
+ }
75
+ if (host === "cdnjs.cloudflare.com") {
76
+ if (segs[0] === "ajax" && segs[1] === "libs" && segs[2])
77
+ return segs[3] ? `${segs[2]}@${segs[3]}` : segs[2];
78
+ return undefined;
79
+ }
80
+ if (host === "ga.jspm.io" || host === "jspm.dev") {
81
+ const s = segs.slice();
82
+ if (s[0]?.startsWith("npm:"))
83
+ s[0] = s[0].slice(4);
84
+ return packageAt(s, 0);
85
+ }
86
+ if (host === "esm.sh") {
87
+ let i = 0;
88
+ while (segs[i] && (/^v\d+$/.test(segs[i]) || segs[i] === "stable"))
89
+ i++;
90
+ if (segs[i] === "gh" && segs[i + 1] && segs[i + 2])
91
+ return `gh/${segs[i + 1]}/${segs[i + 2]}`;
92
+ return packageAt(segs, i);
93
+ }
94
+ if (host === "cdn.skypack.dev") {
95
+ // Pinned URLs look like /-/name@v1.2.3-<hash>/dist=es2019/...
96
+ if (segs[0] === "-") {
97
+ const p = packageAt(segs, 1);
98
+ return p?.replace(/@v(\d[^-]*)-[A-Za-z0-9]+$/, "@$1");
99
+ }
100
+ return packageAt(segs, 0);
101
+ }
102
+ return packageAt(segs, 0);
103
+ }
104
+ /**
105
+ * True when a package spec has no exact version (no @version, or a tag such
106
+ * as @latest). A full commit SHA on a gh/ spec counts as pinned.
107
+ */
108
+ export function isUnpinned(pkg) {
109
+ const at = pkg.lastIndexOf("@");
110
+ if (at <= 0)
111
+ return true;
112
+ const version = pkg.slice(at + 1);
113
+ if (pkg.startsWith("gh/") && /^[0-9a-f]{40}$/i.test(version))
114
+ return false;
115
+ return !/^\d+\.\d+\.\d+/.test(version);
116
+ }
117
+ /**
118
+ * Classify the script that registered a tool. Returns null when the script
119
+ * URL is unknown or not http(s).
120
+ */
121
+ export function classifyRegistrar(registeredBy, pageUrl, platforms = []) {
122
+ const regSite = siteOf(registeredBy);
123
+ if (!registeredBy || !regSite)
124
+ return null;
125
+ const pageSite = siteOf(pageUrl);
126
+ if (!pageSite || regSite === pageSite)
127
+ return { kind: "first-party" };
128
+ const u = new URL(registeredBy);
129
+ const host = u.hostname.toLowerCase();
130
+ for (const p of PLATFORM_HOSTS) {
131
+ if (host === p.host && u.pathname.startsWith(p.pathPrefix) && platforms.includes(p.marker)) {
132
+ return { kind: "platform", platform: p.platform };
133
+ }
134
+ }
135
+ if (LIBRARY_CDN_HOSTS.includes(host)) {
136
+ const pkg = libraryPackage(registeredBy);
137
+ return pkg ? { kind: "library", package: pkg } : { kind: "library" };
138
+ }
139
+ return { kind: "third-party" };
140
+ }
141
+ //# sourceMappingURL=attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribution.js","sourceRoot":"","sources":["../../src/webmcp/attribution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { EnumerationResult } from "./types.js";
2
+ /** Playwright always passes CDPScreenshotNewSurface; a second --enable-features would override it. */
3
+ export declare const CHROMIUM_ARGS: string[];
4
+ export declare const UA_SUFFIX = "vskill-audit-webmcp (+https://verified-skill.com)";
5
+ export declare const PROBE_NAME = "vskill-webmcp-probe";
6
+ interface PwResponse {
7
+ headers(): Record<string, string>;
8
+ }
9
+ interface PwCdpSession {
10
+ send(method: string, params?: Record<string, unknown>): Promise<unknown>;
11
+ on(event: string, handler: (params: any) => void): void;
12
+ detach(): Promise<void>;
13
+ }
14
+ interface PwPage {
15
+ goto(url: string, opts: {
16
+ waitUntil: string;
17
+ timeout: number;
18
+ }): Promise<PwResponse | null>;
19
+ url(): string;
20
+ evaluate<T>(fn: (...args: any[]) => T | Promise<T>, arg?: unknown): Promise<T>;
21
+ waitForTimeout(ms: number): Promise<void>;
22
+ on(event: string, handler: (arg: any) => void): void;
23
+ close(): Promise<void>;
24
+ }
25
+ interface PwContext {
26
+ newPage(): Promise<PwPage>;
27
+ newCDPSession(page: PwPage): Promise<PwCdpSession>;
28
+ addInitScript(script: {
29
+ content: string;
30
+ }): Promise<void>;
31
+ on(event: string, handler: (arg: any) => void): void;
32
+ close(): Promise<void>;
33
+ }
34
+ export interface PwBrowser {
35
+ newContext(opts?: Record<string, unknown>): Promise<PwContext>;
36
+ close(): Promise<void>;
37
+ version(): string;
38
+ isConnected(): boolean;
39
+ }
40
+ interface PwChromium {
41
+ launch(opts: Record<string, unknown>): Promise<PwBrowser>;
42
+ executablePath(): string;
43
+ }
44
+ /**
45
+ * Import playwright-core, then playwright: first from vskill's own install,
46
+ * then from the current project (so `npm i -D playwright-core` works with npx).
47
+ * Returns null when neither resolves.
48
+ */
49
+ export declare function loadChromium(cwd?: string): Promise<PwChromium | null>;
50
+ export declare const PLAYWRIGHT_INSTALL_HINT: string;
51
+ /** Newest Chromium (headless shell preferred) in the usual Playwright cache dirs. */
52
+ export declare function findCachedChromium(dirs?: string[]): string | null;
53
+ /**
54
+ * Resolve the executable: explicit flag, then VSKILL_CHROMIUM, then
55
+ * Playwright's own pinned build, then the newest cached build.
56
+ * Returns undefined when Playwright's default should be used.
57
+ */
58
+ export declare function resolveExecutablePath(chromium: PwChromium, explicit?: string): string | undefined;
59
+ export declare function launchBrowser(opts?: {
60
+ executablePath?: string;
61
+ }): Promise<PwBrowser>;
62
+ /**
63
+ * Runs before any page script in every frame. Wraps registerTool to record
64
+ * the descriptor (minus execute) and the caller's stack. The page's own
65
+ * registerTool still runs unchanged.
66
+ */
67
+ export declare const INIT_SCRIPT = "(() => {\n const KEY = Symbol.for(\"vskill.webmcp\");\n if (window[KEY]) return;\n const log = [];\n try { Object.defineProperty(window, KEY, { value: log, enumerable: false }); } catch (e) { return; }\n // Crawl safety: the audit loads one page; popups (popunders, auto-opened tabs) never load.\n try { window.open = function open() { return null; }; } catch (e) {}\n let proto = null;\n try {\n proto = (typeof ModelContext !== \"undefined\" && ModelContext.prototype) ||\n (document.modelContext && Object.getPrototypeOf(document.modelContext));\n } catch (e) {}\n if (!proto || typeof proto.registerTool !== \"function\") return;\n const safe = (v) => { try { return v === undefined ? undefined : JSON.parse(JSON.stringify(v)); } catch (e) { return undefined; } };\n const str = (v) => (typeof v === \"string\" ? v : undefined);\n const orig = proto.registerTool;\n const wrapped = function registerTool(tool, options) {\n try {\n const t = tool || {};\n const rec = {\n name: String(t.name == null ? \"\" : t.name),\n title: str(t.title),\n description: str(t.description),\n inputSchema: typeof t.inputSchema === \"string\" ? t.inputSchema : safe(t.inputSchema),\n annotations: safe(t.annotations),\n exposedTo: safe((options && options.exposedTo) !== undefined ? options.exposedTo : t.exposedTo),\n stack: String(new Error().stack || \"\"),\n };\n log.push(rec);\n const signal = options && options.signal;\n if (signal && typeof signal.addEventListener === \"function\") {\n signal.addEventListener(\"abort\", () => log.push({ name: rec.name, unregistered: true }), { once: true });\n }\n } catch (e) {}\n return orig.apply(this, arguments);\n };\n try { Object.defineProperty(proto, \"registerTool\", { value: wrapped, writable: true, configurable: true }); } catch (e) {}\n if (typeof proto.unregisterTool === \"function\") {\n const origUn = proto.unregisterTool;\n try {\n Object.defineProperty(proto, \"unregisterTool\", {\n value: function unregisterTool(name) {\n try { log.push({ name: String(name), unregistered: true }); } catch (e) {}\n return origUn.apply(this, arguments);\n },\n writable: true,\n configurable: true,\n });\n } catch (e) {}\n }\n})();\n//# sourceURL=vskill-webmcp-probe.js";
68
+ export interface EnumerateOptions {
69
+ timeoutMs: number;
70
+ /** Max wait after load for registrations to stop (default 5000). */
71
+ settleMs?: number;
72
+ /** Quiet period that ends the settle wait early (default 1500). */
73
+ quietMs?: number;
74
+ userAgent?: string;
75
+ /** Aborting closes the browser context, which ends any pending page work. */
76
+ signal?: AbortSignal;
77
+ }
78
+ /** Browser UA with our suffix, read once per browser. */
79
+ export declare function userAgentFor(browser: PwBrowser): Promise<string>;
80
+ export declare function enumerateSite(browser: PwBrowser, url: string, opts: EnumerateOptions): Promise<EnumerationResult>;
81
+ export {};