@stackwright-pro/mcp 0.1.1 ā 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +642 -48
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +642 -55
- package/dist/server.mjs.map +1 -1
- package/package.json +17 -12
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: '0.1.0',\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n specPath,\n projectRoot,\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`š¦ Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`š¦ ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\nš” Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n excludePatterns,\n projectRoot: projectRoot || process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['š Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\nā ļø Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n let allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1].trim(),\n url: match[2].trim(),\n sha256: match[3].trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const crypto = require('crypto');\n const sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n const crypto = require('crypto');\n sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1].trim(),\n url: match[2].trim(),\n sha256: match[3].trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`š Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`š¦ ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = 'ā” Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = 'š Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = 'š¾ Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n 'šļø Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `āļø ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? 'ā³ Show loading until cached' : fallback === 'true' ? 'š Generate on demand' : 'ā 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`āļø Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = 'š¾';\n if (rev < 60) freshness = 'ā”';\n else if (rev < 300) freshness = 'š';\n else if (rev >= 3600) freshness = 'šļø';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with collection_listing, data_table, or stats_grid content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add stats grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - stats_grid:`);\n yamlLines.push(` label: \"${slug}-stats\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(\n ` text: \"${slug.charAt(0).toUpperCase() + slug.slice(1)} Overview\"`\n );\n yamlLines.push(` textSize: \"h2\"`);\n yamlLines.push(` stats:`);\n yamlLines.push(` - label: \"Total\"`);\n yamlLines.push(` value: \"{{ ${slug}.count }}\"`);\n yamlLines.push(` icon: \"Database\"`);\n yamlLines.push(` source: \"${slug}\"`);\n yamlLines.push(` background: \"surface\"`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - collection_listing:`);\n yamlLines.push(` label: \"${entities[0]}-listing\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(\n ` text: \"${entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ')}\"`\n );\n yamlLines.push(` textSize: \"h2\"`);\n yamlLines.push(` collection: \"${entities[0]}\"`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['\"id\"', '\"name\"', '\"status\"', '\"created_at\"'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => `\"${f.name}\"`)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push(` background: \"background\"`);\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - data_table:`);\n yamlLines.push(` label: \"${entities[0]}-table\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"Detailed View\"`);\n yamlLines.push(` textSize: \"h3\"`);\n yamlLines.push(` collection: \"${entities[0]}\"`);\n yamlLines.push(` sortableColumns: true`);\n yamlLines.push(` exportable: true`);\n yamlLines.push(` background: \"surface\"`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name.replace(/_/g, ' ').replace(/\\b\\w/g, (l) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n"],"mappings":"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","names":["server","path","import_zod","server","path","fs","import_zod","server","import_zod","import_cli_data_explorer","server"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts","../package.json"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport packageJson from '../package.json';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict, stackwright_pro_get_defaults\nregisterPackageTools(server); // stackwright_pro_setup_packages\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`š¦ Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`š¦ ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\nš” Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['š Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\nā ļø Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createHash } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const sha256 = createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n sha256 = createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`š Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`š¦ ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = 'ā” Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = 'š Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = 'š¾ Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n 'šļø Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `āļø ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? 'ā³ Show loading until cached' : fallback === 'true' ? 'š Generate on demand' : 'ā 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`āļø Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = 'š¾';\n if (rev < 60) freshness = 'ā”';\n else if (rev < 300) freshness = 'š';\n else if (rev >= 3600) freshness = 'šļø';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * This bridges to the Python Clarification Protocol server which\n * handles:\n * - Channel routing (TUI, CLI args, config, defaults)\n * - Conflict detection\n * - Stubborn user escalation\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { spawn, ChildProcess } from 'child_process';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { existsSync, unlinkSync } from 'fs';\n\n// Types matching Python server\nexport interface ClarificationRequest {\n context?: string;\n question_type: 'closed_choice' | 'open_text' | 'conditional' | 'multi_step' | 'reconciliation';\n question: string;\n choices?: string[];\n priority?: 'blocking' | 'preferred' | 'optional';\n target_field?: string;\n}\n\nexport interface ClarificationResponse {\n request_id: string;\n decision: {\n value: unknown;\n explicit: boolean;\n source: string;\n };\n fallback_used: boolean;\n fallback_reason?: string;\n}\n\n// Track active Python server processes\nconst activeServers: Map<string, ChildProcess> = new Map();\n\n/**\n * Start the Python Clarification Protocol server\n */\nasync function startPythonServer(sessionId: string): Promise<{ port: number; socketPath: string }> {\n const socketPath = join(tmpdir(), `otter-raft-${randomUUID()}.sock`);\n const port = 8765 + Math.floor(Math.random() * 100); // Random port to avoid conflicts\n\n return new Promise((resolve, reject) => {\n const pythonPath = process.platform === 'win32' ? 'python' : 'python3';\n\n // Find Python package\n const packageRoot = findPythonPackageRoot();\n\n const proc = spawn(\n pythonPath,\n ['-m', 'stackwright_pro.raft.server', '--socket', socketPath, '--port', String(port)],\n {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONPATH: packageRoot,\n },\n }\n );\n\n // Register process for cleanup\n activeServers.set(sessionId, proc);\n\n let startupOutput = '';\n let started = false;\n\n proc.stdout?.on('data', (data: Buffer) => {\n startupOutput += data.toString();\n if (startupOutput.includes('Server ready') || startupOutput.includes('HTTP server')) {\n started = true;\n resolve({ port, socketPath });\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n // Only log errors, not startup messages\n if (!startupOutput.includes('Starting')) {\n console.error('[Python Clarification]', data.toString().trim());\n }\n });\n\n proc.on('error', (err) => {\n if (!started) {\n activeServers.delete(sessionId);\n reject(new Error(`Failed to start Python server: ${err.message}`));\n }\n });\n\n proc.on('exit', (code) => {\n activeServers.delete(sessionId);\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (!started) {\n proc.kill();\n activeServers.delete(sessionId);\n reject(new Error('Python server startup timeout'));\n }\n }, 10000);\n });\n}\n\n/**\n * Stop the Python server for a session\n */\nasync function stopPythonServer(sessionId: string): Promise<void> {\n const proc = activeServers.get(sessionId);\n if (proc) {\n proc.kill('SIGTERM');\n activeServers.delete(sessionId);\n }\n}\n\n/**\n * Make HTTP request to Python server\n */\nasync function httpRequest<T>(\n host: string,\n port: number,\n path: string,\n body?: unknown\n): Promise<T> {\n const http = await import('http');\n\n return new Promise((resolve, reject) => {\n const url = new URL(path, `http://${host}:${port}`);\n\n const reqOptions = {\n hostname: host,\n port: port,\n path: url.pathname,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n\n const req = http.request(reqOptions, (res) => {\n let data = '';\n\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString();\n });\n\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(parsed.detail || parsed.error || `HTTP ${res.statusCode}`));\n } else {\n resolve(parsed);\n }\n } catch (e) {\n reject(new Error(`Failed to parse response: ${data}`));\n }\n });\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n\n req.end();\n });\n}\n\n/**\n * Find Python package root\n */\nfunction findPythonPackageRoot(): string {\n const candidates = [\n join(__dirname, '../../python/src'),\n join(__dirname, '../../../python/src'),\n join(process.cwd(), 'python/src'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return process.cwd();\n}\n\n/**\n * Register clarification MCP tools\n */\nexport function registerClarificationTools(server: McpServer): void {\n // Tool: Ask for clarification (creates session)\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when an otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, not upfront question collection. ' +\n 'Use this when the otter needs user input to proceed. ' +\n \"Returns the user's decision which should be used to continue execution.\",\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text', 'conditional', 'multi_step', 'reconciliation'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Options for closed_choice or multi_step questions'),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority = 'preferred', target_field }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Create session\n await httpRequest(port === 8765 ? '127.0.0.1' : '127.0.0.1', port, '/sessions', {});\n\n // Set context if provided\n if (context) {\n await httpRequest(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n `/sessions/${sessionId}/context`,\n { context: { purpose: context } }\n );\n }\n\n // Ask for clarification\n const request: ClarificationRequest = {\n ...(context !== undefined && { context }),\n question_type,\n question,\n ...(choices !== undefined && { choices }),\n priority,\n ...(target_field !== undefined && { target_field }),\n };\n\n const response = await httpRequest<ClarificationResponse>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/clarify',\n { request }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n // Format response for LLM\n const decision = response.decision;\n const value = decision.value;\n const source = decision.source;\n const explicit = decision.explicit ? 'explicitly' : 'via fallback';\n\n if (response.fallback_used) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā ļø Clarification fallback used: ${response.fallback_reason || 'No user input available'}\\n\\n` +\n `Default value used: ${JSON.stringify(value)}\\n\\n` +\n `š” Consider following up with the user later if this default isn't appropriate.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā
User clarified (${source}): ${JSON.stringify(value)}\\n\\n` +\n `Use this value to continue execution.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n // If server not available, try stdio mode as fallback\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā Clarification failed: ${error instanceof Error ? error.message : 'Unknown error'}\\n\\n` +\n `Cannot proceed without user input. Consider:\\n` +\n `1. Using a reasonable default\\n` +\n `2. Asking the user directly in your response\\n` +\n `3. Skipping this step if optional`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Detect preference conflict\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Use this to identify when users might be indecisive or misunderstood a question. ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: z.record(z.string(), z.string()).describe('What the user actually selected'),\n },\n async ({ stated_preference, selected_values }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Check for conflict\n const response = await httpRequest<{ conflict: boolean; data?: any }>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/conflict',\n { stated_preference, selected_values }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n if (response.conflict) {\n const data = response.data;\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā ļø CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `Conflict: ${data.description}\\n\\n` +\n `Resolution options: ${data.options?.join(', ') || 'Ask user to clarify'}\\n\\n` +\n `š” Consider asking the user to reconcile this conflict.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
No conflict detected between stated preference and selections.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Conflict detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Get clarification defaults\n server.tool(\n 'stackwright_pro_get_defaults',\n 'Get the current clarification defaults from config. ' +\n \"Use this to understand what fallback values will be used if user doesn't provide input.\",\n {\n config_path: z\n .string()\n .optional()\n .describe('Path to config file. Default: .stackwright/clarification.yaml'),\n },\n async ({ config_path }) => {\n // This reads from the Python config module directly\n // For now, return a message pointing to where config is stored\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `š Clarification defaults\\n\\n` +\n `Configuration is loaded from:\\n` +\n `- Environment: CLARIFICATION_* variables\\n` +\n `- Config file: ${config_path || '.stackwright/clarification.yaml'}\\n` +\n `- CLI args: --clarify-* flags\\n\\n` +\n `Default behaviors:\\n` +\n `- allow_dont_know: true (users can skip)\\n` +\n `- default_timeout: 120 seconds\\n` +\n `- channel_priority: [tui, cli_args, config, defaults]\\n\\n` +\n `š” Set CLARIFICATION_DEFAULT_<FIELD>=value to change defaults.`,\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run ā enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n \"Ensures pro packages are present in a project's package.json. \" +\n 'Safe to call multiple times ā never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: z\n .record(z.string(), z.string())\n .describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }'\n ),\n devPackages: z\n .record(z.string(), z.string())\n .optional()\n .describe('devDependencies to add. Same format as packages.'),\n scripts: z\n .record(z.string(), z.string())\n .optional()\n .describe('npm scripts to add. Only adds if key does not already exist.'),\n targetDir: z\n .string()\n .optional()\n .describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: z\n .boolean()\n .optional()\n .default(true)\n .describe('Run pnpm install after writing package.json. Defaults to true.'),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall }) => {\n // exactOptionalPropertyTypes: true means we cannot pass `undefined` explicitly\n // for optional fields ā conditionally spread them instead.\n const result = setupPackages({\n packages,\n runInstall,\n ...(devPackages !== undefined ? { devPackages } : {}),\n ...(scripts !== undefined ? { scripts } : {}),\n ...(targetDir !== undefined ? { targetDir } : {}),\n });\n\n const statusLine = result.success\n ? `ā
package.json updated: ${result.packageJsonPath}`\n : `ā Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation ā extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir ? path.resolve(opts.targetDir) : cwd;\n\n // Ensure resolved path stays within cwd ā no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink ā refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' ā must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' ā only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall',\n 'install',\n 'postinstall',\n 'prepare',\n 'prepublish',\n 'prepublishOnly',\n 'prepack',\n 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' ā writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z\n .object({\n // Zod v4: z.record(keySchema, valueSchema) ā two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n })\n .passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape ā the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies ā NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written ā prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts ā same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back ā use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool ā install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError =\n spawnErr.stderr?.toString().trim() ||\n (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return {\n ...emptyResult,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","{\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.10.0\",\n \"@stackwright-pro/cli-data-explorer\": \"workspace:*\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.1.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^4.0.18\"\n },\n \"scripts\": {\n \"build\": \"tsup src/server.ts --format cjs,esm --dts --clean\",\n \"dev\": \"tsup src/server.ts --format cjs,esm --dts --watch\",\n \"start\": \"node dist/server.js\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"name\": \"@stackwright-pro/mcp\",\n \"version\": \"0.2.0-alpha.0\",\n \"description\": \"MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation\",\n \"license\": \"PROPRIETARY\",\n \"main\": \"./dist/server.js\",\n \"module\": \"./dist/server.mjs\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.js\"\n }\n },\n \"files\": [\n \"dist\"\n ]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAA0B;AAC1B,mBAAqC;;;ACArC,iBAAkB;AAClB,+BAA6C;AAMtC,SAAS,0BAA0BA,SAAyB;AAEjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,UAAU,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,MACnF,aAAa,aACV,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AAAA,IACjE;AAAA,IACA,OAAO,EAAE,UAAU,YAAY,MAAM;AACnC,YAAM,aAAS,uCAAa;AAAA,QAC1B,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,QACzC,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,MACjD,CAAC;AAED,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,gCAAgC,OAAO,UAAU,CAAC,GAAG,KAAK,IAAI,CAAC;AAAA,YACvE;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,QAAkB,CAAC,mBAAY,OAAO,SAAS,MAAM;AAAA,CAAkB;AAE7E,iBAAW,UAAU,OAAO,UAAU;AACpC,cAAM,KAAK,aAAM,OAAO,IAAI,KAAK,OAAO,IAAI,GAAG;AAC/C,cAAM,KAAK,gBAAgB,OAAO,QAAQ,EAAE;AAC5C,cAAM,KAAK,cAAc,OAAO,UAAU,EAAE;AAC5C,YAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,gBAAM,aAAa,OAAO,OACvB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,EAChC,KAAK,IAAI;AACZ,gBAAM,KAAK,aAAa,UAAU,GAAG,OAAO,OAAO,SAAS,IAAI,QAAQ,EAAE,EAAE;AAAA,QAC9E;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,YAAM;AAAA,QACJ;AAAA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,kBAAkB,aACf,MAAM,aAAE,OAAO,CAAC,EAChB,SAAS,2DAA2D;AAAA,MACvE,iBAAiB,aACd,MAAM,aAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,+DAA+D;AAAA,MAC3E,aAAa,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,kBAAkB,iBAAiB,YAAY,MAAM;AAC5D,YAAM,aAAS,yCAAe;AAAA,QAC5B;AAAA,QACA,GAAI,oBAAoB,UAAa,EAAE,gBAAgB;AAAA,QACvD,aAAa,eAAe,QAAQ,IAAI;AAAA,MAC1C,CAAC;AAED,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,4BAA4B,OAAO,UAAU,KAAK,IAAI,CAAC;AAAA,YAC/D;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,QAAkB,CAAC,wCAAiC;AAC1D,YAAM,KAAK,SAAS;AACpB,YAAM,KAAK,eAAe;AAC1B,YAAM,KAAK,mBAAmB;AAC9B,YAAM,KAAK,gBAAgB;AAE3B,UAAI,OAAO,OAAO,WAAW,OAAO,OAAO,QAAQ,SAAS,GAAG;AAC7D,cAAM,KAAK,gBAAgB;AAC3B,mBAAWC,SAAQ,OAAO,OAAO,SAAS;AACxC,gBAAM,KAAK,aAAaA,KAAI,EAAE;AAAA,QAChC;AAAA,MACF;AAEA,UAAI,OAAO,OAAO,WAAW,OAAO,OAAO,QAAQ,SAAS,GAAG;AAC7D,cAAM,KAAK,gBAAgB;AAC3B,mBAAW,WAAW,OAAO,OAAO,SAAS;AAC3C,gBAAM,KAAK,aAAa,OAAO,EAAE;AAAA,QACnC;AAAA,MACF;AAEA,YAAM,KAAK,KAAK;AAEhB,UAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,cAAM,KAAK,0BAAgB;AAC3B,mBAAW,WAAW,OAAO,UAAU;AACrC,gBAAM,KAAK,KAAK,OAAO,EAAE;AAAA,QAC3B;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AClJA,IAAAC,cAAkB;AAClB,oBAA2B;AAC3B,gBAAe;AACf,kBAAiB;AAMV,SAAS,sBAAsBC,SAAyB;AAE7D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,UAAU,cAAE,OAAO,EAAE,SAAS,kDAAkD;AAAA,MAChF,YAAY,cACT,OAAO,EACP,SAAS,EACT,SAAS,uDAAuD;AAAA,IACrE;AAAA,IACA,OAAO,EAAE,UAAU,WAAW,MAAM;AAElC,UAAI,kBAAkB;AACtB,YAAM,YAAkE,CAAC;AAEzE,YAAM,aAAa,cAAc,YAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAE3E,UAAI,UAAAC,QAAG,WAAW,UAAU,GAAG;AAC7B,YAAI;AACF,gBAAM,UAAU,UAAAA,QAAG,aAAa,YAAY,MAAM;AAGlD,gBAAM,gBAAgB,QAAQ;AAAA,YAC5B;AAAA,UACF;AACA,cAAI,iBAAiB,cAAc,CAAC,MAAM,QAAQ;AAChD,8BAAkB;AAElB,kBAAM,cAAc,QAAQ;AAAA,cAC1B;AAAA,YACF;AACA,uBAAW,SAAS,aAAa;AAC/B,wBAAU,KAAK;AAAA,gBACb,MAAM,MAAM,CAAC,EAAG,KAAK;AAAA,gBACrB,KAAK,MAAM,CAAC,EAAG,KAAK;AAAA,gBACpB,QAAQ,MAAM,CAAC,EAAG,KAAK;AAAA,cACzB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAGA,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAqN,QAAQ;AAAA;AAAA,YACrO;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,eAAe,UAAU,KAAK,CAAC,MAAM,EAAE,QAAQ,QAAQ;AAE7D,UAAI,CAAC,cAAc;AACjB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE;AAAA;AAAA;AAAA;AAAA,OAAiE,QAAQ;AAAA;AAAA;AAAA,YAE7E;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAGA,UAAI,CAAC,SAAS,WAAW,SAAS,KAAK,CAAC,SAAS,WAAW,UAAU,GAAG;AACvE,YAAI,UAAAA,QAAG,WAAW,QAAQ,GAAG;AAC3B,gBAAM,cAAc,UAAAA,QAAG,aAAa,UAAU,MAAM;AACpD,gBAAM,aAAS,0BAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK;AAEpE,cAAI,WAAW,aAAa,QAAQ;AAClC,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM;AAAA;AAAA;AAAA;AAAA,YAAwE,aAAa,OAAO,UAAU,GAAG,EAAE,CAAC;AAAA,YAAkB,OAAO,UAAU,GAAG,EAAE,CAAC;AAAA;AAAA;AAAA,gBAC7J;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,QAA6B,aAAa,IAAI;AAAA,OAAU,QAAQ;AAAA,iBAAoB,UAAU,MAAM;AAAA,UAC5G;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAF,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,MAAM,cAAE,OAAO,EAAE,SAAS,kCAAkC;AAAA,MAC5D,KAAK,cAAE,OAAO,EAAE,SAAS,sCAAsC;AAAA,MAC/D,YAAY,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,MAAM,KAAK,WAAW,MAAM;AACnC,YAAM,aAAa,cAAc,YAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAG3E,UAAI,SAAS;AAEb,UAAI;AACF,YAAI,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU,GAAG;AAE3D,mBAAS;AAAA,QACX,WAAW,UAAAC,QAAG,WAAW,GAAG,GAAG;AAC7B,gBAAM,cAAc,UAAAA,QAAG,aAAa,KAAK,MAAM;AAC/C,uBAAS,0BAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK;AAAA,QAChE,OAAO;AACL,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,+BAA0B,GAAG;AAAA,cACrC;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,+BAA0B,CAAC;AAAA,YACnC;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,cAAc,aAAa,IAAI;AAAA,WAChC,GAAG;AAAA,cACA,MAAM;AAEd,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,EAAwE,WAAW;AAAA;AAAA,oBAAyB,MAAM;AAAA,UAC1H;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAF,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,YAAY,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,WAAW,MAAM;AACxB,YAAM,aAAa,cAAc,YAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAE3E,UAAI,CAAC,UAAAC,QAAG,WAAW,UAAU,GAAG;AAC9B,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,UAAU,UAAAA,QAAG,aAAa,YAAY,MAAM;AAGlD,YAAM,kBACJ,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,eAAe;AAElC,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,QAA8D,CAAC;AACrE,YAAM,cAAc,QAAQ;AAAA,QAC1B;AAAA,MACF;AAEA,iBAAW,SAAS,aAAa;AAC/B,cAAM,KAAK;AAAA,UACT,MAAM,MAAM,CAAC,EAAG,KAAK;AAAA,UACrB,KAAK,MAAM,CAAC,EAAG,KAAK;AAAA,UACpB,QAAQ,MAAM,CAAC,EAAG,KAAK,EAAE,UAAU,GAAG,EAAE,IAAI;AAAA,QAC9C,CAAC;AAAA,MACH;AAEA,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAQ,CAAC,6BAAsB,MAAM,MAAM;AAAA,CAAM;AACvD,iBAAW,QAAQ,OAAO;AACxB,cAAM,KAAK,aAAM,KAAK,IAAI,EAAE;AAC5B,cAAM,KAAK,WAAW,KAAK,GAAG,EAAE;AAChC,cAAM,KAAK,YAAY,KAAK,MAAM,EAAE;AACpC,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC1QA,IAAAC,cAAkB;AAQX,SAAS,iBAAiBC,SAAyB;AAExD,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,YAAY,cAAE,OAAO,EAAE,SAAS,iDAAiD;AAAA,MACjF,mBAAmB,cAChB,OAAO,EACP,SAAS,EACT,SAAS,gDAAgD;AAAA,MAC5D,UAAU,cACP,KAAK,CAAC,YAAY,QAAQ,OAAO,CAAC,EAClC,SAAS,EACT,SAAS,iCAAiC;AAAA,MAC7C,YAAY,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,YAAY,oBAAoB,IAAI,WAAW,YAAY,WAAW,MAAM;AACnF,YAAM,aAAa;AAEnB,YAAM,cAAc;AAAA;AAAA,YAEd,UAAU;AAAA;AAAA;AAAA,oBAGF,UAAU;AAAA,kBACZ,QAAQ;AAEpB,UAAI,cAAc;AAClB,UAAI,aAAa,IAAI;AACnB,sBAAc,8CAAyC,aAAa;AAAA,MACtE,WAAW,aAAa,KAAK;AAC3B,sBAAc,6CAAsC,aAAa,IAAI,QAAQ,CAAC,IAAI;AAAA,MACpF,WAAW,aAAa,MAAM;AAC5B,sBAAc,8CAAuC,aAAa,IAAI,QAAQ,CAAC,IAAI;AAAA,MACrF,OAAO;AACL,sBACE,oDAAwC,aAAa,MAAM,QAAQ,CAAC,IAAI;AAAA,MAC5E;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,uCAA6B,UAAU;AAAA;AAAA,EAAS,WAAW;AAAA;AAAA,YAAiB,aAAa,aAAa,qCAAgC,aAAa,SAAS,iCAA0B,0BAAqB;AAAA;AAAA;AAAA,EAAmB,WAAW;AAAA;AAAA,UACjP;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,aAAa,cACV;AAAA,QACC,cAAE,OAAO;AAAA,UACP,MAAM,cAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,UAC3C,mBAAmB,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,QAC3E,CAAC;AAAA,MACH,EACC,SAAS,oCAAoC;AAAA,MAChD,iBAAiB,cACd,KAAK,CAAC,YAAY,QAAQ,OAAO,CAAC,EAClC,SAAS,EACT,SAAS,2BAA2B;AAAA,MACvC,YAAY,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,aAAa,kBAAkB,YAAY,WAAW,MAAM;AACnE,YAAM,QAAQ,CAAC;AAAA,CAA+B;AAE9C,iBAAW,OAAO,aAAa;AAC7B,cAAM,MAAM,IAAI,qBAAqB;AACrC,YAAI,YAAY;AAChB,YAAI,MAAM,GAAI,aAAY;AAAA,iBACjB,MAAM,IAAK,aAAY;AAAA,iBACvB,OAAO,KAAM,aAAY;AAElC,cAAM,KAAK,GAAG,SAAS,IAAI,IAAI,IAAI,gBAAgB,GAAG,GAAG;AAAA,MAC3D;AAEA,YAAM,KAAK;AAAA,YAAe,eAAe,EAAE;AAE3C,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC5GA,IAAAC,cAAkB;AAClB,IAAAC,4BAA6B;AAMtB,SAAS,uBAAuBC,SAAyB;AAE9D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC,EAAE,SAAS,sCAAsC;AAAA,MAC7E,QAAQ,cAAE,KAAK,CAAC,QAAQ,SAAS,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,MACvF,WAAW,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YAAY;AAAA,MACtD,UAAU,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;AAAA,IACpF;AAAA,IACA,OAAO,EAAE,UAAU,SAAS,SAAS,WAAW,SAAS,MAAM;AAE7D,UAAI,gBAAuB,CAAC;AAC5B,UAAI,UAAU;AACZ,cAAM,aAAS,wCAAa,EAAE,SAAS,CAAC;AACxC,YAAI,OAAO,SAAS;AAClB,0BAAgB,OAAO,SAAS,OAAO,CAAC,MAAM,SAAS,SAAS,EAAE,IAAI,CAAC;AAAA,QACzE;AAAA,MACF;AAEA,YAAM,QACJ,aAAa,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,KAAK;AAErF,YAAM,YAAY;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,WAAW,UAAU,WAAW,SAAS;AAC3C,mBAAW,QAAQ,UAAU;AAC3B,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,cAAc;AAC7B,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,0BAA0B;AACzC,oBAAU,KAAK,uBAAuB,IAAI,WAAW;AACrD,oBAAU,KAAK,0BAA0B;AACzC,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,2BAA2B;AAC1C,oBAAU,KAAK,oBAAoB;AACnC,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,EAAE;AAAA,QACnB;AAAA,MACF;AAGA,gBAAU,KAAK,6BAA6B;AAC5C,gBAAU,KAAK,gBAAgB,SAAS,CAAC,CAAC,UAAU;AACpD,gBAAU,KAAK,qBAAqB,SAAS,CAAC,CAAC,EAAE;AACjD,gBAAU,KAAK,yBAAyB;AACxC,gBAAU,KAAK,wBAAwB;AACvC,YAAM,cAAc,CAAC,MAAM,QAAQ,UAAU,YAAY;AACzD,gBAAU;AAAA,QACR,kBACE,cAAc,CAAC,GAAG,QACd,MAAM,GAAG,CAAC,EACX,IAAI,CAAC,MAAW,EAAE,IAAI,EACtB,KAAK,IAAI,KAAK,YAAY,KAAK,IAAI,CACxC;AAAA,MACF;AACA,gBAAU,KAAK,EAAE;AAEjB,UAAI,WAAW,SAAS;AACtB,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,gBAAgB,SAAS,CAAC,CAAC,QAAQ;AAClD,kBAAU,KAAK,qBAAqB,SAAS,CAAC,CAAC,EAAE;AACjD,kBAAU,KAAK,gBAAgB;AAC/B,kBAAU,KAAK,qBAAqB;AACpC,kBAAU,KAAK,sBAAsB;AACrC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,uBAAuB;AACtC,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,yBAAyB;AACxC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,uBAAuB;AAAA,MACxC;AAEA,YAAM,OAAO,UAAU,KAAK,IAAI;AAEhC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,sCAA+B,SAAS,KAAK,IAAI,CAAC;AAAA;AAAA,UAAe,MAAM;AAAA;AAAA;AAAA,EAAmB,IAAI;AAAA;AAAA;AAAA;AAAA,UACtG;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,QAAQ,cAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,MAC7D,WAAW,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,MACpF,UAAU,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,IACnF;AAAA,IACA,OAAO,EAAE,QAAQ,YAAY,MAAM,SAAS,MAAM;AAEhD,UAAI,SAAgB,CAAC;AACrB,UAAI,UAAU;AACZ,cAAM,aAAS,wCAAa,EAAE,SAAS,CAAC;AACxC,YAAI,OAAO,SAAS;AAClB,gBAAM,MAAM,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACzD,cAAI,KAAK;AACP,qBAAS,IAAI;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAAa,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAElE,YAAM,YAAY;AAAA,QAChB,qBAAqB,UAAU;AAAA,QAC/B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,UAAU,iBAAiB,MAAM,IAAI,SAAS;AAAA,QAC7D;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,uBAAuB,MAAM,IAAI,SAAS;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,uCAAuC,MAAM;AAAA,QAC7C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,YAAM,gBACJ,OAAO,SAAS,IACZ,OAAO,MAAM,GAAG,CAAC,IACjB;AAAA,QACE,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,QAClC,EAAE,MAAM,cAAc,MAAM,WAAW;AAAA,QACvC,EAAE,MAAM,cAAc,MAAM,WAAW;AAAA,MACzC;AAEN,iBAAW,SAAS,eAAe;AACjC,cAAM,QAAQ,MAAM,KACjB,QAAQ,MAAM,GAAG,EACjB,QAAQ,SAAS,CAAC,MAAc,EAAE,YAAY,CAAC;AAClD,kBAAU,KAAK,mBAAmB;AAClC,kBAAU,KAAK,yBAAyB,MAAM,IAAI,SAAS;AAC3D,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,0BAA0B,KAAK,GAAG;AACjD,kBAAU,KAAK,gCAAgC;AAC/C,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,+BAA+B,MAAM,IAAI,MAAM,IAAI,MAAM;AACxE,kBAAU,KAAK,qCAAqC;AAAA,MACtD;AAEA,gBAAU,KAAK,kCAAkC;AAEjD,YAAM,OAAO,UAAU,KAAK,IAAI;AAEhC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,wCAAiC,MAAM;AAAA;AAAA;AAAA,EAAmB,IAAI;AAAA;AAAA;AAAA,8BAAoC,MAAM,KAAK,SAAS;AAAA,UAC9H;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC1LA,IAAAC,cAAkB;AAClB,2BAAoC;AACpC,gBAAuB;AACvB,IAAAC,eAAqB;AACrB,IAAAC,iBAA2B;AAC3B,IAAAC,aAAuC;AAwBvC,IAAM,gBAA2C,oBAAI,IAAI;AAKzD,eAAe,kBAAkB,WAAkE;AACjG,QAAM,iBAAa,uBAAK,kBAAO,GAAG,kBAAc,2BAAW,CAAC,OAAO;AACnE,QAAM,OAAO,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAElD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,aAAa,QAAQ,aAAa,UAAU,WAAW;AAG7D,UAAM,cAAc,sBAAsB;AAE1C,UAAM,WAAO;AAAA,MACX;AAAA,MACA,CAAC,MAAM,+BAA+B,YAAY,YAAY,UAAU,OAAO,IAAI,CAAC;AAAA,MACpF;AAAA,QACE,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,QAC9B,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAGA,kBAAc,IAAI,WAAW,IAAI;AAEjC,QAAI,gBAAgB;AACpB,QAAI,UAAU;AAEd,SAAK,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACxC,uBAAiB,KAAK,SAAS;AAC/B,UAAI,cAAc,SAAS,cAAc,KAAK,cAAc,SAAS,aAAa,GAAG;AACnF,kBAAU;AACV,gBAAQ,EAAE,MAAM,WAAW,CAAC;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,SAAK,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAExC,UAAI,CAAC,cAAc,SAAS,UAAU,GAAG;AACvC,gBAAQ,MAAM,0BAA0B,KAAK,SAAS,EAAE,KAAK,CAAC;AAAA,MAChE;AAAA,IACF,CAAC;AAED,SAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,UAAI,CAAC,SAAS;AACZ,sBAAc,OAAO,SAAS;AAC9B,eAAO,IAAI,MAAM,kCAAkC,IAAI,OAAO,EAAE,CAAC;AAAA,MACnE;AAAA,IACF,CAAC;AAED,SAAK,GAAG,QAAQ,CAAC,SAAS;AACxB,oBAAc,OAAO,SAAS;AAC9B,cAAI,uBAAW,UAAU,GAAG;AAC1B,YAAI;AACF,qCAAW,UAAU;AAAA,QACvB,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAC;AAGD,eAAW,MAAM;AACf,UAAI,CAAC,SAAS;AACZ,aAAK,KAAK;AACV,sBAAc,OAAO,SAAS;AAC9B,eAAO,IAAI,MAAM,+BAA+B,CAAC;AAAA,MACnD;AAAA,IACF,GAAG,GAAK;AAAA,EACV,CAAC;AACH;AAKA,eAAe,iBAAiB,WAAkC;AAChE,QAAM,OAAO,cAAc,IAAI,SAAS;AACxC,MAAI,MAAM;AACR,SAAK,KAAK,SAAS;AACnB,kBAAc,OAAO,SAAS;AAAA,EAChC;AACF;AAKA,eAAe,YACb,MACA,MACAC,OACA,MACY;AACZ,QAAM,OAAO,MAAM,OAAO,MAAM;AAEhC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,MAAM,IAAI,IAAIA,OAAM,UAAU,IAAI,IAAI,IAAI,EAAE;AAElD,UAAM,aAAa;AAAA,MACjB,UAAU;AAAA,MACV;AAAA,MACA,MAAM,IAAI;AAAA,MACV,QAAQ,OAAO,SAAS;AAAA,MACxB,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,MAAM,KAAK,QAAQ,YAAY,CAAC,QAAQ;AAC5C,UAAI,OAAO;AAEX,UAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,gBAAQ,MAAM,SAAS;AAAA,MACzB,CAAC;AAED,UAAI,GAAG,OAAO,MAAM;AAClB,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,cAAI,IAAI,cAAc,IAAI,cAAc,KAAK;AAC3C,mBAAO,IAAI,MAAM,OAAO,UAAU,OAAO,SAAS,QAAQ,IAAI,UAAU,EAAE,CAAC;AAAA,UAC7E,OAAO;AACL,oBAAQ,MAAM;AAAA,UAChB;AAAA,QACF,SAAS,GAAG;AACV,iBAAO,IAAI,MAAM,6BAA6B,IAAI,EAAE,CAAC;AAAA,QACvD;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,GAAG,SAAS,MAAM;AAEtB,QAAI,MAAM;AACR,UAAI,MAAM,KAAK,UAAU,IAAI,CAAC;AAAA,IAChC;AAEA,QAAI,IAAI;AAAA,EACV,CAAC;AACH;AAKA,SAAS,wBAAgC;AACvC,QAAM,aAAa;AAAA,QACjB,mBAAK,WAAW,kBAAkB;AAAA,QAClC,mBAAK,WAAW,qBAAqB;AAAA,QACrC,mBAAK,QAAQ,IAAI,GAAG,YAAY;AAAA,EAClC;AAEA,aAAW,aAAa,YAAY;AAClC,YAAI,uBAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,QAAQ,IAAI;AACrB;AAKO,SAAS,2BAA2BC,SAAyB;AAElE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,SAAS,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8CAA8C;AAAA,MACtF,eAAe,cACZ,KAAK,CAAC,iBAAiB,aAAa,eAAe,cAAc,gBAAgB,CAAC,EAClF,SAAS,8BAA8B;AAAA,MAC1C,UAAU,cAAE,OAAO,EAAE,SAAS,4CAA4C;AAAA,MAC1E,SAAS,cACN,MAAM,cAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,mDAAmD;AAAA,MAC/D,UAAU,cACP,KAAK,CAAC,YAAY,aAAa,UAAU,CAAC,EAC1C,SAAS,EACT,SAAS,wDAAwD;AAAA,MACpE,cAAc,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sCAAsC;AAAA,IACrF;AAAA,IACA,OAAO,EAAE,SAAS,eAAe,UAAU,SAAS,WAAW,aAAa,aAAa,MAAM;AAC7F,YAAM,YAAY,WAAO,2BAAW,EAAE,MAAM,GAAG,CAAC,CAAC;AAEjD,UAAI;AAEF,cAAM,EAAE,KAAK,IAAI,MAAM,kBAAkB,SAAS;AAGlD,cAAM,YAAY,SAAS,OAAO,cAAc,aAAa,MAAM,aAAa,CAAC,CAAC;AAGlF,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ,SAAS,OAAO,cAAc;AAAA,YAC9B;AAAA,YACA,aAAa,SAAS;AAAA,YACtB,EAAE,SAAS,EAAE,SAAS,QAAQ,EAAE;AAAA,UAClC;AAAA,QACF;AAGA,cAAM,UAAgC;AAAA,UACpC,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,UACvC;AAAA,UACA;AAAA,UACA,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,UACvC;AAAA,UACA,GAAI,iBAAiB,UAAa,EAAE,aAAa;AAAA,QACnD;AAEA,cAAM,WAAW,MAAM;AAAA,UACrB,SAAS,OAAO,cAAc;AAAA,UAC9B;AAAA,UACA;AAAA,UACA,EAAE,QAAQ;AAAA,QACZ;AAGA,cAAM,iBAAiB,SAAS;AAGhC,cAAM,WAAW,SAAS;AAC1B,cAAM,QAAQ,SAAS;AACvB,cAAM,SAAS,SAAS;AACxB,cAAM,WAAW,SAAS,WAAW,eAAe;AAEpD,YAAI,SAAS,eAAe;AAC1B,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MACE,6CAAmC,SAAS,mBAAmB,yBAAyB;AAAA;AAAA,sBACjE,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA;AAAA,cAEhD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE,0BAAqB,MAAM,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA;AAAA,YAE1D;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,cAAM,iBAAiB,SAAS;AAGhC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE,gCAA2B,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAKvF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,mBAAmB,cAAE,OAAO,EAAE,SAAS,gCAAgC;AAAA,MACvE,iBAAiB,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAAE,SAAS,iCAAiC;AAAA,IAC9F;AAAA,IACA,OAAO,EAAE,mBAAmB,gBAAgB,MAAM;AAChD,YAAM,YAAY,WAAO,2BAAW,EAAE,MAAM,GAAG,CAAC,CAAC;AAEjD,UAAI;AAEF,cAAM,EAAE,KAAK,IAAI,MAAM,kBAAkB,SAAS;AAGlD,cAAM,WAAW,MAAM;AAAA,UACrB,SAAS,OAAO,cAAc;AAAA,UAC9B;AAAA,UACA;AAAA,UACA,EAAE,mBAAmB,gBAAgB;AAAA,QACvC;AAGA,cAAM,iBAAiB,SAAS;AAEhC,YAAI,SAAS,UAAU;AACrB,gBAAM,OAAO,SAAS;AACtB,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MACE;AAAA;AAAA,gBACiB,iBAAiB;AAAA,gBACjB,KAAK,UAAU,eAAe,CAAC;AAAA;AAAA,YACnC,KAAK,WAAW;AAAA;AAAA,sBACN,KAAK,SAAS,KAAK,IAAI,KAAK,qBAAqB;AAAA;AAAA;AAAA,cAE5E;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,cAAM,iBAAiB,SAAS;AAEhC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,qCAAgC,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,YAChG;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAEA;AAAA,MACE,aAAa,cACV,OAAO,EACP,SAAS,EACT,SAAS,+DAA+D;AAAA,IAC7E;AAAA,IACA,OAAO,EAAE,YAAY,MAAM;AAGzB,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MACE;AAAA;AAAA;AAAA;AAAA,iBAGkB,eAAe,iCAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOtE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC3aA,IAAAC,cAAkB;AAClB,IAAAC,aAAiF;AACjF,IAAAC,wBAAyB;AACzB,IAAAC,eAAiB;AAiCV,SAAS,qBAAqBC,SAAyB;AAC5D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA;AAAA,MAEE,UAAU,cACP,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAC7B;AAAA,QACC;AAAA,MACF;AAAA,MACF,aAAa,cACV,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAC7B,SAAS,EACT,SAAS,kDAAkD;AAAA,MAC9D,SAAS,cACN,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAC7B,SAAS,EACT,SAAS,8DAA8D;AAAA,MAC1E,WAAW,cACR,OAAO,EACP,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,YAAY,cACT,QAAQ,EACR,SAAS,EACT,QAAQ,IAAI,EACZ,SAAS,gEAAgE;AAAA,IAC9E;AAAA,IACA,OAAO,EAAE,UAAU,aAAa,SAAS,WAAW,WAAW,MAAM;AAGnE,YAAM,SAAS,cAAc;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,QACnD,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,QAC3C,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjD,CAAC;AAED,YAAM,aAAa,OAAO,UACtB,gCAA2B,OAAO,eAAe,KACjD,kBAAa,OAAO,KAAK;AAE7B,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA,OAAO,MAAM,SAAS,IAClB,UAAU,OAAO,MAAM,MAAM,MAAM,OAAO,MAAM,KAAK,IAAI,CAAC,KAC1D;AAAA,QACJ,OAAO,QAAQ,SAAS,IACpB,4BAA4B,OAAO,QAAQ,MAAM,MAAM,OAAO,QAAQ,KAAK,IAAI,CAAC,KAChF;AAAA,QACJ,OAAO,aAAa,SAAS,IACzB,kBAAkB,OAAO,aAAa,MAAM,MAAM,OAAO,aAAa,KAAK,IAAI,CAAC,KAChF;AAAA,QACJ,iBAAiB,OAAO,YAAY,qBAAqB,OAAO,WAAW,aAAa,uBAAuB,SAAS;AAAA,MAC1H;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,MAAM;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,cAAc,MAMN;AACtB,QAAM,cAA8D;AAAA,IAClE,OAAO,CAAC;AAAA,IACR,SAAS,CAAC;AAAA,IACV,cAAc,CAAC;AAAA,IACf,WAAW;AAAA,IACX,iBAAiB;AAAA,EACnB;AAEA,MAAI;AAIF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,iBAAiB,KAAK,YAAY,aAAAC,QAAK,QAAQ,KAAK,SAAS,IAAI;AAGvE,UAAM,aAAa,IAAI,SAAS,aAAAA,QAAK,GAAG,IAAI,MAAM,MAAM,aAAAA,QAAK;AAC7D,QAAI,mBAAmB,OAAO,CAAC,eAAe,WAAW,UAAU,GAAG;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA;AAAA,QAEjB,OAAO;AAAA,MACT;AAAA,IACF;AAKA,UAAM,4BAA4B,aAAAA,QAAK,KAAK,gBAAgB,cAAc;AAE1E,QAAI,KAAC,uBAAW,yBAAyB,GAAG;AAC1C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,GAAG;AAAA,QACH,OAAO,4BAA4B,cAAc;AAAA,MACnD;AAAA,IACF;AAKA,QAAI;AACJ,QAAI;AACF,uBAAa,yBAAa,cAAc;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA,QACjB,OAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,cAAU,yBAAa,GAAG;AAChC,UAAM,iBAAiB,QAAQ,SAAS,aAAAA,QAAK,GAAG,IAAI,UAAU,UAAU,aAAAA,QAAK;AAC7E,QAAI,eAAe,WAAW,CAAC,WAAW,WAAW,cAAc,GAAG;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA;AAAA,QAEjB,OAAO;AAAA,MACT;AAAA,IACF;AAQA,UAAM,sBAAsB,aAAAA,QAAK,KAAK,YAAY,cAAc;AAEhE,UAAM,cAAU,sBAAU,mBAAmB;AAC7C,QAAI,QAAQ,eAAe,GAAG;AAC5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAMA,UAAM,oBAAoB;AAC1B,UAAM,cAAc;AAAA,MAClB,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC,CAAC;AAAA,MAClC,GAAG,OAAO,KAAK,KAAK,eAAe,CAAC,CAAC;AAAA,IACvC;AACA,eAAW,OAAO,aAAa;AAC7B,UAAI,CAAC,kBAAkB,KAAK,GAAG,GAAG;AAChC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS;AAAA,UACT,OAAO,0BAA0B,GAAG;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAOA,UAAM,kBACJ;AACF,UAAM,oBAAoB;AAAA,MACxB,GAAG,OAAO,QAAQ,KAAK,YAAY,CAAC,CAAC;AAAA,MACrC,GAAG,OAAO,QAAQ,KAAK,eAAe,CAAC,CAAC;AAAA,IAC1C;AACA,eAAW,CAAC,KAAK,OAAO,KAAK,mBAAmB;AAC9C,UAAI,CAAC,gBAAgB,KAAK,QAAQ,KAAK,CAAC,GAAG;AACzC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS;AAAA,UACT,OAAO,iCAAiC,GAAG,OAAO,OAAO;AAAA,QAC3D;AAAA,MACF;AAAA,IACF;AAKA,UAAM,yBAAyB,oBAAI,IAAI;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IACF,CAAC;AACD,QAAI,KAAK,SAAS;AAChB,iBAAW,OAAO,OAAO,KAAK,KAAK,OAAO,GAAG;AAC3C,YAAI,uBAAuB,IAAI,GAAG,GAAG;AACnC,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,SAAS;AAAA,YACT,OAAO,kCAAkC,GAAG;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAKA,UAAM,UAAM,yBAAa,qBAAqB,MAAM;AAGpD,UAAM,oBAAoB,cACvB,OAAO;AAAA;AAAA,MAEN,cAAc,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACxD,iBAAiB,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MAC3D,SAAS,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACrD,CAAC,EACA,YAAY;AAEf,UAAM,eAAe,kBAAkB,UAAU,KAAK,MAAM,GAAG,CAAC;AAChE,QAAI,CAAC,aAAa,SAAS;AACzB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO,mCAAmC,aAAa,MAAM,OAAO;AAAA,MACtE;AAAA,IACF;AAGA,UAAM,SAAS,aAAa;AAK5B,UAAM,QAAkB,CAAC;AACzB,UAAM,UAAoB,CAAC;AAC3B,UAAM,eAAyB,CAAC;AAIhC,UAAM,cAAc,oBAAI,IAAY;AAAA,MAClC,GAAG,OAAO,KAAK,OAAO,gBAAgB,CAAC,CAAC;AAAA,MACxC,GAAG,OAAO,KAAK,OAAO,mBAAmB,CAAC,CAAC;AAAA,IAC7C,CAAC;AAGD,WAAO,eAAe,OAAO,gBAAgB,CAAC;AAC9C,eAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AAC1D,UAAI,YAAY,IAAI,GAAG,GAAG;AACxB,gBAAQ,KAAK,GAAG;AAAA,MAClB,OAAO;AACL,eAAO,aAAa,GAAG,IAAI;AAC3B,oBAAY,IAAI,GAAG;AACnB,cAAM,KAAK,GAAG;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,KAAK,eAAe,OAAO,KAAK,KAAK,WAAW,EAAE,SAAS,GAAG;AAChE,aAAO,kBAAkB,OAAO,mBAAmB,CAAC;AACpD,iBAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,WAAW,GAAG;AAC7D,YAAI,YAAY,IAAI,GAAG,GAAG;AACxB,kBAAQ,KAAK,GAAG;AAAA,QAClB,OAAO;AACL,iBAAO,gBAAgB,GAAG,IAAI;AAC9B,sBAAY,IAAI,GAAG;AACnB,gBAAM,KAAK,GAAG;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,WAAW,OAAO,KAAK,KAAK,OAAO,EAAE,SAAS,GAAG;AACxD,aAAO,UAAU,OAAO,WAAW,CAAC;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,YAAI,OAAO,QAAQ,GAAG,MAAM,QAAW;AACrC,iBAAO,QAAQ,GAAG,IAAI;AACtB,uBAAa,KAAK,GAAG;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAKA,kCAAc,qBAAqB,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAKzE,QAAI,YAAY;AAChB,QAAI;AAEJ,QAAI,KAAK,YAAY;AACnB,UAAI;AACF,4CAAS,gBAAgB,EAAE,KAAK,YAAY,OAAO,QAAQ,SAAS,IAAO,CAAC;AAC5E,oBAAY;AAAA,MACd,SAAS,KAAK;AAGZ,oBAAY;AACZ,cAAM,WAAW;AACjB,uBACE,SAAS,QAAQ,SAAS,EAAE,KAAK,MAChC,eAAe,QAAQ,IAAI,UAAU;AAAA,MAC1C;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF;AACF;;;ACtZA;AAAA,EACE,cAAgB;AAAA,IACd,6BAA6B;AAAA,IAC7B,sCAAsC;AAAA,IACtC,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,eAAe;AAAA,IACf,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,iBAAiB;AAAA,EACnB;AAAA,EACA,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AACF;;;AP1BA,IAAM,SAAS,IAAI,qBAAU;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS,gBAAY;AACvB,CAAC;AAGD,0BAA0B,MAAM;AAChC,sBAAsB,MAAM;AAC5B,iBAAiB,MAAM;AACvB,uBAAuB,MAAM;AAC7B,2BAA2B,MAAM;AACjC,qBAAqB,MAAM;AAE3B,eAAe,OAAO;AACpB,QAAM,YAAY,IAAI,kCAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,UAAQ,MAAM,6CAA6C;AAC7D;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["server","path","import_zod","server","path","fs","import_zod","server","import_zod","import_cli_data_explorer","server","import_zod","import_path","import_crypto","import_fs","path","server","import_zod","import_fs","import_child_process","import_path","server","path"]}
|