@probelabs/visor 0.1.125 → 0.1.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/ai-review-service.d.ts +1 -0
  2. package/dist/ai-review-service.d.ts.map +1 -1
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/docs/ai-configuration.md +23 -0
  5. package/dist/docs/slack-integration.md +6 -0
  6. package/dist/docs/workflows.md +30 -1
  7. package/dist/failure-condition-evaluator.d.ts.map +1 -1
  8. package/dist/frontends/slack-frontend.d.ts +2 -0
  9. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  10. package/dist/generated/config-schema.d.ts +18 -6
  11. package/dist/generated/config-schema.d.ts.map +1 -1
  12. package/dist/generated/config-schema.json +18 -6
  13. package/dist/index.js +7138 -7865
  14. package/dist/liquid-extensions.d.ts.map +1 -1
  15. package/dist/output/traces/{run-2026-01-30T09-25-36-981Z.ndjson → run-2026-02-01T09-59-08-165Z.ndjson} +84 -84
  16. package/dist/output/traces/{run-2026-01-30T09-26-20-969Z.ndjson → run-2026-02-01T09-59-52-595Z.ndjson} +1015 -1015
  17. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  18. package/dist/providers/command-check-provider.d.ts.map +1 -1
  19. package/dist/providers/custom-tool-executor.d.ts.map +1 -1
  20. package/dist/providers/http-client-provider.d.ts.map +1 -1
  21. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  22. package/dist/providers/memory-check-provider.d.ts.map +1 -1
  23. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  24. package/dist/sdk/{check-provider-registry-3KI5RKXT.mjs → check-provider-registry-CVUONJ5A.mjs} +8 -8
  25. package/dist/sdk/{chunk-7GUAFV6L.mjs → chunk-BHOKBQPB.mjs} +15 -10
  26. package/dist/sdk/chunk-BHOKBQPB.mjs.map +1 -0
  27. package/dist/sdk/{chunk-PXFIALUH.mjs → chunk-EORMDOZU.mjs} +19 -62
  28. package/dist/sdk/chunk-EORMDOZU.mjs.map +1 -0
  29. package/dist/sdk/{chunk-SWEEZ5D5.mjs → chunk-MPS4HVQI.mjs} +11 -77
  30. package/dist/sdk/chunk-MPS4HVQI.mjs.map +1 -0
  31. package/dist/sdk/{chunk-A4PGHURG.mjs → chunk-TS6BUNAI.mjs} +130 -75
  32. package/dist/sdk/chunk-TS6BUNAI.mjs.map +1 -0
  33. package/dist/sdk/{chunk-J6EVEXC2.mjs → chunk-VW2GBXQT.mjs} +56 -8
  34. package/dist/sdk/chunk-VW2GBXQT.mjs.map +1 -0
  35. package/dist/sdk/{chunk-RTKJXNZS.mjs → chunk-XWJPT5KQ.mjs} +26 -9
  36. package/dist/sdk/chunk-XWJPT5KQ.mjs.map +1 -0
  37. package/dist/sdk/{config-6CUVEH7H.mjs → config-DXX64GD3.mjs} +2 -2
  38. package/dist/sdk/{failure-condition-evaluator-HB35XRLZ.mjs → failure-condition-evaluator-G4HMJPXF.mjs} +3 -3
  39. package/dist/sdk/{github-frontend-BZ4N3BFZ.mjs → github-frontend-5PCKKHVC.mjs} +3 -3
  40. package/dist/sdk/{host-NYWXLIFC.mjs → host-H3AWNZ2F.mjs} +3 -3
  41. package/dist/sdk/{liquid-extensions-DFDEBMUI.mjs → liquid-extensions-I7O7KMHF.mjs} +3 -2
  42. package/dist/sdk/{routing-7FXPULTO.mjs → routing-QHTGDIXF.mjs} +4 -4
  43. package/dist/sdk/sdk.d.mts +6 -0
  44. package/dist/sdk/sdk.d.ts +6 -0
  45. package/dist/sdk/sdk.js +255 -214
  46. package/dist/sdk/sdk.js.map +1 -1
  47. package/dist/sdk/sdk.mjs +11 -11
  48. package/dist/sdk/{slack-frontend-J442FJWZ.mjs → slack-frontend-JUT3TYVC.mjs} +34 -6
  49. package/dist/sdk/slack-frontend-JUT3TYVC.mjs.map +1 -0
  50. package/dist/sdk/{workflow-check-provider-YUNNF4KC.mjs → workflow-check-provider-3IWBAZP7.mjs} +8 -8
  51. package/dist/sdk/{workflow-registry-6LZKCWHP.mjs → workflow-registry-KFWSDSLM.mjs} +2 -2
  52. package/dist/slack/socket-runner.d.ts +2 -0
  53. package/dist/slack/socket-runner.d.ts.map +1 -1
  54. package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
  55. package/dist/state-machine/states/routing.d.ts.map +1 -1
  56. package/dist/test-runner/index.d.ts.map +1 -1
  57. package/dist/test-runner/validator.d.ts.map +1 -1
  58. package/dist/traces/{run-2026-01-30T09-25-36-981Z.ndjson → run-2026-02-01T09-59-08-165Z.ndjson} +84 -84
  59. package/dist/traces/{run-2026-01-30T09-26-20-969Z.ndjson → run-2026-02-01T09-59-52-595Z.ndjson} +1015 -1015
  60. package/dist/types/config.d.ts +6 -0
  61. package/dist/types/config.d.ts.map +1 -1
  62. package/dist/utils/worktree-manager.d.ts.map +1 -1
  63. package/dist/workflow-executor.d.ts.map +1 -1
  64. package/dist/workflow-registry.d.ts +1 -0
  65. package/dist/workflow-registry.d.ts.map +1 -1
  66. package/package.json +5 -6
  67. package/dist/sdk/chunk-7GUAFV6L.mjs.map +0 -1
  68. package/dist/sdk/chunk-A4PGHURG.mjs.map +0 -1
  69. package/dist/sdk/chunk-J6EVEXC2.mjs.map +0 -1
  70. package/dist/sdk/chunk-PXFIALUH.mjs.map +0 -1
  71. package/dist/sdk/chunk-RTKJXNZS.mjs.map +0 -1
  72. package/dist/sdk/chunk-SWEEZ5D5.mjs.map +0 -1
  73. package/dist/sdk/slack-frontend-J442FJWZ.mjs.map +0 -1
  74. /package/dist/sdk/{check-provider-registry-3KI5RKXT.mjs.map → check-provider-registry-CVUONJ5A.mjs.map} +0 -0
  75. /package/dist/sdk/{config-6CUVEH7H.mjs.map → config-DXX64GD3.mjs.map} +0 -0
  76. /package/dist/sdk/{failure-condition-evaluator-HB35XRLZ.mjs.map → failure-condition-evaluator-G4HMJPXF.mjs.map} +0 -0
  77. /package/dist/sdk/{github-frontend-BZ4N3BFZ.mjs.map → github-frontend-5PCKKHVC.mjs.map} +0 -0
  78. /package/dist/sdk/{host-NYWXLIFC.mjs.map → host-H3AWNZ2F.mjs.map} +0 -0
  79. /package/dist/sdk/{liquid-extensions-DFDEBMUI.mjs.map → liquid-extensions-I7O7KMHF.mjs.map} +0 -0
  80. /package/dist/sdk/{routing-7FXPULTO.mjs.map → routing-QHTGDIXF.mjs.map} +0 -0
  81. /package/dist/sdk/{workflow-check-provider-YUNNF4KC.mjs.map → workflow-check-provider-3IWBAZP7.mjs.map} +0 -0
  82. /package/dist/sdk/{workflow-registry-6LZKCWHP.mjs.map → workflow-registry-KFWSDSLM.mjs.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/failure-condition-evaluator.ts"],"sourcesContent":["/**\n * Failure condition evaluation engine using SandboxJS for secure expression evaluation\n */\n\nimport { ReviewSummary } from './reviewer';\nimport { addEvent } from './telemetry/trace-helpers';\nimport { addFailIfTriggered } from './telemetry/metrics';\nimport {\n FailureConditions,\n FailureCondition,\n FailureConditionContext,\n FailureConditionResult,\n FailureConditionSeverity,\n} from './types/config';\nimport Sandbox from '@nyariv/sandboxjs';\nimport { createSecureSandbox } from './utils/sandbox';\nimport { createPermissionHelpers, detectLocalMode } from './utils/author-permissions';\nimport { MemoryStore } from './memory-store';\n\n/**\n * Evaluates failure conditions using SandboxJS for secure evaluation\n */\nexport class FailureConditionEvaluator {\n private sandbox?: Sandbox;\n\n constructor() {}\n\n /**\n * Create a secure sandbox with whitelisted functions and globals\n */\n private createSecureSandbox(): Sandbox {\n return createSecureSandbox();\n }\n\n /**\n * Evaluate simple fail_if condition\n */\n async evaluateSimpleCondition(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n expression: string,\n previousOutputs?: Record<string, ReviewSummary>,\n authorAssociation?: string\n ): Promise<boolean> {\n const context = this.buildEvaluationContext(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n previousOutputs,\n authorAssociation\n );\n\n try {\n try {\n const isObj = context.output && typeof context.output === 'object';\n const keys = isObj ? Object.keys(context.output as any).join(',') : typeof context.output;\n let errorVal: unknown = undefined;\n if (isObj && (context.output as any).error !== undefined)\n errorVal = (context.output as any).error;\n require('./logger').logger.debug(\n ` fail_if: evaluating '${expression}' with output keys=${keys} error=${String(errorVal)}`\n );\n } catch {}\n const res = this.evaluateExpression(expression, context);\n if (res === true) {\n try {\n addEvent('fail_if.triggered', {\n check: checkName,\n scope: 'check',\n name: `${checkName}_fail_if`,\n expression,\n severity: 'error',\n });\n } catch {}\n try {\n const { emitNdjsonSpanWithEvents } = require('./telemetry/fallback-ndjson');\n emitNdjsonSpanWithEvents(\n 'visor.fail_if',\n { check: checkName, scope: 'check', name: `${checkName}_fail_if` },\n [\n {\n name: 'fail_if.triggered',\n attrs: {\n check: checkName,\n scope: 'check',\n name: `${checkName}_fail_if`,\n expression,\n severity: 'error',\n },\n },\n ]\n );\n } catch {}\n }\n return res;\n } catch (error) {\n console.warn(`Failed to evaluate fail_if expression: ${error}`);\n return false; // Don't fail on evaluation errors\n }\n }\n\n /**\n * Determine if the event is related to pull requests\n */\n private determineIfPullRequest(eventType?: string): boolean {\n if (!eventType) return false;\n\n const prEvents = ['pr_opened', 'pr_updated', 'pr_closed', 'pull_request'];\n return prEvents.includes(eventType) || eventType.startsWith('pr_');\n }\n\n /**\n * Determine if the event is related to issues\n */\n private determineIfIssue(eventType?: string): boolean {\n if (!eventType) return false;\n\n const issueEvents = ['issue_opened', 'issue_comment', 'issues'];\n return issueEvents.includes(eventType) || eventType.startsWith('issue_');\n }\n\n /**\n * Evaluate if condition to determine whether a check should run\n */\n async evaluateIfCondition(\n checkName: string,\n expression: string,\n contextData?: {\n branch?: string;\n baseBranch?: string;\n filesChanged?: string[];\n event?: string;\n environment?: Record<string, string>;\n previousResults?: Map<string, ReviewSummary>;\n authorAssociation?: string;\n workflowInputs?: Record<string, unknown>;\n /** Current step's output for guarantee evaluation */\n output?: unknown;\n }\n ): Promise<boolean> {\n // Build context for if evaluation\n const context = {\n // Check metadata\n checkName,\n\n // Git context\n branch: contextData?.branch || 'unknown',\n baseBranch: contextData?.baseBranch || 'main',\n filesChanged: contextData?.filesChanged || [],\n filesCount: contextData?.filesChanged?.length || 0,\n\n // GitHub event context\n event: {\n event_name: contextData?.event || 'manual',\n action: undefined, // Would be populated from actual GitHub context\n repository: undefined, // Would be populated from actual GitHub context\n },\n\n // Environment variables\n env: contextData?.environment || {},\n\n // Previous check results (unwrap output field like templates do)\n outputs: contextData?.previousResults\n ? (() => {\n const outputs: Record<string, unknown> = {};\n for (const [checkName, result] of contextData.previousResults) {\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result as-is\n const summary = result as ReviewSummary & { output?: unknown };\n outputs[checkName] = summary.output !== undefined ? summary.output : summary;\n }\n return outputs;\n })()\n : {},\n\n // Workflow inputs (for workflows)\n inputs: contextData?.workflowInputs || {},\n\n // Output property: use provided output for guarantee evaluation, or empty for if conditions\n output:\n contextData?.output !== undefined &&\n contextData.output !== null &&\n typeof contextData.output === 'object'\n ? (contextData.output as Record<string, unknown>)\n : { issues: [] },\n // Author association (used by permission helpers)\n authorAssociation: contextData?.authorAssociation,\n\n // Utility metadata\n metadata: {\n checkName,\n schema: '',\n group: '',\n criticalIssues: 0,\n errorIssues: 0,\n warningIssues: 0,\n infoIssues: 0,\n totalIssues: 0,\n hasChanges: (contextData?.filesChanged?.length || 0) > 0,\n branch: contextData?.branch || 'unknown',\n event: contextData?.event || 'manual',\n },\n };\n\n try {\n const res = this.evaluateExpression(expression, context);\n try {\n if (process.env.VISOR_DEBUG === 'true') {\n // Debug if-eval output (only when VISOR_DEBUG enabled)\n const outputKeys = Object.keys(context.outputs || {});\n console.error(\n `[if-eval] check=${checkName} expr=\"${expression}\" result=${String(res)} outputKeys=[${outputKeys.join(',')}]`\n );\n }\n } catch {}\n return res;\n } catch (error) {\n console.warn(`Failed to evaluate if expression for check '${checkName}': ${error}`);\n // Fail-secure: do not run the check on evaluation errors\n return false;\n }\n }\n\n /**\n * Evaluate all failure conditions for a check result\n */\n async evaluateConditions(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n globalConditions?: FailureConditions,\n checkConditions?: FailureConditions,\n previousOutputs?: Record<string, ReviewSummary>,\n authorAssociation?: string\n ): Promise<FailureConditionResult[]> {\n const context = this.buildEvaluationContext(\n checkName,\n checkSchema,\n checkGroup,\n reviewSummary,\n previousOutputs,\n authorAssociation\n );\n\n const results: FailureConditionResult[] = [];\n\n // Evaluate global conditions first\n if (globalConditions) {\n const globalResults = await this.evaluateConditionSet(globalConditions, context, 'global');\n results.push(...globalResults);\n }\n\n // Evaluate check-specific conditions (these override global ones with same name)\n if (checkConditions) {\n const checkResults = await this.evaluateConditionSet(checkConditions, context, 'check');\n\n // Remove global conditions that are overridden by check-specific ones\n const overriddenConditions = new Set(Object.keys(checkConditions));\n const filteredResults = results.filter(\n result => !overriddenConditions.has(result.conditionName)\n );\n\n results.length = 0;\n results.push(...filteredResults, ...checkResults);\n }\n\n return results;\n }\n\n /**\n * Evaluate a set of failure conditions\n */\n private async evaluateConditionSet(\n conditions: FailureConditions,\n context: FailureConditionContext,\n source: 'global' | 'check'\n ): Promise<FailureConditionResult[]> {\n const results: FailureConditionResult[] = [];\n\n for (const [conditionName, condition] of Object.entries(conditions)) {\n try {\n addEvent('fail_if.evaluated', {\n check: context.checkName,\n scope: source,\n name: conditionName,\n expression: this.extractExpression(condition),\n });\n } catch {}\n\n // File fallback: append an NDJSON span with the evaluation event\n try {\n const { emitNdjsonSpanWithEvents } = require('./telemetry/fallback-ndjson');\n emitNdjsonSpanWithEvents(\n 'visor.fail_if',\n { check: context.checkName || 'unknown', scope: source, name: conditionName },\n [\n {\n name: 'fail_if.evaluated',\n attrs: {\n check: context.checkName,\n scope: source,\n name: conditionName,\n expression: this.extractExpression(condition),\n },\n },\n ]\n );\n } catch {}\n\n try {\n const result = await this.evaluateSingleCondition(conditionName, condition, context);\n results.push(result);\n\n if (result.failed) {\n try {\n addEvent('fail_if.triggered', {\n check: context.checkName,\n scope: source,\n name: conditionName,\n expression: result.expression,\n severity: result.severity,\n halt_execution: result.haltExecution,\n });\n } catch {}\n try {\n addFailIfTriggered(context.checkName || 'unknown', source);\n } catch {}\n }\n } catch (error) {\n // If evaluation fails, create an error result\n results.push({\n conditionName,\n failed: false,\n expression: this.extractExpression(condition),\n severity: 'error',\n haltExecution: false,\n error: `Failed to evaluate ${source} condition '${conditionName}': ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n }\n\n return results;\n }\n\n /**\n * Evaluate a single failure condition\n */\n private async evaluateSingleCondition(\n conditionName: string,\n condition: FailureCondition,\n context: FailureConditionContext\n ): Promise<FailureConditionResult> {\n const expression = this.extractExpression(condition);\n const config = this.extractConditionConfig(condition);\n\n try {\n const failed = this.evaluateExpression(expression, context);\n\n return {\n conditionName,\n failed,\n expression,\n message: config.message,\n severity: config.severity || 'error',\n haltExecution: config.halt_execution || false,\n };\n } catch (error) {\n throw new Error(\n `Expression evaluation error: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Secure expression evaluation using SandboxJS\n * Supports the same GitHub Actions-style functions as the previous implementation\n */\n private evaluateExpression(condition: string, context: FailureConditionContext): boolean {\n try {\n // Normalize multi-line or semicolon-separated expressions.\n // Allows writing debug statements on separate lines, e.g.:\n // log(\"start\")\n // log(outputs)\n // outputs[\"fetch-tickets\"].issueType === 'Bug'\n // We convert to a single expression using the comma operator so the\n // final expression determines the boolean result.\n const normalize = (expr: string): string => {\n const trimmed = expr.trim();\n // If it's already a single-line expression without semicolons, keep it.\n if (!/[\\n;]/.test(trimmed)) return trimmed;\n\n // Split on newlines/semicolons, drop empty and comment-only lines.\n const parts = trimmed\n .split(/[\\n;]+/)\n .map(s => s.trim())\n .filter(s => s.length > 0 && !s.startsWith('//'));\n\n if (parts.length === 0) return 'true';\n\n // Support an explicit return in the last statement.\n const lastRaw = parts.pop() as string;\n const last = lastRaw.replace(/^return\\s+/i, '').trim();\n\n // Join leading statements with comma operator; last expression returns value.\n if (parts.length === 0) return last;\n return `(${parts.join(', ')}, ${last})`;\n };\n\n // note: normalization happens later only if raw compilation fails\n // Helper functions for GitHub Actions-style expressions\n const contains = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().includes(String(searchValue).toLowerCase());\n\n const startsWith = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().startsWith(String(searchValue).toLowerCase());\n\n const endsWith = (searchString: string, searchValue: string): boolean =>\n String(searchString).toLowerCase().endsWith(String(searchValue).toLowerCase());\n\n const length = (value: string | unknown[] | Record<string, unknown>): number => {\n if (typeof value === 'string' || Array.isArray(value)) {\n return value.length;\n }\n if (value && typeof value === 'object') {\n return Object.keys(value).length;\n }\n return 0;\n };\n\n const always = (): boolean => true;\n const success = (): boolean => true;\n const failure = (): boolean => false;\n\n // Debug logging function for printing to console\n const log = (...args: unknown[]): void => {\n console.log('🔍 Debug:', ...args);\n };\n\n // Helper functions for array operations\n const hasIssue = (issues: unknown[], field: string, value: unknown): boolean => {\n if (!Array.isArray(issues)) return false;\n return issues.some(issue => (issue as Record<string, unknown>)[field] === value);\n };\n\n const countIssues = (issues: unknown[], field: string, value: unknown): number => {\n if (!Array.isArray(issues)) return 0;\n return issues.filter(issue => (issue as Record<string, unknown>)[field] === value).length;\n };\n\n const hasFileMatching = (issues: unknown[], pattern: string): boolean => {\n if (!Array.isArray(issues)) return false;\n return issues.some(issue => (issue as { file?: string }).file?.includes(pattern));\n };\n\n // Backward compatibility aliases\n const hasIssueWith = hasIssue;\n const hasFileWith = hasFileMatching;\n\n // Permission helper functions\n const permissionHelpers = createPermissionHelpers(\n context.authorAssociation,\n detectLocalMode()\n );\n const hasMinPermission = permissionHelpers.hasMinPermission;\n const isOwner = permissionHelpers.isOwner;\n const isMember = permissionHelpers.isMember;\n const isCollaborator = permissionHelpers.isCollaborator;\n const isContributor = permissionHelpers.isContributor;\n const isFirstTimer = permissionHelpers.isFirstTimer;\n\n // Extract context variables\n const output = context.output || {};\n // Ensure issues is an array - it might be a JSON string from workflow outputs\n let issues = output.issues || [];\n if (typeof issues === 'string') {\n try {\n issues = JSON.parse(issues);\n } catch {\n issues = [];\n }\n }\n if (!Array.isArray(issues)) {\n issues = [];\n }\n\n // Backward compatibility: provide metadata for transition period\n // TODO: Remove after all configurations are updated\n const metadata = context.metadata || {\n checkName: context.checkName || '',\n schema: context.schema || '',\n group: context.group || '',\n criticalIssues: issues.filter((i: { severity?: string }) => i.severity === 'critical')\n .length,\n errorIssues: issues.filter((i: { severity?: string }) => i.severity === 'error').length,\n warningIssues: issues.filter((i: { severity?: string }) => i.severity === 'warning').length,\n infoIssues: issues.filter((i: { severity?: string }) => i.severity === 'info').length,\n totalIssues: issues.length,\n hasChanges: context.hasChanges || false,\n };\n\n // Do not mutate output shape here. Output contracts are defined by providers and\n // workflow outputs. Tests and expressions should rely on those schemas directly.\n\n // Legacy variables for backward compatibility\n const criticalIssues = metadata.criticalIssues;\n const errorIssues = metadata.errorIssues;\n const totalIssues = metadata.totalIssues;\n const warningIssues = metadata.warningIssues;\n const infoIssues = metadata.infoIssues;\n\n // Additional context for 'if' conditions and some failure conditions\n const checkName = context.checkName || '';\n const schema = context.schema || '';\n const group = context.group || '';\n const branch = context.branch || 'unknown';\n const baseBranch = context.baseBranch || 'main';\n const filesChanged = context.filesChanged || [];\n const filesCount = context.filesCount || 0;\n const event = context.event || 'manual';\n const env = context.env || {};\n const outputs = context.outputs || {};\n const inputs = context.inputs || {};\n const debugData = context.debug || null;\n\n // Get memory store and create accessor for fail_if expressions\n const memoryStore = MemoryStore.getInstance();\n const memoryAccessor = {\n get: (key: string, ns?: string) => memoryStore.get(key, ns),\n has: (key: string, ns?: string) => memoryStore.has(key, ns),\n list: (ns?: string) => memoryStore.list(ns),\n getAll: (ns?: string) => memoryStore.getAll(ns),\n };\n\n // Create scope with all context variables and helper functions\n const scope = {\n // Primary context variables\n output,\n outputs,\n debug: debugData,\n // Memory accessor for fail_if expressions\n memory: memoryAccessor,\n // Legacy compatibility variables\n issues,\n metadata,\n criticalIssues,\n errorIssues,\n totalIssues,\n warningIssues,\n infoIssues,\n // If condition context\n checkName,\n schema,\n group,\n branch,\n baseBranch,\n filesChanged,\n filesCount,\n event,\n env,\n inputs,\n // Helper functions\n contains,\n startsWith,\n endsWith,\n length,\n always,\n success,\n failure,\n log,\n hasIssue,\n countIssues,\n hasFileMatching,\n hasIssueWith,\n hasFileWith,\n // Permission helpers\n hasMinPermission,\n isOwner,\n isMember,\n isCollaborator,\n isContributor,\n isFirstTimer,\n };\n\n // Compile and execute the expression in the sandbox\n const raw = condition.trim();\n if (!this.sandbox) {\n this.sandbox = this.createSecureSandbox();\n }\n let result: any;\n // Primary path: SandboxJS\n try {\n let exec: ReturnType<typeof this.sandbox.compile>;\n try {\n exec = this.sandbox.compile(`return (${raw});`);\n } catch {\n const normalizedExpr = normalize(condition);\n exec = this.sandbox.compile(`return (${normalizedExpr});`);\n }\n result = exec(scope).run();\n } catch (_primaryErr) {\n // Fallback path: Node VM for modern syntax (optional chaining, nullish coalescing)\n // Build a minimal, safe context with only whitelisted symbols\n try {\n const vm = require('node:vm');\n const ctx: any = {\n // Scope vars\n output,\n outputs,\n debug: debugData,\n memory: memoryAccessor,\n issues,\n metadata,\n criticalIssues,\n errorIssues,\n totalIssues,\n warningIssues,\n infoIssues,\n checkName,\n schema,\n group,\n branch,\n baseBranch,\n filesChanged,\n filesCount,\n event,\n env,\n inputs,\n // Helpers\n contains,\n startsWith,\n endsWith,\n length,\n always,\n success,\n failure,\n log,\n hasIssue,\n countIssues,\n hasFileMatching,\n hasIssueWith,\n hasFileWith,\n hasMinPermission,\n isOwner,\n isMember,\n isCollaborator,\n isContributor,\n isFirstTimer,\n Math,\n JSON,\n };\n const context = vm.createContext(ctx);\n // Try raw first; if it throws due to semicolons/newlines, normalize\n let code = `(${raw})`;\n try {\n result = new vm.Script(code).runInContext(context, { timeout: 50 });\n } catch {\n const normalizedExpr = normalize(condition);\n code = `(${normalizedExpr})`;\n result = new vm.Script(code).runInContext(context, { timeout: 50 });\n }\n } catch (vmErr) {\n console.error('❌ Failed to evaluate expression:', condition, vmErr);\n throw vmErr;\n }\n }\n try {\n require('./logger').logger.debug(` fail_if: result=${Boolean(result)}`);\n } catch {}\n // Ensure we return a boolean\n return Boolean(result);\n } catch (error) {\n console.error('❌ Failed to evaluate expression:', condition, error);\n // Re-throw the error so it can be caught by evaluateSingleCondition\n // and properly populate the error field in the result\n throw error;\n }\n }\n\n /**\n * Extract the expression from a failure condition\n */\n private extractExpression(condition: FailureCondition): string {\n if (typeof condition === 'string') {\n return condition;\n }\n return condition.condition;\n }\n\n /**\n * Extract configuration from a failure condition\n */\n private extractConditionConfig(condition: FailureCondition): {\n message?: string;\n severity?: FailureConditionSeverity;\n halt_execution?: boolean;\n } {\n if (typeof condition === 'string') {\n return {};\n }\n return {\n message: condition.message,\n severity: condition.severity,\n halt_execution: condition.halt_execution,\n };\n }\n\n /**\n * Build the evaluation context for expressions\n */\n private buildEvaluationContext(\n checkName: string,\n checkSchema: string,\n checkGroup: string,\n reviewSummary: ReviewSummary,\n previousOutputs?: Record<string, ReviewSummary>,\n authorAssociation?: string\n ): FailureConditionContext {\n const { issues, debug } = reviewSummary;\n const reviewSummaryWithOutput = reviewSummary as ReviewSummary & { output?: unknown };\n\n // Extract output field to avoid nesting (output.output)\n const {\n output: extractedOutput,\n // Exclude issues from otherFields since we handle it separately\n issues: _issues, // eslint-disable-line @typescript-eslint/no-unused-vars\n ...otherFields\n } = reviewSummaryWithOutput as any;\n\n // Build output object with safety for array-based outputs (forEach aggregation)\n const aggregatedOutput: Record<string, unknown> = {\n issues: (issues || []).map(issue => ({\n file: issue.file,\n line: issue.line,\n endLine: issue.endLine,\n ruleId: issue.ruleId,\n message: issue.message,\n severity: issue.severity,\n category: issue.category,\n group: issue.group,\n schema: issue.schema,\n suggestion: issue.suggestion,\n replacement: issue.replacement,\n })),\n // Include additional schema-specific data from reviewSummary\n ...otherFields,\n };\n\n if (Array.isArray(extractedOutput)) {\n // Preserve items array and lift common flags for convenience (e.g., output.error)\n aggregatedOutput.items = extractedOutput;\n const anyError = extractedOutput.find(\n it => it && typeof it === 'object' && (it as Record<string, unknown>).error\n ) as Record<string, unknown> | undefined;\n if (anyError && anyError.error !== undefined) {\n aggregatedOutput.error = anyError.error;\n }\n } else if (extractedOutput && typeof extractedOutput === 'object') {\n Object.assign(aggregatedOutput, extractedOutput as Record<string, unknown>);\n }\n\n // If provider attached a raw transform snapshot, merge its fields generically.\n try {\n const raw = (reviewSummaryWithOutput as any).__raw;\n if (raw && typeof raw === 'object') {\n Object.assign(aggregatedOutput, raw as Record<string, unknown>);\n }\n } catch {}\n\n // If output is a string, try to parse JSON (full or from end) to enrich context,\n // and also derive common boolean flags generically (e.g., key:true/false) for fail_if usage.\n try {\n if (typeof extractedOutput === 'string') {\n const parsed =\n this.tryExtractJsonFromEnd(extractedOutput) ??\n (() => {\n try {\n return JSON.parse(extractedOutput);\n } catch {\n return null;\n }\n })();\n if (parsed !== null) {\n if (Array.isArray(parsed)) {\n (aggregatedOutput as any).items = parsed;\n } else if (typeof parsed === 'object') {\n Object.assign(aggregatedOutput, parsed as Record<string, unknown>);\n }\n }\n // Generic boolean key extraction for simple text outputs (no special provider cases)\n const lower = extractedOutput.toLowerCase();\n const boolFrom = (key: string): boolean | null => {\n const reTrue = new RegExp(\n `(?:^|[^a-z0-9_])${key}[^a-z0-9_]*[:=][^a-z0-9_]*true(?:[^a-z0-9_]|$)`\n );\n const reFalse = new RegExp(\n `(?:^|[^a-z0-9_])${key}[^a-z0-9_]*[:=][^a-z0-9_]*false(?:[^a-z0-9_]|$)`\n );\n if (reTrue.test(lower)) return true;\n if (reFalse.test(lower)) return false;\n return null;\n };\n const keys = ['error'];\n for (const k of keys) {\n const v = boolFrom(k);\n if (v !== null && (aggregatedOutput as any)[k] === undefined) {\n (aggregatedOutput as any)[k] = v;\n }\n }\n }\n } catch {}\n\n // Try to parse JSON from content as a last resort when no structured output is present\n try {\n const rsAny = reviewSummaryWithOutput as any;\n const hasStructuredOutput = extractedOutput !== undefined && extractedOutput !== null;\n if (!hasStructuredOutput && typeof rsAny?.content === 'string') {\n const parsedFromContent = this.tryExtractJsonFromEnd(rsAny.content);\n if (parsedFromContent !== null && parsedFromContent !== undefined) {\n if (Array.isArray(parsedFromContent)) {\n (aggregatedOutput as any).items = parsedFromContent;\n } else if (typeof parsedFromContent === 'object') {\n Object.assign(aggregatedOutput, parsedFromContent as Record<string, unknown>);\n }\n }\n }\n } catch {}\n\n // Get memory store instance\n const memoryStore = MemoryStore.getInstance();\n\n const context: FailureConditionContext = {\n output: aggregatedOutput,\n outputs: (() => {\n if (!previousOutputs) return {};\n const outputs: Record<string, unknown> = {};\n for (const [checkName, result] of Object.entries(previousOutputs)) {\n // If the result has a direct output field, use it directly\n // Otherwise, expose the entire result as-is\n const summary = result as ReviewSummary & { output?: unknown };\n outputs[checkName] = summary.output !== undefined ? summary.output : summary;\n }\n return outputs;\n })(),\n // Add memory accessor for fail_if expressions\n memory: {\n get: (key: string, ns?: string) => memoryStore.get(key, ns),\n has: (key: string, ns?: string) => memoryStore.has(key, ns),\n list: (ns?: string) => memoryStore.list(ns),\n getAll: (ns?: string) => memoryStore.getAll(ns),\n } as any,\n // Add basic context info for failure conditions\n checkName: checkName,\n schema: checkSchema,\n group: checkGroup,\n authorAssociation: authorAssociation,\n };\n\n // Add debug information if available\n if (debug) {\n context.debug = {\n errors: debug.errors || [],\n processingTime: debug.processingTime || 0,\n provider: debug.provider || 'unknown',\n model: debug.model || 'unknown',\n };\n }\n\n return context;\n }\n\n // Minimal JSON-from-end extractor for fail_if context fallback\n private tryExtractJsonFromEnd(text: string): unknown | null {\n try {\n const lines = text.split('\\n');\n for (let i = lines.length - 1; i >= 0; i--) {\n const t = lines[i].trim();\n if (t.startsWith('{') || t.startsWith('[')) {\n const candidate = lines.slice(i).join('\\n').trim();\n if (\n (candidate.startsWith('{') && candidate.endsWith('}')) ||\n (candidate.startsWith('[') && candidate.endsWith(']'))\n ) {\n return JSON.parse(candidate);\n }\n }\n }\n } catch {}\n return null;\n }\n\n /**\n * Check if any failure condition requires halting execution\n */\n static shouldHaltExecution(results: FailureConditionResult[]): boolean {\n return results.some(result => result.failed && result.haltExecution);\n }\n\n /**\n * Get all failed conditions\n */\n static getFailedConditions(results: FailureConditionResult[]): FailureConditionResult[] {\n return results.filter(result => result.failed);\n }\n\n /**\n * Group results by severity\n */\n static groupResultsBySeverity(results: FailureConditionResult[]): {\n error: FailureConditionResult[];\n warning: FailureConditionResult[];\n info: FailureConditionResult[];\n } {\n return {\n // Only 'error' severity now (no backward compatibility needed here as this is internal)\n error: results.filter(r => r.severity === 'error'),\n warning: results.filter(r => r.severity === 'warning'),\n info: results.filter(r => r.severity === 'info'),\n };\n }\n\n /**\n * Format results for display\n */\n static formatResults(results: FailureConditionResult[]): string {\n const failed = FailureConditionEvaluator.getFailedConditions(results);\n\n if (failed.length === 0) {\n return '✅ All failure conditions passed';\n }\n\n const grouped = FailureConditionEvaluator.groupResultsBySeverity(failed);\n const sections: string[] = [];\n\n if (grouped.error.length > 0) {\n sections.push(`❌ **Error severity conditions (${grouped.error.length}):**`);\n grouped.error.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n if (grouped.warning.length > 0) {\n sections.push(`⚠️ **Warning conditions (${grouped.warning.length}):**`);\n grouped.warning.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n if (grouped.info.length > 0) {\n sections.push(`ℹ️ **Info conditions (${grouped.info.length}):**`);\n grouped.info.forEach(result => {\n sections.push(` - ${result.conditionName}: ${result.message || result.expression}`);\n });\n }\n\n return sections.join('\\n');\n }\n}\n"],"mappings":"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","names":["checkName","issues","context"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/slack/client.ts","../../src/slack/markdown.ts","../../src/frontends/slack-frontend.ts"],"sourcesContent":["// Lightweight Slack Web API wrapper implemented with fetch (no external deps).\n// Only methods needed by SlackFrontend are implemented.\n\nexport class SlackClient {\n private token: string;\n\n constructor(botToken: string) {\n if (!botToken || typeof botToken !== 'string') {\n throw new Error('SlackClient: botToken is required');\n }\n this.token = botToken;\n }\n\n public readonly reactions = {\n add: async ({\n channel,\n timestamp,\n name,\n }: {\n channel: string;\n timestamp: string;\n name: string;\n }) => {\n const resp: any = await this.api('reactions.add', { channel, timestamp, name });\n if (!resp || resp.ok !== true) {\n // Non-fatal in CLI/test runs – log and continue\n const err = (resp && resp.error) || 'unknown_error';\n console.warn(`Slack reactions.add failed (non-fatal): ${err}`);\n return { ok: false as const };\n }\n return { ok: true } as const;\n },\n remove: async ({\n channel,\n timestamp,\n name,\n }: {\n channel: string;\n timestamp: string;\n name: string;\n }) => {\n const resp: any = await this.api('reactions.remove', { channel, timestamp, name });\n if (!resp || resp.ok !== true) {\n const err = (resp && resp.error) || 'unknown_error';\n console.warn(`Slack reactions.remove failed (non-fatal): ${err}`);\n return { ok: false as const };\n }\n return { ok: true } as const;\n },\n };\n\n public readonly chat = {\n postMessage: async ({\n channel,\n text,\n thread_ts,\n }: {\n channel: string;\n text: string;\n thread_ts?: string;\n }) => {\n const resp: any = await this.api('chat.postMessage', { channel, text, thread_ts });\n if (!resp || resp.ok !== true) {\n const err = (resp && resp.error) || 'unknown_error';\n console.warn(`Slack chat.postMessage failed (non-fatal): ${err}`);\n return {\n ts: undefined,\n message: undefined,\n data: resp,\n };\n }\n // Normalize common fields for tests/frontend\n return {\n ts: resp.ts || (resp.message && resp.message.ts) || undefined,\n message: resp.message,\n data: resp,\n };\n },\n update: async ({ channel, ts, text }: { channel: string; ts: string; text: string }) => {\n const resp: any = await this.api('chat.update', { channel, ts, text });\n if (!resp || resp.ok !== true) {\n const err = (resp && resp.error) || 'unknown_error';\n console.warn(`Slack chat.update failed (non-fatal): ${err}`);\n return { ok: false as const, ts };\n }\n return { ok: true as const, ts: resp.ts || ts };\n },\n };\n\n async getBotUserId(): Promise<string> {\n const resp: any = await this.api('auth.test', {});\n if (!resp || resp.ok !== true || !resp.user_id) {\n console.warn('Slack auth.test failed (non-fatal); bot user id unavailable');\n return 'UNKNOWN_BOT';\n }\n return String(resp.user_id);\n }\n\n async fetchThreadReplies(\n channel: string,\n thread_ts: string,\n limit: number = 40\n ): Promise<\n Array<{ ts: string; user?: string; text?: string; bot_id?: string; thread_ts?: string }>\n > {\n try {\n // Use query-string GET semantics similar to Slack WebClient to avoid\n // subtle JSON/form encoding issues that can cause invalid_arguments\n const params = new URLSearchParams({\n channel,\n ts: thread_ts,\n limit: String(limit),\n });\n const res = await fetch(`https://slack.com/api/conversations.replies?${params.toString()}`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.token}`,\n },\n });\n const resp: any = await res.json();\n if (!resp || resp.ok !== true || !Array.isArray(resp.messages)) {\n const err = (resp && resp.error) || 'unknown_error';\n console.warn(\n `Slack conversations.replies failed (non-fatal): ${err} (channel=${channel}, ts=${thread_ts}, limit=${limit})`\n );\n return [];\n }\n return resp.messages.map((m: any) => ({\n ts: String(m.ts || ''),\n user: m.user,\n text: m.text,\n bot_id: m.bot_id,\n thread_ts: m.thread_ts,\n }));\n } catch (e) {\n console.warn(\n `Slack conversations.replies failed (non-fatal): ${\n e instanceof Error ? e.message : String(e)\n } (channel=${channel}, ts=${thread_ts}, limit=${limit})`\n );\n return [];\n }\n }\n\n public readonly files = {\n /**\n * Upload a file to Slack using files.uploadV2 API\n * @param options Upload options including file content, filename, channel, and thread_ts\n */\n uploadV2: async ({\n content,\n filename,\n channel,\n thread_ts,\n title,\n initial_comment,\n }: {\n content: Buffer;\n filename: string;\n channel: string;\n thread_ts?: string;\n title?: string;\n initial_comment?: string;\n }): Promise<{ ok: boolean; file?: { id: string; permalink?: string } }> => {\n try {\n // Step 1: Get upload URL\n const getUrlResp: any = await this.api('files.getUploadURLExternal', {\n filename,\n length: content.length,\n });\n if (!getUrlResp || getUrlResp.ok !== true || !getUrlResp.upload_url) {\n console.warn(\n `Slack files.getUploadURLExternal failed: ${getUrlResp?.error || 'unknown'}`\n );\n return { ok: false };\n }\n\n // Step 2: Upload file content to the URL\n const uploadResp = await fetch(getUrlResp.upload_url, {\n method: 'POST',\n body: content,\n });\n if (!uploadResp.ok) {\n console.warn(`Slack file upload to URL failed: ${uploadResp.status}`);\n return { ok: false };\n }\n\n // Step 3: Complete the upload and share to channel\n const completeResp: any = await this.api('files.completeUploadExternal', {\n files: [{ id: getUrlResp.file_id, title: title || filename }],\n channel_id: channel,\n thread_ts,\n initial_comment,\n });\n if (!completeResp || completeResp.ok !== true) {\n console.warn(\n `Slack files.completeUploadExternal failed: ${completeResp?.error || 'unknown'}`\n );\n return { ok: false };\n }\n\n return {\n ok: true,\n file: completeResp.files?.[0] || { id: getUrlResp.file_id },\n };\n } catch (e) {\n console.warn(`Slack file upload failed: ${e instanceof Error ? e.message : String(e)}`);\n return { ok: false };\n }\n },\n };\n\n getWebClient(): any {\n return {\n conversations: {\n history: async ({ channel, limit }: { channel: string; limit?: number }) =>\n (await this.api('conversations.history', { channel, limit })) as any,\n open: async ({ users }: { users: string }) =>\n (await this.api('conversations.open', { users })) as any,\n replies: async ({ channel, ts, limit }: { channel: string; ts: string; limit?: number }) =>\n (await this.api('conversations.replies', { channel, ts, limit })) as any,\n },\n };\n }\n\n private async api(method: string, body: Record<string, unknown>): Promise<unknown> {\n // Node 18+ global fetch\n const res = await fetch(`https://slack.com/api/${method}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=utf-8',\n Authorization: `Bearer ${this.token}`,\n },\n body: JSON.stringify(body),\n });\n return (await res.json()) as unknown;\n }\n}\n","// Lightweight Markdown → Slack mrkdwn formatter.\n// The goal is to make common Markdown output from AI steps look natural in Slack\n// without pulling in a full Markdown parser.\n//\n// Supported conversions:\n// - # Header / ## Header → *Header* (bold with visual separation)\n// - **bold** / __bold__ → *bold*\n// - [label](url) → <url|label>\n// - ![alt](url) → <url|alt>\n// - *italic* (inline) → _italic_\n// - ```mermaid blocks → rendered to PNG and uploaded to Slack\n//\n// Everything else is passed through unchanged; Slack will still render many\n// Markdown-like constructs (lists, code fences, etc.) natively.\n\nimport { spawn } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\n/**\n * Represents an extracted mermaid diagram\n */\nexport interface MermaidDiagram {\n /** The full match including ```mermaid and ``` */\n fullMatch: string;\n /** The mermaid code content */\n code: string;\n /** Start index in the original text */\n startIndex: number;\n /** End index in the original text */\n endIndex: number;\n}\n\n/**\n * Extract all mermaid code blocks from text\n */\nexport function extractMermaidDiagrams(text: string): MermaidDiagram[] {\n const diagrams: MermaidDiagram[] = [];\n // Match ```mermaid followed by newline, content, and closing ```\n const regex = /```mermaid\\s*\\n([\\s\\S]*?)```/g;\n let match;\n while ((match = regex.exec(text)) !== null) {\n diagrams.push({\n fullMatch: match[0],\n code: match[1].trim(),\n startIndex: match.index,\n endIndex: match.index + match[0].length,\n });\n }\n return diagrams;\n}\n\n/**\n * Render a mermaid diagram to PNG using mmdc CLI (@mermaid-js/mermaid-cli).\n *\n * Requirements:\n * - Node.js and npx must be available in PATH\n * - Network access on first run (npx downloads the package)\n * - Puppeteer/Chromium dependencies (mermaid-cli uses headless browser)\n *\n * On Linux, you may need to install chromium dependencies:\n * apt-get install -y chromium-browser libatk-bridge2.0-0 libgtk-3-0\n *\n * On Docker/CI, consider using a base image with puppeteer support or\n * pre-installing @mermaid-js/mermaid-cli globally.\n *\n * @param mermaidCode The mermaid diagram code\n * @returns Buffer containing PNG data, or null if rendering failed\n */\nexport async function renderMermaidToPng(mermaidCode: string): Promise<Buffer | null> {\n // Create temp files for input and output\n const tmpDir = os.tmpdir();\n const inputFile = path.join(\n tmpDir,\n `mermaid-${Date.now()}-${Math.random().toString(36).slice(2)}.mmd`\n );\n const outputFile = path.join(\n tmpDir,\n `mermaid-${Date.now()}-${Math.random().toString(36).slice(2)}.png`\n );\n\n try {\n // Write mermaid code to temp file\n fs.writeFileSync(inputFile, mermaidCode, 'utf-8');\n\n // Detect system chromium for puppeteer (mermaid-cli dependency)\n // Without this, puppeteer may hang trying to download its own chromium\n const chromiumPaths = [\n '/usr/bin/chromium',\n '/usr/bin/chromium-browser',\n '/usr/bin/google-chrome',\n '/usr/bin/chrome',\n ];\n let chromiumPath: string | undefined;\n for (const p of chromiumPaths) {\n if (fs.existsSync(p)) {\n chromiumPath = p;\n break;\n }\n }\n\n // Build environment with chromium path if found\n const env = { ...process.env };\n if (chromiumPath) {\n env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;\n }\n\n // Run mmdc to render PNG\n const result = await new Promise<{ success: boolean; error?: string }>(resolve => {\n const proc = spawn(\n 'npx',\n [\n '--yes',\n '@mermaid-js/mermaid-cli',\n '-i',\n inputFile,\n '-o',\n outputFile,\n '-e',\n 'png',\n '-b',\n 'white',\n '-w',\n '1200',\n ],\n {\n timeout: 60000, // 60 second timeout (first run may download packages)\n stdio: ['pipe', 'pipe', 'pipe'],\n env,\n }\n );\n\n let stderr = '';\n proc.stderr?.on('data', data => {\n stderr += data.toString();\n });\n\n proc.on('close', code => {\n if (code === 0) {\n resolve({ success: true });\n } else {\n resolve({ success: false, error: stderr || `Exit code ${code}` });\n }\n });\n\n proc.on('error', err => {\n resolve({ success: false, error: err.message });\n });\n });\n\n if (!result.success) {\n console.warn(`Mermaid rendering failed: ${result.error}`);\n return null;\n }\n\n // Read the output PNG\n if (!fs.existsSync(outputFile)) {\n console.warn('Mermaid output file not created');\n return null;\n }\n\n const pngBuffer = fs.readFileSync(outputFile);\n return pngBuffer;\n } catch (e) {\n console.warn(`Mermaid rendering error: ${e instanceof Error ? e.message : String(e)}`);\n return null;\n } finally {\n // Cleanup temp files\n try {\n if (fs.existsSync(inputFile)) fs.unlinkSync(inputFile);\n if (fs.existsSync(outputFile)) fs.unlinkSync(outputFile);\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Replace mermaid blocks in text with a placeholder message\n * @param text Original text\n * @param diagrams Extracted diagrams\n * @param replacement Text to replace each diagram with (or a function that returns replacement for each index)\n */\nexport function replaceMermaidBlocks(\n text: string,\n diagrams: MermaidDiagram[],\n replacement: string | ((index: number) => string) = '_(See diagram above)_'\n): string {\n if (diagrams.length === 0) return text;\n\n // Sort by start index descending to replace from end to start (preserves indices)\n const sorted = [...diagrams].sort((a, b) => b.startIndex - a.startIndex);\n\n let result = text;\n sorted.forEach((diagram, sortedIndex) => {\n // Calculate original index (since we sorted in reverse)\n const originalIndex = diagrams.length - 1 - sortedIndex;\n const rep = typeof replacement === 'function' ? replacement(originalIndex) : replacement;\n result = result.slice(0, diagram.startIndex) + rep + result.slice(diagram.endIndex);\n });\n\n return result;\n}\n\nexport function markdownToSlack(text: string): string {\n if (!text || typeof text !== 'string') return '';\n\n let out = text;\n\n // Images: ![alt](url) → <url|alt>\n // We intentionally keep only the URL + alt text; Slack will usually unfurl.\n out = out.replace(\n /!\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)/g,\n (_m, alt: string, url: string) => `<${url}|${alt || 'image'}>`\n );\n\n // Links: [label](url) → <url|label>\n out = out.replace(\n /\\[([^\\]]+)\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)/g,\n (_m, label: string, url: string) => `<${url}|${label}>`\n );\n\n // Bold: **text** or __text__ → *text*\n out = out.replace(/\\*\\*([^*]+)\\*\\*/g, (_m, inner: string) => `*${inner}*`);\n out = out.replace(/__([^_]+)__/g, (_m, inner: string) => `*${inner}*`);\n\n // Process lines for headers and bullet lists.\n // Slack's mrkdwn handles \"•\" bullets more naturally than raw \"-\" Markdown.\n const lines = out.split(/\\r?\\n/);\n let inCodeBlock = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n // Track fenced code blocks and avoid rewriting inside them\n if (/^```/.test(trimmed)) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n if (inCodeBlock) continue;\n\n // Headers: # Header → *Header* (Slack doesn't have native headers)\n // Match 1-6 # at start of line, followed by space and text\n const headerMatch = /^(#{1,6})\\s+(.+)$/.exec(trimmed);\n if (headerMatch) {\n const [, hashes, headerText] = headerMatch;\n // For h1/h2, add extra emphasis with newline before (if not first line\n // and previous line is not empty/header/code-fence)\n const prevLine = i > 0 ? lines[i - 1].trim() : '';\n const prevIsHeaderOrFence =\n /^#{1,6}\\s+/.test(prevLine) || /^\\*[^*]+\\*$/.test(prevLine) || /^```/.test(prevLine);\n if (hashes.length <= 2 && i > 0 && prevLine !== '' && !prevIsHeaderOrFence) {\n lines[i] = `\\n*${headerText.trim()}*`;\n } else {\n lines[i] = `*${headerText.trim()}*`;\n }\n continue;\n }\n\n // Bullet lists: \"- item\" or \"* item\" → \"• item\" (preserve indentation)\n const bulletMatch = /^(\\s*)([-*])\\s+(.+)$/.exec(line);\n if (bulletMatch) {\n const [, indent, , rest] = bulletMatch;\n lines[i] = `${indent}• ${rest}`;\n }\n }\n out = lines.join('\\n');\n\n return out;\n}\n\nexport function formatSlackText(text: string): string {\n return markdownToSlack(text);\n}\n","/**\n * Slack Frontend for Visor workflows.\n *\n * Features:\n * - Posts AI replies to Slack threads\n * - Converts Markdown to Slack mrkdwn format\n * - Renders mermaid diagrams to PNG and uploads as images\n * - Manages 👀/👍 reactions for acknowledgement\n * - Handles human input prompts via prompt-state\n *\n * Mermaid Diagram Rendering:\n * - Detects ```mermaid code blocks in AI responses\n * - Renders to PNG using @mermaid-js/mermaid-cli (mmdc)\n * - Uploads rendered images to Slack thread\n * - Replaces mermaid blocks with \"_(See diagram above)_\" placeholder\n *\n * Requirements for mermaid rendering:\n * - Node.js and npx in PATH\n * - Puppeteer/Chromium dependencies (mermaid-cli uses headless browser)\n * - On Linux: apt-get install chromium-browser libatk-bridge2.0-0 libgtk-3-0\n */\nimport type { Frontend, FrontendContext } from './host';\nimport { SlackClient } from '../slack/client';\nimport {\n formatSlackText,\n extractMermaidDiagrams,\n renderMermaidToPng,\n replaceMermaidBlocks,\n} from '../slack/markdown';\nimport { context as otContext, trace } from '../telemetry/lazy-otel';\n\ntype SlackFrontendConfig = {\n defaultChannel?: string;\n groupChannels?: Record<string, string>;\n debounceMs?: number;\n maxWaitMs?: number;\n showRawOutput?: boolean;\n telemetry?: {\n enabled?: boolean;\n };\n};\n\nexport class SlackFrontend implements Frontend {\n public readonly name = 'slack';\n private subs: Array<{ unsubscribe(): void }> = [];\n private cfg: SlackFrontendConfig;\n // Reactions ack/done per run (inbound Slack events only)\n private acked: boolean = false;\n private ackRef: { channel: string; ts: string } | null = null;\n private ackName: string = 'eyes';\n private doneName: string = 'thumbsup';\n private errorNotified: boolean = false;\n\n constructor(config?: SlackFrontendConfig) {\n this.cfg = config || {};\n }\n\n start(ctx: FrontendContext): void {\n const bus = ctx.eventBus;\n\n // Info-level boot log\n try {\n const hasClient = !!(\n (ctx as any).slack ||\n (ctx as any).slackClient ||\n (this.cfg as any)?.botToken ||\n process.env.SLACK_BOT_TOKEN\n );\n ctx.logger.info(`[slack-frontend] started; hasClient=${hasClient} defaultChannel=unset`);\n } catch {}\n\n // If this run was triggered by a Slack event, log key attributes\n try {\n const payload = this.getInboundSlackPayload(ctx);\n if (payload) {\n const ev: any = payload.event || {};\n const ch = String(ev.channel || '-');\n const ts = String(ev.ts || ev.event_ts || '-');\n const user = String(ev.user || ev.bot_id || '-');\n const type = String(ev.type || '-');\n const thread = String(ev.thread_ts || '');\n ctx.logger.info(\n `[slack-frontend] inbound event received: type=${type} channel=${ch} ts=${ts}` +\n (thread ? ` thread_ts=${thread}` : '') +\n ` user=${user}`\n );\n }\n } catch {}\n\n // Listen to check lifecycle; we only post on completion/error (no queued placeholders)\n this.subs.push(\n bus.on('CheckCompleted', async (env: any) => {\n const ev = (env && env.payload) || env;\n // For chat-style AI checks, post direct replies into the Slack thread\n await this.maybePostDirectReply(ctx, ev.checkId, ev.result).catch(() => {});\n })\n );\n this.subs.push(\n bus.on('CheckErrored', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Execution error';\n await this.maybePostError(ctx, 'Check failed', message, ev?.checkId).catch(() => {});\n })\n );\n\n // On terminal state, replace 👀 with 👍 if we acked an inbound Slack message\n this.subs.push(\n bus.on('StateTransition', async (env: any) => {\n const ev = (env && env.payload) || env;\n if (ev && (ev.to === 'Completed' || ev.to === 'Error')) {\n await this.finalizeReactions(ctx).catch(() => {});\n }\n })\n );\n this.subs.push(\n bus.on('Shutdown', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Fatal error';\n await this.maybePostError(ctx, 'Run failed', message).catch(() => {});\n })\n );\n // Add 👀 acknowledgement as soon as first check is scheduled for Slack-driven runs\n this.subs.push(\n bus.on('CheckScheduled', async () => {\n await this.ensureAcknowledgement(ctx).catch(() => {});\n })\n );\n\n // Human-input requests: post prompt to Slack and mark waiting using prompt-state\n this.subs.push(\n bus.on('HumanInputRequested', async (env: any) => {\n try {\n const ev = (env && env.payload) || env;\n if (!ev || typeof ev.prompt !== 'string' || !ev.checkId) return;\n // Determine channel/thread (Slack SocketMode); if we can't, just ignore.\n let channel = ev.channel as string | undefined;\n let threadTs = ev.threadTs as string | undefined;\n if (!channel || !threadTs) {\n const payload = this.getInboundSlackPayload(ctx);\n const e: any = payload?.event;\n const derivedTs = String(e?.thread_ts || e?.ts || e?.event_ts || '');\n const derivedCh = String(e?.channel || '');\n if (derivedCh && derivedTs) {\n channel = channel || derivedCh;\n threadTs = threadTs || derivedTs;\n }\n }\n if (!channel || !threadTs) return;\n\n // Mark waiting in prompt-state without posting the prompt text to Slack.\n const { getPromptStateManager } = await import('../slack/prompt-state');\n const mgr = getPromptStateManager();\n const prev = mgr.getWaiting(channel, threadTs);\n const text = String(ev.prompt);\n mgr.setWaiting(channel, threadTs, {\n checkName: String(ev.checkId),\n prompt: text,\n promptMessageTs: prev?.promptMessageTs,\n promptsPosted: ((prev?.promptsPosted || 0) + 1) as any,\n });\n try {\n ctx.logger.info(\n `[slack-frontend] registered human-input waiting state for ${channel} thread=${threadTs}`\n );\n } catch {}\n } catch (e) {\n try {\n ctx.logger.warn(\n `[slack-frontend] HumanInputRequested handling failed: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n } catch {}\n }\n })\n );\n\n // SnapshotSaved: attach snapshot path to waiting entry for this thread\n this.subs.push(\n bus.on('SnapshotSaved', async (env: any) => {\n try {\n const ev = (env && env.payload) || env;\n const channel = String(ev?.channel || '');\n const threadTs = String(ev?.threadTs || '');\n const filePath = String(ev?.filePath || '');\n if (!channel || !threadTs || !filePath) return;\n const { getPromptStateManager } = await import('../slack/prompt-state');\n const mgr = getPromptStateManager();\n mgr.update(channel, threadTs, { snapshotPath: filePath });\n try {\n ctx.logger.info(\n `[slack-frontend] snapshot path attached to waiting prompt: ${filePath}`\n );\n } catch {}\n } catch {}\n })\n );\n }\n\n stop(): void {\n for (const s of this.subs) s.unsubscribe();\n this.subs = [];\n }\n\n private getSlack(ctx: FrontendContext): any | undefined {\n // Prefer injected fake client in tests: ctx.slack or ctx.slackClient\n const injected = (ctx as any).slack || (ctx as any).slackClient;\n if (injected) return injected;\n // Else try to lazy-create from env or frontend config\n try {\n const token = (this.cfg as any)?.botToken || process.env.SLACK_BOT_TOKEN;\n if (typeof token === 'string' && token.trim()) {\n return new SlackClient(token.trim());\n }\n } catch {}\n return undefined;\n }\n\n private getInboundSlackPayload(ctx: FrontendContext): any | null {\n try {\n const anyCfg: any = ctx.config || {};\n const slackCfg: any = anyCfg.slack || {};\n const endpoint: string = slackCfg.endpoint || '/bots/slack/support';\n const payload: any = (ctx as any).webhookContext?.webhookData?.get(endpoint);\n return payload || null;\n } catch {\n return null;\n }\n }\n\n private getInboundSlackEvent(ctx: FrontendContext): { channel: string; ts: string } | null {\n try {\n const payload = this.getInboundSlackPayload(ctx);\n const ev: any = payload?.event;\n const channel = String(ev?.channel || '');\n const ts = String(ev?.ts || ev?.event_ts || '');\n if (channel && ts) return { channel, ts };\n } catch {}\n return null;\n }\n\n private isTelemetryEnabled(ctx: FrontendContext): boolean {\n try {\n const anyCfg: any = ctx.config || {};\n const slackCfg: any = anyCfg.slack || {};\n const telemetryCfg = slackCfg.telemetry ?? (this.cfg as any)?.telemetry;\n return (\n telemetryCfg === true ||\n (telemetryCfg && typeof telemetryCfg === 'object' && telemetryCfg.enabled === true)\n );\n } catch {\n return false;\n }\n }\n\n private async maybePostError(\n ctx: FrontendContext,\n title: string,\n message: string,\n checkId?: string\n ): Promise<void> {\n if (this.errorNotified) return;\n if (!this.isTelemetryEnabled(ctx)) return;\n const slack = this.getSlack(ctx);\n if (!slack) return;\n const payload = this.getInboundSlackPayload(ctx);\n const ev: any = payload?.event;\n const channel = String(ev?.channel || '');\n const threadTs = String(ev?.thread_ts || ev?.ts || ev?.event_ts || '');\n if (!channel || !threadTs) return;\n\n let text = `❌ ${title}`;\n if (checkId) text += `\\nCheck: ${checkId}`;\n if (message) text += `\\n${message}`;\n\n const traceInfo = this.getTraceInfo();\n if (traceInfo?.traceId) {\n text += `\\n\\n\\`trace_id: ${traceInfo.traceId}\\``;\n }\n\n const formattedText = formatSlackText(text);\n await slack.chat.postMessage({ channel, text: formattedText, thread_ts: threadTs });\n try {\n ctx.logger.info(\n `[slack-frontend] posted error notice to ${channel} thread=${threadTs} check=${checkId || 'run'}`\n );\n } catch {}\n this.errorNotified = true;\n }\n\n private async ensureAcknowledgement(ctx: FrontendContext): Promise<void> {\n if (this.acked) return;\n const ref = this.getInboundSlackEvent(ctx);\n if (!ref) return;\n const slack = this.getSlack(ctx);\n if (!slack) return;\n // Skip ack for bot messages to avoid loops\n try {\n const payload = this.getInboundSlackPayload(ctx);\n const ev: any = payload?.event;\n if (ev?.subtype === 'bot_message') return;\n // If we can resolve bot user id, skip if the sender is the bot\n try {\n const botId = await slack.getBotUserId?.();\n if (botId && ev?.user && String(ev.user) === String(botId)) return;\n } catch {}\n } catch {}\n // Allow overrides via config\n try {\n const anyCfg: any = ctx.config || {};\n const slackCfg: any = anyCfg.slack || {};\n if (slackCfg?.reactions?.enabled === false) return;\n this.ackName = slackCfg?.reactions?.ack || this.ackName;\n this.doneName = slackCfg?.reactions?.done || this.doneName;\n } catch {}\n await slack.reactions.add({ channel: ref.channel, timestamp: ref.ts, name: this.ackName });\n try {\n ctx.logger.info(\n `[slack-frontend] added acknowledgement reaction :${this.ackName}: channel=${ref.channel} ts=${ref.ts}`\n );\n } catch {}\n this.acked = true;\n this.ackRef = ref;\n }\n\n private async finalizeReactions(ctx: FrontendContext): Promise<void> {\n if (!this.acked || !this.ackRef) return;\n const slack = this.getSlack(ctx);\n if (!slack) return;\n try {\n try {\n await slack.reactions.remove({\n channel: this.ackRef.channel,\n timestamp: this.ackRef.ts,\n name: this.ackName,\n });\n } catch {}\n await slack.reactions.add({\n channel: this.ackRef.channel,\n timestamp: this.ackRef.ts,\n name: this.doneName,\n });\n try {\n ctx.logger.info(\n `[slack-frontend] replaced acknowledgement with completion reaction :${this.doneName}: channel=${this.ackRef.channel} ts=${this.ackRef.ts}`\n );\n } catch {}\n } finally {\n // Reset for safety\n this.acked = false;\n this.ackRef = null;\n }\n }\n\n /**\n * Post direct replies into the originating Slack thread when appropriate.\n * This is independent of summary messages and is intended for chat-style flows\n * (e.g., AI answers and explicit chat/notify steps).\n */\n private async maybePostDirectReply(\n ctx: FrontendContext,\n checkId: string,\n result: { output?: any; content?: string }\n ): Promise<void> {\n try {\n const cfg: any = ctx.config || {};\n const checkCfg: any = cfg.checks?.[checkId];\n if (!checkCfg) return;\n\n // Per-workflow / per-frontend flag to allow posting raw JSON\n // outputs for AI steps (useful for debugging router outputs).\n const slackRoot: any = (cfg as any).slack || {};\n const showRawOutput =\n slackRoot.show_raw_output === true || (this.cfg as any)?.showRawOutput === true;\n const telemetryCfg = slackRoot.telemetry ?? (this.cfg as any)?.telemetry;\n\n const providerType = (checkCfg.type as string) || '';\n const isAi = providerType === 'ai';\n const isLogChat = providerType === 'log' && checkCfg.group === 'chat';\n if (!isAi && !isLogChat) return;\n\n // Skip internal steps - they're intermediate processing and shouldn't post to Slack\n if (checkCfg.criticality === 'internal') return;\n\n // For AI checks, only post when using simple/unstructured schemas (or none).\n if (isAi) {\n const schema = checkCfg.schema;\n // String schemas: allow only simple/plain ones\n if (typeof schema === 'string') {\n const simpleSchemas = ['code-review', 'markdown', 'text', 'plain'];\n if (!simpleSchemas.includes(schema)) return;\n }\n // Object schemas (custom JSON): treat as structured; require output.text\n }\n\n const slack = this.getSlack(ctx);\n if (!slack) return;\n\n const payload = this.getInboundSlackPayload(ctx);\n const ev: any = payload?.event;\n const channel = String(ev?.channel || '');\n const threadTs = String(ev?.thread_ts || ev?.ts || ev?.event_ts || '');\n if (!channel || !threadTs) return;\n\n // Prefer output.text; fall back to content ONLY for string/simple schemas.\n const out: any = (result as any)?.output;\n let text: string | undefined;\n if (out && typeof out.text === 'string' && out.text.trim().length > 0) {\n text = out.text.trim();\n } else if (isAi && typeof checkCfg.schema === 'string') {\n if (\n typeof (result as any)?.content === 'string' &&\n (result as any).content.trim().length > 0\n ) {\n text = (result as any).content.trim();\n }\n } else if (isLogChat && typeof (result as any)?.logOutput === 'string') {\n // For log-based chat checks, render the formatted log output as the\n // Slack message when no structured text field is present.\n const raw = (result as any).logOutput;\n if (raw.trim().length > 0) {\n text = raw.trim();\n }\n } else if (isAi && showRawOutput && out !== undefined) {\n try {\n text = JSON.stringify(out, null, 2);\n } catch {\n text = String(out);\n }\n }\n if (!text) return;\n\n // Extract and render mermaid diagrams before posting\n const diagrams = extractMermaidDiagrams(text);\n let processedText = text;\n\n if (diagrams.length > 0) {\n try {\n ctx.logger.info(\n `[slack-frontend] found ${diagrams.length} mermaid diagram(s) to render for ${checkId}`\n );\n } catch {}\n\n // Render and upload each diagram\n const uploadedCount: number[] = [];\n for (let i = 0; i < diagrams.length; i++) {\n const diagram = diagrams[i];\n try {\n ctx.logger.info(`[slack-frontend] rendering mermaid diagram ${i + 1}...`);\n const pngBuffer = await renderMermaidToPng(diagram.code);\n if (pngBuffer) {\n ctx.logger.info(\n `[slack-frontend] rendered diagram ${i + 1}, size=${pngBuffer.length} bytes, uploading...`\n );\n const filename = `diagram-${i + 1}.png`;\n const uploadResult = await slack.files.uploadV2({\n content: pngBuffer,\n filename,\n channel,\n thread_ts: threadTs,\n title: `Diagram ${i + 1}`,\n });\n if (uploadResult.ok) {\n uploadedCount.push(i);\n ctx.logger.info(`[slack-frontend] uploaded mermaid diagram ${i + 1} to ${channel}`);\n } else {\n ctx.logger.warn(`[slack-frontend] upload failed for diagram ${i + 1}`);\n }\n } else {\n ctx.logger.warn(\n `[slack-frontend] mermaid rendering returned null for diagram ${i + 1} (mmdc failed or not installed)`\n );\n }\n } catch (e) {\n ctx.logger.warn(\n `[slack-frontend] failed to render/upload mermaid diagram ${i + 1}: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n }\n }\n\n // Replace mermaid blocks with placeholder text\n if (uploadedCount.length > 0) {\n processedText = replaceMermaidBlocks(text, diagrams, idx =>\n uploadedCount.includes(idx) ? '_(See diagram above)_' : '_(Diagram rendering failed)_'\n );\n }\n }\n\n let decoratedText = processedText;\n const telemetryEnabled =\n telemetryCfg === true ||\n (telemetryCfg && typeof telemetryCfg === 'object' && telemetryCfg.enabled === true);\n if (telemetryEnabled) {\n const traceInfo = this.getTraceInfo();\n if (traceInfo?.traceId) {\n const suffix = `\\`trace_id: ${traceInfo.traceId}\\``;\n decoratedText = `${decoratedText}\\n\\n${suffix}`;\n }\n }\n\n const formattedText = formatSlackText(decoratedText);\n await slack.chat.postMessage({ channel, text: formattedText, thread_ts: threadTs });\n ctx.logger.info(\n `[slack-frontend] posted AI reply for ${checkId} to ${channel} thread=${threadTs}`\n );\n } catch (outerErr) {\n // Log errors instead of silently swallowing them\n try {\n ctx.logger.warn(\n `[slack-frontend] maybePostDirectReply failed for ${checkId}: ${\n outerErr instanceof Error ? outerErr.message : String(outerErr)\n }`\n );\n } catch {}\n }\n }\n\n private getTraceInfo(): { traceId: string; spanId: string } | null {\n try {\n const span = trace.getSpan(otContext.active());\n if (!span) return null;\n const ctx = span.spanContext();\n if (!ctx || !ctx.traceId) return null;\n return { traceId: ctx.traceId, spanId: ctx.spanId };\n } catch {\n return null;\n }\n }\n}\n"],"mappings":";;;;;;;;AAGO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EAER,YAAY,UAAkB;AAC5B,QAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEgB,YAAY;AAAA,IAC1B,KAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAIM;AACJ,YAAM,OAAY,MAAM,KAAK,IAAI,iBAAiB,EAAE,SAAS,WAAW,KAAK,CAAC;AAC9E,UAAI,CAAC,QAAQ,KAAK,OAAO,MAAM;AAE7B,cAAM,MAAO,QAAQ,KAAK,SAAU;AACpC,gBAAQ,KAAK,2CAA2C,GAAG,EAAE;AAC7D,eAAO,EAAE,IAAI,MAAe;AAAA,MAC9B;AACA,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IACA,QAAQ,OAAO;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAIM;AACJ,YAAM,OAAY,MAAM,KAAK,IAAI,oBAAoB,EAAE,SAAS,WAAW,KAAK,CAAC;AACjF,UAAI,CAAC,QAAQ,KAAK,OAAO,MAAM;AAC7B,cAAM,MAAO,QAAQ,KAAK,SAAU;AACpC,gBAAQ,KAAK,8CAA8C,GAAG,EAAE;AAChE,eAAO,EAAE,IAAI,MAAe;AAAA,MAC9B;AACA,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,EACF;AAAA,EAEgB,OAAO;AAAA,IACrB,aAAa,OAAO;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAIM;AACJ,YAAM,OAAY,MAAM,KAAK,IAAI,oBAAoB,EAAE,SAAS,MAAM,UAAU,CAAC;AACjF,UAAI,CAAC,QAAQ,KAAK,OAAO,MAAM;AAC7B,cAAM,MAAO,QAAQ,KAAK,SAAU;AACpC,gBAAQ,KAAK,8CAA8C,GAAG,EAAE;AAChE,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,SAAS;AAAA,UACT,MAAM;AAAA,QACR;AAAA,MACF;AAEA,aAAO;AAAA,QACL,IAAI,KAAK,MAAO,KAAK,WAAW,KAAK,QAAQ,MAAO;AAAA,QACpD,SAAS,KAAK;AAAA,QACd,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,QAAQ,OAAO,EAAE,SAAS,IAAI,KAAK,MAAqD;AACtF,YAAM,OAAY,MAAM,KAAK,IAAI,eAAe,EAAE,SAAS,IAAI,KAAK,CAAC;AACrE,UAAI,CAAC,QAAQ,KAAK,OAAO,MAAM;AAC7B,cAAM,MAAO,QAAQ,KAAK,SAAU;AACpC,gBAAQ,KAAK,yCAAyC,GAAG,EAAE;AAC3D,eAAO,EAAE,IAAI,OAAgB,GAAG;AAAA,MAClC;AACA,aAAO,EAAE,IAAI,MAAe,IAAI,KAAK,MAAM,GAAG;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,MAAM,eAAgC;AACpC,UAAM,OAAY,MAAM,KAAK,IAAI,aAAa,CAAC,CAAC;AAChD,QAAI,CAAC,QAAQ,KAAK,OAAO,QAAQ,CAAC,KAAK,SAAS;AAC9C,cAAQ,KAAK,6DAA6D;AAC1E,aAAO;AAAA,IACT;AACA,WAAO,OAAO,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,mBACJ,SACA,WACA,QAAgB,IAGhB;AACA,QAAI;AAGF,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC;AAAA,QACA,IAAI;AAAA,QACJ,OAAO,OAAO,KAAK;AAAA,MACrB,CAAC;AACD,YAAM,MAAM,MAAM,MAAM,+CAA+C,OAAO,SAAS,CAAC,IAAI;AAAA,QAC1F,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,KAAK;AAAA,QACrC;AAAA,MACF,CAAC;AACD,YAAM,OAAY,MAAM,IAAI,KAAK;AACjC,UAAI,CAAC,QAAQ,KAAK,OAAO,QAAQ,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9D,cAAM,MAAO,QAAQ,KAAK,SAAU;AACpC,gBAAQ;AAAA,UACN,mDAAmD,GAAG,aAAa,OAAO,QAAQ,SAAS,WAAW,KAAK;AAAA,QAC7G;AACA,eAAO,CAAC;AAAA,MACV;AACA,aAAO,KAAK,SAAS,IAAI,CAAC,OAAY;AAAA,QACpC,IAAI,OAAO,EAAE,MAAM,EAAE;AAAA,QACrB,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,QACV,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ,SAAS,GAAG;AACV,cAAQ;AAAA,QACN,mDACE,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAC3C,aAAa,OAAO,QAAQ,SAAS,WAAW,KAAK;AAAA,MACvD;AACA,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEgB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,IAKtB,UAAU,OAAO;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAO2E;AACzE,UAAI;AAEF,cAAM,aAAkB,MAAM,KAAK,IAAI,8BAA8B;AAAA,UACnE;AAAA,UACA,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD,YAAI,CAAC,cAAc,WAAW,OAAO,QAAQ,CAAC,WAAW,YAAY;AACnE,kBAAQ;AAAA,YACN,4CAA4C,YAAY,SAAS,SAAS;AAAA,UAC5E;AACA,iBAAO,EAAE,IAAI,MAAM;AAAA,QACrB;AAGA,cAAM,aAAa,MAAM,MAAM,WAAW,YAAY;AAAA,UACpD,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AACD,YAAI,CAAC,WAAW,IAAI;AAClB,kBAAQ,KAAK,oCAAoC,WAAW,MAAM,EAAE;AACpE,iBAAO,EAAE,IAAI,MAAM;AAAA,QACrB;AAGA,cAAM,eAAoB,MAAM,KAAK,IAAI,gCAAgC;AAAA,UACvE,OAAO,CAAC,EAAE,IAAI,WAAW,SAAS,OAAO,SAAS,SAAS,CAAC;AAAA,UAC5D,YAAY;AAAA,UACZ;AAAA,UACA;AAAA,QACF,CAAC;AACD,YAAI,CAAC,gBAAgB,aAAa,OAAO,MAAM;AAC7C,kBAAQ;AAAA,YACN,8CAA8C,cAAc,SAAS,SAAS;AAAA,UAChF;AACA,iBAAO,EAAE,IAAI,MAAM;AAAA,QACrB;AAEA,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,MAAM,aAAa,QAAQ,CAAC,KAAK,EAAE,IAAI,WAAW,QAAQ;AAAA,QAC5D;AAAA,MACF,SAAS,GAAG;AACV,gBAAQ,KAAK,6BAA6B,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AACtF,eAAO,EAAE,IAAI,MAAM;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAoB;AAClB,WAAO;AAAA,MACL,eAAe;AAAA,QACb,SAAS,OAAO,EAAE,SAAS,MAAM,MAC9B,MAAM,KAAK,IAAI,yBAAyB,EAAE,SAAS,MAAM,CAAC;AAAA,QAC7D,MAAM,OAAO,EAAE,MAAM,MAClB,MAAM,KAAK,IAAI,sBAAsB,EAAE,MAAM,CAAC;AAAA,QACjD,SAAS,OAAO,EAAE,SAAS,IAAI,MAAM,MAClC,MAAM,KAAK,IAAI,yBAAyB,EAAE,SAAS,IAAI,MAAM,CAAC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,IAAI,QAAgB,MAAiD;AAEjF,UAAM,MAAM,MAAM,MAAM,yBAAyB,MAAM,IAAI;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,KAAK,KAAK;AAAA,MACrC;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;AC9NA,SAAS,aAAa;AACtB,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AAmBb,SAAS,uBAAuB,MAAgC;AACrE,QAAM,WAA6B,CAAC;AAEpC,QAAM,QAAQ;AACd,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,aAAS,KAAK;AAAA,MACZ,WAAW,MAAM,CAAC;AAAA,MAClB,MAAM,MAAM,CAAC,EAAE,KAAK;AAAA,MACpB,YAAY,MAAM;AAAA,MAClB,UAAU,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,IACnC,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAmBA,eAAsB,mBAAmB,aAA6C;AAEpF,QAAM,SAAY,UAAO;AACzB,QAAM,YAAiB;AAAA,IACrB;AAAA,IACA,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC9D;AACA,QAAM,aAAkB;AAAA,IACtB;AAAA,IACA,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC9D;AAEA,MAAI;AAEF,IAAG,iBAAc,WAAW,aAAa,OAAO;AAIhD,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI;AACJ,eAAW,KAAK,eAAe;AAC7B,UAAO,cAAW,CAAC,GAAG;AACpB,uBAAe;AACf;AAAA,MACF;AAAA,IACF;AAGA,UAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;AAC7B,QAAI,cAAc;AAChB,UAAI,4BAA4B;AAAA,IAClC;AAGA,UAAM,SAAS,MAAM,IAAI,QAA8C,aAAW;AAChF,YAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,UACE,SAAS;AAAA;AAAA,UACT,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS;AACb,WAAK,QAAQ,GAAG,QAAQ,UAAQ;AAC9B,kBAAU,KAAK,SAAS;AAAA,MAC1B,CAAC;AAED,WAAK,GAAG,SAAS,UAAQ;AACvB,YAAI,SAAS,GAAG;AACd,kBAAQ,EAAE,SAAS,KAAK,CAAC;AAAA,QAC3B,OAAO;AACL,kBAAQ,EAAE,SAAS,OAAO,OAAO,UAAU,aAAa,IAAI,GAAG,CAAC;AAAA,QAClE;AAAA,MACF,CAAC;AAED,WAAK,GAAG,SAAS,SAAO;AACtB,gBAAQ,EAAE,SAAS,OAAO,OAAO,IAAI,QAAQ,CAAC;AAAA,MAChD,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,OAAO,SAAS;AACnB,cAAQ,KAAK,6BAA6B,OAAO,KAAK,EAAE;AACxD,aAAO;AAAA,IACT;AAGA,QAAI,CAAI,cAAW,UAAU,GAAG;AAC9B,cAAQ,KAAK,iCAAiC;AAC9C,aAAO;AAAA,IACT;AAEA,UAAM,YAAe,gBAAa,UAAU;AAC5C,WAAO;AAAA,EACT,SAAS,GAAG;AACV,YAAQ,KAAK,4BAA4B,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AACrF,WAAO;AAAA,EACT,UAAE;AAEA,QAAI;AACF,UAAO,cAAW,SAAS,EAAG,CAAG,cAAW,SAAS;AACrD,UAAO,cAAW,UAAU,EAAG,CAAG,cAAW,UAAU;AAAA,IACzD,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAQO,SAAS,qBACd,MACA,UACA,cAAoD,yBAC5C;AACR,MAAI,SAAS,WAAW,EAAG,QAAO;AAGlC,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU;AAEvE,MAAI,SAAS;AACb,SAAO,QAAQ,CAAC,SAAS,gBAAgB;AAEvC,UAAM,gBAAgB,SAAS,SAAS,IAAI;AAC5C,UAAM,MAAM,OAAO,gBAAgB,aAAa,YAAY,aAAa,IAAI;AAC7E,aAAS,OAAO,MAAM,GAAG,QAAQ,UAAU,IAAI,MAAM,OAAO,MAAM,QAAQ,QAAQ;AAAA,EACpF,CAAC;AAED,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAsB;AACpD,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,MAAI,MAAM;AAIV,QAAM,IAAI;AAAA,IACR;AAAA,IACA,CAAC,IAAI,KAAa,QAAgB,IAAI,GAAG,IAAI,OAAO,OAAO;AAAA,EAC7D;AAGA,QAAM,IAAI;AAAA,IACR;AAAA,IACA,CAAC,IAAI,OAAe,QAAgB,IAAI,GAAG,IAAI,KAAK;AAAA,EACtD;AAGA,QAAM,IAAI,QAAQ,oBAAoB,CAAC,IAAI,UAAkB,IAAI,KAAK,GAAG;AACzE,QAAM,IAAI,QAAQ,gBAAgB,CAAC,IAAI,UAAkB,IAAI,KAAK,GAAG;AAIrE,QAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,MAAI,cAAc;AAClB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,UAAU,KAAK,UAAU;AAE/B,QAAI,OAAO,KAAK,OAAO,GAAG;AACxB,oBAAc,CAAC;AACf;AAAA,IACF;AACA,QAAI,YAAa;AAIjB,UAAM,cAAc,oBAAoB,KAAK,OAAO;AACpD,QAAI,aAAa;AACf,YAAM,CAAC,EAAE,QAAQ,UAAU,IAAI;AAG/B,YAAM,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI;AAC/C,YAAM,sBACJ,aAAa,KAAK,QAAQ,KAAK,cAAc,KAAK,QAAQ,KAAK,OAAO,KAAK,QAAQ;AACrF,UAAI,OAAO,UAAU,KAAK,IAAI,KAAK,aAAa,MAAM,CAAC,qBAAqB;AAC1E,cAAM,CAAC,IAAI;AAAA,GAAM,WAAW,KAAK,CAAC;AAAA,MACpC,OAAO;AACL,cAAM,CAAC,IAAI,IAAI,WAAW,KAAK,CAAC;AAAA,MAClC;AACA;AAAA,IACF;AAGA,UAAM,cAAc,uBAAuB,KAAK,IAAI;AACpD,QAAI,aAAa;AACf,YAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI;AAC3B,YAAM,CAAC,IAAI,GAAG,MAAM,UAAK,IAAI;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,MAAM,KAAK,IAAI;AAErB,SAAO;AACT;AAEO,SAAS,gBAAgB,MAAsB;AACpD,SAAO,gBAAgB,IAAI;AAC7B;;;ACpPA;AAaO,IAAM,gBAAN,MAAwC;AAAA,EAC7B,OAAO;AAAA,EACf,OAAuC,CAAC;AAAA,EACxC;AAAA;AAAA,EAEA,QAAiB;AAAA,EACjB,SAAiD;AAAA,EACjD,UAAkB;AAAA,EAClB,WAAmB;AAAA,EACnB,gBAAyB;AAAA,EAEjC,YAAY,QAA8B;AACxC,SAAK,MAAM,UAAU,CAAC;AAAA,EACxB;AAAA,EAEA,MAAM,KAA4B;AAChC,UAAM,MAAM,IAAI;AAGhB,QAAI;AACF,YAAM,YAAY,CAAC,EAChB,IAAY,SACZ,IAAY,eACZ,KAAK,KAAa,YACnB,QAAQ,IAAI;AAEd,UAAI,OAAO,KAAK,uCAAuC,SAAS,uBAAuB;AAAA,IACzF,QAAQ;AAAA,IAAC;AAGT,QAAI;AACF,YAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,UAAI,SAAS;AACX,cAAM,KAAU,QAAQ,SAAS,CAAC;AAClC,cAAM,KAAK,OAAO,GAAG,WAAW,GAAG;AACnC,cAAM,KAAK,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG;AAC7C,cAAM,OAAO,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG;AAC/C,cAAM,OAAO,OAAO,GAAG,QAAQ,GAAG;AAClC,cAAM,SAAS,OAAO,GAAG,aAAa,EAAE;AACxC,YAAI,OAAO;AAAA,UACT,iDAAiD,IAAI,YAAY,EAAE,OAAO,EAAE,MACzE,SAAS,cAAc,MAAM,KAAK,MACnC,SAAS,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAAC;AAGT,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,kBAAkB,OAAO,QAAa;AAC3C,cAAM,KAAM,OAAO,IAAI,WAAY;AAEnC,cAAM,KAAK,qBAAqB,KAAK,GAAG,SAAS,GAAG,MAAM,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC5E,CAAC;AAAA,IACH;AACA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,gBAAgB,OAAO,QAAa;AACzC,cAAM,KAAM,OAAO,IAAI,WAAY;AACnC,cAAM,UAAU,IAAI,OAAO,WAAW;AACtC,cAAM,KAAK,eAAe,KAAK,gBAAgB,SAAS,IAAI,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACrF,CAAC;AAAA,IACH;AAGA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,mBAAmB,OAAO,QAAa;AAC5C,cAAM,KAAM,OAAO,IAAI,WAAY;AACnC,YAAI,OAAO,GAAG,OAAO,eAAe,GAAG,OAAO,UAAU;AACtD,gBAAM,KAAK,kBAAkB,GAAG,EAAE,MAAM,MAAM;AAAA,UAAC,CAAC;AAAA,QAClD;AAAA,MACF,CAAC;AAAA,IACH;AACA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,YAAY,OAAO,QAAa;AACrC,cAAM,KAAM,OAAO,IAAI,WAAY;AACnC,cAAM,UAAU,IAAI,OAAO,WAAW;AACtC,cAAM,KAAK,eAAe,KAAK,cAAc,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACtE,CAAC;AAAA,IACH;AAEA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,kBAAkB,YAAY;AACnC,cAAM,KAAK,sBAAsB,GAAG,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACtD,CAAC;AAAA,IACH;AAGA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,uBAAuB,OAAO,QAAa;AAChD,YAAI;AACF,gBAAM,KAAM,OAAO,IAAI,WAAY;AACnC,cAAI,CAAC,MAAM,OAAO,GAAG,WAAW,YAAY,CAAC,GAAG,QAAS;AAEzD,cAAI,UAAU,GAAG;AACjB,cAAI,WAAW,GAAG;AAClB,cAAI,CAAC,WAAW,CAAC,UAAU;AACzB,kBAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,kBAAM,IAAS,SAAS;AACxB,kBAAM,YAAY,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,EAAE;AACnE,kBAAM,YAAY,OAAO,GAAG,WAAW,EAAE;AACzC,gBAAI,aAAa,WAAW;AAC1B,wBAAU,WAAW;AACrB,yBAAW,YAAY;AAAA,YACzB;AAAA,UACF;AACA,cAAI,CAAC,WAAW,CAAC,SAAU;AAG3B,gBAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,6BAAuB;AACtE,gBAAM,MAAM,sBAAsB;AAClC,gBAAM,OAAO,IAAI,WAAW,SAAS,QAAQ;AAC7C,gBAAM,OAAO,OAAO,GAAG,MAAM;AAC7B,cAAI,WAAW,SAAS,UAAU;AAAA,YAChC,WAAW,OAAO,GAAG,OAAO;AAAA,YAC5B,QAAQ;AAAA,YACR,iBAAiB,MAAM;AAAA,YACvB,gBAAiB,MAAM,iBAAiB,KAAK;AAAA,UAC/C,CAAC;AACD,cAAI;AACF,gBAAI,OAAO;AAAA,cACT,6DAA6D,OAAO,WAAW,QAAQ;AAAA,YACzF;AAAA,UACF,QAAQ;AAAA,UAAC;AAAA,QACX,SAAS,GAAG;AACV,cAAI;AACF,gBAAI,OAAO;AAAA,cACT,yDACE,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAC3C;AAAA,YACF;AAAA,UACF,QAAQ;AAAA,UAAC;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAGA,SAAK,KAAK;AAAA,MACR,IAAI,GAAG,iBAAiB,OAAO,QAAa;AAC1C,YAAI;AACF,gBAAM,KAAM,OAAO,IAAI,WAAY;AACnC,gBAAM,UAAU,OAAO,IAAI,WAAW,EAAE;AACxC,gBAAM,WAAW,OAAO,IAAI,YAAY,EAAE;AAC1C,gBAAM,WAAW,OAAO,IAAI,YAAY,EAAE;AAC1C,cAAI,CAAC,WAAW,CAAC,YAAY,CAAC,SAAU;AACxC,gBAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,6BAAuB;AACtE,gBAAM,MAAM,sBAAsB;AAClC,cAAI,OAAO,SAAS,UAAU,EAAE,cAAc,SAAS,CAAC;AACxD,cAAI;AACF,gBAAI,OAAO;AAAA,cACT,8DAA8D,QAAQ;AAAA,YACxE;AAAA,UACF,QAAQ;AAAA,UAAC;AAAA,QACX,QAAQ;AAAA,QAAC;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAa;AACX,eAAW,KAAK,KAAK,KAAM,GAAE,YAAY;AACzC,SAAK,OAAO,CAAC;AAAA,EACf;AAAA,EAEQ,SAAS,KAAuC;AAEtD,UAAM,WAAY,IAAY,SAAU,IAAY;AACpD,QAAI,SAAU,QAAO;AAErB,QAAI;AACF,YAAM,QAAS,KAAK,KAAa,YAAY,QAAQ,IAAI;AACzD,UAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AAC7C,eAAO,IAAI,YAAY,MAAM,KAAK,CAAC;AAAA,MACrC;AAAA,IACF,QAAQ;AAAA,IAAC;AACT,WAAO;AAAA,EACT;AAAA,EAEQ,uBAAuB,KAAkC;AAC/D,QAAI;AACF,YAAM,SAAc,IAAI,UAAU,CAAC;AACnC,YAAM,WAAgB,OAAO,SAAS,CAAC;AACvC,YAAM,WAAmB,SAAS,YAAY;AAC9C,YAAM,UAAgB,IAAY,gBAAgB,aAAa,IAAI,QAAQ;AAC3E,aAAO,WAAW;AAAA,IACpB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,qBAAqB,KAA8D;AACzF,QAAI;AACF,YAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,YAAM,KAAU,SAAS;AACzB,YAAM,UAAU,OAAO,IAAI,WAAW,EAAE;AACxC,YAAM,KAAK,OAAO,IAAI,MAAM,IAAI,YAAY,EAAE;AAC9C,UAAI,WAAW,GAAI,QAAO,EAAE,SAAS,GAAG;AAAA,IAC1C,QAAQ;AAAA,IAAC;AACT,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,KAA+B;AACxD,QAAI;AACF,YAAM,SAAc,IAAI,UAAU,CAAC;AACnC,YAAM,WAAgB,OAAO,SAAS,CAAC;AACvC,YAAM,eAAe,SAAS,aAAc,KAAK,KAAa;AAC9D,aACE,iBAAiB,QAChB,gBAAgB,OAAO,iBAAiB,YAAY,aAAa,YAAY;AAAA,IAElF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,eACZ,KACA,OACA,SACA,SACe;AACf,QAAI,KAAK,cAAe;AACxB,QAAI,CAAC,KAAK,mBAAmB,GAAG,EAAG;AACnC,UAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,UAAM,KAAU,SAAS;AACzB,UAAM,UAAU,OAAO,IAAI,WAAW,EAAE;AACxC,UAAM,WAAW,OAAO,IAAI,aAAa,IAAI,MAAM,IAAI,YAAY,EAAE;AACrE,QAAI,CAAC,WAAW,CAAC,SAAU;AAE3B,QAAI,OAAO,UAAK,KAAK;AACrB,QAAI,QAAS,SAAQ;AAAA,SAAY,OAAO;AACxC,QAAI,QAAS,SAAQ;AAAA,EAAK,OAAO;AAEjC,UAAM,YAAY,KAAK,aAAa;AACpC,QAAI,WAAW,SAAS;AACtB,cAAQ;AAAA;AAAA,cAAmB,UAAU,OAAO;AAAA,IAC9C;AAEA,UAAM,gBAAgB,gBAAgB,IAAI;AAC1C,UAAM,MAAM,KAAK,YAAY,EAAE,SAAS,MAAM,eAAe,WAAW,SAAS,CAAC;AAClF,QAAI;AACF,UAAI,OAAO;AAAA,QACT,2CAA2C,OAAO,WAAW,QAAQ,UAAU,WAAW,KAAK;AAAA,MACjG;AAAA,IACF,QAAQ;AAAA,IAAC;AACT,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAc,sBAAsB,KAAqC;AACvE,QAAI,KAAK,MAAO;AAChB,UAAM,MAAM,KAAK,qBAAqB,GAAG;AACzC,QAAI,CAAC,IAAK;AACV,UAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,YAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,YAAM,KAAU,SAAS;AACzB,UAAI,IAAI,YAAY,cAAe;AAEnC,UAAI;AACF,cAAM,QAAQ,MAAM,MAAM,eAAe;AACzC,YAAI,SAAS,IAAI,QAAQ,OAAO,GAAG,IAAI,MAAM,OAAO,KAAK,EAAG;AAAA,MAC9D,QAAQ;AAAA,MAAC;AAAA,IACX,QAAQ;AAAA,IAAC;AAET,QAAI;AACF,YAAM,SAAc,IAAI,UAAU,CAAC;AACnC,YAAM,WAAgB,OAAO,SAAS,CAAC;AACvC,UAAI,UAAU,WAAW,YAAY,MAAO;AAC5C,WAAK,UAAU,UAAU,WAAW,OAAO,KAAK;AAChD,WAAK,WAAW,UAAU,WAAW,QAAQ,KAAK;AAAA,IACpD,QAAQ;AAAA,IAAC;AACT,UAAM,MAAM,UAAU,IAAI,EAAE,SAAS,IAAI,SAAS,WAAW,IAAI,IAAI,MAAM,KAAK,QAAQ,CAAC;AACzF,QAAI;AACF,UAAI,OAAO;AAAA,QACT,oDAAoD,KAAK,OAAO,aAAa,IAAI,OAAO,OAAO,IAAI,EAAE;AAAA,MACvG;AAAA,IACF,QAAQ;AAAA,IAAC;AACT,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAc,kBAAkB,KAAqC;AACnE,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,OAAQ;AACjC,UAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,QAAI,CAAC,MAAO;AACZ,QAAI;AACF,UAAI;AACF,cAAM,MAAM,UAAU,OAAO;AAAA,UAC3B,SAAS,KAAK,OAAO;AAAA,UACrB,WAAW,KAAK,OAAO;AAAA,UACvB,MAAM,KAAK;AAAA,QACb,CAAC;AAAA,MACH,QAAQ;AAAA,MAAC;AACT,YAAM,MAAM,UAAU,IAAI;AAAA,QACxB,SAAS,KAAK,OAAO;AAAA,QACrB,WAAW,KAAK,OAAO;AAAA,QACvB,MAAM,KAAK;AAAA,MACb,CAAC;AACD,UAAI;AACF,YAAI,OAAO;AAAA,UACT,uEAAuE,KAAK,QAAQ,aAAa,KAAK,OAAO,OAAO,OAAO,KAAK,OAAO,EAAE;AAAA,QAC3I;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX,UAAE;AAEA,WAAK,QAAQ;AACb,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,qBACZ,KACA,SACA,QACe;AACf,QAAI;AACF,YAAM,MAAW,IAAI,UAAU,CAAC;AAChC,YAAM,WAAgB,IAAI,SAAS,OAAO;AAC1C,UAAI,CAAC,SAAU;AAIf,YAAM,YAAkB,IAAY,SAAS,CAAC;AAC9C,YAAM,gBACJ,UAAU,oBAAoB,QAAS,KAAK,KAAa,kBAAkB;AAC7E,YAAM,eAAe,UAAU,aAAc,KAAK,KAAa;AAE/D,YAAM,eAAgB,SAAS,QAAmB;AAClD,YAAM,OAAO,iBAAiB;AAC9B,YAAM,YAAY,iBAAiB,SAAS,SAAS,UAAU;AAC/D,UAAI,CAAC,QAAQ,CAAC,UAAW;AAGzB,UAAI,SAAS,gBAAgB,WAAY;AAGzC,UAAI,MAAM;AACR,cAAM,SAAS,SAAS;AAExB,YAAI,OAAO,WAAW,UAAU;AAC9B,gBAAM,gBAAgB,CAAC,eAAe,YAAY,QAAQ,OAAO;AACjE,cAAI,CAAC,cAAc,SAAS,MAAM,EAAG;AAAA,QACvC;AAAA,MAEF;AAEA,YAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,UAAI,CAAC,MAAO;AAEZ,YAAM,UAAU,KAAK,uBAAuB,GAAG;AAC/C,YAAM,KAAU,SAAS;AACzB,YAAM,UAAU,OAAO,IAAI,WAAW,EAAE;AACxC,YAAM,WAAW,OAAO,IAAI,aAAa,IAAI,MAAM,IAAI,YAAY,EAAE;AACrE,UAAI,CAAC,WAAW,CAAC,SAAU;AAG3B,YAAM,MAAY,QAAgB;AAClC,UAAI;AACJ,UAAI,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,EAAE,SAAS,GAAG;AACrE,eAAO,IAAI,KAAK,KAAK;AAAA,MACvB,WAAW,QAAQ,OAAO,SAAS,WAAW,UAAU;AACtD,YACE,OAAQ,QAAgB,YAAY,YACnC,OAAe,QAAQ,KAAK,EAAE,SAAS,GACxC;AACA,iBAAQ,OAAe,QAAQ,KAAK;AAAA,QACtC;AAAA,MACF,WAAW,aAAa,OAAQ,QAAgB,cAAc,UAAU;AAGtE,cAAM,MAAO,OAAe;AAC5B,YAAI,IAAI,KAAK,EAAE,SAAS,GAAG;AACzB,iBAAO,IAAI,KAAK;AAAA,QAClB;AAAA,MACF,WAAW,QAAQ,iBAAiB,QAAQ,QAAW;AACrD,YAAI;AACF,iBAAO,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,QACpC,QAAQ;AACN,iBAAO,OAAO,GAAG;AAAA,QACnB;AAAA,MACF;AACA,UAAI,CAAC,KAAM;AAGX,YAAM,WAAW,uBAAuB,IAAI;AAC5C,UAAI,gBAAgB;AAEpB,UAAI,SAAS,SAAS,GAAG;AACvB,YAAI;AACF,cAAI,OAAO;AAAA,YACT,0BAA0B,SAAS,MAAM,qCAAqC,OAAO;AAAA,UACvF;AAAA,QACF,QAAQ;AAAA,QAAC;AAGT,cAAM,gBAA0B,CAAC;AACjC,iBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,gBAAM,UAAU,SAAS,CAAC;AAC1B,cAAI;AACF,gBAAI,OAAO,KAAK,8CAA8C,IAAI,CAAC,KAAK;AACxE,kBAAM,YAAY,MAAM,mBAAmB,QAAQ,IAAI;AACvD,gBAAI,WAAW;AACb,kBAAI,OAAO;AAAA,gBACT,qCAAqC,IAAI,CAAC,UAAU,UAAU,MAAM;AAAA,cACtE;AACA,oBAAM,WAAW,WAAW,IAAI,CAAC;AACjC,oBAAM,eAAe,MAAM,MAAM,MAAM,SAAS;AAAA,gBAC9C,SAAS;AAAA,gBACT;AAAA,gBACA;AAAA,gBACA,WAAW;AAAA,gBACX,OAAO,WAAW,IAAI,CAAC;AAAA,cACzB,CAAC;AACD,kBAAI,aAAa,IAAI;AACnB,8BAAc,KAAK,CAAC;AACpB,oBAAI,OAAO,KAAK,6CAA6C,IAAI,CAAC,OAAO,OAAO,EAAE;AAAA,cACpF,OAAO;AACL,oBAAI,OAAO,KAAK,8CAA8C,IAAI,CAAC,EAAE;AAAA,cACvE;AAAA,YACF,OAAO;AACL,kBAAI,OAAO;AAAA,gBACT,gEAAgE,IAAI,CAAC;AAAA,cACvE;AAAA,YACF;AAAA,UACF,SAAS,GAAG;AACV,gBAAI,OAAO;AAAA,cACT,4DAA4D,IAAI,CAAC,KAC/D,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAC3C;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAGA,YAAI,cAAc,SAAS,GAAG;AAC5B,0BAAgB;AAAA,YAAqB;AAAA,YAAM;AAAA,YAAU,SACnD,cAAc,SAAS,GAAG,IAAI,0BAA0B;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB;AACpB,YAAM,mBACJ,iBAAiB,QAChB,gBAAgB,OAAO,iBAAiB,YAAY,aAAa,YAAY;AAChF,UAAI,kBAAkB;AACpB,cAAM,YAAY,KAAK,aAAa;AACpC,YAAI,WAAW,SAAS;AACtB,gBAAM,SAAS,eAAe,UAAU,OAAO;AAC/C,0BAAgB,GAAG,aAAa;AAAA;AAAA,EAAO,MAAM;AAAA,QAC/C;AAAA,MACF;AAEA,YAAM,gBAAgB,gBAAgB,aAAa;AACnD,YAAM,MAAM,KAAK,YAAY,EAAE,SAAS,MAAM,eAAe,WAAW,SAAS,CAAC;AAClF,UAAI,OAAO;AAAA,QACT,wCAAwC,OAAO,OAAO,OAAO,WAAW,QAAQ;AAAA,MAClF;AAAA,IACF,SAAS,UAAU;AAEjB,UAAI;AACF,YAAI,OAAO;AAAA,UACT,oDAAoD,OAAO,KACzD,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ,CAChE;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,eAA2D;AACjE,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,QAAU,OAAO,CAAC;AAC7C,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,MAAM,KAAK,YAAY;AAC7B,UAAI,CAAC,OAAO,CAAC,IAAI,QAAS,QAAO;AACjC,aAAO,EAAE,SAAS,IAAI,SAAS,QAAQ,IAAI,OAAO;AAAA,IACpD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}