@mentoringo/vantage-ops-mcp 1.3.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.
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Thin HTTP client for Vantage's /mcp/* authorizer path.
3
+ *
4
+ * Reads VANTAGE_MCP_KEY + VANTAGE_API_URL on server startup (from the
5
+ * parent shell env, falling back to ~/repo/.env). Attaches
6
+ * `Authorization: Bearer <key>` and `Content-Type: application/json`
7
+ * to every request. Returns parsed JSON on 2xx, throws with the
8
+ * server's error shape on 4xx/5xx.
9
+ *
10
+ * Used by the write tools (opportunity_create, activity_log, etc.)
11
+ * so the MCP server never touches DynamoDB directly — writes flow
12
+ * through the same Lambda handlers dashboard users hit, including
13
+ * slug generation, stage history, weighted-value math, and audit.
14
+ */
15
+ export declare class VantageApiError extends Error {
16
+ status: number;
17
+ body: unknown;
18
+ constructor(status: number, body: unknown, message: string);
19
+ }
20
+ export declare function createOpportunity(body: {
21
+ id?: string;
22
+ name: string;
23
+ company_id: string;
24
+ stage?: string;
25
+ value?: number;
26
+ currency?: string;
27
+ probability?: number;
28
+ expected_close_date?: string;
29
+ primary_contact_id?: string;
30
+ campaign_id?: string;
31
+ description?: string;
32
+ notes?: string;
33
+ tags?: string[];
34
+ owner_id?: string;
35
+ }): Promise<unknown>;
36
+ export declare function updateOpportunity(id: string, body: Record<string, unknown>): Promise<unknown>;
37
+ export declare function logActivity(body: {
38
+ entity_type: "company" | "contact" | "opportunity";
39
+ entity_id: string;
40
+ activity_type: string;
41
+ summary: string;
42
+ detail?: string;
43
+ occurred_at?: string;
44
+ }): Promise<unknown>;
45
+ export declare function createContact(body: {
46
+ id?: string;
47
+ first_name: string;
48
+ last_name?: string;
49
+ email?: string;
50
+ company_id?: string;
51
+ title?: string;
52
+ role?: string;
53
+ phone?: string;
54
+ linkedin_url?: string;
55
+ notes?: string;
56
+ }): Promise<unknown>;
57
+ export declare function updateContact(id: string, body: Record<string, unknown>): Promise<unknown>;
58
+ export declare function createCompany(body: {
59
+ name: string;
60
+ client_id: string;
61
+ vertical?: string;
62
+ tier?: string;
63
+ status?: string;
64
+ domain?: string;
65
+ industry?: string;
66
+ description?: string;
67
+ website?: string;
68
+ linkedin_url?: string;
69
+ notes?: string;
70
+ tags?: string[];
71
+ }): Promise<unknown>;
72
+ export declare function updateCompany(id: string, body: Record<string, unknown>): Promise<unknown>;
73
+ export declare function deleteCompany(id: string): Promise<unknown>;
74
+ export declare function enrichCompany(id: string): Promise<unknown>;
75
+ export declare function deleteContact(id: string): Promise<unknown>;
76
+ export declare function deleteOpportunity(id: string): Promise<unknown>;
77
+ export declare function createCampaign(body: {
78
+ name: string;
79
+ client_id: string;
80
+ campaign_type?: string;
81
+ vertical?: string;
82
+ description?: string;
83
+ goal_type?: string;
84
+ goal_target?: number;
85
+ }): Promise<unknown>;
86
+ export declare function updateCampaign(id: string, body: Record<string, unknown>): Promise<unknown>;
87
+ export declare function deleteCampaign(id: string): Promise<unknown>;
88
+ export declare function startCampaign(id: string): Promise<unknown>;
89
+ export declare function pauseCampaign(id: string): Promise<unknown>;
90
+ export declare function addCampaignRecipients(id: string, body: {
91
+ contact_ids: string[];
92
+ }): Promise<unknown>;
93
+ export declare function updateCampaignRecipient(id: string, contactId: string, body: {
94
+ engagement_status: string;
95
+ occurred_at?: string;
96
+ }): Promise<unknown>;
97
+ export declare function addCampaignTargets(id: string, body: {
98
+ company_ids: string[];
99
+ priority?: string;
100
+ }): Promise<unknown>;
101
+ export declare function removeCampaignTarget(id: string, companyId: string): Promise<unknown>;
102
+ export declare function sourceCampaignContacts(id: string, body: {
103
+ titles?: string[];
104
+ seniorities?: string[];
105
+ limit_per_company?: number;
106
+ }): Promise<unknown>;
107
+ export declare function createTemplate(body: {
108
+ name: string;
109
+ body: string;
110
+ subject?: string;
111
+ description?: string;
112
+ cta?: string;
113
+ campaign_type?: string;
114
+ target_vertical?: string;
115
+ target_persona?: string;
116
+ }): Promise<unknown>;
117
+ export declare function updateTemplate(id: string, body: Record<string, unknown>): Promise<unknown>;
118
+ export declare function deleteTemplate(id: string): Promise<unknown>;
119
+ export declare function createOutreach(body: {
120
+ campaign_id: string;
121
+ company_id: string;
122
+ contact_id?: string;
123
+ channel?: string;
124
+ status?: string;
125
+ subject?: string;
126
+ body?: string;
127
+ template_id?: string;
128
+ sent_at?: string;
129
+ }): Promise<unknown>;
130
+ export declare function updateOutreach(id: string, body: Record<string, unknown>): Promise<unknown>;
131
+ export declare function apolloSearchContacts(body: {
132
+ domains?: string[] | string;
133
+ q_organization_name?: string;
134
+ organization_ids?: string[];
135
+ person_titles?: string[];
136
+ person_seniorities?: string[];
137
+ q_keywords?: string;
138
+ page?: number;
139
+ limit?: number;
140
+ }): Promise<unknown>;
141
+ export declare function apolloSearchCompanies(body: {
142
+ q_organization_name?: string;
143
+ q_organization_domains?: string[] | string;
144
+ organization_locations?: string[];
145
+ num_employees_ranges?: string[];
146
+ page?: number;
147
+ limit?: number;
148
+ }): Promise<unknown>;
149
+ export declare function apolloUnlockEmail(body: {
150
+ apollo_id?: string;
151
+ first_name?: string;
152
+ last_name?: string;
153
+ linkedin_url?: string;
154
+ organization_name?: string;
155
+ }): Promise<unknown>;
156
+ export declare function apolloImportContacts(body: {
157
+ client_id: string;
158
+ contacts: Array<Record<string, unknown>>;
159
+ create_missing_companies?: boolean;
160
+ default_company_id?: string;
161
+ }): Promise<unknown>;
162
+ export declare function authConfigured(): boolean;
163
+ export declare function apiUrlForDiagnostics(): string;
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Thin HTTP client for Vantage's /mcp/* authorizer path.
3
+ *
4
+ * Reads VANTAGE_MCP_KEY + VANTAGE_API_URL on server startup (from the
5
+ * parent shell env, falling back to ~/repo/.env). Attaches
6
+ * `Authorization: Bearer <key>` and `Content-Type: application/json`
7
+ * to every request. Returns parsed JSON on 2xx, throws with the
8
+ * server's error shape on 4xx/5xx.
9
+ *
10
+ * Used by the write tools (opportunity_create, activity_log, etc.)
11
+ * so the MCP server never touches DynamoDB directly — writes flow
12
+ * through the same Lambda handlers dashboard users hit, including
13
+ * slug generation, stage history, weighted-value math, and audit.
14
+ */
15
+ import { readFileSync, existsSync } from "fs";
16
+ import { homedir } from "os";
17
+ import { join } from "path";
18
+ const DEFAULT_API_URL = "https://mbmhmzrur4.execute-api.us-east-1.amazonaws.com/prod";
19
+ // Minimal .env parser — avoids pulling in dotenv just for one var.
20
+ // Only parses KEY=VALUE and KEY="VALUE" / KEY='VALUE' lines; skips
21
+ // comments and blanks. Returns a plain object.
22
+ function parseDotenv(path) {
23
+ const out = {};
24
+ if (!existsSync(path))
25
+ return out;
26
+ try {
27
+ const text = readFileSync(path, "utf8");
28
+ for (const raw of text.split(/\r?\n/)) {
29
+ const line = raw.trim();
30
+ if (!line || line.startsWith("#"))
31
+ continue;
32
+ const m = line.match(/^(?:export\s+)?([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/i);
33
+ if (!m)
34
+ continue;
35
+ let [, key, value] = m;
36
+ value = value.trim();
37
+ if ((value.startsWith('"') && value.endsWith('"')) ||
38
+ (value.startsWith("'") && value.endsWith("'"))) {
39
+ value = value.slice(1, -1);
40
+ }
41
+ out[key] = value;
42
+ }
43
+ }
44
+ catch {
45
+ // Unreadable — caller falls back to process.env
46
+ }
47
+ return out;
48
+ }
49
+ // Resolve VANTAGE_MCP_KEY + VANTAGE_API_URL from: explicit process.env
50
+ // first (MCP server config env block takes precedence), then ~/repo/.env.
51
+ function resolveConfig() {
52
+ let apiKey = process.env.VANTAGE_MCP_KEY || null;
53
+ let apiUrl = process.env.VANTAGE_API_URL || DEFAULT_API_URL;
54
+ if (!apiKey) {
55
+ const envFile = parseDotenv(join(homedir(), "repo", ".env"));
56
+ apiKey = envFile.VANTAGE_MCP_KEY || null;
57
+ apiUrl = apiUrl || envFile.VANTAGE_API_URL || DEFAULT_API_URL;
58
+ }
59
+ return { apiUrl, apiKey };
60
+ }
61
+ const { apiUrl, apiKey } = resolveConfig();
62
+ export class VantageApiError extends Error {
63
+ status;
64
+ body;
65
+ constructor(status, body, message) {
66
+ super(message);
67
+ this.status = status;
68
+ this.body = body;
69
+ this.name = "VantageApiError";
70
+ }
71
+ }
72
+ /**
73
+ * Raw HTTP call against the /mcp/* path prefix.
74
+ * Use the higher-level functions below for specific resources.
75
+ */
76
+ async function mcpRequest(method, path, body) {
77
+ if (!apiKey) {
78
+ throw new Error("VANTAGE_MCP_KEY not set. Add it to ~/repo/.env or the mcp.json env block " +
79
+ "for the vantage-ops server. Provision one via the dashboard at /api-keys.");
80
+ }
81
+ // Path must start with /mcp; the API Gateway route is /mcp/{proxy+}.
82
+ // If caller passes an un-prefixed /v2/opportunities or /activities,
83
+ // prepend /mcp transparently.
84
+ const cleanPath = path.startsWith("/mcp")
85
+ ? path
86
+ : `/mcp${path.startsWith("/") ? path : `/${path}`}`;
87
+ const url = `${apiUrl}${cleanPath}`;
88
+ const res = await fetch(url, {
89
+ method,
90
+ headers: {
91
+ Authorization: `Bearer ${apiKey}`,
92
+ "Content-Type": "application/json",
93
+ },
94
+ body: body === undefined ? undefined : JSON.stringify(body),
95
+ });
96
+ const text = await res.text();
97
+ let parsed = text;
98
+ if (text) {
99
+ try {
100
+ parsed = JSON.parse(text);
101
+ }
102
+ catch {
103
+ // Leave as text if not JSON; shouldn't normally happen.
104
+ }
105
+ }
106
+ if (!res.ok) {
107
+ const message = typeof parsed === "object" && parsed && "message" in parsed
108
+ ? String(parsed.message)
109
+ : `Vantage API ${method} ${cleanPath} returned ${res.status}`;
110
+ throw new VantageApiError(res.status, parsed, message);
111
+ }
112
+ return parsed;
113
+ }
114
+ // ─────────────────────────────────────────────────────────────
115
+ // Resource helpers
116
+ // ─────────────────────────────────────────────────────────────
117
+ export async function createOpportunity(body) {
118
+ return mcpRequest("POST", "/v2/opportunities", body);
119
+ }
120
+ export async function updateOpportunity(id, body) {
121
+ return mcpRequest("PATCH", `/v2/opportunities/${id}`, body);
122
+ }
123
+ export async function logActivity(body) {
124
+ return mcpRequest("POST", "/activities", body);
125
+ }
126
+ export async function createContact(body) {
127
+ return mcpRequest("POST", "/v2/contacts", body);
128
+ }
129
+ export async function updateContact(id, body) {
130
+ return mcpRequest("PATCH", `/v2/contacts/${id}`, body);
131
+ }
132
+ // ── Companies ──────────────────────────────────────────────────
133
+ export async function createCompany(body) {
134
+ return mcpRequest("POST", "/companies", body);
135
+ }
136
+ export async function updateCompany(id, body) {
137
+ return mcpRequest("PATCH", `/companies/${id}`, body);
138
+ }
139
+ export async function deleteCompany(id) {
140
+ return mcpRequest("DELETE", `/companies/${id}`);
141
+ }
142
+ export async function enrichCompany(id) {
143
+ return mcpRequest("POST", `/companies/${id}/enrich`, {});
144
+ }
145
+ // ── Contact / Opportunity deletes ──────────────────────────────
146
+ export async function deleteContact(id) {
147
+ return mcpRequest("DELETE", `/v2/contacts/${id}`);
148
+ }
149
+ export async function deleteOpportunity(id) {
150
+ return mcpRequest("DELETE", `/v2/opportunities/${id}`);
151
+ }
152
+ // ── Campaigns ──────────────────────────────────────────────────
153
+ export async function createCampaign(body) {
154
+ return mcpRequest("POST", "/campaigns", body);
155
+ }
156
+ export async function updateCampaign(id, body) {
157
+ return mcpRequest("PATCH", `/campaigns/${id}`, body);
158
+ }
159
+ export async function deleteCampaign(id) {
160
+ return mcpRequest("DELETE", `/campaigns/${id}`);
161
+ }
162
+ export async function startCampaign(id) {
163
+ return mcpRequest("POST", `/campaigns/${id}/start`);
164
+ }
165
+ export async function pauseCampaign(id) {
166
+ return mcpRequest("POST", `/campaigns/${id}/pause`);
167
+ }
168
+ export async function addCampaignRecipients(id, body) {
169
+ return mcpRequest("POST", `/campaigns/${id}/recipients`, body);
170
+ }
171
+ export async function updateCampaignRecipient(id, contactId, body) {
172
+ return mcpRequest("PATCH", `/campaigns/${id}/recipients/${contactId}`, body);
173
+ }
174
+ export async function addCampaignTargets(id, body) {
175
+ return mcpRequest("POST", `/campaigns/${id}/targets`, body);
176
+ }
177
+ export async function removeCampaignTarget(id, companyId) {
178
+ return mcpRequest("DELETE", `/campaigns/${id}/targets/${companyId}`);
179
+ }
180
+ export async function sourceCampaignContacts(id, body) {
181
+ return mcpRequest("POST", `/campaigns/${id}/source-contacts`, body);
182
+ }
183
+ // ── Templates ──────────────────────────────────────────────────
184
+ export async function createTemplate(body) {
185
+ return mcpRequest("POST", "/templates", body);
186
+ }
187
+ export async function updateTemplate(id, body) {
188
+ return mcpRequest("PATCH", `/templates/${id}`, body);
189
+ }
190
+ export async function deleteTemplate(id) {
191
+ return mcpRequest("DELETE", `/templates/${id}`);
192
+ }
193
+ // ── Outreach records ───────────────────────────────────────────
194
+ // Note: Vantage is an outreach TRACKER, not a sender. These endpoints
195
+ // record that a message was sent externally (via LinkedIn, email, etc.)
196
+ // so engagement can be tracked and attributed downstream.
197
+ export async function createOutreach(body) {
198
+ return mcpRequest("POST", "/outreach", body);
199
+ }
200
+ export async function updateOutreach(id, body) {
201
+ return mcpRequest("PATCH", `/outreach/${id}`, body);
202
+ }
203
+ // ── Apollo (search + unlock + import) ─────────────────────────
204
+ // Apollo's mixed_people / mixed_companies / people-match endpoints
205
+ // are wrapped server-side by /apollo/* routes (scope: apollo:write).
206
+ // These do NOT touch DynamoDB directly — they hit Apollo's API and
207
+ // return the raw shape, which the caller can then turn into Vantage
208
+ // contact_create / company_create calls. The exception is
209
+ // apolloImportContacts, which writes through to vantage-contacts-v2-prod
210
+ // in a single batched call.
211
+ export async function apolloSearchContacts(body) {
212
+ return mcpRequest("POST", "/apollo/search", body);
213
+ }
214
+ export async function apolloSearchCompanies(body) {
215
+ return mcpRequest("POST", "/apollo/search-companies", body);
216
+ }
217
+ export async function apolloUnlockEmail(body) {
218
+ return mcpRequest("POST", "/apollo/unlock-email", body);
219
+ }
220
+ export async function apolloImportContacts(body) {
221
+ return mcpRequest("POST", "/apollo/import", body);
222
+ }
223
+ // Exposed for debugging / the health tool
224
+ export function authConfigured() {
225
+ return !!apiKey;
226
+ }
227
+ export function apiUrlForDiagnostics() {
228
+ return apiUrl;
229
+ }
230
+ //# sourceMappingURL=mcp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ interface SkillFrontmatter {
3
+ name: string;
4
+ description: string;
5
+ argumentHint?: string;
6
+ }
7
+ interface ParsedSkill {
8
+ frontmatter: SkillFrontmatter;
9
+ body: string;
10
+ }
11
+ export declare function parseSkill(filepath: string): ParsedSkill | null;
12
+ export declare const BUNDLED_SKILLS: string[];
13
+ export declare function registerBundledSkillPrompts(server: McpServer): void;
14
+ export {};
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Forward-compat MCP prompt registration for the bundled skill workflows.
3
+ *
4
+ * Claude Code does NOT currently surface MCP-server-exposed `prompts` as
5
+ * slash-commands. The filesystem skills under `.claude/skills/<name>/SKILL.md`
6
+ * are the working path for `/<name>` slash invocations in Claude Code today.
7
+ *
8
+ * However, the Claude Agent SDK and other MCP clients DO consume `prompts`
9
+ * via the protocol. Registering the same workflows as MCP prompts here is a
10
+ * zero-cost forward-compat hedge — Agent SDK consumers and any future Claude
11
+ * Code support for prompt-as-slash get the workflows automatically, and the
12
+ * filesystem path keeps working in parallel for Claude Code.
13
+ *
14
+ * The prompt content for each skill is loaded at server startup from the same
15
+ * SKILL.md file that the filesystem path uses, so there's a single source of
16
+ * truth — update the SKILL.md, rebuild, and both surfaces serve the new content.
17
+ */
18
+ import { readFileSync, existsSync } from "node:fs";
19
+ import { join, resolve, dirname } from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+ const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
22
+ const SKILLS_DIR = join(REPO_ROOT, ".claude", "skills");
23
+ export function parseSkill(filepath) {
24
+ if (!existsSync(filepath))
25
+ return null;
26
+ const raw = readFileSync(filepath, "utf8");
27
+ const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
28
+ if (!match)
29
+ return null;
30
+ const fmRaw = match[1];
31
+ const body = match[2].trimStart();
32
+ const fm = {};
33
+ for (const line of fmRaw.split("\n")) {
34
+ const m = line.match(/^([a-z-]+):\s*(.*)$/);
35
+ if (!m)
36
+ continue;
37
+ const key = m[1];
38
+ const value = m[2].trim();
39
+ if (key === "name")
40
+ fm.name = value;
41
+ else if (key === "description")
42
+ fm.description = value;
43
+ else if (key === "argument-hint")
44
+ fm.argumentHint = value;
45
+ }
46
+ if (!fm.name || !fm.description)
47
+ return null;
48
+ return { frontmatter: fm, body };
49
+ }
50
+ export const BUNDLED_SKILLS = ["vet-leads", "lead-enrich", "contact-enrich", "campaign-launch"];
51
+ export function registerBundledSkillPrompts(server) {
52
+ for (const skillName of BUNDLED_SKILLS) {
53
+ const skillPath = join(SKILLS_DIR, skillName, "SKILL.md");
54
+ const parsed = parseSkill(skillPath);
55
+ if (!parsed) {
56
+ console.error(`[prompts] Skipping ${skillName}: SKILL.md missing or malformed at ${skillPath}`);
57
+ continue;
58
+ }
59
+ server.registerPrompt(skillName, {
60
+ title: parsed.frontmatter.name,
61
+ description: parsed.frontmatter.description,
62
+ }, () => ({
63
+ messages: [
64
+ {
65
+ role: "user",
66
+ content: {
67
+ type: "text",
68
+ text: parsed.body,
69
+ },
70
+ },
71
+ ],
72
+ }));
73
+ }
74
+ }
75
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAaxD,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,EAAE,GAA8B,EAAE,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,MAAM;YAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC;aAC/B,IAAI,GAAG,KAAK,aAAa;YAAE,EAAE,CAAC,WAAW,GAAG,KAAK,CAAC;aAClD,IAAI,GAAG,KAAK,eAAe;YAAE,EAAE,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,EAAE,WAAW,EAAE,EAAsB,EAAE,IAAI,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;AAEhG,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,sBAAsB,SAAS,sCAAsC,SAAS,EAAE,CAAC,CAAC;YAChG,SAAS;QACX,CAAC;QACD,MAAM,CAAC,cAAc,CACnB,SAAS,EACT;YACE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,WAAW;SAC5C,EACD,GAAG,EAAE,CAAC,CAAC;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,MAAM,CAAC,IAAI;qBAClB;iBACF;aACF;SACF,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC"}