diff --git a/README.md b/README.md index 20cf84c..2d4fdd7 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,9 @@ npm install @mobile-reality/mdma-prompt-pack # Validation — static analysis for MDMA documents npm install @mobile-reality/mdma-validator + +# CLI — interactive prompt builder + document validation +npx @mobile-reality/mdma-cli ``` All packages are published under the [`@mobile-reality`](https://www.npmjs.com/org/mobile-reality) npm org. @@ -185,7 +188,8 @@ function App({ ast, store }) { | `@mobile-reality/mdma-renderer-react` | React rendering layer with components for all 9 MDMA types and hooks for state access. Provides `MdmaDocument` for full-document rendering and `useComponentState`/`useBinding` for fine-grained reactivity. | | `@mobile-reality/mdma-prompt-pack` | System prompts that teach LLMs how to author valid MDMA documents. Exports `buildSystemPrompt()` to combine the full spec reference with optional custom instructions for domain-specific generation. | | `@mobile-reality/mdma-validator` | Static analysis engine with 10 lint rules covering YAML correctness, schema conformance, ID uniqueness, binding resolution, and PII sensitivity. Powers programmatic validation in CI pipelines and custom tooling. | -| `@mobile-reality/mdma-evals` | LLM evaluation suite built on promptfoo with 3 test suites: base generation quality (25 tests), custom prompt compliance (10 tests), and multi-turn conversation handling (11 conversations, 25 turns). Validates that AI-generated MDMA documents are structurally correct and semantically appropriate. | +| `@mobile-reality/mdma-cli` | Interactive CLI tool for creating custom MDMA prompts. Opens a local web app where you visually select components, configure fields, set domain rules and trigger conditions, then an LLM generates a tailored `customPrompt` for use with `buildSystemPrompt()`. Also includes a `validate` command for static document analysis. | +| `@mobile-reality/mdma-evals` | LLM evaluation suite built on promptfoo with 4 test suites: base generation quality (25 tests), custom prompt compliance (10 tests), multi-turn conversation handling (11 conversations, 25 turns), and prompt builder verification (25 tests). Validates that AI-generated MDMA documents are structurally correct and semantically appropriate. | ## Architecture @@ -197,6 +201,7 @@ function App({ ast, store }) { └── @mobile-reality/mdma-runtime State / events / policy engine └── @mobile-reality/mdma-attachables-core Component handlers └── @mobile-reality/mdma-renderer-react React components +@mobile-reality/mdma-cli CLI prompt builder + validation @mobile-reality/mdma-evals LLM evaluation suite (promptfoo) ``` @@ -208,6 +213,35 @@ pnpm build pnpm test ``` +## CLI + +Interactive prompt builder for creating custom MDMA prompts. + +```bash +# Run the prompt builder — opens a web app in your browser +npx @mobile-reality/mdma-cli + +# Validate MDMA documents +npx @mobile-reality/mdma-cli validate "docs/**/*.md" +npx @mobile-reality/mdma-cli validate "docs/**/*.md" --fix # auto-fix issues +npx @mobile-reality/mdma-cli validate "docs/**/*.md" --json # JSON output +``` + +The prompt builder walks you through: +1. **Pick components** — select from the 9 MDMA types (form, table, approval-gate, etc.) +2. **Configure** — define fields, options, roles, sensitive flags, and business rules +3. **Set triggers** — specify when the AI should generate MDMA components (keywords, contextual conditions) +4. **Generate** — an LLM creates a tailored `customPrompt` based on your configuration +5. **Export** — copy the result and use it in your app: + +```typescript +import { buildSystemPrompt } from '@mobile-reality/mdma-prompt-pack'; + +const systemPrompt = buildSystemPrompt({ + customPrompt: '', +}); +``` + ## Evals LLM evaluation suite using [promptfoo](https://www.promptfoo.dev/) to verify MDMA generation quality. @@ -222,6 +256,9 @@ pnpm eval:custom # Run multi-turn conversation tests (25 turns across 11 conversations) pnpm eval:conversation +# Run prompt builder tests (25 tests) +pnpm eval:prompt-builder + # Run all eval suites pnpm eval:all @@ -241,15 +278,15 @@ pnpm eval:view ### v0.2 — Developer Experience - [ ] More examples (10+ real-world use cases) -- [ ] CLI tool for prompt creation (MDMA flows) +- [x] CLI tool for prompt creation (MDMA flows) - [ ] Improved error messages in parser and validator -- [ ] Webhook execution engine (real HTTP calls in production environments) - [ ] File upload field type for forms ### v0.3 — AI & Generation - [ ] Multi-model eval coverage (Claude, GPT-4o, Gemini, Llama) - [ ] Prompt tuning toolkit — test and compare custom prompts - [ ] Agent-friendly SDK — let AI agents fill forms and trigger actions programmatically +- [ ] Webhook execution engine (real HTTP calls in production environments) ### v1.0 — Production Ready - [ ] Stable API with semantic versioning guarantees diff --git a/evals/assertions/mentions-fields.mjs b/evals/assertions/mentions-fields.mjs new file mode 100644 index 0000000..b1b68b9 --- /dev/null +++ b/evals/assertions/mentions-fields.mjs @@ -0,0 +1,34 @@ +/** + * Asserts that the generated prompt mentions a minimum percentage of the + * configured field names. + * + * config.fields: string[] — field names to look for + * config.minRatio: number — minimum ratio of fields that must appear (default: 0.5) + */ +export default function (output, { config }) { + const fields = config?.fields || []; + const minRatio = config?.minRatio ?? 0.5; + + if (fields.length === 0) { + return { pass: true, score: 1, reason: 'No fields to check' }; + } + + const lower = output.toLowerCase(); + const found = fields.filter((f) => lower.includes(f.toLowerCase())); + const ratio = found.length / fields.length; + + if (ratio >= minRatio) { + return { + pass: true, + score: ratio, + reason: `Found ${found.length}/${fields.length} field names (${(ratio * 100).toFixed(0)}%)`, + }; + } + + const missing = fields.filter((f) => !lower.includes(f.toLowerCase())); + return { + pass: false, + score: ratio, + reason: `Only found ${found.length}/${fields.length} field names (need ${(minRatio * 100).toFixed(0)}%). Missing: ${missing.join(', ')}`, + }; +} diff --git a/evals/assertions/mentions-trigger.mjs b/evals/assertions/mentions-trigger.mjs new file mode 100644 index 0000000..08bbff4 --- /dev/null +++ b/evals/assertions/mentions-trigger.mjs @@ -0,0 +1,67 @@ +/** + * Asserts that the generated customPrompt includes trigger/when-to-generate + * instructions matching the configured trigger mode. + * + * config.mode: 'keyword' | 'immediate' | 'contextual' + * config.keywords: string[] — for keyword mode, specific phrases to check + * config.contextHints: string[] — for contextual mode, hints to look for + */ +export default function (output, { config }) { + const mode = config?.mode; + const lower = output.toLowerCase(); + + if (mode === 'keyword') { + const keywords = config?.keywords || []; + if (keywords.length === 0) { + return { pass: true, score: 1, reason: 'No keywords to check' }; + } + const found = keywords.filter((kw) => lower.includes(kw.toLowerCase())); + if (found.length > 0) { + return { + pass: true, + score: found.length / keywords.length, + reason: `Found ${found.length}/${keywords.length} trigger keywords: ${found.join(', ')}`, + }; + } + return { + pass: false, + score: 0, + reason: `None of the trigger keywords found: ${keywords.join(', ')}`, + }; + } + + if (mode === 'immediate') { + const markers = /immediate|first message|always|conversation start|right away/; + if (markers.test(lower)) { + return { pass: true, score: 1, reason: 'Found immediate trigger instruction' }; + } + return { pass: false, score: 0, reason: 'Missing immediate trigger instruction' }; + } + + if (mode === 'contextual') { + const hints = config?.contextHints || []; + if (hints.length === 0) { + // At least check for contextual-sounding language + const contextMarkers = /when.*user|after.*attempt|if.*express|condition|context/; + if (contextMarkers.test(lower)) { + return { pass: true, score: 1, reason: 'Found contextual trigger language' }; + } + return { pass: false, score: 0, reason: 'Missing contextual trigger language' }; + } + const found = hints.filter((h) => lower.includes(h.toLowerCase())); + if (found.length > 0) { + return { + pass: true, + score: found.length / hints.length, + reason: `Found ${found.length}/${hints.length} context hints`, + }; + } + return { + pass: false, + score: 0, + reason: `None of the contextual hints found: ${hints.join(', ')}`, + }; + } + + return { pass: true, score: 1, reason: 'No trigger mode specified' }; +} diff --git a/evals/assertions/no-spec-repetition.mjs b/evals/assertions/no-spec-repetition.mjs new file mode 100644 index 0000000..970737a --- /dev/null +++ b/evals/assertions/no-spec-repetition.mjs @@ -0,0 +1,35 @@ +/** + * Asserts that the generated customPrompt does NOT repeat the full MDMA spec. + * + * A customPrompt should layer domain-specific instructions on top of the spec, + * not duplicate it. Checks for spec-level content that should not appear. + */ +export default function (output) { + const specMarkers = [ + { pattern: 'MDMA_AUTHOR_PROMPT', label: 'MDMA_AUTHOR_PROMPT reference' }, + { pattern: '## Self-Check Checklist', label: 'Self-check checklist' }, + { pattern: 'Component Reference Table', label: 'Component reference table' }, + { pattern: 'MUST be inside a fenced code block tagged', label: 'Base authoring rule' }, + ]; + + const found = []; + for (const marker of specMarkers) { + if (output.includes(marker.pattern)) { + found.push(marker.label); + } + } + + if (found.length === 0) { + return { + pass: true, + score: 1, + reason: 'No MDMA spec content repeated', + }; + } + + return { + pass: false, + score: 0, + reason: `CustomPrompt repeats MDMA spec content: ${found.join(', ')}`, + }; +} diff --git a/evals/assertions/prompt-has-sections.mjs b/evals/assertions/prompt-has-sections.mjs new file mode 100644 index 0000000..cda19a9 --- /dev/null +++ b/evals/assertions/prompt-has-sections.mjs @@ -0,0 +1,43 @@ +/** + * Asserts that the generated customPrompt contains the expected structural sections. + * + * A well-structured customPrompt should include most of these elements: + * - Domain/role context + * - When to generate / trigger rules + * - Component instructions + * - Workflow or constraints + * + * Pass required section keywords via config.sections (array of regex patterns). + * By default checks for broad structural markers. + */ +export default function (output, { config }) { + const sections = config?.sections || [ + 'domain|workflow|role|assist', + 'form|component|field', + 'sensitive|pii|personal', + ]; + + const lower = output.toLowerCase(); + const missing = []; + + for (const pattern of sections) { + const regex = new RegExp(pattern, 'i'); + if (!regex.test(lower)) { + missing.push(pattern); + } + } + + if (missing.length === 0) { + return { + pass: true, + score: 1, + reason: `All ${sections.length} expected section markers found`, + }; + } + + return { + pass: false, + score: (sections.length - missing.length) / sections.length, + reason: `Missing section markers: ${missing.join(', ')}`, + }; +} diff --git a/evals/assertions/prompt-length.mjs b/evals/assertions/prompt-length.mjs new file mode 100644 index 0000000..088cafe --- /dev/null +++ b/evals/assertions/prompt-length.mjs @@ -0,0 +1,33 @@ +/** + * Asserts that the generated customPrompt is within a reasonable length range. + * + * config.min: minimum chars (default 200) + * config.max: maximum chars (default 8000) + */ +export default function (output, { config }) { + const min = config?.min ?? 200; + const max = config?.max ?? 8000; + const len = output.length; + + if (len < min) { + return { + pass: false, + score: len / min, + reason: `Output too short: ${len} chars (minimum ${min})`, + }; + } + + if (len > max) { + return { + pass: false, + score: max / len, + reason: `Output too long: ${len} chars (maximum ${max})`, + }; + } + + return { + pass: true, + score: 1, + reason: `Output length ${len} chars (within ${min}-${max})`, + }; +} diff --git a/evals/assertions/validate-mdma-examples.mjs b/evals/assertions/validate-mdma-examples.mjs new file mode 100644 index 0000000..0101755 --- /dev/null +++ b/evals/assertions/validate-mdma-examples.mjs @@ -0,0 +1,60 @@ +import { validate } from '@mobile-reality/mdma-validator'; + +/** + * Extracts ```mdma blocks from a customPrompt and validates each one + * as a standalone MDMA document. + * + * Unlike validate-mdma.mjs (which validates the entire output as a document), + * this assertion handles the case where mdma blocks are embedded as examples + * inside instructional prose. + */ +export default function (output) { + const blockRegex = /```mdma\n([\s\S]*?)```/g; + const blocks = [...output.matchAll(blockRegex)]; + + if (blocks.length === 0) { + return { + pass: true, + score: 1, + reason: 'No mdma example blocks to validate (OK for customPrompt)', + }; + } + + const errors = []; + let validCount = 0; + + for (let i = 0; i < blocks.length; i++) { + const blockContent = blocks[i][1].trim(); + // Wrap each block back into a markdown document for the validator + const doc = `\`\`\`mdma\n${blockContent}\n\`\`\``; + + const result = validate(doc, { + exclude: ['thinking-block'], + autoFix: false, + }); + + if (result.ok) { + validCount++; + } else { + const blockErrors = result.issues + .filter((issue) => issue.severity === 'error') + .map((issue) => `[${issue.ruleId}] ${issue.message}`) + .join('; '); + errors.push(`Block ${i + 1}: ${blockErrors}`); + } + } + + if (errors.length === 0) { + return { + pass: true, + score: 1, + reason: `All ${validCount} mdma example block(s) are valid MDMA`, + }; + } + + return { + pass: false, + score: validCount / blocks.length, + reason: `${errors.length}/${blocks.length} mdma block(s) have validation errors:\n${errors.join('\n')}`, + }; +} diff --git a/evals/assertions/yaml-not-json.mjs b/evals/assertions/yaml-not-json.mjs new file mode 100644 index 0000000..ef2655a --- /dev/null +++ b/evals/assertions/yaml-not-json.mjs @@ -0,0 +1,58 @@ +/** + * Asserts that all ```mdma blocks in the output use YAML syntax, not JSON. + * + * Checks: + * - No block starts with { or [ + * - No block contains "type": or "fields": (JSON keys) + * - Every block starts with a YAML key: value pattern (e.g. type: form) + */ +export default function (output) { + const blocks = [...output.matchAll(/```mdma\n([\s\S]*?)```/g)]; + + if (blocks.length === 0) { + // No mdma blocks in a generated customPrompt is acceptable + // (the prompt might describe components without embedding code blocks) + return { pass: true, score: 1, reason: 'No mdma blocks to check (OK for customPrompt)' }; + } + + const issues = []; + + for (let i = 0; i < blocks.length; i++) { + const content = blocks[i][1].trim(); + const blockLabel = `block ${i + 1}`; + + if (content.startsWith('{') || content.startsWith('[')) { + issues.push(`${blockLabel}: starts with JSON syntax`); + } + + if (/"type"\s*:/.test(content)) { + issues.push(`${blockLabel}: contains JSON "type": key`); + } + + if (/"fields"\s*:/.test(content)) { + issues.push(`${blockLabel}: contains JSON "fields": key`); + } + + if (/"id"\s*:/.test(content)) { + issues.push(`${blockLabel}: contains JSON "id": key`); + } + + if (!/^[a-zA-Z_-]+:\s/.test(content)) { + issues.push(`${blockLabel}: does not start with YAML key: value`); + } + } + + if (issues.length === 0) { + return { + pass: true, + score: 1, + reason: `All ${blocks.length} mdma block(s) use valid YAML syntax`, + }; + } + + return { + pass: false, + score: 0, + reason: `JSON detected in mdma blocks:\n${issues.join('\n')}`, + }; +} diff --git a/evals/package.json b/evals/package.json index 0f6934b..7a9dcf0 100644 --- a/evals/package.json +++ b/evals/package.json @@ -6,10 +6,12 @@ "eval": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write; exit 0", "eval:custom": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.custom.yaml; exit 0", "eval:conversation": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.conversation.yaml; exit 0", - "eval:all": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write; PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.custom.yaml; PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.conversation.yaml; exit 0", + "eval:prompt-builder": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.prompt-builder.yaml; exit 0", + "eval:all": "PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write; PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.custom.yaml; PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.conversation.yaml; PROMPTFOO_DISABLE_DATABASE=1 promptfoo eval --no-write -c promptfooconfig.prompt-builder.yaml; exit 0", "eval:view": "promptfoo view" }, "dependencies": { + "@mobile-reality/mdma-cli": "workspace:*", "@mobile-reality/mdma-prompt-pack": "workspace:*", "@mobile-reality/mdma-validator": "workspace:*", "promptfoo": "0.109.0" diff --git a/evals/prompt-builder.mjs b/evals/prompt-builder.mjs new file mode 100644 index 0000000..70a81a3 --- /dev/null +++ b/evals/prompt-builder.mjs @@ -0,0 +1,18 @@ +import { MASTER_PROMPT } from '@mobile-reality/mdma-cli/prompts'; + +/** + * Promptfoo prompt function for CLI Prompt Builder eval. + * + * Sends the Master Prompt as the system message and the user's + * serialized configuration as the user message. The LLM should + * generate a `customPrompt` — a domain-specific prompt that uses + * correct YAML-based MDMA examples. + */ +export default function ({ vars }) { + const escaped = MASTER_PROMPT.replaceAll('{{', '{% raw %}{{').replaceAll('}}', '}}{% endraw %}'); + + return [ + { role: 'system', content: escaped }, + { role: 'user', content: vars.request }, + ]; +} diff --git a/evals/promptfooconfig.prompt-builder.yaml b/evals/promptfooconfig.prompt-builder.yaml new file mode 100644 index 0000000..edb7919 --- /dev/null +++ b/evals/promptfooconfig.prompt-builder.yaml @@ -0,0 +1,30 @@ +# CLI Prompt Builder — promptfoo evaluation config +# +# Tests the Master Prompt's ability to generate correct `customPrompt` values. +# The LLM receives the Master Prompt as system + serialized user config as user message, +# and must generate a domain-specific prompt with YAML examples (not JSON). +# +# Run: pnpm eval:prompt-builder +# View: pnpm eval:view + +description: CLI Prompt Builder Eval + +envPath: .env +outputPath: results-prompt-builder.json + +prompts: + - file://prompt-builder.mjs + +providers: + - openai:gpt-4.1 + +defaultTest: + assert: + # Every generated customPrompt must use YAML, not JSON + - type: javascript + value: file://assertions/yaml-not-json.mjs + # Validate any embedded mdma blocks are structurally correct MDMA + - type: javascript + value: file://assertions/validate-mdma-examples.mjs + +tests: tests-prompt-builder.yaml diff --git a/evals/tests-prompt-builder.yaml b/evals/tests-prompt-builder.yaml new file mode 100644 index 0000000..b1be3d7 --- /dev/null +++ b/evals/tests-prompt-builder.yaml @@ -0,0 +1,1385 @@ +# CLI Prompt Builder — Eval Test Cases +# +# Each test sends a serialized user configuration to the Master Prompt. +# The LLM generates a `customPrompt` that should: +# - Use YAML (not JSON) in any mdma code block examples +# - Include domain-specific instructions +# - Reference the configured fields, trigger rules, and sensitive flags +# - NOT repeat the MDMA spec + +# --------------------------------------------------------------------------- +# 1. KYC Verification — keyword trigger, finance domain +# --------------------------------------------------------------------------- +- description: "KYC verification flow with keyword triggers" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** kyc-verification + **Domain:** finance + **Description:** KYC case review flow that collects applicant identity data, runs compliance checks, and requires dual approval before account activation. + **Business Rules:** Government ID and date of birth must be marked sensitive. Require 2 approvers with roles: compliance-officer, senior-analyst. PEP screening and sanctions list checks are mandatory before approval. + **When to Display Components:** When the user says one of these keywords or phrases: start KYC review, new customer verification, verify identity. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - full_name (text, label: "Full Legal Name", required: true, sensitive: false) + - date_of_birth (date, label: "Date of Birth", required: true, sensitive: true) + - nationality (text, label: "Nationality", required: true, sensitive: false) + - id_number (text, label: "Government ID Number", required: true, sensitive: true) + - email (email, label: "Email Address", required: true, sensitive: true) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/prompt-has-sections.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["KYC", "verify identity", "customer verification"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["full_name", "date_of_birth", "id_number", "email", "nationality"] + minRatio: 0.6 + - type: icontains + value: "sensitive" + - type: icontains + value: "financ" + +# --------------------------------------------------------------------------- +# 2. Patient Intake — immediate trigger, healthcare domain +# --------------------------------------------------------------------------- +- description: "Patient intake with immediate trigger and HIPAA rules" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** patient-intake + **Domain:** healthcare + **Description:** Patient intake and clinical assessment form that gathers demographics, insurance info, medical history, and current symptoms before routing to the appropriate care team. + **Business Rules:** All patient data fields (SSN, DOB, insurance ID) must be sensitive. HIPAA compliance required. Physician approval gate needed before treatment plan activation. Allergies and medications are required fields. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - patient_name (text, label: "Patient Full Name", required: true, sensitive: true) + - date_of_birth (date, label: "Date of Birth", required: true, sensitive: true) + - ssn (text, label: "Social Security Number", required: true, sensitive: true) + - insurance_id (text, label: "Insurance ID", required: true, sensitive: true) + - allergies (textarea, label: "Known Allergies", required: true, sensitive: false) + - medications (textarea, label: "Current Medications", required: true, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/prompt-has-sections.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["patient_name", "date_of_birth", "ssn", "insurance_id", "allergies", "medications"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "healthcare" + +# --------------------------------------------------------------------------- +# 3. Customer Escalation — contextual trigger +# --------------------------------------------------------------------------- +- description: "Customer escalation with contextual trigger conditions" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** customer-escalation + **Domain:** customer-ops + **Description:** Customer escalation workflow for high-priority support tickets. Captures customer details, issue history, and sentiment, then triggers internal review and resolution tracking. + **Business Rules:** Customer email and phone are PII. Escalations open > 24 hours require manager approval. Resolution must include a customer satisfaction follow-up task. CRM webhook fires on status change. + **When to Display Components:** After 3 failed resolution attempts in the conversation, or when the customer expresses frustration and asks for a supervisor. + + **Selected Components:** + + ### form + Fields: + - customer_name (text, label: "Customer Name", required: true, sensitive: false) + - customer_email (email, label: "Customer Email", required: true, sensitive: true) + - customer_phone (text, label: "Customer Phone", required: false, sensitive: true) + - ticket_id (text, label: "Original Ticket ID", required: true, sensitive: false) + - priority (select, label: "Escalation Priority", required: true, sensitive: false) + - issue_summary (textarea, label: "Issue Summary", required: true, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/prompt-has-sections.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: contextual + contextHints: ["frustrat", "supervisor", "failed", "attempt", "escalat"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["customer_name", "customer_email", "ticket_id", "priority", "issue_summary"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + +# --------------------------------------------------------------------------- +# 4. Incident Triage — keyword trigger, engineering domain +# --------------------------------------------------------------------------- +- description: "Incident triage with severity-based approval rules" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** incident-triage + **Domain:** engineering + **Description:** Production incident triage workflow that captures severity, affected services, and timeline, then routes through an on-call approval gate before executing remediation steps. + **Business Rules:** Severity P1/P2 incidents require VP-level approval. All incidents must have a root cause analysis tasklist completed within 48 hours. Slack and PagerDuty webhooks must fire on escalation. + **When to Display Components:** When the user says one of these keywords or phrases: incident, outage, service down, production issue. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - incident_title (text, label: "Incident Title", required: true, sensitive: false) + - severity (select, label: "Severity Level", required: true, sensitive: false) + - affected_services (textarea, label: "Affected Services", required: true, sensitive: false) + - start_time (date, label: "Incident Start Time", required: true, sensitive: false) + - reporter_email (email, label: "Reporter Email", required: true, sensitive: true) + - customer_impact (textarea, label: "Customer Impact Description", required: true, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/prompt-has-sections.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["incident", "outage", "service down", "production issue"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["incident_title", "severity", "affected_services", "reporter_email", "customer_impact"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + +# --------------------------------------------------------------------------- +# 5. Vendor Onboarding — keyword trigger, procurement domain +# --------------------------------------------------------------------------- +- description: "Vendor onboarding with financial PII and multi-gate approval" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** vendor-onboarding + **Domain:** procurement + **Description:** New vendor onboarding flow that collects company info, tax documents, banking details, and compliance certifications before activating the vendor in the payment system. + **Business Rules:** Bank account number and tax ID are sensitive. Require legal review approval and finance approval (2 gates). W-9 or W-8BEN verification must be completed. Contracts over $50k need VP sign-off. + **When to Display Components:** When the user says one of these keywords or phrases: add new vendor, onboard supplier, register vendor. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - company_name (text, label: "Company Legal Name", required: true, sensitive: false) + - tax_id (text, label: "Tax ID / EIN", required: true, sensitive: true) + - contact_email (email, label: "Primary Contact Email", required: true, sensitive: true) + - contact_name (text, label: "Primary Contact Name", required: true, sensitive: false) + - bank_account (text, label: "Bank Account Number", required: true, sensitive: true) + - routing_number (text, label: "Bank Routing Number", required: true, sensitive: true) + - contract_value (number, label: "Annual Contract Value ($)", required: true, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/prompt-has-sections.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["vendor", "onboard", "supplier"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["company_name", "tax_id", "bank_account", "routing_number", "contact_email", "contract_value"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "procurement" + +# --------------------------------------------------------------------------- +# 6. Loan Application — immediate trigger, form + approval-gate + tasklist +# --------------------------------------------------------------------------- +- description: "Loan application with multi-component workflow" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** loan-application + **Domain:** banking + **Description:** Consumer loan application workflow. Collects applicant financial data, runs credit checks via tasklist, and routes through underwriter approval before disbursement. + **Business Rules:** SSN and income are sensitive. Credit score must be collected. Require 1 underwriter approval. Loans over $100k need senior underwriter. Debt-to-income ratio must be calculated. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - applicant_name (text, label: "Applicant Full Name", required: true, sensitive: false) + - ssn (text, label: "Social Security Number", required: true, sensitive: true) + - annual_income (number, label: "Annual Income ($)", required: true, sensitive: true) + - employment_status (select, label: "Employment Status", required: true, sensitive: false) + - loan_amount (number, label: "Requested Loan Amount ($)", required: true, sensitive: false) + - loan_purpose (select, label: "Loan Purpose", required: true, sensitive: false) + + ### approval-gate + Title: Underwriter Approval + Required approvers: 1 + Allowed roles: underwriter, senior-underwriter + + ### tasklist + Items: Verify identity, Pull credit report, Calculate DTI ratio, Check collateral, Review bank statements + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["applicant_name", "ssn", "annual_income", "loan_amount", "loan_purpose"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "approval" + +# --------------------------------------------------------------------------- +# 7. Restaurant Order — keyword trigger, form + table + button +# --------------------------------------------------------------------------- +- description: "Restaurant order flow with table and button" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** restaurant-order + **Domain:** hospitality + **Description:** Digital restaurant ordering assistant that takes customer orders, displays the current menu in a table, and provides an order submission button. + **Business Rules:** No PII fields needed. Menu table should be sortable by price. Order form should capture table number, items, and special dietary notes. Confirm button triggers kitchen webhook. + **When to Display Components:** When the user says one of these keywords or phrases: order food, see menu, place order, what's on the menu. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - table_number (number, label: "Table Number", required: true, sensitive: false) + - items (textarea, label: "Order Items", required: true, sensitive: false) + - dietary_notes (textarea, label: "Dietary Restrictions / Allergies", required: false, sensitive: false) + - special_requests (text, label: "Special Requests", required: false, sensitive: false) + + ### table + Columns: item (Item Name), category (Category), price (Price), available (Available) + Sortable: true + + ### button + Text: "Submit Order" + Variant: primary + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["order", "menu"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["table_number", "items", "dietary_notes"] + minRatio: 0.5 + - type: icontains + value: "table" + - type: icontains + value: "button" + +# --------------------------------------------------------------------------- +# 8. Employee Performance Review — contextual trigger, form + approval-gate +# --------------------------------------------------------------------------- +- description: "Performance review with contextual trigger" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** performance-review + **Domain:** human-resources + **Description:** Quarterly employee performance review process. Manager fills out evaluation form with ratings and feedback, then routes through HR approval before sharing with the employee. + **Business Rules:** Employee salary and performance scores are sensitive. Manager must provide written justification for ratings below "Meets Expectations". HR approval required before employee sees results. Review period dates are mandatory. + **When to Display Components:** When the conversation context indicates the manager wants to submit or start a performance evaluation — for example, discussing employee progress, quarterly reviews, or mentioning performance feedback. + + **Selected Components:** + + ### form + Fields: + - employee_name (text, label: "Employee Name", required: true, sensitive: false) + - employee_id (text, label: "Employee ID", required: true, sensitive: false) + - review_period (text, label: "Review Period", required: true, sensitive: false) + - overall_rating (select, label: "Overall Rating", required: true, sensitive: true) + - strengths (textarea, label: "Key Strengths", required: true, sensitive: false) + - areas_for_improvement (textarea, label: "Areas for Improvement", required: true, sensitive: false) + - salary_recommendation (number, label: "Salary Adjustment (%)", required: false, sensitive: true) + + ### approval-gate + Title: HR Review Approval + Required approvers: 1 + Allowed roles: hr-manager, hr-director + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: contextual + contextHints: ["performance", "review", "evaluat", "feedback", "quarterly"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["employee_name", "overall_rating", "strengths", "areas_for_improvement", "salary_recommendation"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "approval" + +# --------------------------------------------------------------------------- +# 9. Compliance Audit — keyword trigger, form + tasklist + callout +# --------------------------------------------------------------------------- +- description: "Compliance audit with checklist and warning callouts" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** compliance-audit + **Domain:** legal + **Description:** Regulatory compliance audit workflow. Auditor fills out findings form, works through a compliance checklist, and the system displays warning callouts for any non-compliant items. + **Business Rules:** Audit findings with severity "critical" must trigger an error callout. All audit evidence references are required. Auditor email is sensitive. Checklist items must all be completed before the audit can be finalized. + **When to Display Components:** When the user says one of these keywords or phrases: start audit, compliance check, begin assessment, regulatory review. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - audit_title (text, label: "Audit Title", required: true, sensitive: false) + - auditor_email (email, label: "Auditor Email", required: true, sensitive: true) + - department (select, label: "Department Under Audit", required: true, sensitive: false) + - finding_severity (select, label: "Finding Severity", required: true, sensitive: false) + - finding_description (textarea, label: "Finding Description", required: true, sensitive: false) + - evidence_reference (text, label: "Evidence Reference", required: true, sensitive: false) + + ### tasklist + Items: Review policies, Check access controls, Verify data retention, Audit trail review, Interview stakeholders, Document findings + + ### callout + Variant: warning + Used for: flagging non-compliant findings + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["audit", "compliance", "assessment"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["audit_title", "auditor_email", "department", "finding_severity", "finding_description"] + minRatio: 0.5 + - type: icontains + value: "callout" + - type: icontains + value: "tasklist" + +# --------------------------------------------------------------------------- +# 10. Real Estate Listing — immediate trigger, form + chart + table +# --------------------------------------------------------------------------- +- description: "Real estate listing with analytics chart and comparisons table" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** property-listing + **Domain:** real-estate + **Description:** Property listing assistant that collects property details, displays market comparison data in a table, and shows price trend charts for the neighborhood. + **Business Rules:** Owner SSN and bank details are sensitive. Property address is required. Price comparisons table must be sortable. Chart should show 12-month price trends. Square footage and bedrooms are mandatory fields. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - property_address (text, label: "Property Address", required: true, sensitive: false) + - owner_name (text, label: "Owner Name", required: true, sensitive: false) + - owner_ssn (text, label: "Owner SSN", required: false, sensitive: true) + - listing_price (number, label: "Listing Price ($)", required: true, sensitive: false) + - bedrooms (number, label: "Bedrooms", required: true, sensitive: false) + - square_footage (number, label: "Square Footage", required: true, sensitive: false) + - property_type (select, label: "Property Type", required: true, sensitive: false) + + ### table + Columns: address (Address), price (Price), sqft (Sq Ft), beds (Beds), sold_date (Sold Date) + Sortable: true + + ### chart + Variant: bar + Label: "12-Month Price Trend" + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["property_address", "listing_price", "bedrooms", "square_footage", "owner_ssn"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "chart" + +# --------------------------------------------------------------------------- +# 11. IT Asset Management — keyword trigger, form + webhook +# --------------------------------------------------------------------------- +- description: "IT asset tracking with webhook integration" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** asset-management + **Domain:** IT operations + **Description:** IT asset lifecycle tracking. When new hardware arrives or is decommissioned, capture asset details and fire a webhook to update the CMDB (Configuration Management Database). + **Business Rules:** Serial numbers and MAC addresses are sensitive. Asset tag is always required and must be unique. Webhook fires to CMDB API on form submission. Purchase cost should be tracked. + **When to Display Components:** When the user says one of these keywords or phrases: new asset, register device, decommission, asset check-in, hardware received. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - asset_tag (text, label: "Asset Tag", required: true, sensitive: false) + - device_type (select, label: "Device Type", required: true, sensitive: false) + - manufacturer (text, label: "Manufacturer", required: true, sensitive: false) + - serial_number (text, label: "Serial Number", required: true, sensitive: true) + - mac_address (text, label: "MAC Address", required: false, sensitive: true) + - assigned_to (email, label: "Assigned To (Email)", required: false, sensitive: false) + - purchase_cost (number, label: "Purchase Cost ($)", required: true, sensitive: false) + + ### webhook + URL: https://cmdb.internal.company.com/api/assets + Method: POST + Trigger: on form submission + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["asset", "register", "decommission", "hardware"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["asset_tag", "serial_number", "mac_address", "device_type", "purchase_cost"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "webhook" + +# --------------------------------------------------------------------------- +# 12. Event Registration — keyword trigger, form + button + callout +# --------------------------------------------------------------------------- +- description: "Event registration with confirmation callout" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** event-registration + **Domain:** events + **Description:** Conference and event registration workflow. Collects attendee info, dietary preferences, and session choices. Shows a success callout on registration and a register button. + **Business Rules:** Attendee email and phone are sensitive. Early-bird pricing ends March 15. T-shirt size is optional. Show a success callout confirming registration details. Limit 500 attendees. + **When to Display Components:** When the user says one of these keywords or phrases: register for event, sign up, attend conference, book tickets. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - attendee_name (text, label: "Full Name", required: true, sensitive: false) + - email (email, label: "Email Address", required: true, sensitive: true) + - phone (text, label: "Phone Number", required: false, sensitive: true) + - company (text, label: "Company / Organization", required: false, sensitive: false) + - ticket_type (select, label: "Ticket Type", required: true, sensitive: false) + - dietary_preference (select, label: "Dietary Preference", required: false, sensitive: false) + - tshirt_size (select, label: "T-Shirt Size", required: false, sensitive: false) + + ### button + Text: "Complete Registration" + Variant: primary + + ### callout + Variant: success + Used for: confirming successful registration + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["register", "sign up", "conference", "event"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["attendee_name", "email", "ticket_type", "dietary_preference"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "callout" + +# --------------------------------------------------------------------------- +# 13. Insurance Claim — contextual trigger, form + approval-gate + webhook +# --------------------------------------------------------------------------- +- description: "Insurance claim with contextual trigger and multi-step approval" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** insurance-claim + **Domain:** insurance + **Description:** Auto insurance claim filing and adjudication. Collects accident details, vehicle info, and injury data. Routes through claims adjuster approval. Webhook notifies the claims management system. + **Business Rules:** Driver license number, policy number, and injury details are sensitive. Claims over $25k require senior adjuster approval. Photos of damage are referenced but not uploaded. Police report number is required for accidents involving injuries. + **When to Display Components:** When the user describes an accident, mentions filing a claim, or discusses vehicle damage — generate the claims form contextually based on the conversation. + + **Selected Components:** + + ### form + Fields: + - policy_number (text, label: "Policy Number", required: true, sensitive: true) + - claimant_name (text, label: "Claimant Name", required: true, sensitive: false) + - driver_license (text, label: "Driver License Number", required: true, sensitive: true) + - accident_date (date, label: "Date of Accident", required: true, sensitive: false) + - accident_description (textarea, label: "Accident Description", required: true, sensitive: false) + - injury_details (textarea, label: "Injury Details", required: false, sensitive: true) + - estimated_damage (number, label: "Estimated Damage ($)", required: true, sensitive: false) + - police_report_number (text, label: "Police Report Number", required: false, sensitive: false) + + ### approval-gate + Title: Claims Adjuster Review + Required approvers: 1 + Allowed roles: claims-adjuster, senior-adjuster + + ### webhook + URL: https://claims-api.insurance.com/claims + Method: POST + Trigger: on approval + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: contextual + contextHints: ["accident", "claim", "damage", "vehicle"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["policy_number", "driver_license", "accident_date", "accident_description", "estimated_damage"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "approval" + +# --------------------------------------------------------------------------- +# 14. Student Enrollment — immediate trigger, form + tasklist +# --------------------------------------------------------------------------- +- description: "Student enrollment with checklist and immediate trigger" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** student-enrollment + **Domain:** education + **Description:** University student enrollment workflow. Collects student personal data, program selection, and prior education history. Tracks enrollment steps via a checklist. + **Business Rules:** Student SSN, date of birth, and transcript records are sensitive. GPA must be provided. Program selection uses a dropdown with available programs. All enrollment steps must be completed before term start. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - student_name (text, label: "Student Full Name", required: true, sensitive: false) + - date_of_birth (date, label: "Date of Birth", required: true, sensitive: true) + - student_ssn (text, label: "Social Security Number", required: true, sensitive: true) + - email (email, label: "Student Email", required: true, sensitive: false) + - program (select, label: "Program of Study", required: true, sensitive: false) + - gpa (number, label: "Current GPA", required: true, sensitive: false) + - previous_institution (text, label: "Previous Institution", required: false, sensitive: false) + + ### tasklist + Items: Submit transcripts, Pay enrollment deposit, Complete orientation, Submit immunization records, Register for courses, Set up student ID + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["student_name", "date_of_birth", "student_ssn", "program", "gpa"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "tasklist" + +# --------------------------------------------------------------------------- +# 15. Travel Request — keyword trigger, form + approval-gate + button +# --------------------------------------------------------------------------- +- description: "Travel request with budget approval gate" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** travel-request + **Domain:** corporate + **Description:** Business travel request and approval workflow. Employee submits travel details and estimated costs, manager reviews and approves, then a booking confirmation button is enabled. + **Business Rules:** Passport number is sensitive. Travel over $5k requires VP approval in addition to manager. Per diem rates apply based on destination country. Return date must be after departure date. Conference/event name required if travel is for an event. + **When to Display Components:** When the user says one of these keywords or phrases: travel request, book trip, business travel, travel approval. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - employee_name (text, label: "Employee Name", required: true, sensitive: false) + - destination (text, label: "Destination City/Country", required: true, sensitive: false) + - departure_date (date, label: "Departure Date", required: true, sensitive: false) + - return_date (date, label: "Return Date", required: true, sensitive: false) + - purpose (select, label: "Travel Purpose", required: true, sensitive: false) + - estimated_cost (number, label: "Estimated Total Cost ($)", required: true, sensitive: false) + - passport_number (text, label: "Passport Number", required: false, sensitive: true) + - event_name (text, label: "Conference / Event Name", required: false, sensitive: false) + + ### approval-gate + Title: Manager Travel Approval + Required approvers: 1 + Allowed roles: manager, vp + + ### button + Text: "Confirm Booking" + Variant: primary + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["travel", "book trip", "business travel"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["employee_name", "destination", "departure_date", "estimated_cost", "passport_number"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "approval" + +# --------------------------------------------------------------------------- +# 16. Bug Report — keyword trigger, form only (minimal) +# --------------------------------------------------------------------------- +- description: "Simple bug report form — minimal single-component flow" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** bug-report + **Domain:** software-development + **Description:** Simple bug reporting form for an internal engineering team. Captures bug title, severity, steps to reproduce, and expected vs actual behavior. + **Business Rules:** No sensitive fields. All fields except "additional notes" are required. Severity uses a select dropdown. Steps to reproduce must be detailed. + **When to Display Components:** When the user says one of these keywords or phrases: report bug, found a bug, file issue, submit defect. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - bug_title (text, label: "Bug Title", required: true, sensitive: false) + - severity (select, label: "Severity", required: true, sensitive: false) + - steps_to_reproduce (textarea, label: "Steps to Reproduce", required: true, sensitive: false) + - expected_behavior (textarea, label: "Expected Behavior", required: true, sensitive: false) + - actual_behavior (textarea, label: "Actual Behavior", required: true, sensitive: false) + - additional_notes (textarea, label: "Additional Notes", required: false, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["bug", "issue", "defect"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["bug_title", "severity", "steps_to_reproduce", "expected_behavior", "actual_behavior"] + minRatio: 0.5 + +# --------------------------------------------------------------------------- +# 17. Expense Report — contextual trigger, form + chart + approval-gate +# --------------------------------------------------------------------------- +- description: "Expense report with spending chart and contextual trigger" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** expense-report + **Domain:** finance + **Description:** Monthly expense reporting workflow. Employee logs expenses with receipts, a pie chart summarizes spending by category, and a finance manager approves the report. + **Business Rules:** Credit card last 4 digits are sensitive. Each expense line must have a date, amount, and category. Categories: Travel, Meals, Equipment, Software, Office Supplies, Other. Reports over $2k need director approval. + **When to Display Components:** When the user mentions submitting expenses, asks about reimbursement, or discusses business spending — generate the expense form contextually. + + **Selected Components:** + + ### form + Fields: + - employee_name (text, label: "Employee Name", required: true, sensitive: false) + - report_period (text, label: "Report Period", required: true, sensitive: false) + - expense_date (date, label: "Expense Date", required: true, sensitive: false) + - category (select, label: "Category", required: true, sensitive: false) + - amount (number, label: "Amount ($)", required: true, sensitive: false) + - description (text, label: "Description", required: true, sensitive: false) + - card_last_four (text, label: "Card Last 4 Digits", required: false, sensitive: true) + + ### chart + Variant: pie + Label: "Spending by Category" + + ### approval-gate + Title: Finance Manager Approval + Required approvers: 1 + Allowed roles: finance-manager, director + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: contextual + contextHints: ["expense", "reimburs", "spending", "receipt"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["employee_name", "category", "amount", "description", "card_last_four"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "chart" + +# --------------------------------------------------------------------------- +# 18. Warehouse Receiving — keyword trigger, form + tasklist + webhook +# --------------------------------------------------------------------------- +- description: "Warehouse receiving with inspection checklist and webhook" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** warehouse-receiving + **Domain:** logistics + **Description:** Inbound shipment receiving workflow. Warehouse staff log incoming shipments, complete an inspection checklist, and fire a webhook to update the inventory management system. + **Business Rules:** No sensitive fields. PO number and supplier name are required. Inspection checklist must include damage check, quantity verification, and labeling. Webhook fires to WMS API on checklist completion. + **When to Display Components:** When the user says one of these keywords or phrases: shipment arrived, receive goods, incoming delivery, check in shipment. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - po_number (text, label: "Purchase Order Number", required: true, sensitive: false) + - supplier_name (text, label: "Supplier Name", required: true, sensitive: false) + - delivery_date (date, label: "Delivery Date", required: true, sensitive: false) + - carrier (text, label: "Carrier Name", required: false, sensitive: false) + - num_pallets (number, label: "Number of Pallets", required: true, sensitive: false) + - notes (textarea, label: "Receiving Notes", required: false, sensitive: false) + + ### tasklist + Items: Verify PO matches packing slip, Check for visible damage, Count units received, Apply warehouse labels, Move to staging area, Update WMS + + ### webhook + URL: https://wms.warehouse.com/api/receive + Method: POST + Trigger: on checklist completion + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["shipment", "receive", "delivery"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["po_number", "supplier_name", "delivery_date", "num_pallets"] + minRatio: 0.5 + - type: icontains + value: "webhook" + - type: icontains + value: "tasklist" + +# --------------------------------------------------------------------------- +# 19. Tenant Maintenance Request — keyword trigger, form + callout + button +# --------------------------------------------------------------------------- +- description: "Property maintenance request with urgency callout" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** maintenance-request + **Domain:** property-management + **Description:** Tenant maintenance request system. Tenants describe the issue, select urgency, and submit. Emergency requests display an error callout with emergency contact info. Submit button triggers work order creation. + **Business Rules:** Tenant phone number is sensitive. Unit number is required. Emergency issues (gas leak, flooding, fire damage) must show an error callout with the emergency maintenance hotline number. Non-emergency requests show an info callout with expected response time (48 hours). + **When to Display Components:** When the user says one of these keywords or phrases: maintenance request, something broke, need repair, fix my, submit work order. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - tenant_name (text, label: "Tenant Name", required: true, sensitive: false) + - unit_number (text, label: "Unit Number", required: true, sensitive: false) + - tenant_phone (text, label: "Phone Number", required: true, sensitive: true) + - issue_category (select, label: "Issue Category", required: true, sensitive: false) + - urgency (select, label: "Urgency Level", required: true, sensitive: false) + - issue_description (textarea, label: "Describe the Issue", required: true, sensitive: false) + - preferred_time (text, label: "Preferred Service Time", required: false, sensitive: false) + + ### callout + Variant: error (for emergencies) / info (for standard requests) + Used for: displaying emergency contacts or expected response times + + ### button + Text: "Submit Maintenance Request" + Variant: primary + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["maintenance", "repair", "broke", "work order"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["tenant_name", "unit_number", "tenant_phone", "issue_category", "urgency"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "callout" + +# --------------------------------------------------------------------------- +# 20. Clinical Trial Enrollment — contextual trigger, form + approval-gate + tasklist + callout +# --------------------------------------------------------------------------- +- description: "Clinical trial enrollment with complex multi-component workflow" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** clinical-trial-enrollment + **Domain:** pharmaceuticals + **Description:** Clinical trial participant enrollment. Collects patient consent, medical history, and eligibility criteria. IRB (Institutional Review Board) approval required. Displays inclusion/exclusion criteria callout. Tracks enrollment steps via tasklist. + **Business Rules:** All patient medical data, SSN, and contact info are sensitive. IRB approval requires 2 reviewers with role: irb-member. Patients must meet all inclusion criteria and none of the exclusion criteria. Informed consent is mandatory. Age must be 18+. + **When to Display Components:** When the conversation indicates a potential trial participant — for example, when discussing eligibility, asking about enrollment, or when a clinician mentions screening a patient. + + **Selected Components:** + + ### form + Fields: + - participant_name (text, label: "Participant Full Name", required: true, sensitive: true) + - date_of_birth (date, label: "Date of Birth", required: true, sensitive: true) + - participant_ssn (text, label: "SSN", required: true, sensitive: true) + - email (email, label: "Contact Email", required: true, sensitive: true) + - phone (text, label: "Contact Phone", required: true, sensitive: true) + - medical_history (textarea, label: "Relevant Medical History", required: true, sensitive: true) + - current_medications (textarea, label: "Current Medications", required: true, sensitive: true) + - informed_consent (checkbox, label: "I provide informed consent to participate", required: true, sensitive: false) + + ### approval-gate + Title: IRB Approval + Required approvers: 2 + Allowed roles: irb-member + + ### tasklist + Items: Verify eligibility criteria, Obtain informed consent, Complete baseline assessments, Assign participant ID, Schedule first visit, File IRB documentation + + ### callout + Variant: info + Used for: displaying inclusion/exclusion criteria + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: contextual + contextHints: ["eligib", "enroll", "screen", "trial", "participant"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["participant_name", "date_of_birth", "medical_history", "current_medications", "informed_consent"] + minRatio: 0.5 + - type: icontains + value: "sensitive" + - type: icontains + value: "approval" + - type: icontains + value: "tasklist" + +# =========================================================================== +# COMPONENT SCOPE COMPLIANCE TESTS (21-25) +# +# These tests verify the LLM only includes components that were explicitly +# requested. The user reported that requesting only "form + thinking" still +# generates approval-gates, tasklists, webhooks, etc. +# Each test uses llm-rubric to catch hallucinated components. +# =========================================================================== + +# --------------------------------------------------------------------------- +# 21. Form-only — must NOT add approval-gate, tasklist, webhook, button, etc. +# --------------------------------------------------------------------------- +- description: "Form-only config must not hallucinate extra components" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** incident-triage + **Domain:** engineering + **Description:** Production incident triage workflow that captures severity, affected services, and timeline, then routes through an on-call approval gate before executing remediation steps. + **Business Rules:** Severity P1/P2 incidents require VP-level approval. All incidents must have a root cause analysis tasklist completed within 48 hours. Slack and PagerDuty webhooks must fire on escalation. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - incident_title (text, label: "Incident Title", required: true, sensitive: false) + - severity (select, label: "Severity Level", required: true, sensitive: false) + - affected_services (textarea, label: "Affected Services", required: true, sensitive: false) + - start_time (date, label: "Incident Start Time", required: true, sensitive: false) + - reporter_email (email, label: "Reporter Email", required: true, sensitive: true) + - customer_impact (textarea, label: "Customer Impact Description", required: true, sensitive: false) + - estimated_users (number, label: "Estimated Users Affected", required: false, sensitive: false) + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["incident_title", "severity", "affected_services", "reporter_email", "customer_impact"] + minRatio: 0.5 + - type: llm-rubric + value: | + The user's configuration ONLY requested these components: form and thinking. + The generated custom prompt MUST NOT include instructions, examples, or sections + for any of these unrequested components: approval-gate, tasklist, webhook, button, + table, chart, callout. + + Evaluate the output and FAIL if: + - It contains a ```mdma block with type: approval-gate, type: tasklist, type: webhook, + type: button, type: table, type: chart, or type: callout + - It contains sections titled "Approval Gate", "Tasklist", "Webhook", "Button", + "Table", or "Chart" that provide instructions to generate those components + - It describes workflow logic involving components that were not requested + + PASS if the output only describes form and thinking components. + Minor references to other component types in general context (e.g., "MDMA supports + approval-gates") are acceptable, but specific instructions to generate them are not. + +# --------------------------------------------------------------------------- +# 22. Form + callout only — must NOT add approval-gate, webhook, tasklist +# --------------------------------------------------------------------------- +- description: "Form + callout config must not add approval-gate or webhook" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** order-status + **Domain:** e-commerce + **Description:** Order status lookup assistant. Customer provides order ID and the system displays order details in a form and shows a callout with shipping status. Business rules say the system should display an info callout with estimated delivery date and a warning callout if the order is delayed. + **Business Rules:** Customer email is sensitive. Order ID is required. Show info callout for on-time orders and warning callout for delayed orders. Do not collect payment info. + **When to Display Components:** When the user says one of these keywords or phrases: check order, order status, track my order, where is my package. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - order_id (text, label: "Order ID", required: true, sensitive: false) + - customer_email (email, label: "Customer Email", required: true, sensitive: true) + + ### callout + Variant: info / warning + Used for: displaying shipping status and delivery estimates + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["order", "track", "package"] + - type: llm-rubric + value: | + The user's configuration ONLY requested these components: form, callout, and thinking. + The generated custom prompt MUST NOT include instructions, examples, or sections + for any of these unrequested components: approval-gate, tasklist, webhook, button, + table, chart. + + Evaluate the output and FAIL if: + - It contains a ```mdma block with type: approval-gate, type: tasklist, type: webhook, + type: button, type: table, or type: chart + - It contains dedicated sections providing instructions to generate those unrequested components + - It describes workflow logic involving approval gates, webhooks, or tasklists + + PASS if the output only describes form, callout, and thinking components. + +# --------------------------------------------------------------------------- +# 23. Form + button only — must NOT add approval-gate, webhook, chart, table +# --------------------------------------------------------------------------- +- description: "Form + button config must not add approval or webhook logic" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** newsletter-signup + **Domain:** marketing + **Description:** Newsletter subscription form. User enters their email and name, then clicks a subscribe button. Simple two-component flow with no approval or backend integration needed. + **Business Rules:** Email is sensitive. Name is required. The subscribe button should be primary variant. No approval gates or webhooks are needed — this is a simple front-end form. + **When to Display Components:** Immediately when the conversation starts — always respond with MDMA components in the first message. + + **Selected Components:** + + ### form + Fields: + - full_name (text, label: "Full Name", required: true, sensitive: false) + - email (email, label: "Email Address", required: true, sensitive: true) + - interests (select, label: "Topics of Interest", required: false, sensitive: false) + + ### button + Text: "Subscribe" + Variant: primary + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: immediate + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["full_name", "email", "interests"] + minRatio: 0.6 + - type: llm-rubric + value: | + The user's configuration ONLY requested these components: form, button, and thinking. + The generated custom prompt MUST NOT include instructions, examples, or sections + for any of these unrequested components: approval-gate, tasklist, webhook, table, + chart, callout. + + Evaluate the output and FAIL if: + - It contains a ```mdma block with type: approval-gate, type: tasklist, type: webhook, + type: table, type: chart, or type: callout + - It contains dedicated sections instructing the LLM to generate those unrequested components + - It adds workflow logic involving approval, webhooks, or checklists + + PASS if the output only describes form, button, and thinking components. + The configuration explicitly states "No approval gates or webhooks are needed." + +# --------------------------------------------------------------------------- +# 24. Table + chart only — must NOT add form, approval-gate, webhook +# --------------------------------------------------------------------------- +- description: "Table + chart config must not add forms or approval gates" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** sales-dashboard + **Domain:** analytics + **Description:** Read-only sales analytics dashboard. Displays a summary table of regional sales data and a bar chart of revenue trends. No data collection or forms needed — this is a display-only view. + **Business Rules:** No sensitive data. Table must be sortable. Chart shows quarterly revenue. This is purely informational — no forms, no buttons, no approval gates. Just display the data. + **When to Display Components:** When the user says one of these keywords or phrases: show dashboard, sales report, revenue summary, quarterly numbers. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### table + Columns: region (Region), revenue (Revenue), growth (Growth %), deals (Deals Closed) + Sortable: true + + ### chart + Variant: bar + Label: "Quarterly Revenue Trend" + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["dashboard", "sales", "revenue"] + - type: llm-rubric + value: | + The user's configuration ONLY requested these components: table, chart, and thinking. + The generated custom prompt MUST NOT include instructions, examples, or sections + for any of these unrequested components: form, approval-gate, tasklist, webhook, + button, callout. + + Evaluate the output and FAIL if: + - It contains a ```mdma block with type: form, type: approval-gate, type: tasklist, + type: webhook, type: button, or type: callout + - It contains dedicated sections instructing the LLM to generate forms, buttons, + approval gates, or webhooks + - It adds data-collection or approval workflow logic + + PASS if the output only describes table, chart, and thinking components. + The configuration explicitly states "No data collection or forms needed" and + "no forms, no buttons, no approval gates." + +# --------------------------------------------------------------------------- +# 25. Form + tasklist only — must NOT add approval-gate, webhook, chart, callout +# --------------------------------------------------------------------------- +- description: "Form + tasklist config must not add approval-gate or webhook" + vars: + request: | + Generate a custom prompt based on this configuration: + + ## User Configuration + + **Flow Name:** daily-standup + **Domain:** project-management + **Description:** Daily standup capture form with a task checklist. Team members log what they did yesterday, what they're doing today, and any blockers. A tasklist tracks recurring standup preparation items. + **Business Rules:** No sensitive fields. All standup fields are required. Blockers field is optional. Tasklist items are simple preparation steps. No approvals needed — this is a flat team workflow with no hierarchy or gates. + **When to Display Components:** When the user says one of these keywords or phrases: standup, daily update, what did you do yesterday, scrum. Only generate MDMA components when triggered by these phrases, otherwise respond with plain text. + + **Selected Components:** + + ### form + Fields: + - team_member (text, label: "Team Member Name", required: true, sensitive: false) + - yesterday (textarea, label: "What did you do yesterday?", required: true, sensitive: false) + - today (textarea, label: "What are you doing today?", required: true, sensitive: false) + - blockers (textarea, label: "Any blockers?", required: false, sensitive: false) + + ### tasklist + Items: Review yesterday's action items, Check Jira board updates, Prepare demo if needed, Update sprint burndown + + ### thinking + assert: + - type: javascript + value: file://assertions/no-spec-repetition.mjs + - type: javascript + value: file://assertions/prompt-length.mjs + - type: javascript + value: file://assertions/mentions-trigger.mjs + config: + mode: keyword + keywords: ["standup", "daily", "scrum"] + - type: javascript + value: file://assertions/mentions-fields.mjs + config: + fields: ["team_member", "yesterday", "today", "blockers"] + minRatio: 0.6 + - type: llm-rubric + value: | + The user's configuration ONLY requested these components: form, tasklist, and thinking. + The generated custom prompt MUST NOT include instructions, examples, or sections + for any of these unrequested components: approval-gate, webhook, button, table, + chart, callout. + + Evaluate the output and FAIL if: + - It contains a ```mdma block with type: approval-gate, type: webhook, type: button, + type: table, type: chart, or type: callout + - It contains dedicated sections instructing the LLM to generate those unrequested components + - It adds approval or escalation workflow logic + + PASS if the output only describes form, tasklist, and thinking components. + The configuration explicitly states "No approvals needed — this is a flat team + workflow with no hierarchy or gates." diff --git a/package.json b/package.json index f355ca3..0a86dc4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "eval": "pnpm --filter @mobile-reality/mdma-evals eval", "eval:custom": "pnpm --filter @mobile-reality/mdma-evals eval:custom", "eval:conversation": "pnpm --filter @mobile-reality/mdma-evals eval:conversation", + "eval:prompt-builder": "pnpm --filter @mobile-reality/mdma-evals eval:prompt-builder", "eval:all": "pnpm --filter @mobile-reality/mdma-evals eval:all", "eval:view": "pnpm --filter @mobile-reality/mdma-evals eval:view" }, diff --git a/packages/cli/app-dist/assets/index-Bi8tXvnb.js b/packages/cli/app-dist/assets/index-Bi8tXvnb.js new file mode 100644 index 0000000..a322f8a --- /dev/null +++ b/packages/cli/app-dist/assets/index-Bi8tXvnb.js @@ -0,0 +1,646 @@ +var y1=Object.defineProperty;var g1=(i,n,a)=>n in i?y1(i,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[n]=a;var sl=(i,n,a)=>g1(i,typeof n!="symbol"?n+"":n,a);(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))s(u);new MutationObserver(u=>{for(const o of u)if(o.type==="childList")for(const f of o.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&s(f)}).observe(document,{childList:!0,subtree:!0});function a(u){const o={};return u.integrity&&(o.integrity=u.integrity),u.referrerPolicy&&(o.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?o.credentials="include":u.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function s(u){if(u.ep)return;u.ep=!0;const o=a(u);fetch(u.href,o)}})();function b1(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var pf={exports:{}},xs={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Cy;function v1(){if(Cy)return xs;Cy=1;var i=Symbol.for("react.transitional.element"),n=Symbol.for("react.fragment");function a(s,u,o){var f=null;if(o!==void 0&&(f=""+o),u.key!==void 0&&(f=""+u.key),"key"in u){o={};for(var h in u)h!=="key"&&(o[h]=u[h])}else o=u;return u=o.ref,{$$typeof:i,type:s,key:f,ref:u!==void 0?u:null,props:o}}return xs.Fragment=n,xs.jsx=a,xs.jsxs=a,xs}var Oy;function x1(){return Oy||(Oy=1,pf.exports=v1()),pf.exports}var S=x1(),mf={exports:{}},_e={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ny;function S1(){if(Ny)return _e;Ny=1;var i=Symbol.for("react.transitional.element"),n=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),s=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),f=Symbol.for("react.context"),h=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),_=Symbol.iterator;function v(E){return E===null||typeof E!="object"?null:(E=_&&E[_]||E["@@iterator"],typeof E=="function"?E:null)}var N={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,D={};function C(E,Y,k){this.props=E,this.context=Y,this.refs=D,this.updater=k||N}C.prototype.isReactComponent={},C.prototype.setState=function(E,Y){if(typeof E!="object"&&typeof E!="function"&&E!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,E,Y,"setState")},C.prototype.forceUpdate=function(E){this.updater.enqueueForceUpdate(this,E,"forceUpdate")};function H(){}H.prototype=C.prototype;function M(E,Y,k){this.props=E,this.context=Y,this.refs=D,this.updater=k||N}var Q=M.prototype=new H;Q.constructor=M,w(Q,C.prototype),Q.isPureReactComponent=!0;var X=Array.isArray;function B(){}var K={H:null,A:null,T:null,S:null},$=Object.prototype.hasOwnProperty;function te(E,Y,k){var ne=k.ref;return{$$typeof:i,type:E,key:Y,ref:ne!==void 0?ne:null,props:k}}function fe(E,Y){return te(E.type,Y,E.props)}function W(E){return typeof E=="object"&&E!==null&&E.$$typeof===i}function P(E){var Y={"=":"=0",":":"=2"};return"$"+E.replace(/[=:]/g,function(k){return Y[k]})}var ye=/\/+/g;function Ee(E,Y){return typeof E=="object"&&E!==null&&E.key!=null?P(""+E.key):Y.toString(36)}function be(E){switch(E.status){case"fulfilled":return E.value;case"rejected":throw E.reason;default:switch(typeof E.status=="string"?E.then(B,B):(E.status="pending",E.then(function(Y){E.status==="pending"&&(E.status="fulfilled",E.value=Y)},function(Y){E.status==="pending"&&(E.status="rejected",E.reason=Y)})),E.status){case"fulfilled":return E.value;case"rejected":throw E.reason}}throw E}function q(E,Y,k,ne,me){var de=typeof E;(de==="undefined"||de==="boolean")&&(E=null);var ze=!1;if(E===null)ze=!0;else switch(de){case"bigint":case"string":case"number":ze=!0;break;case"object":switch(E.$$typeof){case i:case n:ze=!0;break;case g:return ze=E._init,q(ze(E._payload),Y,k,ne,me)}}if(ze)return me=me(E),ze=ne===""?"."+Ee(E,0):ne,X(me)?(k="",ze!=null&&(k=ze.replace(ye,"$&/")+"/"),q(me,Y,k,"",function(en){return en})):me!=null&&(W(me)&&(me=fe(me,k+(me.key==null||E&&E.key===me.key?"":(""+me.key).replace(ye,"$&/")+"/")+ze)),Y.push(me)),1;ze=0;var tt=ne===""?".":ne+":";if(X(E))for(var Ke=0;Ke>>1,A=q[Ce];if(0>>1;Ceu(k,oe))neu(me,k)?(q[Ce]=me,q[ne]=oe,Ce=ne):(q[Ce]=k,q[Y]=oe,Ce=Y);else if(neu(me,oe))q[Ce]=me,q[ne]=oe,Ce=ne;else break e}}return J}function u(q,J){var oe=q.sortIndex-J.sortIndex;return oe!==0?oe:q.id-J.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;i.unstable_now=function(){return o.now()}}else{var f=Date,h=f.now();i.unstable_now=function(){return f.now()-h}}var m=[],p=[],g=1,b=null,_=3,v=!1,N=!1,w=!1,D=!1,C=typeof setTimeout=="function"?setTimeout:null,H=typeof clearTimeout=="function"?clearTimeout:null,M=typeof setImmediate<"u"?setImmediate:null;function Q(q){for(var J=a(p);J!==null;){if(J.callback===null)s(p);else if(J.startTime<=q)s(p),J.sortIndex=J.expirationTime,n(m,J);else break;J=a(p)}}function X(q){if(w=!1,Q(q),!N)if(a(m)!==null)N=!0,B||(B=!0,P());else{var J=a(p);J!==null&&be(X,J.startTime-q)}}var B=!1,K=-1,$=5,te=-1;function fe(){return D?!0:!(i.unstable_now()-te<$)}function W(){if(D=!1,B){var q=i.unstable_now();te=q;var J=!0;try{e:{N=!1,w&&(w=!1,H(K),K=-1),v=!0;var oe=_;try{t:{for(Q(q),b=a(m);b!==null&&!(b.expirationTime>q&&fe());){var Ce=b.callback;if(typeof Ce=="function"){b.callback=null,_=b.priorityLevel;var A=Ce(b.expirationTime<=q);if(q=i.unstable_now(),typeof A=="function"){b.callback=A,Q(q),J=!0;break t}b===a(m)&&s(m),Q(q)}else s(m);b=a(m)}if(b!==null)J=!0;else{var E=a(p);E!==null&&be(X,E.startTime-q),J=!1}}break e}finally{b=null,_=oe,v=!1}J=void 0}}finally{J?P():B=!1}}}var P;if(typeof M=="function")P=function(){M(W)};else if(typeof MessageChannel<"u"){var ye=new MessageChannel,Ee=ye.port2;ye.port1.onmessage=W,P=function(){Ee.postMessage(null)}}else P=function(){C(W,0)};function be(q,J){K=C(function(){q(i.unstable_now())},J)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(q){q.callback=null},i.unstable_forceFrameRate=function(q){0>q||125Ce?(q.sortIndex=oe,n(p,q),a(m)===null&&q===a(p)&&(w?(H(K),K=-1):w=!0,be(X,oe-Ce))):(q.sortIndex=A,n(m,q),N||v||(N=!0,B||(B=!0,P()))),q},i.unstable_shouldYield=fe,i.unstable_wrapCallback=function(q){var J=_;return function(){var oe=_;_=J;try{return q.apply(this,arguments)}finally{_=oe}}}})(bf)),bf}var Dy;function k1(){return Dy||(Dy=1,gf.exports=_1()),gf.exports}var vf={exports:{}},Tt={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var jy;function w1(){if(jy)return Tt;jy=1;var i=od();function n(m){var p="https://react.dev/errors/"+m;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(n){console.error(n)}}return i(),vf.exports=w1(),vf.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var By;function T1(){if(By)return Ss;By=1;var i=k1(),n=od(),a=A1();function s(e){var t="https://react.dev/errors/"+e;if(1A||(e.current=Ce[A],Ce[A]=null,A--)}function k(e,t){A++,Ce[A]=e.current,e.current=t}var ne=E(null),me=E(null),de=E(null),ze=E(null);function tt(e,t){switch(k(de,t),k(me,e),k(ne,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Fm(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Fm(t),e=Wm(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}Y(ne),k(ne,e)}function Ke(){Y(ne),Y(me),Y(de)}function en(e){e.memoizedState!==null&&k(ze,e);var t=ne.current,l=Wm(t,e.type);t!==l&&(k(me,e),k(ne,l))}function Bn(e){me.current===e&&(Y(ne),Y(me)),ze.current===e&&(Y(ze),ys._currentValue=oe)}var El,$s;function Ln(e){if(El===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);El=t&&t[1]||"",$s=-1)":-1c||T[r]!==R[c]){var I=` +`+T[r].replace(" at new "," at ");return e.displayName&&I.includes("")&&(I=I.replace("",e.displayName)),I}while(1<=r&&0<=c);break}}}finally{ba=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Ln(l):""}function Xs(e,t){switch(e.tag){case 26:case 27:case 5:return Ln(e.type);case 16:return Ln("Lazy");case 13:return e.child!==t&&t!==null?Ln("Suspense Fallback"):Ln("Suspense");case 19:return Ln("SuspenseList");case 0:case 15:return va(e.type,!1);case 11:return va(e.type.render,!1);case 1:return va(e.type,!0);case 31:return Ln("Activity");default:return""}}function Js(e){try{var t="",l=null;do t+=Xs(e,l),l=e,e=e.return;while(e);return t}catch(r){return` +Error generating stack: `+r.message+` +`+r.stack}}var xa=Object.prototype.hasOwnProperty,Sa=i.unstable_scheduleCallback,Cl=i.unstable_cancelCallback,Fu=i.unstable_shouldYield,Wu=i.unstable_requestPaint,Et=i.unstable_now,Pu=i.unstable_getCurrentPriorityLevel,V=i.unstable_ImmediatePriority,ee=i.unstable_UserBlockingPriority,ge=i.unstable_NormalPriority,Oe=i.unstable_LowPriority,Ye=i.unstable_IdlePriority,Kt=i.log,qn=i.unstable_setDisableYieldValue,Ct=null,mt=null;function jt(e){if(typeof Kt=="function"&&qn(e),mt&&typeof mt.setStrictMode=="function")try{mt.setStrictMode(Ct,e)}catch{}}var Xe=Math.clz32?Math.clz32:n0,ci=Math.log,gn=Math.LN2;function n0(e){return e>>>=0,e===0?32:31-(ci(e)/gn|0)|0}var Fs=256,Ws=262144,Ps=4194304;function Vi(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function er(e,t,l){var r=e.pendingLanes;if(r===0)return 0;var c=0,d=e.suspendedLanes,y=e.pingedLanes;e=e.warmLanes;var x=r&134217727;return x!==0?(r=x&~d,r!==0?c=Vi(r):(y&=x,y!==0?c=Vi(y):l||(l=x&~e,l!==0&&(c=Vi(l))))):(x=r&~d,x!==0?c=Vi(x):y!==0?c=Vi(y):l||(l=r&~e,l!==0&&(c=Vi(l)))),c===0?0:t!==0&&t!==c&&(t&d)===0&&(d=c&-c,l=t&-t,d>=l||d===32&&(l&4194048)!==0)?t:c}function Ol(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function i0(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function zd(){var e=Ps;return Ps<<=1,(Ps&62914560)===0&&(Ps=4194304),e}function eo(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Nl(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function a0(e,t,l,r,c,d){var y=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var x=e.entanglements,T=e.expirationTimes,R=e.hiddenUpdates;for(l=y&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var c0=/[\n"\\]/g;function nn(e){return e.replace(c0,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function so(e,t,l,r,c,d,y,x){e.name="",y!=null&&typeof y!="function"&&typeof y!="symbol"&&typeof y!="boolean"?e.type=y:e.removeAttribute("type"),t!=null?y==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+tn(t)):e.value!==""+tn(t)&&(e.value=""+tn(t)):y!=="submit"&&y!=="reset"||e.removeAttribute("value"),t!=null?ro(e,y,tn(t)):l!=null?ro(e,y,tn(l)):r!=null&&e.removeAttribute("value"),c==null&&d!=null&&(e.defaultChecked=!!d),c!=null&&(e.checked=c&&typeof c!="function"&&typeof c!="symbol"),x!=null&&typeof x!="function"&&typeof x!="symbol"&&typeof x!="boolean"?e.name=""+tn(x):e.removeAttribute("name")}function Kd(e,t,l,r,c,d,y,x){if(d!=null&&typeof d!="function"&&typeof d!="symbol"&&typeof d!="boolean"&&(e.type=d),t!=null||l!=null){if(!(d!=="submit"&&d!=="reset"||t!=null)){lo(e);return}l=l!=null?""+tn(l):"",t=t!=null?""+tn(t):l,x||t===e.value||(e.value=t),e.defaultValue=t}r=r??c,r=typeof r!="function"&&typeof r!="symbol"&&!!r,e.checked=x?e.checked:!!r,e.defaultChecked=!!r,y!=null&&typeof y!="function"&&typeof y!="symbol"&&typeof y!="boolean"&&(e.name=y),lo(e)}function ro(e,t,l){t==="number"&&ir(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ea(e,t,l,r){if(e=e.options,t){t={};for(var c=0;c"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ho=!1;if(In)try{var jl={};Object.defineProperty(jl,"passive",{get:function(){ho=!0}}),window.addEventListener("test",jl,jl),window.removeEventListener("test",jl,jl)}catch{ho=!1}var di=null,po=null,lr=null;function Wd(){if(lr)return lr;var e,t=po,l=t.length,r,c="value"in di?di.value:di.textContent,d=c.length;for(e=0;e=Ll),ah=" ",lh=!1;function sh(e,t){switch(e){case"keyup":return q0.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function rh(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ma=!1;function H0(e,t){switch(e){case"compositionend":return rh(t);case"keypress":return t.which!==32?null:(lh=!0,ah);case"textInput":return e=t.data,e===ah&&lh?null:e;default:return null}}function I0(e,t){if(Ma)return e==="compositionend"||!vo&&sh(e,t)?(e=Wd(),lr=po=di=null,Ma=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=r}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=mh(l)}}function gh(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?gh(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function bh(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=ir(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=ir(e.document)}return t}function _o(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var X0=In&&"documentMode"in document&&11>=document.documentMode,za=null,ko=null,Il=null,wo=!1;function vh(e,t,l){var r=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;wo||za==null||za!==ir(r)||(r=za,"selectionStart"in r&&_o(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Il&&Hl(Il,r)||(Il=r,r=Wr(ko,"onSelect"),0>=y,c-=y,wn=1<<32-Xe(t)+c|l<Ae?(je=ue,ue=null):je=ue.sibling;var Ue=L(z,ue,j[Ae],G);if(Ue===null){ue===null&&(ue=je);break}e&&ue&&Ue.alternate===null&&t(z,ue),O=d(Ue,O,Ae),qe===null?he=Ue:qe.sibling=Ue,qe=Ue,ue=je}if(Ae===j.length)return l(z,ue),Be&&Vn(z,Ae),he;if(ue===null){for(;AeAe?(je=ue,ue=null):je=ue.sibling;var ji=L(z,ue,Ue.value,G);if(ji===null){ue===null&&(ue=je);break}e&&ue&&ji.alternate===null&&t(z,ue),O=d(ji,O,Ae),qe===null?he=ji:qe.sibling=ji,qe=ji,ue=je}if(Ue.done)return l(z,ue),Be&&Vn(z,Ae),he;if(ue===null){for(;!Ue.done;Ae++,Ue=j.next())Ue=Z(z,Ue.value,G),Ue!==null&&(O=d(Ue,O,Ae),qe===null?he=Ue:qe.sibling=Ue,qe=Ue);return Be&&Vn(z,Ae),he}for(ue=r(ue);!Ue.done;Ae++,Ue=j.next())Ue=U(ue,z,Ae,Ue.value,G),Ue!==null&&(e&&Ue.alternate!==null&&ue.delete(Ue.key===null?Ae:Ue.key),O=d(Ue,O,Ae),qe===null?he=Ue:qe.sibling=Ue,qe=Ue);return e&&ue.forEach(function(m1){return t(z,m1)}),Be&&Vn(z,Ae),he}function $e(z,O,j,G){if(typeof j=="object"&&j!==null&&j.type===w&&j.key===null&&(j=j.props.children),typeof j=="object"&&j!==null){switch(j.$$typeof){case v:e:{for(var he=j.key;O!==null;){if(O.key===he){if(he=j.type,he===w){if(O.tag===7){l(z,O.sibling),G=c(O,j.props.children),G.return=z,z=G;break e}}else if(O.elementType===he||typeof he=="object"&&he!==null&&he.$$typeof===$&&ea(he)===O.type){l(z,O.sibling),G=c(O,j.props),Ql(G,j),G.return=z,z=G;break e}l(z,O);break}else t(z,O);O=O.sibling}j.type===w?(G=Xi(j.props.children,z.mode,G,j.key),G.return=z,z=G):(G=mr(j.type,j.key,j.props,null,z.mode,G),Ql(G,j),G.return=z,z=G)}return y(z);case N:e:{for(he=j.key;O!==null;){if(O.key===he)if(O.tag===4&&O.stateNode.containerInfo===j.containerInfo&&O.stateNode.implementation===j.implementation){l(z,O.sibling),G=c(O,j.children||[]),G.return=z,z=G;break e}else{l(z,O);break}else t(z,O);O=O.sibling}G=Mo(j,z.mode,G),G.return=z,z=G}return y(z);case $:return j=ea(j),$e(z,O,j,G)}if(be(j))return se(z,O,j,G);if(P(j)){if(he=P(j),typeof he!="function")throw Error(s(150));return j=he.call(j),pe(z,O,j,G)}if(typeof j.then=="function")return $e(z,O,_r(j),G);if(j.$$typeof===M)return $e(z,O,br(z,j),G);kr(z,j)}return typeof j=="string"&&j!==""||typeof j=="number"||typeof j=="bigint"?(j=""+j,O!==null&&O.tag===6?(l(z,O.sibling),G=c(O,j),G.return=z,z=G):(l(z,O),G=No(j,z.mode,G),G.return=z,z=G),y(z)):l(z,O)}return function(z,O,j,G){try{Zl=0;var he=$e(z,O,j,G);return Va=null,he}catch(ue){if(ue===Ya||ue===xr)throw ue;var qe=Qt(29,ue,null,z.mode);return qe.lanes=G,qe.return=z,qe}finally{}}}var na=Yh(!0),Vh=Yh(!1),gi=!1;function Vo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Go(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function bi(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function vi(e,t,l){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,(He&2)!==0){var c=r.pending;return c===null?t.next=t:(t.next=c.next,c.next=t),r.pending=t,t=pr(e),Th(e,null,l),t}return hr(e,r,t,l),pr(e)}function $l(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var r=t.lanes;r&=e.pendingLanes,l|=r,t.lanes=l,jd(e,l)}}function Ko(e,t){var l=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,l===r)){var c=null,d=null;if(l=l.firstBaseUpdate,l!==null){do{var y={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};d===null?c=d=y:d=d.next=y,l=l.next}while(l!==null);d===null?c=d=t:d=d.next=t}else c=d=t;l={baseState:r.baseState,firstBaseUpdate:c,lastBaseUpdate:d,shared:r.shared,callbacks:r.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Zo=!1;function Xl(){if(Zo){var e=Ia;if(e!==null)throw e}}function Jl(e,t,l,r){Zo=!1;var c=e.updateQueue;gi=!1;var d=c.firstBaseUpdate,y=c.lastBaseUpdate,x=c.shared.pending;if(x!==null){c.shared.pending=null;var T=x,R=T.next;T.next=null,y===null?d=R:y.next=R,y=T;var I=e.alternate;I!==null&&(I=I.updateQueue,x=I.lastBaseUpdate,x!==y&&(x===null?I.firstBaseUpdate=R:x.next=R,I.lastBaseUpdate=T))}if(d!==null){var Z=c.baseState;y=0,I=R=T=null,x=d;do{var L=x.lane&-536870913,U=L!==x.lane;if(U?(De&L)===L:(r&L)===L){L!==0&&L===Ha&&(Zo=!0),I!==null&&(I=I.next={lane:0,tag:x.tag,payload:x.payload,callback:null,next:null});e:{var se=e,pe=x;L=t;var $e=l;switch(pe.tag){case 1:if(se=pe.payload,typeof se=="function"){Z=se.call($e,Z,L);break e}Z=se;break e;case 3:se.flags=se.flags&-65537|128;case 0:if(se=pe.payload,L=typeof se=="function"?se.call($e,Z,L):se,L==null)break e;Z=b({},Z,L);break e;case 2:gi=!0}}L=x.callback,L!==null&&(e.flags|=64,U&&(e.flags|=8192),U=c.callbacks,U===null?c.callbacks=[L]:U.push(L))}else U={lane:L,tag:x.tag,payload:x.payload,callback:x.callback,next:null},I===null?(R=I=U,T=Z):I=I.next=U,y|=L;if(x=x.next,x===null){if(x=c.shared.pending,x===null)break;U=x,x=U.next,U.next=null,c.lastBaseUpdate=U,c.shared.pending=null}}while(!0);I===null&&(T=Z),c.baseState=T,c.firstBaseUpdate=R,c.lastBaseUpdate=I,d===null&&(c.shared.lanes=0),wi|=y,e.lanes=y,e.memoizedState=Z}}function Gh(e,t){if(typeof e!="function")throw Error(s(191,e));e.call(t)}function Kh(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ed?d:8;var y=q.T,x={};q.T=x,fc(e,!1,t,l);try{var T=c(),R=q.S;if(R!==null&&R(x,T),T!==null&&typeof T=="object"&&typeof T.then=="function"){var I=av(T,r);Pl(e,t,I,Wt(e))}else Pl(e,t,r,Wt(e))}catch(Z){Pl(e,t,{then:function(){},status:"rejected",reason:Z},Wt())}finally{J.p=d,y!==null&&x.types!==null&&(y.types=x.types),q.T=y}}function cv(){}function oc(e,t,l,r){if(e.tag!==5)throw Error(s(476));var c=kp(e).queue;_p(e,c,t,oe,l===null?cv:function(){return wp(e),l(r)})}function kp(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:oe,baseState:oe,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Qn,lastRenderedState:oe},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Qn,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function wp(e){var t=kp(e);t.next===null&&(t=e.alternate.memoizedState),Pl(e,t.next.queue,{},Wt())}function cc(){return kt(ys)}function Ap(){return st().memoizedState}function Tp(){return st().memoizedState}function fv(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Wt();e=bi(l);var r=vi(t,e,l);r!==null&&(It(r,t,l),$l(r,t,l)),t={cache:Uo()},e.payload=t;return}t=t.return}}function dv(e,t,l){var r=Wt();l={lane:r,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Dr(e)?Cp(t,l):(l=Co(e,t,l,r),l!==null&&(It(l,e,r),Op(l,t,r)))}function Ep(e,t,l){var r=Wt();Pl(e,t,l,r)}function Pl(e,t,l,r){var c={lane:r,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Dr(e))Cp(t,c);else{var d=e.alternate;if(e.lanes===0&&(d===null||d.lanes===0)&&(d=t.lastRenderedReducer,d!==null))try{var y=t.lastRenderedState,x=d(y,l);if(c.hasEagerState=!0,c.eagerState=x,Zt(x,y))return hr(e,t,c,0),Je===null&&dr(),!1}catch{}finally{}if(l=Co(e,t,c,r),l!==null)return It(l,e,r),Op(l,t,r),!0}return!1}function fc(e,t,l,r){if(r={lane:2,revertLane:Vc(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Dr(e)){if(t)throw Error(s(479))}else t=Co(e,l,r,2),t!==null&&It(t,e,2)}function Dr(e){var t=e.alternate;return e===we||t!==null&&t===we}function Cp(e,t){Ka=Tr=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Op(e,t,l){if((l&4194048)!==0){var r=t.lanes;r&=e.pendingLanes,l|=r,t.lanes=l,jd(e,l)}}var es={readContext:kt,use:Or,useCallback:it,useContext:it,useEffect:it,useImperativeHandle:it,useLayoutEffect:it,useInsertionEffect:it,useMemo:it,useReducer:it,useRef:it,useState:it,useDebugValue:it,useDeferredValue:it,useTransition:it,useSyncExternalStore:it,useId:it,useHostTransitionStatus:it,useFormState:it,useActionState:it,useOptimistic:it,useMemoCache:it,useCacheRefresh:it};es.useEffectEvent=it;var Np={readContext:kt,use:Or,useCallback:function(e,t){return Ot().memoizedState=[e,t===void 0?null:t],e},useContext:kt,useEffect:hp,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Mr(4194308,4,gp.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Mr(4194308,4,e,t)},useInsertionEffect:function(e,t){Mr(4,2,e,t)},useMemo:function(e,t){var l=Ot();t=t===void 0?null:t;var r=e();if(ia){jt(!0);try{e()}finally{jt(!1)}}return l.memoizedState=[r,t],r},useReducer:function(e,t,l){var r=Ot();if(l!==void 0){var c=l(t);if(ia){jt(!0);try{l(t)}finally{jt(!1)}}}else c=t;return r.memoizedState=r.baseState=c,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:c},r.queue=e,e=e.dispatch=dv.bind(null,we,e),[r.memoizedState,e]},useRef:function(e){var t=Ot();return e={current:e},t.memoizedState=e},useState:function(e){e=ac(e);var t=e.queue,l=Ep.bind(null,we,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:rc,useDeferredValue:function(e,t){var l=Ot();return uc(l,e,t)},useTransition:function(){var e=ac(!1);return e=_p.bind(null,we,e.queue,!0,!1),Ot().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var r=we,c=Ot();if(Be){if(l===void 0)throw Error(s(407));l=l()}else{if(l=t(),Je===null)throw Error(s(349));(De&127)!==0||Fh(r,t,l)}c.memoizedState=l;var d={value:l,getSnapshot:t};return c.queue=d,hp(Ph.bind(null,r,d,e),[e]),r.flags|=2048,Qa(9,{destroy:void 0},Wh.bind(null,r,d,l,t),null),l},useId:function(){var e=Ot(),t=Je.identifierPrefix;if(Be){var l=An,r=wn;l=(r&~(1<<32-Xe(r)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Er++,0<\/script>",d=d.removeChild(d.firstChild);break;case"select":d=typeof r.is=="string"?y.createElement("select",{is:r.is}):y.createElement("select"),r.multiple?d.multiple=!0:r.size&&(d.size=r.size);break;default:d=typeof r.is=="string"?y.createElement(c,{is:r.is}):y.createElement(c)}}d[St]=t,d[Rt]=r;e:for(y=t.child;y!==null;){if(y.tag===5||y.tag===6)d.appendChild(y.stateNode);else if(y.tag!==4&&y.tag!==27&&y.child!==null){y.child.return=y,y=y.child;continue}if(y===t)break e;for(;y.sibling===null;){if(y.return===null||y.return===t)break e;y=y.return}y.sibling.return=y.return,y=y.sibling}t.stateNode=d;e:switch(At(d,c,r),c){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}r&&Xn(t)}}return et(t),Ac(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Xn(t);else{if(typeof r!="string"&&t.stateNode===null)throw Error(s(166));if(e=de.current,qa(t)){if(e=t.stateNode,l=t.memoizedProps,r=null,c=_t,c!==null)switch(c.tag){case 27:case 5:r=c.memoizedProps}e[St]=t,e=!!(e.nodeValue===l||r!==null&&r.suppressHydrationWarning===!0||Xm(e.nodeValue,l)),e||mi(t,!0)}else e=Pr(e).createTextNode(r),e[St]=t,t.stateNode=e}return et(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(r=qa(t),l!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(s(557));e[St]=t}else Ji(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;et(t),e=!1}else l=Ro(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Xt(t),t):(Xt(t),null);if((t.flags&128)!==0)throw Error(s(558))}return et(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(c=qa(t),r!==null&&r.dehydrated!==null){if(e===null){if(!c)throw Error(s(318));if(c=t.memoizedState,c=c!==null?c.dehydrated:null,!c)throw Error(s(317));c[St]=t}else Ji(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;et(t),c=!1}else c=Ro(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=c),c=!0;if(!c)return t.flags&256?(Xt(t),t):(Xt(t),null)}return Xt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=r!==null,e=e!==null&&e.memoizedState!==null,l&&(r=t.child,c=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(c=r.alternate.memoizedState.cachePool.pool),d=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(d=r.memoizedState.cachePool.pool),d!==c&&(r.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),qr(t,t.updateQueue),et(t),null);case 4:return Ke(),e===null&&Qc(t.stateNode.containerInfo),et(t),null;case 10:return Kn(t.type),et(t),null;case 19:if(Y(lt),r=t.memoizedState,r===null)return et(t),null;if(c=(t.flags&128)!==0,d=r.rendering,d===null)if(c)ns(r,!1);else{if(at!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(d=Ar(e),d!==null){for(t.flags|=128,ns(r,!1),e=d.updateQueue,t.updateQueue=e,qr(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Eh(l,e),l=l.sibling;return k(lt,lt.current&1|2),Be&&Vn(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Et()>Vr&&(t.flags|=128,c=!0,ns(r,!1),t.lanes=4194304)}else{if(!c)if(e=Ar(d),e!==null){if(t.flags|=128,c=!0,e=e.updateQueue,t.updateQueue=e,qr(t,e),ns(r,!0),r.tail===null&&r.tailMode==="hidden"&&!d.alternate&&!Be)return et(t),null}else 2*Et()-r.renderingStartTime>Vr&&l!==536870912&&(t.flags|=128,c=!0,ns(r,!1),t.lanes=4194304);r.isBackwards?(d.sibling=t.child,t.child=d):(e=r.last,e!==null?e.sibling=d:t.child=d,r.last=d)}return r.tail!==null?(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Et(),e.sibling=null,l=lt.current,k(lt,c?l&1|2:l&1),Be&&Vn(t,r.treeForkCount),e):(et(t),null);case 22:case 23:return Xt(t),$o(),r=t.memoizedState!==null,e!==null?e.memoizedState!==null!==r&&(t.flags|=8192):r&&(t.flags|=8192),r?(l&536870912)!==0&&(t.flags&128)===0&&(et(t),t.subtreeFlags&6&&(t.flags|=8192)):et(t),l=t.updateQueue,l!==null&&qr(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==l&&(t.flags|=2048),e!==null&&Y(Pi),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Kn(ct),et(t),null;case 25:return null;case 30:return null}throw Error(s(156,t.tag))}function gv(e,t){switch(Do(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Kn(ct),Ke(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Bn(t),null;case 31:if(t.memoizedState!==null){if(Xt(t),t.alternate===null)throw Error(s(340));Ji()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Xt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));Ji()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Y(lt),null;case 4:return Ke(),null;case 10:return Kn(t.type),null;case 22:case 23:return Xt(t),$o(),e!==null&&Y(Pi),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Kn(ct),null;case 25:return null;default:return null}}function em(e,t){switch(Do(t),t.tag){case 3:Kn(ct),Ke();break;case 26:case 27:case 5:Bn(t);break;case 4:Ke();break;case 31:t.memoizedState!==null&&Xt(t);break;case 13:Xt(t);break;case 19:Y(lt);break;case 10:Kn(t.type);break;case 22:case 23:Xt(t),$o(),e!==null&&Y(Pi);break;case 24:Kn(ct)}}function is(e,t){try{var l=t.updateQueue,r=l!==null?l.lastEffect:null;if(r!==null){var c=r.next;l=c;do{if((l.tag&e)===e){r=void 0;var d=l.create,y=l.inst;r=d(),y.destroy=r}l=l.next}while(l!==c)}}catch(x){Ge(t,t.return,x)}}function _i(e,t,l){try{var r=t.updateQueue,c=r!==null?r.lastEffect:null;if(c!==null){var d=c.next;r=d;do{if((r.tag&e)===e){var y=r.inst,x=y.destroy;if(x!==void 0){y.destroy=void 0,c=t;var T=l,R=x;try{R()}catch(I){Ge(c,T,I)}}}r=r.next}while(r!==d)}}catch(I){Ge(t,t.return,I)}}function tm(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{Kh(t,l)}catch(r){Ge(e,e.return,r)}}}function nm(e,t,l){l.props=aa(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(r){Ge(e,t,r)}}function as(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof l=="function"?e.refCleanup=l(r):l.current=r}}catch(c){Ge(e,t,c)}}function Tn(e,t){var l=e.ref,r=e.refCleanup;if(l!==null)if(typeof r=="function")try{r()}catch(c){Ge(e,t,c)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(c){Ge(e,t,c)}else l.current=null}function im(e){var t=e.type,l=e.memoizedProps,r=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&r.focus();break e;case"img":l.src?r.src=l.src:l.srcSet&&(r.srcset=l.srcSet)}}catch(c){Ge(e,e.return,c)}}function Tc(e,t,l){try{var r=e.stateNode;Uv(r,e.type,l,t),r[Rt]=t}catch(c){Ge(e,e.return,c)}}function am(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Oi(e.type)||e.tag===4}function Ec(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||am(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Oi(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Cc(e,t,l){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=Hn));else if(r!==4&&(r===27&&Oi(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Cc(e,t,l),e=e.sibling;e!==null;)Cc(e,t,l),e=e.sibling}function Ur(e,t,l){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(r!==4&&(r===27&&Oi(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Ur(e,t,l),e=e.sibling;e!==null;)Ur(e,t,l),e=e.sibling}function lm(e){var t=e.stateNode,l=e.memoizedProps;try{for(var r=e.type,c=t.attributes;c.length;)t.removeAttributeNode(c[0]);At(t,r,l),t[St]=e,t[Rt]=l}catch(d){Ge(e,e.return,d)}}var Jn=!1,ht=!1,Oc=!1,sm=typeof WeakSet=="function"?WeakSet:Set,vt=null;function bv(e,t){if(e=e.containerInfo,Jc=su,e=bh(e),_o(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var r=l.getSelection&&l.getSelection();if(r&&r.rangeCount!==0){l=r.anchorNode;var c=r.anchorOffset,d=r.focusNode;r=r.focusOffset;try{l.nodeType,d.nodeType}catch{l=null;break e}var y=0,x=-1,T=-1,R=0,I=0,Z=e,L=null;t:for(;;){for(var U;Z!==l||c!==0&&Z.nodeType!==3||(x=y+c),Z!==d||r!==0&&Z.nodeType!==3||(T=y+r),Z.nodeType===3&&(y+=Z.nodeValue.length),(U=Z.firstChild)!==null;)L=Z,Z=U;for(;;){if(Z===e)break t;if(L===l&&++R===c&&(x=y),L===d&&++I===r&&(T=y),(U=Z.nextSibling)!==null)break;Z=L,L=Z.parentNode}Z=U}l=x===-1||T===-1?null:{start:x,end:T}}else l=null}l=l||{start:0,end:0}}else l=null;for(Fc={focusedElem:e,selectionRange:l},su=!1,vt=t;vt!==null;)if(t=vt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,vt=e;else for(;vt!==null;){switch(t=vt,d=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),At(d,r,l),d[St]=e,bt(d),r=d;break e;case"link":var y=dy("link","href",c).get(r+(l.href||""));if(y){for(var x=0;x$e&&(y=$e,$e=pe,pe=y);var z=yh(x,pe),O=yh(x,$e);if(z&&O&&(U.rangeCount!==1||U.anchorNode!==z.node||U.anchorOffset!==z.offset||U.focusNode!==O.node||U.focusOffset!==O.offset)){var j=Z.createRange();j.setStart(z.node,z.offset),U.removeAllRanges(),pe>$e?(U.addRange(j),U.extend(O.node,O.offset)):(j.setEnd(O.node,O.offset),U.addRange(j))}}}}for(Z=[],U=x;U=U.parentNode;)U.nodeType===1&&Z.push({element:U,left:U.scrollLeft,top:U.scrollTop});for(typeof x.focus=="function"&&x.focus(),x=0;xl?32:l,q.T=null,l=Bc,Bc=null;var d=Ti,y=ti;if(yt=0,Wa=Ti=null,ti=0,(He&6)!==0)throw Error(s(331));var x=He;if(He|=4,gm(d.current),pm(d,d.current,y,l),He=x,cs(0,!1),mt&&typeof mt.onPostCommitFiberRoot=="function")try{mt.onPostCommitFiberRoot(Ct,d)}catch{}return!0}finally{J.p=c,q.T=r,Rm(e,t)}}function Lm(e,t,l){t=ln(l,t),t=mc(e.stateNode,t,2),e=vi(e,t,2),e!==null&&(Nl(e,2),En(e))}function Ge(e,t,l){if(e.tag===3)Lm(e,e,l);else for(;t!==null;){if(t.tag===3){Lm(t,e,l);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof r.componentDidCatch=="function"&&(Ai===null||!Ai.has(r))){e=ln(l,e),l=qp(2),r=vi(t,l,2),r!==null&&(Up(l,r,t,e),Nl(r,2),En(r));break}}t=t.return}}function Hc(e,t,l){var r=e.pingCache;if(r===null){r=e.pingCache=new Sv;var c=new Set;r.set(t,c)}else c=r.get(t),c===void 0&&(c=new Set,r.set(t,c));c.has(l)||(zc=!0,c.add(l),e=Tv.bind(null,e,t,l),t.then(e,e))}function Tv(e,t,l){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Je===e&&(De&l)===l&&(at===4||at===3&&(De&62914560)===De&&300>Et()-Yr?(He&2)===0&&Pa(e,0):Dc|=l,Fa===De&&(Fa=0)),En(e)}function qm(e,t){t===0&&(t=zd()),e=$i(e,t),e!==null&&(Nl(e,t),En(e))}function Ev(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),qm(e,l)}function Cv(e,t){var l=0;switch(e.tag){case 31:case 13:var r=e.stateNode,c=e.memoizedState;c!==null&&(l=c.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),qm(e,l)}function Ov(e,t){return Sa(e,t)}var Xr=null,tl=null,Ic=!1,Jr=!1,Yc=!1,Ci=0;function En(e){e!==tl&&e.next===null&&(tl===null?Xr=tl=e:tl=tl.next=e),Jr=!0,Ic||(Ic=!0,Mv())}function cs(e,t){if(!Yc&&Jr){Yc=!0;do for(var l=!1,r=Xr;r!==null;){if(e!==0){var c=r.pendingLanes;if(c===0)var d=0;else{var y=r.suspendedLanes,x=r.pingedLanes;d=(1<<31-Xe(42|e)+1)-1,d&=c&~(y&~x),d=d&201326741?d&201326741|1:d?d|2:0}d!==0&&(l=!0,Ym(r,d))}else d=De,d=er(r,r===Je?d:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),(d&3)===0||Ol(r,d)||(l=!0,Ym(r,d));r=r.next}while(l);Yc=!1}}function Nv(){Um()}function Um(){Jr=Ic=!1;var e=0;Ci!==0&&Iv()&&(e=Ci);for(var t=Et(),l=null,r=Xr;r!==null;){var c=r.next,d=Hm(r,t);d===0?(r.next=null,l===null?Xr=c:l.next=c,c===null&&(tl=l)):(l=r,(e!==0||(d&3)!==0)&&(Jr=!0)),r=c}yt!==0&&yt!==5||cs(e),Ci!==0&&(Ci=0)}function Hm(e,t){for(var l=e.suspendedLanes,r=e.pingedLanes,c=e.expirationTimes,d=e.pendingLanes&-62914561;0x)break;var I=T.transferSize,Z=T.initiatorType;I&&Jm(Z)&&(T=T.responseEnd,y+=I*(T"u"?null:document;function uy(e,t,l){var r=nl;if(r&&typeof t=="string"&&t){var c=nn(t);c='link[rel="'+e+'"][href="'+c+'"]',typeof l=="string"&&(c+='[crossorigin="'+l+'"]'),ry.has(c)||(ry.add(c),e={rel:e,crossOrigin:l,href:t},r.querySelector(c)===null&&(t=r.createElement("link"),At(t,"link",e),bt(t),r.head.appendChild(t)))}}function Jv(e){ni.D(e),uy("dns-prefetch",e,null)}function Fv(e,t){ni.C(e,t),uy("preconnect",e,t)}function Wv(e,t,l){ni.L(e,t,l);var r=nl;if(r&&e&&t){var c='link[rel="preload"][as="'+nn(t)+'"]';t==="image"&&l&&l.imageSrcSet?(c+='[imagesrcset="'+nn(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(c+='[imagesizes="'+nn(l.imageSizes)+'"]')):c+='[href="'+nn(e)+'"]';var d=c;switch(t){case"style":d=il(e);break;case"script":d=al(e)}fn.has(d)||(e=b({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),fn.set(d,e),r.querySelector(c)!==null||t==="style"&&r.querySelector(ps(d))||t==="script"&&r.querySelector(ms(d))||(t=r.createElement("link"),At(t,"link",e),bt(t),r.head.appendChild(t)))}}function Pv(e,t){ni.m(e,t);var l=nl;if(l&&e){var r=t&&typeof t.as=="string"?t.as:"script",c='link[rel="modulepreload"][as="'+nn(r)+'"][href="'+nn(e)+'"]',d=c;switch(r){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":d=al(e)}if(!fn.has(d)&&(e=b({rel:"modulepreload",href:e},t),fn.set(d,e),l.querySelector(c)===null)){switch(r){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(ms(d)))return}r=l.createElement("link"),At(r,"link",e),bt(r),l.head.appendChild(r)}}}function e1(e,t,l){ni.S(e,t,l);var r=nl;if(r&&e){var c=Aa(r).hoistableStyles,d=il(e);t=t||"default";var y=c.get(d);if(!y){var x={loading:0,preload:null};if(y=r.querySelector(ps(d)))x.loading=5;else{e=b({rel:"stylesheet",href:e,"data-precedence":t},l),(l=fn.get(d))&&lf(e,l);var T=y=r.createElement("link");bt(T),At(T,"link",e),T._p=new Promise(function(R,I){T.onload=R,T.onerror=I}),T.addEventListener("load",function(){x.loading|=1}),T.addEventListener("error",function(){x.loading|=2}),x.loading|=4,tu(y,t,r)}y={type:"stylesheet",instance:y,count:1,state:x},c.set(d,y)}}}function t1(e,t){ni.X(e,t);var l=nl;if(l&&e){var r=Aa(l).hoistableScripts,c=al(e),d=r.get(c);d||(d=l.querySelector(ms(c)),d||(e=b({src:e,async:!0},t),(t=fn.get(c))&&sf(e,t),d=l.createElement("script"),bt(d),At(d,"link",e),l.head.appendChild(d)),d={type:"script",instance:d,count:1,state:null},r.set(c,d))}}function n1(e,t){ni.M(e,t);var l=nl;if(l&&e){var r=Aa(l).hoistableScripts,c=al(e),d=r.get(c);d||(d=l.querySelector(ms(c)),d||(e=b({src:e,async:!0,type:"module"},t),(t=fn.get(c))&&sf(e,t),d=l.createElement("script"),bt(d),At(d,"link",e),l.head.appendChild(d)),d={type:"script",instance:d,count:1,state:null},r.set(c,d))}}function oy(e,t,l,r){var c=(c=de.current)?eu(c):null;if(!c)throw Error(s(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=il(l.href),l=Aa(c).hoistableStyles,r=l.get(t),r||(r={type:"style",instance:null,count:0,state:null},l.set(t,r)),r):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=il(l.href);var d=Aa(c).hoistableStyles,y=d.get(e);if(y||(c=c.ownerDocument||c,y={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},d.set(e,y),(d=c.querySelector(ps(e)))&&!d._p&&(y.instance=d,y.state.loading=5),fn.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},fn.set(e,l),d||i1(c,e,l,y.state))),t&&r===null)throw Error(s(528,""));return y}if(t&&r!==null)throw Error(s(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=al(l),l=Aa(c).hoistableScripts,r=l.get(t),r||(r={type:"script",instance:null,count:0,state:null},l.set(t,r)),r):{type:"void",instance:null,count:0,state:null};default:throw Error(s(444,e))}}function il(e){return'href="'+nn(e)+'"'}function ps(e){return'link[rel="stylesheet"]['+e+"]"}function cy(e){return b({},e,{"data-precedence":e.precedence,precedence:null})}function i1(e,t,l,r){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?r.loading=1:(t=e.createElement("link"),r.preload=t,t.addEventListener("load",function(){return r.loading|=1}),t.addEventListener("error",function(){return r.loading|=2}),At(t,"link",l),bt(t),e.head.appendChild(t))}function al(e){return'[src="'+nn(e)+'"]'}function ms(e){return"script[async]"+e}function fy(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var r=e.querySelector('style[data-href~="'+nn(l.href)+'"]');if(r)return t.instance=r,bt(r),r;var c=b({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement("style"),bt(r),At(r,"style",c),tu(r,l.precedence,e),t.instance=r;case"stylesheet":c=il(l.href);var d=e.querySelector(ps(c));if(d)return t.state.loading|=4,t.instance=d,bt(d),d;r=cy(l),(c=fn.get(c))&&lf(r,c),d=(e.ownerDocument||e).createElement("link"),bt(d);var y=d;return y._p=new Promise(function(x,T){y.onload=x,y.onerror=T}),At(d,"link",r),t.state.loading|=4,tu(d,l.precedence,e),t.instance=d;case"script":return d=al(l.src),(c=e.querySelector(ms(d)))?(t.instance=c,bt(c),c):(r=l,(c=fn.get(d))&&(r=b({},l),sf(r,c)),e=e.ownerDocument||e,c=e.createElement("script"),bt(c),At(c,"link",r),e.head.appendChild(c),t.instance=c);case"void":return null;default:throw Error(s(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(r=t.instance,t.state.loading|=4,tu(r,l.precedence,e));return t.instance}function tu(e,t,l){for(var r=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),c=r.length?r[r.length-1]:null,d=c,y=0;y title"):null)}function a1(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function py(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function l1(e,t,l,r){if(l.type==="stylesheet"&&(typeof r.media!="string"||matchMedia(r.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var c=il(r.href),d=t.querySelector(ps(c));if(d){t=d._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=iu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=d,bt(d);return}d=t.ownerDocument||t,r=cy(r),(c=fn.get(c))&&lf(r,c),d=d.createElement("link"),bt(d);var y=d;y._p=new Promise(function(x,T){y.onload=x,y.onerror=T}),At(d,"link",r),l.instance=d}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=iu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var rf=0;function s1(e,t){return e.stylesheets&&e.count===0&&lu(e,e.stylesheets),0rf?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(c)}}:null}function iu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)lu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var au=null;function lu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,au=new Map,t.forEach(r1,e),au=null,iu.call(e))}function r1(e,t){if(!(t.state.loading&4)){var l=au.get(e);if(l)var r=l.get(null);else{l=new Map,au.set(e,l);for(var c=e.querySelectorAll("link[data-precedence],style[data-precedence]"),d=0;d"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(n){console.error(n)}}return i(),yf.exports=T1(),yf.exports}var C1=E1();const O1=[{mode:"keyword",label:"Keyword / Phrase",description:"User says a specific word or phrase"},{mode:"immediate",label:"Immediate",description:"Right when conversation starts"},{mode:"contextual",label:"Contextual",description:"Based on conversation context"}];function N1({domain:i,onChange:n,onSample:a}){const s=(o,f)=>{n({...i,[o]:f})},u=o=>{n({...i,triggerMode:o,trigger:o==="immediate"?"":i.trigger})};return S.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:[S.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[S.jsx("h3",{style:{margin:0,fontSize:"14px",fontWeight:600,color:"#e0e0e0"},children:"Domain Context"}),S.jsx("button",{type:"button",onClick:a,style:M1,title:"Fill with random sample data",children:"Sample"})]}),S.jsxs("label",{style:hu,children:[S.jsx("span",{style:_s,children:"Flow Name"}),S.jsx("input",{type:"text",value:i.name,onChange:o=>s("name",o.target.value),placeholder:"e.g., kyc-verification",style:rl})]}),S.jsxs("label",{style:hu,children:[S.jsx("span",{style:_s,children:"Domain"}),S.jsx("input",{type:"text",value:i.domain,onChange:o=>s("domain",o.target.value),placeholder:"e.g., finance, healthcare, engineering",style:rl})]}),S.jsxs("label",{style:hu,children:[S.jsx("span",{style:_s,children:"Description"}),S.jsx("textarea",{value:i.description,onChange:o=>s("description",o.target.value),placeholder:"What should this flow accomplish?",rows:3,style:{...rl,resize:"vertical"}})]}),S.jsxs("label",{style:hu,children:[S.jsx("span",{style:_s,children:"Business Rules"}),S.jsx("textarea",{value:i.businessRules,onChange:o=>s("businessRules",o.target.value),placeholder:"Constraints, requirements, compliance rules...",rows:3,style:{...rl,resize:"vertical"}})]}),S.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"6px"},children:[S.jsx("span",{style:_s,children:"When to Display"}),S.jsx("div",{style:{display:"flex",gap:"6px"},children:O1.map(o=>S.jsx("button",{type:"button",onClick:()=>u(o.mode),title:o.description,style:{...z1,...i.triggerMode===o.mode?{borderColor:"#6366f1",color:"#a5b4fc",background:"#1e1b4b"}:{}},children:o.label},o.mode))}),i.triggerMode==="keyword"&&S.jsx("input",{type:"text",value:i.trigger,onChange:o=>s("trigger",o.target.value),placeholder:'e.g., "start KYC", "new incident", "onboard vendor"',style:rl}),i.triggerMode==="immediate"&&S.jsx("span",{style:{fontSize:"11px",color:"#666",fontStyle:"italic"},children:"Components will be generated in the first response."}),i.triggerMode==="contextual"&&S.jsx("textarea",{value:i.trigger,onChange:o=>s("trigger",o.target.value),placeholder:'Describe the situation, e.g., "After user provides customer name and issue description" or "When 3 resolution attempts have failed"',rows:3,style:{...rl,resize:"vertical"}})]})]})}const hu={display:"flex",flexDirection:"column",gap:"4px"},_s={fontSize:"12px",fontWeight:500,color:"#aaa"},rl={padding:"8px 10px",border:"1px solid #333",borderRadius:"6px",background:"#1a1a1a",color:"#e0e0e0",fontSize:"13px",fontFamily:"inherit",outline:"none"},M1={padding:"4px 10px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#6366f1",fontSize:"11px",fontWeight:500,cursor:"pointer"},z1={padding:"5px 10px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#888",fontSize:"11px",fontWeight:500,cursor:"pointer",flex:1,textAlign:"center"},D1={form:{label:"Form",description:"Collect structured user input",icon:"📋"},button:{label:"Button",description:"Trigger actions on click",icon:"🔘"},tasklist:{label:"Tasklist",description:"Checklist with completion tracking",icon:"✅"},table:{label:"Table",description:"Display tabular data",icon:"📊"},callout:{label:"Callout",description:"Highlighted info/warning blocks",icon:"💡"},"approval-gate":{label:"Approval Gate",description:"Require approvals to proceed",icon:"🔒"},webhook:{label:"Webhook",description:"HTTP requests on action",icon:"🔗"},chart:{label:"Chart",description:"Data visualization",icon:"📈"},thinking:{label:"Thinking",description:"AI reasoning display",icon:"🧠"}};function j1({components:i,onToggle:n}){return S.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:[S.jsx("h3",{style:{margin:0,fontSize:"14px",fontWeight:600,color:"#e0e0e0"},children:"Components"}),S.jsx("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:"8px"},children:i.map(a=>{const s=D1[a.type];return S.jsxs("button",{onClick:()=>n(a.type),style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"4px",padding:"10px 6px",border:a.enabled?"2px solid #6366f1":"1px solid #333",borderRadius:"8px",background:a.enabled?"#1e1b4b":"#1a1a1a",color:a.enabled?"#a5b4fc":"#888",cursor:"pointer",transition:"all 0.15s",fontSize:"11px",textAlign:"center"},children:[S.jsx("span",{style:{fontSize:"20px"},children:s.icon}),S.jsx("span",{style:{fontWeight:600,fontSize:"12px"},children:s.label}),S.jsx("span",{style:{fontSize:"10px",color:"#666",lineHeight:1.2},children:s.description})]},a.type)})})]})}function R1({components:i,onUpdate:n}){const a=i.filter(s=>s.enabled&&s.type!=="thinking");return a.length===0?S.jsx("p",{style:{color:"#666",fontSize:"13px",fontStyle:"italic"},children:"Select components above to configure them."}):S.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:[S.jsx("h3",{style:{margin:0,fontSize:"14px",fontWeight:600,color:"#e0e0e0"},children:"Configure Components"}),a.map(s=>S.jsx(B1,{config:s,onUpdate:n},s.type))]})}function B1({config:i,onUpdate:n}){switch(i.type){case"form":return S.jsx(L1,{config:i,onUpdate:n});case"approval-gate":return S.jsx(q1,{config:i,onUpdate:n});case"tasklist":return S.jsx(U1,{config:i,onUpdate:n});case"table":return S.jsx(H1,{config:i,onUpdate:n});default:return S.jsxs("div",{style:Hs,children:[S.jsx("span",{style:Is,children:i.type}),S.jsx("span",{style:{fontSize:"12px",color:"#666"},children:"No additional configuration needed."})]})}}function L1({config:i,onUpdate:n}){var h;const a=((h=i.form)==null?void 0:h.fields)??[],[s,u]=re.useState({name:"",type:"text",label:"",required:!1,sensitive:!1}),o=()=>{!s.name||!s.label||(n("form",{form:{fields:[...a,{...s}]}}),u({name:"",type:"text",label:"",required:!1,sensitive:!1}))},f=m=>{n("form",{form:{fields:a.filter((p,g)=>g!==m)}})};return S.jsxs("div",{style:Hs,children:[S.jsx("span",{style:Is,children:"Form Fields"}),a.map((m,p)=>S.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",fontSize:"12px"},children:[S.jsx("span",{style:{color:"#a5b4fc",fontWeight:500},children:m.name}),S.jsxs("span",{style:{color:"#666"},children:["(",m.type,")"]}),S.jsxs("span",{style:{color:"#888"},children:['"',m.label,'"']}),m.required&&S.jsx("span",{style:{color:"#f59e0b",fontSize:"10px"},children:"required"}),m.sensitive&&S.jsx("span",{style:{color:"#ef4444",fontSize:"10px"},children:"sensitive"}),S.jsx("button",{onClick:()=>f(p),style:qu,children:"x"})]},p)),S.jsxs("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap",alignItems:"center"},children:[S.jsx("input",{placeholder:"name",value:s.name,onChange:m=>u(p=>({...p,name:m.target.value})),style:{...qi,width:"80px"}}),S.jsx("input",{placeholder:"label",value:s.label,onChange:m=>u(p=>({...p,label:m.target.value})),style:{...qi,width:"100px"}}),S.jsx("select",{value:s.type,onChange:m=>u(p=>({...p,type:m.target.value})),style:qi,children:["text","number","email","date","select","checkbox","textarea"].map(m=>S.jsx("option",{value:m,children:m},m))}),S.jsxs("label",{style:{fontSize:"11px",color:"#888",display:"flex",gap:"3px",alignItems:"center"},children:[S.jsx("input",{type:"checkbox",checked:s.required,onChange:m=>u(p=>({...p,required:m.target.checked}))}),"req"]}),S.jsxs("label",{style:{fontSize:"11px",color:"#888",display:"flex",gap:"3px",alignItems:"center"},children:[S.jsx("input",{type:"checkbox",checked:s.sensitive,onChange:m=>u(p=>({...p,sensitive:m.target.checked}))}),"PII"]}),S.jsx("button",{onClick:o,style:Lu,children:"+ Add"})]})]})}function q1({config:i,onUpdate:n}){const a=i.approvalGate??{roles:[],requiredApprovers:1,requireReason:!1},[s,u]=re.useState(""),o=()=>{s&&(n("approval-gate",{approvalGate:{...a,roles:[...a.roles,s]}}),u(""))};return S.jsxs("div",{style:Hs,children:[S.jsx("span",{style:Is,children:"Approval Gate"}),S.jsx("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap"},children:a.roles.map((f,h)=>S.jsxs("span",{style:{background:"#1e1b4b",color:"#a5b4fc",padding:"2px 8px",borderRadius:"4px",fontSize:"11px"},children:[f,S.jsx("button",{onClick:()=>n("approval-gate",{approvalGate:{...a,roles:a.roles.filter((m,p)=>p!==h)}}),style:{...qu,marginLeft:"4px"},children:"x"})]},h))}),S.jsxs("div",{style:{display:"flex",gap:"6px",alignItems:"center"},children:[S.jsx("input",{placeholder:"role name",value:s,onChange:f=>u(f.target.value),onKeyDown:f=>f.key==="Enter"&&o(),style:qi}),S.jsx("button",{onClick:o,style:Lu,children:"+ Role"})]}),S.jsxs("label",{style:{fontSize:"12px",color:"#888",display:"flex",gap:"8px",alignItems:"center"},children:["Required approvers:",S.jsx("input",{type:"number",min:1,value:a.requiredApprovers,onChange:f=>n("approval-gate",{approvalGate:{...a,requiredApprovers:Number(f.target.value)}}),style:{...qi,width:"50px"}})]}),S.jsxs("label",{style:{fontSize:"12px",color:"#888",display:"flex",gap:"4px",alignItems:"center"},children:[S.jsx("input",{type:"checkbox",checked:a.requireReason,onChange:f=>n("approval-gate",{approvalGate:{...a,requireReason:f.target.checked}})}),"Require reason on denial"]})]})}function U1({config:i,onUpdate:n}){var f;const a=((f=i.tasklist)==null?void 0:f.items)??[],[s,u]=re.useState(""),o=()=>{s&&(n("tasklist",{tasklist:{items:[...a,s]}}),u(""))};return S.jsxs("div",{style:Hs,children:[S.jsx("span",{style:Is,children:"Tasklist Items"}),a.map((h,m)=>S.jsxs("div",{style:{display:"flex",gap:"6px",alignItems:"center",fontSize:"12px"},children:[S.jsx("span",{style:{color:"#e0e0e0"},children:h}),S.jsx("button",{onClick:()=>n("tasklist",{tasklist:{items:a.filter((p,g)=>g!==m)}}),style:qu,children:"x"})]},m)),S.jsxs("div",{style:{display:"flex",gap:"6px"},children:[S.jsx("input",{placeholder:"New task item",value:s,onChange:h=>u(h.target.value),onKeyDown:h=>h.key==="Enter"&&o(),style:{...qi,flex:1}}),S.jsx("button",{onClick:o,style:Lu,children:"+ Add"})]})]})}function H1({config:i,onUpdate:n}){var f;const a=((f=i.table)==null?void 0:f.columns)??[],[s,u]=re.useState({key:"",header:""}),o=()=>{!s.key||!s.header||(n("table",{table:{columns:[...a,{...s}]}}),u({key:"",header:""}))};return S.jsxs("div",{style:Hs,children:[S.jsx("span",{style:Is,children:"Table Columns"}),a.map((h,m)=>S.jsxs("div",{style:{display:"flex",gap:"6px",alignItems:"center",fontSize:"12px"},children:[S.jsx("span",{style:{color:"#a5b4fc"},children:h.key}),S.jsxs("span",{style:{color:"#888"},children:['"',h.header,'"']}),S.jsx("button",{onClick:()=>n("table",{table:{columns:a.filter((p,g)=>g!==m)}}),style:qu,children:"x"})]},m)),S.jsxs("div",{style:{display:"flex",gap:"6px"},children:[S.jsx("input",{placeholder:"key",value:s.key,onChange:h=>u(m=>({...m,key:h.target.value})),style:{...qi,width:"80px"}}),S.jsx("input",{placeholder:"header",value:s.header,onChange:h=>u(m=>({...m,header:h.target.value})),style:{...qi,flex:1}}),S.jsx("button",{onClick:o,style:Lu,children:"+ Add"})]})]})}const Hs={display:"flex",flexDirection:"column",gap:"8px",padding:"10px",border:"1px solid #333",borderRadius:"6px",background:"#111"},Is={fontSize:"13px",fontWeight:600,color:"#a5b4fc",textTransform:"capitalize"},qi={padding:"4px 8px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#e0e0e0",fontSize:"12px",outline:"none"},Lu={padding:"4px 10px",border:"1px solid #6366f1",borderRadius:"4px",background:"#1e1b4b",color:"#a5b4fc",fontSize:"11px",cursor:"pointer",whiteSpace:"nowrap"},qu={border:"none",background:"none",color:"#666",cursor:"pointer",fontSize:"12px",padding:"0 2px"},I1={baseUrl:"http://localhost:11434/v1",apiKey:"",model:"llama3"},xu={openai:{label:"OpenAI",baseUrl:"https://api.openai.com/v1",apiKey:"",model:"gpt-4o",requiresKey:!0},anthropic:{label:"Anthropic",baseUrl:"https://api.anthropic.com/v1",apiKey:"",model:"claude-sonnet-4-5-20250929",requiresKey:!0},gemini:{label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta/openai",apiKey:"",model:"gemini-2.0-flash",requiresKey:!0},openrouter:{label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKey:"",model:"anthropic/claude-sonnet-4-5-20250929",requiresKey:!0},groq:{label:"Groq",baseUrl:"https://api.groq.com/openai/v1",apiKey:"",model:"llama-3.3-70b-versatile",requiresKey:!0},ollama:{label:"Ollama",baseUrl:"http://localhost:11434/v1",apiKey:"",model:"llama3",requiresKey:!1}};async function*jg(i,n,a){var p,g,b,_;const s=`${i.baseUrl.replace(/\/+$/,"")}/chat/completions`,u={"Content-Type":"application/json"};i.apiKey&&(u.Authorization=`Bearer ${i.apiKey}`);const o=await fetch(s,{method:"POST",headers:u,body:JSON.stringify({model:i.model,messages:n,stream:!0}),signal:a});if(!o.ok){const v=await o.text();throw new Error(`LLM API error ${o.status}: ${v}`)}const f=(p=o.body)==null?void 0:p.getReader();if(!f)throw new Error("No response body");const h=new TextDecoder;let m="";for(;;){const{done:v,value:N}=await f.read();if(v)break;m+=h.decode(N,{stream:!0});const w=m.split(` +`);m=w.pop()??"";for(const D of w){const C=D.trim();if(!C||!C.startsWith("data: "))continue;const H=C.slice(6);if(H==="[DONE]")return;try{const Q=(_=(b=(g=JSON.parse(H).choices)==null?void 0:g[0])==null?void 0:b.delta)==null?void 0:_.content;Q&&(yield Q)}catch{}}}}async function Rg(i,n,a){var h,m,p;const s=`${i.baseUrl.replace(/\/+$/,"")}/chat/completions`,u={"Content-Type":"application/json"};i.apiKey&&(u.Authorization=`Bearer ${i.apiKey}`);const o=await fetch(s,{method:"POST",headers:u,body:JSON.stringify({model:i.model,messages:n,stream:!1}),signal:a});if(!o.ok){const g=await o.text();throw new Error(`LLM API error ${o.status}: ${g}`)}return((p=(m=(h=(await o.json()).choices)==null?void 0:h[0])==null?void 0:m.message)==null?void 0:p.content)??""}const Bg="mdma-builder-api-keys";function Lg(){try{return JSON.parse(localStorage.getItem(Bg)||"{}")}catch{return{}}}function Y1(i,n){const a=Lg();a[i]=n,localStorage.setItem(Bg,JSON.stringify(a))}function V1(i){for(const[n,a]of Object.entries(xu))if(i===a.baseUrl)return n;return null}function G1({messages:i,isGenerating:n,error:a,onGenerate:s,onStop:u,onReset:o,config:f,onConfigChange:h}){const[m,p]=re.useState(""),[g,b]=re.useState(!1),_=re.useMemo(()=>V1(f.baseUrl),[f.baseUrl]),v=_?xu[_]:null,N=H=>{const M=xu[H],Q=Lg();h({baseUrl:M.baseUrl,model:M.model,apiKey:Q[H]||""})},w=H=>{h({...f,apiKey:H}),_&&Y1(_,H)},D=()=>{const H=m.trim();p(""),s(H||void 0)},C=!(v!=null&&v.requiresKey)||f.apiKey.length>0;return S.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%"},children:[S.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center",padding:"8px 0"},children:[S.jsx("button",{onClick:()=>b(H=>!H),style:qy,children:g?"Hide Settings":"Settings"}),S.jsxs("span",{style:{fontSize:"11px",color:"#666"},children:[(v==null?void 0:v.label)||"Custom"," / ",f.model]}),!C&&S.jsx("span",{style:{fontSize:"11px",color:"#f59e0b"},children:"API key required"}),S.jsx("div",{style:{flex:1}}),S.jsx("button",{onClick:o,style:qy,children:"Clear"})]}),g&&S.jsxs("div",{style:{padding:"12px",border:"1px solid #333",borderRadius:"8px",background:"#111",marginBottom:"8px",display:"flex",flexDirection:"column",gap:"10px"},children:[S.jsx("span",{style:{fontSize:"12px",color:"#888",fontWeight:500},children:"Provider"}),S.jsx("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap"},children:Object.entries(xu).map(([H,M])=>S.jsx("button",{onClick:()=>N(H),style:{...K1,..._===H?{borderColor:"#6366f1",color:"#a5b4fc",background:"#1e1b4b"}:{}},children:M.label},H))}),(v==null?void 0:v.requiresKey)&&S.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[S.jsxs("span",{style:{fontSize:"11px",color:"#888"},children:[v.label," API Key"]}),S.jsx("input",{placeholder:`Enter your ${v.label} API key...`,type:"password",value:f.apiKey,onChange:H=>w(H.target.value),style:{...xf,borderColor:f.apiKey?"#22c55e33":"#f59e0b33"}}),f.apiKey&&S.jsxs("span",{style:{fontSize:"10px",color:"#22c55e"},children:["Key saved for ",v.label]})]}),S.jsxs("div",{style:{display:"flex",gap:"8px"},children:[S.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:"4px"},children:[S.jsx("span",{style:{fontSize:"11px",color:"#888"},children:"Model"}),S.jsx("input",{placeholder:"Model",value:f.model,onChange:H=>h({...f,model:H.target.value}),style:xf})]}),S.jsxs("div",{style:{flex:2,display:"flex",flexDirection:"column",gap:"4px"},children:[S.jsx("span",{style:{fontSize:"11px",color:"#888"},children:"Base URL"}),S.jsx("input",{placeholder:"Base URL",value:f.baseUrl,onChange:H=>h({...f,baseUrl:H.target.value}),style:xf})]})]})]}),S.jsxs("div",{style:{flex:1,overflowY:"auto",display:"flex",flexDirection:"column",gap:"8px",padding:"4px 0"},children:[i.length===0&&!n&&S.jsx("div",{style:{color:"#555",fontSize:"13px",textAlign:"center",padding:"40px 20px"},children:C?S.jsxs(S.Fragment,{children:["Configure components on the left, then click ",S.jsx("strong",{children:"Generate"}),"."]}):S.jsxs(S.Fragment,{children:["Set your ",S.jsx("strong",{children:(v==null?void 0:v.label)||"LLM"})," API key in Settings above to get started."]})}),i.filter(H=>H.role!=="system").map((H,M)=>S.jsx("div",{style:{padding:"8px 12px",borderRadius:"8px",fontSize:"13px",lineHeight:1.5,background:H.role==="user"?"#1e1b4b":"#1a1a1a",color:H.role==="user"?"#c7d2fe":"#e0e0e0",alignSelf:H.role==="user"?"flex-end":"flex-start",maxWidth:"90%",whiteSpace:"pre-wrap"},children:H.content},M)),n&&S.jsx("div",{style:{fontSize:"12px",color:"#6366f1",padding:"4px"},children:"Generating..."}),a&&S.jsx("div",{style:{fontSize:"12px",color:"#ef4444",padding:"4px"},children:a})]}),S.jsxs("div",{style:{display:"flex",gap:"8px",paddingTop:"8px",borderTop:"1px solid #222"},children:[S.jsx("textarea",{value:m,onChange:H=>p(H.target.value),onKeyDown:H=>{H.key==="Enter"&&!H.shiftKey&&(H.preventDefault(),!n&&C&&D())},placeholder:i.length===0?"Click Generate or type to refine...":"Refine the prompt...",rows:2,disabled:!C,style:{flex:1,padding:"8px 10px",border:"1px solid #333",borderRadius:"6px",background:"#1a1a1a",color:"#e0e0e0",fontSize:"13px",fontFamily:"inherit",resize:"none",outline:"none",opacity:C?1:.5}}),n?S.jsx("button",{onClick:u,style:{...Uy,background:"#7f1d1d",borderColor:"#ef4444"},children:"Stop"}):S.jsx("button",{type:"button",onClick:D,disabled:!C,style:{...Uy,opacity:C?1:.5},children:i.length===0?"Generate":"Send"})]})]})}const qy={border:"none",background:"none",color:"#6366f1",cursor:"pointer",fontSize:"12px",padding:0},K1={padding:"6px 12px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#888",fontSize:"12px",cursor:"pointer",fontWeight:500},xf={padding:"6px 8px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#e0e0e0",fontSize:"12px",outline:"none"},Uy={padding:"8px 16px",border:"1px solid #6366f1",borderRadius:"6px",background:"#1e1b4b",color:"#a5b4fc",fontSize:"13px",fontWeight:600,cursor:"pointer",alignSelf:"flex-end"};function Z1({prompt:i,isGenerating:n}){const[a,s]=re.useState(!1),u=async()=>{await navigator.clipboard.writeText(i),s(!0),setTimeout(()=>s(!1),2e3)},o=()=>{const f=new Blob([i],{type:"text/plain"}),h=URL.createObjectURL(f),m=document.createElement("a");m.href=h,m.download="mdma-custom-prompt.txt",m.click(),URL.revokeObjectURL(h)};return!i&&!n?S.jsx("div",{style:Hy,children:S.jsxs("div",{style:{color:"#666",fontSize:"13px",textAlign:"center",padding:"40px 20px"},children:[S.jsxs("p",{style:{marginBottom:"8px"},children:["Configure your components and click ",S.jsx("strong",{children:"Generate"}),"."]}),S.jsxs("p",{style:{fontSize:"11px"},children:["The generated prompt will be used with:",S.jsx("br",{}),S.jsxs("code",{style:{color:"#a5b4fc"},children:["buildSystemPrompt(","{ customPrompt }",")"]})]})]})}):S.jsxs("div",{style:Hy,children:[S.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"},children:[S.jsx("h3",{style:{margin:0,fontSize:"14px",fontWeight:600,color:"#e0e0e0"},children:"Generated Prompt"}),S.jsxs("div",{style:{display:"flex",gap:"6px"},children:[S.jsx("button",{onClick:u,style:Iy,disabled:!i,children:a?"Copied!":"Copy"}),S.jsx("button",{onClick:o,style:Iy,disabled:!i,children:"Save"})]})]}),S.jsxs("pre",{style:{flex:1,overflowY:"auto",padding:"12px",border:"1px solid #333",borderRadius:"6px",background:"#0a0a0a",color:"#d4d4d4",fontSize:"12px",lineHeight:1.6,whiteSpace:"pre-wrap",wordBreak:"break-word",margin:0},children:[i,n&&S.jsx("span",{style:{color:"#6366f1"},children:"|"})]}),i&&S.jsxs("div",{style:{marginTop:"10px",padding:"10px",border:"1px solid #1e1b4b",borderRadius:"6px",background:"#0f0e26"},children:[S.jsx("p",{style:{margin:0,fontSize:"11px",color:"#888"},children:"Usage in your app:"}),S.jsxs("code",{style:{fontSize:"12px",color:"#a5b4fc"},children:["import { buildSystemPrompt } from '@mobile-reality/mdma-prompt-pack';",S.jsx("br",{}),S.jsx("br",{}),"const systemPrompt = buildSystemPrompt({",S.jsx("br",{})," customPrompt: ``",S.jsx("br",{}),"});"]})]})]})}const Hy={display:"flex",flexDirection:"column",height:"100%"},Iy={padding:"4px 12px",border:"1px solid #333",borderRadius:"4px",background:"#1a1a1a",color:"#e0e0e0",fontSize:"11px",cursor:"pointer"},Yy=`You are an expert MDMA document author. MDMA (Markdown Document with Micro-Applications) extends standard Markdown with interactive components defined in fenced code blocks using the \`mdma\` language tag. Think before you generate content, and ensure it adheres to the MDMA format and authoring rules. + +CRITICAL: Your output IS the Markdown document — write headings, paragraphs, and \`\`\`mdma blocks directly. NEVER wrap your response in \`\`\`markdown code fences. Your response is already rendered as Markdown. + +## Document Format + +An MDMA document is a standard Markdown file that contains one or more interactive component blocks. Each component block is a YAML snippet inside a fenced code block tagged with \`mdma\`. Here is an example of what your output should look like — note there are NO outer \`\`\`markdown fences: + +# My Document Title + +Some regular Markdown content here. + +\`\`\`mdma +type: form +id: contact-form +fields: + - name: email + type: email + label: Email Address + required: true +\`\`\` + +More Markdown content can follow. + +## Component Types + +MDMA supports 9 component types. Every component shares these base fields: + +- **id** (string, required) — Unique identifier within the document +- **type** (string, required) — Component type name +- **label** (string, optional) — Display label +- **sensitive** (boolean, default: false) — If true, values are redacted in logs +- **disabled** (boolean | binding, default: false) +- **visible** (boolean | binding, default: true) +- **meta** (object, optional) — Arbitrary metadata + +### 1. form + +Collects user input via structured fields. + +\`\`\`yaml +type: form +id: +fields: + - name: # required, string + type: text | number | email | date | select | checkbox | textarea + label: # required, string + required: true | false # default: false + sensitive: true | false # default: false — set true for PII + defaultValue: # optional + options: # required when type is "select" + - label: