@studiometa/forge-mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +7 -6
  2. package/dist/formatters.d.ts +101 -36
  3. package/dist/formatters.d.ts.map +1 -1
  4. package/dist/handlers/backups.d.ts.map +1 -1
  5. package/dist/handlers/batch.d.ts.map +1 -1
  6. package/dist/handlers/certificates.d.ts.map +1 -1
  7. package/dist/handlers/commands.d.ts.map +1 -1
  8. package/dist/handlers/context.d.ts.map +1 -1
  9. package/dist/handlers/daemons.d.ts.map +1 -1
  10. package/dist/handlers/database-users.d.ts.map +1 -1
  11. package/dist/handlers/databases.d.ts.map +1 -1
  12. package/dist/handlers/deployments.d.ts.map +1 -1
  13. package/dist/handlers/env.d.ts.map +1 -1
  14. package/dist/handlers/factory.d.ts +7 -37
  15. package/dist/handlers/factory.d.ts.map +1 -1
  16. package/dist/handlers/firewall-rules.d.ts.map +1 -1
  17. package/dist/handlers/help.d.ts.map +1 -1
  18. package/dist/handlers/index.d.ts +1 -0
  19. package/dist/handlers/index.d.ts.map +1 -1
  20. package/dist/handlers/monitors.d.ts.map +1 -1
  21. package/dist/handlers/nginx-config.d.ts.map +1 -1
  22. package/dist/handlers/nginx-templates.d.ts.map +1 -1
  23. package/dist/handlers/recipes.d.ts.map +1 -1
  24. package/dist/handlers/redirect-rules.d.ts.map +1 -1
  25. package/dist/handlers/scheduled-jobs.d.ts.map +1 -1
  26. package/dist/handlers/security-rules.d.ts.map +1 -1
  27. package/dist/handlers/servers.d.ts.map +1 -1
  28. package/dist/handlers/sites.d.ts.map +1 -1
  29. package/dist/handlers/ssh-keys.d.ts.map +1 -1
  30. package/dist/handlers/user.d.ts.map +1 -1
  31. package/dist/handlers/utils.d.ts +1 -1
  32. package/dist/handlers/utils.d.ts.map +1 -1
  33. package/dist/hints.d.ts +1 -1
  34. package/dist/hints.d.ts.map +1 -1
  35. package/dist/{http-Cwp91mT-.js → http-K9wiprZX.js} +16 -12
  36. package/dist/http-K9wiprZX.js.map +1 -0
  37. package/dist/http.d.ts +1 -1
  38. package/dist/http.d.ts.map +1 -1
  39. package/dist/http.js +2 -2
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +21 -10
  42. package/dist/index.js.map +1 -1
  43. package/dist/oauth.d.ts +1 -1
  44. package/dist/oauth.d.ts.map +1 -1
  45. package/dist/oauth.js +42 -41
  46. package/dist/oauth.js.map +1 -1
  47. package/dist/server.js +2 -2
  48. package/dist/sessions.d.ts.map +1 -1
  49. package/dist/stdio.d.ts +4 -2
  50. package/dist/stdio.d.ts.map +1 -1
  51. package/dist/tools.d.ts.map +1 -1
  52. package/dist/{version-CIiN0iJr.js → version-CHrJu_54.js} +922 -364
  53. package/dist/version-CHrJu_54.js.map +1 -0
  54. package/package.json +4 -4
  55. package/skills/SKILL.md +14 -12
  56. package/dist/http-Cwp91mT-.js.map +0 -1
  57. package/dist/version-CIiN0iJr.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"version-CIiN0iJr.js","names":[],"sources":["../src/instructions.ts","../src/formatters.ts","../src/errors.ts","../src/handlers/utils.ts","../src/handlers/factory.ts","../src/handlers/backups.ts","../src/tools.ts","../src/handlers/batch.ts","../src/hints.ts","../src/handlers/certificates.ts","../src/handlers/commands.ts","../src/handlers/daemons.ts","../src/handlers/databases.ts","../src/handlers/database-users.ts","../src/handlers/deployments.ts","../src/handlers/env.ts","../src/handlers/firewall-rules.ts","../src/handlers/help.ts","../src/handlers/monitors.ts","../src/handlers/nginx-config.ts","../src/handlers/nginx-templates.ts","../src/handlers/recipes.ts","../src/handlers/redirect-rules.ts","../src/handlers/scheduled-jobs.ts","../src/handlers/schema.ts","../src/handlers/security-rules.ts","../src/handlers/context.ts","../src/handlers/servers.ts","../src/handlers/sites.ts","../src/handlers/ssh-keys.ts","../src/handlers/user.ts","../src/handlers/auto-resolve.ts","../src/handlers/index.ts","../src/version.ts"],"sourcesContent":["/**\n * MCP Server Instructions\n *\n * These instructions are sent to MCP clients during initialization\n * and used as context/hints for the LLM. Ensures the AI agent\n * knows how to properly use the Forge MCP server.\n *\n * The content is derived from skills/SKILL.md (without YAML frontmatter).\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Load instructions from SKILL.md file.\n * Removes YAML frontmatter (content between --- markers).\n */\nfunction loadInstructions(): string {\n try {\n // In dist/, go up to package root, then to skills/\n const skillPath = join(__dirname, \"..\", \"skills\", \"SKILL.md\");\n const content = readFileSync(skillPath, \"utf-8\");\n\n // Remove YAML frontmatter (between --- markers at start of file)\n const withoutFrontmatter = content.replace(/^---\\n[\\s\\S]*?\\n---\\n+/, \"\");\n\n return withoutFrontmatter.trim();\n } catch {\n return 'Laravel Forge MCP Server - Use the forge tool with resource and action parameters. Call action=\"help\" for documentation.';\n }\n}\n\nexport const INSTRUCTIONS = loadInstructions();\n","/**\n * Response formatters for MCP tool output.\n *\n * This module contains per-resource formatter functions that convert\n * executor data payloads into human-readable text for MCP responses.\n *\n * Keeping formatting in the MCP layer ensures executors remain pure data\n * functions that can be reused by any adapter (CLI, SDK, etc.).\n */\n\nimport type {\n ForgeBackupConfig,\n ForgeCertificate,\n ForgeCommand,\n ForgeDaemon,\n ForgeDatabase,\n ForgeDatabaseUser,\n ForgeDeployment,\n ForgeFirewallRule,\n ForgeMonitor,\n ForgeNginxTemplate,\n ForgeRecipe,\n ForgeRedirectRule,\n ForgeScheduledJob,\n ForgeSecurityRule,\n ForgeServer,\n ForgeSite,\n ForgeSshKey,\n ForgeUser,\n} from \"@studiometa/forge-api\";\n\n// ── Servers ──────────────────────────────────────────\n\n/**\n * Format a list of servers.\n */\nexport function formatServerList(servers: ForgeServer[]): string {\n if (servers.length === 0) {\n return \"No servers found.\";\n }\n const lines = servers.map(\n (s) =>\n `• ${s.name} (ID: ${s.id}) — ${s.provider} ${s.region} — ${s.ip_address} — ${s.is_ready ? \"ready\" : \"provisioning\"}`,\n );\n return `${servers.length} server(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single server.\n */\nexport function formatServer(server: ForgeServer): string {\n return [\n `Server: ${server.name} (ID: ${server.id})`,\n `Provider: ${server.provider} (${server.region})`,\n `IP: ${server.ip_address}`,\n `PHP: ${server.php_version}`,\n `Ubuntu: ${server.ubuntu_version}`,\n `Status: ${server.is_ready ? \"ready\" : \"provisioning\"}`,\n `Created: ${server.created_at}`,\n ].join(\"\\n\");\n}\n\n// ── Sites ────────────────────────────────────────────\n\n/**\n * Format a list of sites.\n */\nexport function formatSiteList(sites: ForgeSite[], serverId?: string): string {\n if (sites.length === 0) {\n return serverId ? `No sites on server ${serverId}.` : \"No sites found.\";\n }\n const lines = sites.map((s) => `• ${s.name} (ID: ${s.id}) — ${s.project_type} — ${s.status}`);\n const header = serverId\n ? `${sites.length} site(s) on server ${serverId}:`\n : `${sites.length} site(s):`;\n return `${header}\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single site.\n */\nexport function formatSite(site: ForgeSite): string {\n return [\n `Site: ${site.name} (ID: ${site.id})`,\n `Type: ${site.project_type}`,\n `Directory: ${site.directory}`,\n `Repository: ${site.repository ?? \"none\"}`,\n `Branch: ${site.repository_branch ?? \"none\"}`,\n `Status: ${site.status}`,\n `Deploy status: ${site.deployment_status ?? \"none\"}`,\n `Quick deploy: ${site.quick_deploy ? \"enabled\" : \"disabled\"}`,\n `PHP: ${site.php_version}`,\n `Created: ${site.created_at}`,\n ].join(\"\\n\");\n}\n\n// ── Databases ────────────────────────────────────────\n\n/**\n * Format a list of databases.\n */\nexport function formatDatabaseList(databases: ForgeDatabase[]): string {\n if (databases.length === 0) {\n return \"No databases found.\";\n }\n const lines = databases.map((d) => `• ${d.name} (ID: ${d.id}) — ${d.status}`);\n return `${databases.length} database(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single database.\n */\nexport function formatDatabase(db: ForgeDatabase): string {\n return `Database: ${db.name} (ID: ${db.id})\\nStatus: ${db.status}\\nCreated: ${db.created_at}`;\n}\n\n// ── Database Users ────────────────────────────────────\n\n/**\n * Format a list of database users.\n */\nexport function formatDatabaseUserList(users: ForgeDatabaseUser[]): string {\n if (users.length === 0) {\n return \"No database users found.\";\n }\n const lines = users.map((u) => `• ${u.name} (ID: ${u.id}) — ${u.status}`);\n return `${users.length} database user(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single database user.\n */\nexport function formatDatabaseUser(user: ForgeDatabaseUser): string {\n return [\n `Database User: ${user.name} (ID: ${user.id})`,\n `Status: ${user.status}`,\n `Databases: ${user.databases.length > 0 ? user.databases.join(\", \") : \"none\"}`,\n `Created: ${user.created_at}`,\n ].join(\"\\n\");\n}\n\n// ── Deployments ──────────────────────────────────────\n\n/**\n * Format a list of deployments.\n */\nexport function formatDeploymentList(deployments: ForgeDeployment[]): string {\n if (deployments.length === 0) {\n return \"No deployments found.\";\n }\n const lines = deployments.map(\n (d) =>\n `• #${d.id} — ${d.status} — ${d.commit_hash?.slice(0, 7) ?? \"no commit\"} — ${d.started_at}`,\n );\n return `${deployments.length} deployment(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a deployment action result.\n *\n * When a `DeployResult` is provided the output includes status, elapsed time,\n * and the deployment log. When called with just IDs (legacy) it falls back to\n * the simple confirmation message so existing tests keep passing.\n */\nexport function formatDeployAction(\n siteId: string,\n serverId: string,\n result?: { status: \"success\" | \"failed\"; log: string; elapsed_ms: number },\n): string {\n if (!result) {\n return `Deployment triggered for site ${siteId} on server ${serverId}.`;\n }\n\n const elapsedSec = (result.elapsed_ms / 1000).toFixed(1);\n const statusLabel = result.status === \"success\" ? \"✓ succeeded\" : \"✗ failed\";\n const lines = [\n `Deployment ${statusLabel} for site ${siteId} on server ${serverId} (${elapsedSec}s).`,\n ];\n\n if (result.log) {\n lines.push(\"\", \"Deployment log:\", result.log);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format deployment script content.\n */\nexport function formatDeploymentScript(script: string): string {\n return `Deployment script:\\n${script}`;\n}\n\n/**\n * Format deployment output.\n */\nexport function formatDeploymentOutput(deploymentId: string, output: string): string {\n return `Deployment ${deploymentId} output:\\n${output}`;\n}\n\n/**\n * Format a deployment script update confirmation.\n */\nexport function formatDeploymentScriptUpdated(siteId: string, serverId: string): string {\n return `Deployment script updated for site ${siteId} on server ${serverId}.`;\n}\n\n// ── Certificates ─────────────────────────────────────\n\n/**\n * Format a list of certificates.\n */\nexport function formatCertificateList(certificates: ForgeCertificate[]): string {\n if (certificates.length === 0) {\n return \"No certificates found.\";\n }\n const lines = certificates.map(\n (c) =>\n `• ${c.domain} (ID: ${c.id}) — ${c.type} — ${c.active ? \"active\" : \"inactive\"} — ${c.status}`,\n );\n return `${certificates.length} certificate(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single certificate.\n */\nexport function formatCertificate(cert: ForgeCertificate): string {\n return `Certificate: ${cert.domain} (ID: ${cert.id})\\nType: ${cert.type}\\nStatus: ${cert.status}\\nActive: ${cert.active}`;\n}\n\n// ── Daemons ──────────────────────────────────────────\n\n/**\n * Format a list of daemons.\n */\nexport function formatDaemonList(daemons: ForgeDaemon[]): string {\n if (daemons.length === 0) {\n return \"No daemons found.\";\n }\n const lines = daemons.map((d) => `• ${d.command} (ID: ${d.id}) — user: ${d.user} — ${d.status}`);\n return `${daemons.length} daemon(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single daemon.\n */\nexport function formatDaemon(daemon: ForgeDaemon): string {\n return `Daemon: ${daemon.command} (ID: ${daemon.id})\\nUser: ${daemon.user}\\nProcesses: ${daemon.processes}\\nStatus: ${daemon.status}`;\n}\n\n// ── Firewall Rules ───────────────────────────────────\n\n/**\n * Format a list of firewall rules.\n */\nexport function formatFirewallRuleList(rules: ForgeFirewallRule[]): string {\n if (rules.length === 0) {\n return \"No firewall rules found.\";\n }\n const lines = rules.map(\n (r) => `• ${r.name} (ID: ${r.id}) — port: ${r.port} — ${r.ip_address} — ${r.status}`,\n );\n return `${rules.length} firewall rule(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single firewall rule.\n */\nexport function formatFirewallRule(rule: ForgeFirewallRule): string {\n return `Firewall Rule: ${rule.name} (ID: ${rule.id})\\nPort: ${rule.port}\\nType: ${rule.type}\\nIP: ${rule.ip_address}\\nStatus: ${rule.status}`;\n}\n\n// ── Monitors ─────────────────────────────────────────\n\n/**\n * Format a list of monitors.\n */\nexport function formatMonitorList(monitors: ForgeMonitor[]): string {\n if (monitors.length === 0) {\n return \"No monitors found.\";\n }\n const lines = monitors.map(\n (m) => `• ${m.type} ${m.operator} ${m.threshold} (ID: ${m.id}) — ${m.state}`,\n );\n return `${monitors.length} monitor(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single monitor.\n */\nexport function formatMonitor(monitor: ForgeMonitor): string {\n return `Monitor: ${monitor.type} ${monitor.operator} ${monitor.threshold} (ID: ${monitor.id})\\nState: ${monitor.state}\\nMinutes: ${monitor.minutes}`;\n}\n\n// ── SSH Keys ─────────────────────────────────────────\n\n/**\n * Format a list of SSH keys.\n */\nexport function formatSshKeyList(keys: ForgeSshKey[]): string {\n if (keys.length === 0) {\n return \"No SSH keys found.\";\n }\n const lines = keys.map((k) => `• ${k.name} (ID: ${k.id}) — ${k.status}`);\n return `${keys.length} SSH key(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single SSH key.\n */\nexport function formatSshKey(key: ForgeSshKey): string {\n return `SSH Key: ${key.name} (ID: ${key.id})\\nStatus: ${key.status}\\nCreated: ${key.created_at}`;\n}\n\n// ── Scheduled Jobs ───────────────────────────────────\n\n/**\n * Format a list of scheduled jobs.\n */\nexport function formatScheduledJobList(jobs: ForgeScheduledJob[]): string {\n if (jobs.length === 0) {\n return \"No scheduled jobs found.\";\n }\n const lines = jobs.map(\n (j) => `• ${j.command} (ID: ${j.id}) — ${j.frequency} — ${j.status} — user: ${j.user}`,\n );\n return `${jobs.length} scheduled job(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single scheduled job.\n */\nexport function formatScheduledJob(job: ForgeScheduledJob): string {\n return [\n `Job: ${job.command} (ID: ${job.id})`,\n `User: ${job.user}`,\n `Frequency: ${job.frequency}`,\n `Cron: ${job.cron}`,\n `Status: ${job.status}`,\n `Created: ${job.created_at}`,\n ].join(\"\\n\");\n}\n\n// ── Security Rules ───────────────────────────────────\n\n/**\n * Format a list of security rules.\n */\nexport function formatSecurityRuleList(rules: ForgeSecurityRule[]): string {\n if (rules.length === 0) {\n return \"No security rules found.\";\n }\n const lines = rules.map((r) => `• ${r.name} (ID: ${r.id}) — path: ${r.path ?? \"/\"}`);\n return `${rules.length} security rule(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single security rule.\n */\nexport function formatSecurityRule(rule: ForgeSecurityRule): string {\n return `Security Rule: ${rule.name} (ID: ${rule.id})\\nPath: ${rule.path ?? \"/\"}`;\n}\n\n// ── Redirect Rules ───────────────────────────────────\n\n/**\n * Format a list of redirect rules.\n */\nexport function formatRedirectRuleList(rules: ForgeRedirectRule[]): string {\n if (rules.length === 0) {\n return \"No redirect rules found.\";\n }\n const lines = rules.map((r) => `• ${r.from} → ${r.to} (ID: ${r.id}) — ${r.type}`);\n return `${rules.length} redirect rule(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single redirect rule.\n */\nexport function formatRedirectRule(rule: ForgeRedirectRule): string {\n return `Redirect Rule: ${rule.from} → ${rule.to} (ID: ${rule.id})\\nType: ${rule.type}`;\n}\n\n// ── Nginx ────────────────────────────────────────────\n\n/**\n * Format nginx configuration content.\n */\nexport function formatNginxConfig(content: string): string {\n return `Nginx configuration:\\n${content}`;\n}\n\n// ── Nginx Templates ──────────────────────────────────\n\n/**\n * Format a list of nginx templates.\n */\nexport function formatNginxTemplateList(templates: ForgeNginxTemplate[]): string {\n if (templates.length === 0) {\n return \"No nginx templates found.\";\n }\n const lines = templates.map((t) => `• ${t.name} (ID: ${t.id})`);\n return `${templates.length} nginx template(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single nginx template.\n */\nexport function formatNginxTemplate(template: ForgeNginxTemplate): string {\n return `Nginx Template: ${template.name} (ID: ${template.id})\\n\\n${template.content}`;\n}\n\n// ── Backup Configs ───────────────────────────────────\n\n/**\n * Format a list of backup configurations.\n */\nexport function formatBackupConfigList(backups: ForgeBackupConfig[]): string {\n if (backups.length === 0) {\n return \"No backup configurations found.\";\n }\n const lines = backups.map(\n (b) =>\n `• ${b.provider_name} (ID: ${b.id}) — ${b.frequency} — ${b.status} — last: ${b.last_backup_time ?? \"never\"}`,\n );\n return `${backups.length} backup config(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single backup configuration.\n */\nexport function formatBackupConfig(backup: ForgeBackupConfig): string {\n return [\n `Backup Config: ${backup.provider_name} (ID: ${backup.id})`,\n `Frequency: ${backup.frequency}`,\n `Status: ${backup.status}`,\n `Retention: ${backup.retention} backups`,\n `Databases: ${backup.databases.map((d) => d.name).join(\", \") || \"none\"}`,\n `Last backup: ${backup.last_backup_time ?? \"never\"}`,\n ].join(\"\\n\");\n}\n\n// ── Recipes ──────────────────────────────────────────\n\n/**\n * Format a list of recipes.\n */\nexport function formatRecipeList(recipes: ForgeRecipe[]): string {\n if (recipes.length === 0) {\n return \"No recipes found.\";\n }\n const lines = recipes.map((r) => `• ${r.name} (ID: ${r.id}) — user: ${r.user}`);\n return `${recipes.length} recipe(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single recipe.\n */\nexport function formatRecipe(recipe: ForgeRecipe): string {\n return `Recipe: ${recipe.name} (ID: ${recipe.id})\\nUser: ${recipe.user}\\nScript:\\n${recipe.script}`;\n}\n\n// ── Commands ─────────────────────────────────────────\n\n/**\n * Format a list of commands.\n */\nexport function formatCommandList(commands: ForgeCommand[]): string {\n if (commands.length === 0) {\n return \"No commands found.\";\n }\n const lines = commands.map(\n (c) => `• #${c.id} — ${c.status} — ${c.user_name} — ${c.command.slice(0, 60)}`,\n );\n return `${commands.length} command(s):\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Format a single command.\n */\nexport function formatCommand(command: ForgeCommand): string {\n return [\n `Command #${command.id}`,\n `Command: ${command.command}`,\n `Status: ${command.status}`,\n `User: ${command.user_name}`,\n `Created: ${command.created_at}`,\n ].join(\"\\n\");\n}\n\n// ── Env ──────────────────────────────────────────────\n\n/**\n * Format environment variables content.\n */\nexport function formatEnv(content: string): string {\n return `Environment variables:\\n${content}`;\n}\n\n// ── User ─────────────────────────────────────────────\n\n/**\n * Format the authenticated user.\n */\nexport function formatUser(user: ForgeUser): string {\n return [\n `User: ${user.name} (ID: ${user.id})`,\n `Email: ${user.email}`,\n `GitHub: ${user.connected_to_github ? \"connected\" : \"not connected\"}`,\n `GitLab: ${user.connected_to_gitlab ? \"connected\" : \"not connected\"}`,\n `2FA: ${user.two_factor_enabled ? \"enabled\" : \"disabled\"}`,\n ].join(\"\\n\");\n}\n\n// ── Generic helpers ──────────────────────────────────\n\n/**\n * Format a deleted resource confirmation.\n */\nexport function formatDeleted(resource: string, id: string): string {\n return `${resource} ${id} deleted.`;\n}\n\n/**\n * Format a created resource confirmation (for simple cases).\n */\nexport function formatCreated(resource: string, name: string, id: number | string): string {\n return `${resource} created: ${name} (ID: ${id})`;\n}\n","/**\n * Custom error classes for MCP server\n *\n * These provide structured error handling with LLM-friendly messages\n * that include guidance on how to resolve issues.\n */\n\n/**\n * Error thrown when user input validation fails.\n * These errors should be returned to the user directly.\n *\n * Includes optional hints for how to resolve the issue.\n */\nexport class UserInputError extends Error {\n public readonly hints?: string[];\n\n constructor(message: string, hints?: string[]) {\n super(message);\n this.name = \"UserInputError\";\n this.hints = hints;\n }\n\n /**\n * Format error message with hints for LLM consumption\n */\n toFormattedMessage(): string {\n let msg = `**Input Error:** ${this.message}`;\n if (this.hints && this.hints.length > 0) {\n msg += \"\\n\\n**Hints:**\\n\" + this.hints.map((h) => `- ${h}`).join(\"\\n\");\n }\n return msg;\n }\n}\n\n/**\n * Error messages with guidance for common validation failures\n */\nexport const ErrorMessages = {\n // Required field errors\n missingId: (action: string) =>\n new UserInputError(`id is required for ${action} action`, [\n `Use action=\"list\" first to find the resource ID`,\n `Then use action=\"${action}\" with the id parameter`,\n ]),\n\n missingRequiredFields: (resource: string, fields: string[]) =>\n new UserInputError(\n `${fields.join(\", \")} ${fields.length === 1 ? \"is\" : \"are\"} required for creating ${resource}`,\n [\n `Provide all required fields: ${fields.join(\", \")}`,\n `Use action=\"help\" for detailed documentation on ${resource}`,\n ],\n ),\n\n // Invalid action errors\n invalidAction: (action: string, resource: string, validActions: string[]) =>\n new UserInputError(`Invalid action \"${action}\" for ${resource}`, [\n `Valid actions are: ${validActions.join(\", \")}`,\n `Use action=\"help\" with resource=\"${resource}\" for detailed documentation`,\n ]),\n\n // Unknown resource errors\n unknownResource: (resource: string, validResources: string[]) =>\n new UserInputError(`Unknown resource: ${resource}`, [\n `Valid resources are: ${validResources.join(\", \")}`,\n `Use action=\"help\" without a resource for an overview of all resources`,\n ]),\n\n // Update-specific errors\n noUpdateFieldsSpecified: (allowedFields: string[]) =>\n new UserInputError(\n `No updates specified. Provide at least one of: ${allowedFields.join(\", \")}`,\n [\"Specify at least one field to update\", `Updatable fields are: ${allowedFields.join(\", \")}`],\n ),\n\n // API errors\n apiError: (statusCode: number, message: string) => {\n const hints: string[] = [];\n\n if (statusCode === 401) {\n hints.push(\"Check that your API token is valid and not expired\");\n } else if (statusCode === 403) {\n hints.push(\"You may not have permission to access this resource\");\n hints.push(\"Check your API token permissions\");\n } else if (statusCode === 404) {\n hints.push(\"The resource may not exist or you may not have access\");\n hints.push(\"Verify the resource ID is correct\");\n hints.push('Use action=\"list\" to find valid resource IDs');\n } else if (statusCode === 422) {\n hints.push(\"The request data may be invalid\");\n hints.push(\"Check the field values and types\");\n hints.push('Use action=\"help\" for field documentation');\n } else if (statusCode >= 500) {\n hints.push(\"This is a server error - try again later\");\n }\n\n return new UserInputError(`API error (${statusCode}): ${message}`, hints);\n },\n} as const;\n\n/**\n * Check if an error is a UserInputError\n */\nexport function isUserInputError(error: unknown): error is UserInputError {\n return error instanceof UserInputError;\n}\n","import type { ToolResult } from \"./types.ts\";\n\nimport { UserInputError } from \"../errors.ts\";\n\n/**\n * Create a successful result with both human-readable text and structured content.\n *\n * - When `data` is a string, `structuredContent` wraps it as `{ result: data }`.\n * - When `data` is an object/array, `structuredContent` is `{ result: data }` and\n * the text representation is the JSON-serialized form.\n */\nexport function jsonResult(data: string | Record<string, unknown> | unknown): ToolResult {\n const text = typeof data === \"string\" ? data : JSON.stringify(data, null, 2);\n return {\n content: [{ type: \"text\", text }],\n structuredContent: { success: true, result: data },\n };\n}\n\n/**\n * Validate an ID-like value (must be alphanumeric/dashes only).\n * Prevents path traversal via `../` in URL segments.\n *\n * @returns true if the value is safe, false otherwise.\n */\nexport function sanitizeId(value: string): boolean {\n return /^[\\w-]+$/.test(value);\n}\n\n/**\n * Create an error result with structured error content.\n */\nexport function errorResult(message: string): ToolResult {\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n structuredContent: { success: false, error: message },\n isError: true,\n };\n}\n\n/**\n * Create an input error result from a UserInputError or a plain message with an optional suggestion.\n *\n * When a UserInputError is passed, its formatted message (including hints) is used.\n * When a plain string is passed, the optional suggestion is appended.\n */\nexport function inputErrorResult(error: UserInputError | string, suggestion?: string): ToolResult {\n let text: string;\n let errorMessage: string;\n if (error instanceof UserInputError) {\n text = error.toFormattedMessage();\n errorMessage = error.message;\n } else {\n errorMessage = error;\n text = suggestion ? `Error: ${error}\\n\\nSuggestion: ${suggestion}` : `Error: ${error}`;\n }\n return {\n content: [{ type: \"text\", text }],\n structuredContent: { success: false, error: errorMessage },\n isError: true,\n };\n}\n","/**\n * Factory for creating Forge resource handlers.\n *\n * Encapsulates the repetitive list/get/create/update/delete pattern\n * shared by all MCP resource handlers.\n */\n\nimport type { ExecutorContext, ExecutorResult } from \"@studiometa/forge-core\";\n\nimport type { ContextualHints } from \"../hints.ts\";\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nimport { errorResult, jsonResult, sanitizeId } from \"./utils.ts\";\n\n/**\n * Configuration for a resource handler.\n */\nexport interface ResourceHandlerConfig {\n /** Resource name for error messages */\n resource: string;\n\n /** Valid actions for this resource */\n actions: string[];\n\n /** Fields required per action (in addition to defaults) */\n requiredFields?: Record<string, string[]>;\n\n /** Executor functions keyed by action name */\n // biome-ignore lint: executor signatures vary per resource\n executors: Record<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (options: any, ctx: ExecutorContext) => Promise<ExecutorResult<unknown>>\n >;\n\n /**\n * Generate contextual hints for the get action response.\n *\n * Called with the executor result data and the resource id.\n * Only injected when `ctx.includeHints` is true.\n */\n hints?: (data: unknown, id: string) => ContextualHints;\n\n /** Map tool args to executor options. Defaults to pass-through. */\n mapOptions?: (action: string, args: CommonArgs) => Record<string, unknown>;\n\n /**\n * Format the executor result data into human-readable text for MCP output.\n *\n * Called with the executor result data and the tool args when compact mode\n * is enabled. If not provided, the data is JSON-serialized.\n */\n // biome-ignore lint: formatter signatures vary per resource\n formatResult?: (action: string, data: any, args: CommonArgs) => string;\n}\n\n/**\n * Create a resource handler from configuration.\n *\n * Returns a function that routes actions to the correct executor,\n * validates required fields, and formats results.\n *\n * @example\n * ```typescript\n * export const handleDatabases = createResourceHandler({\n * resource: 'databases',\n * actions: ['list', 'get', 'create', 'delete'],\n * requiredFields: {\n * list: ['server_id'],\n * get: ['server_id', 'id'],\n * create: ['server_id', 'name'],\n * delete: ['server_id', 'id'],\n * },\n * executors: {\n * list: listDatabases,\n * get: getDatabase,\n * create: createDatabase,\n * delete: deleteDatabase,\n * },\n * formatResult: (action, data) => {\n * if (action === 'list') return formatDatabaseList(data);\n * if (action === 'get') return formatDatabase(data);\n * return 'Done.';\n * },\n * });\n * ```\n */\nexport function createResourceHandler(\n config: ResourceHandlerConfig,\n): (action: string, args: CommonArgs, ctx: HandlerContext) => Promise<ToolResult> {\n const {\n resource,\n actions,\n requiredFields = {},\n executors,\n hints,\n mapOptions,\n formatResult,\n } = config;\n\n return async (action: string, args: CommonArgs, ctx: HandlerContext): Promise<ToolResult> => {\n // Validate action\n if (!actions.includes(action)) {\n return errorResult(\n `Unknown action \"${action}\" for ${resource}. Valid actions: ${actions.join(\", \")}.`,\n );\n }\n\n // Check required fields\n const required = requiredFields[action] ?? [];\n for (const field of required) {\n if (!args[field]) {\n return errorResult(`Missing required field: ${field}`);\n }\n }\n\n // Validate ID-like fields to prevent path traversal\n for (const field of [\"id\", \"server_id\", \"site_id\"]) {\n const value = args[field];\n if (value !== undefined && !sanitizeId(String(value))) {\n return errorResult(`Invalid ${field}: \"${value}\". IDs must be alphanumeric.`);\n }\n }\n\n // Get executor\n const executor = executors[action];\n if (!executor) {\n return errorResult(`Action \"${action}\" is not yet implemented for ${resource}.`);\n }\n\n // Map args to executor options — strip MCP-specific fields from passthrough\n let options: Record<string, unknown>;\n if (mapOptions) {\n options = mapOptions(action, args);\n } else {\n const { resource: _r, action: _a, compact: _c, ...rest } = args;\n options = rest;\n }\n\n // Execute\n const result = await executor(options as Record<string, unknown>, ctx.executorContext);\n\n // Format result\n if (result.data === undefined) {\n // Void result (delete, activate, etc.) — use formatter or generic message\n const text = formatResult ? formatResult(action, undefined, args) : \"Done.\";\n return jsonResult(text);\n }\n\n if (ctx.compact && formatResult) {\n return jsonResult(formatResult(action, result.data, args));\n }\n\n // For non-compact get responses, inject contextual hints when enabled\n if (action === \"get\" && ctx.includeHints && hints) {\n /* v8 ignore start */\n const id = args.id ?? args.server_id ?? \"\";\n /* v8 ignore stop */\n const responseData = {\n ...(result.data as Record<string, unknown>),\n _hints: hints(result.data, String(id)),\n };\n return jsonResult(responseData);\n }\n\n return jsonResult(result.data);\n };\n}\n","import {\n createBackupConfig,\n deleteBackupConfig,\n getBackupConfig,\n listBackupConfigs,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeBackupConfig } from \"@studiometa/forge-api\";\n\nimport { formatBackupConfig, formatBackupConfigList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleBackups = createResourceHandler({\n resource: \"backups\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"provider\", \"credentials\", \"frequency\", \"databases\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listBackupConfigs,\n get: getBackupConfig,\n create: createBackupConfig,\n delete: deleteBackupConfig,\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatBackupConfigList(data as ForgeBackupConfig[]);\n case \"get\":\n return formatBackupConfig(data as ForgeBackupConfig);\n case \"create\":\n return formatBackupConfig(data as ForgeBackupConfig);\n case \"delete\":\n return `Backup config ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { RESOURCES } from \"@studiometa/forge-core\";\n\n/**\n * Read-only actions — safe operations that don't modify server state.\n */\nexport const READ_ACTIONS = [\"list\", \"get\", \"resolve\", \"help\", \"schema\", \"context\"] as const;\n\n/**\n * Write actions — operations that modify server state.\n * These are separated into the `forge_write` tool for safety.\n */\nexport const WRITE_ACTIONS = [\n \"create\",\n \"update\",\n \"delete\",\n \"deploy\",\n \"reboot\",\n \"restart\",\n \"activate\",\n \"run\",\n] as const;\n\nexport type ReadAction = (typeof READ_ACTIONS)[number];\nexport type WriteAction = (typeof WRITE_ACTIONS)[number];\n\n/**\n * Check if an action is a write action.\n */\nexport function isWriteAction(action: string): action is WriteAction {\n return (WRITE_ACTIONS as readonly string[]).includes(action);\n}\n\n/**\n * Check if an action is a read action.\n */\nexport function isReadAction(action: string): action is ReadAction {\n return (READ_ACTIONS as readonly string[]).includes(action);\n}\n\n/**\n * Output schema shared by all forge tools.\n *\n * All tools return a consistent envelope:\n * - success: true/false\n * - result: the resource data (shape varies by resource and action)\n * - error: error message (only when success is false)\n *\n * The `result` field contains resource-specific data:\n * - list actions → array of resource objects\n * - get actions → single resource object (or string for env/nginx/scripts)\n * - help/schema → documentation text or schema object\n * - write actions → confirmation message or updated resource\n */\nconst OUTPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n success: {\n type: \"boolean\" as const,\n description: \"Whether the operation succeeded\",\n } as object,\n result: {\n description:\n \"Operation result — shape varies by resource and action (array for list, object for get, string for text content)\",\n } as object,\n error: {\n type: \"string\" as const,\n description: \"Error message (only present on failure)\",\n } as object,\n },\n required: [\"success\"],\n};\n\n/**\n * Shared input schema properties used by both forge and forge_write tools.\n */\nconst SHARED_INPUT_PROPERTIES = {\n resource: {\n type: \"string\" as const,\n enum: [...RESOURCES],\n description: \"Forge resource to operate on\",\n },\n id: { type: \"string\" as const, description: \"Resource ID (for get, delete, update actions)\" },\n server_id: {\n type: \"string\" as const,\n description:\n \"Server ID or name (names are auto-resolved via partial match, requires unique match)\",\n },\n site_id: {\n type: \"string\" as const,\n description: \"Site ID or domain name (auto-resolved via partial match, requires server_id)\",\n },\n compact: {\n type: \"boolean\" as const,\n description: \"Compact output (default: true for list, false for get)\",\n },\n query: {\n type: \"string\" as const,\n description:\n \"Search query for resolve action (matches by name, case-insensitive partial match)\",\n },\n};\n\n/**\n * Read-only tool for querying Forge resources.\n *\n * Annotated with readOnlyHint so MCP clients like Claude Desktop\n * can auto-approve read operations.\n */\nconst FORGE_READ_TOOL: Tool = {\n name: \"forge\",\n title: \"Laravel Forge\",\n description: [\n \"Laravel Forge API — read operations.\",\n `Resources: ${RESOURCES.join(\", \")}.`,\n `Actions: ${[...READ_ACTIONS].join(\", \")}.`,\n \"Discovery: action=help with any resource for filters and examples.\",\n \"Context: action=context on servers or sites fetches all sub-resources in one call.\",\n \"Server operations require id. Site operations require server_id.\",\n \"Deployment operations require server_id and site_id.\",\n \"Batch: use resource=batch action=run with an operations array to execute multiple reads in one call.\",\n \"resolve: find resources by name (partial, case-insensitive) — provide query field.\",\n ].join(\"\\n\"),\n annotations: {\n title: \"Laravel Forge\",\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: \"object\" as const,\n properties: {\n ...SHARED_INPUT_PROPERTIES,\n action: {\n type: \"string\" as const,\n enum: [...READ_ACTIONS],\n description: 'Read action to perform. Use \"help\" for resource documentation.',\n },\n operations: {\n type: \"array\" as const,\n description:\n \"Array of operations for batch execution (max 10). Each operation needs resource, action, and any additional params.\",\n items: {\n type: \"object\" as const,\n properties: {\n resource: { type: \"string\" as const },\n action: { type: \"string\" as const },\n },\n required: [\"resource\", \"action\"],\n },\n },\n },\n required: [\"resource\", \"action\"],\n },\n outputSchema: OUTPUT_SCHEMA,\n};\n\n/**\n * Write tool for mutating Forge resources.\n *\n * Annotated with destructiveHint so MCP clients always prompt\n * for confirmation before executing writes.\n */\nconst FORGE_WRITE_TOOL: Tool = {\n name: \"forge_write\",\n title: \"Laravel Forge (Write)\",\n description: [\n \"Laravel Forge API — write operations (create, update, delete, deploy, reboot, etc.).\",\n `Resources: ${RESOURCES.join(\", \")}.`,\n `Actions: ${[...WRITE_ACTIONS].join(\", \")}.`,\n \"Server operations require id. Site operations require server_id.\",\n \"Deployment operations require server_id and site_id.\",\n \"Use forge tool with action=help for resource documentation.\",\n ].join(\"\\n\"),\n annotations: {\n title: \"Laravel Forge (Write)\",\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: \"object\" as const,\n properties: {\n ...SHARED_INPUT_PROPERTIES,\n action: {\n type: \"string\" as const,\n enum: [...WRITE_ACTIONS],\n description: \"Write action to perform\",\n },\n // Server fields\n name: {\n type: \"string\" as const,\n description: \"Resource name (servers, databases, daemons, etc.)\",\n },\n provider: {\n type: \"string\" as const,\n description: \"Server provider (e.g. ocean2, linode, aws)\",\n },\n region: { type: \"string\" as const, description: \"Server region (e.g. nyc3, us-east-1)\" },\n size: { type: \"string\" as const, description: \"Server size (e.g. s-1vcpu-1gb)\" },\n credential_id: {\n type: \"string\" as const,\n description: \"Provider credential ID for server creation\",\n },\n type: {\n type: \"string\" as const,\n description:\n \"Resource type (e.g. app, web, worker for servers; mysql, postgres for databases; disk_usage, used_memory for monitors)\",\n },\n // Site fields\n domain: { type: \"string\" as const, description: \"Site domain name (e.g. example.com)\" },\n project_type: {\n type: \"string\" as const,\n description: \"Site project type (e.g. php, html, symfony, laravel)\",\n },\n directory: {\n type: \"string\" as const,\n description: \"Web directory relative to site root (e.g. /public)\",\n },\n // Content fields (env, nginx, deployment script)\n content: {\n type: \"string\" as const,\n description: \"Content body for env variables, nginx config, or deployment script updates\",\n },\n // Daemon fields\n command: {\n type: \"string\" as const,\n description:\n \"Shell command to execute (daemons: background process command; recipes: bash script inline; commands: site command)\",\n },\n user: {\n type: \"string\" as const,\n description: \"Unix user to run as (daemons, scheduled jobs; e.g. forge, root)\",\n },\n // Firewall fields\n port: {\n type: [\"string\", \"number\"] as unknown as string,\n description: \"Port number or range (firewall rules, e.g. 80 or 8000-9000)\",\n },\n ip_address: {\n type: \"string\" as const,\n description: \"IP address to allow/block (firewall rules, e.g. 192.168.1.1)\",\n },\n // SSH key fields\n key: {\n type: \"string\" as const,\n description: \"Public SSH key content (ssh-rsa ... or ssh-ed25519 ...)\",\n },\n // Redirect fields\n from: {\n type: \"string\" as const,\n description: \"Source path for redirect rules (e.g. /old-page)\",\n },\n to: {\n type: \"string\" as const,\n description: \"Destination URL for redirect rules (e.g. /new-page)\",\n },\n // Security rule fields\n credentials: {\n type: \"array\" as const,\n description: \"HTTP basic auth credentials for security rules [{username, password}]\",\n items: { type: \"object\" as const },\n },\n // Monitor fields\n operator: {\n type: \"string\" as const,\n description: \"Comparison operator for monitors (e.g. gte, lte)\",\n },\n threshold: {\n type: \"number\" as const,\n description: \"Threshold value that triggers the monitor alert\",\n },\n minutes: {\n type: \"number\" as const,\n description: \"Check interval in minutes for monitors (e.g. 5)\",\n },\n // Scheduled job fields\n frequency: {\n type: \"string\" as const,\n description: \"Cron frequency for scheduled jobs (e.g. minutely, hourly, nightly, custom)\",\n },\n // Recipe fields\n script: { type: \"string\" as const, description: \"Bash script content for recipes\" },\n servers: {\n type: \"array\" as const,\n description: \"Server IDs to run a recipe on (e.g. [123, 456])\",\n items: { type: \"number\" as const },\n },\n },\n required: [\"resource\", \"action\"],\n },\n outputSchema: OUTPUT_SCHEMA,\n};\n\n/**\n * Core tools available in both stdio and HTTP transports.\n *\n * Split into two tools for safety:\n * - `forge` — read-only operations (auto-approvable by MCP clients)\n * - `forge_write` — write operations (always requires confirmation)\n */\nexport const TOOLS: Tool[] = [FORGE_READ_TOOL, FORGE_WRITE_TOOL];\n\n/**\n * Options for filtering available tools.\n */\nexport interface GetToolsOptions {\n /** When true, only read-only tools are returned (forge_write is excluded). */\n readOnly?: boolean;\n}\n\n/**\n * Get the list of core tools, optionally filtered.\n *\n * In read-only mode, forge_write is excluded entirely — it won't appear\n * in the tool listing and cannot be called.\n */\nexport function getTools(options?: GetToolsOptions): Tool[] {\n if (options?.readOnly) {\n return TOOLS.filter((t) => t.name !== \"forge_write\");\n }\n return [...TOOLS];\n}\n\n/**\n * Additional tools only available in stdio mode.\n */\nexport const STDIO_ONLY_TOOLS: Tool[] = [\n {\n name: \"forge_configure\",\n title: \"Configure Forge\",\n description:\n \"Configure Laravel Forge API token. The token is stored locally in the XDG config directory.\",\n annotations: {\n title: \"Configure Forge\",\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: \"object\" as const,\n properties: {\n apiToken: { type: \"string\" as const, description: \"Your Laravel Forge API token\" },\n },\n required: [\"apiToken\"],\n },\n outputSchema: {\n type: \"object\" as const,\n properties: {\n success: { type: \"boolean\" as const },\n message: { type: \"string\" as const, description: \"Confirmation message\" },\n apiToken: { type: \"string\" as const, description: \"Masked API token (last 4 chars)\" },\n },\n required: [\"success\"],\n },\n },\n {\n name: \"forge_get_config\",\n title: \"Get Forge Config\",\n description: \"Get current Forge configuration (shows masked token and config status).\",\n annotations: {\n title: \"Get Forge Config\",\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: \"object\" as const,\n properties: {},\n },\n outputSchema: {\n type: \"object\" as const,\n properties: {\n apiToken: { type: \"string\" as const, description: \"Masked API token or 'not configured'\" },\n configured: { type: \"boolean\" as const, description: \"Whether a token is configured\" },\n },\n required: [\"configured\"],\n },\n },\n];\n","/**\n * Batch handler — executes multiple read operations in a single MCP call.\n *\n * Reduces round-trips for AI agents by running operations in parallel\n * with Promise.allSettled, isolating per-operation failures.\n */\n\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nimport { isReadAction } from \"../tools.ts\";\nimport { errorResult, jsonResult } from \"./utils.ts\";\n\ntype RouteHandler = (\n resource: string,\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n) => Promise<ToolResult>;\n\nconst MAX_OPERATIONS = 10;\n\n/**\n * Handle batch action — executes multiple read operations in parallel.\n */\nexport async function handleBatch(\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n routeToHandler: RouteHandler,\n): Promise<ToolResult> {\n if (action !== \"run\") {\n return errorResult(`Unknown action \"${action}\" for batch resource. Only \"run\" is supported.`);\n }\n\n const { operations } = args;\n\n if (operations === undefined || operations === null) {\n return errorResult('Missing required field: \"operations\". Provide an array of operations.');\n }\n\n if (!Array.isArray(operations)) {\n return errorResult('\"operations\" must be an array of operation objects.');\n }\n\n if (operations.length > MAX_OPERATIONS) {\n return errorResult(\n `Too many operations: ${operations.length}. Maximum is ${MAX_OPERATIONS} per batch.`,\n );\n }\n\n // Validate each operation\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i] as Record<string, unknown>;\n if (!op || typeof op !== \"object\") {\n return errorResult(`Operation at index ${i} must be an object.`);\n }\n if (!op[\"resource\"] || typeof op[\"resource\"] !== \"string\") {\n return errorResult(`Operation at index ${i} is missing required field \"resource\".`);\n }\n if (!op[\"action\"] || typeof op[\"action\"] !== \"string\") {\n return errorResult(`Operation at index ${i} is missing required field \"action\".`);\n }\n if (!isReadAction(op[\"action\"] as string)) {\n return errorResult(\n `Operation at index ${i} has invalid action \"${op[\"action\"]}\". Only read actions are allowed in batch: list, get, help, schema.`,\n );\n }\n }\n\n // Execute all operations in parallel\n const settled = await Promise.allSettled(\n operations.map((op) => {\n const { resource, action: opAction, ...rest } = op as Record<string, unknown>;\n return routeToHandler(\n resource as string,\n opAction as string,\n { resource: resource as string, action: opAction as string, ...rest } as CommonArgs,\n ctx,\n );\n }),\n );\n\n // Aggregate results\n let succeeded = 0;\n let failed = 0;\n\n const results = settled.map((outcome, index) => {\n const op = operations[index] as Record<string, unknown>;\n const resource = op[\"resource\"] as string;\n const opAction = op[\"action\"] as string;\n\n if (outcome.status === \"fulfilled\") {\n const toolResult = outcome.value;\n if (toolResult.isError) {\n failed++;\n return {\n index,\n resource,\n action: opAction,\n error:\n toolResult.structuredContent?.[\"error\"] ??\n /* v8 ignore next */\n toolResult.content[0]?.text ??\n \"Unknown error\",\n };\n }\n succeeded++;\n return {\n index,\n resource,\n action: opAction,\n data: toolResult.structuredContent?.[\"result\"] ?? toolResult.content[0]?.text,\n };\n } else {\n failed++;\n return {\n index,\n resource,\n action: opAction,\n error: outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason),\n };\n }\n });\n\n return jsonResult({\n _batch: {\n total: operations.length,\n succeeded,\n failed,\n },\n results,\n });\n}\n","/**\n * Contextual hints for AI agents.\n *\n * After get/list actions, suggests related resources and common next steps\n * to help agents discover what's available.\n */\n\ninterface ResourceHint {\n resource: string;\n description: string;\n example: Record<string, unknown>;\n}\n\nexport interface ContextualHints {\n related_resources?: ResourceHint[];\n common_actions?: { action: string; example: Record<string, unknown> }[];\n}\n\n/**\n * Hints after getting a server.\n */\nexport function getServerHints(serverId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"sites\",\n description: \"List sites on this server\",\n example: { resource: \"sites\", action: \"list\", server_id: serverId },\n },\n {\n resource: \"databases\",\n description: \"List databases\",\n example: { resource: \"databases\", action: \"list\", server_id: serverId },\n },\n {\n resource: \"daemons\",\n description: \"List background processes\",\n example: { resource: \"daemons\", action: \"list\", server_id: serverId },\n },\n {\n resource: \"firewall-rules\",\n description: \"List firewall rules\",\n example: { resource: \"firewall-rules\", action: \"list\", server_id: serverId },\n },\n {\n resource: \"ssh-keys\",\n description: \"List SSH keys on this server\",\n example: { resource: \"ssh-keys\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Reboot server\",\n example: { resource: \"servers\", action: \"reboot\", id: serverId },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a site.\n */\nexport function getSiteHints(serverId: string, siteId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"deployments\",\n description: \"List deployments for this site\",\n example: { resource: \"deployments\", action: \"list\", server_id: serverId, site_id: siteId },\n },\n {\n resource: \"env\",\n description: \"Get environment variables\",\n example: { resource: \"env\", action: \"get\", server_id: serverId, site_id: siteId },\n },\n {\n resource: \"certificates\",\n description: \"List SSL certificates\",\n example: { resource: \"certificates\", action: \"list\", server_id: serverId, site_id: siteId },\n },\n {\n resource: \"nginx\",\n description: \"Get nginx configuration\",\n example: { resource: \"nginx\", action: \"get\", server_id: serverId, site_id: siteId },\n },\n ],\n common_actions: [\n {\n action: \"Deploy this site\",\n example: {\n resource: \"deployments\",\n action: \"deploy\",\n server_id: serverId,\n site_id: siteId,\n },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a database.\n */\nexport function getDatabaseHints(serverId: string, databaseId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"databases\",\n description: \"List all databases on this server\",\n example: { resource: \"databases\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Delete this database\",\n example: { resource: \"databases\", action: \"delete\", server_id: serverId, id: databaseId },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a database user.\n */\nexport function getDatabaseUserHints(serverId: string, userId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"database-users\",\n description: \"List all database users on this server\",\n example: { resource: \"database-users\", action: \"list\", server_id: serverId },\n },\n {\n resource: \"databases\",\n description: \"List databases on this server\",\n example: { resource: \"databases\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Delete this database user\",\n example: {\n resource: \"database-users\",\n action: \"delete\",\n server_id: serverId,\n id: userId,\n },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a daemon.\n */\nexport function getDaemonHints(serverId: string, daemonId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"daemons\",\n description: \"List all daemons on this server\",\n example: { resource: \"daemons\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Restart this daemon\",\n example: { resource: \"daemons\", action: \"restart\", server_id: serverId, id: daemonId },\n },\n {\n action: \"Delete this daemon\",\n example: { resource: \"daemons\", action: \"delete\", server_id: serverId, id: daemonId },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a certificate.\n */\nexport function getCertificateHints(\n serverId: string,\n siteId: string,\n certificateId: string,\n): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"certificates\",\n description: \"List all certificates for this site\",\n example: {\n resource: \"certificates\",\n action: \"list\",\n server_id: serverId,\n site_id: siteId,\n },\n },\n ],\n common_actions: [\n {\n action: \"Activate this certificate\",\n example: {\n resource: \"certificates\",\n action: \"activate\",\n server_id: serverId,\n site_id: siteId,\n id: certificateId,\n },\n },\n {\n action: \"Delete this certificate\",\n example: {\n resource: \"certificates\",\n action: \"delete\",\n server_id: serverId,\n site_id: siteId,\n id: certificateId,\n },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a firewall rule.\n */\nexport function getFirewallRuleHints(serverId: string, ruleId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"firewall-rules\",\n description: \"List all firewall rules on this server\",\n example: { resource: \"firewall-rules\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Delete this firewall rule\",\n example: {\n resource: \"firewall-rules\",\n action: \"delete\",\n server_id: serverId,\n id: ruleId,\n },\n },\n ],\n };\n}\n\n/**\n * Hints after getting an SSH key.\n */\nexport function getSshKeyHints(serverId: string, keyId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"ssh-keys\",\n description: \"List all SSH keys on this server\",\n example: { resource: \"ssh-keys\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Delete this SSH key\",\n example: { resource: \"ssh-keys\", action: \"delete\", server_id: serverId, id: keyId },\n },\n ],\n };\n}\n\n/**\n * Hints after getting a recipe.\n */\nexport function getRecipeHints(recipeId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"recipes\",\n description: \"List all recipes\",\n example: { resource: \"recipes\", action: \"list\" },\n },\n ],\n common_actions: [\n {\n action: \"Run this recipe on servers\",\n example: { resource: \"recipes\", action: \"run\", id: recipeId, servers: [] },\n },\n {\n action: \"Delete this recipe\",\n example: { resource: \"recipes\", action: \"delete\", id: recipeId },\n },\n ],\n };\n}\n\n/**\n * Hints after getting an nginx template.\n */\nexport function getNginxTemplateHints(serverId: string, templateId: string): ContextualHints {\n return {\n related_resources: [\n {\n resource: \"nginx-templates\",\n description: \"List all nginx templates on this server\",\n example: { resource: \"nginx-templates\", action: \"list\", server_id: serverId },\n },\n ],\n common_actions: [\n {\n action: \"Update this nginx template\",\n example: {\n resource: \"nginx-templates\",\n action: \"update\",\n server_id: serverId,\n id: templateId,\n content: \"<nginx config content>\",\n },\n },\n {\n action: \"Delete this nginx template\",\n example: {\n resource: \"nginx-templates\",\n action: \"delete\",\n server_id: serverId,\n id: templateId,\n },\n },\n ],\n };\n}\n","import {\n activateCertificate,\n createCertificate,\n deleteCertificate,\n getCertificate,\n listCertificates,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeCertificate } from \"@studiometa/forge-api\";\n\nimport { formatCertificate, formatCertificateList } from \"../formatters.ts\";\nimport { getCertificateHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleCertificates = createResourceHandler({\n resource: \"certificates\",\n actions: [\"list\", \"get\", \"create\", \"delete\", \"activate\"],\n requiredFields: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"domain\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n activate: [\"server_id\", \"site_id\", \"id\"],\n },\n executors: {\n list: listCertificates,\n get: getCertificate,\n create: createCertificate,\n delete: deleteCertificate,\n activate: activateCertificate,\n },\n hints: (data, id) => {\n const cert = data as ForgeCertificate;\n return getCertificateHints(String(cert.server_id), String(cert.site_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatCertificateList(data as ForgeCertificate[]);\n case \"get\":\n return formatCertificate(data as ForgeCertificate);\n case \"create\":\n return formatCertificate(data as ForgeCertificate);\n case \"delete\":\n return `Certificate ${args.id} deleted.`;\n case \"activate\":\n return `Certificate ${args.id} activated.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import { createCommand, getCommand, listCommands } from \"@studiometa/forge-core\";\n\nimport type { ForgeCommand } from \"@studiometa/forge-api\";\n\nimport { formatCommand, formatCommandList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleCommands = createResourceHandler({\n resource: \"commands\",\n actions: [\"list\", \"get\", \"create\"],\n requiredFields: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"command\"],\n },\n executors: {\n list: listCommands,\n get: getCommand,\n create: createCommand,\n },\n formatResult: (action, data) => {\n switch (action) {\n case \"list\":\n return formatCommandList(data as ForgeCommand[]);\n case \"get\":\n return formatCommand(data as ForgeCommand);\n case \"create\":\n return formatCommand(data as ForgeCommand);\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createDaemon,\n deleteDaemon,\n getDaemon,\n listDaemons,\n restartDaemon,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeDaemon } from \"@studiometa/forge-api\";\n\nimport { formatDaemon, formatDaemonList } from \"../formatters.ts\";\nimport { getDaemonHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleDaemons = createResourceHandler({\n resource: \"daemons\",\n actions: [\"list\", \"get\", \"create\", \"delete\", \"restart\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"command\"],\n delete: [\"server_id\", \"id\"],\n restart: [\"server_id\", \"id\"],\n },\n executors: {\n list: listDaemons,\n get: getDaemon,\n create: createDaemon,\n delete: deleteDaemon,\n restart: restartDaemon,\n },\n hints: (data, id) => {\n const daemon = data as ForgeDaemon;\n return getDaemonHints(String(daemon.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatDaemonList(data as ForgeDaemon[]);\n case \"get\":\n return formatDaemon(data as ForgeDaemon);\n case \"create\":\n return formatDaemon(data as ForgeDaemon);\n case \"delete\":\n return `Daemon ${args.id} deleted.`;\n case \"restart\":\n return `Daemon ${args.id} restarted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import { createDatabase, deleteDatabase, getDatabase, listDatabases } from \"@studiometa/forge-core\";\n\nimport type { ForgeDatabase } from \"@studiometa/forge-api\";\n\nimport { formatDatabase, formatDatabaseList } from \"../formatters.ts\";\nimport { getDatabaseHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleDatabases = createResourceHandler({\n resource: \"databases\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listDatabases,\n get: getDatabase,\n create: createDatabase,\n delete: deleteDatabase,\n },\n hints: (data, id) => {\n const db = data as ForgeDatabase;\n return getDatabaseHints(String(db.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatDatabaseList(data as ForgeDatabase[]);\n case \"get\":\n return formatDatabase(data as ForgeDatabase);\n case \"create\":\n return formatDatabase(data as ForgeDatabase);\n case \"delete\":\n return `Database ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createDatabaseUser,\n deleteDatabaseUser,\n getDatabaseUser,\n listDatabaseUsers,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeDatabaseUser } from \"@studiometa/forge-api\";\n\nimport { formatDatabaseUser, formatDatabaseUserList } from \"../formatters.ts\";\nimport { getDatabaseUserHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleDatabaseUsers = createResourceHandler({\n resource: \"database-users\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"password\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listDatabaseUsers,\n get: getDatabaseUser,\n create: createDatabaseUser,\n delete: deleteDatabaseUser,\n },\n hints: (data, id) => {\n const user = data as ForgeDatabaseUser;\n return getDatabaseUserHints(String(user.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatDatabaseUserList(data as ForgeDatabaseUser[]);\n case \"get\":\n return formatDatabaseUser(data as ForgeDatabaseUser);\n case \"create\":\n return formatDatabaseUser(data as ForgeDatabaseUser);\n case \"delete\":\n return `Database user ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n deploySiteAndWait,\n getDeploymentOutput,\n getDeploymentScript,\n listDeployments,\n updateDeploymentScript,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeDeployment } from \"@studiometa/forge-api\";\n\nimport {\n formatDeploymentList,\n formatDeploymentOutput,\n formatDeploymentScript,\n formatDeploymentScriptUpdated,\n formatDeployAction,\n} from \"../formatters.ts\";\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nimport { errorResult, jsonResult, sanitizeId } from \"./utils.ts\";\n\n/**\n * Handle deployment resource actions.\n *\n * Not using the factory because the `get` action has special logic\n * (with id → output, without id → script).\n */\nexport async function handleDeployments(\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n if (!args.server_id) return errorResult(\"Missing required field: server_id\");\n if (!args.site_id) return errorResult(\"Missing required field: site_id\");\n\n // Validate IDs to prevent path traversal\n if (!sanitizeId(args.server_id)) {\n return errorResult(`Invalid server_id: \"${args.server_id}\". IDs must be alphanumeric.`);\n }\n if (!sanitizeId(args.site_id)) {\n return errorResult(`Invalid site_id: \"${args.site_id}\". IDs must be alphanumeric.`);\n }\n if (args.id && !sanitizeId(args.id)) {\n return errorResult(`Invalid id: \"${args.id}\". IDs must be alphanumeric.`);\n }\n\n const opts = { server_id: args.server_id, site_id: args.site_id };\n\n switch (action) {\n case \"list\": {\n const result = await listDeployments(opts, ctx.executorContext);\n if (ctx.compact) {\n return jsonResult(formatDeploymentList(result.data as ForgeDeployment[]));\n }\n return jsonResult(result.data);\n }\n\n case \"deploy\": {\n const deployResult = await deploySiteAndWait(opts, ctx.executorContext);\n return jsonResult(formatDeployAction(args.site_id, args.server_id, deployResult.data));\n }\n\n case \"get\": {\n if (args.id) {\n const result = await getDeploymentOutput(\n { ...opts, deployment_id: args.id },\n ctx.executorContext,\n );\n return jsonResult(formatDeploymentOutput(args.id, result.data as string));\n }\n const result = await getDeploymentScript(opts, ctx.executorContext);\n return jsonResult(formatDeploymentScript(result.data as string));\n }\n\n case \"update\": {\n if (!args.content) return errorResult(\"Missing required field: content\");\n await updateDeploymentScript(\n { ...opts, content: args.content as string },\n ctx.executorContext,\n );\n return jsonResult(formatDeploymentScriptUpdated(args.site_id, args.server_id));\n }\n\n default:\n return errorResult(\n `Unknown action \"${action}\" for deployments. Valid actions: list, deploy, get, update.`,\n );\n }\n}\n","import { getEnv, updateEnv } from \"@studiometa/forge-core\";\n\nimport { formatEnv } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleEnv = createResourceHandler({\n resource: \"env\",\n actions: [\"get\", \"update\"],\n requiredFields: {\n get: [\"server_id\", \"site_id\"],\n update: [\"server_id\", \"site_id\", \"content\"],\n },\n executors: {\n get: getEnv,\n update: updateEnv,\n },\n mapOptions: (_action, args) => ({\n server_id: args.server_id,\n site_id: args.site_id,\n content: args.content,\n }),\n formatResult: (action, data) => {\n switch (action) {\n case \"get\":\n return formatEnv(data as string);\n case \"update\":\n return \"Environment variables updated.\";\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createFirewallRule,\n deleteFirewallRule,\n getFirewallRule,\n listFirewallRules,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeFirewallRule } from \"@studiometa/forge-api\";\n\nimport { formatFirewallRule, formatFirewallRuleList } from \"../formatters.ts\";\nimport { getFirewallRuleHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleFirewallRules = createResourceHandler({\n resource: \"firewall-rules\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"port\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listFirewallRules,\n get: getFirewallRule,\n create: createFirewallRule,\n delete: deleteFirewallRule,\n },\n hints: (data, id) => {\n const rule = data as ForgeFirewallRule;\n return getFirewallRuleHints(String(rule.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatFirewallRuleList(data as ForgeFirewallRule[]);\n case \"get\":\n return formatFirewallRule(data as ForgeFirewallRule);\n case \"create\":\n return formatFirewallRule(data as ForgeFirewallRule);\n case \"delete\":\n return `Firewall rule ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","/**\n * Help handler — provides detailed documentation for each resource.\n *\n * Follows the productive-tools convention: per-resource docs with\n * actions, required fields, field descriptions, and examples.\n */\n\nimport type { ToolResult } from \"./types.ts\";\n\nimport { jsonResult } from \"./utils.ts\";\n\ninterface ResourceHelp {\n description: string;\n scope: string;\n actions: Record<string, string>;\n fields?: Record<string, string>;\n examples?: Array<{ description: string; params: Record<string, unknown> }>;\n}\n\nconst RESOURCE_HELP: Record<string, ResourceHelp> = {\n servers: {\n description:\n \"Manage Laravel Forge servers — provisioned cloud instances (DigitalOcean, AWS, Hetzner, etc.)\",\n scope: \"global (no parent ID needed)\",\n actions: {\n list: \"List all servers in your Forge account\",\n get: \"Get a single server by ID with full details\",\n create: \"Provision a new server (requires provider, type, region, name)\",\n delete: \"Delete a server by ID (irreversible)\",\n reboot: \"Reboot a server by ID\",\n context:\n \"Get full server context: server details + all sub-resources (sites, databases, database users, daemons, firewall rules, scheduled jobs) in one call\",\n resolve: \"Find servers by name (partial, case-insensitive match)\",\n },\n fields: {\n id: \"Server ID\",\n name: \"Server name (hostname)\",\n provider: \"Cloud provider (hetzner, ocean2, aws, linode, vultr, custom)\",\n region: \"Provider region code\",\n ip_address: \"Public IP address\",\n is_ready: \"Whether the server has finished provisioning\",\n php_version: \"Default PHP version (php84, php83, etc.)\",\n },\n examples: [\n { description: \"List all servers\", params: { resource: \"servers\", action: \"list\" } },\n {\n description: \"Get server details\",\n params: { resource: \"servers\", action: \"get\", id: \"123\" },\n },\n {\n description: \"Reboot a server\",\n params: { resource: \"servers\", action: \"reboot\", id: \"123\" },\n },\n {\n description: \"Get full server context (server + all sub-resources)\",\n params: { resource: \"servers\", action: \"context\", id: \"123\" },\n },\n {\n description: \"Find servers by name\",\n params: { resource: \"servers\", action: \"resolve\", query: \"prod\" },\n },\n ],\n },\n\n sites: {\n description: \"Manage sites on a Forge server — web applications, PHP projects, static sites\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List all sites on a server\",\n get: \"Get a single site by ID\",\n create: \"Create a new site (requires domain, project_type)\",\n delete: \"Delete a site by ID\",\n context:\n \"Get full site context: site details + recent deployments (last 5) + certificates + redirect rules + security rules in one call\",\n resolve: \"Find sites by domain name (partial, case-insensitive match, requires server_id)\",\n },\n fields: {\n id: \"Site ID\",\n server_id: \"Parent server ID\",\n name: \"Domain name (e.g. example.com)\",\n project_type: \"Project type (php, html, symfony, symfony_dev, symfony_four, laravel)\",\n directory: \"Web root directory (e.g. /public)\",\n repository: \"Git repository URL (if connected)\",\n deployment_status: \"Last deployment status (null, deploying, deployed, failed)\",\n },\n examples: [\n {\n description: \"List sites on a server\",\n params: { resource: \"sites\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Get site details\",\n params: { resource: \"sites\", action: \"get\", server_id: \"123\", id: \"456\" },\n },\n {\n description: \"Create a Laravel site\",\n params: {\n resource: \"sites\",\n action: \"create\",\n server_id: \"123\",\n domain: \"app.example.com\",\n project_type: \"php\",\n directory: \"/public\",\n },\n },\n {\n description: \"Get full site context (site + deployments + certificates + rules)\",\n params: { resource: \"sites\", action: \"context\", server_id: \"123\", id: \"456\" },\n },\n {\n description: \"Find sites by domain name\",\n params: { resource: \"sites\", action: \"resolve\", server_id: \"123\", query: \"example\" },\n },\n ],\n },\n\n deployments: {\n description: \"Manage site deployments — trigger, monitor, and configure deploy scripts\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n list: \"List recent deployments for a site\",\n deploy: \"Trigger a new deployment\",\n get: \"Get deployment output (requires deployment_id in 'id' field)\",\n update: \"Update the deployment script (provide 'content' field)\",\n },\n fields: {\n id: \"Deployment ID\",\n server_id: \"Parent server ID\",\n site_id: \"Parent site ID\",\n status: \"Deployment status (null, deploying, deployed, failed)\",\n displayable_type: \"Type of deployment trigger\",\n ended_at: \"Completion timestamp\",\n },\n examples: [\n {\n description: \"Deploy a site\",\n params: { resource: \"deployments\", action: \"deploy\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"List deployments\",\n params: { resource: \"deployments\", action: \"list\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Get deployment output\",\n params: {\n resource: \"deployments\",\n action: \"get\",\n server_id: \"123\",\n site_id: \"456\",\n id: \"789\",\n },\n },\n {\n description: \"Update deploy script\",\n params: {\n resource: \"deployments\",\n action: \"update\",\n server_id: \"123\",\n site_id: \"456\",\n content:\n \"cd /home/forge/app.example.com\\ngit pull\\ncomposer install\\nphp artisan migrate --force\",\n },\n },\n ],\n },\n\n env: {\n description: \"Manage environment variables (.env file) for a site\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n get: \"Get the current .env file content\",\n update: \"Replace the entire .env file (provide 'content' field)\",\n },\n examples: [\n {\n description: \"Get env variables\",\n params: { resource: \"env\", action: \"get\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Update env\",\n params: {\n resource: \"env\",\n action: \"update\",\n server_id: \"123\",\n site_id: \"456\",\n content: \"APP_ENV=production\\nAPP_DEBUG=false\\nDB_HOST=127.0.0.1\",\n },\n },\n ],\n },\n\n nginx: {\n description: \"Manage Nginx configuration for a site\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n get: \"Get the current Nginx config\",\n update: \"Replace the Nginx config (provide 'content' field)\",\n },\n examples: [\n {\n description: \"Get nginx config\",\n params: { resource: \"nginx\", action: \"get\", server_id: \"123\", site_id: \"456\" },\n },\n ],\n },\n\n certificates: {\n description: \"Manage SSL/TLS certificates for a site — Let's Encrypt, custom, or cloned\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n list: \"List certificates for a site\",\n get: \"Get certificate details\",\n create: \"Create/request a new certificate\",\n delete: \"Delete a certificate\",\n activate: \"Activate a certificate (make it the active cert for the site)\",\n },\n examples: [\n {\n description: \"List certificates\",\n params: { resource: \"certificates\", action: \"list\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Create Let's Encrypt cert\",\n params: {\n resource: \"certificates\",\n action: \"create\",\n server_id: \"123\",\n site_id: \"456\",\n domain: \"example.com\",\n type: \"new\",\n },\n },\n {\n description: \"Activate a certificate\",\n params: {\n resource: \"certificates\",\n action: \"activate\",\n server_id: \"123\",\n site_id: \"456\",\n id: \"789\",\n },\n },\n ],\n },\n\n databases: {\n description: \"Manage MySQL/PostgreSQL databases on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List databases on a server\",\n get: \"Get database details\",\n create: \"Create a new database (optionally with user)\",\n delete: \"Delete a database\",\n },\n fields: {\n name: \"Database name\",\n user: \"(create only) Create a database user\",\n password: \"(create only) User password\",\n },\n examples: [\n {\n description: \"List databases\",\n params: { resource: \"databases\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Create database with user\",\n params: {\n resource: \"databases\",\n action: \"create\",\n server_id: \"123\",\n name: \"myapp\",\n user: \"admin\",\n password: \"secret123\",\n },\n },\n ],\n },\n\n \"database-users\": {\n description: \"Manage database users on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List database users on a server\",\n get: \"Get database user details\",\n create: \"Create a new database user\",\n delete: \"Delete a database user\",\n },\n fields: {\n name: \"Database user name\",\n password: \"User password\",\n databases: \"(create only) Array of database IDs to grant access to\",\n },\n examples: [\n {\n description: \"List database users\",\n params: { resource: \"database-users\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Create a database user\",\n params: {\n resource: \"database-users\",\n action: \"create\",\n server_id: \"123\",\n name: \"forge\",\n password: \"secret123\",\n databases: [1, 2],\n },\n },\n ],\n },\n\n daemons: {\n description: \"Manage background processes (daemons) — queue workers, websocket servers, etc.\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List daemons on a server\",\n get: \"Get daemon details\",\n create: \"Create a new daemon\",\n delete: \"Delete a daemon\",\n restart: \"Restart a daemon\",\n },\n fields: {\n command: \"Shell command to run\",\n user: \"Execution user (default: forge)\",\n directory: \"Working directory\",\n processes: \"Number of processes (default: 1)\",\n },\n examples: [\n {\n description: \"List daemons\",\n params: { resource: \"daemons\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Create queue worker\",\n params: {\n resource: \"daemons\",\n action: \"create\",\n server_id: \"123\",\n command: \"php artisan queue:work --tries=3\",\n user: \"forge\",\n },\n },\n {\n description: \"Restart a daemon\",\n params: { resource: \"daemons\", action: \"restart\", server_id: \"123\", id: \"456\" },\n },\n ],\n },\n\n \"firewall-rules\": {\n description: \"Manage UFW firewall rules on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List firewall rules\",\n get: \"Get rule details\",\n create: \"Create a new firewall rule\",\n delete: \"Delete a firewall rule\",\n },\n fields: {\n name: \"Rule name/description\",\n port: \"Port number or range (e.g. 80, 8000-9000)\",\n type: \"allow or deny (default: allow)\",\n ip_address: \"Restrict to specific IP (optional)\",\n },\n examples: [\n {\n description: \"List firewall rules\",\n params: { resource: \"firewall-rules\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Open port 3000\",\n params: {\n resource: \"firewall-rules\",\n action: \"create\",\n server_id: \"123\",\n name: \"Allow Node.js\",\n port: 3000,\n },\n },\n ],\n },\n\n \"ssh-keys\": {\n description: \"Manage SSH keys on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List SSH keys\",\n get: \"Get key details\",\n create: \"Add an SSH key to the server\",\n delete: \"Remove an SSH key\",\n },\n fields: {\n name: \"Key label/description\",\n key: \"Public key content (ssh-rsa ...)\",\n username: \"User to add the key to (optional)\",\n },\n examples: [\n {\n description: \"List SSH keys\",\n params: { resource: \"ssh-keys\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Add SSH key\",\n params: {\n resource: \"ssh-keys\",\n action: \"create\",\n server_id: \"123\",\n name: \"Deploy Key\",\n key: \"ssh-rsa AAAA...\",\n },\n },\n ],\n },\n\n \"security-rules\": {\n description: \"Manage HTTP Basic Auth security rules for a site\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n list: \"List security rules\",\n get: \"Get rule details\",\n create: \"Create a security rule with credentials\",\n delete: \"Delete a security rule\",\n },\n examples: [\n {\n description: \"List security rules\",\n params: { resource: \"security-rules\", action: \"list\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Create basic auth\",\n params: {\n resource: \"security-rules\",\n action: \"create\",\n server_id: \"123\",\n site_id: \"456\",\n name: \"Staging Auth\",\n credentials: [{ username: \"admin\", password: \"secret\" }],\n },\n },\n ],\n },\n\n \"redirect-rules\": {\n description: \"Manage URL redirect rules for a site\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n list: \"List redirect rules\",\n get: \"Get rule details\",\n create: \"Create a redirect rule\",\n delete: \"Delete a redirect rule\",\n },\n fields: {\n from: \"Source path (regex supported)\",\n to: \"Destination URL\",\n type: \"redirect (302, default) or permanent (301)\",\n },\n examples: [\n {\n description: \"List redirects\",\n params: { resource: \"redirect-rules\", action: \"list\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Create redirect\",\n params: {\n resource: \"redirect-rules\",\n action: \"create\",\n server_id: \"123\",\n site_id: \"456\",\n from: \"/old-page\",\n to: \"/new-page\",\n type: \"permanent\",\n },\n },\n ],\n },\n\n monitors: {\n description: \"Manage server monitoring alerts — CPU, disk, memory thresholds\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List monitors\",\n get: \"Get monitor details\",\n create: \"Create a monitor\",\n delete: \"Delete a monitor\",\n },\n fields: {\n type: \"Monitor type (disk, cpu, memory)\",\n operator: \"Comparison operator (gte, lte)\",\n threshold: \"Threshold value (e.g. 80 for 80%)\",\n minutes: \"Check interval in minutes\",\n },\n examples: [\n {\n description: \"List monitors\",\n params: { resource: \"monitors\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Alert on high disk usage\",\n params: {\n resource: \"monitors\",\n action: \"create\",\n server_id: \"123\",\n type: \"disk\",\n operator: \"gte\",\n threshold: 80,\n minutes: 5,\n },\n },\n ],\n },\n\n \"nginx-templates\": {\n description: \"Manage reusable Nginx configuration templates on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List nginx templates\",\n get: \"Get template with content\",\n create: \"Create a new template\",\n update: \"Update template name or content\",\n delete: \"Delete a template\",\n },\n examples: [\n {\n description: \"List templates\",\n params: { resource: \"nginx-templates\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Get template content\",\n params: { resource: \"nginx-templates\", action: \"get\", server_id: \"123\", id: \"456\" },\n },\n ],\n },\n\n backups: {\n description:\n \"Manage backup configurations — automated database backups to S3, Spaces, or other providers\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List backup configurations on a server\",\n get: \"Get backup config details (databases, schedule, retention)\",\n create: \"Create a new backup configuration\",\n delete: \"Delete a backup configuration\",\n },\n fields: {\n provider: \"Backup provider (s3, spaces, custom)\",\n credentials: \"Provider credentials (keys, bucket, region)\",\n frequency: \"Backup frequency (daily, weekly, custom)\",\n databases: \"Array of database IDs to back up\",\n retention: \"Number of backups to retain\",\n },\n examples: [\n {\n description: \"List backup configs\",\n params: { resource: \"backups\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Get backup config details\",\n params: { resource: \"backups\", action: \"get\", server_id: \"123\", id: \"456\" },\n },\n ],\n },\n\n commands: {\n description: \"Execute and list site commands — run artisan commands or shell scripts on a site\",\n scope: \"site (requires server_id + site_id)\",\n actions: {\n list: \"List commands executed on a site\",\n get: \"Get command details and status\",\n create: \"Execute a new command on the site\",\n },\n fields: {\n command: \"Shell command to execute\",\n },\n examples: [\n {\n description: \"List commands\",\n params: { resource: \"commands\", action: \"list\", server_id: \"123\", site_id: \"456\" },\n },\n {\n description: \"Run a command\",\n params: {\n resource: \"commands\",\n action: \"create\",\n server_id: \"123\",\n site_id: \"456\",\n command: \"php artisan migrate --force\",\n },\n },\n ],\n },\n\n \"scheduled-jobs\": {\n description: \"Manage cron jobs (scheduled tasks) on a server\",\n scope: \"server (requires server_id)\",\n actions: {\n list: \"List scheduled jobs on a server\",\n get: \"Get job details (command, frequency, cron expression)\",\n create: \"Create a new scheduled job\",\n delete: \"Delete a scheduled job\",\n },\n fields: {\n command: \"Shell command to schedule\",\n user: \"Execution user (default: forge)\",\n frequency: \"Frequency preset (minutely, hourly, nightly, weekly, monthly, custom)\",\n minute: \"(custom frequency) Minute field\",\n hour: \"(custom frequency) Hour field\",\n day: \"(custom frequency) Day of month field\",\n month: \"(custom frequency) Month field\",\n weekday: \"(custom frequency) Day of week field\",\n },\n examples: [\n {\n description: \"List scheduled jobs\",\n params: { resource: \"scheduled-jobs\", action: \"list\", server_id: \"123\" },\n },\n {\n description: \"Create minutely scheduler\",\n params: {\n resource: \"scheduled-jobs\",\n action: \"create\",\n server_id: \"123\",\n command: \"php /home/forge/app.com/artisan schedule:run\",\n frequency: \"minutely\",\n user: \"forge\",\n },\n },\n ],\n },\n\n user: {\n description: \"Get the currently authenticated Forge user profile\",\n scope: \"global (no parent ID needed)\",\n actions: {\n get: \"Get the authenticated user's profile (name, email, connected services)\",\n },\n examples: [\n {\n description: \"Get user profile\",\n params: { resource: \"user\", action: \"get\" },\n },\n ],\n },\n\n batch: {\n description:\n \"Execute multiple read operations in a single call — reduces round-trips for AI agents\",\n scope: \"global (no parent ID needed)\",\n actions: {\n run: \"Execute a batch of read operations in parallel (max 10)\",\n },\n fields: {\n operations: \"Array of operations [{resource, action, ...params}] (max 10)\",\n },\n examples: [\n {\n description: \"Batch: list servers + list sites on a server\",\n params: {\n resource: \"batch\",\n action: \"run\",\n operations: [\n { resource: \"servers\", action: \"list\" },\n { resource: \"sites\", action: \"list\", server_id: \"123\" },\n ],\n },\n },\n ],\n },\n\n recipes: {\n description:\n \"Manage and run server recipes — reusable bash scripts executed on one or more servers\",\n scope: \"global (no parent ID needed)\",\n actions: {\n list: \"List all recipes\",\n get: \"Get recipe details and script content\",\n create: \"Create a new recipe\",\n delete: \"Delete a recipe\",\n run: \"Run a recipe on specified servers (provide 'servers' as array of server IDs)\",\n },\n fields: {\n name: \"Recipe name\",\n script: \"Bash script content\",\n user: \"Execution user (default: root)\",\n servers: \"(run only) Array of server IDs to run on\",\n },\n examples: [\n { description: \"List recipes\", params: { resource: \"recipes\", action: \"list\" } },\n {\n description: \"Create a recipe\",\n params: {\n resource: \"recipes\",\n action: \"create\",\n name: \"Clear caches\",\n script: \"php artisan cache:clear\\nphp artisan view:clear\",\n },\n },\n {\n description: \"Run recipe on servers\",\n params: { resource: \"recipes\", action: \"run\", id: \"123\", servers: [1, 2, 3] },\n },\n ],\n },\n};\n\n/**\n * Handle help action — returns documentation for a specific resource.\n */\nexport function handleHelp(resource: string): ToolResult {\n const help = RESOURCE_HELP[resource];\n\n if (!help) {\n return handleHelpOverview();\n }\n\n return jsonResult({ resource, ...help });\n}\n\n/**\n * Get help for all resources (overview).\n */\nexport function handleHelpOverview(): ToolResult {\n const overview = Object.entries(RESOURCE_HELP).map(([resource, help]) => ({\n resource,\n description: help.description,\n scope: help.scope,\n actions: Object.keys(help.actions),\n }));\n\n return jsonResult({\n message: 'Use action=\"help\" with a specific resource for detailed documentation',\n resources: overview,\n _tip: \"Always call { action: 'help', resource: '<name>' } before your first interaction with any resource to learn required fields and examples.\",\n });\n}\n","import { createMonitor, deleteMonitor, getMonitor, listMonitors } from \"@studiometa/forge-core\";\n\nimport type { ForgeMonitor } from \"@studiometa/forge-api\";\n\nimport { formatMonitor, formatMonitorList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleMonitors = createResourceHandler({\n resource: \"monitors\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"type\", \"operator\", \"threshold\", \"minutes\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listMonitors,\n get: getMonitor,\n create: createMonitor,\n delete: deleteMonitor,\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatMonitorList(data as ForgeMonitor[]);\n case \"get\":\n return formatMonitor(data as ForgeMonitor);\n case \"create\":\n return formatMonitor(data as ForgeMonitor);\n case \"delete\":\n return `Monitor ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import { getNginxConfig, updateNginxConfig } from \"@studiometa/forge-core\";\n\nimport { formatNginxConfig } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleNginxConfig = createResourceHandler({\n resource: \"nginx\",\n actions: [\"get\", \"update\"],\n requiredFields: {\n get: [\"server_id\", \"site_id\"],\n update: [\"server_id\", \"site_id\", \"content\"],\n },\n executors: {\n get: getNginxConfig,\n update: updateNginxConfig,\n },\n mapOptions: (_action, args) => ({\n server_id: args.server_id,\n site_id: args.site_id,\n content: args.content,\n }),\n formatResult: (action, data) => {\n switch (action) {\n case \"get\":\n return formatNginxConfig(data as string);\n case \"update\":\n return \"Nginx configuration updated.\";\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createNginxTemplate,\n deleteNginxTemplate,\n getNginxTemplate,\n listNginxTemplates,\n updateNginxTemplate,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeNginxTemplate } from \"@studiometa/forge-api\";\n\nimport { formatNginxTemplate, formatNginxTemplateList } from \"../formatters.ts\";\nimport { getNginxTemplateHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleNginxTemplates = createResourceHandler({\n resource: \"nginx-templates\",\n actions: [\"list\", \"get\", \"create\", \"update\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"content\"],\n update: [\"server_id\", \"id\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listNginxTemplates,\n get: getNginxTemplate,\n create: createNginxTemplate,\n update: updateNginxTemplate,\n delete: deleteNginxTemplate,\n },\n hints: (data, id) => {\n const template = data as ForgeNginxTemplate;\n return getNginxTemplateHints(String(template.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatNginxTemplateList(data as ForgeNginxTemplate[]);\n case \"get\":\n return formatNginxTemplate(data as ForgeNginxTemplate);\n case \"create\":\n return formatNginxTemplate(data as ForgeNginxTemplate);\n case \"update\":\n return formatNginxTemplate(data as ForgeNginxTemplate);\n case \"delete\":\n return `Nginx template ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createRecipe,\n deleteRecipe,\n getRecipe,\n listRecipes,\n runRecipe,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeRecipe } from \"@studiometa/forge-api\";\n\nimport { formatRecipe, formatRecipeList } from \"../formatters.ts\";\nimport { getRecipeHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleRecipes = createResourceHandler({\n resource: \"recipes\",\n actions: [\"list\", \"get\", \"create\", \"delete\", \"run\"],\n requiredFields: {\n get: [\"id\"],\n create: [\"name\", \"script\"],\n delete: [\"id\"],\n run: [\"id\", \"servers\"],\n },\n executors: {\n list: listRecipes,\n get: getRecipe,\n create: createRecipe,\n delete: deleteRecipe,\n run: runRecipe,\n },\n hints: (_data, id) => getRecipeHints(id),\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatRecipeList(data as ForgeRecipe[]);\n case \"get\":\n return formatRecipe(data as ForgeRecipe);\n case \"create\":\n return formatRecipe(data as ForgeRecipe);\n case \"delete\":\n return `Recipe ${args.id} deleted.`;\n case \"run\": {\n const servers = args.servers;\n const count = Array.isArray(servers) ? servers.length : 1;\n return `Recipe ${args.id} run on ${count} server(s).`;\n }\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createRedirectRule,\n deleteRedirectRule,\n getRedirectRule,\n listRedirectRules,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeRedirectRule } from \"@studiometa/forge-api\";\n\nimport { formatRedirectRule, formatRedirectRuleList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleRedirectRules = createResourceHandler({\n resource: \"redirect-rules\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"from\", \"to\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n },\n executors: {\n list: listRedirectRules,\n get: getRedirectRule,\n create: createRedirectRule,\n delete: deleteRedirectRule,\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatRedirectRuleList(data as ForgeRedirectRule[]);\n case \"get\":\n return formatRedirectRule(data as ForgeRedirectRule);\n case \"create\":\n return formatRedirectRule(data as ForgeRedirectRule);\n case \"delete\":\n return `Redirect rule ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n createScheduledJob,\n deleteScheduledJob,\n getScheduledJob,\n listScheduledJobs,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeScheduledJob } from \"@studiometa/forge-api\";\n\nimport { formatScheduledJob, formatScheduledJobList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleScheduledJobs = createResourceHandler({\n resource: \"scheduled-jobs\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"command\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listScheduledJobs,\n get: getScheduledJob,\n create: createScheduledJob,\n delete: deleteScheduledJob,\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatScheduledJobList(data as ForgeScheduledJob[]);\n case \"get\":\n return formatScheduledJob(data as ForgeScheduledJob);\n case \"create\":\n return formatScheduledJob(data as ForgeScheduledJob);\n case \"delete\":\n return `Scheduled job ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","/**\n * Schema handler — compact, machine-readable resource specifications.\n *\n * More concise than action=help, optimized for LLM consumption when only\n * field metadata is needed (actions, required params, field descriptions).\n */\n\nimport type { ToolResult } from \"./types.ts\";\n\nimport { jsonResult } from \"./utils.ts\";\n\ninterface ResourceFieldSpec {\n required: boolean;\n type: string;\n}\n\ninterface ResourceSchemaData {\n actions: string[];\n scope: string;\n required: Record<string, string[]>;\n create?: Record<string, ResourceFieldSpec>;\n}\n\nconst RESOURCE_SCHEMAS: Record<string, ResourceSchemaData> = {\n servers: {\n actions: [\"list\", \"get\", \"create\", \"delete\", \"reboot\", \"resolve\", \"context\"],\n scope: \"global\",\n required: {\n get: [\"id\"],\n create: [\"provider\", \"type\", \"region\", \"name\"],\n delete: [\"id\"],\n reboot: [\"id\"],\n context: [\"id\"],\n resolve: [\"query\"],\n },\n create: {\n provider: { required: true, type: \"string — hetzner, ocean2, aws, etc.\" },\n type: { required: true, type: \"string — app, web, worker, etc.\" },\n region: { required: true, type: \"string — provider-specific region code\" },\n name: { required: true, type: \"string\" },\n credential_id: { required: false, type: \"string — provider credential ID\" },\n php_version: { required: false, type: \"string — php84, php83, etc.\" },\n database: { required: false, type: \"string — database name to create\" },\n },\n },\n\n sites: {\n actions: [\"list\", \"get\", \"create\", \"delete\", \"resolve\", \"context\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"domain\", \"project_type\"],\n delete: [\"server_id\", \"id\"],\n context: [\"server_id\", \"id\"],\n resolve: [\"server_id\", \"query\"],\n },\n create: {\n domain: { required: true, type: \"string — e.g. example.com\" },\n project_type: { required: true, type: \"string — php, html, symfony, etc.\" },\n directory: { required: false, type: \"string — web root (/public)\" },\n },\n },\n\n deployments: {\n actions: [\"list\", \"deploy\", \"get\", \"update\"],\n scope: \"site\",\n required: {\n list: [\"server_id\", \"site_id\"],\n deploy: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n update: [\"server_id\", \"site_id\", \"content\"],\n },\n },\n\n env: {\n actions: [\"get\", \"update\"],\n scope: \"site\",\n required: {\n get: [\"server_id\", \"site_id\"],\n update: [\"server_id\", \"site_id\", \"content\"],\n },\n },\n\n nginx: {\n actions: [\"get\", \"update\"],\n scope: \"site\",\n required: {\n get: [\"server_id\", \"site_id\"],\n update: [\"server_id\", \"site_id\", \"content\"],\n },\n },\n\n certificates: {\n actions: [\"list\", \"get\", \"create\", \"delete\", \"activate\"],\n scope: \"site\",\n required: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"domain\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n activate: [\"server_id\", \"site_id\", \"id\"],\n },\n create: {\n type: { required: false, type: \"string — new, existing, clone (default: new)\" },\n domain: { required: true, type: \"string\" },\n },\n },\n\n databases: {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string — database name\" },\n user: { required: false, type: \"string — database user to create\" },\n password: { required: false, type: \"string — user password\" },\n },\n },\n\n \"database-users\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"password\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string — database user name\" },\n password: { required: true, type: \"string — user password\" },\n databases: { required: false, type: \"array — database IDs to grant access to\" },\n },\n },\n\n daemons: {\n actions: [\"list\", \"get\", \"create\", \"delete\", \"restart\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"command\"],\n delete: [\"server_id\", \"id\"],\n restart: [\"server_id\", \"id\"],\n },\n create: {\n command: { required: true, type: \"string — e.g. php artisan queue:work\" },\n user: { required: false, type: \"string — default: forge\" },\n directory: { required: false, type: \"string — working directory\" },\n processes: { required: false, type: \"number — default: 1\" },\n },\n },\n\n \"firewall-rules\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"port\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string\" },\n port: { required: true, type: \"number|string — e.g. 80, 443, 8000-9000\" },\n type: { required: false, type: \"string — allow (default) or deny\" },\n ip_address: { required: false, type: \"string — restrict to IP\" },\n },\n },\n\n \"ssh-keys\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"key\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string — key label\" },\n key: { required: true, type: \"string — public key content\" },\n username: { required: false, type: \"string — user to add key to\" },\n },\n },\n\n \"security-rules\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"site\",\n required: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"name\", \"credentials\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string — rule name\" },\n path: { required: false, type: \"string — protected path (default: /)\" },\n credentials: { required: true, type: \"array — [{username, password}]\" },\n },\n },\n\n \"redirect-rules\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"site\",\n required: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"from\", \"to\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n },\n create: {\n from: { required: true, type: \"string — source path\" },\n to: { required: true, type: \"string — destination URL\" },\n type: { required: false, type: \"string — redirect (302) or permanent (301)\" },\n },\n },\n\n monitors: {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"type\", \"operator\", \"threshold\", \"minutes\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n type: { required: true, type: \"string — disk, cpu, memory, etc.\" },\n operator: { required: true, type: \"string — gte, lte\" },\n threshold: { required: true, type: \"number — e.g. 80\" },\n minutes: { required: true, type: \"number — check interval in minutes\" },\n },\n },\n\n \"nginx-templates\": {\n actions: [\"list\", \"get\", \"create\", \"update\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"content\"],\n update: [\"server_id\", \"id\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n name: { required: true, type: \"string — template name\" },\n content: { required: true, type: \"string — nginx configuration template\" },\n },\n },\n\n backups: {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"provider\", \"credentials\", \"frequency\", \"databases\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n provider: { required: true, type: \"string — s3, spaces, custom\" },\n credentials: { required: true, type: \"object — provider credentials (key, secret, etc.)\" },\n frequency: { required: true, type: \"string — daily, weekly, custom\" },\n databases: { required: true, type: \"array — database IDs to back up\" },\n directory: { required: false, type: \"string — backup directory\" },\n email: { required: false, type: \"string — notification email\" },\n retention: { required: false, type: \"number — backups to retain (default: 7)\" },\n },\n },\n\n commands: {\n actions: [\"list\", \"get\", \"create\"],\n scope: \"site\",\n required: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"command\"],\n },\n create: {\n command: { required: true, type: \"string — shell command to execute\" },\n },\n },\n\n \"scheduled-jobs\": {\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n scope: \"server\",\n required: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"command\"],\n delete: [\"server_id\", \"id\"],\n },\n create: {\n command: { required: true, type: \"string — command to schedule\" },\n user: { required: false, type: \"string — execution user (default: forge)\" },\n frequency: {\n required: false,\n type: \"string — minutely, hourly, nightly, weekly, monthly, custom\",\n },\n minute: { required: false, type: \"string — cron minute field (custom frequency)\" },\n hour: { required: false, type: \"string — cron hour field\" },\n day: { required: false, type: \"string — cron day field\" },\n month: { required: false, type: \"string — cron month field\" },\n weekday: { required: false, type: \"string — cron weekday field\" },\n },\n },\n\n user: {\n actions: [\"get\"],\n scope: \"global\",\n required: {},\n },\n\n batch: {\n actions: [\"run\"],\n scope: \"global\",\n required: {\n run: [\"operations\"],\n },\n },\n\n recipes: {\n actions: [\"list\", \"get\", \"create\", \"delete\", \"run\"],\n scope: \"global\",\n required: {\n get: [\"id\"],\n create: [\"name\", \"script\"],\n delete: [\"id\"],\n run: [\"id\", \"servers\"],\n },\n create: {\n name: { required: true, type: \"string — recipe name\" },\n script: { required: true, type: \"string — bash script content\" },\n user: { required: false, type: \"string — execution user (default: root)\" },\n },\n },\n};\n\n/**\n * Handle schema action — returns compact spec for a specific resource.\n */\nexport function handleSchema(resource: string): ToolResult {\n const schema = RESOURCE_SCHEMAS[resource];\n\n if (!schema) {\n return jsonResult({\n error: `Unknown resource: ${resource}`,\n available_resources: Object.keys(RESOURCE_SCHEMAS),\n });\n }\n\n return jsonResult({ resource, ...schema });\n}\n\n/**\n * Get schema overview for all resources.\n */\nexport function handleSchemaOverview(): ToolResult {\n const overview = Object.entries(RESOURCE_SCHEMAS).map(([resource, schema]) => ({\n resource,\n actions: schema.actions,\n scope: schema.scope,\n }));\n\n return jsonResult({\n _tip: 'Use action=\"schema\" with a specific resource for full required/create spec',\n resources: overview,\n });\n}\n","import {\n createSecurityRule,\n deleteSecurityRule,\n getSecurityRule,\n listSecurityRules,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeSecurityRule } from \"@studiometa/forge-api\";\n\nimport { formatSecurityRule, formatSecurityRuleList } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleSecurityRules = createResourceHandler({\n resource: \"security-rules\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\", \"site_id\"],\n get: [\"server_id\", \"site_id\", \"id\"],\n create: [\"server_id\", \"site_id\", \"name\", \"credentials\"],\n delete: [\"server_id\", \"site_id\", \"id\"],\n },\n executors: {\n list: listSecurityRules,\n get: getSecurityRule,\n create: createSecurityRule,\n delete: deleteSecurityRule,\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatSecurityRuleList(data as ForgeSecurityRule[]);\n case \"get\":\n return formatSecurityRule(data as ForgeSecurityRule);\n case \"create\":\n return formatSecurityRule(data as ForgeSecurityRule);\n case \"delete\":\n return `Security rule ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import {\n getServer,\n getSite,\n listCertificates,\n listDaemons,\n listDatabaseUsers,\n listDatabases,\n listDeployments,\n listFirewallRules,\n listRedirectRules,\n listScheduledJobs,\n listSecurityRules,\n listSites,\n} from \"@studiometa/forge-core\";\n\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\nimport { errorResult, jsonResult } from \"./utils.ts\";\n\n/**\n * Handle server context action — fetches server details plus all sub-resources\n * (sites, databases, database users, daemons, firewall rules, scheduled jobs)\n * in parallel in a single call.\n */\nexport async function handleServerContext(\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n const serverId = args.id;\n if (!serverId) return errorResult(\"Missing required field: id\");\n\n const execCtx = ctx.executorContext;\n\n const [server, sites, databases, dbUsers, daemons, firewallRules, scheduledJobs] =\n await Promise.all([\n getServer({ server_id: serverId }, execCtx),\n listSites({ server_id: serverId }, execCtx),\n listDatabases({ server_id: serverId }, execCtx),\n listDatabaseUsers({ server_id: serverId }, execCtx),\n listDaemons({ server_id: serverId }, execCtx),\n listFirewallRules({ server_id: serverId }, execCtx),\n listScheduledJobs({ server_id: serverId }, execCtx),\n ]);\n\n return jsonResult({\n server: server.data,\n sites: sites.data,\n databases: databases.data,\n database_users: dbUsers.data,\n daemons: daemons.data,\n firewall_rules: firewallRules.data,\n scheduled_jobs: scheduledJobs.data,\n });\n}\n\n/**\n * Handle site context action — fetches site details plus all sub-resources\n * (recent deployments, certificates, redirect rules, security rules)\n * in parallel in a single call. Deployments are limited to the last 5.\n */\nexport async function handleSiteContext(\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n const serverId = args.server_id;\n const siteId = args.id;\n if (!serverId) return errorResult(\"Missing required field: server_id\");\n if (!siteId) return errorResult(\"Missing required field: id\");\n\n const execCtx = ctx.executorContext;\n\n const [site, deployments, certificates, redirectRules, securityRules] = await Promise.all([\n getSite({ server_id: serverId, site_id: siteId }, execCtx),\n listDeployments({ server_id: serverId, site_id: siteId }, execCtx),\n listCertificates({ server_id: serverId, site_id: siteId }, execCtx),\n listRedirectRules({ server_id: serverId, site_id: siteId }, execCtx),\n listSecurityRules({ server_id: serverId, site_id: siteId }, execCtx),\n ]);\n\n const recentDeployments = Array.isArray(deployments.data)\n ? deployments.data.slice(0, 5)\n : deployments.data;\n\n return jsonResult({\n site: site.data,\n deployments: recentDeployments,\n certificates: certificates.data,\n redirect_rules: redirectRules.data,\n security_rules: securityRules.data,\n });\n}\n","import {\n createServer,\n deleteServer,\n getServer,\n listServers,\n rebootServer,\n resolveServers,\n} from \"@studiometa/forge-core\";\n\nimport type { ForgeServer } from \"@studiometa/forge-api\";\nimport type { ResolveResult } from \"@studiometa/forge-core\";\n\nimport { formatServer, formatServerList } from \"../formatters.ts\";\nimport { getServerHints } from \"../hints.ts\";\nimport { handleServerContext } from \"./context.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nconst _handleServers = createResourceHandler({\n resource: \"servers\",\n actions: [\"list\", \"get\", \"create\", \"delete\", \"reboot\", \"resolve\"],\n requiredFields: {\n get: [\"id\"],\n create: [\"provider\", \"name\", \"type\", \"region\"],\n delete: [\"id\"],\n reboot: [\"id\"],\n resolve: [\"query\"],\n },\n executors: {\n list: listServers,\n get: getServer,\n create: createServer,\n delete: deleteServer,\n reboot: rebootServer,\n resolve: resolveServers,\n },\n hints: (_data, id) => getServerHints(id),\n mapOptions: (action, args) => {\n switch (action) {\n case \"get\":\n case \"delete\":\n case \"reboot\":\n return { server_id: args.id };\n case \"create\":\n return {\n provider: args.provider,\n /* v8 ignore next */\n credential_id: Number(args.credential_id) || 0,\n name: args.name,\n /* v8 ignore next */\n type: args.type ?? \"app\",\n /* v8 ignore next */\n size: args.size ?? \"\",\n region: args.region,\n };\n case \"resolve\":\n return { query: args.query };\n default:\n return {};\n }\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatServerList(data as ForgeServer[]);\n case \"get\":\n return formatServer(data as ForgeServer);\n case \"create\":\n return formatServer(data as ForgeServer);\n case \"delete\":\n return `Server ${args.id} deleted.`;\n case \"reboot\":\n return `Server ${args.id} reboot initiated.`;\n case \"resolve\": {\n const result = data as ResolveResult;\n if (result.total === 0) return `No servers matching \"${result.query}\".`;\n const lines = result.matches.map((m) => `• ${m.name} (ID: ${m.id})`);\n return `${result.total} server(s) matching \"${result.query}\":\\n${lines.join(\"\\n\")}`;\n }\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n\n/**\n * Handle servers resource actions, intercepting the `context` action\n * for rich single-call resource fetching.\n */\nexport async function handleServers(\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n if (action === \"context\") {\n return handleServerContext(args, ctx);\n }\n return _handleServers(action, args, ctx);\n}\n","import { createSite, deleteSite, getSite, listSites, resolveSites } from \"@studiometa/forge-core\";\n\nimport type { ForgeSite } from \"@studiometa/forge-api\";\nimport type { ResolveSiteResult } from \"@studiometa/forge-core\";\n\nimport { formatSite, formatSiteList } from \"../formatters.ts\";\nimport { getSiteHints } from \"../hints.ts\";\nimport { handleSiteContext } from \"./context.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nconst _handleSites = createResourceHandler({\n resource: \"sites\",\n actions: [\"list\", \"get\", \"create\", \"delete\", \"resolve\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"domain\"],\n delete: [\"server_id\", \"id\"],\n resolve: [\"server_id\", \"query\"],\n },\n executors: {\n list: listSites,\n get: getSite,\n create: createSite,\n delete: deleteSite,\n resolve: resolveSites,\n },\n hints: (data, id) => {\n const site = data as ForgeSite;\n return getSiteHints(String(site.server_id), id);\n },\n mapOptions: (action, args) => {\n switch (action) {\n case \"list\":\n return { server_id: args.server_id };\n case \"get\":\n return { server_id: args.server_id, site_id: args.id };\n case \"create\":\n return {\n server_id: args.server_id,\n domain: args.domain,\n project_type: args.project_type ?? \"php\",\n directory: args.directory,\n };\n case \"delete\":\n return { server_id: args.server_id, site_id: args.id };\n case \"resolve\":\n return { server_id: args.server_id, query: args.query };\n /* v8 ignore next */\n default:\n return {};\n }\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatSiteList(data as ForgeSite[], args.server_id as string | undefined);\n case \"get\":\n return formatSite(data as ForgeSite);\n case \"create\":\n return formatSite(data as ForgeSite);\n case \"delete\":\n return `Site ${args.id} deleted from server ${args.server_id}.`;\n case \"resolve\": {\n const result = data as ResolveSiteResult;\n if (result.total === 0)\n return `No sites matching \"${result.query}\" on server ${args.server_id}.`;\n const lines = result.matches.map((m) => `• ${m.name} (ID: ${m.id})`);\n return `${result.total} site(s) matching \"${result.query}\" on server ${args.server_id}:\\n${lines.join(\"\\n\")}`;\n }\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n\n/**\n * Handle sites resource actions, intercepting the `context` action\n * for rich single-call resource fetching.\n */\nexport async function handleSites(\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n if (action === \"context\") {\n return handleSiteContext(args, ctx);\n }\n return _handleSites(action, args, ctx);\n}\n","import { createSshKey, deleteSshKey, getSshKey, listSshKeys } from \"@studiometa/forge-core\";\n\nimport type { ForgeSshKey } from \"@studiometa/forge-api\";\n\nimport { formatSshKey, formatSshKeyList } from \"../formatters.ts\";\nimport { getSshKeyHints } from \"../hints.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleSshKeys = createResourceHandler({\n resource: \"ssh-keys\",\n actions: [\"list\", \"get\", \"create\", \"delete\"],\n requiredFields: {\n list: [\"server_id\"],\n get: [\"server_id\", \"id\"],\n create: [\"server_id\", \"name\", \"key\"],\n delete: [\"server_id\", \"id\"],\n },\n executors: {\n list: listSshKeys,\n get: getSshKey,\n create: createSshKey,\n delete: deleteSshKey,\n },\n hints: (data, id) => {\n const key = data as ForgeSshKey;\n return getSshKeyHints(String(key.server_id), id);\n },\n formatResult: (action, data, args) => {\n switch (action) {\n case \"list\":\n return formatSshKeyList(data as ForgeSshKey[]);\n case \"get\":\n return formatSshKey(data as ForgeSshKey);\n case \"create\":\n return formatSshKey(data as ForgeSshKey);\n case \"delete\":\n return `SSH key ${args.id} deleted.`;\n /* v8 ignore next */\n default:\n return \"Done.\";\n }\n },\n});\n","import { getUser } from \"@studiometa/forge-core\";\n\nimport type { ForgeUser } from \"@studiometa/forge-api\";\n\nimport { formatUser } from \"../formatters.ts\";\nimport { createResourceHandler } from \"./factory.ts\";\n\nexport const handleUser = createResourceHandler({\n resource: \"user\",\n actions: [\"get\"],\n executors: {\n get: getUser,\n },\n formatResult: (_action, data) => {\n return formatUser(data as ForgeUser);\n },\n});\n","import type { ExecutorContext } from \"@studiometa/forge-core\";\nimport { resolveServers, resolveSites } from \"@studiometa/forge-core\";\nimport type { CommonArgs } from \"./types.ts\";\nimport { errorResult } from \"./utils.ts\";\nimport type { ToolResult } from \"./types.ts\";\n\n/**\n * Check if a value is a numeric ID.\n */\nfunction isNumericId(value: string): boolean {\n return /^\\d+$/.test(value);\n}\n\n/**\n * Result of auto-resolution. Either the args are updated with resolved IDs,\n * or an error result is returned.\n */\nexport type AutoResolveResult = { ok: true; args: CommonArgs } | { ok: false; error: ToolResult };\n\n/**\n * Auto-resolve non-numeric server_id and site_id fields.\n *\n * Order matters: server_id is resolved first because site_id resolution\n * requires a numeric server_id.\n *\n * Skipped for the 'resolve' action itself (it IS the resolve action).\n */\nexport async function autoResolveIds(\n args: CommonArgs,\n executorContext: ExecutorContext,\n): Promise<AutoResolveResult> {\n // Don't auto-resolve for the resolve action itself\n if (args.action === \"resolve\") {\n return { ok: true, args };\n }\n\n const resolved = { ...args };\n\n // Resolve server_id if non-numeric\n if (resolved.server_id && !isNumericId(resolved.server_id)) {\n const result = await resolveServers({ query: resolved.server_id }, executorContext);\n const { matches, total } = result.data;\n\n if (total === 0) {\n return {\n ok: false,\n error: errorResult(\n `No server matching \"${resolved.server_id}\". Use { resource: \"servers\", action: \"resolve\", query: \"${resolved.server_id}\" } to search.`,\n ),\n };\n }\n\n // Check for exact single match\n const exactMatch = matches.length === 1 && total === 1;\n if (!exactMatch && total > 1) {\n const matchList = matches.map((m) => ` • ${m.name} (ID: ${m.id})`).join(\"\\n\");\n return {\n ok: false,\n error: errorResult(\n `Ambiguous server name \"${resolved.server_id}\" — ${total} matches found:\\n${matchList}\\n\\nUse a more specific name or pass the numeric ID.`,\n ),\n };\n }\n\n resolved.server_id = String(matches[0]!.id);\n }\n\n // Resolve site_id if non-numeric (requires resolved server_id)\n if (resolved.site_id && !isNumericId(resolved.site_id)) {\n if (!resolved.server_id) {\n return {\n ok: false,\n error: errorResult(\n \"Cannot resolve site name without a server_id. Provide server_id first.\",\n ),\n };\n }\n\n const result = await resolveSites(\n { server_id: resolved.server_id, query: resolved.site_id },\n executorContext,\n );\n const { matches, total } = result.data;\n\n if (total === 0) {\n return {\n ok: false,\n error: errorResult(\n `No site matching \"${resolved.site_id}\" on server ${resolved.server_id}. Use { resource: \"sites\", action: \"resolve\", server_id: \"${resolved.server_id}\", query: \"${resolved.site_id}\" } to search.`,\n ),\n };\n }\n\n if (total > 1) {\n const matchList = matches.map((m) => ` • ${m.name} (ID: ${m.id})`).join(\"\\n\");\n return {\n ok: false,\n error: errorResult(\n `Ambiguous site name \"${resolved.site_id}\" — ${total} matches found:\\n${matchList}\\n\\nUse a more specific name or pass the numeric ID.`,\n ),\n };\n }\n\n resolved.site_id = String(matches[0]!.id);\n }\n\n return { ok: true, args: resolved };\n}\n","/**\n * Tool execution handlers for Forge MCP server.\n * Shared between stdio and HTTP transports.\n *\n * Two tools with clear separation:\n * - forge: read-only operations (list, get, help, schema)\n * - forge_write: write operations (create, update, delete, deploy, reboot, etc.)\n */\n\nimport type { AuditLogger, ExecutorContext } from \"@studiometa/forge-core\";\n\nimport { HttpClient } from \"@studiometa/forge-api\";\nimport { createAuditLogger, RESOURCES } from \"@studiometa/forge-core\";\n\nimport type { CommonArgs, HandlerContext, ToolResult } from \"./types.ts\";\n\nimport { handleBackups } from \"./backups.ts\";\nimport { handleBatch } from \"./batch.ts\";\nimport { handleCertificates } from \"./certificates.ts\";\nimport { handleCommands } from \"./commands.ts\";\nimport { handleDaemons } from \"./daemons.ts\";\nimport { handleDatabases } from \"./databases.ts\";\nimport { handleDatabaseUsers } from \"./database-users.ts\";\nimport { handleDeployments } from \"./deployments.ts\";\nimport { handleEnv } from \"./env.ts\";\nimport { handleFirewallRules } from \"./firewall-rules.ts\";\nimport { handleHelp, handleHelpOverview } from \"./help.ts\";\nimport { handleMonitors } from \"./monitors.ts\";\nimport { handleNginxConfig } from \"./nginx-config.ts\";\nimport { handleNginxTemplates } from \"./nginx-templates.ts\";\nimport { handleRecipes } from \"./recipes.ts\";\nimport { handleRedirectRules } from \"./redirect-rules.ts\";\nimport { handleScheduledJobs } from \"./scheduled-jobs.ts\";\nimport { handleSchema, handleSchemaOverview } from \"./schema.ts\";\nimport { handleSecurityRules } from \"./security-rules.ts\";\nimport { handleServers } from \"./servers.ts\";\nimport { handleSites } from \"./sites.ts\";\nimport { handleSshKeys } from \"./ssh-keys.ts\";\nimport { handleUser } from \"./user.ts\";\nimport { isForgeApiError } from \"@studiometa/forge-api\";\n\nimport { isUserInputError } from \"../errors.ts\";\nimport { isWriteAction, isReadAction } from \"../tools.ts\";\nimport { errorResult } from \"./utils.ts\";\nimport { autoResolveIds } from \"./auto-resolve.ts\";\n\nexport type { ToolResult } from \"./types.ts\";\n\n/** Valid resources derived from core constants */\nconst VALID_RESOURCES = [...RESOURCES];\n\n// Lazy audit logger — initialized on first write call to avoid import-time side effects\nlet _auditLogger: AuditLogger | null = null;\nfunction getAuditLogger(): AuditLogger {\n if (!_auditLogger) _auditLogger = createAuditLogger(\"mcp\");\n return _auditLogger;\n}\n\n/**\n * Route to the appropriate resource handler.\n */\nfunction routeToHandler(\n resource: string,\n action: string,\n args: CommonArgs,\n ctx: HandlerContext,\n): Promise<ToolResult> {\n switch (resource) {\n case \"servers\":\n return handleServers(action, args, ctx);\n case \"sites\":\n return handleSites(action, args, ctx);\n case \"deployments\":\n return handleDeployments(action, args, ctx);\n case \"env\":\n return handleEnv(action, args, ctx);\n case \"nginx\":\n return handleNginxConfig(action, args, ctx);\n case \"certificates\":\n return handleCertificates(action, args, ctx);\n case \"databases\":\n return handleDatabases(action, args, ctx);\n case \"database-users\":\n return handleDatabaseUsers(action, args, ctx);\n case \"daemons\":\n return handleDaemons(action, args, ctx);\n case \"firewall-rules\":\n return handleFirewallRules(action, args, ctx);\n case \"ssh-keys\":\n return handleSshKeys(action, args, ctx);\n case \"security-rules\":\n return handleSecurityRules(action, args, ctx);\n case \"redirect-rules\":\n return handleRedirectRules(action, args, ctx);\n case \"monitors\":\n return handleMonitors(action, args, ctx);\n case \"nginx-templates\":\n return handleNginxTemplates(action, args, ctx);\n case \"recipes\":\n return handleRecipes(action, args, ctx);\n case \"backups\":\n return handleBackups(action, args, ctx);\n case \"commands\":\n return handleCommands(action, args, ctx);\n case \"scheduled-jobs\":\n return handleScheduledJobs(action, args, ctx);\n case \"user\":\n return handleUser(action, args, ctx);\n case \"batch\":\n return handleBatch(action, args, ctx, routeToHandler);\n /* v8 ignore next 6 -- all valid resources are handled above; unreachable in practice */\n default:\n return Promise.resolve(\n errorResult(\n `Unknown resource \"${resource}\". Valid resources: ${VALID_RESOURCES.join(\", \")}. Use action=\"help\" for documentation.`,\n ),\n );\n }\n}\n\n/**\n * Execute a tool call with provided credentials.\n *\n * This is the main entry point shared between stdio and HTTP transports.\n * Validates that the action matches the tool (read vs write).\n */\nexport async function executeToolWithCredentials(\n name: string,\n args: Record<string, unknown>,\n credentials: { apiToken: string },\n): Promise<ToolResult> {\n const { resource, action, compact, ...rest } = args as CommonArgs;\n\n if (!resource || !action) {\n return errorResult('Missing required fields: \"resource\" and \"action\".');\n }\n\n // Batch resource is read-only even though it uses the \"run\" action name.\n // Handle it early, before the write-action guard, to avoid misdirection.\n if (resource === \"batch\") {\n // Validate batch is only called from the forge (read) tool\n if (name !== \"forge\") {\n return errorResult(\n 'The \"batch\" resource is read-only and must be used with the \"forge\" tool, not \"forge_write\".',\n );\n }\n // Validate resource is known before creating context\n const client = new HttpClient({ token: credentials.apiToken });\n const executorContext: ExecutorContext = { client };\n const handlerContext: HandlerContext = {\n executorContext,\n compact: compact ?? true,\n };\n return routeToHandler(\n resource,\n action,\n { resource, action, ...rest } as CommonArgs,\n handlerContext,\n );\n }\n\n // Validate action matches the tool\n if (name === \"forge\" && isWriteAction(action)) {\n return errorResult(\n `Action \"${action}\" is a write operation. Use the \"forge_write\" tool instead.`,\n );\n }\n\n if (name === \"forge_write\" && isReadAction(action)) {\n return errorResult(`Action \"${action}\" is a read operation. Use the \"forge\" tool instead.`);\n }\n\n // Help is available for all resources (doesn't need API)\n if (action === \"help\") {\n /* v8 ignore start */\n return resource ? handleHelp(resource) : handleHelpOverview();\n /* v8 ignore stop */\n }\n\n // Schema is available for all resources (doesn't need API)\n if (action === \"schema\") {\n /* v8 ignore start */\n return resource ? handleSchema(resource) : handleSchemaOverview();\n /* v8 ignore stop */\n }\n\n // Validate resource\n if (!VALID_RESOURCES.includes(resource as (typeof VALID_RESOURCES)[number])) {\n return errorResult(\n `Unknown resource \"${resource}\". Valid resources: ${VALID_RESOURCES.join(\", \")}. Use action=\"help\" for documentation.`,\n );\n }\n\n // Create executor context\n const client = new HttpClient({ token: credentials.apiToken });\n const executorContext: ExecutorContext = { client };\n const handlerContext: HandlerContext = {\n executorContext,\n compact: compact ?? action !== \"get\",\n includeHints: action === \"get\",\n };\n\n // Auto-resolve non-numeric server_id/site_id\n const allArgs = { resource, action, ...rest } as CommonArgs;\n const resolveResult = await autoResolveIds(allArgs, executorContext);\n if (!resolveResult.ok) {\n return resolveResult.error;\n }\n const resolvedArgs = resolveResult.args;\n\n // Route to resource handler with error catching\n try {\n const result = await routeToHandler(resource, action, resolvedArgs, handlerContext);\n if (name === \"forge_write\") {\n getAuditLogger().log({\n source: \"mcp\",\n resource,\n action,\n args: rest as Record<string, unknown>,\n status: result.isError ? \"error\" : \"success\",\n });\n }\n return result;\n } catch (error) {\n let errorMessage: string;\n if (isUserInputError(error)) {\n errorMessage = error.toFormattedMessage();\n } else if (isForgeApiError(error)) {\n errorMessage = `Forge API error (${error.status}): ${error.message}`;\n } else {\n /* v8 ignore start */\n errorMessage = error instanceof Error ? error.message : String(error);\n /* v8 ignore stop */\n }\n if (name === \"forge_write\") {\n getAuditLogger().log({\n source: \"mcp\",\n resource,\n action,\n args: rest as Record<string, unknown>,\n status: \"error\",\n error: errorMessage,\n });\n }\n return errorResult(errorMessage);\n }\n}\n","declare const __VERSION__: string;\n\nexport const VERSION: string = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : \"0.0.0-dev\";\n"],"mappings":";;;;;;;;;;;;;;AAcA,IAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;;;;;AAMzD,SAAS,mBAA2B;AAClC,KAAI;AAQF,SALgB,aADE,KAAK,WAAW,MAAM,UAAU,WAAW,EACrB,QAAQ,CAGb,QAAQ,0BAA0B,GAAG,CAE9C,MAAM;SAC1B;AACN,SAAO;;;AAIX,MAAa,eAAe,kBAAkB;;;;ACC9C,SAAgB,iBAAiB,SAAgC;AAC/D,KAAI,QAAQ,WAAW,EACrB,QAAO;CAET,MAAM,QAAQ,QAAQ,KACnB,MACC,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,SAAS,GAAG,EAAE,OAAO,KAAK,EAAE,WAAW,KAAK,EAAE,WAAW,UAAU,iBACvG;AACD,QAAO,GAAG,QAAQ,OAAO,eAAe,MAAM,KAAK,KAAK;;;;;AAM1D,SAAgB,aAAa,QAA6B;AACxD,QAAO;EACL,WAAW,OAAO,KAAK,QAAQ,OAAO,GAAG;EACzC,aAAa,OAAO,SAAS,IAAI,OAAO,OAAO;EAC/C,OAAO,OAAO;EACd,QAAQ,OAAO;EACf,WAAW,OAAO;EAClB,WAAW,OAAO,WAAW,UAAU;EACvC,YAAY,OAAO;EACpB,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,eAAe,OAAoB,UAA2B;AAC5E,KAAI,MAAM,WAAW,EACnB,QAAO,WAAW,sBAAsB,SAAS,KAAK;CAExD,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,aAAa,KAAK,EAAE,SAAS;AAI7F,QAAO,GAHQ,WACX,GAAG,MAAM,OAAO,qBAAqB,SAAS,KAC9C,GAAG,MAAM,OAAO,WACH,IAAI,MAAM,KAAK,KAAK;;;;;AAMvC,SAAgB,WAAW,MAAyB;AAClD,QAAO;EACL,SAAS,KAAK,KAAK,QAAQ,KAAK,GAAG;EACnC,SAAS,KAAK;EACd,cAAc,KAAK;EACnB,eAAe,KAAK,cAAc;EAClC,WAAW,KAAK,qBAAqB;EACrC,WAAW,KAAK;EAChB,kBAAkB,KAAK,qBAAqB;EAC5C,iBAAiB,KAAK,eAAe,YAAY;EACjD,QAAQ,KAAK;EACb,YAAY,KAAK;EAClB,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,mBAAmB,WAAoC;AACrE,KAAI,UAAU,WAAW,EACvB,QAAO;CAET,MAAM,QAAQ,UAAU,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,SAAS;AAC7E,QAAO,GAAG,UAAU,OAAO,iBAAiB,MAAM,KAAK,KAAK;;;;;AAM9D,SAAgB,eAAe,IAA2B;AACxD,QAAO,aAAa,GAAG,KAAK,QAAQ,GAAG,GAAG,aAAa,GAAG,OAAO,aAAa,GAAG;;;;;AAQnF,SAAgB,uBAAuB,OAAoC;AACzE,KAAI,MAAM,WAAW,EACnB,QAAO;CAET,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,SAAS;AACzE,QAAO,GAAG,MAAM,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAM/D,SAAgB,mBAAmB,MAAiC;AAClE,QAAO;EACL,kBAAkB,KAAK,KAAK,QAAQ,KAAK,GAAG;EAC5C,WAAW,KAAK;EAChB,cAAc,KAAK,UAAU,SAAS,IAAI,KAAK,UAAU,KAAK,KAAK,GAAG;EACtE,YAAY,KAAK;EAClB,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,qBAAqB,aAAwC;AAC3E,KAAI,YAAY,WAAW,EACzB,QAAO;CAET,MAAM,QAAQ,YAAY,KACvB,MACC,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,KAAK,EAAE,aAAa,MAAM,GAAG,EAAE,IAAI,YAAY,KAAK,EAAE,aAClF;AACD,QAAO,GAAG,YAAY,OAAO,mBAAmB,MAAM,KAAK,KAAK;;;;;;;;;AAUlE,SAAgB,mBACd,QACA,UACA,QACQ;AACR,KAAI,CAAC,OACH,QAAO,iCAAiC,OAAO,aAAa,SAAS;CAGvE,MAAM,cAAc,OAAO,aAAa,KAAM,QAAQ,EAAE;CAExD,MAAM,QAAQ,CACZ,cAFkB,OAAO,WAAW,YAAY,gBAAgB,WAEtC,YAAY,OAAO,aAAa,SAAS,IAAI,WAAW,KACnF;AAED,KAAI,OAAO,IACT,OAAM,KAAK,IAAI,mBAAmB,OAAO,IAAI;AAG/C,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,uBAAuB,QAAwB;AAC7D,QAAO,uBAAuB;;;;;AAMhC,SAAgB,uBAAuB,cAAsB,QAAwB;AACnF,QAAO,cAAc,aAAa,YAAY;;;;;AAMhD,SAAgB,8BAA8B,QAAgB,UAA0B;AACtF,QAAO,sCAAsC,OAAO,aAAa,SAAS;;;;;AAQ5E,SAAgB,sBAAsB,cAA0C;AAC9E,KAAI,aAAa,WAAW,EAC1B,QAAO;CAET,MAAM,QAAQ,aAAa,KACxB,MACC,KAAK,EAAE,OAAO,QAAQ,EAAE,GAAG,MAAM,EAAE,KAAK,KAAK,EAAE,SAAS,WAAW,WAAW,KAAK,EAAE,SACxF;AACD,QAAO,GAAG,aAAa,OAAO,oBAAoB,MAAM,KAAK,KAAK;;;;;AAMpE,SAAgB,kBAAkB,MAAgC;AAChE,QAAO,gBAAgB,KAAK,OAAO,QAAQ,KAAK,GAAG,WAAW,KAAK,KAAK,YAAY,KAAK,OAAO,YAAY,KAAK;;;;;AAQnH,SAAgB,iBAAiB,SAAgC;AAC/D,KAAI,QAAQ,WAAW,EACrB,QAAO;CAET,MAAM,QAAQ,QAAQ,KAAK,MAAM,KAAK,EAAE,QAAQ,QAAQ,EAAE,GAAG,YAAY,EAAE,KAAK,KAAK,EAAE,SAAS;AAChG,QAAO,GAAG,QAAQ,OAAO,eAAe,MAAM,KAAK,KAAK;;;;;AAM1D,SAAgB,aAAa,QAA6B;AACxD,QAAO,WAAW,OAAO,QAAQ,QAAQ,OAAO,GAAG,WAAW,OAAO,KAAK,eAAe,OAAO,UAAU,YAAY,OAAO;;;;;AAQ/H,SAAgB,uBAAuB,OAAoC;AACzE,KAAI,MAAM,WAAW,EACnB,QAAO;CAET,MAAM,QAAQ,MAAM,KACjB,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,YAAY,EAAE,KAAK,KAAK,EAAE,WAAW,KAAK,EAAE,SAC7E;AACD,QAAO,GAAG,MAAM,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAM/D,SAAgB,mBAAmB,MAAiC;AAClE,QAAO,kBAAkB,KAAK,KAAK,QAAQ,KAAK,GAAG,WAAW,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ,KAAK,WAAW,YAAY,KAAK;;;;;AAQvI,SAAgB,kBAAkB,UAAkC;AAClE,KAAI,SAAS,WAAW,EACtB,QAAO;CAET,MAAM,QAAQ,SAAS,KACpB,MAAM,KAAK,EAAE,KAAK,GAAG,EAAE,SAAS,GAAG,EAAE,UAAU,QAAQ,EAAE,GAAG,MAAM,EAAE,QACtE;AACD,QAAO,GAAG,SAAS,OAAO,gBAAgB,MAAM,KAAK,KAAK;;;;;AAM5D,SAAgB,cAAc,SAA+B;AAC3D,QAAO,YAAY,QAAQ,KAAK,GAAG,QAAQ,SAAS,GAAG,QAAQ,UAAU,QAAQ,QAAQ,GAAG,YAAY,QAAQ,MAAM,aAAa,QAAQ;;;;;AAQ7I,SAAgB,iBAAiB,MAA6B;AAC5D,KAAI,KAAK,WAAW,EAClB,QAAO;CAET,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,SAAS;AACxE,QAAO,GAAG,KAAK,OAAO,gBAAgB,MAAM,KAAK,KAAK;;;;;AAMxD,SAAgB,aAAa,KAA0B;AACrD,QAAO,YAAY,IAAI,KAAK,QAAQ,IAAI,GAAG,aAAa,IAAI,OAAO,aAAa,IAAI;;;;;AAQtF,SAAgB,uBAAuB,MAAmC;AACxE,KAAI,KAAK,WAAW,EAClB,QAAO;CAET,MAAM,QAAQ,KAAK,KAChB,MAAM,KAAK,EAAE,QAAQ,QAAQ,EAAE,GAAG,MAAM,EAAE,UAAU,KAAK,EAAE,OAAO,WAAW,EAAE,OACjF;AACD,QAAO,GAAG,KAAK,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAM9D,SAAgB,mBAAmB,KAAgC;AACjE,QAAO;EACL,QAAQ,IAAI,QAAQ,QAAQ,IAAI,GAAG;EACnC,SAAS,IAAI;EACb,cAAc,IAAI;EAClB,SAAS,IAAI;EACb,WAAW,IAAI;EACf,YAAY,IAAI;EACjB,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,uBAAuB,OAAoC;AACzE,KAAI,MAAM,WAAW,EACnB,QAAO;CAET,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,YAAY,EAAE,QAAQ,MAAM;AACpF,QAAO,GAAG,MAAM,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAM/D,SAAgB,mBAAmB,MAAiC;AAClE,QAAO,kBAAkB,KAAK,KAAK,QAAQ,KAAK,GAAG,WAAW,KAAK,QAAQ;;;;;AAQ7E,SAAgB,uBAAuB,OAAoC;AACzE,KAAI,MAAM,WAAW,EACnB,QAAO;CAET,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,EAAE,KAAK,KAAK,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,OAAO;AACjF,QAAO,GAAG,MAAM,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAM/D,SAAgB,mBAAmB,MAAiC;AAClE,QAAO,kBAAkB,KAAK,KAAK,KAAK,KAAK,GAAG,QAAQ,KAAK,GAAG,WAAW,KAAK;;;;;AAQlF,SAAgB,kBAAkB,SAAyB;AACzD,QAAO,yBAAyB;;;;;AAQlC,SAAgB,wBAAwB,WAAyC;AAC/E,KAAI,UAAU,WAAW,EACvB,QAAO;CAET,MAAM,QAAQ,UAAU,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,GAAG;AAC/D,QAAO,GAAG,UAAU,OAAO,uBAAuB,MAAM,KAAK,KAAK;;;;;AAMpE,SAAgB,oBAAoB,UAAsC;AACxE,QAAO,mBAAmB,SAAS,KAAK,QAAQ,SAAS,GAAG,OAAO,SAAS;;;;;AAQ9E,SAAgB,uBAAuB,SAAsC;AAC3E,KAAI,QAAQ,WAAW,EACrB,QAAO;CAET,MAAM,QAAQ,QAAQ,KACnB,MACC,KAAK,EAAE,cAAc,QAAQ,EAAE,GAAG,MAAM,EAAE,UAAU,KAAK,EAAE,OAAO,WAAW,EAAE,oBAAoB,UACtG;AACD,QAAO,GAAG,QAAQ,OAAO,sBAAsB,MAAM,KAAK,KAAK;;;;;AAMjE,SAAgB,mBAAmB,QAAmC;AACpE,QAAO;EACL,kBAAkB,OAAO,cAAc,QAAQ,OAAO,GAAG;EACzD,cAAc,OAAO;EACrB,WAAW,OAAO;EAClB,cAAc,OAAO,UAAU;EAC/B,cAAc,OAAO,UAAU,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,IAAI;EAChE,gBAAgB,OAAO,oBAAoB;EAC5C,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,iBAAiB,SAAgC;AAC/D,KAAI,QAAQ,WAAW,EACrB,QAAO;CAET,MAAM,QAAQ,QAAQ,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,YAAY,EAAE,OAAO;AAC/E,QAAO,GAAG,QAAQ,OAAO,eAAe,MAAM,KAAK,KAAK;;;;;AAM1D,SAAgB,aAAa,QAA6B;AACxD,QAAO,WAAW,OAAO,KAAK,QAAQ,OAAO,GAAG,WAAW,OAAO,KAAK,aAAa,OAAO;;;;;AAQ7F,SAAgB,kBAAkB,UAAkC;AAClE,KAAI,SAAS,WAAW,EACtB,QAAO;CAET,MAAM,QAAQ,SAAS,KACpB,MAAM,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,KAAK,EAAE,UAAU,KAAK,EAAE,QAAQ,MAAM,GAAG,GAAG,GAC7E;AACD,QAAO,GAAG,SAAS,OAAO,gBAAgB,MAAM,KAAK,KAAK;;;;;AAM5D,SAAgB,cAAc,SAA+B;AAC3D,QAAO;EACL,YAAY,QAAQ;EACpB,YAAY,QAAQ;EACpB,WAAW,QAAQ;EACnB,SAAS,QAAQ;EACjB,YAAY,QAAQ;EACrB,CAAC,KAAK,KAAK;;;;;AAQd,SAAgB,UAAU,SAAyB;AACjD,QAAO,2BAA2B;;;;;AAQpC,SAAgB,WAAW,MAAyB;AAClD,QAAO;EACL,SAAS,KAAK,KAAK,QAAQ,KAAK,GAAG;EACnC,UAAU,KAAK;EACf,WAAW,KAAK,sBAAsB,cAAc;EACpD,WAAW,KAAK,sBAAsB,cAAc;EACpD,QAAQ,KAAK,qBAAqB,YAAY;EAC/C,CAAC,KAAK,KAAK;;;;;;;;;;;;;;AClfd,IAAa,iBAAb,cAAoC,MAAM;CACxC;CAEA,YAAY,SAAiB,OAAkB;AAC7C,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,QAAQ;;;;;CAMf,qBAA6B;EAC3B,IAAI,MAAM,oBAAoB,KAAK;AACnC,MAAI,KAAK,SAAS,KAAK,MAAM,SAAS,EACpC,QAAO,qBAAqB,KAAK,MAAM,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,KAAK;AAExE,SAAO;;;;;;AAyEX,SAAgB,iBAAiB,OAAyC;AACxE,QAAO,iBAAiB;;;;;;;;;AC7F1B,SAAgB,WAAW,MAA8D;AAEvF,QAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAFf,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,EAAE;GAE1C,CAAC;EACjC,mBAAmB;GAAE,SAAS;GAAM,QAAQ;GAAM;EACnD;;;;;;;;AASH,SAAgB,WAAW,OAAwB;AACjD,QAAO,WAAW,KAAK,MAAM;;;;;AAM/B,SAAgB,YAAY,SAA6B;AACvD,QAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,UAAU;GAAW,CAAC;EACtD,mBAAmB;GAAE,SAAS;GAAO,OAAO;GAAS;EACrD,SAAS;EACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACkDH,SAAgB,sBACd,QACgF;CAChF,MAAM,EACJ,UACA,SACA,iBAAiB,EAAE,EACnB,WACA,OACA,YACA,iBACE;AAEJ,QAAO,OAAO,QAAgB,MAAkB,QAA6C;AAE3F,MAAI,CAAC,QAAQ,SAAS,OAAO,CAC3B,QAAO,YACL,mBAAmB,OAAO,QAAQ,SAAS,mBAAmB,QAAQ,KAAK,KAAK,CAAC,GAClF;EAIH,MAAM,WAAW,eAAe,WAAW,EAAE;AAC7C,OAAK,MAAM,SAAS,SAClB,KAAI,CAAC,KAAK,OACR,QAAO,YAAY,2BAA2B,QAAQ;AAK1D,OAAK,MAAM,SAAS;GAAC;GAAM;GAAa;GAAU,EAAE;GAClD,MAAM,QAAQ,KAAK;AACnB,OAAI,UAAU,KAAA,KAAa,CAAC,WAAW,OAAO,MAAM,CAAC,CACnD,QAAO,YAAY,WAAW,MAAM,KAAK,MAAM,8BAA8B;;EAKjF,MAAM,WAAW,UAAU;AAC3B,MAAI,CAAC,SACH,QAAO,YAAY,WAAW,OAAO,+BAA+B,SAAS,GAAG;EAIlF,IAAI;AACJ,MAAI,WACF,WAAU,WAAW,QAAQ,KAAK;OAC7B;GACL,MAAM,EAAE,UAAU,IAAI,QAAQ,IAAI,SAAS,IAAI,GAAG,SAAS;AAC3D,aAAU;;EAIZ,MAAM,SAAS,MAAM,SAAS,SAAoC,IAAI,gBAAgB;AAGtF,MAAI,OAAO,SAAS,KAAA,EAGlB,QAAO,WADM,eAAe,aAAa,QAAQ,KAAA,GAAW,KAAK,GAAG,QAC7C;AAGzB,MAAI,IAAI,WAAW,aACjB,QAAO,WAAW,aAAa,QAAQ,OAAO,MAAM,KAAK,CAAC;AAI5D,MAAI,WAAW,SAAS,IAAI,gBAAgB,OAAO;;GAEjD,MAAM,KAAK,KAAK,MAAM,KAAK,aAAa;AAMxC,UAAO,WAJc;IACnB,GAAI,OAAO;IACX,QAAQ,MAAM,OAAO,MAAM,OAAO,GAAG,CAAC;IACvC,CAC8B;;AAGjC,SAAO,WAAW,OAAO,KAAK;;;ACzJlC,MAAa,gBAAgB,sBAAsB;CACjD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAY;GAAe;GAAa;GAAY;EAC1E,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;;;;ACnCF,MAAa,eAAe;CAAC;CAAQ;CAAO;CAAW;CAAQ;CAAU;CAAU;;;;;AAMnF,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;AAQD,SAAgB,cAAc,QAAuC;AACnE,QAAQ,cAAoC,SAAS,OAAO;;;;;AAM9D,SAAgB,aAAa,QAAsC;AACjE,QAAQ,aAAmC,SAAS,OAAO;;;;;;;;;;;;;;;;AAiB7D,IAAM,gBAAgB;CACpB,MAAM;CACN,YAAY;EACV,SAAS;GACP,MAAM;GACN,aAAa;GACd;EACD,QAAQ,EACN,aACE,oHACH;EACD,OAAO;GACL,MAAM;GACN,aAAa;GACd;EACF;CACD,UAAU,CAAC,UAAU;CACtB;;;;AAKD,IAAM,0BAA0B;CAC9B,UAAU;EACR,MAAM;EACN,MAAM,CAAC,GAAG,UAAU;EACpB,aAAa;EACd;CACD,IAAI;EAAE,MAAM;EAAmB,aAAa;EAAiD;CAC7F,WAAW;EACT,MAAM;EACN,aACE;EACH;CACD,SAAS;EACP,MAAM;EACN,aAAa;EACd;CACD,SAAS;EACP,MAAM;EACN,aAAa;EACd;CACD,OAAO;EACL,MAAM;EACN,aACE;EACH;CACF;;;;;;;;AA0MD,MAAa,QAAgB,CAlMC;CAC5B,MAAM;CACN,OAAO;CACP,aAAa;EACX;EACA,cAAc,UAAU,KAAK,KAAK,CAAC;EACnC,YAAY,CAAC,GAAG,aAAa,CAAC,KAAK,KAAK,CAAC;EACzC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK;CACZ,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY;GACV,GAAG;GACH,QAAQ;IACN,MAAM;IACN,MAAM,CAAC,GAAG,aAAa;IACvB,aAAa;IACd;GACD,YAAY;IACV,MAAM;IACN,aACE;IACF,OAAO;KACL,MAAM;KACN,YAAY;MACV,UAAU,EAAE,MAAM,UAAmB;MACrC,QAAQ,EAAE,MAAM,UAAmB;MACpC;KACD,UAAU,CAAC,YAAY,SAAS;KACjC;IACF;GACF;EACD,UAAU,CAAC,YAAY,SAAS;EACjC;CACD,cAAc;CACf,EAQ8B;CAC7B,MAAM;CACN,OAAO;CACP,aAAa;EACX;EACA,cAAc,UAAU,KAAK,KAAK,CAAC;EACnC,YAAY,CAAC,GAAG,cAAc,CAAC,KAAK,KAAK,CAAC;EAC1C;EACA;EACA;EACD,CAAC,KAAK,KAAK;CACZ,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY;GACV,GAAG;GACH,QAAQ;IACN,MAAM;IACN,MAAM,CAAC,GAAG,cAAc;IACxB,aAAa;IACd;GAED,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,UAAU;IACR,MAAM;IACN,aAAa;IACd;GACD,QAAQ;IAAE,MAAM;IAAmB,aAAa;IAAwC;GACxF,MAAM;IAAE,MAAM;IAAmB,aAAa;IAAkC;GAChF,eAAe;IACb,MAAM;IACN,aAAa;IACd;GACD,MAAM;IACJ,MAAM;IACN,aACE;IACH;GAED,QAAQ;IAAE,MAAM;IAAmB,aAAa;IAAuC;GACvF,cAAc;IACZ,MAAM;IACN,aAAa;IACd;GACD,WAAW;IACT,MAAM;IACN,aAAa;IACd;GAED,SAAS;IACP,MAAM;IACN,aAAa;IACd;GAED,SAAS;IACP,MAAM;IACN,aACE;IACH;GACD,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GAED,MAAM;IACJ,MAAM,CAAC,UAAU,SAAS;IAC1B,aAAa;IACd;GACD,YAAY;IACV,MAAM;IACN,aAAa;IACd;GAED,KAAK;IACH,MAAM;IACN,aAAa;IACd;GAED,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,IAAI;IACF,MAAM;IACN,aAAa;IACd;GAED,aAAa;IACX,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAmB;IACnC;GAED,UAAU;IACR,MAAM;IACN,aAAa;IACd;GACD,WAAW;IACT,MAAM;IACN,aAAa;IACd;GACD,SAAS;IACP,MAAM;IACN,aAAa;IACd;GAED,WAAW;IACT,MAAM;IACN,aAAa;IACd;GAED,QAAQ;IAAE,MAAM;IAAmB,aAAa;IAAmC;GACnF,SAAS;IACP,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAmB;IACnC;GACF;EACD,UAAU,CAAC,YAAY,SAAS;EACjC;CACD,cAAc;CACf,CAS+D;;;;;;;AAgBhE,SAAgB,SAAS,SAAmC;AAC1D,KAAI,SAAS,SACX,QAAO,MAAM,QAAQ,MAAM,EAAE,SAAS,cAAc;AAEtD,QAAO,CAAC,GAAG,MAAM;;;;;AAMnB,MAAa,mBAA2B,CACtC;CACE,MAAM;CACN,OAAO;CACP,aACE;CACF,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY,EACV,UAAU;GAAE,MAAM;GAAmB,aAAa;GAAgC,EACnF;EACD,UAAU,CAAC,WAAW;EACvB;CACD,cAAc;EACZ,MAAM;EACN,YAAY;GACV,SAAS,EAAE,MAAM,WAAoB;GACrC,SAAS;IAAE,MAAM;IAAmB,aAAa;IAAwB;GACzE,UAAU;IAAE,MAAM;IAAmB,aAAa;IAAmC;GACtF;EACD,UAAU,CAAC,UAAU;EACtB;CACF,EACD;CACE,MAAM;CACN,OAAO;CACP,aAAa;CACb,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY,EAAE;EACf;CACD,cAAc;EACZ,MAAM;EACN,YAAY;GACV,UAAU;IAAE,MAAM;IAAmB,aAAa;IAAwC;GAC1F,YAAY;IAAE,MAAM;IAAoB,aAAa;IAAiC;GACvF;EACD,UAAU,CAAC,aAAa;EACzB;CACF,CACF;AC7WD,IAAM,iBAAiB;;;;AAKvB,eAAsB,YACpB,QACA,MACA,KACA,gBACqB;AACrB,KAAI,WAAW,MACb,QAAO,YAAY,mBAAmB,OAAO,gDAAgD;CAG/F,MAAM,EAAE,eAAe;AAEvB,KAAI,eAAe,KAAA,KAAa,eAAe,KAC7C,QAAO,YAAY,0EAAwE;AAG7F,KAAI,CAAC,MAAM,QAAQ,WAAW,CAC5B,QAAO,YAAY,wDAAsD;AAG3E,KAAI,WAAW,SAAS,eACtB,QAAO,YACL,wBAAwB,WAAW,OAAO,eAAe,eAAe,aACzE;AAIH,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,KAAK,WAAW;AACtB,MAAI,CAAC,MAAM,OAAO,OAAO,SACvB,QAAO,YAAY,sBAAsB,EAAE,qBAAqB;AAElE,MAAI,CAAC,GAAG,eAAe,OAAO,GAAG,gBAAgB,SAC/C,QAAO,YAAY,sBAAsB,EAAE,wCAAwC;AAErF,MAAI,CAAC,GAAG,aAAa,OAAO,GAAG,cAAc,SAC3C,QAAO,YAAY,sBAAsB,EAAE,sCAAsC;AAEnF,MAAI,CAAC,aAAa,GAAG,UAAoB,CACvC,QAAO,YACL,sBAAsB,EAAE,uBAAuB,GAAG,UAAU,qEAC7D;;CAKL,MAAM,UAAU,MAAM,QAAQ,WAC5B,WAAW,KAAK,OAAO;EACrB,MAAM,EAAE,UAAU,QAAQ,UAAU,GAAG,SAAS;AAChD,SAAO,eACL,UACA,UACA;GAAY;GAAoB,QAAQ;GAAoB,GAAG;GAAM,EACrE,IACD;GACD,CACH;CAGD,IAAI,YAAY;CAChB,IAAI,SAAS;CAEb,MAAM,UAAU,QAAQ,KAAK,SAAS,UAAU;EAC9C,MAAM,KAAK,WAAW;EACtB,MAAM,WAAW,GAAG;EACpB,MAAM,WAAW,GAAG;AAEpB,MAAI,QAAQ,WAAW,aAAa;GAClC,MAAM,aAAa,QAAQ;AAC3B,OAAI,WAAW,SAAS;AACtB;AACA,WAAO;KACL;KACA;KACA,QAAQ;KACR,OACE,WAAW,oBAAoB,YAE/B,WAAW,QAAQ,IAAI,QACvB;KACH;;AAEH;AACA,UAAO;IACL;IACA;IACA,QAAQ;IACR,MAAM,WAAW,oBAAoB,aAAa,WAAW,QAAQ,IAAI;IAC1E;SACI;AACL;AACA,UAAO;IACL;IACA;IACA,QAAQ;IACR,OAAO,QAAQ,kBAAkB,QAAQ,QAAQ,OAAO,UAAU,OAAO,QAAQ,OAAO;IACzF;;GAEH;AAEF,QAAO,WAAW;EAChB,QAAQ;GACN,OAAO,WAAW;GAClB;GACA;GACD;EACD;EACD,CAAC;;;;;AC9GJ,SAAgB,eAAe,UAAmC;AAChE,QAAO;EACL,mBAAmB;GACjB;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAS,QAAQ;KAAQ,WAAW;KAAU;IACpE;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAa,QAAQ;KAAQ,WAAW;KAAU;IACxE;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAW,QAAQ;KAAQ,WAAW;KAAU;IACtE;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAkB,QAAQ;KAAQ,WAAW;KAAU;IAC7E;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAY,QAAQ;KAAQ,WAAW;KAAU;IACvE;GACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAU,IAAI;IAAU;GACjE,CACF;EACF;;;;;AAMH,SAAgB,aAAa,UAAkB,QAAiC;AAC9E,QAAO;EACL,mBAAmB;GACjB;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAe,QAAQ;KAAQ,WAAW;KAAU,SAAS;KAAQ;IAC3F;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAO,QAAQ;KAAO,WAAW;KAAU,SAAS;KAAQ;IAClF;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAgB,QAAQ;KAAQ,WAAW;KAAU,SAAS;KAAQ;IAC5F;GACD;IACE,UAAU;IACV,aAAa;IACb,SAAS;KAAE,UAAU;KAAS,QAAQ;KAAO,WAAW;KAAU,SAAS;KAAQ;IACpF;GACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACV;GACF,CACF;EACF;;;;;AAMH,SAAgB,iBAAiB,UAAkB,YAAqC;AACtF,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAa,QAAQ;IAAQ,WAAW;IAAU;GACxE,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAa,QAAQ;IAAU,WAAW;IAAU,IAAI;IAAY;GAC1F,CACF;EACF;;;;;AAMH,SAAgB,qBAAqB,UAAkB,QAAiC;AACtF,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAU;GAC7E,EACD;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAa,QAAQ;IAAQ,WAAW;IAAU;GACxE,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACL;GACF,CACF;EACF;;;;;AAMH,SAAgB,eAAe,UAAkB,UAAmC;AAClF,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAQ,WAAW;IAAU;GACtE,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAW,WAAW;IAAU,IAAI;IAAU;GACvF,EACD;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAU,WAAW;IAAU,IAAI;IAAU;GACtF,CACF;EACF;;;;;AAMH,SAAgB,oBACd,UACA,QACA,eACiB;AACjB,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACV;GACF,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,IAAI;IACL;GACF,EACD;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,IAAI;IACL;GACF,CACF;EACF;;;;;AAMH,SAAgB,qBAAqB,UAAkB,QAAiC;AACtF,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAU;GAC7E,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACL;GACF,CACF;EACF;;;;;AAMH,SAAgB,eAAe,UAAkB,OAAgC;AAC/E,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAY,QAAQ;IAAQ,WAAW;IAAU;GACvE,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAY,QAAQ;IAAU,WAAW;IAAU,IAAI;IAAO;GACpF,CACF;EACF;;;;;AAMH,SAAgB,eAAe,UAAmC;AAChE,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAQ;GACjD,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAO,IAAI;IAAU,SAAS,EAAE;IAAE;GAC3E,EACD;GACE,QAAQ;GACR,SAAS;IAAE,UAAU;IAAW,QAAQ;IAAU,IAAI;IAAU;GACjE,CACF;EACF;;;;;AAMH,SAAgB,sBAAsB,UAAkB,YAAqC;AAC3F,QAAO;EACL,mBAAmB,CACjB;GACE,UAAU;GACV,aAAa;GACb,SAAS;IAAE,UAAU;IAAmB,QAAQ;IAAQ,WAAW;IAAU;GAC9E,CACF;EACD,gBAAgB,CACd;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACJ,SAAS;IACV;GACF,EACD;GACE,QAAQ;GACR,SAAS;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACL;GACF,CACF;EACF;;AC1TH,MAAa,qBAAqB,sBAAsB;CACtD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAW;CACxD,gBAAgB;EACd,MAAM,CAAC,aAAa,UAAU;EAC9B,KAAK;GAAC;GAAa;GAAW;GAAK;EACnC,QAAQ;GAAC;GAAa;GAAW;GAAS;EAC1C,QAAQ;GAAC;GAAa;GAAW;GAAK;EACtC,UAAU;GAAC;GAAa;GAAW;GAAK;EACzC;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,UAAU;EACX;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,OAAO;AACb,SAAO,oBAAoB,OAAO,KAAK,UAAU,EAAE,OAAO,KAAK,QAAQ,EAAE,GAAG;;CAE9E,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,sBAAsB,KAA2B;GAC1D,KAAK,MACH,QAAO,kBAAkB,KAAyB;GACpD,KAAK,SACH,QAAO,kBAAkB,KAAyB;GACpD,KAAK,SACH,QAAO,eAAe,KAAK,GAAG;GAChC,KAAK,WACH,QAAO,eAAe,KAAK,GAAG;GAEhC,QACE,QAAO;;;CAGd,CAAC;AC7CF,MAAa,iBAAiB,sBAAsB;CAClD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAS;CAClC,gBAAgB;EACd,MAAM,CAAC,aAAa,UAAU;EAC9B,KAAK;GAAC;GAAa;GAAW;GAAK;EACnC,QAAQ;GAAC;GAAa;GAAW;GAAU;EAC5C;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACT;CACD,eAAe,QAAQ,SAAS;AAC9B,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,kBAAkB,KAAuB;GAClD,KAAK,MACH,QAAO,cAAc,KAAqB;GAC5C,KAAK,SACH,QAAO,cAAc,KAAqB;GAE5C,QACE,QAAO;;;CAGd,CAAC;ACnBF,MAAa,gBAAgB,sBAAsB;CACjD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAU;CACvD,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ,CAAC,aAAa,UAAU;EAChC,QAAQ,CAAC,aAAa,KAAK;EAC3B,SAAS,CAAC,aAAa,KAAK;EAC7B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,SAAS;EACV;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,SAAS;AACf,SAAO,eAAe,OAAO,OAAO,UAAU,EAAE,GAAG;;CAErD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,iBAAiB,KAAsB;GAChD,KAAK,MACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,UAAU,KAAK,GAAG;GAC3B,KAAK,UACH,QAAO,UAAU,KAAK,GAAG;GAE3B,QACE,QAAO;;;CAGd,CAAC;AC5CF,MAAa,kBAAkB,sBAAsB;CACnD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ,CAAC,aAAa,OAAO;EAC7B,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,KAAK;AACX,SAAO,iBAAiB,OAAO,GAAG,UAAU,EAAE,GAAG;;CAEnD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,mBAAmB,KAAwB;GACpD,KAAK,MACH,QAAO,eAAe,KAAsB;GAC9C,KAAK,SACH,QAAO,eAAe,KAAsB;GAC9C,KAAK,SACH,QAAO,YAAY,KAAK,GAAG;GAE7B,QACE,QAAO;;;CAGd,CAAC;AC7BF,MAAa,sBAAsB,sBAAsB;CACvD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAQ;GAAW;EACzC,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,OAAO;AACb,SAAO,qBAAqB,OAAO,KAAK,UAAU,EAAE,GAAG;;CAEzD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;;;;;;;ACpBF,eAAsB,kBACpB,QACA,MACA,KACqB;AACrB,KAAI,CAAC,KAAK,UAAW,QAAO,YAAY,oCAAoC;AAC5E,KAAI,CAAC,KAAK,QAAS,QAAO,YAAY,kCAAkC;AAGxE,KAAI,CAAC,WAAW,KAAK,UAAU,CAC7B,QAAO,YAAY,uBAAuB,KAAK,UAAU,8BAA8B;AAEzF,KAAI,CAAC,WAAW,KAAK,QAAQ,CAC3B,QAAO,YAAY,qBAAqB,KAAK,QAAQ,8BAA8B;AAErF,KAAI,KAAK,MAAM,CAAC,WAAW,KAAK,GAAG,CACjC,QAAO,YAAY,gBAAgB,KAAK,GAAG,8BAA8B;CAG3E,MAAM,OAAO;EAAE,WAAW,KAAK;EAAW,SAAS,KAAK;EAAS;AAEjE,SAAQ,QAAR;EACE,KAAK,QAAQ;GACX,MAAM,SAAS,MAAM,gBAAgB,MAAM,IAAI,gBAAgB;AAC/D,OAAI,IAAI,QACN,QAAO,WAAW,qBAAqB,OAAO,KAA0B,CAAC;AAE3E,UAAO,WAAW,OAAO,KAAK;;EAGhC,KAAK,UAAU;GACb,MAAM,eAAe,MAAM,kBAAkB,MAAM,IAAI,gBAAgB;AACvE,UAAO,WAAW,mBAAmB,KAAK,SAAS,KAAK,WAAW,aAAa,KAAK,CAAC;;EAGxF,KAAK;AACH,OAAI,KAAK,IAAI;IACX,MAAM,SAAS,MAAM,oBACnB;KAAE,GAAG;KAAM,eAAe,KAAK;KAAI,EACnC,IAAI,gBACL;AACD,WAAO,WAAW,uBAAuB,KAAK,IAAI,OAAO,KAAe,CAAC;;AAG3E,UAAO,WAAW,wBADH,MAAM,oBAAoB,MAAM,IAAI,gBAAgB,EACnB,KAAe,CAAC;EAGlE,KAAK;AACH,OAAI,CAAC,KAAK,QAAS,QAAO,YAAY,kCAAkC;AACxE,SAAM,uBACJ;IAAE,GAAG;IAAM,SAAS,KAAK;IAAmB,EAC5C,IAAI,gBACL;AACD,UAAO,WAAW,8BAA8B,KAAK,SAAS,KAAK,UAAU,CAAC;EAGhF,QACE,QAAO,YACL,mBAAmB,OAAO,8DAC3B;;;ACjFP,MAAa,YAAY,sBAAsB;CAC7C,UAAU;CACV,SAAS,CAAC,OAAO,SAAS;CAC1B,gBAAgB;EACd,KAAK,CAAC,aAAa,UAAU;EAC7B,QAAQ;GAAC;GAAa;GAAW;GAAU;EAC5C;CACD,WAAW;EACT,KAAK;EACL,QAAQ;EACT;CACD,aAAa,SAAS,UAAU;EAC9B,WAAW,KAAK;EAChB,SAAS,KAAK;EACd,SAAS,KAAK;EACf;CACD,eAAe,QAAQ,SAAS;AAC9B,UAAQ,QAAR;GACE,KAAK,MACH,QAAO,UAAU,KAAe;GAClC,KAAK,SACH,QAAO;GAET,QACE,QAAO;;;CAGd,CAAC;ACnBF,MAAa,sBAAsB,sBAAsB;CACvD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAQ;GAAO;EACrC,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,OAAO;AACb,SAAO,qBAAqB,OAAO,KAAK,UAAU,EAAE,GAAG;;CAEzD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;AC5BF,IAAM,gBAA8C;CAClD,SAAS;EACP,aACE;EACF,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,SACE;GACF,SAAS;GACV;EACD,QAAQ;GACN,IAAI;GACJ,MAAM;GACN,UAAU;GACV,QAAQ;GACR,YAAY;GACZ,UAAU;GACV,aAAa;GACd;EACD,UAAU;GACR;IAAE,aAAa;IAAoB,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAQ;IAAE;GACpF;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAO,IAAI;KAAO;IAC1D;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAU,IAAI;KAAO;IAC7D;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAW,IAAI;KAAO;IAC9D;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAW,OAAO;KAAQ;IAClE;GACF;EACF;CAED,OAAO;EACL,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,SACE;GACF,SAAS;GACV;EACD,QAAQ;GACN,IAAI;GACJ,WAAW;GACX,MAAM;GACN,cAAc;GACd,WAAW;GACX,YAAY;GACZ,mBAAmB;GACpB;EACD,UAAU;GACR;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAS,QAAQ;KAAQ,WAAW;KAAO;IAChE;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAS,QAAQ;KAAO,WAAW;KAAO,IAAI;KAAO;IAC1E;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,QAAQ;KACR,cAAc;KACd,WAAW;KACZ;IACF;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAS,QAAQ;KAAW,WAAW;KAAO,IAAI;KAAO;IAC9E;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAS,QAAQ;KAAW,WAAW;KAAO,OAAO;KAAW;IACrF;GACF;EACF;CAED,aAAa;EACX,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,QAAQ;GACR,KAAK;GACL,QAAQ;GACT;EACD,QAAQ;GACN,IAAI;GACJ,WAAW;GACX,SAAS;GACT,QAAQ;GACR,kBAAkB;GAClB,UAAU;GACX;EACD,UAAU;GACR;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAe,QAAQ;KAAU,WAAW;KAAO,SAAS;KAAO;IACxF;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAe,QAAQ;KAAQ,WAAW;KAAO,SAAS;KAAO;IACtF;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,SAAS;KACT,IAAI;KACL;IACF;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,SAAS;KACT,SACE;KACH;IACF;GACF;EACF;CAED,KAAK;EACH,aAAa;EACb,OAAO;EACP,SAAS;GACP,KAAK;GACL,QAAQ;GACT;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAO,QAAQ;IAAO,WAAW;IAAO,SAAS;IAAO;GAC7E,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,SAAS;IACV;GACF,CACF;EACF;CAED,OAAO;EACL,aAAa;EACb,OAAO;EACP,SAAS;GACP,KAAK;GACL,QAAQ;GACT;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAS,QAAQ;IAAO,WAAW;IAAO,SAAS;IAAO;GAC/E,CACF;EACF;CAED,cAAc;EACZ,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,UAAU;GACX;EACD,UAAU;GACR;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAgB,QAAQ;KAAQ,WAAW;KAAO,SAAS;KAAO;IACvF;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,SAAS;KACT,QAAQ;KACR,MAAM;KACP;IACF;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,SAAS;KACT,IAAI;KACL;IACF;GACF;EACF;CAED,WAAW;EACT,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,MAAM;GACN,UAAU;GACX;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAa,QAAQ;IAAQ,WAAW;IAAO;GACpE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,MAAM;IACN,UAAU;IACX;GACF,CACF;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,UAAU;GACV,WAAW;GACZ;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAO;GACzE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,UAAU;IACV,WAAW,CAAC,GAAG,EAAE;IAClB;GACF,CACF;EACF;CAED,SAAS;EACP,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,SAAS;GACV;EACD,QAAQ;GACN,SAAS;GACT,MAAM;GACN,WAAW;GACX,WAAW;GACZ;EACD,UAAU;GACR;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAQ,WAAW;KAAO;IAClE;GACD;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,WAAW;KACX,SAAS;KACT,MAAM;KACP;IACF;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAW,WAAW;KAAO,IAAI;KAAO;IAChF;GACF;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,MAAM;GACN,MAAM;GACN,YAAY;GACb;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAO;GACzE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,MAAM;IACP;GACF,CACF;EACF;CAED,YAAY;EACV,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,KAAK;GACL,UAAU;GACX;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAY,QAAQ;IAAQ,WAAW;IAAO;GACnE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,KAAK;IACN;GACF,CACF;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAO,SAAS;IAAO;GACzF,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,MAAM;IACN,aAAa,CAAC;KAAE,UAAU;KAAS,UAAU;KAAU,CAAC;IACzD;GACF,CACF;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,IAAI;GACJ,MAAM;GACP;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAO,SAAS;IAAO;GACzF,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,MAAM;IACN,IAAI;IACJ,MAAM;IACP;GACF,CACF;EACF;CAED,UAAU;EACR,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,MAAM;GACN,UAAU;GACV,WAAW;GACX,SAAS;GACV;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAY,QAAQ;IAAQ,WAAW;IAAO;GACnE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,UAAU;IACV,WAAW;IACX,SAAS;IACV;GACF,CACF;EACF;CAED,mBAAmB;EACjB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,QAAQ;GACT;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAmB,QAAQ;IAAQ,WAAW;IAAO;GAC1E,EACD;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAmB,QAAQ;IAAO,WAAW;IAAO,IAAI;IAAO;GACpF,CACF;EACF;CAED,SAAS;EACP,aACE;EACF,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,UAAU;GACV,aAAa;GACb,WAAW;GACX,WAAW;GACX,WAAW;GACZ;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAW,QAAQ;IAAQ,WAAW;IAAO;GAClE,EACD;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAW,QAAQ;IAAO,WAAW;IAAO,IAAI;IAAO;GAC5E,CACF;EACF;CAED,UAAU;EACR,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACT;EACD,QAAQ,EACN,SAAS,4BACV;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAY,QAAQ;IAAQ,WAAW;IAAO,SAAS;IAAO;GACnF,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,SAAS;IACV;GACF,CACF;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACT;EACD,QAAQ;GACN,SAAS;GACT,MAAM;GACN,WAAW;GACX,QAAQ;GACR,MAAM;GACN,KAAK;GACL,OAAO;GACP,SAAS;GACV;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAkB,QAAQ;IAAQ,WAAW;IAAO;GACzE,EACD;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,WAAW;IACX,MAAM;IACP;GACF,CACF;EACF;CAED,MAAM;EACJ,aAAa;EACb,OAAO;EACP,SAAS,EACP,KAAK,0EACN;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IAAE,UAAU;IAAQ,QAAQ;IAAO;GAC5C,CACF;EACF;CAED,OAAO;EACL,aACE;EACF,OAAO;EACP,SAAS,EACP,KAAK,2DACN;EACD,QAAQ,EACN,YAAY,gEACb;EACD,UAAU,CACR;GACE,aAAa;GACb,QAAQ;IACN,UAAU;IACV,QAAQ;IACR,YAAY,CACV;KAAE,UAAU;KAAW,QAAQ;KAAQ,EACvC;KAAE,UAAU;KAAS,QAAQ;KAAQ,WAAW;KAAO,CACxD;IACF;GACF,CACF;EACF;CAED,SAAS;EACP,aACE;EACF,OAAO;EACP,SAAS;GACP,MAAM;GACN,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,KAAK;GACN;EACD,QAAQ;GACN,MAAM;GACN,QAAQ;GACR,MAAM;GACN,SAAS;GACV;EACD,UAAU;GACR;IAAE,aAAa;IAAgB,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAQ;IAAE;GAChF;IACE,aAAa;IACb,QAAQ;KACN,UAAU;KACV,QAAQ;KACR,MAAM;KACN,QAAQ;KACT;IACF;GACD;IACE,aAAa;IACb,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAO,IAAI;KAAO,SAAS;MAAC;MAAG;MAAG;MAAE;KAAE;IAC9E;GACF;EACF;CACF;;;;AAKD,SAAgB,WAAW,UAA8B;CACvD,MAAM,OAAO,cAAc;AAE3B,KAAI,CAAC,KACH,QAAO,oBAAoB;AAG7B,QAAO,WAAW;EAAE;EAAU,GAAG;EAAM,CAAC;;;;;AAM1C,SAAgB,qBAAiC;AAQ/C,QAAO,WAAW;EAChB,SAAS;EACT,WATe,OAAO,QAAQ,cAAc,CAAC,KAAK,CAAC,UAAU,WAAW;GACxE;GACA,aAAa,KAAK;GAClB,OAAO,KAAK;GACZ,SAAS,OAAO,KAAK,KAAK,QAAQ;GACnC,EAAE;EAKD,MAAM;EACP,CAAC;;ACrtBJ,MAAa,iBAAiB,sBAAsB;CAClD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAQ;GAAY;GAAa;GAAU;EACjE,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,kBAAkB,KAAuB;GAClD,KAAK,MACH,QAAO,cAAc,KAAqB;GAC5C,KAAK,SACH,QAAO,cAAc,KAAqB;GAC5C,KAAK,SACH,QAAO,WAAW,KAAK,GAAG;GAE5B,QACE,QAAO;;;CAGd,CAAC;AChCF,MAAa,oBAAoB,sBAAsB;CACrD,UAAU;CACV,SAAS,CAAC,OAAO,SAAS;CAC1B,gBAAgB;EACd,KAAK,CAAC,aAAa,UAAU;EAC7B,QAAQ;GAAC;GAAa;GAAW;GAAU;EAC5C;CACD,WAAW;EACT,KAAK;EACL,QAAQ;EACT;CACD,aAAa,SAAS,UAAU;EAC9B,WAAW,KAAK;EAChB,SAAS,KAAK;EACd,SAAS,KAAK;EACf;CACD,eAAe,QAAQ,SAAS;AAC9B,UAAQ,QAAR;GACE,KAAK,MACH,QAAO,kBAAkB,KAAe;GAC1C,KAAK,SACH,QAAO;GAET,QACE,QAAO;;;CAGd,CAAC;AClBF,MAAa,uBAAuB,sBAAsB;CACxD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAS;CACtD,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAQ;GAAU;EACxC,QAAQ,CAAC,aAAa,KAAK;EAC3B,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,QAAQ;EACT;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,WAAW;AACjB,SAAO,sBAAsB,OAAO,SAAS,UAAU,EAAE,GAAG;;CAE9D,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,wBAAwB,KAA6B;GAC9D,KAAK,MACH,QAAO,oBAAoB,KAA2B;GACxD,KAAK,SACH,QAAO,oBAAoB,KAA2B;GACxD,KAAK,SACH,QAAO,oBAAoB,KAA2B;GACxD,KAAK,SACH,QAAO,kBAAkB,KAAK,GAAG;GAEnC,QACE,QAAO;;;CAGd,CAAC;ACtCF,MAAa,gBAAgB,sBAAsB;CACjD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAM;CACnD,gBAAgB;EACd,KAAK,CAAC,KAAK;EACX,QAAQ,CAAC,QAAQ,SAAS;EAC1B,QAAQ,CAAC,KAAK;EACd,KAAK,CAAC,MAAM,UAAU;EACvB;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,KAAK;EACN;CACD,QAAQ,OAAO,OAAO,eAAe,GAAG;CACxC,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,iBAAiB,KAAsB;GAChD,KAAK,MACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,UAAU,KAAK,GAAG;GAC3B,KAAK,OAAO;IACV,MAAM,UAAU,KAAK;IACrB,MAAM,QAAQ,MAAM,QAAQ,QAAQ,GAAG,QAAQ,SAAS;AACxD,WAAO,UAAU,KAAK,GAAG,UAAU,MAAM;;GAG3C,QACE,QAAO;;;CAGd,CAAC;ACvCF,MAAa,sBAAsB,sBAAsB;CACvD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,aAAa,UAAU;EAC9B,KAAK;GAAC;GAAa;GAAW;GAAK;EACnC,QAAQ;GAAC;GAAa;GAAW;GAAQ;GAAK;EAC9C,QAAQ;GAAC;GAAa;GAAW;GAAK;EACvC;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;AC9BF,MAAa,sBAAsB,sBAAsB;CACvD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ,CAAC,aAAa,UAAU;EAChC,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;ACnBF,IAAM,mBAAuD;CAC3D,SAAS;EACP,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAU;GAAW;GAAU;EAC5E,OAAO;EACP,UAAU;GACR,KAAK,CAAC,KAAK;GACX,QAAQ;IAAC;IAAY;IAAQ;IAAU;IAAO;GAC9C,QAAQ,CAAC,KAAK;GACd,QAAQ,CAAC,KAAK;GACd,SAAS,CAAC,KAAK;GACf,SAAS,CAAC,QAAQ;GACnB;EACD,QAAQ;GACN,UAAU;IAAE,UAAU;IAAM,MAAM;IAAuC;GACzE,MAAM;IAAE,UAAU;IAAM,MAAM;IAAmC;GACjE,QAAQ;IAAE,UAAU;IAAM,MAAM;IAA0C;GAC1E,MAAM;IAAE,UAAU;IAAM,MAAM;IAAU;GACxC,eAAe;IAAE,UAAU;IAAO,MAAM;IAAmC;GAC3E,aAAa;IAAE,UAAU;IAAO,MAAM;IAA+B;GACrE,UAAU;IAAE,UAAU;IAAO,MAAM;IAAoC;GACxE;EACF;CAED,OAAO;EACL,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAW;GAAU;EAClE,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAU;IAAe;GAC/C,QAAQ,CAAC,aAAa,KAAK;GAC3B,SAAS,CAAC,aAAa,KAAK;GAC5B,SAAS,CAAC,aAAa,QAAQ;GAChC;EACD,QAAQ;GACN,QAAQ;IAAE,UAAU;IAAM,MAAM;IAA6B;GAC7D,cAAc;IAAE,UAAU;IAAM,MAAM;IAAqC;GAC3E,WAAW;IAAE,UAAU;IAAO,MAAM;IAA+B;GACpE;EACF;CAED,aAAa;EACX,SAAS;GAAC;GAAQ;GAAU;GAAO;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,aAAa,UAAU;GAC9B,QAAQ,CAAC,aAAa,UAAU;GAChC,KAAK;IAAC;IAAa;IAAW;IAAK;GACnC,QAAQ;IAAC;IAAa;IAAW;IAAU;GAC5C;EACF;CAED,KAAK;EACH,SAAS,CAAC,OAAO,SAAS;EAC1B,OAAO;EACP,UAAU;GACR,KAAK,CAAC,aAAa,UAAU;GAC7B,QAAQ;IAAC;IAAa;IAAW;IAAU;GAC5C;EACF;CAED,OAAO;EACL,SAAS,CAAC,OAAO,SAAS;EAC1B,OAAO;EACP,UAAU;GACR,KAAK,CAAC,aAAa,UAAU;GAC7B,QAAQ;IAAC;IAAa;IAAW;IAAU;GAC5C;EACF;CAED,cAAc;EACZ,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAW;EACxD,OAAO;EACP,UAAU;GACR,MAAM,CAAC,aAAa,UAAU;GAC9B,KAAK;IAAC;IAAa;IAAW;IAAK;GACnC,QAAQ;IAAC;IAAa;IAAW;IAAS;GAC1C,QAAQ;IAAC;IAAa;IAAW;IAAK;GACtC,UAAU;IAAC;IAAa;IAAW;IAAK;GACzC;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAO,MAAM;IAAgD;GAC/E,QAAQ;IAAE,UAAU;IAAM,MAAM;IAAU;GAC3C;EACF;CAED,WAAW;EACT,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ,CAAC,aAAa,OAAO;GAC7B,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAA0B;GACxD,MAAM;IAAE,UAAU;IAAO,MAAM;IAAoC;GACnE,UAAU;IAAE,UAAU;IAAO,MAAM;IAA0B;GAC9D;EACF;CAED,kBAAkB;EAChB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAQ;IAAW;GACzC,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAA+B;GAC7D,UAAU;IAAE,UAAU;IAAM,MAAM;IAA0B;GAC5D,WAAW;IAAE,UAAU;IAAO,MAAM;IAA2C;GAChF;EACF;CAED,SAAS;EACP,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAU;EACvD,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ,CAAC,aAAa,UAAU;GAChC,QAAQ,CAAC,aAAa,KAAK;GAC3B,SAAS,CAAC,aAAa,KAAK;GAC7B;EACD,QAAQ;GACN,SAAS;IAAE,UAAU;IAAM,MAAM;IAAwC;GACzE,MAAM;IAAE,UAAU;IAAO,MAAM;IAA2B;GAC1D,WAAW;IAAE,UAAU;IAAO,MAAM;IAA8B;GAClE,WAAW;IAAE,UAAU;IAAO,MAAM;IAAuB;GAC5D;EACF;CAED,kBAAkB;EAChB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAQ;IAAO;GACrC,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAU;GACxC,MAAM;IAAE,UAAU;IAAM,MAAM;IAA2C;GACzE,MAAM;IAAE,UAAU;IAAO,MAAM;IAAoC;GACnE,YAAY;IAAE,UAAU;IAAO,MAAM;IAA2B;GACjE;EACF;CAED,YAAY;EACV,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAQ;IAAM;GACpC,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAsB;GACpD,KAAK;IAAE,UAAU;IAAM,MAAM;IAA+B;GAC5D,UAAU;IAAE,UAAU;IAAO,MAAM;IAA+B;GACnE;EACF;CAED,kBAAkB;EAChB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,aAAa,UAAU;GAC9B,KAAK;IAAC;IAAa;IAAW;IAAK;GACnC,QAAQ;IAAC;IAAa;IAAW;IAAQ;IAAc;GACvD,QAAQ;IAAC;IAAa;IAAW;IAAK;GACvC;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAsB;GACpD,MAAM;IAAE,UAAU;IAAO,MAAM;IAAwC;GACvE,aAAa;IAAE,UAAU;IAAM,MAAM;IAAkC;GACxE;EACF;CAED,kBAAkB;EAChB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,aAAa,UAAU;GAC9B,KAAK;IAAC;IAAa;IAAW;IAAK;GACnC,QAAQ;IAAC;IAAa;IAAW;IAAQ;IAAK;GAC9C,QAAQ;IAAC;IAAa;IAAW;IAAK;GACvC;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAwB;GACtD,IAAI;IAAE,UAAU;IAAM,MAAM;IAA4B;GACxD,MAAM;IAAE,UAAU;IAAO,MAAM;IAA8C;GAC9E;EACF;CAED,UAAU;EACR,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAQ;IAAY;IAAa;IAAU;GACjE,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAoC;GAClE,UAAU;IAAE,UAAU;IAAM,MAAM;IAAqB;GACvD,WAAW;IAAE,UAAU;IAAM,MAAM;IAAoB;GACvD,SAAS;IAAE,UAAU;IAAM,MAAM;IAAsC;GACxE;EACF;CAED,mBAAmB;EACjB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAS;EACtD,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAQ;IAAU;GACxC,QAAQ,CAAC,aAAa,KAAK;GAC3B,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAA0B;GACxD,SAAS;IAAE,UAAU;IAAM,MAAM;IAAyC;GAC3E;EACF;CAED,SAAS;EACP,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ;IAAC;IAAa;IAAY;IAAe;IAAa;IAAY;GAC1E,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,UAAU;IAAE,UAAU;IAAM,MAAM;IAA+B;GACjE,aAAa;IAAE,UAAU;IAAM,MAAM;IAAqD;GAC1F,WAAW;IAAE,UAAU;IAAM,MAAM;IAAkC;GACrE,WAAW;IAAE,UAAU;IAAM,MAAM;IAAmC;GACtE,WAAW;IAAE,UAAU;IAAO,MAAM;IAA6B;GACjE,OAAO;IAAE,UAAU;IAAO,MAAM;IAA+B;GAC/D,WAAW;IAAE,UAAU;IAAO,MAAM;IAA2C;GAChF;EACF;CAED,UAAU;EACR,SAAS;GAAC;GAAQ;GAAO;GAAS;EAClC,OAAO;EACP,UAAU;GACR,MAAM,CAAC,aAAa,UAAU;GAC9B,KAAK;IAAC;IAAa;IAAW;IAAK;GACnC,QAAQ;IAAC;IAAa;IAAW;IAAU;GAC5C;EACD,QAAQ,EACN,SAAS;GAAE,UAAU;GAAM,MAAM;GAAqC,EACvE;EACF;CAED,kBAAkB;EAChB,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAS;EAC5C,OAAO;EACP,UAAU;GACR,MAAM,CAAC,YAAY;GACnB,KAAK,CAAC,aAAa,KAAK;GACxB,QAAQ,CAAC,aAAa,UAAU;GAChC,QAAQ,CAAC,aAAa,KAAK;GAC5B;EACD,QAAQ;GACN,SAAS;IAAE,UAAU;IAAM,MAAM;IAAgC;GACjE,MAAM;IAAE,UAAU;IAAO,MAAM;IAA4C;GAC3E,WAAW;IACT,UAAU;IACV,MAAM;IACP;GACD,QAAQ;IAAE,UAAU;IAAO,MAAM;IAAiD;GAClF,MAAM;IAAE,UAAU;IAAO,MAAM;IAA4B;GAC3D,KAAK;IAAE,UAAU;IAAO,MAAM;IAA2B;GACzD,OAAO;IAAE,UAAU;IAAO,MAAM;IAA6B;GAC7D,SAAS;IAAE,UAAU;IAAO,MAAM;IAA+B;GAClE;EACF;CAED,MAAM;EACJ,SAAS,CAAC,MAAM;EAChB,OAAO;EACP,UAAU,EAAE;EACb;CAED,OAAO;EACL,SAAS,CAAC,MAAM;EAChB,OAAO;EACP,UAAU,EACR,KAAK,CAAC,aAAa,EACpB;EACF;CAED,SAAS;EACP,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;GAAM;EACnD,OAAO;EACP,UAAU;GACR,KAAK,CAAC,KAAK;GACX,QAAQ,CAAC,QAAQ,SAAS;GAC1B,QAAQ,CAAC,KAAK;GACd,KAAK,CAAC,MAAM,UAAU;GACvB;EACD,QAAQ;GACN,MAAM;IAAE,UAAU;IAAM,MAAM;IAAwB;GACtD,QAAQ;IAAE,UAAU;IAAM,MAAM;IAAgC;GAChE,MAAM;IAAE,UAAU;IAAO,MAAM;IAA2C;GAC3E;EACF;CACF;;;;AAKD,SAAgB,aAAa,UAA8B;CACzD,MAAM,SAAS,iBAAiB;AAEhC,KAAI,CAAC,OACH,QAAO,WAAW;EAChB,OAAO,qBAAqB;EAC5B,qBAAqB,OAAO,KAAK,iBAAiB;EACnD,CAAC;AAGJ,QAAO,WAAW;EAAE;EAAU,GAAG;EAAQ,CAAC;;;;;AAM5C,SAAgB,uBAAmC;AAOjD,QAAO,WAAW;EAChB,MAAM;EACN,WARe,OAAO,QAAQ,iBAAiB,CAAC,KAAK,CAAC,UAAU,aAAa;GAC7E;GACA,SAAS,OAAO;GAChB,OAAO,OAAO;GACf,EAAE;EAKF,CAAC;;AC1WJ,MAAa,sBAAsB,sBAAsB;CACvD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,aAAa,UAAU;EAC9B,KAAK;GAAC;GAAa;GAAW;GAAK;EACnC,QAAQ;GAAC;GAAa;GAAW;GAAQ;GAAc;EACvD,QAAQ;GAAC;GAAa;GAAW;GAAK;EACvC;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,uBAAuB,KAA4B;GAC5D,KAAK,MACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,mBAAmB,KAA0B;GACtD,KAAK,SACH,QAAO,iBAAiB,KAAK,GAAG;GAElC,QACE,QAAO;;;CAGd,CAAC;;;;;;ACnBF,eAAsB,oBACpB,MACA,KACqB;CACrB,MAAM,WAAW,KAAK;AACtB,KAAI,CAAC,SAAU,QAAO,YAAY,6BAA6B;CAE/D,MAAM,UAAU,IAAI;CAEpB,MAAM,CAAC,QAAQ,OAAO,WAAW,SAAS,SAAS,eAAe,iBAChE,MAAM,QAAQ,IAAI;EAChB,UAAU,EAAE,WAAW,UAAU,EAAE,QAAQ;EAC3C,UAAU,EAAE,WAAW,UAAU,EAAE,QAAQ;EAC3C,cAAc,EAAE,WAAW,UAAU,EAAE,QAAQ;EAC/C,kBAAkB,EAAE,WAAW,UAAU,EAAE,QAAQ;EACnD,YAAY,EAAE,WAAW,UAAU,EAAE,QAAQ;EAC7C,kBAAkB,EAAE,WAAW,UAAU,EAAE,QAAQ;EACnD,kBAAkB,EAAE,WAAW,UAAU,EAAE,QAAQ;EACpD,CAAC;AAEJ,QAAO,WAAW;EAChB,QAAQ,OAAO;EACf,OAAO,MAAM;EACb,WAAW,UAAU;EACrB,gBAAgB,QAAQ;EACxB,SAAS,QAAQ;EACjB,gBAAgB,cAAc;EAC9B,gBAAgB,cAAc;EAC/B,CAAC;;;;;;;AAQJ,eAAsB,kBACpB,MACA,KACqB;CACrB,MAAM,WAAW,KAAK;CACtB,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,SAAU,QAAO,YAAY,oCAAoC;AACtE,KAAI,CAAC,OAAQ,QAAO,YAAY,6BAA6B;CAE7D,MAAM,UAAU,IAAI;CAEpB,MAAM,CAAC,MAAM,aAAa,cAAc,eAAe,iBAAiB,MAAM,QAAQ,IAAI;EACxF,QAAQ;GAAE,WAAW;GAAU,SAAS;GAAQ,EAAE,QAAQ;EAC1D,gBAAgB;GAAE,WAAW;GAAU,SAAS;GAAQ,EAAE,QAAQ;EAClE,iBAAiB;GAAE,WAAW;GAAU,SAAS;GAAQ,EAAE,QAAQ;EACnE,kBAAkB;GAAE,WAAW;GAAU,SAAS;GAAQ,EAAE,QAAQ;EACpE,kBAAkB;GAAE,WAAW;GAAU,SAAS;GAAQ,EAAE,QAAQ;EACrE,CAAC;CAEF,MAAM,oBAAoB,MAAM,QAAQ,YAAY,KAAK,GACrD,YAAY,KAAK,MAAM,GAAG,EAAE,GAC5B,YAAY;AAEhB,QAAO,WAAW;EAChB,MAAM,KAAK;EACX,aAAa;EACb,cAAc,aAAa;EAC3B,gBAAgB,cAAc;EAC9B,gBAAgB,cAAc;EAC/B,CAAC;;ACtEJ,IAAM,iBAAiB,sBAAsB;CAC3C,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAU;EAAU;CACjE,gBAAgB;EACd,KAAK,CAAC,KAAK;EACX,QAAQ;GAAC;GAAY;GAAQ;GAAQ;GAAS;EAC9C,QAAQ,CAAC,KAAK;EACd,QAAQ,CAAC,KAAK;EACd,SAAS,CAAC,QAAQ;EACnB;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,SAAS;EACV;CACD,QAAQ,OAAO,OAAO,eAAe,GAAG;CACxC,aAAa,QAAQ,SAAS;AAC5B,UAAQ,QAAR;GACE,KAAK;GACL,KAAK;GACL,KAAK,SACH,QAAO,EAAE,WAAW,KAAK,IAAI;GAC/B,KAAK,SACH,QAAO;IACL,UAAU,KAAK;IAEf,eAAe,OAAO,KAAK,cAAc,IAAI;IAC7C,MAAM,KAAK;IAEX,MAAM,KAAK,QAAQ;IAEnB,MAAM,KAAK,QAAQ;IACnB,QAAQ,KAAK;IACd;GACH,KAAK,UACH,QAAO,EAAE,OAAO,KAAK,OAAO;GAC9B,QACE,QAAO,EAAE;;;CAGf,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,iBAAiB,KAAsB;GAChD,KAAK,MACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,UAAU,KAAK,GAAG;GAC3B,KAAK,SACH,QAAO,UAAU,KAAK,GAAG;GAC3B,KAAK,WAAW;IACd,MAAM,SAAS;AACf,QAAI,OAAO,UAAU,EAAG,QAAO,wBAAwB,OAAO,MAAM;IACpE,MAAM,QAAQ,OAAO,QAAQ,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,GAAG;AACpE,WAAO,GAAG,OAAO,MAAM,uBAAuB,OAAO,MAAM,MAAM,MAAM,KAAK,KAAK;;GAGnF,QACE,QAAO;;;CAGd,CAAC;;;;;AAMF,eAAsB,cACpB,QACA,MACA,KACqB;AACrB,KAAI,WAAW,UACb,QAAO,oBAAoB,MAAM,IAAI;AAEvC,QAAO,eAAe,QAAQ,MAAM,IAAI;;ACvF1C,IAAM,eAAe,sBAAsB;CACzC,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;EAAU;CACvD,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ,CAAC,aAAa,SAAS;EAC/B,QAAQ,CAAC,aAAa,KAAK;EAC3B,SAAS,CAAC,aAAa,QAAQ;EAChC;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,SAAS;EACV;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,OAAO;AACb,SAAO,aAAa,OAAO,KAAK,UAAU,EAAE,GAAG;;CAEjD,aAAa,QAAQ,SAAS;AAC5B,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,EAAE,WAAW,KAAK,WAAW;GACtC,KAAK,MACH,QAAO;IAAE,WAAW,KAAK;IAAW,SAAS,KAAK;IAAI;GACxD,KAAK,SACH,QAAO;IACL,WAAW,KAAK;IAChB,QAAQ,KAAK;IACb,cAAc,KAAK,gBAAgB;IACnC,WAAW,KAAK;IACjB;GACH,KAAK,SACH,QAAO;IAAE,WAAW,KAAK;IAAW,SAAS,KAAK;IAAI;GACxD,KAAK,UACH,QAAO;IAAE,WAAW,KAAK;IAAW,OAAO,KAAK;IAAO;GAEzD,QACE,QAAO,EAAE;;;CAGf,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,eAAe,MAAqB,KAAK,UAAgC;GAClF,KAAK,MACH,QAAO,WAAW,KAAkB;GACtC,KAAK,SACH,QAAO,WAAW,KAAkB;GACtC,KAAK,SACH,QAAO,QAAQ,KAAK,GAAG,uBAAuB,KAAK,UAAU;GAC/D,KAAK,WAAW;IACd,MAAM,SAAS;AACf,QAAI,OAAO,UAAU,EACnB,QAAO,sBAAsB,OAAO,MAAM,cAAc,KAAK,UAAU;IACzE,MAAM,QAAQ,OAAO,QAAQ,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,GAAG,GAAG;AACpE,WAAO,GAAG,OAAO,MAAM,qBAAqB,OAAO,MAAM,cAAc,KAAK,UAAU,KAAK,MAAM,KAAK,KAAK;;GAG7G,QACE,QAAO;;;CAGd,CAAC;;;;;AAMF,eAAsB,YACpB,QACA,MACA,KACqB;AACrB,KAAI,WAAW,UACb,QAAO,kBAAkB,MAAM,IAAI;AAErC,QAAO,aAAa,QAAQ,MAAM,IAAI;;AClFxC,MAAa,gBAAgB,sBAAsB;CACjD,UAAU;CACV,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAS;CAC5C,gBAAgB;EACd,MAAM,CAAC,YAAY;EACnB,KAAK,CAAC,aAAa,KAAK;EACxB,QAAQ;GAAC;GAAa;GAAQ;GAAM;EACpC,QAAQ,CAAC,aAAa,KAAK;EAC5B;CACD,WAAW;EACT,MAAM;EACN,KAAK;EACL,QAAQ;EACR,QAAQ;EACT;CACD,QAAQ,MAAM,OAAO;EACnB,MAAM,MAAM;AACZ,SAAO,eAAe,OAAO,IAAI,UAAU,EAAE,GAAG;;CAElD,eAAe,QAAQ,MAAM,SAAS;AACpC,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,iBAAiB,KAAsB;GAChD,KAAK,MACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,aAAa,KAAoB;GAC1C,KAAK,SACH,QAAO,WAAW,KAAK,GAAG;GAE5B,QACE,QAAO;;;CAGd,CAAC;ACnCF,MAAa,aAAa,sBAAsB;CAC9C,UAAU;CACV,SAAS,CAAC,MAAM;CAChB,WAAW,EACT,KAAK,SACN;CACD,eAAe,SAAS,SAAS;AAC/B,SAAO,WAAW,KAAkB;;CAEvC,CAAC;;;;ACPF,SAAS,YAAY,OAAwB;AAC3C,QAAO,QAAQ,KAAK,MAAM;;;;;;;;;;AAiB5B,eAAsB,eACpB,MACA,iBAC4B;AAE5B,KAAI,KAAK,WAAW,UAClB,QAAO;EAAE,IAAI;EAAM;EAAM;CAG3B,MAAM,WAAW,EAAE,GAAG,MAAM;AAG5B,KAAI,SAAS,aAAa,CAAC,YAAY,SAAS,UAAU,EAAE;EAE1D,MAAM,EAAE,SAAS,WADF,MAAM,eAAe,EAAE,OAAO,SAAS,WAAW,EAAE,gBAAgB,EACjD;AAElC,MAAI,UAAU,EACZ,QAAO;GACL,IAAI;GACJ,OAAO,YACL,uBAAuB,SAAS,UAAU,2DAA2D,SAAS,UAAU,gBACzH;GACF;AAKH,MAAI,EADe,QAAQ,WAAW,KAAK,UAAU,MAClC,QAAQ,GAAG;GAC5B,MAAM,YAAY,QAAQ,KAAK,MAAM,OAAO,EAAE,KAAK,QAAQ,EAAE,GAAG,GAAG,CAAC,KAAK,KAAK;AAC9E,UAAO;IACL,IAAI;IACJ,OAAO,YACL,0BAA0B,SAAS,UAAU,MAAM,MAAM,mBAAmB,UAAU,sDACvF;IACF;;AAGH,WAAS,YAAY,OAAO,QAAQ,GAAI,GAAG;;AAI7C,KAAI,SAAS,WAAW,CAAC,YAAY,SAAS,QAAQ,EAAE;AACtD,MAAI,CAAC,SAAS,UACZ,QAAO;GACL,IAAI;GACJ,OAAO,YACL,yEACD;GACF;EAOH,MAAM,EAAE,SAAS,WAJF,MAAM,aACnB;GAAE,WAAW,SAAS;GAAW,OAAO,SAAS;GAAS,EAC1D,gBACD,EACiC;AAElC,MAAI,UAAU,EACZ,QAAO;GACL,IAAI;GACJ,OAAO,YACL,qBAAqB,SAAS,QAAQ,cAAc,SAAS,UAAU,4DAA4D,SAAS,UAAU,aAAa,SAAS,QAAQ,gBACrL;GACF;AAGH,MAAI,QAAQ,GAAG;GACb,MAAM,YAAY,QAAQ,KAAK,MAAM,OAAO,EAAE,KAAK,QAAQ,EAAE,GAAG,GAAG,CAAC,KAAK,KAAK;AAC9E,UAAO;IACL,IAAI;IACJ,OAAO,YACL,wBAAwB,SAAS,QAAQ,MAAM,MAAM,mBAAmB,UAAU,sDACnF;IACF;;AAGH,WAAS,UAAU,OAAO,QAAQ,GAAI,GAAG;;AAG3C,QAAO;EAAE,IAAI;EAAM,MAAM;EAAU;;;ACzDrC,IAAM,kBAAkB,CAAC,GAAG,UAAU;AAGtC,IAAI,eAAmC;AACvC,SAAS,iBAA8B;AACrC,KAAI,CAAC,aAAc,gBAAe,kBAAkB,MAAM;AAC1D,QAAO;;;;;AAMT,SAAS,eACP,UACA,QACA,MACA,KACqB;AACrB,SAAQ,UAAR;EACE,KAAK,UACH,QAAO,cAAc,QAAQ,MAAM,IAAI;EACzC,KAAK,QACH,QAAO,YAAY,QAAQ,MAAM,IAAI;EACvC,KAAK,cACH,QAAO,kBAAkB,QAAQ,MAAM,IAAI;EAC7C,KAAK,MACH,QAAO,UAAU,QAAQ,MAAM,IAAI;EACrC,KAAK,QACH,QAAO,kBAAkB,QAAQ,MAAM,IAAI;EAC7C,KAAK,eACH,QAAO,mBAAmB,QAAQ,MAAM,IAAI;EAC9C,KAAK,YACH,QAAO,gBAAgB,QAAQ,MAAM,IAAI;EAC3C,KAAK,iBACH,QAAO,oBAAoB,QAAQ,MAAM,IAAI;EAC/C,KAAK,UACH,QAAO,cAAc,QAAQ,MAAM,IAAI;EACzC,KAAK,iBACH,QAAO,oBAAoB,QAAQ,MAAM,IAAI;EAC/C,KAAK,WACH,QAAO,cAAc,QAAQ,MAAM,IAAI;EACzC,KAAK,iBACH,QAAO,oBAAoB,QAAQ,MAAM,IAAI;EAC/C,KAAK,iBACH,QAAO,oBAAoB,QAAQ,MAAM,IAAI;EAC/C,KAAK,WACH,QAAO,eAAe,QAAQ,MAAM,IAAI;EAC1C,KAAK,kBACH,QAAO,qBAAqB,QAAQ,MAAM,IAAI;EAChD,KAAK,UACH,QAAO,cAAc,QAAQ,MAAM,IAAI;EACzC,KAAK,UACH,QAAO,cAAc,QAAQ,MAAM,IAAI;EACzC,KAAK,WACH,QAAO,eAAe,QAAQ,MAAM,IAAI;EAC1C,KAAK,iBACH,QAAO,oBAAoB,QAAQ,MAAM,IAAI;EAC/C,KAAK,OACH,QAAO,WAAW,QAAQ,MAAM,IAAI;EACtC,KAAK,QACH,QAAO,YAAY,QAAQ,MAAM,KAAK,eAAe;EAEvD,QACE,QAAO,QAAQ,QACb,YACE,qBAAqB,SAAS,sBAAsB,gBAAgB,KAAK,KAAK,CAAC,wCAChF,CACF;;;;;;;;;AAUP,eAAsB,2BACpB,MACA,MACA,aACqB;CACrB,MAAM,EAAE,UAAU,QAAQ,SAAS,GAAG,SAAS;AAE/C,KAAI,CAAC,YAAY,CAAC,OAChB,QAAO,YAAY,wDAAoD;AAKzE,KAAI,aAAa,SAAS;AAExB,MAAI,SAAS,QACX,QAAO,YACL,qGACD;EAKH,MAAM,iBAAiC;GACrC,iBAFuC,EAAE,QAD5B,IAAI,WAAW,EAAE,OAAO,YAAY,UAAU,CAAC,EACX;GAGjD,SAAS,WAAW;GACrB;AACD,SAAO,eACL,UACA,QACA;GAAE;GAAU;GAAQ,GAAG;GAAM,EAC7B,eACD;;AAIH,KAAI,SAAS,WAAW,cAAc,OAAO,CAC3C,QAAO,YACL,WAAW,OAAO,6DACnB;AAGH,KAAI,SAAS,iBAAiB,aAAa,OAAO,CAChD,QAAO,YAAY,WAAW,OAAO,sDAAsD;AAI7F,KAAI,WAAW;;AAEb,QAAO,WAAW,WAAW,SAAS,GAAG,oBAAoB;AAK/D,KAAI,WAAW;;AAEb,QAAO,WAAW,aAAa,SAAS,GAAG,sBAAsB;AAKnE,KAAI,CAAC,gBAAgB,SAAS,SAA6C,CACzE,QAAO,YACL,qBAAqB,SAAS,sBAAsB,gBAAgB,KAAK,KAAK,CAAC,wCAChF;CAKH,MAAM,kBAAmC,EAAE,QAD5B,IAAI,WAAW,EAAE,OAAO,YAAY,UAAU,CAAC,EACX;CACnD,MAAM,iBAAiC;EACrC;EACA,SAAS,WAAW,WAAW;EAC/B,cAAc,WAAW;EAC1B;CAID,MAAM,gBAAgB,MAAM,eADZ;EAAE;EAAU;EAAQ,GAAG;EAAM,EACO,gBAAgB;AACpE,KAAI,CAAC,cAAc,GACjB,QAAO,cAAc;CAEvB,MAAM,eAAe,cAAc;AAGnC,KAAI;EACF,MAAM,SAAS,MAAM,eAAe,UAAU,QAAQ,cAAc,eAAe;AACnF,MAAI,SAAS,cACX,iBAAgB,CAAC,IAAI;GACnB,QAAQ;GACR;GACA;GACA,MAAM;GACN,QAAQ,OAAO,UAAU,UAAU;GACpC,CAAC;AAEJ,SAAO;UACA,OAAO;EACd,IAAI;AACJ,MAAI,iBAAiB,MAAM,CACzB,gBAAe,MAAM,oBAAoB;WAChC,gBAAgB,MAAM,CAC/B,gBAAe,oBAAoB,MAAM,OAAO,KAAK,MAAM;;;AAG3D,iBAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAGvE,MAAI,SAAS,cACX,iBAAgB,CAAC,IAAI;GACnB,QAAQ;GACR;GACA;GACA,MAAM;GACN,QAAQ;GACR,OAAO;GACR,CAAC;AAEJ,SAAO,YAAY,aAAa;;;AClPpC,MAAa,UAAA"}