{"version":3,"file":"mcp-proxy.mjs","names":[],"sources":["../src/mcp/proxy.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { appendFile, mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport type { ContentBlock, GetPromptResult } from '@modelcontextprotocol/sdk/types.js'\nimport { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server'\nimport * as z from 'zod'\nimport type { InvestigatorConfig } from '../config/schema.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport type { McpTool } from './schema-cache.js'\nimport { HIDDEN_REMOTE_TOOL_NAMES, PUBLIC_MCP_TOOL_ALLOWED_ARGS, PUBLIC_MCP_TOOL_REQUIRED_ARGS } from './tool-visibility.js'\nimport { PaymentRequiredError } from './client.js'\nimport { primitiveBackendUsageStatus } from './usage-status.js'\n\nconst LOCAL_TOOL_NAMES = new Set([\n  'meta_network_capabilities',\n  'meta_usage_status',\n  'meta_help',\n  'wallet_balance',\n])\nconst GRAPH_RESOURCE_URI = 'ui://chain-insights/graph'\nconst GRAPH_APP_TOOL_NAMES = new Set([\n  'aml_address_risk',\n  'aml_trace_victim_funds',\n  'aml_trace_suspect_funds',\n  'aml_trace_deposit_sources',\n])\nconst GRAPH_ARRAY_KEYS = ['nodes', 'edges', 'flows', 'edge_anchors'] as const\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport type McpProxyMode = 'workspace' | 'stateless'\n\nexport function resolveMcpProxyMode(env: NodeJS.ProcessEnv = process.env): McpProxyMode {\n  const raw = env['CHAIN_INSIGHTS_MCP_PROXY_MODE']?.trim().toLowerCase()\n  if (!raw || raw === 'workspace') return 'workspace'\n  if (raw === 'stateless' || raw === 'no-workspace' || raw === 'workspace-less') return 'stateless'\n  throw new Error(`CHAIN_INSIGHTS_MCP_PROXY_MODE must be workspace or stateless; got \"${raw}\"`)\n}\n\nconst COMMA_SEPARATED_ADDRESS_FIELDS = new Set([\n  'victim_addresses',\n  'known_suspect_addresses',\n  'suspect_addresses',\n  'deposit_addresses',\n])\n\nconst KNOWN_PUBLIC_TOOL_DESCRIPTIONS: Record<string, string> = {\n  meta_network_capabilities: 'Return the current Chain Insights network and tool support matrix.',\n  meta_usage_status: \"Return the caller's public free graph_query quota for the current UTC day.\",\n  meta_help: 'Show a short guide to Chain Insights tools and workflow.',\n  wallet_balance: 'Show the local Chain Insights payment wallet address, payment network, token, and amount.',\n  aml_address_risk: 'Screen one blockchain address for AML risk, behavior patterns, neighborhood context, exchange exposure, and optional comparison with another address. Set topology_scope=archive_topology to screen against full history instead of the default live_topology; archive_topology can take substantially longer and is billed for the real time it takes.',\n  aml_trace_victim_funds: 'Trace victim or trusted-source funds forward to intermediary and exchange deposit candidates. Defaults to topology_scope=live_topology (recent activity, fast); set topology_scope=archive_topology for older incidents or when live_topology finds nothing -- it can take substantially longer and is billed for the real time it takes.',\n  aml_trace_suspect_funds: 'Trace suspect-controlled scammer, mule, operator, or laundering-ring funds forward to cashout topology. Defaults to topology_scope=live_topology (recent activity, fast); set topology_scope=archive_topology for older incidents or when live_topology finds nothing -- it can take substantially longer and is billed for the real time it takes.',\n  aml_trace_deposit_sources: 'Trace suspected deposit or cashout addresses backward to upstream sources, shared funders, and convergence. Defaults to topology_scope=live_topology (recent activity, fast); set topology_scope=archive_topology for older incidents or when live_topology finds nothing -- it can take substantially longer and is billed for the real time it takes.',\n  graph_query: 'Run a read-only GQL/Cypher query through the Chain Insights graph endpoint. Use USE live_topology for recent topology, USE archive_topology for historical topology, and USE facts for labels, features, risk scores, assets, and enrichment. Cross-layer correlated joins may be limited by the active graph endpoint; preserve full addresses exactly.',\n  graph_query_batch: 'Run multiple read-only GQL/Cypher queries through the Chain Insights graph endpoint in one paid batch. Prefer this for related topology/facts reads.',\n}\nconst FALLBACK_GRAPH_PRIMITIVE_TOOL_NAMES = ['graph_query', 'graph_query_batch'] as const\n\ntype ToolInputShape = Record<string, z.ZodTypeAny>\ntype ToolHandler = (args: unknown, extra?: unknown) => Promise<unknown> | unknown\ntype ToolRegistrationConfig = Parameters<McpServer['registerTool']>[1]\ntype ToolCallInput = { name: string; arguments?: Record<string, unknown> }\ntype RemoteToolCaller = {\n  callTool: Client['callTool']\n}\ntype ChainInsightsGraphMeta = {\n  schema: string\n  url: string\n}\n\nconst NETWORK_DESCRIPTION = 'Network to query, for example Bittensor or Base.'\nconst BITTENSOR_NETWORK_SCHEMA = z.enum(['bittensor']).describe(NETWORK_DESCRIPTION)\nconst TOPOLOGY_SCOPE_DESCRIPTION = 'Which topology graph to query: live_topology (default, fast, recent activity) or archive_topology (full history, slower and billed for the extra real time it takes at the same per-second rate). Use archive_topology for older incidents that may be outside the live window.'\nconst TOPOLOGY_SCOPE_SCHEMA = z.enum(['live_topology', 'archive_topology']).optional().describe(TOPOLOGY_SCOPE_DESCRIPTION)\nconst EMPTY_INPUT_SCHEMA = z.strictObject({})\nconst REMOTE_GRAPH_TOOL_REQUEST_TIMEOUT_MS = 15 * 60 * 1000\n\nconst CHAIN_INSIGHTS_WORKFLOW = [\n  'Workflow:',\n  '1. Chain Insights workspaces are append-only local working directories. Bootstrap with cia init before workflows that persist artifacts.',\n  '2. Do not call investigation tools until required arguments are known. Network is required; use meta_network_capabilities to check supported networks and available tools, or ask the user if missing.',\n  '3. Use aml_address_risk for single-address enrichment. Use aml_trace_victim_funds for victim/source forward tracing and aml_trace_suspect_funds for suspect-controlled outbound laundering/cashout topology; both include a bounded deposit_funding traceback preview for discovered deposit candidates. Use aml_trace_deposit_sources for deeper reverse traceback from suspected deposit endpoints. Use graph_query(_batch) only when the high-level tools do not answer the exact question.',\n  '4. Persisted outputs belong in the initialized workspace under reports/, reports/graphs/, reports/tables/, artifacts/, entities/, sessions/, and published/.',\n  '5. For local review, inspect the generated Markdown and graph/table artifacts directly in the workspace.',\n].join('\\n')\n\nconst GRAPH_SCHEMA_HINTS = [\n  'Graph query hints for network=bittensor:',\n  '- The graph is identity-grain. The only topology node label is Identity (satellite Address nodes exist only for member-address lookup), keyed by identity_id in the canonical prefixed form <network>:<canonical_address>, for example bittensor:0x1874a43d7c6d888f9eda3d22a3a49704e3cadb24.',\n  '- Identity nodes carry identity_id, labels, and is_exchange. There is no addresses list property and no network property; each network domain has its own graph. Member-address forms live exclusively on satellite (:Address {address, network}) nodes; enumerate them with MATCH (i:Identity {identity_id: $id})-[:HAS_ADDRESS]->(m:Address) RETURN m.address, m.network.',\n  '- Identity nodes also carry a slim live risk verdict (risk_score float, risk_level string) plus base activity rollups: degree_in/degree_out/degree_total (distinct counterparty identities), tx_in_count/tx_out_count/tx_total_count, total_in_usd/total_out_usd/total_volume_usd, net_flow_usd (in minus out; positive = net receiver) — all computed from external flows only — and first_activity_timestamp/last_activity_timestamp/activity_span_days, which include all flows (self-loops included). Movement between an identity\\'s own member forms is excluded from the degree/count/USD rollups and exposed separately as internal_tx_count/internal_volume_usd (sparse: absent when zero, like is_exchange). FLOWS_TO edges carry tx_count, amount_usd_sum, avg_tx_size_usd (understates when price_coverage_ratio < 1), first/last_seen_timestamp, first/last_tx_id, dominant_asset (largest USD share), price_coverage_ratio. Lifetime aggregates are the only serving window.',\n  '- Resolve any member address form (0x or SS58) to its identity with the indexed exact lookup: MATCH (m:Address {address: $input})<-[:HAS_ADDRESS]-(i:Identity) RETURN i.identity_id LIMIT 1. :Address(address) is unique and index-backed.',\n  '- Detailed, provenanced scoring still comes from USE facts: (:Identity)-[:HAS_RISK_SCORE]->(:RiskScore) for model versions/processing dates, (:Identity)-[:HAS_LABEL]->(:AddressLabel) for label risk, (:Identity)-[:HAS_FEATURE]->(:AddressFeature) for feature metrics. Use node risk_score/risk_level only as the quick-triage verdict; never read ml_* properties off topology nodes.',\n  '- Facts graph labels include Identity, AddressLabel, AddressFeature, RiskScore, Asset, NeuronEndpoint, Hotkey, and IPAddress. Facts identity keys match live identity_id values exactly.',\n  '- Live topology relationships include FLOWS_TO and RISK_PROXIMITY between Identity nodes. Bittensor live topology may also include the pure-Cypher neuron overlay: (:Identity)-[:SERVES]->(:Subnet) and (:Identity)-[:OWNS]->(:Identity), with detailed neuron endpoint facts still served from USE facts.',\n  '- FLOWS_TO properties are scoped to the selected topology graph and commonly carry tx_count, amount_usd_sum, avg_tx_size_usd, first_seen_timestamp, last_seen_timestamp, first_tx_id, last_tx_id, dominant_asset, price_coverage_ratio. Confirm available fields through runtime schema before relying on them.',\n  '- Traversal rule: for BFS, fixed-hop fallback, shortest-path, or manual FLOWS_TO traversal, exchange hot wallets are terminal endpoints only. Do not expand from, through, or classify exchange nodes as deposit, suspect, or intermediate candidates; filter every non-terminal node with is_exchange IS NULL.',\n  '- Start schema discovery with endpoint-safe property reads: MATCH (n:Identity) WHERE n.identity_id IS NOT NULL RETURN n.identity_id AS identity_id, n.labels AS labels, n.risk_score AS risk_score, n.risk_level AS risk_level LIMIT 20',\n  '- Relationship discovery: MATCH (:Identity)-[r:FLOWS_TO]->(:Identity) RETURN r.amount_usd_sum AS amount_usd_sum, r.tx_count AS tx_count LIMIT 20',\n  '- graph_query uses the active Chain Insights graph endpoint. Select the graph with USE live_topology for recent topology, USE archive_topology for historical topology, and USE facts for labels, features, risk scores, assets, and enrichment. If an older endpoint surfaces a legacy topology_scope argument, treat it as compatibility routing only; identity is the node grain, not the topology name.',\n  '- Archive topology labels include Identity and Address. Archived money-flow topology is represented as (:Identity)-[:FLOWS_TO]->(:Identity) relationships with period_granularity, period_start_date, and period_end_date, and archive member-address lookup uses (:Identity)-[:HAS_ADDRESS]->(:Address) with Address.address and member-ledger Address.network projected for public address resolution.',\n  '- All graph_query calls are read-only. Never use CREATE, INSERT, MERGE, SET, DELETE, REMOVE, DROP, DETACH, ADD, CONNECT, DISCONNECT, ALTER, TRUNCATE, GRANT, or REVOKE.',\n  '- Use USE facts graph patterns for fact and enrichment reads. Do not query internal table namespaces directly.',\n].join('\\n')\n\nconst GRAPH_REPORT_HINTS = [\n  'Graph visualization behavior:',\n  '- Graph-backed tools return the investigator report as text content and keep raw graph data out of LLM-visible structuredContent.',\n  '- Chain Insights prepares the graph view automatically from local workspace report files when graph metadata is available.',\n  '- If the graph view cannot load a report, retry the graph-backed tool call so Chain Insights can recreate the local graph report.',\n].join('\\n')\n\nconst SERVER_INSTRUCTIONS = [\n  'Chain Insights is a local graph-analysis workspace for AI agents.',\n  CHAIN_INSIGHTS_WORKFLOW,\n  GRAPH_REPORT_HINTS,\n  GRAPH_SCHEMA_HINTS,\n  'Presentation rules: preserve tool summaries as returned; never truncate blockchain addresses or identity_resolution audit mappings.',\n].join('\\n\\n')\n\nconst STATELESS_SERVER_INSTRUCTIONS = [\n  'Chain Insights is running as a stateless AML proxy for a host application.',\n  'Do not use local workspace persistence, wallet, or graph report workflows in this mode.',\n  'Use meta_network_capabilities first when network support is unknown, then call aml_address_risk, aml_trace_victim_funds, aml_trace_suspect_funds, aml_trace_deposit_sources, graph_query, or graph_query_batch as needed.',\n  GRAPH_SCHEMA_HINTS,\n  'Presentation rules: preserve tool summaries as returned; never truncate blockchain addresses or identity_resolution audit mappings.',\n].join('\\n\\n')\n\nfunction readGraphAppHtml(): string {\n  const candidates = [\n    path.resolve(__dirname, 'templates', 'graph.html'),\n    path.resolve(__dirname, '..', 'templates', 'graph.html'),\n    path.resolve(__dirname, '..', 'viz', 'templates', 'graph.html'),\n  ]\n\n  for (const candidate of candidates) {\n    try {\n      return readFileSync(candidate, 'utf8')\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err\n    }\n  }\n\n  throw new Error(`Chain Insights Graph app template not found. Tried: ${candidates.join(', ')}`)\n}\n\nfunction graphArtifactOrigins(config: Pick<InvestigatorConfig, 'serverPort'>): string[] {\n  return [\n    `http://127.0.0.1:${config.serverPort}`,\n    `http://localhost:${config.serverPort}`,\n  ]\n}\n\nfunction hasGraphApp(tool: McpTool): boolean {\n  const configuredUri = tool._meta?.ui\n  if (\n    configuredUri &&\n    typeof configuredUri === 'object' &&\n    'resourceUri' in configuredUri &&\n    configuredUri.resourceUri === GRAPH_RESOURCE_URI\n  ) {\n    return true\n  }\n\n  if (tool._meta?.['ui/resourceUri'] === GRAPH_RESOURCE_URI) return true\n  if (GRAPH_APP_TOOL_NAMES.has(tool.name)) return true\n  return JSON.stringify(tool.outputSchema ?? {}).includes('\"app_data\"')\n}\n\nfunction graphToolMeta(tool: McpTool): Record<string, unknown> & { ui: { resourceUri: string } } {\n  const meta = { ...(tool._meta ?? {}) }\n  const ui =\n    meta.ui && typeof meta.ui === 'object' && !Array.isArray(meta.ui)\n      ? { ...(meta.ui as Record<string, unknown>) }\n      : {}\n\n  return {\n    ...meta,\n    ui: {\n      ...ui,\n      resourceUri: GRAPH_RESOURCE_URI,\n    },\n  }\n}\n\nfunction knownPublicToolInputSchema(toolName: string): ToolInputShape | null {\n  switch (toolName) {\n    case 'aml_address_risk':\n      return {\n        address: z.string().min(1).describe('Blockchain address to screen.'),\n        network: BITTENSOR_NETWORK_SCHEMA,\n        compare_address: z.string().optional().describe('Optional address to compare against the screened address.'),\n        include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n        topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n      }\n    case 'aml_trace_victim_funds':\n      return {\n        victim_addresses: z.string().min(1).describe('Victim or source addresses, comma-separated. Min 1, max 5.'),\n        network: BITTENSOR_NETWORK_SCHEMA,\n        known_suspect_addresses: z.string().optional().describe('Optional known suspect addresses for context only. Max 5.'),\n        incident_timestamp_ms: z.number().min(0).optional().describe('Optional incident time as a Unix timestamp in milliseconds, not a block number.'),\n        max_hops: z.number().int().min(1).max(5).optional().describe('Trace depth in hops. Default 3.'),\n        include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n        topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n      }\n    case 'aml_trace_suspect_funds':\n      return {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        suspect_addresses: z.string().min(1).describe('Suspect-controlled addresses, comma-separated. Min 1, max 5.'),\n        incident_timestamp_ms: z.number().min(0).optional().describe('Optional incident time as a Unix timestamp in milliseconds, not a block number.'),\n        max_hops: z.number().int().min(1).max(5).optional().describe('Trace depth in hops. Default 3.'),\n        include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n        topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n      }\n    case 'aml_trace_deposit_sources':\n      return {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        deposit_addresses: z.string().min(1).describe('Suspected deposit or cashout addresses, comma-separated. Min 1, max 5.'),\n        max_hops: z.number().int().min(1).max(5).optional().describe('Reverse trace depth in hops. Default 2.'),\n        include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n        topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n      }\n    case 'graph_query':\n      return {\n        query: z.string().min(1).describe('Read-only GQL/Cypher query. Use USE live_topology for recent topology, USE archive_topology for historical topology, and USE facts for labels, features, risk scores, assets, and enrichment.'),\n        network: BITTENSOR_NETWORK_SCHEMA,\n      }\n    case 'graph_query_batch':\n      return {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        queries: z.array(z.object({\n          id: z.string().optional(),\n          query: z.string().min(1).describe('Read-only GQL/Cypher query'),\n        })).min(1).max(20),\n        per_query_timeout_seconds: z.number().int().min(1).max(600).optional(),\n      }\n    default:\n      return null\n  }\n}\n\nfunction fallbackGraphPrimitiveTools(): McpTool[] {\n  return FALLBACK_GRAPH_PRIMITIVE_TOOL_NAMES.map((name) => ({\n    name,\n    description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS[name],\n  }))\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction redactLogValue(value: unknown): unknown {\n  if (Array.isArray(value)) return value.map(redactLogValue)\n  if (!isRecord(value)) return value\n  return Object.fromEntries(Object.entries(value).map(([key, entry]) => {\n    if (/token|secret|password|private.?key|authorization/i.test(key)) return [key, '[redacted]']\n    return [key, redactLogValue(entry)]\n  }))\n}\n\nfunction errorForLog(err: unknown): Record<string, unknown> {\n  const error = err as Error\n  return {\n    name: error.name ?? 'Error',\n    message: error.message ?? String(err),\n  }\n}\n\nfunction sanitizeCypher(query: string): string {\n  return query.replace(/\\s+/g, ' ').trim()\n}\n\nfunction cypherLogPayload(tool: string, args: unknown): Record<string, unknown> | null {\n  if (!isRecord(args)) return null\n  if (tool === 'graph_query') {\n    return {\n      network: args.network,\n      queries: [{\n        id: tool,\n        query: typeof args.query === 'string' ? sanitizeCypher(args.query) : args.query,\n      }],\n    }\n  }\n  if (tool === 'graph_query_batch') {\n    const queries = Array.isArray(args.queries) ? args.queries : []\n    return {\n      network: args.network,\n      per_query_timeout_seconds: args.per_query_timeout_seconds,\n      query_count: queries.length,\n      queries: queries.map((entry, index) => isRecord(entry)\n        ? {\n            id: typeof entry.id === 'string' ? entry.id : `q${index + 1}`,\n            query: typeof entry.query === 'string' ? sanitizeCypher(entry.query) : entry.query,\n          }\n        : { id: `q${index + 1}`, query: entry }),\n    }\n  }\n  return null\n}\n\nfunction createMcpLogger(config: Pick<InvestigatorConfig, 'dataDir'>) {\n  const disabled = process.env.CHAIN_INSIGHTS_MCP_LOG === '0'\n  const filePath = process.env.CHAIN_INSIGHTS_MCP_LOG_PATH?.trim() || path.join(config.dataDir, '.chain-insights', 'runtime', 'logs', 'mcp-proxy.jsonl')\n\n  async function write(level: 'info' | 'error', event: string, fields: Record<string, unknown> = {}): Promise<void> {\n    if (disabled) return\n    try {\n      await mkdir(path.dirname(filePath), { recursive: true })\n      await appendFile(filePath, JSON.stringify({\n        ts: new Date().toISOString(),\n        level,\n        event,\n        pid: process.pid,\n        ...fields,\n      }) + '\\n', { mode: 0o600 })\n    } catch {\n      // Logging must never break the stdio MCP server.\n    }\n  }\n\n  return {\n    filePath,\n    info: (event: string, fields?: Record<string, unknown>) => write('info', event, fields),\n    error: (event: string, fields?: Record<string, unknown>) => write('error', event, fields),\n  }\n}\n\nfunction installToolLogging(server: McpServer, logger: ReturnType<typeof createMcpLogger>): void {\n  const existingRegisterTool = server.registerTool\n  const originalRegisterTool = existingRegisterTool.bind(server)\n  const wrappedRegisterTool = ((name: string, config: ToolRegistrationConfig, handler: ToolHandler) => {\n    const wrapped: ToolHandler = async (args, extra) => {\n      const startedAt = Date.now()\n      await logger.info('tool.start', {\n        tool: name,\n        args: redactLogValue(args),\n      })\n      try {\n        const result = await handler(args, extra)\n        const isError = isRecord(result) && result.isError === true\n        await logger.info('tool.end', {\n          tool: name,\n          duration_ms: Date.now() - startedAt,\n          is_error: isError,\n        })\n        return result\n      } catch (err) {\n        await logger.error('tool.throw', {\n          tool: name,\n          duration_ms: Date.now() - startedAt,\n          error: errorForLog(err),\n        })\n        throw err\n      }\n    }\n    return originalRegisterTool(name, config, wrapped as never)\n  }) as typeof server.registerTool\n  Object.assign(wrappedRegisterTool, existingRegisterTool)\n  server.registerTool = wrappedRegisterTool\n}\n\nfunction installRemoteCypherLogging(remoteClient: RemoteToolCaller, logger: ReturnType<typeof createMcpLogger>): void {\n  const existingCallTool = remoteClient.callTool\n  const originalCallTool = existingCallTool.bind(remoteClient)\n  const wrappedCallTool = (async (...args: Parameters<Client['callTool']>) => {\n    const input = args[0] as ToolCallInput\n    const queryPayload = cypherLogPayload(input.name, input.arguments)\n    const startedAt = Date.now()\n    if (queryPayload) {\n      await logger.info('topology.start', {\n        tool: input.name,\n        ...queryPayload,\n      })\n    }\n    try {\n      const result = await originalCallTool(...args)\n      if (queryPayload) {\n        await logger.info('topology.end', {\n          tool: input.name,\n          duration_ms: Date.now() - startedAt,\n          is_error: isRecord(result) && result.isError === true,\n        })\n      }\n      return result\n    } catch (err) {\n      if (queryPayload) {\n        await logger.error('cypher.throw', {\n          tool: input.name,\n          duration_ms: Date.now() - startedAt,\n          error: errorForLog(err),\n        })\n      }\n      throw err\n    }\n  }) as typeof remoteClient.callTool\n  Object.assign(wrappedCallTool, existingCallTool)\n  remoteClient.callTool = wrappedCallTool\n}\n\nfunction remoteToolRequestOptions(toolName: string): Parameters<Client['callTool']>[2] | undefined {\n  if (toolName === 'graph_query' || toolName === 'graph_query_batch') {\n    return {\n      timeout: REMOTE_GRAPH_TOOL_REQUEST_TIMEOUT_MS,\n      maxTotalTimeout: REMOTE_GRAPH_TOOL_REQUEST_TIMEOUT_MS,\n    }\n  }\n  return undefined\n}\n\nfunction isBlankArgument(value: unknown): boolean {\n  if (value === undefined || value === null) return true\n  if (typeof value === 'string') return value.trim() === ''\n  if (Array.isArray(value)) return value.length === 0 || value.every(isBlankArgument)\n  return false\n}\n\nfunction normalizeRemoteToolArguments(toolName: string, args: unknown): Record<string, unknown> {\n  const normalized = isRecord(args) ? { ...args } : {}\n  if (!(toolName in PUBLIC_MCP_TOOL_REQUIRED_ARGS)) return normalized\n\n  for (const fieldName of COMMA_SEPARATED_ADDRESS_FIELDS) {\n    const value = normalized[fieldName]\n    if (Array.isArray(value)) {\n      normalized[fieldName] = value\n        .map((entry) => String(entry).trim())\n        .filter(Boolean)\n        .join(',')\n    }\n  }\n\n  const allowedArgs = PUBLIC_MCP_TOOL_ALLOWED_ARGS[toolName]\n  if (!allowedArgs) return normalized\n  return Object.fromEntries(Object.entries(normalized).filter(([key]) => allowedArgs.includes(key)))\n}\n\nfunction validateKnownPublicToolArguments(\n  toolName: string,\n  args: Record<string, unknown>,\n): string | null {\n  const requiredArgs = PUBLIC_MCP_TOOL_REQUIRED_ARGS[toolName]\n  if (!requiredArgs) return null\n\n  for (const argName of requiredArgs) {\n    if (isBlankArgument(args[argName])) {\n      return `Missing required argument: ${argName}`\n    }\n  }\n\n  return null\n}\n\nfunction claudeFacingToolDescription(tool: McpTool): string {\n  const baseDescription = KNOWN_PUBLIC_TOOL_DESCRIPTIONS[tool.name] ?? tool.description ?? tool.name\n  const requiredArgs = PUBLIC_MCP_TOOL_REQUIRED_ARGS[tool.name]\n  if (!requiredArgs) return baseDescription\n  return [\n    baseDescription,\n    '',\n    `Required arguments: ${requiredArgs.join(', ')}.`,\n    'If the user did not provide the network, ask for it before calling this tool. Do not guess a default network.',\n  ].join('\\n')\n}\n\nfunction knownPublicToolAnnotations(toolName: string): Record<string, boolean> | undefined {\n  if (\n    toolName === 'graph_query' ||\n    toolName === 'graph_query_batch' ||\n    toolName.startsWith('aml_')\n  ) {\n    return {\n      readOnlyHint: true,\n      destructiveHint: false,\n      idempotentHint: true,\n      openWorldHint: true,\n    }\n  }\n  return undefined\n}\n\ntype RemoteToolResult = {\n  content?: ContentBlock[]\n  structuredContent?: Record<string, unknown>\n  _meta?: Record<string, unknown>\n  isError?: boolean\n}\n\nfunction promptResult(text: string, description?: string): GetPromptResult {\n  return {\n    description,\n    messages: [\n      {\n        role: 'user',\n        content: {\n          type: 'text',\n          text,\n        },\n      },\n    ],\n  }\n}\n\nfunction registerLocalPrompts(server: McpServer): void {\n  server.registerPrompt(\n    'aml-address-risk',\n    {\n      title: 'AML Address Risk',\n      description: 'Screen a blockchain address for AML risk, behavioral patterns, neighborhood profile, member addresses, and exchange links.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        address: z.string().describe('Blockchain address to screen'),\n        compare_address: z.string().optional().describe('Optional address to compare against the screened address'),\n      },\n    },\n    async ({ network, address, compare_address }) => promptResult(\n      [\n        `Use Chain Insights aml_address_risk on ${network} for:`,\n        '',\n        `\\`${address}\\``,\n        compare_address ? `\\nCompare with: \\`${compare_address}\\`` : '',\n        '',\n        'Present the summary as-is. Do not add analysis, verdicts, or risk assessments; the tool output already contains the risk assessment.',\n      ].filter(Boolean).join('\\n'),\n      'AML address risk screening',\n    ),\n  )\n\n  server.registerPrompt(\n    'aml-trace-victim-funds',\n    {\n      title: 'AML Trace Victim Funds',\n      description: 'Trace victim or trusted-source funds forward to deposit candidates.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        victim_addresses: z.string().describe('Victim/source addresses, comma-separated'),\n        known_suspect_addresses: z.string().optional().describe('Optional known suspect addresses for context only'),\n      },\n    },\n    async ({ network, victim_addresses, known_suspect_addresses }) => promptResult([\n      `Use Chain Insights aml_trace_victim_funds on ${network}.`,\n      '',\n      'Victim/source addresses:',\n      victim_addresses,\n      known_suspect_addresses ? `\\nKnown suspects for context only:\\n${known_suspect_addresses}` : '',\n      '',\n      'Present the summary as-is and use continuation.recommended_next_tools for follow-up.',\n    ].filter(Boolean).join('\\n'), 'AML victim/source trace'),\n  )\n\n  server.registerPrompt(\n    'aml-trace-suspect-funds',\n    {\n      title: 'AML Trace Suspect Funds',\n      description: 'Trace suspect-controlled funds forward to cashout topology.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        suspect_addresses: z.string().describe('Suspect-controlled addresses, comma-separated'),\n      },\n    },\n    async ({ network, suspect_addresses }) => promptResult([\n      `Use Chain Insights aml_trace_suspect_funds on ${network}.`,\n      '',\n      'Suspect-controlled addresses:',\n      suspect_addresses,\n      '',\n      'Present the summary as-is and use continuation.recommended_next_tools for follow-up.',\n    ].join('\\n'), 'AML suspect trace'),\n  )\n\n  server.registerPrompt(\n    'aml-trace-deposit-sources',\n    {\n      title: 'AML Trace Deposit Sources',\n      description: 'Trace suspected deposit or cashout addresses backward to upstream sources.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        deposit_addresses: z.string().describe('Suspected deposit/cashout addresses, comma-separated'),\n      },\n    },\n    async ({ network, deposit_addresses }) => promptResult([\n      `Use Chain Insights aml_trace_deposit_sources on ${network}.`,\n      '',\n      'Suspected deposit/cashout addresses:',\n      deposit_addresses,\n      '',\n      'Present the summary as-is and use continuation.recommended_next_tools for follow-up.',\n    ].join('\\n'), 'AML deposit-source trace'),\n  )\n\n  server.registerPrompt(\n    'meta-network-capabilities',\n    {\n      title: 'Network Capabilities',\n      description: 'Inspect supported networks and available tools before selecting a network.',\n      argsSchema: {},\n    },\n    async () => promptResult(\n      'Use Chain Insights meta_network_capabilities. Report only the supported networks and available tools exactly as returned; do not infer unsupported networks.',\n      'Network capabilities',\n    ),\n  )\n\n  server.registerPrompt(\n    'meta-usage-status',\n    {\n      title: 'Usage Status',\n      description: \"Check the caller's public free graph_query quota.\",\n      argsSchema: {},\n    },\n    async () => promptResult(\n      'Use Chain Insights meta_usage_status. Report the quota fields exactly as returned.',\n      'Usage status',\n    ),\n  )\n\n  server.registerPrompt(\n    'graph-query',\n    {\n      title: 'Graph Query',\n      description: 'Run a read-only GQL/Cypher query through the Chain Insights graph endpoint.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        query: z.string().describe('Read-only GQL/Cypher query'),\n      },\n    },\n    async ({ network, query }) => promptResult(\n      [\n        `Use Chain Insights graph_query on ${network} with this read-only GQL/Cypher query:`,\n        '',\n        '```gql',\n        query,\n        '```',\n        '',\n        'Use USE live_topology for recent topology, USE archive_topology for historical topology, and USE facts for labels, features, risk scores, assets, and enrichment. If you need schema context, first run small discovery queries such as MATCH (i:Identity) RETURN i.identity_id AS identity_id, keys(i) AS identity_properties LIMIT 5 and MATCH (:Identity)-[r:FLOWS_TO]->(:Identity) RETURN keys(r) AS flow_properties LIMIT 5. Return identity_id and member addresses when available; never shorten addresses with ellipses.',\n      ].join('\\n'),\n      'Graph query',\n    ),\n  )\n\n  server.registerPrompt(\n    'graph-query-batch',\n    {\n      title: 'Graph Query Batch',\n      description: 'Run related read-only GQL/Cypher queries through the Chain Insights graph endpoint in one paid batch.',\n      argsSchema: {\n        network: BITTENSOR_NETWORK_SCHEMA,\n        queries: z.string().describe('JSON array of query objects with optional id and required query fields'),\n        per_query_timeout_seconds: z.string().optional().describe('Optional integer timeout per query, 1-600 seconds'),\n      },\n    },\n    async ({ network, queries, per_query_timeout_seconds }) => promptResult(\n      [\n        `Use Chain Insights graph_query_batch on ${network} with these read-only GQL/Cypher queries:`,\n        '',\n        '```json',\n        queries,\n        '```',\n        per_query_timeout_seconds ? `per_query_timeout_seconds: ${per_query_timeout_seconds}` : '',\n        '',\n        'Use USE live_topology for recent topology, USE archive_topology for historical topology, and USE facts for labels, features, risk scores, assets, and enrichment. If you need schema context, first run small discovery queries such as MATCH (i:Identity) RETURN i.identity_id AS identity_id, keys(i) AS identity_properties LIMIT 5 and MATCH (:Identity)-[r:FLOWS_TO]->(:Identity) RETURN keys(r) AS flow_properties LIMIT 5. Return identity_id and member addresses when available; never shorten addresses with ellipses.',\n      ].filter(Boolean).join('\\n'),\n      'Graph query batch',\n    ),\n  )\n\n  server.registerPrompt(\n    'wallet-balance',\n    {\n      title: 'Wallet Balance',\n      description: 'Show the local Chain Insights payment wallet address, payment network, token, and amount.',\n      argsSchema: {},\n    },\n    async () => promptResult(\n      'Use Chain Insights wallet_balance. Show the wallet address, payment network, token, and amount exactly as returned.',\n      'Wallet balance',\n    ),\n  )\n\n  server.registerPrompt(\n    'meta-help',\n    {\n      title: 'Chain Insights Help',\n      description: 'Show available Chain Insights tools and workspace workflow.',\n      argsSchema: {},\n    },\n    async () => promptResult(\n      'Use Chain Insights meta_help. Summarize the available tools and workspace workflow without inventing capabilities.',\n      'Chain Insights help',\n    ),\n  )\n\n\n}\n\nfunction hasGraphArrayFields(value: unknown): boolean {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n  const record = value as Record<string, unknown>\n  return GRAPH_ARRAY_KEYS.some((key) => Array.isArray(record[key]))\n}\n\nfunction sanitizeStructuredContentForGraphPayload(\n  structuredContent: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n  if (!structuredContent) return undefined\n  return sanitizeStructuredValue(structuredContent) as Record<string, unknown>\n}\n\nfunction sanitizeStructuredValue(value: unknown): unknown {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) return value\n\n  const sanitized: Record<string, unknown> = {}\n  for (const [key, childValue] of Object.entries(value)) {\n    if (key === 'app_data') continue\n    if (GRAPH_ARRAY_KEYS.includes(key as (typeof GRAPH_ARRAY_KEYS)[number]) && Array.isArray(childValue)) {\n      continue\n    }\n    sanitized[key] = sanitizeStructuredValue(childValue)\n  }\n\n  return sanitized\n}\n\nfunction getRemoteGraphPayload(result: RemoteToolResult): Record<string, unknown> | null {\n  const chainInsights = result._meta?.chainInsights\n  if (!chainInsights || typeof chainInsights !== 'object' || Array.isArray(chainInsights)) return null\n  const graph = (chainInsights as Record<string, unknown>).graph\n  if (graph === undefined) return null\n  if (!graph || typeof graph !== 'object' || Array.isArray(graph)) {\n    throw new Error('Invalid remote graph payload')\n  }\n\n  const graphRecord = graph as Record<string, unknown>\n  if (!('data' in graphRecord)) {\n    if ('url' in graphRecord || hasGraphArrayFields(graphRecord)) {\n      throw new Error('Invalid remote graph payload')\n    }\n    return null\n  }\n\n  const data = graphRecord.data\n  if (!data || typeof data !== 'object' || Array.isArray(data)) {\n    throw new Error('Invalid remote graph payload')\n  }\n\n  return data as Record<string, unknown>\n}\n\nasync function normalizeRemoteToolResult(\n  result: RemoteToolResult,\n  config: Pick<InvestigatorConfig, 'dataDir' | 'serverPort'>,\n  toolName = 'remote-graph',\n  includeAttachments = true,\n) {\n  const graphPayload = getRemoteGraphPayload(result)\n  const meta = { ...(result._meta ?? {}) }\n\n  if (graphPayload && includeAttachments) {\n    const { writeGraphReport } = await import('./graph-reports.js')\n    const { ensureArtifactServer } = await import('./artifact-server.js')\n    const report = await writeGraphReport(graphPayload as never, {\n      serverPort: config.serverPort,\n      slug: toolName || 'remote-graph',\n    })\n    await ensureArtifactServer(config.serverPort)\n    meta.chainInsights = {\n      ...((meta.chainInsights as Record<string, unknown>) ?? {}),\n      graph: {\n        schema: report.schema,\n        url: report.url,\n      },\n    }\n  }\n\n  return {\n    content: result.content ?? [],\n    structuredContent: sanitizeStructuredContentForGraphPayload(result.structuredContent),\n    _meta: Object.keys(meta).length > 0 ? meta : undefined,\n    isError: result.isError,\n  }\n}\n\nfunction shouldIncludeAttachments(args: Record<string, unknown>, workspaceArtifactsEnabled: boolean): boolean {\n  return workspaceArtifactsEnabled && args['include_attachments'] !== false\n}\n\nasync function writeLocalGraphMeta(\n  graphData: unknown,\n  config: Pick<InvestigatorConfig, 'dataDir' | 'serverPort'>,\n  slug: string,\n  includeAttachments: boolean,\n): Promise<ChainInsightsGraphMeta | undefined> {\n  if (!includeAttachments) return undefined\n  const { writeGraphReport } = await import('./graph-reports.js')\n  const { ensureArtifactServer } = await import('./artifact-server.js')\n  const report = await writeGraphReport(graphData as never, {\n    serverPort: config.serverPort,\n    slug,\n  })\n  await ensureArtifactServer(config.serverPort)\n  return {\n    schema: report.schema,\n    url: report.url,\n  }\n}\n\nfunction graphMetaResult(graph: ChainInsightsGraphMeta | undefined): Record<string, unknown> | undefined {\n  return graph\n    ? {\n        chainInsights: {\n          graph,\n        },\n      }\n    : undefined\n}\n\nfunction cleanCapabilityLayers(value: unknown): Record<string, unknown> {\n  const layers = isRecord(value) ? value : {}\n  const topologySource = isRecord(layers.topology) ? layers.topology : {}\n  const topology: Record<string, unknown> = {\n    enabled: isRecord(layers.topology) ? topologySource.enabled === true : true,\n  }\n  if (isRecord(topologySource.live)) topology.live = topologySource.live\n  if (isRecord(topologySource.archive)) topology.archive = topologySource.archive\n  return {\n    facts: { enabled: isRecord(layers.facts) ? layers.facts.enabled === true : true },\n    risk: { enabled: isRecord(layers.risk) ? layers.risk.enabled === true : false },\n    topology,\n  }\n}\n\nfunction defaultBittensorCapability() {\n  return {\n    network: 'bittensor',\n    display_name: 'Bittensor',\n    status: 'live',\n    default: true,\n    layers: {\n      facts: { enabled: true },\n      risk: { enabled: false },\n      topology: { enabled: true, live: { enabled: true }, archive: { enabled: true } },\n    },\n    tools: {\n      graph_query: 'available',\n      graph_query_batch: 'available',\n    },\n  }\n}\n\nfunction cleanNetworkCapabilities(value: unknown) {\n  const structuredContent = isRecord(value) ? value.structuredContent : undefined\n  const facts = isRecord(structuredContent) ? structuredContent.facts : undefined\n  const capabilities = isRecord(facts) ? facts.capabilities : undefined\n  const networks = isRecord(capabilities) && Array.isArray(capabilities.networks)\n    ? capabilities.networks\n    : []\n  const bittensor = networks.find((network): network is Record<string, unknown> => (\n    isRecord(network) && network.network === 'bittensor'\n  ))\n\n  const cleaned = bittensor\n    ? {\n        network: 'bittensor',\n        display_name: typeof bittensor.display_name === 'string' ? bittensor.display_name : 'Bittensor',\n        status: typeof bittensor.status === 'string' ? bittensor.status : 'live',\n        default: bittensor.default === false ? false : true,\n        layers: cleanCapabilityLayers(bittensor.layers),\n        tools: {\n          graph_query: 'available',\n          graph_query_batch: 'available',\n        },\n      }\n    : defaultBittensorCapability()\n\n  return {\n    schema: 'chain-insights.result.v1' as const,\n    tool: 'meta_network_capabilities',\n    hint: null,\n    facts: {\n      capabilities: {\n        schema: 'chain-insights.network-capabilities.v1' as const,\n        networks: [cleaned],\n      },\n    },\n  }\n}\n\nfunction jsonTextResult(structuredContent: Record<string, unknown>) {\n  return {\n    content: [{ type: 'text' as const, text: JSON.stringify(structuredContent, null, 2) }],\n    structuredContent,\n    isError: false,\n  }\n}\n\n/**\n * Core proxy logic — exported so tests can inject dependencies directly.\n * The IIFE at the bottom calls this with real dependencies.\n *\n * stdout purity: NEVER write to stdout in this file. Use console.error() or process.stderr.write() only.\n * All diagnostic output goes to console.error() or process.stderr.write().\n */\nexport async function createProxy(): Promise<void> {\n  // Lazy imports to avoid module-load side effects (critical for stdio proxy)\n  const { loadConfig } = await import('../config/index.js')\n  const { activeDataDir, findActiveWorkspace } = await import('../workspace/active.js')\n  const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await import('./client.js')\n  const { loadSchema, saveSchema } = await import('./schema-cache.js')\n\n  const proxyMode = resolveMcpProxyMode()\n  const workspaceArtifactsEnabled = proxyMode === 'workspace'\n  const loadedConfig = await loadConfig()\n  const activeWorkspace = workspaceArtifactsEnabled ? findActiveWorkspace() : null\n  const config = {\n    ...loadedConfig,\n    dataDir: workspaceArtifactsEnabled ? activeDataDir(loadedConfig.dataDir) : loadedConfig.dataDir,\n  }\n  const logger = createMcpLogger(config)\n  await logger.info('proxy.start', {\n    data_dir: config.dataDir,\n    workspace_root: activeWorkspace?.root,\n    proxy_mode: proxyMode,\n    graph_mcp_mode: config.graphMcpMode,\n    graph_mcp_endpoint: resolveGraphMcpEndpoint(config),\n    log_path: logger.filePath,\n  })\n  const graphMcpEndpoint = resolveGraphMcpEndpoint(config)\n\n  // Build remote MCP client. The local Chain Insights MCP surface must still\n  // start when the graph endpoint is temporarily unavailable so agents can use\n  // help and wallet tools.\n  const remoteClient = new Client({ name: 'chain-insights-proxy-client', version: PACKAGE_VERSION })\n  let remoteConnected = false\n  let remoteUnavailableMessage: string | undefined\n  let mcpFetch: typeof fetch | undefined\n\n  try {\n    mcpFetch = await createConfiguredGraphMcpFetch(config)\n  } catch (err) {\n    await logger.error('remote.fetch_setup_failed', {\n      endpoint: graphMcpEndpoint,\n      error: errorForLog(err),\n    })\n    remoteUnavailableMessage = `Chain Insights Graph setup unavailable at ${graphMcpEndpoint}: ${(err as Error).message}`\n    process.stderr.write(\n      `Chain Insights MCP graph tools unavailable: ${remoteUnavailableMessage}. Local Chain Insights tools are still available.\\n`,\n    )\n  }\n\n  if (mcpFetch) {\n    try {\n      await remoteClient.connect(\n        new StreamableHTTPClientTransport(new URL(graphMcpEndpoint), { fetch: mcpFetch }),\n      )\n      remoteConnected = true\n      await logger.info('remote.connect', {\n        transport: 'streamable_http',\n        endpoint: graphMcpEndpoint,\n      })\n    } catch {\n      await logger.error('remote.connect_failed', {\n        transport: 'streamable_http',\n        endpoint: graphMcpEndpoint,\n      })\n      // StreamableHTTP failed — try SSE fallback (assumption A1 from RESEARCH.md)\n      try {\n        const { SSEClientTransport } = await import('@modelcontextprotocol/sdk/client/sse.js')\n        await remoteClient.connect(\n          new SSEClientTransport(new URL(graphMcpEndpoint), { fetch: mcpFetch }),\n        )\n        remoteConnected = true\n        await logger.info('remote.connect', {\n          transport: 'sse',\n          endpoint: graphMcpEndpoint,\n        })\n      } catch (err2) {\n        await logger.error('remote.connect_failed', {\n          transport: 'sse',\n          endpoint: graphMcpEndpoint,\n          error: errorForLog(err2),\n        })\n        remoteUnavailableMessage = `Chain Insights Graph unreachable at ${graphMcpEndpoint}: ${(err2 as Error).message}`\n        process.stderr.write(\n          `Chain Insights MCP graph tools unavailable: ${remoteUnavailableMessage}. Local Chain Insights tools are still available.\\n`,\n        )\n      }\n    }\n  }\n  if (remoteConnected) installRemoteCypherLogging(remoteClient as unknown as RemoteToolCaller, logger)\n\n  // Schema cache check — skip remote listTools call on cache hit\n  let tools: McpTool[] | null = await loadSchema(graphMcpEndpoint)\n\n  if (!tools && remoteConnected) {\n    // Cache miss — fetch tools from remote (client is already connected above)\n    const result = await remoteClient.listTools()\n    tools = result.tools as McpTool[]\n    await saveSchema(tools, graphMcpEndpoint)\n    await logger.info('schema.tools_loaded', {\n      source: 'remote',\n      count: tools.length,\n    })\n  } else if (tools) {\n    await logger.info('schema.tools_loaded', {\n      source: 'cache',\n      count: tools.length,\n    })\n  } else {\n    tools = fallbackGraphPrimitiveTools()\n    await logger.info('schema.tools_loaded', {\n      source: 'unavailable',\n      count: tools.length,\n    })\n  }\n  const remoteToolNames = new Set((tools ?? []).map((tool) => tool.name))\n\n  // Build local stdio proxy server\n  const server = new McpServer(\n    { name: 'chain-insights', version: PACKAGE_VERSION },\n    { instructions: workspaceArtifactsEnabled ? SERVER_INSTRUCTIONS : STATELESS_SERVER_INSTRUCTIONS },\n  )\n  installToolLogging(server, logger)\n\n  if (remoteConnected) {\n    try {\n      await remoteClient.listPrompts()\n    } catch (err) {\n      await logger.error('remote.prompts_failed', {\n        endpoint: graphMcpEndpoint,\n        error: errorForLog(err),\n      })\n      process.stderr.write(\n        `Chain Insights MCP remote prompt metadata unavailable at ${graphMcpEndpoint}: ${(err as Error).message}\\n`,\n      )\n    }\n  }\n\n  registerLocalPrompts(server)\n\n  const caseToolError = (label: string, err: unknown) => ({\n    content: [{ type: 'text' as const, text: `${label} failed: ${(err as Error).message}` }],\n    isError: true,\n  })\n\n  const parseTags = (tags: string | string[] | undefined): string[] => {\n    if (Array.isArray(tags)) return tags.map((tag) => tag.trim()).filter(Boolean)\n    if (typeof tags === 'string') return tags.split(',').map((tag) => tag.trim()).filter(Boolean)\n    return []\n  }\n\n  server.registerTool(\n    'meta_network_capabilities',\n    {\n      title: 'Network Capabilities',\n      description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.meta_network_capabilities,\n      inputSchema: EMPTY_INPUT_SCHEMA,\n      annotations: {\n        readOnlyHint: true,\n        destructiveHint: false,\n        idempotentHint: true,\n        openWorldHint: false,\n      },\n    },\n    async () => {\n      if (remoteConnected && remoteToolNames.has('network_capabilities')) {\n        try {\n          const result = await remoteClient.callTool({ name: 'network_capabilities', arguments: {} })\n          return jsonTextResult(cleanNetworkCapabilities(result))\n        } catch (err) {\n          return {\n            content: [{ type: 'text' as const, text: `Network capabilities failed: ${(err as Error).message}` }],\n            isError: true,\n          }\n        }\n      }\n      return jsonTextResult(cleanNetworkCapabilities(undefined))\n    },\n  )\n\n  server.registerTool(\n    'meta_usage_status',\n    {\n      title: 'Usage Status',\n      description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.meta_usage_status,\n      inputSchema: EMPTY_INPUT_SCHEMA,\n      annotations: {\n        readOnlyHint: true,\n        destructiveHint: false,\n        idempotentHint: true,\n        openWorldHint: true,\n      },\n    },\n    async () => {\n      try {\n        if (!remoteConnected) {\n          return {\n            content: [{\n              type: 'text' as const,\n              text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n            }],\n            isError: true,\n          }\n        }\n        if (!remoteToolNames.has('usage_status')) {\n          return jsonTextResult(primitiveBackendUsageStatus(graphMcpEndpoint))\n        }\n        const result = await remoteClient.callTool({ name: 'usage_status', arguments: {} }) as RemoteToolResult\n        const structuredContent = isRecord(result.structuredContent)\n          ? { ...result.structuredContent, tool: 'meta_usage_status' }\n          : undefined\n        return {\n          content: structuredContent\n            ? [{ type: 'text' as const, text: JSON.stringify(structuredContent, null, 2) }]\n            : result.content ?? [],\n          structuredContent,\n          _meta: result._meta,\n          isError: result.isError,\n        }\n      } catch (err) {\n        return {\n          content: [{ type: 'text' as const, text: `Usage status failed: ${(err as Error).message}` }],\n          isError: true,\n        }\n      }\n    },\n  )\n\n  if (workspaceArtifactsEnabled) {\n  server.registerTool(\n    'wallet_balance',\n    {\n      title: 'Wallet Balance',\n      description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.wallet_balance,\n      inputSchema: EMPTY_INPUT_SCHEMA,\n      annotations: {\n        readOnlyHint: true,\n        destructiveHint: false,\n        idempotentHint: true,\n        openWorldHint: true,\n      },\n    },\n    async () => {\n      try {\n        const { formatWalletBalanceResult, getWalletAccount, getWalletBalanceResult } = await import('../wallet/tools.js')\n        const account = await getWalletAccount()\n        const structuredContent = await getWalletBalanceResult(account)\n        return {\n          content: [{ type: 'text' as const, text: formatWalletBalanceResult(structuredContent) }],\n          structuredContent: structuredContent as unknown as Record<string, unknown>,\n          isError: false,\n        }\n      } catch (err) {\n        return {\n          content: [{ type: 'text' as const, text: `Balance failed: ${(err as Error).message}` }],\n          isError: true,\n        }\n      }\n    },\n  )\n  }\n  // NOTE: only wallet_balance is workspace-only. Everything below — the graph\n  // app resource, the aml_*/graph tools, and server.connect() — is shared and\n  // MUST run in stateless mode too. (Regression #136: this brace had drifted to\n  // the end of the function, so stateless mode skipped server.connect entirely.)\n\n  registerAppResource(\n    server,\n    'Fund Flow Graph',\n    GRAPH_RESOURCE_URI,\n    {\n      description: 'Interactive fund-flow and pattern graph for Chain Insights investigation reports.',\n      _meta: {\n        ui: {\n          csp: {\n            resourceDomains: graphArtifactOrigins(config),\n            connectDomains: graphArtifactOrigins(config),\n          },\n        },\n      },\n    },\n    async () => ({\n      contents: [\n        {\n          uri: GRAPH_RESOURCE_URI,\n          mimeType: RESOURCE_MIME_TYPE,\n          text: readGraphAppHtml(),\n          _meta: {\n            ui: {\n              csp: {\n                resourceDomains: graphArtifactOrigins(config),\n                connectDomains: graphArtifactOrigins(config),\n              },\n            },\n          },\n        },\n      ],\n    }),\n  )\n\n\n\n  if (!remoteToolNames.has('aml_address_risk')) {\n    registerAppTool(\n      server,\n      'aml_address_risk',\n      {\n        title: 'Address Risk',\n        description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.aml_address_risk,\n        inputSchema: {\n          address: z.string().min(1).describe('Blockchain address to screen'),\n          network: BITTENSOR_NETWORK_SCHEMA,\n          compare_address: z.string().optional().describe('Optional address to compare against the screened address'),\n          include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n          topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n        },\n        _meta: {\n          ui: {\n            resourceUri: GRAPH_RESOURCE_URI,\n          },\n        },\n        annotations: {\n          readOnlyHint: true,\n          destructiveHint: false,\n          idempotentHint: true,\n          openWorldHint: true,\n        },\n      },\n      async ({ address, network, compare_address, include_attachments, topology_scope }) => {\n        try {\n          if (!remoteConnected) {\n            return {\n              content: [{\n                type: 'text' as const,\n                text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n              }],\n              isError: true,\n            }\n          }\n          const { addressRisk } = await import('../investigation/public-tools.js')\n          const result = await addressRisk(remoteClient, {\n            address,\n            network,\n            compareAddress: compare_address,\n            writeArtifacts: workspaceArtifactsEnabled,\n            topologyScope: topology_scope,\n          })\n          const graph = await writeLocalGraphMeta(\n            result.graphData,\n            config,\n            `address-risk-${network}-${address}`,\n            shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled),\n          )\n          return {\n            content: [{ type: 'text' as const, text: result.summaryText }],\n            structuredContent: result.structuredContent,\n            _meta: graphMetaResult(graph),\n            isError: false,\n          }\n        } catch (err) {\n          if (err instanceof PaymentRequiredError) {\n            return { content: [{ type: 'text' as const, text: err.message }], isError: true }\n          }\n          return {\n            content: [{ type: 'text' as const, text: `Address risk failed: ${(err as Error).message}` }],\n            isError: true,\n          }\n        }\n      },\n    )\n  }\n\n  if (!remoteToolNames.has('aml_trace_victim_funds')) {\n    registerAppTool(\n      server,\n      'aml_trace_victim_funds',\n      {\n        title: 'Trace Victim Funds',\n        description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.aml_trace_victim_funds,\n        inputSchema: {\n          victim_addresses: z.union([z.string().min(1), z.array(z.string().min(1))]).describe('Victim or source addresses, comma-separated or an array. Min 1, max 5.'),\n          network: BITTENSOR_NETWORK_SCHEMA,\n          known_suspect_addresses: z.union([z.string(), z.array(z.string())]).optional().describe('Known suspect addresses for context only. Max 5.'),\n          include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n          incident_timestamp_ms: z.number().min(0).optional().describe('Optional incident time as a Unix timestamp in milliseconds, not a block number.'),\n          max_hops: z.number().int().min(1).max(5).optional().describe('Trace depth in hops. Default 3.'),\n          topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n        },\n        _meta: {\n          ui: {\n            resourceUri: GRAPH_RESOURCE_URI,\n          },\n        },\n        annotations: {\n          readOnlyHint: true,\n          destructiveHint: false,\n          idempotentHint: true,\n          openWorldHint: true,\n        },\n      },\n      async ({ victim_addresses, known_suspect_addresses, network, incident_timestamp_ms, max_hops, include_attachments, topology_scope }) => {\n        try {\n          if (!remoteConnected) {\n            return {\n              content: [{\n                type: 'text' as const,\n                text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n              }],\n              isError: true,\n            }\n          }\n          const { traceVictimFunds } = await import('../investigation/public-tools.js')\n          const result = await traceVictimFunds(remoteClient, config, {\n            victimAddresses: victim_addresses,\n            knownSuspectAddresses: known_suspect_addresses,\n            network,\n            incidentTimestampMs: incident_timestamp_ms,\n            maxHops: max_hops,\n            writeArtifacts: workspaceArtifactsEnabled,\n            topologyScope: topology_scope,\n          })\n          const graph = await writeLocalGraphMeta(\n            result.graphData,\n            config,\n            `trace-victim-funds-${network}`,\n            shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled),\n          )\n          return {\n            content: [{ type: 'text' as const, text: result.summaryText }],\n            structuredContent: result.structuredContent,\n            _meta: graphMetaResult(graph),\n            isError: false,\n          }\n        } catch (err) {\n          if (err instanceof PaymentRequiredError) {\n            return { content: [{ type: 'text' as const, text: err.message }], isError: true }\n          }\n          return {\n            content: [{ type: 'text' as const, text: `Trace victim funds failed: ${(err as Error).message}` }],\n            isError: true,\n          }\n        }\n      },\n    )\n  }\n\n  if (!remoteToolNames.has('aml_trace_suspect_funds')) {\n    registerAppTool(\n      server,\n      'aml_trace_suspect_funds',\n      {\n        title: 'Trace Suspect Funds',\n        description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.aml_trace_suspect_funds,\n        inputSchema: {\n          network: BITTENSOR_NETWORK_SCHEMA,\n          suspect_addresses: z.union([z.string().min(1), z.array(z.string().min(1))]).describe('Suspect-controlled addresses, comma-separated or an array. Min 1, max 5.'),\n          incident_timestamp_ms: z.number().min(0).optional().describe('Optional incident time as a Unix timestamp in milliseconds, not a block number.'),\n          max_hops: z.number().int().min(1).max(5).optional().describe('Trace depth in hops. Default 3.'),\n          include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n          topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n        },\n        _meta: {\n          ui: {\n            resourceUri: GRAPH_RESOURCE_URI,\n          },\n        },\n        annotations: {\n          readOnlyHint: true,\n          destructiveHint: false,\n          idempotentHint: true,\n          openWorldHint: true,\n        },\n      },\n      async ({ suspect_addresses, incident_timestamp_ms, network, max_hops, include_attachments, topology_scope }) => {\n        try {\n          if (!remoteConnected) {\n            return {\n              content: [{\n                type: 'text' as const,\n                text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n              }],\n              isError: true,\n            }\n          }\n          const { traceSuspectFunds } = await import('../investigation/public-tools.js')\n          const result = await traceSuspectFunds(remoteClient, config, {\n            suspectAddresses: suspect_addresses,\n            network,\n            maxHops: max_hops,\n            incidentTimestampMs: incident_timestamp_ms,\n            writeArtifacts: workspaceArtifactsEnabled,\n            topologyScope: topology_scope,\n          })\n          const graph = await writeLocalGraphMeta(\n            result.graphData,\n            config,\n            `trace-suspect-funds-${network}`,\n            shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled),\n          )\n          return {\n            content: [{ type: 'text' as const, text: result.summaryText }],\n            structuredContent: result.structuredContent,\n            _meta: graphMetaResult(graph),\n            isError: false,\n          }\n        } catch (err) {\n          if (err instanceof PaymentRequiredError) {\n            return { content: [{ type: 'text' as const, text: err.message }], isError: true }\n          }\n          return {\n            content: [{ type: 'text' as const, text: `Trace suspect funds failed: ${(err as Error).message}` }],\n            isError: true,\n          }\n        }\n      },\n    )\n  }\n\n  if (!remoteToolNames.has('aml_trace_deposit_sources')) {\n    registerAppTool(\n      server,\n      'aml_trace_deposit_sources',\n      {\n        title: 'Trace Deposit Sources',\n        description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.aml_trace_deposit_sources,\n        inputSchema: {\n          network: BITTENSOR_NETWORK_SCHEMA,\n          deposit_addresses: z.union([z.string().min(1), z.array(z.string().min(1))]).describe('Suspected deposit or cashout addresses, comma-separated or an array. Min 1, max 5.'),\n          max_hops: z.number().int().min(1).max(5).optional().describe('Reverse trace depth in hops. Default 2.'),\n          include_attachments: z.boolean().optional().describe('Include graph app report metadata'),\n          topology_scope: TOPOLOGY_SCOPE_SCHEMA,\n        },\n        _meta: {\n          ui: {\n            resourceUri: GRAPH_RESOURCE_URI,\n          },\n        },\n        annotations: {\n          readOnlyHint: true,\n          destructiveHint: false,\n          idempotentHint: true,\n          openWorldHint: true,\n        },\n      },\n      async ({ deposit_addresses, network, max_hops, include_attachments, topology_scope }) => {\n        try {\n          if (!remoteConnected) {\n            return {\n              content: [{\n                type: 'text' as const,\n                text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n              }],\n              isError: true,\n            }\n          }\n          const { traceDepositSources } = await import('../investigation/public-tools.js')\n          const result = await traceDepositSources(remoteClient, config, {\n            depositAddresses: deposit_addresses,\n            network,\n            maxHops: max_hops,\n            writeArtifacts: workspaceArtifactsEnabled,\n            topologyScope: topology_scope,\n          })\n          const graph = await writeLocalGraphMeta(\n            result.graphData,\n            config,\n            `trace-deposit-sources-${network}`,\n            shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled),\n          )\n          return {\n            content: [{ type: 'text' as const, text: result.summaryText }],\n            structuredContent: result.structuredContent,\n            _meta: graphMetaResult(graph),\n            isError: false,\n          }\n        } catch (err) {\n          if (err instanceof PaymentRequiredError) {\n            return { content: [{ type: 'text' as const, text: err.message }], isError: true }\n          }\n          return {\n            content: [{ type: 'text' as const, text: `Trace deposit sources failed: ${(err as Error).message}` }],\n            isError: true,\n          }\n        }\n      },\n    )\n  }\n\n  server.registerTool(\n    'meta_help',\n    {\n      title: 'Chain Insights Help',\n      description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.meta_help,\n      inputSchema: EMPTY_INPUT_SCHEMA,\n      annotations: {\n        readOnlyHint: true,\n        destructiveHint: false,\n        idempotentHint: true,\n        openWorldHint: false,\n      },\n    },\n    async () => ({\n      content: [\n        {\n          type: 'text' as const,\n          text: workspaceArtifactsEnabled\n            ? [\n                'Chain Insights helps AI agents run AML investigation workflows and keep evidence in local workspace files.',\n                '',\n                CHAIN_INSIGHTS_WORKFLOW,\n                '',\n                'Investigation tools:',\n                '- meta_network_capabilities: inspect supported networks and available tools.',\n                '- meta_usage_status: check the caller public free graph_query quota.',\n                '- aml_address_risk: screen one blockchain address; optionally compare it with another address.',\n                '- aml_trace_victim_funds: trace up to five victim/source addresses forward to exchange deposit candidates.',\n                '- aml_trace_deposit_sources: trace backward from suspected deposit/cashout addresses to upstream funders and shared-source convergence.',\n                '- aml_trace_suspect_funds: trace up to five suspected scammer, mule, operator, or laundering-ring addresses forward to cashout topology.',\n                '- graph_query: run read-only GQL/Cypher through the universal graph endpoint. Use USE live_topology, USE archive_topology, or USE facts.',\n                '- graph_query_batch: run related read-only graph-language queries through one paid graph call.',\n                '',\n                'Wallet tools:',\n                '- wallet_balance: show the local payment wallet address, payment network, token, and amount.',\n                '- meta_help: show this overview.',\n                '',\n                GRAPH_REPORT_HINTS,\n              ].join('\\n')\n            : [\n                'Chain Insights stateless AML proxy for host applications.',\n                '',\n                'Local workspace persistence, wallet, and graph report attachment tools are disabled in this mode.',\n                '',\n                'Available graph-backed tools:',\n                '- meta_network_capabilities: inspect supported networks and available tools.',\n                '- meta_usage_status: check the caller public free graph_query quota.',\n                '- aml_address_risk: screen one blockchain address; optionally compare it with another address.',\n                '- aml_trace_victim_funds: trace up to five victim/source addresses forward to exchange deposit candidates.',\n                '- aml_trace_deposit_sources: trace backward from suspected deposit/cashout addresses to upstream funders and shared-source convergence.',\n                '- aml_trace_suspect_funds: trace up to five suspected scammer, mule, operator, or laundering-ring addresses forward to cashout topology.',\n                '- graph_query: run read-only GQL/Cypher through the universal graph endpoint. Use USE live_topology, USE archive_topology, or USE facts.',\n                '- graph_query_batch: run related read-only graph-language queries through one paid graph call.',\n              ].join('\\n'),\n        },\n      ],\n      isError: false,\n    }),\n  )\n\n  // Register each remote tool locally — passthrough proxy pattern\n  for (const tool of tools ?? []) {\n    if (HIDDEN_REMOTE_TOOL_NAMES.has(tool.name)) continue\n    if (LOCAL_TOOL_NAMES.has(tool.name)) continue\n    const inputSchema = knownPublicToolInputSchema(tool.name) ?? z.object({}).passthrough()\n    const handler = async (args: unknown) => {\n      try {\n        if (!remoteConnected) {\n          return {\n            content: [{\n              type: 'text' as const,\n              text: `${remoteUnavailableMessage ?? `Chain Insights Graph is not connected at ${graphMcpEndpoint}`}. Restart the Chain Insights MCP proxy after the endpoint is reachable.`,\n            }],\n            isError: true,\n          }\n        }\n        const normalizedArgs = normalizeRemoteToolArguments(tool.name, args)\n        const validationError = validateKnownPublicToolArguments(tool.name, normalizedArgs)\n        if (validationError) {\n          return {\n            content: [{ type: 'text' as const, text: validationError }],\n            isError: true,\n          }\n        }\n        const request = {\n          name: tool.name,\n          arguments: normalizedArgs,\n        }\n        const requestOptions = remoteToolRequestOptions(tool.name)\n        const result = requestOptions\n          ? await remoteClient.callTool(request, undefined, requestOptions)\n          : await remoteClient.callTool(request)\n        return await normalizeRemoteToolResult(\n          result as RemoteToolResult,\n          config,\n          tool.name,\n          shouldIncludeAttachments(normalizedArgs, workspaceArtifactsEnabled),\n        )\n      } catch (err) {\n        if (err instanceof PaymentRequiredError) {\n          return {\n            content: [{ type: 'text' as const, text: err.message }],\n            isError: true,\n          }\n        }\n        const msg = (err as Error).message ?? String(err)\n        const isTransport402 = /\\b402\\b/.test(msg) || msg.toLowerCase().includes('payment')\n        if (isTransport402) {\n          return {\n            content: [{\n              type: 'text' as const,\n              text: `Payment required for ${tool.name}. This tool costs USDC on Base via x402 micropayments. ` +\n                'Next steps: run `chain-insights wallet ready` to check funding and finish one-time payment setup, ' +\n                'run `chain-insights wallet topup` if it says the wallet needs USDC, ' +\n                'or `chain-insights access-key set <key>` if you have been given test access.',\n            }],\n            isError: true,\n          }\n        }\n        return {\n          content: [{ type: 'text' as const, text: `MCP call failed: ${msg}` }],\n          isError: true,\n        }\n      }\n    }\n    const toolConfig = {\n      title: tool.title,\n      description: claudeFacingToolDescription(tool),\n      inputSchema,\n      ...(knownPublicToolAnnotations(tool.name) ? { annotations: knownPublicToolAnnotations(tool.name) } : {}),\n    }\n\n    if (hasGraphApp(tool)) {\n      registerAppTool(\n        server,\n        tool.name,\n        {\n          ...toolConfig,\n          _meta: graphToolMeta(tool),\n        },\n        handler,\n      )\n    } else {\n      server.registerTool(tool.name, toolConfig, handler)\n    }\n  }\n\n  // Connect to stdio transport — after this line, stdout belongs to MCP\n  const transport = new StdioServerTransport()\n  await server.connect(transport)\n  await logger.info('proxy.ready', {\n    tools: [\n      ...LOCAL_TOOL_NAMES,\n      ...(tools ?? []).map((tool) => tool.name).filter((name) => !HIDDEN_REMOTE_TOOL_NAMES.has(name) && !LOCAL_TOOL_NAMES.has(name)),\n    ].length,\n  })\n\n  // Signal handling — clean shutdown\n  const shutdown = async () => {\n    await logger.info('proxy.shutdown')\n    transport.close()\n    process.exit(0)\n  }\n  process.on('SIGINT', () => { void shutdown() })\n  process.on('SIGTERM', () => { void shutdown() })\n}\n\n\n// Entry point — only execute when run as the main module (not when imported by tests)\n// Using process.argv check to detect direct execution vs import\nif (process.argv[1] && import.meta.url.includes(process.argv[1].replace(/\\\\/g, '/'))) {\n  createProxy().catch((err) => {\n    process.stderr.write(`Chain Insights MCP proxy startup failed: ${(err as Error).message}\\n`)\n    process.exit(1)\n  })\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,mCAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,qBAAqB;AAC3B,MAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,mBAAmB;CAAC;CAAS;CAAS;CAAS;AAAc;AACnE,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;AAI7D,SAAgB,oBAAoB,MAAyB,QAAQ,KAAmB;CACtF,MAAM,MAAM,IAAI,gCAAgC,EAAE,KAAK,CAAC,CAAC,YAAY;CACrE,IAAI,CAAC,OAAO,QAAQ,aAAa,OAAO;CACxC,IAAI,QAAQ,eAAe,QAAQ,kBAAkB,QAAQ,kBAAkB,OAAO;CACtF,MAAM,IAAI,MAAM,sEAAsE,IAAI,EAAE;AAC9F;AAEA,MAAM,iDAAiC,IAAI,IAAI;CAC7C;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iCAAyD;CAC7D,2BAA2B;CAC3B,mBAAmB;CACnB,WAAW;CACX,gBAAgB;CAChB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,2BAA2B;CAC3B,aAAa;CACb,mBAAmB;AACrB;AACA,MAAM,sCAAsC,CAAC,eAAe,mBAAmB;AAe/E,MAAM,2BAA2B,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,kDAAmB;AAEnF,MAAM,wBAAwB,EAAE,KAAK,CAAC,iBAAiB,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iRAA0B;AAC1H,MAAM,qBAAqB,EAAE,aAAa,CAAC,CAAC;AAC5C,MAAM,uCAAuC,MAAU;AAEvD,MAAM,0BAA0B;CAC9B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;AAEX,MAAM,qBAAqB;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;AAEX,MAAM,qBAAqB;CACzB;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;AAEX,MAAM,sBAAsB;CAC1B;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,MAAM;AAEb,MAAM,gCAAgC;CACpC;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,MAAM;AAEb,SAAS,mBAA2B;CAClC,MAAM,aAAa;EACjB,KAAK,QAAQ,WAAW,aAAa,YAAY;EACjD,KAAK,QAAQ,WAAW,MAAM,aAAa,YAAY;EACvD,KAAK,QAAQ,WAAW,MAAM,OAAO,aAAa,YAAY;CAChE;CAEA,KAAK,MAAM,aAAa,YACtB,IAAI;EACF,OAAO,aAAa,WAAW,MAAM;CACvC,SAAS,KAAK;EACZ,IAAK,IAA8B,SAAS,UAAU,MAAM;CAC9D;CAGF,MAAM,IAAI,MAAM,uDAAuD,WAAW,KAAK,IAAI,GAAG;AAChG;AAEA,SAAS,qBAAqB,QAA0D;CACtF,OAAO,CACL,oBAAoB,OAAO,cAC3B,oBAAoB,OAAO,YAC7B;AACF;AAEA,SAAS,YAAY,MAAwB;CAC3C,MAAM,gBAAgB,KAAK,OAAO;CAClC,IACE,iBACA,OAAO,kBAAkB,YACzB,iBAAiB,iBACjB,cAAc,gBAAgB,oBAE9B,OAAO;CAGT,IAAI,KAAK,QAAQ,sBAAsB,oBAAoB,OAAO;CAClE,IAAI,qBAAqB,IAAI,KAAK,IAAI,GAAG,OAAO;CAChD,OAAO,KAAK,UAAU,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,cAAY;AACtE;AAEA,SAAS,cAAc,MAA0E;CAC/F,MAAM,OAAO,EAAE,GAAI,KAAK,SAAS,CAAC,EAAG;CACrC,MAAM,KACJ,KAAK,MAAM,OAAO,KAAK,OAAO,YAAY,CAAC,MAAM,QAAQ,KAAK,EAAE,IAC5D,EAAE,GAAI,KAAK,GAA+B,IAC1C,CAAC;CAEP,OAAO;EACL,GAAG;EACH,IAAI;GACF,GAAG;GACH,aAAa;EACf;CACF;AACF;AAEA,SAAS,2BAA2B,UAAyC;CAC3E,QAAQ,UAAR;EACE,KAAK,oBACH,OAAO;GACL,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,+BAA+B;GACnE,SAAS;GACT,iBAAiB,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,2DAA2D;GAC3G,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACF,KAAK,0BACH,OAAO;GACL,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,4DAA4D;GACzG,SAAS;GACT,yBAAyB,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,2DAA2D;GACnH,uBAAuB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iFAAiF;GAC9I,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;GAC9F,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACF,KAAK,2BACH,OAAO;GACL,SAAS;GACT,mBAAmB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,8DAA8D;GAC5G,uBAAuB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iFAAiF;GAC9I,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;GAC9F,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACF,KAAK,6BACH,OAAO;GACL,SAAS;GACT,mBAAmB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,wEAAwE;GACtH,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,yCAAyC;GACtG,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACF,KAAK,eACH,OAAO;GACL,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,+LAA+L;GACjO,SAAS;EACX;EACF,KAAK,qBACH,OAAO;GACL,SAAS;GACT,SAAS,EAAE,MAAM,EAAE,OAAO;IACxB,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,4BAA4B;GAChE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;GACjB,2BAA2B,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;EACvE;EACF,SACE,OAAO;CACX;AACF;AAEA,SAAS,8BAAyC;CAChD,OAAO,oCAAoC,KAAK,UAAU;EACxD;EACA,aAAa,+BAA+B;CAC9C,EAAE;AACJ;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AACrE;AAEA,SAAS,eAAe,OAAyB;CAC/C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,cAAc;CACzD,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAC7B,OAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW;EACpE,IAAI,oDAAoD,KAAK,GAAG,GAAG,OAAO,CAAC,KAAK,YAAY;EAC5F,OAAO,CAAC,KAAK,eAAe,KAAK,CAAC;CACpC,CAAC,CAAC;AACJ;AAEA,SAAS,YAAY,KAAuC;CAC1D,MAAM,QAAQ;CACd,OAAO;EACL,MAAM,MAAM,QAAQ;EACpB,SAAS,MAAM,WAAW,OAAO,GAAG;CACtC;AACF;AAEA,SAAS,eAAe,OAAuB;CAC7C,OAAO,MAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AACzC;AAEA,SAAS,iBAAiB,MAAc,MAA+C;CACrF,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO;CAC5B,IAAI,SAAS,eACX,OAAO;EACL,SAAS,KAAK;EACd,SAAS,CAAC;GACR,IAAI;GACJ,OAAO,OAAO,KAAK,UAAU,WAAW,eAAe,KAAK,KAAK,IAAI,KAAK;EAC5E,CAAC;CACH;CAEF,IAAI,SAAS,qBAAqB;EAChC,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IAAI,KAAK,UAAU,CAAC;EAC9D,OAAO;GACL,SAAS,KAAK;GACd,2BAA2B,KAAK;GAChC,aAAa,QAAQ;GACrB,SAAS,QAAQ,KAAK,OAAO,UAAU,SAAS,KAAK,IACjD;IACE,IAAI,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK,IAAI,QAAQ;IAC1D,OAAO,OAAO,MAAM,UAAU,WAAW,eAAe,MAAM,KAAK,IAAI,MAAM;GAC/E,IACA;IAAE,IAAI,IAAI,QAAQ;IAAK,OAAO;GAAM,CAAC;EAC3C;CACF;CACA,OAAO;AACT;AAEA,SAAS,gBAAgB,QAA6C;CACpE,MAAM,WAAW,QAAQ,IAAI,2BAA2B;CACxD,MAAM,WAAW,QAAQ,IAAI,6BAA6B,KAAK,KAAK,KAAK,KAAK,OAAO,SAAS,mBAAmB,WAAW,QAAQ,iBAAiB;CAErJ,eAAe,MAAM,OAAyB,OAAe,SAAkC,CAAC,GAAkB;EAChH,IAAI,UAAU;EACd,IAAI;GACF,MAAM,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;GACvD,MAAM,WAAW,UAAU,KAAK,UAAU;IACxC,qBAAI,IAAI,KAAK,EAAA,CAAE,YAAY;IAC3B;IACA;IACA,KAAK,QAAQ;IACb,GAAG;GACL,CAAC,IAAI,MAAM,EAAE,MAAM,IAAM,CAAC;EAC5B,QAAQ,CAER;CACF;CAEA,OAAO;EACL;EACA,OAAO,OAAe,WAAqC,MAAM,QAAQ,OAAO,MAAM;EACtF,QAAQ,OAAe,WAAqC,MAAM,SAAS,OAAO,MAAM;CAC1F;AACF;AAEA,SAAS,mBAAmB,QAAmB,QAAkD;CAC/F,MAAM,uBAAuB,OAAO;CACpC,MAAM,uBAAuB,qBAAqB,KAAK,MAAM;CAC7D,MAAM,wBAAwB,MAAc,QAAgC,YAAyB;EACnG,MAAM,UAAuB,OAAO,MAAM,UAAU;GAClD,MAAM,YAAY,KAAK,IAAI;GAC3B,MAAM,OAAO,KAAK,cAAc;IAC9B,MAAM;IACN,MAAM,eAAe,IAAI;GAC3B,CAAC;GACD,IAAI;IACF,MAAM,SAAS,MAAM,QAAQ,MAAM,KAAK;IACxC,MAAM,UAAU,SAAS,MAAM,KAAK,OAAO,YAAY;IACvD,MAAM,OAAO,KAAK,YAAY;KAC5B,MAAM;KACN,aAAa,KAAK,IAAI,IAAI;KAC1B,UAAU;IACZ,CAAC;IACD,OAAO;GACT,SAAS,KAAK;IACZ,MAAM,OAAO,MAAM,cAAc;KAC/B,MAAM;KACN,aAAa,KAAK,IAAI,IAAI;KAC1B,OAAO,YAAY,GAAG;IACxB,CAAC;IACD,MAAM;GACR;EACF;EACA,OAAO,qBAAqB,MAAM,QAAQ,OAAgB;CAC5D;CACA,OAAO,OAAO,qBAAqB,oBAAoB;CACvD,OAAO,eAAe;AACxB;AAEA,SAAS,2BAA2B,cAAgC,QAAkD;CACpH,MAAM,mBAAmB,aAAa;CACtC,MAAM,mBAAmB,iBAAiB,KAAK,YAAY;CAC3D,MAAM,mBAAmB,OAAO,GAAG,SAAyC;EAC1E,MAAM,QAAQ,KAAK;EACnB,MAAM,eAAe,iBAAiB,MAAM,MAAM,MAAM,SAAS;EACjE,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI,cACF,MAAM,OAAO,KAAK,kBAAkB;GAClC,MAAM,MAAM;GACZ,GAAG;EACL,CAAC;EAEH,IAAI;GACF,MAAM,SAAS,MAAM,iBAAiB,GAAG,IAAI;GAC7C,IAAI,cACF,MAAM,OAAO,KAAK,gBAAgB;IAChC,MAAM,MAAM;IACZ,aAAa,KAAK,IAAI,IAAI;IAC1B,UAAU,SAAS,MAAM,KAAK,OAAO,YAAY;GACnD,CAAC;GAEH,OAAO;EACT,SAAS,KAAK;GACZ,IAAI,cACF,MAAM,OAAO,MAAM,gBAAgB;IACjC,MAAM,MAAM;IACZ,aAAa,KAAK,IAAI,IAAI;IAC1B,OAAO,YAAY,GAAG;GACxB,CAAC;GAEH,MAAM;EACR;CACF;CACA,OAAO,OAAO,iBAAiB,gBAAgB;CAC/C,aAAa,WAAW;AAC1B;AAEA,SAAS,yBAAyB,UAAiE;CACjG,IAAI,aAAa,iBAAiB,aAAa,qBAC7C,OAAO;EACL,SAAS;EACT,iBAAiB;CACnB;AAGJ;AAEA,SAAS,gBAAgB,OAAyB;CAChD,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO;CAClD,IAAI,OAAO,UAAU,UAAU,OAAO,MAAM,KAAK,MAAM;CACvD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,WAAW,KAAK,MAAM,MAAM,eAAe;CAClF,OAAO;AACT;AAEA,SAAS,6BAA6B,UAAkB,MAAwC;CAC9F,MAAM,aAAa,SAAS,IAAI,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CACnD,IAAI,EAAE,YAAY,gCAAgC,OAAO;CAEzD,KAAK,MAAM,aAAa,gCAAgC;EACtD,MAAM,QAAQ,WAAW;EACzB,IAAI,MAAM,QAAQ,KAAK,GACrB,WAAW,aAAa,MACrB,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CACpC,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEf;CAEA,MAAM,cAAc,6BAA6B;CACjD,IAAI,CAAC,aAAa,OAAO;CACzB,OAAO,OAAO,YAAY,OAAO,QAAQ,UAAU,CAAC,CAAC,QAAQ,CAAC,SAAS,YAAY,SAAS,GAAG,CAAC,CAAC;AACnG;AAEA,SAAS,iCACP,UACA,MACe;CACf,MAAM,eAAe,8BAA8B;CACnD,IAAI,CAAC,cAAc,OAAO;CAE1B,KAAK,MAAM,WAAW,cACpB,IAAI,gBAAgB,KAAK,QAAQ,GAC/B,OAAO,8BAA8B;CAIzC,OAAO;AACT;AAEA,SAAS,4BAA4B,MAAuB;CAC1D,MAAM,kBAAkB,+BAA+B,KAAK,SAAS,KAAK,eAAe,KAAK;CAC9F,MAAM,eAAe,8BAA8B,KAAK;CACxD,IAAI,CAAC,cAAc,OAAO;CAC1B,OAAO;EACL;EACA;EACA,uBAAuB,aAAa,KAAK,IAAI,EAAE;EAC/C;CACF,CAAC,CAAC,KAAK,IAAI;AACb;AAEA,SAAS,2BAA2B,UAAuD;CACzF,IACE,aAAa,iBACb,aAAa,uBACb,SAAS,WAAW,MAAM,GAE1B,OAAO;EACL,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;CACjB;AAGJ;AASA,SAAS,aAAa,MAAc,aAAuC;CACzE,OAAO;EACL;EACA,UAAU,CACR;GACE,MAAM;GACN,SAAS;IACP,MAAM;IACN;GACF;EACF,CACF;CACF;AACF;AAEA,SAAS,qBAAqB,QAAyB;CACrD,OAAO,eACL,oBACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,8BAA8B;GAC3D,iBAAiB,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,0DAA0D;EAC5G;CACF,GACA,OAAO,EAAE,SAAS,SAAS,sBAAsB,aAC/C;EACE,0CAA0C,QAAQ;EAClD;EACA,KAAK,QAAQ;EACb,kBAAkB,qBAAqB,gBAAgB,MAAM;EAC7D;EACA;CACF,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI,GAC3B,4BACF,CACF;CAEA,OAAO,eACL,0BACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,kBAAkB,EAAE,OAAO,CAAC,CAAC,SAAS,0CAA0C;GAChF,yBAAyB,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mDAAmD;EAC7G;CACF,GACA,OAAO,EAAE,SAAS,kBAAkB,8BAA8B,aAAa;EAC7E,gDAAgD,QAAQ;EACxD;EACA;EACA;EACA,0BAA0B,uCAAuC,4BAA4B;EAC7F;EACA;CACF,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI,GAAG,yBAAyB,CACzD;CAEA,OAAO,eACL,2BACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,mBAAmB,EAAE,OAAO,CAAC,CAAC,SAAS,+CAA+C;EACxF;CACF,GACA,OAAO,EAAE,SAAS,wBAAwB,aAAa;EACrD,iDAAiD,QAAQ;EACzD;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI,GAAG,mBAAmB,CACnC;CAEA,OAAO,eACL,6BACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,mBAAmB,EAAE,OAAO,CAAC,CAAC,SAAS,sDAAsD;EAC/F;CACF,GACA,OAAO,EAAE,SAAS,wBAAwB,aAAa;EACrD,mDAAmD,QAAQ;EAC3D;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI,GAAG,0BAA0B,CAC1C;CAEA,OAAO,eACL,6BACA;EACE,OAAO;EACP,aAAa;EACb,YAAY,CAAC;CACf,GACA,YAAY,aACV,gKACA,sBACF,CACF;CAEA,OAAO,eACL,qBACA;EACE,OAAO;EACP,aAAa;EACb,YAAY,CAAC;CACf,GACA,YAAY,aACV,sFACA,cACF,CACF;CAEA,OAAO,eACL,eACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,4BAA4B;EACzD;CACF,GACA,OAAO,EAAE,SAAS,YAAY,aAC5B;EACE,qCAAqC,QAAQ;EAC7C;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI,GACX,aACF,CACF;CAEA,OAAO,eACL,qBACA;EACE,OAAO;EACP,aAAa;EACb,YAAY;GACV,SAAS;GACT,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,wEAAwE;GACrG,2BAA2B,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mDAAmD;EAC/G;CACF,GACA,OAAO,EAAE,SAAS,SAAS,gCAAgC,aACzD;EACE,2CAA2C,QAAQ;EACnD;EACA;EACA;EACA;EACA,4BAA4B,8BAA8B,8BAA8B;EACxF;EACA;CACF,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI,GAC3B,mBACF,CACF;CAEA,OAAO,eACL,kBACA;EACE,OAAO;EACP,aAAa;EACb,YAAY,CAAC;CACf,GACA,YAAY,aACV,uHACA,gBACF,CACF;CAEA,OAAO,eACL,aACA;EACE,OAAO;EACP,aAAa;EACb,YAAY,CAAC;CACf,GACA,YAAY,aACV,sHACA,qBACF,CACF;AAGF;AAEA,SAAS,oBAAoB,OAAyB;CACpD,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,SAAS;CACf,OAAO,iBAAiB,MAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,CAAC;AAClE;AAEA,SAAS,yCACP,mBACqC;CACrC,IAAI,CAAC,mBAAmB,OAAO,KAAA;CAC/B,OAAO,wBAAwB,iBAAiB;AAClD;AAEA,SAAS,wBAAwB,OAAyB;CACxD,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CAExE,MAAM,YAAqC,CAAC;CAC5C,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,KAAK,GAAG;EACrD,IAAI,QAAQ,YAAY;EACxB,IAAI,iBAAiB,SAAS,GAAwC,KAAK,MAAM,QAAQ,UAAU,GACjG;EAEF,UAAU,OAAO,wBAAwB,UAAU;CACrD;CAEA,OAAO;AACT;AAEA,SAAS,sBAAsB,QAA0D;CACvF,MAAM,gBAAgB,OAAO,OAAO;CACpC,IAAI,CAAC,iBAAiB,OAAO,kBAAkB,YAAY,MAAM,QAAQ,aAAa,GAAG,OAAO;CAChG,MAAM,QAAS,cAA0C;CACzD,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D,MAAM,IAAI,MAAM,8BAA8B;CAGhD,MAAM,cAAc;CACpB,IAAI,EAAE,UAAU,cAAc;EAC5B,IAAI,SAAS,eAAe,oBAAoB,WAAW,GACzD,MAAM,IAAI,MAAM,8BAA8B;EAEhD,OAAO;CACT;CAEA,MAAM,OAAO,YAAY;CACzB,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,8BAA8B;CAGhD,OAAO;AACT;AAEA,eAAe,0BACb,QACA,QACA,WAAW,gBACX,qBAAqB,MACrB;CACA,MAAM,eAAe,sBAAsB,MAAM;CACjD,MAAM,OAAO,EAAE,GAAI,OAAO,SAAS,CAAC,EAAG;CAEvC,IAAI,gBAAgB,oBAAoB;EACtC,MAAM,EAAE,qBAAqB,MAAM,OAAO;EAC1C,MAAM,EAAE,yBAAyB,MAAM,OAAO;EAC9C,MAAM,SAAS,MAAM,iBAAiB,cAAuB;GAC3D,YAAY,OAAO;GACnB,MAAM,YAAY;EACpB,CAAC;EACD,MAAM,qBAAqB,OAAO,UAAU;EAC5C,KAAK,gBAAgB;GACnB,GAAK,KAAK,iBAA6C,CAAC;GACxD,OAAO;IACL,QAAQ,OAAO;IACf,KAAK,OAAO;GACd;EACF;CACF;CAEA,OAAO;EACL,SAAS,OAAO,WAAW,CAAC;EAC5B,mBAAmB,yCAAyC,OAAO,iBAAiB;EACpF,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,KAAA;EAC7C,SAAS,OAAO;CAClB;AACF;AAEA,SAAS,yBAAyB,MAA+B,2BAA6C;CAC5G,OAAO,6BAA6B,KAAK,2BAA2B;AACtE;AAEA,eAAe,oBACb,WACA,QACA,MACA,oBAC6C;CAC7C,IAAI,CAAC,oBAAoB,OAAO,KAAA;CAChC,MAAM,EAAE,qBAAqB,MAAM,OAAO;CAC1C,MAAM,EAAE,yBAAyB,MAAM,OAAO;CAC9C,MAAM,SAAS,MAAM,iBAAiB,WAAoB;EACxD,YAAY,OAAO;EACnB;CACF,CAAC;CACD,MAAM,qBAAqB,OAAO,UAAU;CAC5C,OAAO;EACL,QAAQ,OAAO;EACf,KAAK,OAAO;CACd;AACF;AAEA,SAAS,gBAAgB,OAAgF;CACvG,OAAO,QACH,EACE,eAAe,EACb,MACF,EACF,IACA,KAAA;AACN;AAEA,SAAS,sBAAsB,OAAyC;CACtE,MAAM,SAAS,SAAS,KAAK,IAAI,QAAQ,CAAC;CAC1C,MAAM,iBAAiB,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAW,CAAC;CACtE,MAAM,WAAoC,EACxC,SAAS,SAAS,OAAO,QAAQ,IAAI,eAAe,YAAY,OAAO,KACzE;CACA,IAAI,SAAS,eAAe,IAAI,GAAG,SAAS,OAAO,eAAe;CAClE,IAAI,SAAS,eAAe,OAAO,GAAG,SAAS,UAAU,eAAe;CACxE,OAAO;EACL,OAAO,EAAE,SAAS,SAAS,OAAO,KAAK,IAAI,OAAO,MAAM,YAAY,OAAO,KAAK;EAChF,MAAM,EAAE,SAAS,SAAS,OAAO,IAAI,IAAI,OAAO,KAAK,YAAY,OAAO,MAAM;EAC9E;CACF;AACF;AAEA,SAAS,6BAA6B;CACpC,OAAO;EACL,SAAS;EACT,cAAc;EACd,QAAQ;EACR,SAAS;EACT,QAAQ;GACN,OAAO,EAAE,SAAS,KAAK;GACvB,MAAM,EAAE,SAAS,MAAM;GACvB,UAAU;IAAE,SAAS;IAAM,MAAM,EAAE,SAAS,KAAK;IAAG,SAAS,EAAE,SAAS,KAAK;GAAE;EACjF;EACA,OAAO;GACL,aAAa;GACb,mBAAmB;EACrB;CACF;AACF;AAEA,SAAS,yBAAyB,OAAgB;CAChD,MAAM,oBAAoB,SAAS,KAAK,IAAI,MAAM,oBAAoB,KAAA;CACtE,MAAM,QAAQ,SAAS,iBAAiB,IAAI,kBAAkB,QAAQ,KAAA;CACtE,MAAM,eAAe,SAAS,KAAK,IAAI,MAAM,eAAe,KAAA;CAI5D,MAAM,aAHW,SAAS,YAAY,KAAK,MAAM,QAAQ,aAAa,QAAQ,IAC1E,aAAa,WACb,CAAC,EAAA,CACsB,MAAM,YAC/B,SAAS,OAAO,KAAK,QAAQ,YAAY,WAC1C;CAgBD,OAAO;EACL,QAAQ;EACR,MAAM;EACN,MAAM;EACN,OAAO,EACL,cAAc;GACZ,QAAQ;GACR,UAAU,CArBA,YACZ;IACE,SAAS;IACT,cAAc,OAAO,UAAU,iBAAiB,WAAW,UAAU,eAAe;IACpF,QAAQ,OAAO,UAAU,WAAW,WAAW,UAAU,SAAS;IAClE,SAAS,UAAU,YAAY,QAAQ,QAAQ;IAC/C,QAAQ,sBAAsB,UAAU,MAAM;IAC9C,OAAO;KACL,aAAa;KACb,mBAAmB;IACrB;GACF,IACA,2BAA2B,CASP;EACpB,EACF;CACF;AACF;AAEA,SAAS,eAAe,mBAA4C;CAClE,OAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,mBAAmB,MAAM,CAAC;EAAE,CAAC;EACrF;EACA,SAAS;CACX;AACF;;;;;;;;AASA,eAAsB,cAA6B;CAEjD,MAAM,EAAE,eAAe,MAAM,OAAO,wBAAqB,CAAA,MAAA,MAAA,EAAA,CAAA;CACzD,MAAM,EAAE,eAAe,wBAAwB,MAAM,OAAO,wBAAyB,CAAA,MAAA,MAAA,EAAA,CAAA;CACrF,MAAM,EAAE,+BAA+B,4BAA4B,MAAM,OAAO,wBAAc,CAAA,MAAA,MAAA,EAAA,CAAA;CAC9F,MAAM,EAAE,YAAY,eAAe,MAAM,OAAO;CAEhD,MAAM,YAAY,oBAAoB;CACtC,MAAM,4BAA4B,cAAc;CAChD,MAAM,eAAe,MAAM,WAAW;CACtC,MAAM,kBAAkB,4BAA4B,oBAAoB,IAAI;CAC5E,MAAM,SAAS;EACb,GAAG;EACH,SAAS,4BAA4B,cAAc,aAAa,OAAO,IAAI,aAAa;CAC1F;CACA,MAAM,SAAS,gBAAgB,MAAM;CACrC,MAAM,OAAO,KAAK,eAAe;EAC/B,UAAU,OAAO;EACjB,gBAAgB,iBAAiB;EACjC,YAAY;EACZ,gBAAgB,OAAO;EACvB,oBAAoB,wBAAwB,MAAM;EAClD,UAAU,OAAO;CACnB,CAAC;CACD,MAAM,mBAAmB,wBAAwB,MAAM;CAKvD,MAAM,eAAe,IAAI,OAAO;EAAE,MAAM;EAA+B,SAAS;CAAgB,CAAC;CACjG,IAAI,kBAAkB;CACtB,IAAI;CACJ,IAAI;CAEJ,IAAI;EACF,WAAW,MAAM,8BAA8B,MAAM;CACvD,SAAS,KAAK;EACZ,MAAM,OAAO,MAAM,6BAA6B;GAC9C,UAAU;GACV,OAAO,YAAY,GAAG;EACxB,CAAC;EACD,2BAA2B,6CAA6C,iBAAiB,IAAK,IAAc;EAC5G,QAAQ,OAAO,MACb,+CAA+C,yBAAyB,oDAC1E;CACF;CAEA,IAAI,UACF,IAAI;EACF,MAAM,aAAa,QACjB,IAAI,8BAA8B,IAAI,IAAI,gBAAgB,GAAG,EAAE,OAAO,SAAS,CAAC,CAClF;EACA,kBAAkB;EAClB,MAAM,OAAO,KAAK,kBAAkB;GAClC,WAAW;GACX,UAAU;EACZ,CAAC;CACH,QAAQ;EACN,MAAM,OAAO,MAAM,yBAAyB;GAC1C,WAAW;GACX,UAAU;EACZ,CAAC;EAED,IAAI;GACF,MAAM,EAAE,uBAAuB,MAAM,OAAO;GAC5C,MAAM,aAAa,QACjB,IAAI,mBAAmB,IAAI,IAAI,gBAAgB,GAAG,EAAE,OAAO,SAAS,CAAC,CACvE;GACA,kBAAkB;GAClB,MAAM,OAAO,KAAK,kBAAkB;IAClC,WAAW;IACX,UAAU;GACZ,CAAC;EACH,SAAS,MAAM;GACb,MAAM,OAAO,MAAM,yBAAyB;IAC1C,WAAW;IACX,UAAU;IACV,OAAO,YAAY,IAAI;GACzB,CAAC;GACD,2BAA2B,uCAAuC,iBAAiB,IAAK,KAAe;GACvG,QAAQ,OAAO,MACb,+CAA+C,yBAAyB,oDAC1E;EACF;CACF;CAEF,IAAI,iBAAiB,2BAA2B,cAA6C,MAAM;CAGnG,IAAI,QAA0B,MAAM,WAAW,gBAAgB;CAE/D,IAAI,CAAC,SAAS,iBAAiB;EAG7B,SAAQ,MADa,aAAa,UAAU,EAAA,CAC7B;EACf,MAAM,WAAW,OAAO,gBAAgB;EACxC,MAAM,OAAO,KAAK,uBAAuB;GACvC,QAAQ;GACR,OAAO,MAAM;EACf,CAAC;CACH,OAAO,IAAI,OACT,MAAM,OAAO,KAAK,uBAAuB;EACvC,QAAQ;EACR,OAAO,MAAM;CACf,CAAC;MACI;EACL,QAAQ,4BAA4B;EACpC,MAAM,OAAO,KAAK,uBAAuB;GACvC,QAAQ;GACR,OAAO,MAAM;EACf,CAAC;CACH;CACA,MAAM,kBAAkB,IAAI,KAAK,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,IAAI,CAAC;CAGtE,MAAM,SAAS,IAAI,UACjB;EAAE,MAAM;EAAkB,SAAS;CAAgB,GACnD,EAAE,cAAc,4BAA4B,sBAAsB,8BAA8B,CAClG;CACA,mBAAmB,QAAQ,MAAM;CAEjC,IAAI,iBACF,IAAI;EACF,MAAM,aAAa,YAAY;CACjC,SAAS,KAAK;EACZ,MAAM,OAAO,MAAM,yBAAyB;GAC1C,UAAU;GACV,OAAO,YAAY,GAAG;EACxB,CAAC;EACD,QAAQ,OAAO,MACb,4DAA4D,iBAAiB,IAAK,IAAc,QAAQ,GAC1G;CACF;CAGF,qBAAqB,MAAM;CAa3B,OAAO,aACL,6BACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;EACb,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,YAAY;EACV,IAAI,mBAAmB,gBAAgB,IAAI,sBAAsB,GAC/D,IAAI;GAEF,OAAO,eAAe,yBAAyB,MAD1B,aAAa,SAAS;IAAE,MAAM;IAAwB,WAAW,CAAC;GAAE,CAAC,CACrC,CAAC;EACxD,SAAS,KAAK;GACZ,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,gCAAiC,IAAc;IAAU,CAAC;IACnG,SAAS;GACX;EACF;EAEF,OAAO,eAAe,yBAAyB,KAAA,CAAS,CAAC;CAC3D,CACF;CAEA,OAAO,aACL,qBACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;EACb,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,YAAY;EACV,IAAI;GACF,IAAI,CAAC,iBACH,OAAO;IACL,SAAS,CAAC;KACR,MAAM;KACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;IACtG,CAAC;IACD,SAAS;GACX;GAEF,IAAI,CAAC,gBAAgB,IAAI,cAAc,GACrC,OAAO,eAAe,4BAA4B,gBAAgB,CAAC;GAErE,MAAM,SAAS,MAAM,aAAa,SAAS;IAAE,MAAM;IAAgB,WAAW,CAAC;GAAE,CAAC;GAClF,MAAM,oBAAoB,SAAS,OAAO,iBAAiB,IACvD;IAAE,GAAG,OAAO;IAAmB,MAAM;GAAoB,IACzD,KAAA;GACJ,OAAO;IACL,SAAS,oBACL,CAAC;KAAE,MAAM;KAAiB,MAAM,KAAK,UAAU,mBAAmB,MAAM,CAAC;IAAE,CAAC,IAC5E,OAAO,WAAW,CAAC;IACvB;IACA,OAAO,OAAO;IACd,SAAS,OAAO;GAClB;EACF,SAAS,KAAK;GACZ,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,wBAAyB,IAAc;IAAU,CAAC;IAC3F,SAAS;GACX;EACF;CACF,CACF;CAEA,IAAI,2BACJ,OAAO,aACL,kBACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;EACb,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,YAAY;EACV,IAAI;GACF,MAAM,EAAE,2BAA2B,kBAAkB,2BAA2B,MAAM,OAAO,uBAAqB,CAAA,MAAA,MAAA,EAAA,CAAA;GAElH,MAAM,oBAAoB,MAAM,uBAAuB,MADjC,iBAAiB,CACuB;GAC9D,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,0BAA0B,iBAAiB;IAAE,CAAC;IACpE;IACnB,SAAS;GACX;EACF,SAAS,KAAK;GACZ,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,mBAAoB,IAAc;IAAU,CAAC;IACtF,SAAS;GACX;EACF;CACF,CACF;CAOA,oBACE,QACA,mBACA,oBACA;EACE,aAAa;EACb,OAAO,EACL,IAAI,EACF,KAAK;GACH,iBAAiB,qBAAqB,MAAM;GAC5C,gBAAgB,qBAAqB,MAAM;EAC7C,EACF,EACF;CACF,GACA,aAAa,EACX,UAAU,CACR;EACE,KAAK;EACL,UAAU;EACV,MAAM,iBAAiB;EACvB,OAAO,EACL,IAAI,EACF,KAAK;GACH,iBAAiB,qBAAqB,MAAM;GAC5C,gBAAgB,qBAAqB,MAAM;EAC7C,EACF,EACF;CACF,CACF,EACF,EACF;CAIA,IAAI,CAAC,gBAAgB,IAAI,kBAAkB,GACzC,gBACE,QACA,oBACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;GACX,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,8BAA8B;GAClE,SAAS;GACT,iBAAiB,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,0DAA0D;GAC1G,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACA,OAAO,EACL,IAAI,EACF,aAAa,mBACf,EACF;EACA,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,OAAO,EAAE,SAAS,SAAS,iBAAiB,qBAAqB,qBAAqB;EACpF,IAAI;GACF,IAAI,CAAC,iBACH,OAAO;IACL,SAAS,CAAC;KACR,MAAM;KACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;IACtG,CAAC;IACD,SAAS;GACX;GAEF,MAAM,EAAE,gBAAgB,MAAM,OAAO;GACrC,MAAM,SAAS,MAAM,YAAY,cAAc;IAC7C;IACA;IACA,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;GACjB,CAAC;GACD,MAAM,QAAQ,MAAM,oBAClB,OAAO,WACP,QACA,gBAAgB,QAAQ,GAAG,WAC3B,yBAAyB,EAAE,oBAAoB,GAAG,yBAAyB,CAC7E;GACA,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,OAAO;IAAY,CAAC;IAC7D,mBAAmB,OAAO;IAC1B,OAAO,gBAAgB,KAAK;IAC5B,SAAS;GACX;EACF,SAAS,KAAK;GACZ,IAAI,eAAe,sBACjB,OAAO;IAAE,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,IAAI;IAAQ,CAAC;IAAG,SAAS;GAAK;GAElF,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,wBAAyB,IAAc;IAAU,CAAC;IAC3F,SAAS;GACX;EACF;CACF,CACF;CAGF,IAAI,CAAC,gBAAgB,IAAI,wBAAwB,GAC/C,gBACE,QACA,0BACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;GACX,kBAAkB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,wEAAwE;GAC5J,SAAS;GACT,yBAAyB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,kDAAkD;GAC1I,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,uBAAuB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iFAAiF;GAC9I,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;GAC9F,gBAAgB;EAClB;EACA,OAAO,EACL,IAAI,EACF,aAAa,mBACf,EACF;EACA,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,OAAO,EAAE,kBAAkB,yBAAyB,SAAS,uBAAuB,UAAU,qBAAqB,qBAAqB;EACtI,IAAI;GACF,IAAI,CAAC,iBACH,OAAO;IACL,SAAS,CAAC;KACR,MAAM;KACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;IACtG,CAAC;IACD,SAAS;GACX;GAEF,MAAM,EAAE,qBAAqB,MAAM,OAAO;GAC1C,MAAM,SAAS,MAAM,iBAAiB,cAAc,QAAQ;IAC1D,iBAAiB;IACjB,uBAAuB;IACvB;IACA,qBAAqB;IACrB,SAAS;IACT,gBAAgB;IAChB,eAAe;GACjB,CAAC;GACD,MAAM,QAAQ,MAAM,oBAClB,OAAO,WACP,QACA,sBAAsB,WACtB,yBAAyB,EAAE,oBAAoB,GAAG,yBAAyB,CAC7E;GACA,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,OAAO;IAAY,CAAC;IAC7D,mBAAmB,OAAO;IAC1B,OAAO,gBAAgB,KAAK;IAC5B,SAAS;GACX;EACF,SAAS,KAAK;GACZ,IAAI,eAAe,sBACjB,OAAO;IAAE,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,IAAI;IAAQ,CAAC;IAAG,SAAS;GAAK;GAElF,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,8BAA+B,IAAc;IAAU,CAAC;IACjG,SAAS;GACX;EACF;CACF,CACF;CAGF,IAAI,CAAC,gBAAgB,IAAI,yBAAyB,GAChD,gBACE,QACA,2BACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;GACX,SAAS;GACT,mBAAmB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,0EAA0E;GAC/J,uBAAuB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iFAAiF;GAC9I,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,iCAAiC;GAC9F,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACA,OAAO,EACL,IAAI,EACF,aAAa,mBACf,EACF;EACA,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,OAAO,EAAE,mBAAmB,uBAAuB,SAAS,UAAU,qBAAqB,qBAAqB;EAC9G,IAAI;GACF,IAAI,CAAC,iBACH,OAAO;IACL,SAAS,CAAC;KACR,MAAM;KACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;IACtG,CAAC;IACD,SAAS;GACX;GAEF,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAC3C,MAAM,SAAS,MAAM,kBAAkB,cAAc,QAAQ;IAC3D,kBAAkB;IAClB;IACA,SAAS;IACT,qBAAqB;IACrB,gBAAgB;IAChB,eAAe;GACjB,CAAC;GACD,MAAM,QAAQ,MAAM,oBAClB,OAAO,WACP,QACA,uBAAuB,WACvB,yBAAyB,EAAE,oBAAoB,GAAG,yBAAyB,CAC7E;GACA,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,OAAO;IAAY,CAAC;IAC7D,mBAAmB,OAAO;IAC1B,OAAO,gBAAgB,KAAK;IAC5B,SAAS;GACX;EACF,SAAS,KAAK;GACZ,IAAI,eAAe,sBACjB,OAAO;IAAE,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,IAAI;IAAQ,CAAC;IAAG,SAAS;GAAK;GAElF,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,+BAAgC,IAAc;IAAU,CAAC;IAClG,SAAS;GACX;EACF;CACF,CACF;CAGF,IAAI,CAAC,gBAAgB,IAAI,2BAA2B,GAClD,gBACE,QACA,6BACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;GACX,SAAS;GACT,mBAAmB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,oFAAoF;GACzK,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,yCAAyC;GACtG,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,mCAAmC;GACxF,gBAAgB;EAClB;EACA,OAAO,EACL,IAAI,EACF,aAAa,mBACf,EACF;EACA,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,OAAO,EAAE,mBAAmB,SAAS,UAAU,qBAAqB,qBAAqB;EACvF,IAAI;GACF,IAAI,CAAC,iBACH,OAAO;IACL,SAAS,CAAC;KACR,MAAM;KACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;IACtG,CAAC;IACD,SAAS;GACX;GAEF,MAAM,EAAE,wBAAwB,MAAM,OAAO;GAC7C,MAAM,SAAS,MAAM,oBAAoB,cAAc,QAAQ;IAC7D,kBAAkB;IAClB;IACA,SAAS;IACT,gBAAgB;IAChB,eAAe;GACjB,CAAC;GACD,MAAM,QAAQ,MAAM,oBAClB,OAAO,WACP,QACA,yBAAyB,WACzB,yBAAyB,EAAE,oBAAoB,GAAG,yBAAyB,CAC7E;GACA,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,OAAO;IAAY,CAAC;IAC7D,mBAAmB,OAAO;IAC1B,OAAO,gBAAgB,KAAK;IAC5B,SAAS;GACX;EACF,SAAS,KAAK;GACZ,IAAI,eAAe,sBACjB,OAAO;IAAE,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,IAAI;IAAQ,CAAC;IAAG,SAAS;GAAK;GAElF,OAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAiB,MAAM,iCAAkC,IAAc;IAAU,CAAC;IACpG,SAAS;GACX;EACF;CACF,CACF;CAGF,OAAO,aACL,aACA;EACE,OAAO;EACP,aAAa,+BAA+B;EAC5C,aAAa;EACb,aAAa;GACX,cAAc;GACd,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;EACjB;CACF,GACA,aAAa;EACX,SAAS,CACP;GACE,MAAM;GACN,MAAM,4BACF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF,CAAC,CAAC,KAAK,IAAI,IACX;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF,CAAC,CAAC,KAAK,IAAI;EACjB,CACF;EACA,SAAS;CACX,EACF;CAGA,KAAK,MAAM,QAAQ,SAAS,CAAC,GAAG;EAC9B,IAAI,yBAAyB,IAAI,KAAK,IAAI,GAAG;EAC7C,IAAI,iBAAiB,IAAI,KAAK,IAAI,GAAG;EACrC,MAAM,cAAc,2BAA2B,KAAK,IAAI,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY;EACtF,MAAM,UAAU,OAAO,SAAkB;GACvC,IAAI;IACF,IAAI,CAAC,iBACH,OAAO;KACL,SAAS,CAAC;MACR,MAAM;MACN,MAAM,GAAG,4BAA4B,4CAA4C,mBAAmB;KACtG,CAAC;KACD,SAAS;IACX;IAEF,MAAM,iBAAiB,6BAA6B,KAAK,MAAM,IAAI;IACnE,MAAM,kBAAkB,iCAAiC,KAAK,MAAM,cAAc;IAClF,IAAI,iBACF,OAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAiB,MAAM;KAAgB,CAAC;KAC1D,SAAS;IACX;IAEF,MAAM,UAAU;KACd,MAAM,KAAK;KACX,WAAW;IACb;IACA,MAAM,iBAAiB,yBAAyB,KAAK,IAAI;IAIzD,OAAO,MAAM,0BAHE,iBACX,MAAM,aAAa,SAAS,SAAS,KAAA,GAAW,cAAc,IAC9D,MAAM,aAAa,SAAS,OAAO,GAGrC,QACA,KAAK,MACL,yBAAyB,gBAAgB,yBAAyB,CACpE;GACF,SAAS,KAAK;IACZ,IAAI,eAAe,sBACjB,OAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAiB,MAAM,IAAI;KAAQ,CAAC;KACtD,SAAS;IACX;IAEF,MAAM,MAAO,IAAc,WAAW,OAAO,GAAG;IAEhD,IADuB,UAAU,KAAK,GAAG,KAAK,IAAI,YAAY,CAAC,CAAC,SAAS,SAAS,GAEhF,OAAO;KACL,SAAS,CAAC;MACR,MAAM;MACN,MAAM,wBAAwB,KAAK,KAAK;KAI1C,CAAC;KACD,SAAS;IACX;IAEF,OAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAiB,MAAM,oBAAoB;KAAM,CAAC;KACpE,SAAS;IACX;GACF;EACF;EACA,MAAM,aAAa;GACjB,OAAO,KAAK;GACZ,aAAa,4BAA4B,IAAI;GAC7C;GACA,GAAI,2BAA2B,KAAK,IAAI,IAAI,EAAE,aAAa,2BAA2B,KAAK,IAAI,EAAE,IAAI,CAAC;EACxG;EAEA,IAAI,YAAY,IAAI,GAClB,gBACE,QACA,KAAK,MACL;GACE,GAAG;GACH,OAAO,cAAc,IAAI;EAC3B,GACA,OACF;OAEA,OAAO,aAAa,KAAK,MAAM,YAAY,OAAO;CAEtD;CAGA,MAAM,YAAY,IAAI,qBAAqB;CAC3C,MAAM,OAAO,QAAQ,SAAS;CAC9B,MAAM,OAAO,KAAK,eAAe,EAC/B,OAAO,CACL,GAAG,kBACH,IAAI,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,QAAQ,SAAS,CAAC,yBAAyB,IAAI,IAAI,KAAK,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAC/H,CAAC,CAAC,OACJ,CAAC;CAGD,MAAM,WAAW,YAAY;EAC3B,MAAM,OAAO,KAAK,gBAAgB;EAClC,UAAU,MAAM;EAChB,QAAQ,KAAK,CAAC;CAChB;CACA,QAAQ,GAAG,gBAAgB;EAAE,SAAc;CAAE,CAAC;CAC9C,QAAQ,GAAG,iBAAiB;EAAE,SAAc;CAAE,CAAC;AACjD;AAKA,IAAI,QAAQ,KAAK,MAAM,OAAO,KAAK,IAAI,SAAS,QAAQ,KAAK,EAAE,CAAC,QAAQ,OAAO,GAAG,CAAC,GACjF,YAAY,CAAC,CAAC,OAAO,QAAQ;CAC3B,QAAQ,OAAO,MAAM,4CAA6C,IAAc,QAAQ,GAAG;CAC3F,QAAQ,KAAK,CAAC;AAChB,CAAC"}