@certscore/mcp 0.2.12 → 0.2.15

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAwDD,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,mBAAwB,aA2SzE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAyED,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,mBAAwB,aAkSzE"}
package/dist/server.js CHANGED
@@ -2,9 +2,20 @@ import { CertScoreClient, CertScoreTimeoutError } from "@certscore/sdk";
2
2
  import { certScoreMcpToolContracts } from "@certscore/api-contracts";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { CERTSCORE_MCP_VERSION } from "./version.js";
5
- import { boundEvidencePacket, buildScanBundle, exportFindings, limitPreConsentRows, normalizeDetail, normalizeFormat, paginateFindingList, scanIdFromStatus, toToolError, toToolResult } from "./tools.js";
6
- let createScanDeprecationWarningPrinted = false;
5
+ import { boundEvidencePacket, buildScanBundle, exportFindings, limitPreConsentRows, normalizeDetail, normalizeFormat, paginateFindingList, toInvalidArgumentsToolError, toToolError, toToolResult, withMcpAgentGuidance } from "./tools.js";
7
6
  const DEFAULT_MCP_SCAN_WAIT_MS = 45_000;
7
+ async function retryTransientOriginFailure(operation) {
8
+ try {
9
+ return await operation();
10
+ }
11
+ catch (error) {
12
+ const retryable = error instanceof Error && "status" in error && [502, 503, 504].includes(Number(error.status));
13
+ if (!retryable) {
14
+ throw error;
15
+ }
16
+ return operation();
17
+ }
18
+ }
8
19
  function scanCreationMetadata(value) {
9
20
  return {
10
21
  executionMode: value.executionMode,
@@ -45,7 +56,11 @@ export function createCertScoreMcpServer(options = {}) {
45
56
  name: "certscore",
46
57
  version: CERTSCORE_MCP_VERSION
47
58
  });
48
- const lightTools = new Set(["scan_site", "get_scan_status", "get_scan_bundle"]);
59
+ const sdkCreateToolError = server.createToolError.bind(server);
60
+ server.createToolError = (message) => message.includes("Input validation error:")
61
+ ? toInvalidArgumentsToolError(message)
62
+ : sdkCreateToolError(message);
63
+ const lightTools = new Set(["certscore_scan_site", "certscore_get_scan_status", "certscore_get_scan_bundle"]);
49
64
  const registerMcpTool = server.registerTool.bind(server);
50
65
  const registerTool = (name, contract, handler) => {
51
66
  if (options.toolProfile === "light" && !lightTools.has(name)) {
@@ -53,78 +68,57 @@ export function createCertScoreMcpServer(options = {}) {
53
68
  }
54
69
  registerMcpTool(name, contract, handler);
55
70
  };
56
- async function createPulseScanTool(input) {
57
- const result = await client.submitScan(input.url, {
58
- detail: normalizeDetail(input.detail),
59
- format: normalizeFormat(input.format),
60
- freshness: input.freshness ?? "latest",
61
- scanFrom: input.scanFrom
62
- });
63
- return {
64
- type: "certscore_mcp_scan_created",
65
- status: result.status,
66
- jobId: result.jobId ?? null,
67
- scanId: result.scanId ?? result.scan_id ?? null,
68
- completed: result.completed ?? false,
69
- statusUrl: result.statusUrl ?? result.nextCheckUrl ?? null,
70
- resultUrl: result.resultUrl ?? null,
71
- reportUrl: result.reportUrl ?? null,
72
- pulse: result.pulse ?? null,
73
- resultDisposition: result.resultDisposition ?? result.pulse?.resultDisposition ?? null,
74
- noGo: result.noGo ?? result.pulse?.noGo ?? null
75
- };
76
- }
77
- registerTool("create_scan", toolContract("create_scan"), async (input) => {
78
- try {
79
- if (!createScanDeprecationWarningPrinted) {
80
- createScanDeprecationWarningPrinted = true;
81
- console.error("[certscore-mcp] create_scan is deprecated in the 0.2.x line. Use scan_site for new integrations.");
82
- }
83
- return toToolResult(await createPulseScanTool(input));
84
- }
85
- catch (error) {
86
- return toToolError(error);
87
- }
88
- });
89
- registerTool("scan_site", toolContract("scan_site"), async (input) => {
71
+ registerTool("certscore_scan_site", toolContract("certscore_scan_site"), async (input) => {
90
72
  try {
91
73
  const created = await client.scans.create(input.url, {
92
74
  freshness: input.freshness ?? "latest",
93
75
  scanFrom: input.scanFrom
94
76
  });
95
77
  if (input.waitForCompletion === false || created.type === "certscore_scan") {
96
- return toToolResult(created);
78
+ return toToolResult(withMcpAgentGuidance(created));
97
79
  }
98
80
  try {
99
81
  const completed = await client.scans.wait(created, {
100
82
  maxWaitMs: Math.min(input.maxWaitSeconds ? input.maxWaitSeconds * 1_000 : DEFAULT_MCP_SCAN_WAIT_MS, DEFAULT_MCP_SCAN_WAIT_MS)
101
83
  });
102
- return toToolResult({
84
+ return toToolResult(withMcpAgentGuidance({
103
85
  ...completed,
104
- ...scanCreationMetadata(created),
105
- recommendedNextTool: "get_scan_bundle"
106
- });
86
+ ...scanCreationMetadata(created)
87
+ }));
107
88
  }
108
89
  catch (error) {
109
- if (!(error instanceof CertScoreTimeoutError)) {
110
- throw error;
111
- }
112
90
  const scanId = created.scanId ?? created.scan_id;
113
- if (scanId) {
114
- return toToolResult({
115
- ...(await client.scans.status(scanId)),
116
- ...scanCreationMetadata(created),
117
- recommendedNextTool: "get_scan_status"
118
- });
91
+ console.warn(JSON.stringify({
92
+ event: "mcp.certscore_scan_site.wait_deferred",
93
+ errorName: error instanceof Error ? error.name : "UnknownError",
94
+ jobId: created.jobId ?? null,
95
+ scanId: scanId ?? null,
96
+ status: created.status ?? null
97
+ }));
98
+ if (error instanceof CertScoreTimeoutError && scanId) {
99
+ try {
100
+ return toToolResult(withMcpAgentGuidance({
101
+ ...(await client.scans.status(scanId)),
102
+ ...scanCreationMetadata(created)
103
+ }));
104
+ }
105
+ catch {
106
+ // Creation already succeeded. Preserve that stable identity when
107
+ // the follow-up status read is briefly unavailable.
108
+ }
119
109
  }
120
- return toToolResult(created);
110
+ // Waiting is a convenience layered on top of scan creation. Once the
111
+ // API has accepted a scan, never turn a transient polling or hydration
112
+ // failure into an identity-less tool error that encourages callers to
113
+ // submit a second, non-idempotent certscore_scan_site request.
114
+ return toToolResult(withMcpAgentGuidance(created));
121
115
  }
122
116
  }
123
117
  catch (error) {
124
118
  return toToolError(error);
125
119
  }
126
120
  });
127
- registerTool("get_scan", toolContract("get_scan"), async ({ scanId }) => {
121
+ registerTool("certscore_get_scan", toolContract("certscore_get_scan"), async ({ scanId }) => {
128
122
  try {
129
123
  return toToolResult(await client.scans.get(scanId));
130
124
  }
@@ -132,53 +126,47 @@ export function createCertScoreMcpServer(options = {}) {
132
126
  return toToolError(error);
133
127
  }
134
128
  });
135
- registerTool("get_scan_status", toolContract("get_scan_status"), async ({ jobId, scanId }) => {
129
+ registerTool("certscore_get_scan_status", toolContract("certscore_get_scan_status"), async ({ scanId }) => {
136
130
  try {
137
- if (scanId) {
138
- const status = await client.scans.status(scanId);
139
- const needsTerminalHydration = status.status === "completed" || status.status === "completed_limited";
140
- if (needsTerminalHydration) {
141
- try {
142
- const scan = await client.scans.get(scanId);
143
- return toToolResult({
144
- ...status,
145
- type: "certscore_scan_job",
146
- status: scan.status,
147
- domain: scan.domain,
148
- resultDisposition: scan.resultDisposition,
149
- noGo: scan.noGo,
150
- startedAt: scan.startedAt,
151
- completedAt: scan.completedAt,
152
- scanTimeSeconds: scan.scanTimeSeconds,
153
- recommendedNextTool: "get_scan_bundle"
154
- });
155
- }
156
- catch {
157
- // Preserve the API status response if the terminal scan resource is
158
- // briefly unavailable during eventual-consistency windows.
159
- }
131
+ const status = await client.scans.status(scanId);
132
+ const needsTerminalHydration = status.status === "completed" || status.status === "completed_limited";
133
+ if (needsTerminalHydration) {
134
+ try {
135
+ const scan = await client.scans.get(scanId);
136
+ return toToolResult(withMcpAgentGuidance({
137
+ ...status,
138
+ type: "certscore_scan_job",
139
+ status: scan.status,
140
+ domain: scan.domain,
141
+ url: scan.url ?? null,
142
+ resultDisposition: scan.resultDisposition,
143
+ noGo: scan.noGo,
144
+ createdAt: scan.createdAt ?? null,
145
+ startedAt: scan.startedAt,
146
+ completedAt: scan.completedAt,
147
+ scanTimeSeconds: scan.scanTimeSeconds,
148
+ score: scan.score ?? null,
149
+ scoreStatus: scan.scoreStatus,
150
+ scoreVersion: scan.scoreVersion ?? null,
151
+ scoreUpdatedAt: scan.scoreUpdatedAt ?? null,
152
+ riskLevel: scan.riskLevel ?? null,
153
+ coverage: scan.coverage ?? null,
154
+ reportUrl: scan.links?.report ?? status.reportUrl ?? null,
155
+ links: { ...status.links, ...scan.links }
156
+ }));
157
+ }
158
+ catch {
159
+ // Preserve the API status response if the terminal scan resource is
160
+ // briefly unavailable during eventual-consistency windows.
160
161
  }
161
- return toToolResult(status);
162
- }
163
- if (!jobId) {
164
- return toToolResult({
165
- error: {
166
- name: "InvalidToolInput",
167
- message: "Provide either scanId for API v2 scan status or jobId for Pulse job status."
168
- }
169
- });
170
162
  }
171
- const status = await client.getJobStatus(jobId);
172
- return toToolResult({
173
- ...status,
174
- scanId: scanIdFromStatus(status)
175
- });
163
+ return toToolResult(withMcpAgentGuidance(status));
176
164
  }
177
165
  catch (error) {
178
166
  return toToolError(error);
179
167
  }
180
168
  });
181
- registerTool("get_report", toolContract("get_report"), async ({ scanId, detail, format }) => {
169
+ registerTool("certscore_get_report", toolContract("certscore_get_report"), async ({ scanId, detail, format }) => {
182
170
  try {
183
171
  const normalizedFormat = normalizeFormat(format);
184
172
  const result = normalizedFormat === "markdown"
@@ -196,7 +184,7 @@ export function createCertScoreMcpServer(options = {}) {
196
184
  return toToolError(error);
197
185
  }
198
186
  });
199
- registerTool("get_evidence", toolContract("get_evidence"), async ({ scanId }) => {
187
+ registerTool("certscore_get_evidence", toolContract("certscore_get_evidence"), async ({ scanId }) => {
200
188
  try {
201
189
  return toToolResult(boundEvidencePacket(await client.getScan(scanId, { detail: "evidence", format: "json" })));
202
190
  }
@@ -204,18 +192,37 @@ export function createCertScoreMcpServer(options = {}) {
204
192
  return toToolError(error);
205
193
  }
206
194
  });
207
- registerTool("get_scan_bundle", toolContract("get_scan_bundle"), async ({ scanId, maxFindings, maxPreConsentRows }) => {
195
+ registerTool("certscore_get_scan_bundle", toolContract("certscore_get_scan_bundle"), async ({ scanId, detail = "summary", maxBytes, maxFindings, maxPreConsentRows }) => {
208
196
  try {
209
- const [scan, report, evidence, findings, preConsentCookiesTrackers] = await Promise.all([
210
- client.scans.get(scanId),
211
- client.getScan(scanId, { detail: "summary", format: "json" }),
212
- client.getScan(scanId, { detail: "evidence", format: "json" }),
213
- client.findings.list(scanId),
214
- client.scans.preConsentCookiesTrackers(scanId)
197
+ const scan = await retryTransientOriginFailure(() => client.scans.get(scanId));
198
+ if (scan.status === "completed_limited" && scan.resultDisposition === "no_go") {
199
+ return toToolResult(buildScanBundle({
200
+ detail,
201
+ evidence: null,
202
+ findings: { type: "certscore_finding_list", scanId, findings: [] },
203
+ maxBytes,
204
+ maxFindings,
205
+ maxPreConsentRows,
206
+ preConsentCookiesTrackers: null,
207
+ report: null,
208
+ scan
209
+ }));
210
+ }
211
+ const includeEvidence = detail === "evidence" || detail === "full";
212
+ const reportDetail = detail === "full" ? "full" : includeEvidence ? "evidence" : "summary";
213
+ const [report, findings, preConsentCookiesTrackers] = await Promise.all([
214
+ retryTransientOriginFailure(() => client.getScan(scanId, { detail: reportDetail, format: "json" })),
215
+ retryTransientOriginFailure(() => client.findings.list(scanId)),
216
+ includeEvidence
217
+ ? retryTransientOriginFailure(() => client.scans.preConsentCookiesTrackers(scanId))
218
+ : Promise.resolve(null)
215
219
  ]);
220
+ const evidence = includeEvidence ? report : null;
216
221
  return toToolResult(buildScanBundle({
222
+ detail,
217
223
  evidence,
218
224
  findings,
225
+ maxBytes,
219
226
  maxFindings,
220
227
  maxPreConsentRows,
221
228
  preConsentCookiesTrackers,
@@ -227,7 +234,7 @@ export function createCertScoreMcpServer(options = {}) {
227
234
  return toToolError(error);
228
235
  }
229
236
  });
230
- registerTool("export_findings", toolContract("export_findings"), async ({ scanId }) => {
237
+ registerTool("certscore_export_findings", toolContract("certscore_export_findings"), async ({ scanId }) => {
231
238
  try {
232
239
  const report = await client.getScan(scanId, { detail: "full", format: "json" });
233
240
  return toToolResult(exportFindings(report));
@@ -236,7 +243,7 @@ export function createCertScoreMcpServer(options = {}) {
236
243
  return toToolError(error);
237
244
  }
238
245
  });
239
- registerTool("list_findings", toolContract("list_findings"), async ({ limit, offset, scanId }) => {
246
+ registerTool("certscore_list_findings", toolContract("certscore_list_findings"), async ({ limit, offset, scanId }) => {
240
247
  try {
241
248
  return toToolResult(paginateFindingList(await client.findings.list(scanId), { limit, offset }));
242
249
  }
@@ -244,7 +251,7 @@ export function createCertScoreMcpServer(options = {}) {
244
251
  return toToolError(error);
245
252
  }
246
253
  });
247
- registerTool("get_pre_consent_cookies_trackers", toolContract("get_pre_consent_cookies_trackers"), async ({ maxRows, scanId }) => {
254
+ registerTool("certscore_get_pre_consent_cookies_trackers", toolContract("certscore_get_pre_consent_cookies_trackers"), async ({ maxRows, scanId }) => {
248
255
  try {
249
256
  return toToolResult(limitPreConsentRows(await client.scans.preConsentCookiesTrackers(scanId), { maxRows }));
250
257
  }
@@ -252,7 +259,7 @@ export function createCertScoreMcpServer(options = {}) {
252
259
  return toToolError(error);
253
260
  }
254
261
  });
255
- registerTool("explain_finding", toolContract("explain_finding"), async ({ scanId, findingId }) => {
262
+ registerTool("certscore_explain_finding", toolContract("certscore_explain_finding"), async ({ scanId, findingId }) => {
256
263
  try {
257
264
  return toToolResult(await client.findings.explain(scanId, findingId));
258
265
  }
@@ -260,7 +267,7 @@ export function createCertScoreMcpServer(options = {}) {
260
267
  return toToolError(error);
261
268
  }
262
269
  });
263
- registerTool("get_latest_domain_scan", toolContract("get_latest_domain_scan"), async ({ domain, scanFrom }) => {
270
+ registerTool("certscore_get_latest_domain_scan", toolContract("certscore_get_latest_domain_scan"), async ({ domain, scanFrom }) => {
264
271
  try {
265
272
  return toToolResult(await client.domains.latest(domain, { scanFrom }));
266
273
  }
@@ -268,7 +275,7 @@ export function createCertScoreMcpServer(options = {}) {
268
275
  return toToolError(error);
269
276
  }
270
277
  });
271
- registerTool("get_latest_domain_pre_consent_cookies_trackers", toolContract("get_latest_domain_pre_consent_cookies_trackers"), async ({ domain, maxRows, scanFrom }) => {
278
+ registerTool("certscore_get_latest_domain_pre_consent_cookies_trackers", toolContract("certscore_get_latest_domain_pre_consent_cookies_trackers"), async ({ domain, maxRows, scanFrom }) => {
272
279
  try {
273
280
  return toToolResult(limitPreConsentRows(await client.domains.latestPreConsentCookiesTrackers(domain, { scanFrom }), { maxRows }));
274
281
  }
package/dist/tools.d.ts CHANGED
@@ -1,8 +1,22 @@
1
1
  import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
2
  import { type FindingList, type JobStatus, type PreConsentCookiesTrackers, type PulseDetail, type PulseFormat, type PulseResult, type ScanResource, type TopFinding } from "@certscore/sdk";
3
3
  export declare const MAX_EVIDENCE_PACKET_CHARS = 250000;
4
+ type ActionableError = {
5
+ code: string;
6
+ message: string;
7
+ retryable: boolean;
8
+ retryAfterSeconds: number | null;
9
+ recommendedNextAction: string;
10
+ field?: string;
11
+ mcpCode?: number;
12
+ };
4
13
  export declare function toToolResult(payload: unknown): CallToolResult;
5
14
  export declare function toToolError(error: unknown): CallToolResult;
15
+ export declare function toInvalidArgumentsToolError(errorMessage: string): CallToolResult;
16
+ export declare function withMcpAgentGuidance<T extends Record<string, any>>(value: T): T & {
17
+ error: ActionableError | null;
18
+ observationOnlyDisclaimer: string;
19
+ };
6
20
  export declare function boundEvidencePacket<T>(payload: T, maxSerializedChars?: number): T | Record<string, unknown>;
7
21
  export declare function normalizeDetail(detail: PulseDetail | undefined): PulseDetail;
8
22
  export declare function normalizeFormat(format: PulseFormat | undefined): PulseFormat;
@@ -38,68 +52,16 @@ export declare function limitPreConsentRows<T extends Record<string, unknown>>(p
38
52
  maxRows?: number;
39
53
  }): T;
40
54
  export declare function buildScanBundle(input: {
41
- evidence: PulseResult;
55
+ detail?: "summary" | "findings" | "evidence" | "full";
56
+ evidence?: PulseResult | null;
42
57
  findings: FindingList;
43
58
  maxFindings?: number;
59
+ maxBytes?: number;
44
60
  maxPreConsentRows?: number;
45
- preConsentCookiesTrackers: PreConsentCookiesTrackers;
46
- report: PulseResult;
61
+ preConsentCookiesTrackers?: PreConsentCookiesTrackers | null;
62
+ report: PulseResult | null;
47
63
  scan: ScanResource;
48
- }): {
49
- type: string;
50
- scanId: string;
51
- status: import("packages/certscore-sdk/dist/types.js").PulseJobStatus;
52
- resultDisposition: "no_go" | null;
53
- noGo: import("@certscore/sdk").ScanNoGoResult | null;
54
- scan: ScanResource;
55
- summary: {
56
- summary: {} | null;
57
- executiveSummary: {} | null;
58
- counts: {} | null;
59
- coverage: {} | null;
60
- agentInterpretation: {} | null;
61
- };
62
- findings: import("packages/certscore-sdk/dist/types.js").FindingSummary[];
63
- findingsMetadata: {
64
- shown: number;
65
- total: number;
66
- truncated: boolean;
67
- };
68
- evidenceSummary: {
69
- evidenceSafetyNotes: {} | null;
70
- projectionDiagnostics: {} | null;
71
- projectedFindings: unknown;
72
- coverageDiagnostics: unknown;
73
- policySurfaceCoverage: unknown;
74
- };
75
- preConsentCookiesTrackers: {
76
- summary: {
77
- [key: string]: unknown;
78
- rowCount: number;
79
- trackerCount: number;
80
- cookieCount: number;
81
- requestCount: number;
82
- totalRowCount?: number;
83
- truncated?: boolean;
84
- };
85
- rows: import("packages/certscore-sdk/dist/types.js").PreConsentCookiesTrackersRow[];
86
- shown: number;
87
- total: number;
88
- truncated: boolean;
89
- };
90
- links: {
91
- [key: string]: string | undefined;
92
- self?: string;
93
- status?: string;
94
- findings?: string;
95
- pulse?: string;
96
- report?: string;
97
- latestDomainScan?: string;
98
- docs?: string;
99
- };
100
- recommendedNextTool: string | null;
101
- disclaimer: string | null;
102
- };
64
+ }): Record<string, any>;
103
65
  export declare function explainFinding(report: PulseResult, findingId: string): {
104
66
  type: string;
105
67
  scanId: string | null;
@@ -143,4 +105,5 @@ export declare function explainFinding(report: PulseResult, findingId: string):
143
105
  message?: undefined;
144
106
  availableFindingIds?: undefined;
145
107
  };
108
+ export {};
146
109
  //# sourceMappingURL=tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,yBAAyB,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5M,eAAO,MAAM,yBAAyB,SAAU,CAAC;AAKjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAa7D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA0B1D;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,kBAAkB,SAA4B,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0C9H;AA6ID,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,CAE5E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,CAE5E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,iBAEjD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,iBAGlD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,EAAE,CAQpE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;EAsBjD;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,OAAO,EAAE,CAAC,EACV,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,CAAC,CAoBH;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,OAAO,EAAE,CAAC,EACV,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjC,CAAC,CAiBH;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,yBAAyB,CAAC;IACrD,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmEA;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCpE"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}