cdp-mcp 0.2.1 → 0.4.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.
Files changed (96) hide show
  1. package/README.md +28 -303
  2. package/bin.js +23 -0
  3. package/contract.d.ts +1 -0
  4. package/contract.js +2 -0
  5. package/index.d.ts +1 -0
  6. package/index.js +2 -0
  7. package/package.json +31 -73
  8. package/dist/contract.d.ts +0 -11
  9. package/dist/contract.js +0 -11
  10. package/dist/contract.js.map +0 -1
  11. package/dist/index.d.ts +0 -18
  12. package/dist/index.js +0 -402
  13. package/dist/index.js.map +0 -1
  14. package/dist/locator.d.ts +0 -108
  15. package/dist/locator.js +0 -176
  16. package/dist/locator.js.map +0 -1
  17. package/dist/server.d.ts +0 -2
  18. package/dist/server.js +0 -41
  19. package/dist/server.js.map +0 -1
  20. package/dist/session/browser.d.ts +0 -29
  21. package/dist/session/browser.js +0 -409
  22. package/dist/session/browser.js.map +0 -1
  23. package/dist/session/buffers.d.ts +0 -48
  24. package/dist/session/buffers.js +0 -43
  25. package/dist/session/buffers.js.map +0 -1
  26. package/dist/session/pause.d.ts +0 -21
  27. package/dist/session/pause.js +0 -99
  28. package/dist/session/pause.js.map +0 -1
  29. package/dist/session/state.d.ts +0 -53
  30. package/dist/session/state.js +0 -93
  31. package/dist/session/state.js.map +0 -1
  32. package/dist/sourcemap/loader.d.ts +0 -4
  33. package/dist/sourcemap/loader.js +0 -138
  34. package/dist/sourcemap/loader.js.map +0 -1
  35. package/dist/sourcemap/normalize.d.ts +0 -2
  36. package/dist/sourcemap/normalize.js +0 -59
  37. package/dist/sourcemap/normalize.js.map +0 -1
  38. package/dist/sourcemap/store.d.ts +0 -57
  39. package/dist/sourcemap/store.js +0 -185
  40. package/dist/sourcemap/store.js.map +0 -1
  41. package/dist/tools/_locator_runtime.d.ts +0 -31
  42. package/dist/tools/_locator_runtime.js +0 -243
  43. package/dist/tools/_locator_runtime.js.map +0 -1
  44. package/dist/tools/_register.d.ts +0 -2
  45. package/dist/tools/_register.js +0 -30
  46. package/dist/tools/_register.js.map +0 -1
  47. package/dist/tools/breakpoints.d.ts +0 -4
  48. package/dist/tools/breakpoints.js +0 -164
  49. package/dist/tools/breakpoints.js.map +0 -1
  50. package/dist/tools/console.d.ts +0 -2
  51. package/dist/tools/console.js +0 -48
  52. package/dist/tools/console.js.map +0 -1
  53. package/dist/tools/dom.d.ts +0 -2
  54. package/dist/tools/dom.js +0 -309
  55. package/dist/tools/dom.js.map +0 -1
  56. package/dist/tools/execution.d.ts +0 -29
  57. package/dist/tools/execution.js +0 -89
  58. package/dist/tools/execution.js.map +0 -1
  59. package/dist/tools/forms.d.ts +0 -8
  60. package/dist/tools/forms.js +0 -256
  61. package/dist/tools/forms.js.map +0 -1
  62. package/dist/tools/inspect.d.ts +0 -2
  63. package/dist/tools/inspect.js +0 -178
  64. package/dist/tools/inspect.js.map +0 -1
  65. package/dist/tools/nav.d.ts +0 -2
  66. package/dist/tools/nav.js +0 -136
  67. package/dist/tools/nav.js.map +0 -1
  68. package/dist/tools/network.d.ts +0 -2
  69. package/dist/tools/network.js +0 -137
  70. package/dist/tools/network.js.map +0 -1
  71. package/dist/tools/session.d.ts +0 -2
  72. package/dist/tools/session.js +0 -76
  73. package/dist/tools/session.js.map +0 -1
  74. package/dist/tools/source.d.ts +0 -2
  75. package/dist/tools/source.js +0 -63
  76. package/dist/tools/source.js.map +0 -1
  77. package/dist/tools/storage.d.ts +0 -2
  78. package/dist/tools/storage.js +0 -296
  79. package/dist/tools/storage.js.map +0 -1
  80. package/dist/util/browser-resolve.d.ts +0 -19
  81. package/dist/util/browser-resolve.js +0 -263
  82. package/dist/util/browser-resolve.js.map +0 -1
  83. package/dist/util/errors.d.ts +0 -7
  84. package/dist/util/errors.js +0 -12
  85. package/dist/util/errors.js.map +0 -1
  86. package/dist/util/format.d.ts +0 -20
  87. package/dist/util/format.js +0 -65
  88. package/dist/util/format.js.map +0 -1
  89. package/dist/util/log.d.ts +0 -6
  90. package/dist/util/log.js +0 -34
  91. package/dist/util/log.js.map +0 -1
  92. package/docs/chromium-sandboxing.md +0 -197
  93. package/docs/known-chromium-gaps.md +0 -138
  94. package/docs/launchd-service.md +0 -217
  95. package/docs/local-l3-e2e-setup.md +0 -199
  96. package/docs/systemd-service.md +0 -233
