@selfhost.dev/mcp-server 0.3.0 → 0.4.1
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/README.md +147 -24
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +3 -3
- package/dist/client.js +1 -1
- package/dist/config.js +1 -1
- package/dist/index.js +29 -4
- package/dist/index.js.map +1 -1
- package/dist/rate-limiter.js +1 -1
- package/dist/tools/billing.js +14 -14
- package/dist/tools/credentials.js +1 -1
- package/dist/tools/database-users.js +9 -9
- package/dist/tools/deployment-domains.d.ts +2 -0
- package/dist/tools/deployment-domains.js +128 -0
- package/dist/tools/deployment-domains.js.map +1 -0
- package/dist/tools/deployment-notifications.d.ts +2 -0
- package/dist/tools/deployment-notifications.js +74 -0
- package/dist/tools/deployment-notifications.js.map +1 -0
- package/dist/tools/deployments.d.ts +2 -0
- package/dist/tools/deployments.js +302 -0
- package/dist/tools/deployments.js.map +1 -0
- package/dist/tools/env-vars.d.ts +2 -0
- package/dist/tools/env-vars.js +121 -0
- package/dist/tools/env-vars.js.map +1 -0
- package/dist/tools/github.d.ts +2 -0
- package/dist/tools/github.js +106 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/hetzner.js +13 -13
- package/dist/tools/instances.js +11 -11
- package/dist/tools/pgbouncer.js +4 -4
- package/dist/tools/pitr.js +16 -16
- package/dist/tools/project-databases.d.ts +2 -0
- package/dist/tools/project-databases.js +169 -0
- package/dist/tools/project-databases.js.map +1 -0
- package/dist/tools/project-services.d.ts +2 -0
- package/dist/tools/project-services.js +93 -0
- package/dist/tools/project-services.js.map +1 -0
- package/dist/tools/projects.d.ts +2 -0
- package/dist/tools/projects.js +141 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/scaling.js +13 -13
- package/dist/types/models.js +1 -1
- package/dist/types/tiers.js +31 -1
- package/dist/types/tiers.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Custom domains for deployments. Two layers:
|
|
6
|
+
* - Deployment-scoped DeploymentDomain (rides on the deployment payload)
|
|
7
|
+
* - Org-scoped CustomDomainVerification (DNS ownership state, shared across deployments)
|
|
8
|
+
*
|
|
9
|
+
* Endpoints:
|
|
10
|
+
* - PATCH /api/v1/platform/github_repo_deployments/:pid/domains full-replace the domain set
|
|
11
|
+
* - POST /api/v1/platform/github_repo_deployments/:pid/domains append one domain
|
|
12
|
+
* - DELETE /api/v1/platform/github_repo_deployments/:pid/domains/:domain remove one
|
|
13
|
+
* - GET /api/v1/platform/custom_domains list org domain verifications
|
|
14
|
+
* - POST /api/v1/platform/custom_domains/:domain/verify check DNS records live
|
|
15
|
+
*
|
|
16
|
+
* Adding a domain auto-creates the org verification record and returns the DNS
|
|
17
|
+
* records (a TXT for ownership + a CNAME for routing) the user must add. A
|
|
18
|
+
* domain only goes live (and gets a cert) once `verify_custom_domain` confirms
|
|
19
|
+
* BOTH records.
|
|
20
|
+
*/
|
|
21
|
+
const DEPLOYMENTS_BASE = "/api/v1/platform/github_repo_deployments";
|
|
22
|
+
const CUSTOM_DOMAINS_BASE = "/api/v1/platform/custom_domains";
|
|
23
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
24
|
+
function hasOrg() {
|
|
25
|
+
return session.getActiveOrgId() !== null;
|
|
26
|
+
}
|
|
27
|
+
function normalizeDomain(domain) {
|
|
28
|
+
return domain.trim().toLowerCase().replace(/^https?:\/\//, "").replace(/\/.*$/, "");
|
|
29
|
+
}
|
|
30
|
+
export function registerDeploymentDomainTools(server) {
|
|
31
|
+
server.tool("sync_deployment_domains", "Set the FULL list of custom domains on a deployment (replaces any existing set - domains not included are removed). Use this to set/change the primary domain or remove several at once. For just adding one domain, prefer `add_deployment_domain`. Each domain that's new auto-creates an org verification record; the response/`get_deployment` then carries the DNS records to add. The deployment must be provisioned (422 otherwise).", {
|
|
32
|
+
deployment_pid: z.string().min(1),
|
|
33
|
+
domains: z.array(z.object({
|
|
34
|
+
domain: z.string().min(1),
|
|
35
|
+
is_primary: z.boolean().optional().describe("Mark this as the primary domain (at most one)"),
|
|
36
|
+
})).describe("The complete desired domain set; replaces the current set atomically"),
|
|
37
|
+
}, async ({ deployment_pid, domains }) => {
|
|
38
|
+
if (!hasOrg())
|
|
39
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
40
|
+
const normalized = domains.map((d) => ({ domain: normalizeDomain(d.domain), is_primary: d.is_primary ?? false }));
|
|
41
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/domains`, {
|
|
42
|
+
method: "PATCH",
|
|
43
|
+
body: { domains: normalized },
|
|
44
|
+
toolName: "sync_deployment_domains",
|
|
45
|
+
});
|
|
46
|
+
if (!result.success) {
|
|
47
|
+
return { content: [{ type: "text", text: `Failed to sync domains (${result.statusCode}): ${result.message}` }] };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{ type: "text", text: "Domains updated. Add the DNS records shown, then call `verify_custom_domain` for each domain. `get_deployment` shows current domain status." },
|
|
52
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
server.tool("add_deployment_domain", "Add (append) one custom domain to a deployment as its primary domain, keeping any existing domains. Auto-creates the org verification record and returns the DNS records (TXT + CNAME) to configure. After adding the records at your DNS provider, call `verify_custom_domain`. The deployment must be provisioned (422 otherwise).", {
|
|
57
|
+
deployment_pid: z.string().min(1),
|
|
58
|
+
domain: z.string().min(1).describe("e.g. app.example.com (scheme/path are stripped)"),
|
|
59
|
+
}, async ({ deployment_pid, domain }) => {
|
|
60
|
+
if (!hasOrg())
|
|
61
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
62
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/domains`, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
body: { domain: normalizeDomain(domain) },
|
|
65
|
+
toolName: "add_deployment_domain",
|
|
66
|
+
});
|
|
67
|
+
if (!result.success) {
|
|
68
|
+
return { content: [{ type: "text", text: `Failed to add domain (${result.statusCode}): ${result.message}` }] };
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{ type: "text", text: "Domain added. Configure the DNS records returned below, then call `verify_custom_domain`." },
|
|
73
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
server.tool("remove_deployment_domain", "Remove one custom domain from a deployment. The remaining domains are re-synced and primary metadata updated.", {
|
|
78
|
+
deployment_pid: z.string().min(1),
|
|
79
|
+
domain: z.string().min(1),
|
|
80
|
+
}, async ({ deployment_pid, domain }) => {
|
|
81
|
+
if (!hasOrg())
|
|
82
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
83
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/domains/${encodeURIComponent(normalizeDomain(domain))}`, {
|
|
84
|
+
method: "DELETE",
|
|
85
|
+
toolName: "remove_deployment_domain",
|
|
86
|
+
});
|
|
87
|
+
if (!result.success) {
|
|
88
|
+
return { content: [{ type: "text", text: `Failed to remove domain (${result.statusCode}): ${result.message}` }] };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{ type: "text", text: "Domain removed." },
|
|
93
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
server.tool("verify_custom_domain", "Check a custom domain's DNS records live and advance its verification. The domain must have been added to a deployment first. Outcomes: `verified` (both TXT + CNAME present → domain goes live with HTTPS); `ownership_verified` (TXT only - add the CNAME); `routing_configured` (CNAME only - add the TXT); or 422 `pending_verification` (neither found yet - DNS can take up to 48h). The `checks` object reports each record's status and expected value.", {
|
|
98
|
+
domain: z.string().min(1),
|
|
99
|
+
}, async ({ domain }) => {
|
|
100
|
+
if (!hasOrg())
|
|
101
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
102
|
+
const result = await apiRequest(`${CUSTOM_DOMAINS_BASE}/${encodeURIComponent(normalizeDomain(domain))}/verify`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
toolName: "verify_custom_domain",
|
|
105
|
+
});
|
|
106
|
+
if (!result.success) {
|
|
107
|
+
const parts = [
|
|
108
|
+
{ type: "text", text: `Domain not fully verified yet (${result.statusCode}): ${result.message}` },
|
|
109
|
+
];
|
|
110
|
+
if (result.data)
|
|
111
|
+
parts.push({ type: "text", text: JSON.stringify(result.data, null, 2) });
|
|
112
|
+
return { content: parts };
|
|
113
|
+
}
|
|
114
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
115
|
+
});
|
|
116
|
+
server.tool("list_custom_domains", "List all custom-domain verifications for the active organization, with each domain's status (pending_verification | ownership_verified | routing_configured | verified) and when it was verified.", {}, async () => {
|
|
117
|
+
if (!hasOrg())
|
|
118
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
119
|
+
const result = await apiRequest(CUSTOM_DOMAINS_BASE, {
|
|
120
|
+
toolName: "list_custom_domains",
|
|
121
|
+
});
|
|
122
|
+
if (!result.success) {
|
|
123
|
+
return { content: [{ type: "text", text: `Failed to list custom domains (${result.statusCode}): ${result.message}` }] };
|
|
124
|
+
}
|
|
125
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=deployment-domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-domains.js","sourceRoot":"","sources":["../../src/tools/deployment-domains.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Deployment notification bindings - link an existing org notification channel
|
|
6
|
+
* (the `nchan_...` channels from `list_notification_channels`) to a deployment,
|
|
7
|
+
* so it's notified on terminal deploy-run outcomes (succeeded / failed / aborted).
|
|
8
|
+
* Binding covers all terminal events; there is no per-event selection.
|
|
9
|
+
*
|
|
10
|
+
* Endpoints (base /api/v1/platform/github_repo_deployments/:pid/notifications):
|
|
11
|
+
* - GET /notifications list enabled bindings
|
|
12
|
+
* - POST /notifications bind a channel (body {notification_channel_pid})
|
|
13
|
+
* - DELETE /notifications/:channel_pid unbind a channel
|
|
14
|
+
*
|
|
15
|
+
* Note: only org OWNERS may manage these bindings. Create the channel itself via
|
|
16
|
+
* `create_notification_channel` first.
|
|
17
|
+
*/
|
|
18
|
+
const DEPLOYMENTS_BASE = "/api/v1/platform/github_repo_deployments";
|
|
19
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
20
|
+
function hasOrg() {
|
|
21
|
+
return session.getActiveOrgId() !== null;
|
|
22
|
+
}
|
|
23
|
+
export function registerDeploymentNotificationTools(server) {
|
|
24
|
+
server.tool("list_deployment_notification_bindings", "List the notification channels bound to a deployment (which channels get notified when a deploy succeeds/fails/aborts). Returns binding_pid, notification_channel_pid, channel_type, name, and bound_at.", {
|
|
25
|
+
deployment_pid: z.string().min(1),
|
|
26
|
+
}, async ({ deployment_pid }) => {
|
|
27
|
+
if (!hasOrg())
|
|
28
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
29
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/notifications`, {
|
|
30
|
+
toolName: "list_deployment_notification_bindings",
|
|
31
|
+
});
|
|
32
|
+
if (!result.success) {
|
|
33
|
+
return { content: [{ type: "text", text: `Failed to list notification bindings (${result.statusCode}): ${result.message}` }] };
|
|
34
|
+
}
|
|
35
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
36
|
+
});
|
|
37
|
+
server.tool("bind_deployment_notification_channel", "Bind an existing org notification channel to a deployment so it's notified on deploy outcomes. The channel pid (nchan_...) comes from `list_notification_channels` (create one with `create_notification_channel` if needed). Returns 422 if already bound, 404 if the channel doesn't exist. Org owner only.", {
|
|
38
|
+
deployment_pid: z.string().min(1),
|
|
39
|
+
notification_channel_pid: z.string().min(1).describe("Org notification channel pid, e.g. nchan_..."),
|
|
40
|
+
}, async ({ deployment_pid, notification_channel_pid }) => {
|
|
41
|
+
if (!hasOrg())
|
|
42
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
43
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/notifications`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
body: { notification_channel_pid },
|
|
46
|
+
toolName: "bind_deployment_notification_channel",
|
|
47
|
+
});
|
|
48
|
+
if (!result.success) {
|
|
49
|
+
return { content: [{ type: "text", text: `Failed to bind notification channel (${result.statusCode}): ${result.message}` }] };
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{ type: "text", text: "Notification channel bound to deployment." },
|
|
54
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
server.tool("unbind_deployment_notification_channel", "Unbind a notification channel from a deployment (it will no longer be notified on deploy outcomes). Pass the notification_channel_pid (NOT the binding pid). Org owner only.", {
|
|
59
|
+
deployment_pid: z.string().min(1),
|
|
60
|
+
notification_channel_pid: z.string().min(1).describe("The notification channel pid (nchan_...) to unbind"),
|
|
61
|
+
}, async ({ deployment_pid, notification_channel_pid }) => {
|
|
62
|
+
if (!hasOrg())
|
|
63
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
64
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/notifications/${notification_channel_pid}`, {
|
|
65
|
+
method: "DELETE",
|
|
66
|
+
toolName: "unbind_deployment_notification_channel",
|
|
67
|
+
});
|
|
68
|
+
if (!result.success) {
|
|
69
|
+
return { content: [{ type: "text", text: `Failed to unbind notification channel (${result.statusCode}): ${result.message}` }] };
|
|
70
|
+
}
|
|
71
|
+
return { content: [{ type: "text", text: "Notification channel unbound from deployment." }] };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=deployment-notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-notifications.js","sourceRoot":"","sources":["../../src/tools/deployment-notifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Deployments (GithubRepoDeployment) - a deployed app from a GitHub repo,
|
|
6
|
+
* living inside a project (CoolifyProject). Each deployment has a build/run
|
|
7
|
+
* history; runs are returned INLINE on the deployment payload (`deployment_runs`,
|
|
8
|
+
* newest 50), there is no separate runs-list endpoint.
|
|
9
|
+
*
|
|
10
|
+
* Endpoints (base /api/v1/platform/github_repo_deployments):
|
|
11
|
+
* - GET / list (apps for the org)
|
|
12
|
+
* - GET /:pid show (single deployment + inline runs)
|
|
13
|
+
* - POST / create (provision Coolify app + first deploy)
|
|
14
|
+
* - PATCH /:pid update status/auto_deploy/ignore_paths/max_concurrent_previews
|
|
15
|
+
* - PATCH /:pid/build_config update build_pack/base_directory/port/dockerfile_location/env_vars
|
|
16
|
+
* - DELETE /:pid delete (also removes the Coolify app)
|
|
17
|
+
* - POST /:pid/deploy trigger a manual deploy (new run)
|
|
18
|
+
* - GET /:pid/logs app/container logs
|
|
19
|
+
* - GET /:pid/health health probe
|
|
20
|
+
* - GET /:pid/runs/:run_pid/logs build + container logs for one run
|
|
21
|
+
* - POST /:pid/runs/:run_pid/redeploy re-run the same commit
|
|
22
|
+
* - POST /:pid/runs/:run_pid/rollback re-deploy a prior successful run's commit
|
|
23
|
+
*
|
|
24
|
+
* `organization_id` is auto-injected from the active org by the HTTP client.
|
|
25
|
+
*/
|
|
26
|
+
const DEPLOYMENTS_BASE = "/api/v1/platform/github_repo_deployments";
|
|
27
|
+
const BUILD_PACKS = ["nixpacks", "dockerfile", "dockercompose", "static"];
|
|
28
|
+
const DEPLOY_STATUSES = ["active", "paused"];
|
|
29
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
30
|
+
function hasOrg() {
|
|
31
|
+
return session.getActiveOrgId() !== null;
|
|
32
|
+
}
|
|
33
|
+
const RUN_STATUS_NOTE = "Run status values: `enqueued`/`building`/`deploying` are in-progress (transient); `active` = deployed successfully; `failed`/`aborted`/`removed`/`skipped` are terminal. Poll until the latest run reaches a terminal status.";
|
|
34
|
+
export function registerDeploymentTools(server) {
|
|
35
|
+
server.tool("list_deployments", `List deployments (apps) in the active organization. Each entry includes repo_full_name, branch, build_pack, port, status (active | paused - the container lifecycle, distinct from a run's status), deploy_url, custom domains, and an inline \`deployment_runs\` array (newest 50). ${RUN_STATUS_NOTE}`, {
|
|
36
|
+
is_preview: z.boolean().optional().describe("If set, filter by preview-deployment flag"),
|
|
37
|
+
}, async ({ is_preview }) => {
|
|
38
|
+
if (!hasOrg())
|
|
39
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
40
|
+
const result = await apiRequest(DEPLOYMENTS_BASE, {
|
|
41
|
+
query: { is_preview: is_preview === undefined ? undefined : String(is_preview) },
|
|
42
|
+
toolName: "list_deployments",
|
|
43
|
+
});
|
|
44
|
+
if (!result.success) {
|
|
45
|
+
return { content: [{ type: "text", text: `Failed to list deployments (${result.statusCode}): ${result.message}` }] };
|
|
46
|
+
}
|
|
47
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
48
|
+
});
|
|
49
|
+
server.tool("get_deployment", `Get one deployment by pid, including its inline build/run history (\`deployment_runs\`, newest 50) and the \`current_deployment_run_pid\`. Use this to POLL deploy progress after \`trigger_deploy\`/\`redeploy_run\`/\`rollback_run\`: re-call every ~5s until the latest run reaches a terminal status. ${RUN_STATUS_NOTE}`, {
|
|
50
|
+
deployment_pid: z.string().min(1),
|
|
51
|
+
}, async ({ deployment_pid }) => {
|
|
52
|
+
if (!hasOrg())
|
|
53
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
54
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}`, {
|
|
55
|
+
toolName: "get_deployment",
|
|
56
|
+
});
|
|
57
|
+
if (!result.success) {
|
|
58
|
+
return { content: [{ type: "text", text: `Failed to get deployment (${result.statusCode}): ${result.message}` }] };
|
|
59
|
+
}
|
|
60
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
61
|
+
});
|
|
62
|
+
server.tool("create_deployment", "Create a deployment (app) from a GitHub repo inside an existing project. The project (`coolify_project_pid`) MUST already be `active` (provisioned) - check `get_project` first. Provisions a Coolify app and enqueues the first build automatically. For private repos you must pass `installation_id` (from `list_github_installations`). If build_pack/port are omitted they're auto-detected (you can pre-run `detect_repo_config`). Returns the deployment + its first run; poll `get_deployment` for build progress.", {
|
|
63
|
+
repo_url: z.string().min(1).describe("https://github.com/owner/repo (optionally /tree/<branch>/<subdir>)"),
|
|
64
|
+
coolify_project_pid: z.string().min(1).describe("Target project pid; must be status `active`"),
|
|
65
|
+
branch: z.string().optional().describe("Branch to deploy; defaults to the repo's default branch"),
|
|
66
|
+
installation_id: z.number().int().optional().describe("GitHub App installation numeric id; required for private repos"),
|
|
67
|
+
environment: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "lowercase alphanumeric + hyphens").max(50).optional().describe("Coolify environment name (default production)"),
|
|
68
|
+
build_pack: z.enum(BUILD_PACKS).optional().describe("Build strategy; auto-detected if omitted"),
|
|
69
|
+
base_directory: z.string().optional().describe("Monorepo sub-directory to build from"),
|
|
70
|
+
dockerfile_location: z.string().optional().describe("Path to Dockerfile (when build_pack=dockerfile and it's nested)"),
|
|
71
|
+
port: z.number().int().min(1).max(65535).optional().describe("Container port; auto-detected/defaults to 3000"),
|
|
72
|
+
env_vars: z.record(z.string()).optional().describe("Initial environment variables { KEY: value }. Keys must match ^[A-Za-z_][A-Za-z0-9_]*$; values must be non-empty."),
|
|
73
|
+
required_env_vars: z.array(z.string()).optional().describe("Keys that must be present and non-blank in env_vars"),
|
|
74
|
+
custom_domain: z.string().optional().describe("Custom domain to attach after creation"),
|
|
75
|
+
}, async (args) => {
|
|
76
|
+
if (!hasOrg())
|
|
77
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
78
|
+
const body = {
|
|
79
|
+
repo_url: args.repo_url,
|
|
80
|
+
coolify_project_pid: args.coolify_project_pid,
|
|
81
|
+
};
|
|
82
|
+
if (args.branch !== undefined)
|
|
83
|
+
body.branch = args.branch;
|
|
84
|
+
if (args.installation_id !== undefined)
|
|
85
|
+
body.installation_id = args.installation_id;
|
|
86
|
+
if (args.environment !== undefined)
|
|
87
|
+
body.environment = args.environment;
|
|
88
|
+
if (args.build_pack !== undefined)
|
|
89
|
+
body.build_pack = args.build_pack;
|
|
90
|
+
if (args.base_directory !== undefined)
|
|
91
|
+
body.base_directory = args.base_directory;
|
|
92
|
+
if (args.dockerfile_location !== undefined)
|
|
93
|
+
body.dockerfile_location = args.dockerfile_location;
|
|
94
|
+
if (args.port !== undefined)
|
|
95
|
+
body.port = args.port;
|
|
96
|
+
if (args.env_vars !== undefined)
|
|
97
|
+
body.env_vars = args.env_vars;
|
|
98
|
+
if (args.required_env_vars !== undefined)
|
|
99
|
+
body.required_env_vars = args.required_env_vars;
|
|
100
|
+
if (args.custom_domain !== undefined)
|
|
101
|
+
body.custom_domain = args.custom_domain;
|
|
102
|
+
const result = await apiRequest(DEPLOYMENTS_BASE, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
body,
|
|
105
|
+
toolName: "create_deployment",
|
|
106
|
+
});
|
|
107
|
+
if (!result.success) {
|
|
108
|
+
return { content: [{ type: "text", text: `Failed to create deployment (${result.statusCode}): ${result.message}` }] };
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{ type: "text", text: "Deployment created and first build enqueued. Poll `get_deployment` until the latest run reaches a terminal status." },
|
|
113
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
server.tool("update_deployment", "Update a deployment's lifecycle/routing settings: pause/resume (`status`), toggle GitHub-push auto-deploy, set ignore_paths, or cap concurrent preview deployments. Pass at least one field. To change build settings (build_pack/port/base_directory) use `update_deployment_build_config` instead. Pausing blocks deploys until resumed.", {
|
|
118
|
+
deployment_pid: z.string().min(1),
|
|
119
|
+
status: z.enum(DEPLOY_STATUSES).optional().describe("`paused` suspends deploys; `active` resumes"),
|
|
120
|
+
auto_deploy: z.boolean().optional().describe("Auto-deploy on GitHub push"),
|
|
121
|
+
ignore_paths: z.array(z.string()).optional().describe("Paths excluded from auto-deploy triggers (replaces the list)"),
|
|
122
|
+
max_concurrent_previews: z.number().int().min(1).max(20).optional().describe("Max simultaneous preview deployments (1-20)"),
|
|
123
|
+
}, async ({ deployment_pid, status, auto_deploy, ignore_paths, max_concurrent_previews }) => {
|
|
124
|
+
if (!hasOrg())
|
|
125
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
126
|
+
const body = {};
|
|
127
|
+
if (status !== undefined)
|
|
128
|
+
body.status = status;
|
|
129
|
+
if (auto_deploy !== undefined)
|
|
130
|
+
body.auto_deploy = auto_deploy;
|
|
131
|
+
if (ignore_paths !== undefined)
|
|
132
|
+
body.ignore_paths = ignore_paths;
|
|
133
|
+
if (max_concurrent_previews !== undefined)
|
|
134
|
+
body.max_concurrent_previews = max_concurrent_previews;
|
|
135
|
+
if (Object.keys(body).length === 0) {
|
|
136
|
+
return { content: [{ type: "text", text: "No changes - pass at least one of status / auto_deploy / ignore_paths / max_concurrent_previews." }] };
|
|
137
|
+
}
|
|
138
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}`, {
|
|
139
|
+
method: "PATCH",
|
|
140
|
+
body,
|
|
141
|
+
toolName: "update_deployment",
|
|
142
|
+
});
|
|
143
|
+
if (!result.success) {
|
|
144
|
+
return { content: [{ type: "text", text: `Failed to update deployment (${result.statusCode}): ${result.message}` }] };
|
|
145
|
+
}
|
|
146
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
147
|
+
});
|
|
148
|
+
server.tool("update_deployment_build_config", "Update a deployment's build configuration: build_pack, base_directory, port, dockerfile_location, and/or env_vars. The deployment must be provisioned (have a Coolify app) - otherwise returns 422. WARNING: if `env_vars` is provided it FULLY REPLACES the variable set (keys not included are deleted); to add/edit without deleting, use `set_env_vars`/`merge_env_vars` instead. Pass at least one field.", {
|
|
149
|
+
deployment_pid: z.string().min(1),
|
|
150
|
+
build_pack: z.enum(BUILD_PACKS).optional(),
|
|
151
|
+
base_directory: z.string().optional(),
|
|
152
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
153
|
+
dockerfile_location: z.string().optional(),
|
|
154
|
+
env_vars: z.record(z.string()).optional().describe("FULL REPLACEMENT of all env vars { KEY: value }"),
|
|
155
|
+
}, async ({ deployment_pid, build_pack, base_directory, port, dockerfile_location, env_vars }) => {
|
|
156
|
+
if (!hasOrg())
|
|
157
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
158
|
+
const body = {};
|
|
159
|
+
if (build_pack !== undefined)
|
|
160
|
+
body.build_pack = build_pack;
|
|
161
|
+
if (base_directory !== undefined)
|
|
162
|
+
body.base_directory = base_directory;
|
|
163
|
+
if (port !== undefined)
|
|
164
|
+
body.port = port;
|
|
165
|
+
if (dockerfile_location !== undefined)
|
|
166
|
+
body.dockerfile_location = dockerfile_location;
|
|
167
|
+
if (env_vars !== undefined)
|
|
168
|
+
body.env_vars = env_vars;
|
|
169
|
+
if (Object.keys(body).length === 0) {
|
|
170
|
+
return { content: [{ type: "text", text: "No changes - pass at least one build-config field." }] };
|
|
171
|
+
}
|
|
172
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/build_config`, {
|
|
173
|
+
method: "PATCH",
|
|
174
|
+
body,
|
|
175
|
+
toolName: "update_deployment_build_config",
|
|
176
|
+
});
|
|
177
|
+
if (!result.success) {
|
|
178
|
+
return { content: [{ type: "text", text: `Failed to update build config (${result.statusCode}): ${result.message}` }] };
|
|
179
|
+
}
|
|
180
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
181
|
+
});
|
|
182
|
+
server.tool("delete_deployment", "Delete a deployment and its Coolify app, build history, env vars, and attached domains. Irreversible.", {
|
|
183
|
+
deployment_pid: z.string().min(1),
|
|
184
|
+
name: z.string().optional().describe("Repo/app name for the confirmation message (cosmetic)"),
|
|
185
|
+
confirm: z.boolean().describe("Must be true. Removes the app and all its data."),
|
|
186
|
+
}, async ({ deployment_pid, name, confirm }) => {
|
|
187
|
+
if (!hasOrg())
|
|
188
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
189
|
+
if (!confirm) {
|
|
190
|
+
const label = name ? `\`${name}\` (${deployment_pid})` : deployment_pid;
|
|
191
|
+
return { content: [{ type: "text", text: `⚠️ About to DELETE deployment ${label} - removes the Coolify app, build history, env vars, and domains. No undo.\n\nCall again with confirm=true to proceed.` }] };
|
|
192
|
+
}
|
|
193
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}`, {
|
|
194
|
+
method: "DELETE",
|
|
195
|
+
toolName: "delete_deployment",
|
|
196
|
+
});
|
|
197
|
+
if (!result.success) {
|
|
198
|
+
return { content: [{ type: "text", text: `Failed to delete deployment (${result.statusCode}): ${result.message}` }] };
|
|
199
|
+
}
|
|
200
|
+
return { content: [{ type: "text", text: "Deployment removed successfully." }] };
|
|
201
|
+
});
|
|
202
|
+
server.tool("trigger_deploy", "Trigger a manual deploy of a deployment's current branch (creates a new build run). Returns 409 if a deploy is already in progress (one deploy at a time), or 422 if the deployment is paused or not yet provisioned. Poll `get_deployment` for the new run's progress.", {
|
|
203
|
+
deployment_pid: z.string().min(1),
|
|
204
|
+
}, async ({ deployment_pid }) => {
|
|
205
|
+
if (!hasOrg())
|
|
206
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
207
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/deploy`, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
toolName: "trigger_deploy",
|
|
210
|
+
});
|
|
211
|
+
if (!result.success) {
|
|
212
|
+
return { content: [{ type: "text", text: `Failed to trigger deploy (${result.statusCode}): ${result.message}` }] };
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
content: [
|
|
216
|
+
{ type: "text", text: "Deploy triggered (new run enqueued). Poll `get_deployment` or `get_run_logs` for progress." },
|
|
217
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
});
|
|
221
|
+
server.tool("get_deployment_logs", "Get the deployment's current application/container logs (the running app's stdout/stderr). For per-build logs of a specific run, use `get_run_logs` instead. Returns 422 if the deployment isn't provisioned yet.", {
|
|
222
|
+
deployment_pid: z.string().min(1),
|
|
223
|
+
}, async ({ deployment_pid }) => {
|
|
224
|
+
if (!hasOrg())
|
|
225
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
226
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/logs`, {
|
|
227
|
+
toolName: "get_deployment_logs",
|
|
228
|
+
});
|
|
229
|
+
if (!result.success) {
|
|
230
|
+
return { content: [{ type: "text", text: `Failed to get deployment logs (${result.statusCode}): ${result.message}` }] };
|
|
231
|
+
}
|
|
232
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
233
|
+
});
|
|
234
|
+
server.tool("get_deployment_health", "Get a deployment's health: whether the deploy_url is reachable, when it was last checked, any error, and the attached domains.", {
|
|
235
|
+
deployment_pid: z.string().min(1),
|
|
236
|
+
}, async ({ deployment_pid }) => {
|
|
237
|
+
if (!hasOrg())
|
|
238
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
239
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/health`, {
|
|
240
|
+
toolName: "get_deployment_health",
|
|
241
|
+
});
|
|
242
|
+
if (!result.success) {
|
|
243
|
+
return { content: [{ type: "text", text: `Failed to get deployment health (${result.statusCode}): ${result.message}` }] };
|
|
244
|
+
}
|
|
245
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
246
|
+
});
|
|
247
|
+
server.tool("get_run_logs", `Get the full build + container logs for one deployment run, plus the run object. The returned log buffer is cumulative and idempotent - each call returns the whole buffer, so REPLACE (don't append) on each poll. To stream a live build, re-call every ~5-10s until \`deployment_run.status\` is terminal. A 422 "Deployment has not started yet" means the run is still enqueued - back off and retry. ${RUN_STATUS_NOTE}`, {
|
|
248
|
+
deployment_pid: z.string().min(1),
|
|
249
|
+
run_pid: z.string().min(1).describe("Run pid, e.g. run_01h... (from a deployment's deployment_runs)"),
|
|
250
|
+
}, async ({ deployment_pid, run_pid }) => {
|
|
251
|
+
if (!hasOrg())
|
|
252
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
253
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/runs/${run_pid}/logs`, {
|
|
254
|
+
toolName: "get_run_logs",
|
|
255
|
+
});
|
|
256
|
+
if (!result.success) {
|
|
257
|
+
return { content: [{ type: "text", text: `Failed to get run logs (${result.statusCode}): ${result.message}` }] };
|
|
258
|
+
}
|
|
259
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
260
|
+
});
|
|
261
|
+
server.tool("redeploy_run", "Re-run a previous build from the SAME commit it used. Useful to retry a failed build or rebuild without a new push. Requires the source run to have a commit SHA, the deployment to be active, and no in-progress run (422 otherwise). Creates a new run; poll `get_deployment`.", {
|
|
262
|
+
deployment_pid: z.string().min(1),
|
|
263
|
+
run_pid: z.string().min(1).describe("The run to re-run (its commit will be redeployed)"),
|
|
264
|
+
}, async ({ deployment_pid, run_pid }) => {
|
|
265
|
+
if (!hasOrg())
|
|
266
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
267
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/runs/${run_pid}/redeploy`, {
|
|
268
|
+
method: "POST",
|
|
269
|
+
toolName: "redeploy_run",
|
|
270
|
+
});
|
|
271
|
+
if (!result.success) {
|
|
272
|
+
return { content: [{ type: "text", text: `Failed to redeploy (${result.statusCode}): ${result.message}` }] };
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{ type: "text", text: "Redeploy triggered (new run from the same commit)." },
|
|
277
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
server.tool("rollback_run", "Roll back by re-deploying the commit from a PRIOR SUCCESSFUL run. Only runs with status `active` (deployed successfully) can be rolled back to - returns 422 otherwise. Requires the deployment to be active and no in-progress run. Creates a new run; poll `get_deployment`.", {
|
|
282
|
+
deployment_pid: z.string().min(1),
|
|
283
|
+
run_pid: z.string().min(1).describe("A previously-successful run to roll back to (status must be `active`)"),
|
|
284
|
+
}, async ({ deployment_pid, run_pid }) => {
|
|
285
|
+
if (!hasOrg())
|
|
286
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
287
|
+
const result = await apiRequest(`${DEPLOYMENTS_BASE}/${deployment_pid}/runs/${run_pid}/rollback`, {
|
|
288
|
+
method: "POST",
|
|
289
|
+
toolName: "rollback_run",
|
|
290
|
+
});
|
|
291
|
+
if (!result.success) {
|
|
292
|
+
return { content: [{ type: "text", text: `Failed to roll back (${result.statusCode}): ${result.message}` }] };
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
content: [
|
|
296
|
+
{ type: "text", text: "Rollback triggered (re-deploying the selected run's commit)." },
|
|
297
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
298
|
+
],
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=deployments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployments.js","sourceRoot":"","sources":["../../src/tools/deployments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,gBAAgB,GAAG,0CAA0C,CAAC;AACpE,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,CAAU,CAAC;AACnF,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEtD,MAAM,MAAM,GACV,qFAAqF,CAAC;AAExF,SAAS,MAAM;IACb,OAAO,OAAO,CAAC,cAAc,EAAE,KAAK,IAAI,CAAC;AAC3C,CAAC;AAED,MAAM,eAAe,GACnB,+NAA+N,CAAC;AAElO,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,wRAAwR,eAAe,EAAE,EACzS;QACE,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACzF,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACvB,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,gBAAgB,EAAE;YACzD,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;YAChF,QAAQ,EAAE,kBAAkB;SAC7B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACvH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,6SAA6S,eAAe,EAAE,EAC9T;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAClC,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,EAAE,EAAE;YAChF,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,6BAA6B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACrH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,4fAA4f,EAC5f;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oEAAoE,CAAC;QAC1G,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QAC9F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;QACjG,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gEAAgE,CAAC;QACvH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,sBAAsB,EAAE,kCAAkC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QACtK,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QAC/F,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACtF,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;QACtH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;QAC9G,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mHAAmH,CAAC;QACvK,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;QACjH,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;KACxF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAA4B;YACpC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC9C,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACzD,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;YAAE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QACpF,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACxE,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACrE,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS;YAAE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QACjF,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS;YAAE,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAChG,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/D,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS;YAAE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAC1F,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS;YAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAE9E,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,gBAAgB,EAAE;YACzD,MAAM,EAAE,MAAM;YACd,IAAI;YACJ,QAAQ,EAAE,mBAAmB;SAC9B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gCAAgC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACxH,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oHAAoH,EAAE;gBAC5I,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAC7D;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,4UAA4U,EAC5U;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QAClG,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QAC1E,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;QACrH,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;KAC5H,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,uBAAuB,EAAE,EAAE,EAAE;QACvF,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAC/C,IAAI,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC9D,IAAI,YAAY,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjE,IAAI,uBAAuB,KAAK,SAAS;YAAE,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QAClG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kGAAkG,EAAE,CAAC,EAAE,CAAC;QACnJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,EAAE,EAAE;YAChF,MAAM,EAAE,OAAO;YACf,IAAI;YACJ,QAAQ,EAAE,mBAAmB;SAC9B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gCAAgC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACxH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gCAAgC,EAChC,gZAAgZ,EAChZ;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE;QAC1C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;QACnD,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;KACtG,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC5F,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,IAAI,UAAU,KAAK,SAAS;YAAE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC3D,IAAI,cAAc,KAAK,SAAS;YAAE,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACvE,IAAI,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACzC,IAAI,mBAAmB,KAAK,SAAS;YAAE,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QACtF,IAAI,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACrD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oDAAoD,EAAE,CAAC,EAAE,CAAC;QACrG,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,eAAe,EAAE;YAC7F,MAAM,EAAE,OAAO;YACf,IAAI;YACJ,QAAQ,EAAE,gCAAgC;SAC3C,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,uGAAuG,EACvG;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QAC7F,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;KACjF,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,cAAc,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,KAAK,wHAAwH,EAAE,CAAC,EAAE,CAAC;QAChN,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,EAAE,EAAE;YAChF,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,mBAAmB;SAC9B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gCAAgC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACxH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,yQAAyQ,EACzQ;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAClC,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,SAAS,EAAE;YACvF,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,6BAA6B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACrH,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,4FAA4F,EAAE;gBACpH,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAC7D;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,mNAAmN,EACnN;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAClC,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,OAAO,EAAE;YACrF,QAAQ,EAAE,qBAAqB;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,gIAAgI,EAChI;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAClC,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,SAAS,EAAE;YACvF,QAAQ,EAAE,uBAAuB;SAClC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oCAAoC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC5H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,8YAA8Y,eAAe,EAAE,EAC/Z;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gEAAgE,CAAC;KACtG,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,EAAE;QACpC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,SAAS,OAAO,OAAO,EAAE;YACrG,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACnH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,kRAAkR,EAClR;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mDAAmD,CAAC;KACzF,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,EAAE;QACpC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,SAAS,OAAO,WAAW,EAAE;YACzG,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC/G,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oDAAoD,EAAE;gBAC5E,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAC7D;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,gRAAgR,EAChR;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uEAAuE,CAAC;KAC7G,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,EAAE;QACpC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,gBAAgB,IAAI,cAAc,SAAS,OAAO,WAAW,EAAE;YACzG,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAChH,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8DAA8D,EAAE;gBACtF,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAC7D;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|