@frase/mcp-server 0.3.6 → 0.3.8
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/CHANGELOG.md +10 -0
- package/dist/content-types-config-mirror.d.ts +75 -0
- package/dist/content-types-config-mirror.d.ts.map +1 -0
- package/dist/content-types-config-mirror.js +75 -0
- package/dist/content-types-config-mirror.js.map +1 -0
- package/dist/content-types.d.ts +3 -3
- package/dist/content-types.d.ts.map +1 -1
- package/dist/content-types.js +4 -2
- package/dist/content-types.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/clean-render.d.ts +42 -0
- package/dist/lib/clean-render.d.ts.map +1 -0
- package/dist/lib/clean-render.js +126 -0
- package/dist/lib/clean-render.js.map +1 -0
- package/dist/prompts/content-pipeline.d.ts.map +1 -1
- package/dist/prompts/content-pipeline.js +5 -2
- package/dist/prompts/content-pipeline.js.map +1 -1
- package/dist/prompts/create-seo-article.d.ts.map +1 -1
- package/dist/prompts/create-seo-article.js +5 -2
- package/dist/prompts/create-seo-article.js.map +1 -1
- package/dist/tools/ai-visibility.d.ts +14 -0
- package/dist/tools/ai-visibility.d.ts.map +1 -1
- package/dist/tools/ai-visibility.js +296 -0
- package/dist/tools/ai-visibility.js.map +1 -1
- package/dist/tools/briefs.d.ts +6 -6
- package/dist/tools/cms-posts.d.ts +2 -0
- package/dist/tools/cms-posts.d.ts.map +1 -1
- package/dist/tools/cms-posts.js +62 -11
- package/dist/tools/cms-posts.js.map +1 -1
- package/dist/tools/index.d.ts +7 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +16 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/serp.d.ts.map +1 -1
- package/dist/tools/serp.js +17 -13
- package/dist/tools/serp.js.map +1 -1
- package/package.json +12 -5
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.7] - 2026-06-04
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `analyze_serp`: People Also Ask entries rendered as `[object Object]` and several fields showed `undefined`. PAA questions and result fields now render correctly.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Bumped `@frase/core` dependency to `0.1.5`, which adds the `ToolResult.hidden`/`reason` hide-mirror fields and `McpToolDefinition.inputSchema.additionalProperties` that the AI-visibility tools rely on. (The tools had used these since late May, but core was never republished — the build only typechecks at publish time, so it surfaced now.)
|
|
15
|
+
- Updated runtime dependencies (`hono`, `@modelcontextprotocol/sdk`) and upgraded the test toolchain (`vitest` 2.x → 4.x) to clear a critical security advisory.
|
|
16
|
+
- `server.json` `version` (and its nested npm package `version`) corrected from `0.3.5` to track the package version — it had drifted behind `package.json`/`manifest.json` since 0.3.6.
|
|
17
|
+
|
|
8
18
|
## [0.3.6] - 2026-05-18
|
|
9
19
|
|
|
10
20
|
### Added
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-package mirror of the per-content-type JSON Schemas emitted by
|
|
3
|
+
* `src/lib/content/content-type-configs/*` in the main Next.js app.
|
|
4
|
+
*
|
|
5
|
+
* Cross-package import is blocked: the MCP server publishes as its own
|
|
6
|
+
* npm package and cannot reach into the main app's Next.js source. This
|
|
7
|
+
* constant MUST stay in sync with `src/lib/content/content-type-configs/tool-review.ts`.
|
|
8
|
+
*
|
|
9
|
+
* A parity contract test asserts deep-equality against the live
|
|
10
|
+
* `contentTypeConfigRegistry.tool_review.jsonSchema` produced by zod 4's
|
|
11
|
+
* `z.toJSONSchema()`:
|
|
12
|
+
* src/lib/content/content-type-configs/__tests__/mcp-parity.test.ts
|
|
13
|
+
*
|
|
14
|
+
* If you change the Zod schema in the main app, regenerate this constant
|
|
15
|
+
* by running (from repo root):
|
|
16
|
+
* npx tsx -e "import('./src/lib/content/content-type-configs/tool-review').then(m => console.log(JSON.stringify((m.default ?? m).toolReviewConfigModule.jsonSchema, null, 2)))"
|
|
17
|
+
* and paste the output below verbatim. The contract test will fail until
|
|
18
|
+
* the mirror is updated.
|
|
19
|
+
*/
|
|
20
|
+
export declare const TOOL_REVIEW_JSON_SCHEMA: {
|
|
21
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
22
|
+
readonly type: "object";
|
|
23
|
+
readonly properties: {
|
|
24
|
+
readonly rating: {
|
|
25
|
+
readonly type: "number";
|
|
26
|
+
readonly minimum: 0;
|
|
27
|
+
readonly maximum: 5;
|
|
28
|
+
};
|
|
29
|
+
readonly prosList: {
|
|
30
|
+
readonly default: readonly [];
|
|
31
|
+
readonly type: "array";
|
|
32
|
+
readonly items: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
readonly minLength: 1;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
readonly consList: {
|
|
38
|
+
readonly default: readonly [];
|
|
39
|
+
readonly type: "array";
|
|
40
|
+
readonly items: {
|
|
41
|
+
readonly type: "string";
|
|
42
|
+
readonly minLength: 1;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
readonly pricingNote: {
|
|
46
|
+
readonly type: "string";
|
|
47
|
+
readonly minLength: 1;
|
|
48
|
+
};
|
|
49
|
+
readonly verdictSummary: {
|
|
50
|
+
readonly type: "string";
|
|
51
|
+
readonly minLength: 1;
|
|
52
|
+
};
|
|
53
|
+
readonly toolCategory: {
|
|
54
|
+
readonly type: "string";
|
|
55
|
+
readonly minLength: 1;
|
|
56
|
+
};
|
|
57
|
+
readonly toolOS: {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
readonly minLength: 1;
|
|
60
|
+
};
|
|
61
|
+
readonly aggregateRatingValue: {
|
|
62
|
+
readonly type: "number";
|
|
63
|
+
readonly minimum: 0;
|
|
64
|
+
readonly maximum: 5;
|
|
65
|
+
};
|
|
66
|
+
readonly aggregateRatingCount: {
|
|
67
|
+
readonly type: "integer";
|
|
68
|
+
readonly minimum: 0;
|
|
69
|
+
readonly maximum: 9007199254740991;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
readonly required: readonly ["rating", "prosList", "consList"];
|
|
73
|
+
readonly additionalProperties: false;
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=content-types-config-mirror.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-types-config-mirror.d.ts","sourceRoot":"","sources":["../src/content-types-config-mirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsD1B,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-package mirror of the per-content-type JSON Schemas emitted by
|
|
3
|
+
* `src/lib/content/content-type-configs/*` in the main Next.js app.
|
|
4
|
+
*
|
|
5
|
+
* Cross-package import is blocked: the MCP server publishes as its own
|
|
6
|
+
* npm package and cannot reach into the main app's Next.js source. This
|
|
7
|
+
* constant MUST stay in sync with `src/lib/content/content-type-configs/tool-review.ts`.
|
|
8
|
+
*
|
|
9
|
+
* A parity contract test asserts deep-equality against the live
|
|
10
|
+
* `contentTypeConfigRegistry.tool_review.jsonSchema` produced by zod 4's
|
|
11
|
+
* `z.toJSONSchema()`:
|
|
12
|
+
* src/lib/content/content-type-configs/__tests__/mcp-parity.test.ts
|
|
13
|
+
*
|
|
14
|
+
* If you change the Zod schema in the main app, regenerate this constant
|
|
15
|
+
* by running (from repo root):
|
|
16
|
+
* npx tsx -e "import('./src/lib/content/content-type-configs/tool-review').then(m => console.log(JSON.stringify((m.default ?? m).toolReviewConfigModule.jsonSchema, null, 2)))"
|
|
17
|
+
* and paste the output below verbatim. The contract test will fail until
|
|
18
|
+
* the mirror is updated.
|
|
19
|
+
*/
|
|
20
|
+
export const TOOL_REVIEW_JSON_SCHEMA = {
|
|
21
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
rating: {
|
|
25
|
+
type: "number",
|
|
26
|
+
minimum: 0,
|
|
27
|
+
maximum: 5,
|
|
28
|
+
},
|
|
29
|
+
prosList: {
|
|
30
|
+
default: [],
|
|
31
|
+
type: "array",
|
|
32
|
+
items: {
|
|
33
|
+
type: "string",
|
|
34
|
+
minLength: 1,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
consList: {
|
|
38
|
+
default: [],
|
|
39
|
+
type: "array",
|
|
40
|
+
items: {
|
|
41
|
+
type: "string",
|
|
42
|
+
minLength: 1,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
pricingNote: {
|
|
46
|
+
type: "string",
|
|
47
|
+
minLength: 1,
|
|
48
|
+
},
|
|
49
|
+
verdictSummary: {
|
|
50
|
+
type: "string",
|
|
51
|
+
minLength: 1,
|
|
52
|
+
},
|
|
53
|
+
toolCategory: {
|
|
54
|
+
type: "string",
|
|
55
|
+
minLength: 1,
|
|
56
|
+
},
|
|
57
|
+
toolOS: {
|
|
58
|
+
type: "string",
|
|
59
|
+
minLength: 1,
|
|
60
|
+
},
|
|
61
|
+
aggregateRatingValue: {
|
|
62
|
+
type: "number",
|
|
63
|
+
minimum: 0,
|
|
64
|
+
maximum: 5,
|
|
65
|
+
},
|
|
66
|
+
aggregateRatingCount: {
|
|
67
|
+
type: "integer",
|
|
68
|
+
minimum: 0,
|
|
69
|
+
maximum: 9007199254740991,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
required: ["rating", "prosList", "consList"],
|
|
73
|
+
additionalProperties: false,
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=content-types-config-mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-types-config-mirror.js","sourceRoot":"","sources":["../src/content-types-config-mirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO,EAAE,8CAA8C;IACvD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,CAAC;aACb;SACF;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,CAAC;aACb;SACF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;SACb;QACD,cAAc,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;SACb;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;SACb;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;SACb;QACD,oBAAoB,EAAE;YACpB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX;QACD,oBAAoB,EAAE;YACpB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,gBAAgB;SAC1B;KACF;IACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC;IAC5C,oBAAoB,EAAE,KAAK;CACnB,CAAC"}
|
package/dist/content-types.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The 18-type content taxonomy used by the Frase platform.
|
|
3
3
|
*
|
|
4
4
|
* This is the canonical list of values the `/api/v1/briefs` endpoint
|
|
5
5
|
* accepts in `content_type`. The API also accepts legacy 5-bucket
|
|
6
6
|
* values (`blog`, `guide`, `landing`, `product`, `comparison`) for
|
|
7
7
|
* back-compat and normalizes them at the boundary, but new MCP
|
|
8
|
-
* integrations should use these
|
|
8
|
+
* integrations should use these 18 values directly.
|
|
9
9
|
*
|
|
10
10
|
* Keep this list in lockstep with `src/lib/core/content-types.ts`
|
|
11
11
|
* in the main app. We can't import from there because the MCP server
|
|
12
12
|
* publishes as its own npm package and can't reach into Next.js source.
|
|
13
13
|
*/
|
|
14
|
-
export declare const CONTENT_TYPES: readonly ["blog_post", "page", "faq", "glossary", "comparison", "pillar", "how_to", "landing", "listicle", "case_study", "tutorial", "news", "product_update", "data_report", "event", "resource"];
|
|
14
|
+
export declare const CONTENT_TYPES: readonly ["blog_post", "page", "faq", "glossary", "comparison", "pillar", "how_to", "landing", "listicle", "case_study", "tutorial", "news", "product_update", "data_report", "event", "resource", "alternative", "tool_review"];
|
|
15
15
|
export type ContentType = (typeof CONTENT_TYPES)[number];
|
|
16
16
|
//# sourceMappingURL=content-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-types.d.ts","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"content-types.d.ts","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,kOAmBhB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/content-types.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The 18-type content taxonomy used by the Frase platform.
|
|
3
3
|
*
|
|
4
4
|
* This is the canonical list of values the `/api/v1/briefs` endpoint
|
|
5
5
|
* accepts in `content_type`. The API also accepts legacy 5-bucket
|
|
6
6
|
* values (`blog`, `guide`, `landing`, `product`, `comparison`) for
|
|
7
7
|
* back-compat and normalizes them at the boundary, but new MCP
|
|
8
|
-
* integrations should use these
|
|
8
|
+
* integrations should use these 18 values directly.
|
|
9
9
|
*
|
|
10
10
|
* Keep this list in lockstep with `src/lib/core/content-types.ts`
|
|
11
11
|
* in the main app. We can't import from there because the MCP server
|
|
@@ -28,5 +28,7 @@ export const CONTENT_TYPES = [
|
|
|
28
28
|
"data_report",
|
|
29
29
|
"event",
|
|
30
30
|
"resource",
|
|
31
|
+
"alternative",
|
|
32
|
+
"tool_review",
|
|
31
33
|
];
|
|
32
34
|
//# sourceMappingURL=content-types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-types.js","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW;IACX,MAAM;IACN,KAAK;IACL,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,UAAU;IACV,YAAY;IACZ,UAAU;IACV,MAAM;IACN,gBAAgB;IAChB,aAAa;IACb,OAAO;IACP,UAAU;
|
|
1
|
+
{"version":3,"file":"content-types.js","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW;IACX,MAAM;IACN,KAAK;IACL,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,UAAU;IACV,YAAY;IACZ,UAAU;IACV,MAAM;IACN,gBAAgB;IAChB,aAAa;IACb,OAAO;IACP,UAAU;IACV,aAAa;IACb,aAAa;CACL,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ import { ALL_RESOURCE_TEMPLATES, listAllResources, readResource, getRootResource
|
|
|
65
65
|
import { ALL_PROMPTS, getPromptByName, getPromptMessages, } from "./prompts/index.js";
|
|
66
66
|
// Server metadata
|
|
67
67
|
const SERVER_NAME = "frase-mcp-server";
|
|
68
|
-
const SERVER_VERSION = "0.3.
|
|
68
|
+
const SERVER_VERSION = "0.3.7";
|
|
69
69
|
/**
|
|
70
70
|
* Main MCP server class
|
|
71
71
|
*/
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ToolExecutor } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Detects "the tool ran successfully but shipped garbage" — the class of bug
|
|
4
|
+
* where an object is coerced into markdown as `[object Object]`, or a leaked
|
|
5
|
+
* `undefined`/`NaN` lands in rendered prose. (Real example: People Also Ask
|
|
6
|
+
* entries rendered as `[object Object]` to every user, found only via a
|
|
7
|
+
* customer report.)
|
|
8
|
+
*
|
|
9
|
+
* In tests/CI a dirty render throws (pre-merge gate). In real traffic it never
|
|
10
|
+
* throws — it emits a structured warning and returns the result unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export interface RenderIssue {
|
|
13
|
+
/** The offending token, e.g. "[object Object]", "undefined", "empty-table". */
|
|
14
|
+
pattern: string;
|
|
15
|
+
/** A short slice of surrounding text, for the warning/error message. */
|
|
16
|
+
snippet: string;
|
|
17
|
+
}
|
|
18
|
+
export interface AssertCleanRenderOpts {
|
|
19
|
+
/**
|
|
20
|
+
* Set for `success: false` results — only the `[object …]` check runs, since
|
|
21
|
+
* error messages may legitimately mention "undefined"/"NaN".
|
|
22
|
+
*/
|
|
23
|
+
errorResult?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare class CleanRenderError extends Error {
|
|
26
|
+
readonly toolName: string;
|
|
27
|
+
readonly issues: RenderIssue[];
|
|
28
|
+
constructor(toolName: string, issues: RenderIssue[]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns the render defects found in `markdown` (empty array = clean). Pure;
|
|
32
|
+
* conservative by design — tuned to catch the real bug class with near-zero
|
|
33
|
+
* false positives on legitimate empty-state output.
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertCleanRender(markdown: string, opts?: AssertCleanRenderOpts): RenderIssue[];
|
|
36
|
+
/**
|
|
37
|
+
* Wraps a tool executor so its rendered markdown is validated on every call.
|
|
38
|
+
* Applied at the `TOOL_EXECUTORS` chokepoint, so it covers every tool on both
|
|
39
|
+
* the stdio and in-app HTTP surfaces. Never alters the result.
|
|
40
|
+
*/
|
|
41
|
+
export declare function withCleanRender(toolName: string, executor: ToolExecutor): ToolExecutor;
|
|
42
|
+
//# sourceMappingURL=clean-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean-render.d.ts","sourceRoot":"","sources":["../../src/lib/clean-render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAgBD,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,WAAW,EAAE;gBADrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EAAE;CAQxC;AAyBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,qBAA0B,GAC/B,WAAW,EAAE,CA0Df;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GACrB,YAAY,CAmBd"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throw on a dirty render instead of warning. Tests, CI, and the scheduled
|
|
3
|
+
* synthetic smoke opt in; real stdio (customer machine) and in-app HTTP traffic
|
|
4
|
+
* never throw — a bad render must not break a live tool call. Evaluated per
|
|
5
|
+
* call so the environment can be toggled (e.g. in tests).
|
|
6
|
+
*/
|
|
7
|
+
function isRenderStrict() {
|
|
8
|
+
return (!!process.env.VITEST ||
|
|
9
|
+
process.env.NODE_ENV === "test" ||
|
|
10
|
+
process.env.FRASE_RENDER_STRICT === "1");
|
|
11
|
+
}
|
|
12
|
+
export class CleanRenderError extends Error {
|
|
13
|
+
toolName;
|
|
14
|
+
issues;
|
|
15
|
+
constructor(toolName, issues) {
|
|
16
|
+
super(`Tool "${toolName}" produced a dirty render: ` +
|
|
17
|
+
issues.map((i) => `${i.pattern} (…${i.snippet}…)`).join("; "));
|
|
18
|
+
this.toolName = toolName;
|
|
19
|
+
this.issues = issues;
|
|
20
|
+
this.name = "CleanRenderError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Blank out spans where these tokens are legitimate so they don't trip the
|
|
25
|
+
* scanner: fenced code blocks, inline code, and italic placeholders (the
|
|
26
|
+
* `_No results found._` empty-state convention, which `hidden: true` branches
|
|
27
|
+
* also use). Replaced with a space to preserve word boundaries around them.
|
|
28
|
+
*/
|
|
29
|
+
function stripSafeSpans(md) {
|
|
30
|
+
return md
|
|
31
|
+
.replace(/```[\s\S]*?```/g, " ")
|
|
32
|
+
.replace(/`[^`]*`/g, " ")
|
|
33
|
+
// NOTE: greedy `_…_` blanking can also blank a snake_case span in prose
|
|
34
|
+
// (e.g. `field_undefined_value`), which could mask a token sitting between
|
|
35
|
+
// two snake_case words. That's a false-negative only (we'd miss a defect),
|
|
36
|
+
// never a false-positive — acceptable for this conservative validator.
|
|
37
|
+
.replace(/_[^_]+_/g, " ");
|
|
38
|
+
}
|
|
39
|
+
function snippetAround(text, index, len) {
|
|
40
|
+
const start = Math.max(0, index - 30);
|
|
41
|
+
const end = Math.min(text.length, index + len + 30);
|
|
42
|
+
return text.slice(start, end).replace(/\s+/g, " ").trim();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns the render defects found in `markdown` (empty array = clean). Pure;
|
|
46
|
+
* conservative by design — tuned to catch the real bug class with near-zero
|
|
47
|
+
* false positives on legitimate empty-state output.
|
|
48
|
+
*/
|
|
49
|
+
export function assertCleanRender(markdown, opts = {}) {
|
|
50
|
+
const issues = [];
|
|
51
|
+
if (!markdown)
|
|
52
|
+
return issues;
|
|
53
|
+
// A coerced object is always a bug — even inside code or error messages.
|
|
54
|
+
const objMatch = markdown.match(/\[object \w+\]/);
|
|
55
|
+
if (objMatch) {
|
|
56
|
+
issues.push({
|
|
57
|
+
pattern: objMatch[0],
|
|
58
|
+
snippet: snippetAround(markdown, objMatch.index ?? 0, objMatch[0].length),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Error results legitimately mention "undefined"/"NaN"; stop after the
|
|
62
|
+
// object check above.
|
|
63
|
+
if (opts.errorResult)
|
|
64
|
+
return issues;
|
|
65
|
+
const stripped = stripSafeSpans(markdown);
|
|
66
|
+
// Leaked `undefined`/`NaN` — but ONLY in a formatted-value position, never in
|
|
67
|
+
// free prose. Many tools pass verbatim user/LLM text through (article bodies,
|
|
68
|
+
// brief sections, descriptions) that legitimately contains the words
|
|
69
|
+
// "undefined"/"NaN"; scanning prose would false-positive and, in strict mode,
|
|
70
|
+
// throw on a valid tool call. So we anchor to where the formatter emits a
|
|
71
|
+
// value: a table cell, a bold "key:" value, a colon-terminated heading/label,
|
|
72
|
+
// or a bare list item. Case-sensitive — JS coercion yields exactly these.
|
|
73
|
+
// `null` is deliberately not checked (pervasive in legit JSON/prose).
|
|
74
|
+
const SCAFFOLD_TOKEN_RES = [
|
|
75
|
+
/\|\s*(undefined|NaN)\s*(?=\|)/g, // | undefined | (table cell)
|
|
76
|
+
/:\*\*\s*(undefined|NaN)\b/g, // **Key:** undefined
|
|
77
|
+
/:[^\S\n]*(undefined|NaN)[^\S\n]*$/gm, // ## Heading: undefined / Label: undefined
|
|
78
|
+
/^[^\S\n]*[-*][^\S\n]+(undefined|NaN)[^\S\n]*$/gm, // - undefined (bare list value)
|
|
79
|
+
];
|
|
80
|
+
for (const re of SCAFFOLD_TOKEN_RES) {
|
|
81
|
+
let m;
|
|
82
|
+
while ((m = re.exec(stripped)) !== null) {
|
|
83
|
+
issues.push({
|
|
84
|
+
pattern: m[1],
|
|
85
|
+
snippet: snippetAround(stripped, m.index, m[0].length),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// A markdown table separator row with no data row after it. `formatTable()`
|
|
90
|
+
// guards this, but a hand-rolled table can still emit an empty grid.
|
|
91
|
+
const lines = stripped.split("\n");
|
|
92
|
+
const separatorRe = /^\s*\|(?:\s*:?-+:?\s*\|)+\s*$/;
|
|
93
|
+
for (let i = 0; i < lines.length; i++) {
|
|
94
|
+
if (separatorRe.test(lines[i])) {
|
|
95
|
+
const next = lines[i + 1];
|
|
96
|
+
const nextIsRow = next !== undefined && /^\s*\|/.test(next);
|
|
97
|
+
if (!nextIsRow) {
|
|
98
|
+
issues.push({ pattern: "empty-table", snippet: lines[i].trim() });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return issues;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wraps a tool executor so its rendered markdown is validated on every call.
|
|
106
|
+
* Applied at the `TOOL_EXECUTORS` chokepoint, so it covers every tool on both
|
|
107
|
+
* the stdio and in-app HTTP surfaces. Never alters the result.
|
|
108
|
+
*/
|
|
109
|
+
export function withCleanRender(toolName, executor) {
|
|
110
|
+
return async (input, context) => {
|
|
111
|
+
const result = await executor(input, context);
|
|
112
|
+
const issues = assertCleanRender(result.markdown ?? "", {
|
|
113
|
+
errorResult: !result.success,
|
|
114
|
+
});
|
|
115
|
+
if (issues.length > 0) {
|
|
116
|
+
if (isRenderStrict()) {
|
|
117
|
+
throw new CleanRenderError(toolName, issues);
|
|
118
|
+
}
|
|
119
|
+
// Structured warning → Sentry Logs via consoleLoggingIntegration on the
|
|
120
|
+
// in-app surface; visible in stderr on the stdio surface.
|
|
121
|
+
console.warn("mcp_dirty_render", JSON.stringify({ tool: toolName, issues }));
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=clean-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean-render.js","sourceRoot":"","sources":["../../src/lib/clean-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-pipeline.d.ts","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"content-pipeline.d.ts","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,mBAwCnC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC9E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,CAoDD"}
|
|
@@ -34,7 +34,10 @@ export const contentPipelinePrompt = {
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
name: "content_type",
|
|
37
|
-
description: "
|
|
37
|
+
description: "Canonical content type (one of 18) — e.g. blog_post, how_to, listicle, " +
|
|
38
|
+
"case_study, tutorial, comparison, alternative, tool_review, pillar, landing, " +
|
|
39
|
+
"faq, glossary, news, product_update, data_report, event, resource, page. " +
|
|
40
|
+
"Default: blog_post. See create_brief for the enum.",
|
|
38
41
|
required: false,
|
|
39
42
|
},
|
|
40
43
|
{
|
|
@@ -53,7 +56,7 @@ export function getContentPipelineMessages(args) {
|
|
|
53
56
|
const topic = args.topic || "the requested topic";
|
|
54
57
|
const siteId = args.site_id || "";
|
|
55
58
|
const targetScore = args.target_score || "70";
|
|
56
|
-
const contentType = args.content_type || "
|
|
59
|
+
const contentType = args.content_type || "blog_post";
|
|
57
60
|
const targetLanguage = args.target_language || "en";
|
|
58
61
|
const targetCountry = args.target_country || "us";
|
|
59
62
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-pipeline.js","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,mNAAmN;IACrN,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,0EAA0E;YACvF,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,
|
|
1
|
+
{"version":3,"file":"content-pipeline.js","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,mNAAmN;IACrN,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,0EAA0E;YACvF,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,yEAAyE;gBACzE,+EAA+E;gBAC/E,2EAA2E;gBAC3E,oDAAoD;YACtD,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,iBAAiB;YACvB,WAAW,EAAE,iFAAiF;YAC9F,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,6EAA6E;YAC1F,QAAQ,EAAE,KAAK;SAChB;KACF;CACF,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,IAA4B;IAIrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;IACpD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC;IAElD,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,sCAAsC,KAAK;;;aAG5C,MAAM;kBACD,WAAW;+BACE,WAAW;cAC5B,cAAc;aACf,aAAa;;;;wDAI8B,KAAK,kBAAkB,MAAM;;;;mBAIlE,WAAW;;;;;;0BAMJ,WAAW;;;;;+DAK0B,MAAM,iKAAiK,MAAM;;4FAEhJ,KAAK,wDAAwD,KAAK;;;;;;;gCAO9H;aACzB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-seo-article.d.ts","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"create-seo-article.d.ts","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,sBAAsB,EAAE,mBA8BpC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC/E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,CA4DD"}
|
|
@@ -26,7 +26,10 @@ export const createSeoArticlePrompt = {
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
name: "content_type",
|
|
29
|
-
description: "
|
|
29
|
+
description: "Canonical content type (one of 18) — e.g. blog_post, how_to, listicle, " +
|
|
30
|
+
"case_study, tutorial, comparison, alternative, tool_review, pillar, landing, " +
|
|
31
|
+
"faq, glossary, news, product_update, data_report, event, resource, page. " +
|
|
32
|
+
"Default: blog_post. See create_brief for the enum.",
|
|
30
33
|
required: false,
|
|
31
34
|
},
|
|
32
35
|
{
|
|
@@ -38,7 +41,7 @@ export const createSeoArticlePrompt = {
|
|
|
38
41
|
};
|
|
39
42
|
export function getCreateSeoArticleMessages(args) {
|
|
40
43
|
const topic = args.topic || "the requested topic";
|
|
41
|
-
const contentType = args.content_type || "
|
|
44
|
+
const contentType = args.content_type || "blog_post";
|
|
42
45
|
const siteId = args.site_id || "";
|
|
43
46
|
const targetScore = args.target_score || "70";
|
|
44
47
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-seo-article.js","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,yPAAyP;IAC3P,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,+CAA+C;YAC5D,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,iGAAiG;YAC9G,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"create-seo-article.js","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,yPAAyP;IAC3P,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,+CAA+C;YAC5D,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,iGAAiG;YAC9G,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,yEAAyE;gBACzE,+EAA+E;gBAC/E,2EAA2E;gBAC3E,oDAAoD;YACtD,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,KAAK;SAChB;KACF;CACF,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,IAA4B;IAItE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;IAE9C,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,uDAAuD,KAAK;;;kBAGxD,WAAW;aAChB,MAAM;+BACY,WAAW;;;;6DAImB,KAAK,kBAAkB,MAAM;;;;sBAIpE,WAAW;;;;;;;;;;;;;;;;;;;6BAmBJ,WAAW;;;;;8CAKM,MAAM;0GACsD,MAAM;;;;4EAIpC,KAAK;;;uEAGV;aAChE;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Track how your content appears in AI-powered search results
|
|
5
5
|
*/
|
|
6
|
+
import { z } from "zod";
|
|
6
7
|
import type { McpToolDefinition, ToolContext, ToolResult } from "../types.js";
|
|
7
8
|
export declare const getAiVisibilityTool: McpToolDefinition;
|
|
8
9
|
export declare function executeGetAiVisibility(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
10
|
+
export declare const getIndustryBenchmarkTool: McpToolDefinition;
|
|
11
|
+
export declare function executeGetIndustryBenchmark(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
9
12
|
export declare const listPromptsTool: McpToolDefinition;
|
|
10
13
|
export declare function executeListPrompts(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
11
14
|
export declare const createPromptTool: McpToolDefinition;
|
|
@@ -22,6 +25,17 @@ export declare const getInsightsTool: McpToolDefinition;
|
|
|
22
25
|
export declare function executeGetInsights(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
23
26
|
export declare const getCrawlerLogsTool: McpToolDefinition;
|
|
24
27
|
export declare function executeGetCrawlerLogs(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
28
|
+
export declare const CITATION_FORMULA_FEATURE_LABELS: Record<string, string>;
|
|
29
|
+
export declare function citationFormulaLabelFor(featureName: string): string;
|
|
30
|
+
export declare const getCitationFormulaInputSchema: z.ZodObject<{
|
|
31
|
+
flavor: z.ZodDefault<z.ZodEnum<["active", "full"]>>;
|
|
32
|
+
}, "strict", z.ZodTypeAny, {
|
|
33
|
+
flavor: "full" | "active";
|
|
34
|
+
}, {
|
|
35
|
+
flavor?: "full" | "active" | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
export declare const getCitationFormulaTool: McpToolDefinition;
|
|
38
|
+
export declare function executeGetCitationFormula(input: unknown, context: ToolContext): Promise<ToolResult>;
|
|
25
39
|
export declare const aiVisibilityTools: McpToolDefinition[];
|
|
26
40
|
export declare const aiVisibilityExecutors: Record<string, (input: unknown, context: ToolContext) => Promise<ToolResult>>;
|
|
27
41
|
//# sourceMappingURL=ai-visibility.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-visibility.d.ts","sourceRoot":"","sources":["../../src/tools/ai-visibility.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"ai-visibility.d.ts","sourceRoot":"","sources":["../../src/tools/ai-visibility.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EAGX,MAAM,aAAa,CAAC;AAwIrB,eAAO,MAAM,mBAAmB,EAAE,iBAiBjC,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAmHrB;AA2HD,eAAO,MAAM,wBAAwB,EAAE,iBAmBtC,CAAC;AAEF,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoHrB;AAYD,eAAO,MAAM,eAAe,EAAE,iBAoB7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA8CrB;AAiBD,eAAO,MAAM,gBAAgB,EAAE,iBA8C9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA8CrB;AAUD,eAAO,MAAM,aAAa,EAAE,iBAa3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAiErB;AAcD,eAAO,MAAM,gBAAgB,EAAE,iBAiC9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAaD,eAAO,MAAM,kBAAkB,EAAE,iBAwBhC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAwDrB;AAWD,eAAO,MAAM,aAAa,EAAE,iBAgB3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAsDrB;AAYD,eAAO,MAAM,eAAe,EAAE,iBAoB7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoErB;AAoBD,eAAO,MAAM,kBAAkB,EAAE,iBAqBhC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAqDrB;AA8BD,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAUlE,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAQnE;AAED,eAAO,MAAM,6BAA6B;;;;;;EAI/B,CAAC;AAEZ,eAAO,MAAM,sBAAsB,EAAE,iBAiBpC,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA2FrB;AAMD,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,EAYhD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CACxC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAa9D,CAAC"}
|