@@ -1,57 +0,0 @@
1
- import { SourceMapConsumer } from "@jridgewell/source-map";
2
- import type { Protocol } from "devtools-protocol";
3
- export interface ScriptInfo {
4
- scriptId: string;
5
- url: string;
6
- sourceMapURL?: string;
7
- startLine: number;
8
- startColumn: number;
9
- endLine: number;
10
- endColumn: number;
11
- executionContextId: number;
12
- hash: string;
13
- isModule?: boolean;
14
- sessionId?: string;
15
- consumer?: SourceMapConsumer;
16
- sources?: string[];
17
- loadError?: string;
18
- }
19
- export declare class ScriptStore {
20
- private byKey;
21
- upsert(info: Omit<ScriptInfo, "consumer" | "sources" | "loadError">): void;
22
- get(scriptId: string, sessionId?: string): ScriptInfo | undefined;
23
- all(): ScriptInfo[];
24
- remove(scriptId: string, sessionId?: string): void;
25
- clear(): void;
26
- findByOriginalSource(file: string): ScriptInfo[];
27
- attachMap(scriptId: string, sessionId: string | undefined, raw: string, mapUrl?: string): ScriptInfo | null;
28
- setLoadError(scriptId: string, sessionId: string | undefined, err: string): void;
29
- }
30
- export declare function cdpToPublic(loc: {
31
- lineNumber: number;
32
- columnNumber?: number;
33
- }): {
34
- line: number;
35
- column: number;
36
- };
37
- export declare function publicToCdp(loc: {
38
- line: number;
39
- column?: number;
40
- }): {
41
- lineNumber: number;
42
- columnNumber: number;
43
- };
44
- export declare function mapCdpToOriginal(store: ScriptStore, frame: Pick<Protocol.Debugger.CallFrame["location"], "scriptId" | "lineNumber" | "columnNumber">, sessionId: string | undefined): {
45
- file: string;
46
- line: number;
47
- column: number;
48
- } | null;
49
- export interface GeneratedLocation {
50
- scriptId: string;
51
- scriptUrl: string;
52
- sessionId?: string;
53
- lineNumber: number;
54
- columnNumber: number;
55
- }
56
- export declare function mapOriginalToGenerated(store: ScriptStore, file: string, line: number, // 1-based
57
- column?: number): GeneratedLocation[];
@@ -1,185 +0,0 @@
1
- import { SourceMapConsumer } from "@jridgewell/source-map";
2
- import { normalizeSourcePath, pathMatches } from "./normalize.js";
3
- import { log } from "../util/log.js";
4
- // CDP scriptIds are scoped per Debugger agent (per flat session). Two
5
- // targets — page + worker, or two iframes — can independently emit
6
- // scriptId="42". Keying the store on scriptId alone would let the second
7
- // upsert silently overwrite the first, attach the wrong source map, or
8
- // resolve paused frames to the wrong script. Compound key is sessionId
9
- // (or a synthetic root marker) + scriptId.
10
- const ROOT_KEY = "__root__";
11
- const keyFor = (scriptId, sessionId) => `${sessionId ?? ROOT_KEY} ${scriptId}`;
12
- // Indexes scripts the browser has parsed and their (optional) source maps.
13
- export class ScriptStore {
14
- byKey = new Map();
15
- // HMR / soft-reload note: when a script is re-parsed under the same
16
- // (sessionId, scriptId), Object.assign(existing, info) copies the new
17
- // metadata fields but does NOT overwrite `consumer`, `sources`, or
18
- // `loadError` because they aren't in the upsert payload (the input type
19
- // explicitly Omit<>'s them). A subsequent Debugger.scriptParsed for the
20
- // *same* scriptId therefore inherits the OLD source-map consumer until
21
- // attachMap() is called again. This is intentional for soft reloads
22
- // (the source-map URL is usually the same), but means HMR-changed maps
23
- // can leak stale mappings until the next session reset() clears them.
24
- // close_session/switchTarget call ScriptStore.clear() so cross-session
25
- // contamination is bounded — within a session, downstream callers must
26
- // re-attachMap() after any reload that may have changed the map.
27
- upsert(info) {
28
- const key = keyFor(info.scriptId, info.sessionId);
29
- const existing = this.byKey.get(key);
30
- if (existing) {
31
- Object.assign(existing, info);
32
- }
33
- else {
34
- this.byKey.set(key, { ...info });
35
- }
36
- }
37
- get(scriptId, sessionId) {
38
- return this.byKey.get(keyFor(scriptId, sessionId));
39
- }
40
- all() {
41
- return Array.from(this.byKey.values());
42
- }
43
- remove(scriptId, sessionId) {
44
- this.byKey.delete(keyFor(scriptId, sessionId));
45
- }
46
- clear() {
47
- for (const s of this.byKey.values())
48
- s.consumer?.destroy();
49
- this.byKey.clear();
50
- }
51
- // Find scripts whose source map references the given TS file.
52
- findByOriginalSource(file) {
53
- const matches = [];
54
- for (const s of this.byKey.values()) {
55
- if (!s.sources)
56
- continue;
57
- if (s.sources.some((src) => pathMatches(src, file))) {
58
- matches.push(s);
59
- }
60
- }
61
- return matches;
62
- }
63
- attachMap(scriptId, sessionId, raw, mapUrl) {
64
- const script = this.byKey.get(keyFor(scriptId, sessionId));
65
- if (!script)
66
- return null;
67
- try {
68
- const consumer = new SourceMapConsumer(raw, mapUrl);
69
- script.consumer = consumer;
70
- script.sources = (consumer.sources ?? []).map((s) => normalizeSourcePath(s ?? ""));
71
- script.loadError = undefined;
72
- }
73
- catch (e) {
74
- script.loadError = `source-map parse failed: ${String(e)}`;
75
- log.warn("source-map parse failed", { scriptId, sessionId, url: script.url, error: String(e) });
76
- }
77
- return script;
78
- }
79
- setLoadError(scriptId, sessionId, err) {
80
- const s = this.byKey.get(keyFor(scriptId, sessionId));
81
- if (s)
82
- s.loadError = err;
83
- }
84
- }
85
- // Helpers for converting CDP <-> source-map line numbering.
86
- // CDP: 0-based line, 0-based column.
87
- // source-map: 1-based line, 0-based column.
88
- // Public tool API: 1-based line, 0-based column.
89
- export function cdpToPublic(loc) {
90
- return { line: loc.lineNumber + 1, column: loc.columnNumber ?? 0 };
91
- }
92
- export function publicToCdp(loc) {
93
- return { lineNumber: loc.line - 1, columnNumber: loc.column ?? 0 };
94
- }
95
- // Translate a CDP-paused frame's location to a public TS location, if a map is available.
96
- export function mapCdpToOriginal(store, frame, sessionId) {
97
- const script = store.get(frame.scriptId, sessionId);
98
- if (!script?.consumer)
99
- return null;
100
- const orig = script.consumer.originalPositionFor({
101
- line: frame.lineNumber + 1, // source-map is 1-based
102
- column: frame.columnNumber ?? 0,
103
- });
104
- if (orig.source == null || orig.line == null)
105
- return null;
106
- return {
107
- file: normalizeSourcePath(orig.source),
108
- line: orig.line, // already 1-based
109
- column: orig.column ?? 0,
110
- };
111
- }
112
- // Translate a public TS coord to one or more CDP coords for setBreakpointByUrl.
113
- //
114
- // Uses `allGeneratedPositionsFor` (NOT `generatedPositionFor`) because the
115
- // latter requires an EXACT (line, column) match against the source map's
116
- // emitted mappings — and esbuild/vite typically emit mappings only at
117
- // statement starts (e.g., column 2 for an indented `return x;`), not at
118
- // column 0. Setting a breakpoint at `handlers.ts:12` should land regardless
119
- // of whether the caller supplied column 0 (the default) or the exact
120
- // column of the first statement; `allGeneratedPositionsFor` enumerates
121
- // every generated position for the source line, which is the contract
122
- // debuggers want for breakpoint resolution. (PR #11 e2e bug — line 12 of
123
- // the sample app has mappings at columns 2 and 9 but none at column 0.)
124
- //
125
- // If the source line has multiple generated positions across distinct
126
- // generated lines (rare with single-line vite bundles, common after
127
- // minification splits or with classic webpack), each is emitted as its
128
- // own GeneratedLocation — Debugger.setBreakpointByUrl ends up binding at
129
- // each, which is what users intuitively expect.
130
- export function mapOriginalToGenerated(store, file, line, // 1-based
131
- column = 0) {
132
- const out = [];
133
- for (const script of store.findByOriginalSource(file)) {
134
- if (!script.consumer)
135
- continue;
136
- const sourceKey = pickSourceKey(script, file);
137
- if (!sourceKey)
138
- continue;
139
- // Forward the caller's column. allGeneratedPositionsFor with column=0
140
- // returns the first mapping on the source line (the line-broad case
141
- // set_breakpoint uses by default). With a non-zero column it returns
142
- // the mapping at-or-after that original column — honoring an
143
- // explicitly-supplied column without forcing exact-match strictness.
144
- // (Codex/Opus PR #11 round-2: prior version pinned column:0 here and
145
- // silently ignored the caller's value.)
146
- const positions = script.consumer.allGeneratedPositionsFor({
147
- source: sourceKey,
148
- line, // 1-based in
149
- column,
150
- });
151
- // De-dup by (gen line, gen col) — different originalColumn mappings on
152
- // the same source line can collapse to the same generated position
153
- // after minification, but we only need one breakpoint binding per
154
- // distinct generated location.
155
- const seen = new Set();
156
- for (const gen of positions) {
157
- if (gen.line == null)
158
- continue;
159
- const key = `${gen.line}:${gen.column ?? 0}`;
160
- if (seen.has(key))
161
- continue;
162
- seen.add(key);
163
- out.push({
164
- scriptId: script.scriptId,
165
- scriptUrl: script.url,
166
- ...(script.sessionId ? { sessionId: script.sessionId } : {}),
167
- lineNumber: gen.line - 1, // back to 0-based for CDP
168
- columnNumber: gen.column ?? 0,
169
- });
170
- }
171
- }
172
- return out;
173
- }
174
- function pickSourceKey(script, file) {
175
- if (!script.consumer)
176
- return null;
177
- // We want the source as it appears in the map (with whatever prefix it had)
178
- // so the consumer can look it up.
179
- for (const raw of script.consumer.sources ?? []) {
180
- if (raw && pathMatches(raw, file))
181
- return raw;
182
- }
183
- return null;
184
- }
185
- //# sourceMappingURL=store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/sourcemap/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAqBrC,sEAAsE;AACtE,mEAAmE;AACnE,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,2CAA2C;AAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC;AAC5B,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,SAA6B,EAAE,EAAE,CACjE,GAAG,SAAS,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAEzC,2EAA2E;AAC3E,MAAM,OAAO,WAAW;IACd,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE9C,oEAAoE;IACpE,sEAAsE;IACtE,mEAAmE;IACnE,wEAAwE;IACxE,wEAAwE;IACxE,uEAAuE;IACvE,oEAAoE;IACpE,uEAAuE;IACvE,sEAAsE;IACtE,uEAAuE;IACvE,uEAAuE;IACvE,iEAAiE;IACjE,MAAM,CAAC,IAA4D;QACjE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,GAAG,CAAC,QAAgB,EAAE,SAAkB;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,GAAG;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE,SAAkB;QACzC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,KAAK;QACH,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,oBAAoB,CAAC,IAAY;QAC/B,MAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,SAAS;YACzB,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,CAAC,QAAgB,EAAE,SAA6B,EAAE,GAAW,EAAE,MAAe;QACrF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC3B,MAAM,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClD,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAC,CAC7B,CAAC;YACF,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,SAAS,GAAG,4BAA4B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,QAAgB,EAAE,SAA6B,EAAE,GAAW;QACvE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC;YAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;IAC3B,CAAC;CACF;AAED,4DAA4D;AAC5D,qCAAqC;AACrC,4CAA4C;AAC5C,iDAAiD;AAEjD,MAAM,UAAU,WAAW,CAAC,GAG3B;IACC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAG3B;IACC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,gBAAgB,CAC9B,KAAkB,EAClB,KAAgG,EAChG,SAA6B;IAE7B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,EAAE,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAC/C,IAAI,EAAE,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,wBAAwB;QACpD,MAAM,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC1D,OAAO;QACL,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QACtC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,kBAAkB;QACnC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC;KACzB,CAAC;AACJ,CAAC;AAUD,gFAAgF;AAChF,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,sEAAsE;AACtE,wEAAwE;AACxE,4EAA4E;AAC5E,qEAAqE;AACrE,uEAAuE;AACvE,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,uEAAuE;AACvE,yEAAyE;AACzE,gDAAgD;AAChD,MAAM,UAAU,sBAAsB,CACpC,KAAkB,EAClB,IAAY,EACZ,IAAY,EAAE,UAAU;AACxB,SAAiB,CAAC;IAElB,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,SAAS;QAC/B,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,sEAAsE;QACtE,oEAAoE;QACpE,qEAAqE;QACrE,6DAA6D;QAC7D,qEAAqE;QACrE,qEAAqE;QACrE,wCAAwC;QACxC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAC;YACzD,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,aAAa;YACnB,MAAM;SACP,CAAC,CAAC;QACH,uEAAuE;QACvE,mEAAmE;QACnE,kEAAkE;QAClE,+BAA+B;QAC/B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI;gBAAE,SAAS;YAC/B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC7C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC;gBACP,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,SAAS,EAAE,MAAM,CAAC,GAAG;gBACrB,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,UAAU,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,0BAA0B;gBACpD,YAAY,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,MAAkB,EAAE,IAAY;IACrD,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAClC,4EAA4E;IAC5E,kCAAkC;IAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAChD,IAAI,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,31 +0,0 @@
1
- import { type LocatorSpec } from "../locator.js";
2
- /**
3
- * Normalize a LocatorSpec for tool use, surfacing failures as the repo's
4
- * structured `ToolError` (historically `missing_arg`) instead of the contract's
5
- * plain `LocatorError`.
6
- */
7
- export declare function normalizeLocator(input: LocatorSpec): LocatorSpec;
8
- /**
9
- * In-page helper library: text/visibility utilities, the accessibility
10
- * heuristics (`implicitRole`, `accessibleName`, `cssPath`), `elementInfo`, and
11
- * `findElements(spec)`. Inject this into a `Runtime.evaluate` expression before
12
- * `locatorReadScript()` or `mutationHelpersScript()`.
13
- */
14
- export declare function locatorHelpersScript(): string;
15
- /**
16
- * The read-only `locate(spec, options)` entry. Compose after
17
- * `locatorHelpersScript()`; returns `{ ok, error?, found, count, visible_count, matches }`.
18
- */
19
- export declare function locatorReadScript(): string;
20
- /**
21
- * Mutation helpers for the form-driving tools. Compose after
22
- * `locatorHelpersScript()`:
23
- * - `resolveOne(spec)` → `{ ok, el?, count, visible_count, error?, code? }`,
24
- * preferring visible matches (the same visible-first bias `locate` reports)
25
- * and picking the first match. On failure `code` distinguishes an
26
- * invalid/unsupported locator (`invalid_locator`, mirroring locate/wait_for)
27
- * from a valid locator that matched nothing (`not_found`).
28
- * - `fireEvents(el, types)` → dispatch bubbling events (e.g. `input`/`change`)
29
- * so app frameworks observe a programmatic mutation.
30
- */
31
- export declare function mutationHelpersScript(): string;
@@ -1,243 +0,0 @@
1
- /**
2
- * Shared, tools-side locator plumbing.
3
- *
4
- * The canonical LocatorSpec contract lives in `../locator.ts` (zod-only, public).
5
- * This module adds the parts that are specific to running locators *inside the
6
- * page* and to the cdp-mcp tool error envelope:
7
- * - `normalizeLocator` — the contract normalizer, re-wrapping `LocatorError`
8
- * as the repo's structured `ToolError` (preserving its error code).
9
- * - `locatorHelpersScript()` — the in-page helper library (accessibility
10
- * heuristics, visibility, `findElements`, `elementInfo`).
11
- * - `locatorReadScript()` — the read-only `locate(spec, options)` entry.
12
- * - `mutationHelpersScript()` — `resolveOne(spec)` + `fireEvents(el, types)`,
13
- * used by the form-driving tools to resolve and mutate an element with the
14
- * exact same matching semantics as `locate`.
15
- *
16
- * Both `dom.ts` (read) and the form-driving tools (drive) compose these so a
17
- * locator behaves identically whether it is queried or acted upon.
18
- */
19
- import { ToolError } from "../util/errors.js";
20
- import { normalizeLocator as normalizeLocatorContract, LocatorError, } from "../locator.js";
21
- /**
22
- * Normalize a LocatorSpec for tool use, surfacing failures as the repo's
23
- * structured `ToolError` (historically `missing_arg`) instead of the contract's
24
- * plain `LocatorError`.
25
- */
26
- export function normalizeLocator(input) {
27
- try {
28
- return normalizeLocatorContract(input);
29
- }
30
- catch (e) {
31
- if (e instanceof LocatorError)
32
- throw new ToolError(e.code, e.message);
33
- throw e;
34
- }
35
- }
36
- /**
37
- * In-page helper library: text/visibility utilities, the accessibility
38
- * heuristics (`implicitRole`, `accessibleName`, `cssPath`), `elementInfo`, and
39
- * `findElements(spec)`. Inject this into a `Runtime.evaluate` expression before
40
- * `locatorReadScript()` or `mutationHelpersScript()`.
41
- */
42
- export function locatorHelpersScript() {
43
- return String.raw `
44
- const compact = (value) => (value || "").replace(/\s+/g, " ").trim();
45
- const lower = (value) => compact(value).toLowerCase();
46
- const cssEscape = (value) => globalThis.CSS?.escape ? globalThis.CSS.escape(value) : String(value).replace(/["\\]/g, "\\$&");
47
- const matchesText = (actual, expected, exact) => {
48
- if (expected == null || expected === "") return true;
49
- const a = lower(actual);
50
- const e = lower(expected);
51
- return exact ? a === e : a.includes(e);
52
- };
53
- const textOf = (el) => compact(el.innerText || el.textContent || "");
54
- const isVisible = (el) => {
55
- if (!el.isConnected) return false;
56
- const style = getComputedStyle(el);
57
- if (style.visibility === "hidden" || style.display === "none" || Number(style.opacity) === 0) return false;
58
- const rect = el.getBoundingClientRect();
59
- return rect.width > 0 && rect.height > 0;
60
- };
61
- const labelText = (el) => {
62
- if ("labels" in el && el.labels && el.labels.length > 0) {
63
- return compact(Array.from(el.labels).map((label) => label.innerText || label.textContent || "").join(" "));
64
- }
65
- return "";
66
- };
67
- const accessibleName = (el) => {
68
- const ariaLabel = el.getAttribute("aria-label");
69
- if (ariaLabel) return compact(ariaLabel);
70
- const labelledBy = el.getAttribute("aria-labelledby");
71
- if (labelledBy) {
72
- const text = labelledBy
73
- .split(/\s+/)
74
- .map((id) => document.getElementById(id)?.innerText || document.getElementById(id)?.textContent || "")
75
- .join(" ");
76
- if (compact(text)) return compact(text);
77
- }
78
- const label = labelText(el);
79
- if (label) return label;
80
- if (el instanceof HTMLInputElement && ["button", "submit", "reset"].includes(el.type)) return compact(el.value);
81
- if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) return compact(el.placeholder || el.value || "");
82
- if (el instanceof HTMLImageElement) return compact(el.alt || "");
83
- return textOf(el);
84
- };
85
- const implicitRole = (el) => {
86
- const explicit = el.getAttribute("role");
87
- if (explicit) return lower(explicit.split(/\s+/)[0]);
88
- const tag = el.tagName.toLowerCase();
89
- if (tag === "button") return "button";
90
- if (tag === "a" && el.hasAttribute("href")) return "link";
91
- if (/^h[1-6]$/.test(tag)) return "heading";
92
- if (tag === "textarea") return "textbox";
93
- if (tag === "select") return el.multiple ? "listbox" : "combobox";
94
- if (tag === "img") return "img";
95
- if (el.isContentEditable) return "textbox";
96
- if (tag === "input") {
97
- const type = lower(el.getAttribute("type") || "text");
98
- if (["button", "submit", "reset"].includes(type)) return "button";
99
- if (type === "checkbox") return "checkbox";
100
- if (type === "radio") return "radio";
101
- if (type === "range") return "slider";
102
- if (["email", "password", "search", "tel", "text", "url", ""].includes(type)) return "textbox";
103
- if (type === "number") return "spinbutton";
104
- }
105
- return "";
106
- };
107
- const cssPath = (el) => {
108
- if (el.id) return "#" + cssEscape(el.id);
109
- const testId = el.getAttribute("data-testid") || el.getAttribute("data-test-id") || el.getAttribute("data-test");
110
- if (testId) return "[" + (el.hasAttribute("data-testid") ? "data-testid" : el.hasAttribute("data-test-id") ? "data-test-id" : "data-test") + "=\"" + cssEscape(testId) + "\"]";
111
- const parts = [];
112
- let node = el;
113
- while (node && node.nodeType === Node.ELEMENT_NODE && parts.length < 5) {
114
- const tag = node.tagName.toLowerCase();
115
- const name = node.getAttribute("name");
116
- if (name) {
117
- parts.unshift(tag + "[name=\"" + cssEscape(name) + "\"]");
118
- break;
119
- }
120
- const siblings = Array.from(node.parentElement?.children || []).filter((child) => child.tagName === node.tagName);
121
- const index = siblings.indexOf(node) + 1;
122
- parts.unshift(siblings.length > 1 ? tag + ":nth-of-type(" + index + ")" : tag);
123
- node = node.parentElement;
124
- }
125
- return parts.join(" > ");
126
- };
127
- const elementInfo = (el) => {
128
- const rect = el.getBoundingClientRect();
129
- const info = {
130
- selector: cssPath(el),
131
- tag: el.tagName.toLowerCase(),
132
- role: implicitRole(el) || undefined,
133
- name: accessibleName(el) || undefined,
134
- text: textOf(el).slice(0, 300),
135
- visible: isVisible(el),
136
- disabled: "disabled" in el ? !!el.disabled : undefined,
137
- value: "value" in el ? el.value : undefined,
138
- checked: "checked" in el ? !!el.checked : undefined,
139
- bbox: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
140
- };
141
- return Object.fromEntries(Object.entries(info).filter(([, value]) => value !== undefined && value !== ""));
142
- };
143
- const queryAll = (selector) => {
144
- try {
145
- return { ok: true, elements: Array.from(document.querySelectorAll(selector)) };
146
- } catch (error) {
147
- return { ok: false, error: "Invalid CSS selector " + selector + ": " + error.message };
148
- }
149
- };
150
- const leafTextMatches = (el, expected, exact) => {
151
- if (!matchesText(textOf(el), expected, exact)) return false;
152
- return !Array.from(el.children).some((child) => matchesText(textOf(child), expected, exact));
153
- };
154
- const findElements = (spec) => {
155
- const by = spec.by || (spec.selector || spec.css ? "css" : "");
156
- const exact = !!spec.exact;
157
- if (by === "css") return queryAll(spec.selector || spec.css);
158
- if (by === "text") {
159
- return { ok: true, elements: Array.from(document.querySelectorAll("body *")).filter((el) => leafTextMatches(el, spec.text || spec.name, exact)) };
160
- }
161
- if (by === "role") {
162
- return { ok: true, elements: Array.from(document.querySelectorAll("body *")).filter((el) => implicitRole(el) === lower(spec.role) && matchesText(accessibleName(el), spec.name, exact)) };
163
- }
164
- if (by === "test_id" || by === "testId") {
165
- const wanted = spec.test_id || spec.testId || spec.name;
166
- const candidates = Array.from(document.querySelectorAll("[data-testid], [data-test-id], [data-test]"));
167
- return { ok: true, elements: candidates.filter((el) => [el.getAttribute("data-testid"), el.getAttribute("data-test-id"), el.getAttribute("data-test")].some((value) => matchesText(value, wanted, true))) };
168
- }
169
- if (by === "label") {
170
- const wanted = spec.label || spec.name;
171
- const controls = [];
172
- for (const label of Array.from(document.querySelectorAll("label"))) {
173
- if (!matchesText(textOf(label), wanted, exact)) continue;
174
- const control = label.control || label.querySelector("input, textarea, select, button");
175
- if (control) controls.push(control);
176
- }
177
- return { ok: true, elements: controls };
178
- }
179
- if (by === "placeholder") {
180
- const wanted = spec.placeholder || spec.name;
181
- return { ok: true, elements: Array.from(document.querySelectorAll("[placeholder]")).filter((el) => matchesText(el.getAttribute("placeholder"), wanted, exact)) };
182
- }
183
- if (by === "name") {
184
- return { ok: true, elements: Array.from(document.querySelectorAll("[name]")).filter((el) => matchesText(el.getAttribute("name"), spec.name, true)) };
185
- }
186
- return { ok: false, error: "Unsupported locator strategy: " + by };
187
- };
188
- `;
189
- }
190
- /**
191
- * The read-only `locate(spec, options)` entry. Compose after
192
- * `locatorHelpersScript()`; returns `{ ok, error?, found, count, visible_count, matches }`.
193
- */
194
- export function locatorReadScript() {
195
- return String.raw `
196
- const locate = (spec, options) => {
197
- const found = findElements(spec);
198
- if (!found.ok) return { ok: false, error: found.error, found: false, count: 0, visible_count: 0, matches: [] };
199
- const all = found.elements;
200
- const visible = all.filter(isVisible);
201
- const returned = (options.includeHidden ? all : visible).slice(0, options.limit || 20).map(elementInfo);
202
- return {
203
- ok: true,
204
- found: returned.length > 0,
205
- count: all.length,
206
- visible_count: visible.length,
207
- matches: returned,
208
- };
209
- };
210
- `;
211
- }
212
- /**
213
- * Mutation helpers for the form-driving tools. Compose after
214
- * `locatorHelpersScript()`:
215
- * - `resolveOne(spec)` → `{ ok, el?, count, visible_count, error?, code? }`,
216
- * preferring visible matches (the same visible-first bias `locate` reports)
217
- * and picking the first match. On failure `code` distinguishes an
218
- * invalid/unsupported locator (`invalid_locator`, mirroring locate/wait_for)
219
- * from a valid locator that matched nothing (`not_found`).
220
- * - `fireEvents(el, types)` → dispatch bubbling events (e.g. `input`/`change`)
221
- * so app frameworks observe a programmatic mutation.
222
- */
223
- export function mutationHelpersScript() {
224
- return String.raw `
225
- const resolveOne = (spec) => {
226
- const found = findElements(spec);
227
- // findElements only returns !ok for an invalid/unsupported locator (bad CSS
228
- // selector or unknown strategy) — the same condition locate/wait_for report
229
- // as invalid_locator. A valid locator that simply matches nothing is the
230
- // distinct not_found case below.
231
- if (!found.ok) return { ok: false, error: found.error, code: "invalid_locator" };
232
- const all = found.elements;
233
- const visible = all.filter(isVisible);
234
- const pick = visible.length ? visible : all;
235
- if (pick.length === 0) return { ok: false, error: "no element matches locator", code: "not_found" };
236
- return { ok: true, el: pick[0], count: all.length, visible_count: visible.length };
237
- };
238
- const fireEvents = (el, types) => {
239
- for (const t of types) el.dispatchEvent(new Event(t, { bubbles: true }));
240
- };
241
- `;
242
- }
243
- //# sourceMappingURL=_locator_runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_locator_runtime.js","sourceRoot":"","sources":["../../src/tools/_locator_runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EACL,gBAAgB,IAAI,wBAAwB,EAC5C,YAAY,GAEb,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,IAAI,CAAC;QACH,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,YAAY;YAAE,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiJhB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;GAehB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;GAiBhB,CAAC;AACJ,CAAC"}
@@ -1,2 +0,0 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare function registerJsonTool<TInput extends Record<string, any>>(server: McpServer, name: string, description: string, inputShape: Record<string, any> | undefined, handler: (input: TInput) => Promise<unknown> | unknown): void;
@@ -1,30 +0,0 @@
1
- import { ToolError } from "../util/errors.js";
2
- import { log } from "../util/log.js";
3
- import { toolJson, toolText } from "../util/format.js";
4
- // Wrap a tool handler with consistent error handling so any thrown error
5
- // becomes a structured `isError: true` result rather than an MCP transport error.
6
- export function registerJsonTool(server, name, description, inputShape, handler) {
7
- server.registerTool(name, {
8
- description,
9
- ...(inputShape ? { inputSchema: inputShape } : {}),
10
- }, async (args) => {
11
- try {
12
- const result = await handler((args ?? {}));
13
- if (result === undefined)
14
- return toolText("ok");
15
- if (typeof result === "string")
16
- return toolText(result);
17
- return toolJson(result);
18
- }
19
- catch (e) {
20
- const code = e instanceof ToolError ? e.code : "internal_error";
21
- const msg = e instanceof Error ? e.message : String(e);
22
- log.warn(`tool error ${name}`, { code, msg });
23
- return {
24
- isError: true,
25
- content: [{ type: "text", text: JSON.stringify({ error: code, message: msg }) }],
26
- };
27
- }
28
- });
29
- }
30
- //# sourceMappingURL=_register.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_register.js","sourceRoot":"","sources":["../../src/tools/_register.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEvD,yEAAyE;AACzE,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAC9B,MAAiB,EACjB,IAAY,EACZ,WAAmB,EACnB,UAA2C,EAC3C,OAAsD;IAEtD,MAAM,CAAC,YAAY,CACjB,IAAI,EACJ;QACE,WAAW;QACX,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1D,EACD,KAAK,EAAE,IAAS,EAAE,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,IAAI,IAAI,EAAE,CAAW,CAAC,CAAC;YACrD,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,CAAC,YAAY,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;YAChE,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;aAC1F,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,4 +0,0 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare function registerBreakpointTools(server: McpServer): void;
3
- /** @internal exported for unit tests; not part of the MCP tool surface. */
4
- export declare function buildConditionExpression(condition?: string, logMessage?: string): string | undefined;