@clipform/mcp-server 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-JID43EDM.js → chunk-2AJMWM5W.js} +67 -4
- package/dist/chunk-2AJMWM5W.js.map +1 -0
- package/dist/{chunk-JOJJ2XFL.js → chunk-6MLZZSNM.js} +61 -3
- package/dist/{chunk-JOJJ2XFL.js.map → chunk-6MLZZSNM.js.map} +1 -1
- package/dist/{chunk-KWEBCAPF.js → chunk-BYJMRIB6.js} +10 -4
- package/dist/chunk-BYJMRIB6.js.map +1 -0
- package/dist/{chunk-ZVHI2V7B.js → chunk-CN4XBVFD.js} +133 -108
- package/dist/{chunk-ZVHI2V7B.js.map → chunk-CN4XBVFD.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/prompts.js +2 -2
- package/dist/resources.js +2 -2
- package/dist/server.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-JID43EDM.js.map +0 -1
- package/dist/chunk-KWEBCAPF.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
JSONRPCMessageSchema,
|
|
4
4
|
createServer
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-CN4XBVFD.js";
|
|
6
|
+
import "./chunk-6MLZZSNM.js";
|
|
7
|
+
import "./chunk-2AJMWM5W.js";
|
|
8
8
|
import {
|
|
9
9
|
setMcpVersion
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BYJMRIB6.js";
|
|
11
11
|
import "./chunk-HCZI2UJ5.js";
|
|
12
12
|
|
|
13
13
|
// src/index.ts
|
package/dist/prompts.js
CHANGED
package/dist/resources.js
CHANGED
package/dist/server.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-CN4XBVFD.js";
|
|
4
|
+
import "./chunk-6MLZZSNM.js";
|
|
5
|
+
import "./chunk-2AJMWM5W.js";
|
|
6
|
+
import "./chunk-BYJMRIB6.js";
|
|
7
7
|
import "./chunk-HCZI2UJ5.js";
|
|
8
8
|
export {
|
|
9
9
|
createServer
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resources.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getSessionContext } from \"./lib/session-context.js\";\nimport { FORM_TYPE_KEYS, FORM_TYPES, ALL_VARIANTS } from \"@vid-master/config\";\n\nexport const GUIDE_TYPES = FORM_TYPE_KEYS as readonly string[] as readonly [string, ...string[]];\nexport type GuideType = (typeof FORM_TYPE_KEYS)[number];\n\nexport const QUIZ_VARIANTS = ALL_VARIANTS as readonly string[] as readonly [string, ...string[]];\nexport type QuizVariant = (typeof ALL_VARIANTS)[number];\n\nconst WRITING_PRINCIPLES = `## Writing Principles\n\n- **Write for the ear.** Narration is spoken aloud. Short sentences. Natural rhythm.\n- **Research before writing.** Find 2-3 genuinely interesting facts per topic. Generic content doesn't hold attention.\n- **Conversational, not encyclopaedic.** \"Here's what's wild about this...\" not \"The subject is characterized by...\"\n- **Cut ruthlessly.** Every word must earn its place.\n- **Never reveal answers in narration.** The user picks from options - narration teases and builds intrigue.\n- **Don't read answer options aloud.** The viewer can see them on screen.\n\n## Narration Tips\n\n- Tease the topic, don't summarise it\n- Give one interesting fact that makes the user curious\n- 5-15 seconds per question narration\n- If TTS comes back too long, trim the copy and regenerate\n\n## Research\n\nSearch for the specific subject, not generic terms (\"komodo dragon habitat\" not \"reptile\"). Cross-reference facts - quiz answers must be correct. Look for the surprising angle: what would make someone say \"wait, really?\"\n\nFor timeless topics (history, geography, science), write from your own knowledge. For anything recent or uncertain, use web search or clipform_search_news. If neither is available, refuse rather than fabricate.`;\n\nconst MEDIA_WORKFLOW = `## Media Workflow\n\n1. **clipform_generate_tts** - narration audio (returns word-level captions) - batch ALL items in one call\n2. **clipform_search_media** (kind: \"image\") - find 3 images per question - batch ALL queries in one call\n3. **clipform_generate_video** - Ken Burns video from images + audio. Rendering more than one video? Pass wait: false on EVERY call (each returns a job ID immediately, renders run in parallel), then collect URLs with clipform_check_render.\n4. **clipform_upload_node_media** - attach video with captions (set show_captions: true) - batch all uploads in one call\n\n**Image selection:**\n- ONLY use URLs from clipform_search_media results\n- ALL returned images are pre-cleared for commercial use - pick by visual quality, not by provider or license\n- **Question media must not accidentally reveal the answer.** Unless the media IS the clue (emoji quiz, guess-the-flag - then choose it deliberately for difficulty), search the question's category or scene-setting context, not the answer. Answer-specific media belongs on the reveal. Test: could someone who knows nothing pick the right option just from the media?\n- For non-question media (intros, reveals, surveys), search the specific subject, not generic terms\n- Pick visually distinct images (different angles, colors, subjects) - use each result's description/alt text to judge\n- Portrait images fill the 9:16 frame best and results come portrait-first by default; landscape images get automatic blur-pad framing. Request orientation: \"landscape\" only when you specifically want wide shots.\n\n**Slideshow defaults:**\n- 3 images per question, random_effects: true\n- transition: { type: \"fade\", duration: 1 }\n- Auto focal point detection, eased motion, and cinematic vignette are built in`;\n\nconst GUIDE_DESCRIPTIONS: Record<GuideType, string> = {\n \"quiz\": \"Craft knowledge for writing engaging quizzes - difficulty curves, question psychology, narration style, scoring\",\n \"survey\": \"Craft knowledge for feedback surveys, NPS, and research forms - brevity, rating scales, respondent fatigue\",\n \"interview\": \"Craft knowledge for building interview forms - warm-up pacing, open questions, consent, video responses\",\n \"funnel\": \"Craft knowledge for lead qualification funnels - planned feature, conditional routing coming soon\",\n \"testimonial\": \"Craft knowledge for collecting testimonials and customer stories on video - storytelling prompts, comfort techniques, consent\",\n \"application\": \"Craft knowledge for application and evaluation forms - multi-section structure, video responses for behavioural questions, screening\",\n \"booking\": \"Craft knowledge for event registration and booking forms - minimal friction, video welcome, confirmation flow\",\n};\n\nconst QUIZ_VARIANT_DESCRIPTIONS: Record<QuizVariant, string> = {\n \"personality\": \"Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers\",\n \"comprehension\": \"Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation\",\n};\n\nconst GUIDE_CONTENT: Record<GuideType, string> = {\n \"quiz\": `# Quiz Writing Guide\n\n## Psychology\n\nEach question is a micro variable-reward event - the same dopamine loop that keeps people watching. Once someone answers 2-3 questions, sunk cost kicks in and they finish. Viewers mentally compete, then want to compare scores.\n\n**Target 50-60% correct.** Too easy = no challenge. Too hard = people feel stupid and won't share.\n\n## Difficulty Curve\n\n| Position | Difficulty | Purpose |\n|----------|-----------|---------|\n| Q1-Q2 | Easy (80%+ get right) | Build confidence and commitment |\n| Q3-Q5 | Medium | Peak engagement |\n| Q6-Q8 | Hard (include one \"gotcha\") | The \"everyone gets this wrong\" moment |\n| Q9-Q10 | One hard, one satisfying medium | End on a smart feeling, not defeat |\n\n## Question Design\n\n- **No guessable answer pattern** - set randomise_options: true and the viewer shuffles options at render time. Do NOT hand-vary correct answer positions; it has no effect once options shuffle.\n- **Myth-busters**: \"Sushi means raw fish - True or False?\" (False - it means seasoned rice)\n- **Sounds fake but true**: counterintuitive correct answers make people rewatch\n- **Common misconceptions**: \"Capital of Australia?\" (not Sydney - Canberra)\n- Under 12-15 words per question for mobile readability\n- Trigger gut reactions, not deep thinking\n\n## Wrong Answer Generation\n\nFor numeric questions (population, speed, weight), scale the real answer by random multipliers (0.3x to 3x) rounded to the same magnitude. Makes wrong answers plausible but clearly different.\n\n## Color Brain Questions (ColorCards composition)\n\nInspired by the Color Brain board game - every answer is identified by its colours. Show flat colour chips, ask \"what has these colours?\". Use the \\`ColorCards\\` composition for the question card.\n\n**Colour palette constraint:** Swatches are solid flat chips. Only use clearly distinguishable basic colours: red, blue, green, yellow, white, black, orange, purple, pink, brown, grey. No navy vs blue, no teal vs cyan - they look the same as flat chips. The skill is picking subjects where a combo of basic colours is unique enough to identify.\n\n**Question categories:**\n- Flags: \"Which country's flag has these colours?\" (pair with FlagReveal for answer)\n- Brand logos: red + yellow = McDonald's, red + white = Coca-Cola\n- Sports teams: red + white = Arsenal, red + blue + white = Barcelona\n- Superheroes/characters: red + blue = Spider-Man, yellow + black = Batman\n- Food: red + green = watermelon, yellow + brown = banana\n\n**Difficulty scaling:**\n- Easy: iconic subjects with unique colour combos (Japan flag: red + white)\n- Medium: common subjects but colours shared with others (Italy vs Ireland: both green + white + one more)\n- Hard: obscure subjects or very common colour combos that fit many answers\n\n**Design rules:**\n- 2-4 colours per question works best. 5+ gets messy and hard to distinguish.\n- If two answer options would produce identical swatches, don't use that question.\n- Pair with a reveal composition (FlagReveal, image, or text) for the answer.\n\n## Settings\n\n- show_step_counter: true\n- disable_back_navigation: true (prevent going back to change answers after seeing feedback)\n\n## Narration Style\n\nYou're a quiz master, not a question reader. Each question's narration should:\n\n1. **Tease** - set the scene, build intrigue (\"This one catches everyone out\")\n2. **Give context** - one interesting fact that makes the question richer\n3. **Pose the question** - \"So here's the question...\"\n\n**Don't say:**\n- \"You either know it or you don't\" (meaningless filler)\n- \"This is a really hard one\" on every question (loses impact)\n- \"Welcome to my quiz\" / \"Hey guys\" (wastes time, skip to Q1)\n\n${WRITING_PRINCIPLES}\n\n${MEDIA_WORKFLOW}`,\n\n \"survey\": `# Survey & Feedback Guide\n\n## Purpose\n\nCollect structured feedback - NPS, customer satisfaction, product research, post-event feedback. The goal is clean, analysable data with minimal respondent fatigue.\n\n## Structure\n\nSurveys should be ruthlessly short. Every extra question costs you completions.\n\n1. **Key metric** - the one number you care about (NPS, satisfaction rating, likelihood to recommend). Put it first while attention is highest.\n2. **Follow-up** - one open-ended \"why?\" question. \"What's the main reason for your score?\" This is where the insight lives.\n3. **Specific questions** (optional) - 2-3 targeted choice questions on specific areas. Don't fish - only ask what you'll act on.\n4. **Contact** (optional) - only if you need to follow up. Many surveys are better anonymous.\n5. **End screen** - \"Thanks for your feedback!\" Keep it simple.\n\n## Question Design\n\n- **Choice questions for data, open questions for insight.** Don't use open-ended where a rating scale would do, and don't use ratings where you need to understand why.\n- **Balanced scales.** Equal positive and negative options. \"Excellent / Good / Fair / Poor\" not \"Amazing / Great / Good / OK / Bad.\"\n- **No leading questions.** \"How much did you enjoy...?\" assumes they enjoyed it.\n- **5 questions max.** If you need more, you're running research, not a survey - split it up.\n\n## Narration for Surveys\n\nOptional - many surveys work fine as text only. If using narration:\n\n- Keep it brief (5-8 seconds). \"We'd love your quick feedback on...\"\n- Don't narrate every question - just the opener to set the tone\n- Friendly but efficient. Respect their time.\n\n## Settings\n\n- disable_back_navigation: false\n- show_step_counter: true (shows progress, reduces abandonment)\n\n${WRITING_PRINCIPLES}`,\n\n \"interview\": `# Interview Guide\n\n## Purpose\n\nCollect responses through structured conversations - journalist callouts, async video interviews, expert input, case study interviews. You're guiding someone through questions, with their answers as structured data or video responses.\n\n## Structure\n\n1. **Warm-up question** - something easy and low-stakes to get them comfortable. \"Tell us your name and what you do\" or \"What's your role?\"\n2. **Core questions** - the real ask. Open-ended, one topic per question. Don't over-split - 2-3 core questions max.\n3. **Follow-up** (optional) - \"Anything else you'd like to add?\" catches things you didn't think to ask.\n4. **Contact collection** - first name + email minimum. Add phone/company if relevant.\n5. **Consent** - \"I agree that my response may be used in [context].\" Always include for media use.\n6. **End screen** - set expectations: \"Thanks! We'll be in touch if we'd like to take things further.\"\n\n## Question Design\n\n- **Open-ended by default.** Use \"open\" type with text + audio + video response enabled. Let the respondent choose their format.\n- **One topic per question.** \"Tell us about your experience AND what you'd change\" is two questions.\n- **Prompt, don't interrogate.** \"What surprised you most about working with us?\" beats \"Rate your satisfaction.\"\n- **Keep it short.** 3-5 questions total. Every extra question loses respondents.\n\n## Narration for Interviews\n\nWarmer and more personal than quiz narration. You're inviting someone to share, not testing them.\n\n- \"We'd love to hear your perspective...\"\n- \"Take your time with this one - there's no wrong answer\"\n- Keep narration under 10 seconds - the respondent's answer is the content, not yours\n\n## Settings\n\n- disable_back_navigation: false (let people review their answers)\n- show_step_counter: true (so they know how much is left)\n\n${WRITING_PRINCIPLES}\n\n${MEDIA_WORKFLOW}`,\n\n \"funnel\": `# Lead Qualification Funnel - Coming Soon\n\nFunnel capabilities with conditional routing and branching logic are planned but not yet available. This guide will be expanded when the branching feature launches.\n\nIn the meantime, you can build a simple linear qualification form using the survey or quiz workflows.`,\n\n \"testimonial\": `# Testimonial & Story Collection Guide\n\n## Purpose\n\nCapture authentic stories from customers, users, or participants on camera. The respondent's video IS the deliverable - you're producing content, not collecting data. The questions are storytelling prompts designed to elicit a compelling narrative arc.\n\n## Storytelling Arc\n\nThe best testimonials follow a three-part structure. Each prompt maps to one part:\n\n1. **Before** - \"What was your situation before?\" (establishes the problem)\n2. **During** - \"What was the experience like?\" (the journey)\n3. **After** - \"What's different now?\" (the transformation/result)\n\nThis gives you a complete story you can edit into marketing content.\n\n## Prompt Design\n\n- **Open-ended, video-first.** Every core question should be type \"open\" with video response enabled.\n- **One idea per prompt.** \"Tell us about your experience and what you'd recommend\" is two prompts.\n- **Warm and specific.** \"What surprised you most about working with us?\" beats \"Tell us about your experience.\"\n- **3-5 prompts max.** Fewer = higher completion. The best testimonials come from 3 focused questions.\n- **Don't ask for ratings.** This isn't a survey. You want stories, not numbers.\n\n## Making Respondents Comfortable\n\n- Start with something easy: name, role, how long they've been a customer\n- Narration should feel like a friendly conversation, not a formal interview\n- \"Take your time - there's no rush and no wrong answer\"\n- Keep narration under 8 seconds per prompt - the respondent's answer is the content\n\n## Consent\n\nAlways include a consent node for testimonials. The response will be used in marketing, on your website, or in sales materials. Be explicit about where it may appear.\n\n## Settings\n\n- disable_back_navigation: false (let people re-record if they weren't happy)\n- show_step_counter: true (shows progress, reduces surprise)\n\n## Narration Style\n\nWarm, appreciative, and encouraging:\n- \"We'd love to hear your story...\"\n- \"What you share will help others just like you\"\n- \"There's no script - just speak from the heart\"\n\nDo NOT say \"this will only take a minute\" (it won't) or \"just a quick video\" (undermines the ask).\n\n${WRITING_PRINCIPLES}\n\n${MEDIA_WORKFLOW}`,\n\n \"application\": `# Application & Evaluation Guide\n\n## Purpose\n\nCollect structured applications - job applications, programme admissions, grant proposals, course enrolments. Applications mix structured data (contact, qualifications) with open-ended responses (motivation, experience). Video responses reveal personality and communication skills that text can't capture.\n\n## Structure\n\nApplications have a natural multi-section flow:\n\n1. **Identity** - name, email, phone. Get this first while motivation is highest.\n2. **Qualifications** - role-specific structured questions (experience level, skills, availability). Choice or short text.\n3. **Open responses** - \"Tell us about a time when...\" or \"Why are you interested?\" Video encouraged for behavioural questions.\n4. **Supporting material** (optional) - \"Anything else you'd like to share?\"\n5. **Confirmation** - clear next steps. \"We'll review your application and get back to you within X days.\"\n\n## Question Design\n\n- **Structured for screening, open for depth.** Use choice questions to filter (experience level, availability), open questions to understand (motivation, fit).\n- **Video for behavioural questions.** \"Walk us through how you'd approach...\" is far more revealing on video than in text.\n- **One question per screen.** Applications feel long - keep each step focused.\n- **8-10 questions max.** Even for detailed applications. Every extra question increases abandonment.\n- **Don't duplicate the CV.** Ask for what a resume doesn't show: motivation, culture fit, communication style.\n\n## Narration for Applications\n\nProfessional and welcoming. You're the organisation's first impression.\n\n- \"Thanks for your interest - let's get to know you\"\n- \"Take your time with this one\"\n- Keep narration factual and brief - applicants want to know what's expected, not be entertained\n\n## Settings\n\n- disable_back_navigation: false (applicants need to review and revise)\n- show_step_counter: true (essential - applicants need to know how much is left)\n\n${WRITING_PRINCIPLES}\n\n${MEDIA_WORKFLOW}`,\n\n \"booking\": `# Booking & Registration Guide\n\n## Purpose\n\nEvent registration, course signup, workshop booking, consultation scheduling. The goal is minimal friction to confirmed attendance. Video makes registrations feel personal - a welcome video from the host builds anticipation and reduces no-shows.\n\n## Structure\n\nRegistrations should be fast. Every field you add costs completions.\n\n1. **Welcome** - a short video or narrated intro that sells the event and sets expectations. This is where video adds the most value.\n2. **Essential info** - name, email. Absolute minimum.\n3. **Event-specific details** (if needed) - dietary requirements, session preferences, t-shirt size. Only ask what you'll actually use.\n4. **Confirmation** - \"You're registered! Here's what to expect.\" Include date, time, location/link.\n\n## Question Design\n\n- **3-5 fields maximum.** Name + email + 1-3 event-specific fields. That's it.\n- **Choice questions over open-ended.** \"Which session interests you most?\" not \"What are you hoping to learn?\" You need structured data for logistics.\n- **Contact is mandatory.** This isn't anonymous - you need to confirm their spot.\n- **Don't over-collect.** Phone number, company, job title - only if you genuinely need them for the event.\n\n## Video Welcome\n\nThe registration's killer feature. A 15-30 second video from the host:\n- Who you are and what the event is about\n- What attendees will get out of it\n- Why you're excited about it\n\nThis turns a boring form into a personal invitation. Completion rates go up when people feel welcomed.\n\n## Narration Style\n\nEnthusiastic but efficient. Respect their time.\n- \"We're excited to have you!\"\n- \"Just a few quick details and you're in\"\n- Keep total narration under 20 seconds across the whole form (excluding the welcome video)\n\n## Settings\n\n- disable_back_navigation: false\n- show_step_counter: false (it's so short, a counter adds unnecessary UI)\n\n${WRITING_PRINCIPLES}`,\n};\n\nconst QUIZ_VARIANT_ADDONS: Record<QuizVariant, string> = {\n \"personality\": `---\n\n# Personality Quiz Addendum\n\n> The following sections supplement the base quiz guide above. For personality quizzes, scoring works differently (categories, not right/wrong) and there is no answer feedback. Where guidance below conflicts with the base (e.g., narration style), follow the personality-specific version.\n\n## How Personality Quizzes Work\n\nPersonality quizzes have NO correct answers. Each option should feel equally valid and appealing. The experience is about self-expression and fun, not testing knowledge. Always set show_answer_feedback: false.\n\n**NOTE:** Full category-based scoring (where each option maps to outcome categories via the \\`scores\\` field and the winning category determines a personalised result screen) is coming soon. For now, design personality quizzes as engaging choice-based forms with a single end screen. The questions themselves are the experience.\n\n## Category Design (Conceptual)\n\nEven without automated scoring, design your questions around 3-5 outcome categories:\n\n- **3-5 categories** is the sweet spot. Fewer feels too binary, more feels random.\n- Categories should be **distinct but equally appealing**. Nobody wants to get the \"bad\" result.\n- Name them after the outcome, not the trait: \"Explorer\" not \"Adventurous\", \"The Architect\" not \"Organised\".\n- Use categories to guide question and option design, even though automated scoring is not yet available.\n\n## Personality Question Design\n\n- Questions should feel **personally revealing** but low-stakes: \"Pick your ideal Saturday morning\" not \"What's your biggest weakness?\"\n- Scenario-based questions work better than abstract preference questions\n- Each question should meaningfully differentiate between categories\n- Avoid questions where all options clearly map to one obvious personality\n\n## End Screen\n\nWrite a single end screen that feels personal and shareable:\n\n- **Title**: Something warm and inviting, like \"Thanks for playing!\" or \"That was fun!\"\n- **Message**: Encourage sharing - \"Compare your answers with friends!\" Personality quizzes are inherently social.\n- show_score: false (there is no score to show)\n- show_share_button: true (personality results are inherently shareable)\n- NOTE: Automated result screens per category (scoring_results) are coming soon.\n\n## Personality Narration Style\n\nReflective and curious, not quizmaster-y:\n- \"This one says a lot about you...\"\n- \"There's no wrong answer here - go with your gut\"\n- \"What does your choice reveal?\"\n\nDo NOT say \"let's see if you get this right\" - there is no right answer.`,\n\n \"comprehension\": `---\n\n# Comprehension Quiz Addendum\n\n> The following sections supplement the base quiz guide above. Comprehension quizzes test whether someone watched a specific piece of content, not general knowledge. Scoring and settings match the base quiz, but question sourcing and distractor design are completely different.\n\n## How Comprehension Differs from Trivia\n\nA trivia quiz tests general knowledge. A comprehension quiz tests whether someone watched a specific piece of content. The questions should be **unfair to non-watchers and fair to watchers**.\n\n| | Trivia Quiz | Comprehension Quiz |\n|---|---|---|\n| Source | Research + your knowledge | The video transcript |\n| Questions | General facts | Specific claims from the video |\n| Wrong answers | Common misconceptions | Things you'd guess without watching |\n| Goal | Entertainment + learning | Proof of watching + retention |\n\n## Extracting Questions from Transcripts\n\nRead the transcript looking for:\n\n1. **Specific numbers or data** - \"The presenter says it takes X days to...\" (detail recall)\n2. **Causal claims** - \"According to the video, this happens because...\" (comprehension)\n3. **Examples used** - \"What example does the presenter use to explain...?\" (attention)\n4. **Sequence of topics** - \"What does the presenter discuss right after...?\" (structure following)\n5. **The main argument** - \"What is the presenter's main point about...?\" (thesis comprehension)\n6. **Counterintuitive points** - anything the presenter says is surprising or commonly misunderstood\n\n## Distractor Design (Wrong Answers)\n\nMake wrong answers plausible to someone who **didn't watch**:\n\n- Use correct facts from other sources about the same topic (tests whether they watched THIS video)\n- Include things that sound likely based on the title alone\n- For number questions, use nearby values that seem reasonable\n- Never include obviously joke answers - every option should feel possible\n\n## Audience Adaptation\n\n| Audience | Question style | Language | Count |\n|----------|---------------|----------|-------|\n| Young children (5-8) | Concrete details, visual moments | Simple, short sentences | 4-6 |\n| Older children (9-12) | Details + basic inference | Clear, direct | 6-8 |\n| Teens (13-17) | Inference + sequence + argument | Natural, conversational | 6-10 |\n| Adults | Full range including critical analysis | Match the video's register | 6-10 |\n\nFor young children: focus on \"What did you SEE?\" and \"Who did what?\" rather than abstract arguments.\n\n## Comprehension Narration Style\n\nReference the video naturally but don't spoil:\n\n- \"If you were paying attention during the bit about...\"\n- \"This is one of those details most people miss...\"\n- \"The presenter made a really specific claim here...\"`,\n};\n\nexport function getGuideContent(type: GuideType, variant?: QuizVariant): string {\n const base = GUIDE_CONTENT[type];\n if (type === \"quiz\" && variant) {\n return base + \"\\n\\n\" + QUIZ_VARIANT_ADDONS[variant];\n }\n return base;\n}\n\nexport function getGuideUri(type: GuideType, variant?: QuizVariant): string {\n if (type === \"quiz\" && variant) {\n return `clipform://guides/quiz/${variant}`;\n }\n return `clipform://guides/${type}`;\n}\n\nexport function registerResources(server: McpServer) {\n for (const type of GUIDE_TYPES) {\n server.registerResource(\n `guide-${type}`,\n getGuideUri(type),\n {\n description: GUIDE_DESCRIPTIONS[type],\n mimeType: \"text/markdown\",\n annotations: { audience: [\"assistant\" as const], priority: 0.8 },\n },\n async () => ({\n contents: [{\n uri: getGuideUri(type),\n mimeType: \"text/markdown\",\n text: getGuideContent(type),\n }],\n }),\n );\n }\n\n for (const variant of QUIZ_VARIANTS) {\n server.registerResource(\n `guide-quiz-${variant}`,\n getGuideUri(\"quiz\", variant),\n {\n description: QUIZ_VARIANT_DESCRIPTIONS[variant],\n mimeType: \"text/markdown\",\n annotations: { audience: [\"assistant\" as const], priority: 0.8 },\n },\n async () => ({\n contents: [{\n uri: getGuideUri(\"quiz\", variant),\n mimeType: \"text/markdown\",\n text: getGuideContent(\"quiz\", variant),\n }],\n }),\n );\n }\n\n server.registerResource(\n \"context-session\",\n \"clipform://context/session\",\n {\n description:\n \"Current session info: auth mode, workspace, plan tier, node limits, feature flags. Read this before planning content to know your constraints.\",\n mimeType: \"text/markdown\",\n annotations: { audience: [\"assistant\"], priority: 1.0 },\n },\n async () => {\n const text = await getSessionContext();\n return {\n contents: [\n {\n uri: \"clipform://context/session\",\n mimeType: \"text/markdown\",\n text: text || \"Session context unavailable - API may not be reachable.\",\n },\n ],\n };\n }\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../config/form-types.js","../../config/features.js","../../config/help-links.js","../../config/node-types.js","../../config/integration-catalog.js","../../config/index.js","../src/lib/telemetry.ts","../src/lib/api-client.ts","../src/lib/session-context.ts"],"sourcesContent":["// @vid-master/config/form-types\n// Static form type definitions — single source of truth for all apps.\n// Workflow prose (step-by-step instructions) and craft guides remain in the\n// MCP server. This registry defines structural metadata only.\n\nexport const FORM_TYPES = {\n quiz: {\n label: 'Quiz',\n description: 'Scored knowledge quiz with narrated video questions',\n is_active: true,\n sort_order: 1,\n category: 'assessment',\n aliases: ['trivia', 'test', 'exam'],\n variants: ['personality', 'comprehension'],\n required_features: [],\n required_node_types: ['choice', 'end_screen'],\n default_media_style: 'video',\n guide_uri: 'clipform://guides/quiz',\n guide_description: 'Craft knowledge for writing engaging quizzes - difficulty curves, question psychology, narration style, scoring',\n discovery: [\n { key: 'topic', question: 'What topic or subject area?', fallback: 'General trivia', mode: 'all' },\n { key: 'question_count', question: 'How many questions?', fallback: '8', mode: 'all' },\n { key: 'media_style', question: 'Video with narration (recommended), images, or text only?', fallback: 'Video with narration', mode: 'full' },\n ],\n variant_discovery: {\n personality: [\n { key: 'topic', question: \"What's the theme? (Which X are you?)\", fallback: 'General personality', mode: 'all' },\n { key: 'categories', question: 'What outcome categories? (3-5 results)', fallback: 'Infer 4 categories from the theme', mode: 'full' },\n { key: 'question_count', question: 'How many questions?', fallback: '8', mode: 'all' },\n ],\n comprehension: [\n { key: 'youtube_url', question: \"What's the YouTube URL?\", fallback: 'REQUIRED - cannot proceed without it', mode: 'all' },\n { key: 'question_count', question: 'How many questions?', fallback: '8', mode: 'all' },\n { key: 'audience', question: \"Who's the audience? (kids, teens, adults)\", fallback: 'General adults', mode: 'full' },\n ],\n },\n variant_guide_uris: {\n personality: 'clipform://guides/quiz/personality',\n comprehension: 'clipform://guides/quiz/comprehension',\n },\n variant_descriptions: {\n personality: 'Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers',\n comprehension: 'Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation',\n },\n prompt: { name: 'create-quiz', title: 'Create a Quiz', description: 'Build a scored knowledge quiz with narrated video questions' },\n },\n\n survey: {\n label: 'Survey',\n description: 'Feedback survey, NPS form, or research questionnaire',\n is_active: true,\n sort_order: 2,\n category: 'feedback',\n aliases: ['feedback', 'poll', 'nps', 'questionnaire'],\n variants: [],\n required_features: [],\n required_node_types: ['choice', 'open', 'end_screen'],\n default_media_style: 'text',\n guide_uri: 'clipform://guides/survey',\n guide_description: 'Craft knowledge for feedback surveys, NPS, and research forms - brevity, rating scales, respondent fatigue',\n discovery: [\n { key: 'topic', question: 'What are you measuring? (satisfaction, NPS, feedback on what?)', fallback: 'General satisfaction', mode: 'all' },\n { key: 'anonymous', question: 'Anonymous or identified responses?', fallback: 'Anonymous', mode: 'full' },\n ],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-survey', title: 'Create a Survey', description: 'Build a feedback survey, NPS form, or research questionnaire' },\n },\n\n interview: {\n label: 'Interview',\n description: 'Async video interview, case study, or expert input collection',\n is_active: true,\n sort_order: 3,\n category: 'collection',\n aliases: ['case-study', 'callout'],\n variants: [],\n required_features: [],\n required_node_types: ['open', 'contact', 'end_screen'],\n default_media_style: 'video',\n guide_uri: 'clipform://guides/interview',\n guide_description: 'Craft knowledge for building interview forms - warm-up pacing, open questions, consent, video responses',\n discovery: [\n { key: 'purpose', question: 'What are you collecting? (case studies, feedback, expert input)', fallback: 'General responses', mode: 'all' },\n { key: 'response_format', question: 'How should people respond? (video, audio, text, all)', fallback: 'All formats', mode: 'full' },\n { key: 'needs_consent', question: 'Need a consent statement?', fallback: 'Yes', mode: 'full' },\n ],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-interview', title: 'Create an Interview', description: 'Build an async video interview for collecting case studies, feedback, or expert input' },\n },\n\n funnel: {\n label: 'Funnel',\n description: 'Lead qualification funnel with conditional routing',\n is_active: false,\n sort_order: 4,\n category: 'qualification',\n aliases: ['lead-gen', 'qualification', 'lead-magnet'],\n variants: [],\n required_features: ['branching'],\n required_node_types: ['choice', 'contact', 'end_screen'],\n default_media_style: 'text',\n guide_uri: 'clipform://guides/funnel',\n guide_description: 'Craft knowledge for lead qualification funnels - planned feature, conditional routing coming soon',\n discovery: [],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-funnel', title: 'Create a Funnel', description: 'Lead qualification funnels with branching logic are planned but not yet available' },\n },\n\n testimonial: {\n label: 'Testimonial',\n description: 'Video testimonial and story collection form',\n is_active: true,\n sort_order: 5,\n category: 'collection',\n aliases: ['story', 'review'],\n variants: [],\n required_features: [],\n required_node_types: ['open', 'contact', 'end_screen'],\n default_media_style: 'video',\n guide_uri: 'clipform://guides/testimonial',\n guide_description: 'Craft knowledge for collecting testimonials and customer stories on video - storytelling prompts, comfort techniques, consent',\n discovery: [\n { key: 'use_case', question: 'What stories are you collecting? (customer success, employee, partner)', fallback: 'Customer success stories', mode: 'all' },\n { key: 'media_style', question: 'Video responses (recommended), audio, or text?', fallback: 'Video', mode: 'full' },\n ],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-testimonial', title: 'Collect Testimonials', description: 'Build a video testimonial collection form - capture authentic customer stories on camera' },\n },\n\n application: {\n label: 'Application',\n description: 'Structured application form for jobs, programmes, or grants',\n is_active: true,\n sort_order: 6,\n category: 'collection',\n aliases: ['job-application', 'admission', 'enrollment', 'grant'],\n variants: [],\n required_features: [],\n required_node_types: ['open', 'choice', 'contact', 'end_screen'],\n default_media_style: 'video',\n guide_uri: 'clipform://guides/application',\n guide_description: 'Craft knowledge for application and evaluation forms - multi-section structure, video responses for behavioural questions, screening',\n discovery: [\n { key: 'role', question: 'What role or position?', fallback: 'General application', mode: 'all' },\n ],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-application', title: 'Create an Application Form', description: 'Build a structured application form with video responses for behavioural questions' },\n },\n\n booking: {\n label: 'Booking',\n description: 'Event registration, course signup, or booking form',\n is_active: true,\n sort_order: 7,\n category: 'registration',\n aliases: ['registration', 'signup', 'event', 'rsvp', 'workshop'],\n variants: [],\n required_features: [],\n required_node_types: ['contact', 'choice', 'end_screen'],\n default_media_style: 'text',\n guide_uri: 'clipform://guides/booking',\n guide_description: 'Craft knowledge for event registration and booking forms - minimal friction, video welcome, confirmation flow',\n discovery: [\n { key: 'event_name', question: \"What's the event name?\", fallback: 'Event registration', mode: 'all' },\n { key: 'event_type', question: 'What type? (workshop, webinar, meetup, conference)', fallback: 'Event', mode: 'full' },\n ],\n variant_discovery: {},\n variant_guide_uris: {},\n variant_descriptions: {},\n prompt: { name: 'create-booking', title: 'Create a Booking Form', description: 'Build an event registration or booking form with a personal video welcome' },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Derived exports\n// ---------------------------------------------------------------------------\n\nexport const FORM_TYPES_LIST = Object.entries(FORM_TYPES)\n .map(([key, def]) => ({ key, ...def }))\n .sort((a, b) => a.sort_order - b.sort_order);\n\nexport const FORM_TYPE_KEYS = Object.keys(FORM_TYPES);\n\nexport const WORKFLOW_TYPES = FORM_TYPE_KEYS.filter(\n key => FORM_TYPES[key].is_active\n);\n\nexport const FORM_TYPE_ALIASES = Object.fromEntries(\n Object.entries(FORM_TYPES).flatMap(([key, def]) =>\n def.aliases.map(alias => [alias, key])\n )\n);\n\nexport const ALL_VARIANTS = Object.entries(FORM_TYPES).flatMap(\n ([, def]) => def.variants\n);\n\nexport function resolveFormType(input) {\n const normalised = input.toLowerCase().trim();\n if (FORM_TYPES[normalised]) return normalised;\n return FORM_TYPE_ALIASES[normalised] ?? null;\n}\n\nexport function getDiscoveryParams(formType, variant, mode = 'full') {\n const def = FORM_TYPES[formType];\n if (!def) return [];\n\n let params;\n if (variant && def.variant_discovery?.[variant]) {\n params = def.variant_discovery[variant];\n } else {\n params = def.discovery;\n }\n\n if (mode === 'demo') {\n return params.filter(p => p.mode === 'all');\n }\n return params;\n}\n\nexport function isFormTypeAvailable(formType, features) {\n const def = FORM_TYPES[formType];\n if (!def || !def.is_active) return false;\n return def.required_features.every(\n featureKey => features[featureKey]?.enabled === true\n );\n}\n\nexport function getAvailableFormTypes(features) {\n return FORM_TYPE_KEYS.filter(key => isFormTypeAvailable(key, features));\n}\n","/**\n * Feature registry - single source of truth for what Clipform can and cannot do.\n *\n * enabled: runtime gate - does the dashboard/viewer expose this feature?\n * status:\n * 'live' - shipped and working in production\n * 'beta' - available but not fully polished\n * 'planned' - on the roadmap, not yet usable\n *\n * Rules:\n * - Marketing copy, blog posts, and landing pages must only claim features with status 'live'\n * - 'planned' features can be mentioned as \"coming soon\" but never as current capability\n * - When a feature ships: set enabled to true, status to 'live'\n * - Everything else derives from this file (PRODUCT.features, FEATURE_FLAGS, content claims)\n *\n * @type {Record<string, { name: string, description: string, enabled: boolean, status: 'live' | 'beta' | 'planned', category: string }>}\n */\nexport const FEATURES = {\n // -- Builder --\n visual_form_builder: {\n name: 'Visual form builder',\n description: 'Drag-and-drop node-based form builder powered by React Flow',\n enabled: true,\n status: 'live',\n category: 'builder',\n },\n form_themes: {\n name: 'Form themes',\n description: 'Customise primary colour, background colour, and font',\n enabled: true,\n status: 'live',\n category: 'builder',\n },\n media_prompts: {\n name: 'Media prompts',\n description: 'Attach video, audio, or images to any question node',\n enabled: true,\n status: 'live',\n category: 'builder',\n },\n node_logic: {\n name: 'Node routing logic',\n description: 'Define the order nodes appear in - currently supports linear paths (A to B to C)',\n enabled: true,\n status: 'live',\n category: 'builder',\n },\n branching: {\n name: 'Conditional branching',\n description: 'Choice nodes route to different destinations based on which option is picked',\n enabled: false,\n status: 'planned',\n category: 'builder',\n },\n custom_scores: {\n name: 'Custom scoring',\n description: 'Assign scores to choice options for quizzes and assessments',\n enabled: false,\n status: 'planned',\n category: 'builder',\n },\n text_response: {\n name: 'Text response option',\n description: 'Allow free-text input alongside choice options',\n enabled: false,\n status: 'planned',\n category: 'builder',\n },\n custom_fonts: {\n name: 'Custom fonts',\n description: 'Upload and use custom fonts in forms',\n enabled: false,\n status: 'planned',\n category: 'builder',\n },\n brand_name: {\n name: 'Custom brand name',\n description: 'Replace Clipform branding with your own brand name',\n enabled: false,\n status: 'planned',\n category: 'builder',\n },\n allow_resume: {\n name: 'Session resume',\n description: 'Respondents can continue a form where they left off',\n enabled: true,\n status: 'live',\n category: 'builder',\n },\n\n // -- Node types --\n node_start: {\n name: 'Start node',\n description: 'Entry point for every form',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_choice: {\n name: 'Multiple choice',\n description: 'Single or multi-select questions with configurable options',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_open: {\n name: 'Open-ended questions',\n description: 'Free-form responses via text, audio, or video',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_contact: {\n name: 'Contact form',\n description: 'Structured fields (name, email, phone, company) with consent checkboxes',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_button: {\n name: 'Button',\n description: 'Simple navigation or statement node',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_redirect: {\n name: 'Redirect',\n description: 'Terminal node that sends respondents to an external URL',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_end_screen: {\n name: 'End screen',\n description: 'Configurable thank-you screen with messaging, CTAs, and share button',\n enabled: true,\n status: 'live',\n category: 'node-types',\n },\n node_scale: {\n name: 'Scale / rating',\n description: 'Numerical rating questions (1-10, stars, etc.)',\n enabled: false,\n status: 'planned',\n category: 'node-types',\n },\n node_file_upload: {\n name: 'File upload',\n description: 'Collect files from respondents',\n enabled: false,\n status: 'planned',\n category: 'node-types',\n },\n node_booking: {\n name: 'Booking',\n description: 'Calendly or Google Meet scheduling embedded in the form',\n enabled: false,\n status: 'planned',\n category: 'node-types',\n },\n node_payment: {\n name: 'Payment',\n description: 'Collect payments via Stripe or Paddle inline',\n enabled: false,\n status: 'planned',\n category: 'node-types',\n },\n\n // -- Response formats --\n text_responses: {\n name: 'Text responses',\n description: 'Respondents type free-form text answers',\n enabled: true,\n status: 'live',\n category: 'responses',\n },\n audio_responses: {\n name: 'Audio responses',\n description: 'Respondents record audio directly in the browser',\n enabled: true,\n status: 'live',\n category: 'responses',\n },\n video_responses: {\n name: 'Video responses',\n description: 'Respondents record video directly in the browser',\n enabled: true,\n status: 'live',\n category: 'responses',\n },\n audio_attachments: {\n name: 'Audio attachments',\n description: 'Attach audio files to form nodes',\n enabled: false,\n status: 'planned',\n category: 'responses',\n },\n transcription: {\n name: 'Auto-transcription',\n description: 'Whisper-powered transcription for audio and video responses',\n enabled: true,\n status: 'live',\n category: 'responses',\n },\n\n // -- Analytics --\n analytics_overview: {\n name: 'Analytics dashboard',\n description: 'Views, starts, completions with daily time series',\n enabled: true,\n status: 'live',\n category: 'analytics',\n },\n analytics_demographics: {\n name: 'Demographic breakdown',\n description: 'Country, browser, device, and referrer source analytics',\n enabled: true,\n status: 'live',\n category: 'analytics',\n },\n utm_tracking: {\n name: 'UTM parameter tracking',\n description: 'Track utm_source, utm_medium, utm_campaign on form views',\n enabled: false,\n status: 'planned',\n category: 'analytics',\n },\n csv_export: {\n name: 'CSV export',\n description: 'Export analytics and response data to CSV',\n enabled: false,\n status: 'planned',\n category: 'analytics',\n },\n tracked_links: {\n name: 'Tracked links',\n description: 'URL tracking and click-through analytics for shared form links',\n enabled: false,\n status: 'planned',\n category: 'analytics',\n },\n\n // -- Sharing & embedding --\n public_share_links: {\n name: 'Public share links',\n description: 'Share forms via a public URL',\n enabled: true,\n status: 'live',\n category: 'sharing',\n },\n share_node: {\n name: 'Share individual nodes',\n description: 'Share a direct link to a specific node within a form',\n enabled: false,\n status: 'planned',\n category: 'sharing',\n },\n embed_inline: {\n name: 'Inline embed',\n description: 'Embed forms on external websites via script tag or JavaScript API',\n enabled: true,\n status: 'live',\n category: 'sharing',\n },\n embed_widget: {\n name: 'Embed widget',\n description: 'Floating button that opens a form in a modal overlay',\n enabled: false,\n status: 'planned',\n category: 'sharing',\n },\n embed_slots: {\n name: 'Embed slots',\n description: 'Named slots that point an embed at a form, so content can be swapped from the dashboard without changing the embed code',\n enabled: false,\n status: 'beta',\n category: 'sharing',\n },\n remove_branding: {\n name: 'Remove branding',\n description: 'Hide Clipform watermark (Pro plan)',\n enabled: true,\n status: 'live',\n category: 'sharing',\n },\n\n // -- AI --\n ai_form_generation: {\n name: 'AI form generation',\n description: 'Generate complete forms from a text prompt via MCP or dashboard',\n enabled: true,\n status: 'live',\n category: 'ai',\n },\n ai_tts: {\n name: 'AI text-to-speech',\n description: 'Generate voiceover audio for form prompts',\n enabled: true,\n status: 'live',\n category: 'ai',\n },\n\n // -- API --\n public_api: {\n name: 'Public API',\n description: 'REST API for form creation, node management, and response collection',\n enabled: true,\n status: 'live',\n category: 'api',\n },\n api_keys: {\n name: 'API key management',\n description: 'Self-service API key creation in the dashboard',\n enabled: false,\n status: 'planned',\n category: 'api',\n },\n\n // -- Integrations --\n webhooks: {\n name: 'Webhooks',\n description: 'Send response data to external URLs on form completion',\n enabled: false,\n status: 'planned',\n category: 'integrations',\n },\n integrations: {\n name: 'Third-party integrations',\n description: 'Connect forms to external services (Zapier, HubSpot, Slack, etc.)',\n enabled: false,\n status: 'planned',\n category: 'integrations',\n },\n notifications: {\n name: 'Response notifications',\n description: 'Email or webhook alerts when new responses arrive',\n enabled: false,\n status: 'planned',\n category: 'integrations',\n },\n import_typeform: {\n name: 'Typeform importer',\n description: 'Import forms from Typeform into Clipform',\n enabled: false,\n status: 'planned',\n category: 'integrations',\n },\n import_tally: {\n name: 'Tally importer',\n description: 'Import forms from Tally into Clipform',\n enabled: false,\n status: 'planned',\n category: 'integrations',\n },\n};\n\n/**\n * Backwards-compatible FEATURE_FLAGS object.\n * Maps the old flag names to FEATURES[key].enabled so existing dashboard code\n * keeps working without changes. Migrate consumers to FEATURES.x.enabled over time.\n */\nexport const FEATURE_FLAGS = {\n get ENABLE_BRANCHING() { return FEATURES.branching.enabled; },\n get ENABLE_CUSTOM_SCORES() { return FEATURES.custom_scores.enabled; },\n get ENABLE_TEXT_RESPONSE() { return FEATURES.text_response.enabled; },\n get INLINE_EMBED() { return FEATURES.embed_inline.enabled; },\n get WIDGET_EMBED() { return FEATURES.embed_widget.enabled; },\n get AUDIO_ATTACHMENTS() { return FEATURES.audio_attachments.enabled; },\n get WEBHOOKS() { return FEATURES.webhooks.enabled; },\n get INTEGRATIONS() { return FEATURES.integrations.enabled; },\n get CUSTOM_FONTS() { return FEATURES.custom_fonts.enabled; },\n get TRACKED_LINKS() { return FEATURES.tracked_links.enabled; },\n get SHARE_NODE() { return FEATURES.share_node.enabled; },\n get BRAND_NAME() { return FEATURES.brand_name.enabled; },\n get CSV_EXPORT() { return FEATURES.csv_export.enabled; },\n get ALLOW_RESUME() { return FEATURES.allow_resume.enabled; },\n get UTM_ANALYTICS() { return FEATURES.utm_tracking.enabled; },\n get API_KEYS() { return FEATURES.api_keys.enabled; },\n get NOTIFICATIONS() { return FEATURES.notifications.enabled; },\n get IMPORT_TYPEFORM() { return FEATURES.import_typeform.enabled; },\n get IMPORT_TALLY() { return FEATURES.import_tally.enabled; },\n};\n\nexport function getLiveFeatures() {\n return Object.values(FEATURES).filter(f => f.status === 'live');\n}\n\nexport function getPlannedFeatures() {\n return Object.values(FEATURES).filter(f => f.status === 'planned');\n}\n\nexport function getFeaturesByCategory(category) {\n return Object.values(FEATURES).filter(f => f.category === category);\n}\n","// @vid-master/config/help-links\n// Single source of truth for every in-product \"Learn more\" deep-link (#394).\n// In-product copy stays a short, actionable summary; the full explanation\n// lives in docs and we link to it, so the two can't drift.\n//\n// HELP_TOPICS is pure data (docs path + anchor, no base URL) so the docs\n// link-check script (apps/docs/scripts/check-help-links.mjs) can verify every\n// anchor resolves to a real heading without touching env. Consumers use\n// HELP_LINKS from the package root, which composes full URLs off\n// BUSINESS.urls.docs.\n\n/**\n * Keyed by concept. `path` is relative to the docs site root (which already\n * includes the /docs basePath); `anchor` must match a heading slug in the\n * target page (custom [#anchor] syntax or the auto-generated slug).\n */\nexport const HELP_TOPICS = {\n goLive: { path: '/guides/sharing', anchor: 'go-live' },\n cantGoLive: { path: '/guides/sharing', anchor: 'cant-go-live' },\n liveAndDraft: { path: '/guides/managing-forms', anchor: 'live-and-draft' },\n publishingChanges: { path: '/guides/managing-forms', anchor: 'publishing-changes' },\n embedding: { path: '/guides/embed', anchor: null },\n};\n\n/** Compose full HELP_LINKS URLs from a docs base URL (no trailing slash). */\nexport function buildHelpLinks(docsBaseUrl) {\n const links = {};\n for (const [key, { path, anchor }] of Object.entries(HELP_TOPICS)) {\n links[key] = `${docsBaseUrl}${path}${anchor ? `#${anchor}` : ''}`;\n }\n return links;\n}\n","// @vid-master/config/node-types\n// Static node type definitions — single source of truth for all apps.\n// New node types require code changes (new component, renderer, etc.),\n// so this data is version-controlled rather than stored in the database.\n\nexport const NODE_TYPES = {\n start: {\n label: 'Start',\n shorthand: 'Start',\n icon: 'ArrowRight',\n color: '#D1FAE5',\n description: 'Entry point for the form - connects to the first node',\n category: 'start',\n sort_order: 0,\n has_options: false,\n is_terminal: false,\n show_nav_bar: false,\n loading: 'eager',\n supports_prompt: false,\n supports_media: false,\n is_system: true,\n is_active: true,\n show_in_results: false,\n default_config: null,\n config_schema: null,\n response_schema: null,\n output_schema: null,\n },\n choice: {\n label: 'Multiple Choice',\n shorthand: 'Multi',\n icon: 'CheckSquare',\n color: '#DBEAFE',\n description: 'Single or multiple choice node with predefined options',\n category: 'input',\n sort_order: 1,\n has_options: true,\n min_options: 1,\n max_options: 6,\n max_option_length: 36,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'eager',\n supports_prompt: true,\n supports_media: true,\n is_system: false,\n is_active: true,\n show_in_results: true,\n default_config: {\n selection_mode: 'single',\n choice: { enable_branching: true, record_scores: false },\n randomise_options: false,\n show_option_count: false,\n options: [\n { content: 'Option 1' },\n { content: 'Option 2' },\n ],\n },\n config_schema: {\n type: 'object',\n properties: {\n choice: {\n type: 'object',\n properties: {\n enable_branching: {\n type: 'boolean',\n label: 'Enable branching logic',\n default: true,\n description: 'Allow each option to have its own logic path. When disabled, all options share a single jump action.',\n },\n show_answer_feedback: {\n type: 'boolean',\n label: 'Show answer feedback',\n default: false,\n description: 'Show correct/incorrect feedback after selection (requires scored options).',\n },\n record_scores: {\n type: 'boolean',\n label: 'Mark correct answer',\n default: false,\n description: 'Select which option is the correct answer.',\n },\n },\n },\n selection_mode: {\n enum: ['single', 'multiple'],\n type: 'string',\n label: 'Selection mode',\n default: 'single',\n description: 'Allow single or multiple selections',\n },\n allow_text_response: {\n type: 'boolean',\n label: 'Allow text response',\n default: false,\n description: 'Allow free-text response in addition to options (single choice only)',\n },\n randomise_options: {\n type: 'boolean',\n label: 'Randomise options',\n default: false,\n description: 'Show options in random order',\n },\n show_option_count: {\n type: 'boolean',\n label: 'Show option count',\n default: false,\n description: 'Display number of options',\n },\n content_media_type: {\n enum: ['upload', 'recorded'],\n type: 'string',\n label: 'Content media type',\n description: 'How the node media was provided',\n },\n },\n },\n response_schema: {\n type: 'string',\n description: 'Selected option ID',\n },\n output_schema: {\n type: 'object',\n required: ['type', 'label', 'option_id'],\n properties: {\n type: { type: 'string', const: 'choice' },\n label: { type: 'string', description: 'Human-readable option label' },\n option_id: { type: 'string', format: 'uuid', description: 'Selected option UUID' },\n },\n },\n },\n open: {\n label: 'Open Ended',\n shorthand: 'Open',\n icon: 'Type',\n color: '#DBEAFE',\n description: 'Free-form text responses from users',\n category: 'input',\n sort_order: 2,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'eager',\n supports_prompt: true,\n supports_media: true,\n is_system: false,\n is_active: true,\n show_in_results: true,\n default_config: {\n formats: [\n { order: 0, format: 'text' },\n { order: 1, format: 'audio' },\n { order: 2, format: 'video' },\n ],\n },\n config_schema: {\n type: 'object',\n properties: {\n formats: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n format: { enum: ['text', 'audio', 'video'], type: 'string' },\n order: { type: 'number' },\n },\n },\n label: 'Allowed response formats',\n description: 'Which formats the user can respond with, in display order',\n },\n content_media_type: {\n enum: ['upload', 'recorded'],\n type: 'string',\n label: 'Content media type',\n description: 'How the node media was provided',\n },\n },\n },\n response_schema: {\n type: 'object',\n required: ['response_type'],\n properties: {\n text: {\n type: 'string',\n description: 'Text response (when response_type is text) or transcribed text from audio/video',\n },\n media: {\n type: 'object',\n properties: {\n type: { enum: ['audio', 'video'], type: 'string' },\n storage_path: { type: 'string' },\n facing_mode: { enum: ['user', 'environment'], type: 'string' },\n preview_crop: {\n type: 'object',\n properties: {\n stream_width: { type: 'number' },\n stream_height: { type: 'number' },\n preview_width: { type: 'number' },\n preview_height: { type: 'number' },\n },\n },\n },\n description: 'Media response (when response_type is audio or video)',\n },\n response_type: {\n enum: ['text', 'audio', 'video'],\n type: 'string',\n },\n transcription: {\n type: 'object',\n properties: {\n text: { type: 'string' },\n language: { type: 'string' },\n duration: { type: 'number' },\n words: { type: 'array' },\n },\n description: 'Whisper transcription data for audio/video responses',\n },\n },\n },\n output_schema: {\n type: 'object',\n required: ['type'],\n properties: {\n type: { type: 'string', const: 'text' },\n text: { type: 'string', description: 'Text response or transcription' },\n media: {\n type: 'object',\n properties: {\n type: { enum: ['audio', 'video'], type: 'string' },\n storage_path: { type: 'string' },\n facing_mode: { enum: ['user', 'environment'], type: 'string' },\n preview_crop: {\n type: 'object',\n properties: {\n stream_width: { type: 'number' },\n stream_height: { type: 'number' },\n preview_width: { type: 'number' },\n preview_height: { type: 'number' },\n },\n },\n },\n },\n transcription: {\n type: 'object',\n properties: {\n text: { type: 'string' },\n language: { type: 'string' },\n },\n },\n },\n },\n },\n scale: {\n label: 'Scale',\n shorthand: 'Scale',\n icon: 'BarChart3',\n color: '#DBEAFE',\n description: 'Numerical rating or scale node (1-10, etc.)',\n category: 'input',\n sort_order: 3,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'eager',\n supports_prompt: true,\n supports_media: true,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: null,\n config_schema: {\n type: 'object',\n properties: {\n max: { type: 'number', label: 'Maximum value', default: 10, required: true },\n min: { type: 'number', label: 'Minimum value', default: 1, required: true },\n step: { min: 0.1, type: 'number', label: 'Step increment', default: 1 },\n left_label: { type: 'string', label: 'Left label', placeholder: 'Not likely' },\n right_label: { type: 'string', label: 'Right label', placeholder: 'Very likely' },\n show_numbers: { type: 'boolean', label: 'Show numbers', default: true },\n },\n },\n response_schema: {\n type: 'number',\n description: 'Selected scale value',\n },\n output_schema: null,\n },\n booking: {\n label: 'Booking',\n shorthand: 'Booking',\n icon: 'Calendar',\n color: '#E9D5FF',\n description: null,\n category: 'action',\n sort_order: 4,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: null,\n config_schema: {\n type: 'object',\n oneOf: [\n {\n required: ['calendly'],\n properties: {\n calendly: {\n type: 'object',\n properties: {\n event_name: { type: 'string', label: 'Event name', description: 'Display name for the event' },\n event_type_uri: { type: 'string', label: 'Event type URI', format: 'uri', description: 'Your Calendly event type URI', placeholder: 'https://calendly.com/your-link' },\n },\n },\n },\n },\n {\n required: ['google_meet'],\n properties: {\n google_meet: {\n type: 'object',\n properties: {\n duration: { type: 'number', label: 'Duration (minutes)', default: 30, description: 'Meeting duration in minutes' },\n calendar_id: { type: 'string', label: 'Calendar', description: 'Google Calendar to use for bookings' },\n event_title: { type: 'string', label: 'Event title', default: 'Meeting', description: 'Default title for scheduled meetings' },\n calendar_name: { type: 'string', label: 'Calendar name', description: 'Display name for the selected calendar' },\n },\n },\n },\n },\n ],\n description: 'Booking provider configuration (one provider per node)',\n },\n response_schema: {\n type: 'object',\n oneOf: [\n {\n required: ['calendly'],\n properties: {\n calendly: {\n type: 'object',\n required: ['event_uri', 'scheduled_time'],\n properties: {\n event_uri: { type: 'string', format: 'uri' },\n event_type: { type: 'string' },\n invitee_uri: { type: 'string', format: 'uri' },\n reschedule_url: { type: 'string', format: 'uri' },\n scheduled_time: { type: 'string', format: 'date-time' },\n cancellation_url: { type: 'string', format: 'uri' },\n },\n },\n },\n },\n ],\n description: 'Booking response with provider-specific data',\n },\n output_schema: null,\n },\n contact: {\n label: 'Contact Form',\n shorthand: 'Contact',\n icon: 'User',\n color: '#CFFAFE',\n description: 'Collect standardized contact information (name, email, phone, company)',\n category: 'input',\n sort_order: 5,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: true,\n show_in_results: false,\n default_config: {\n fields: [\n { id: 'first_name', type: 'first_name', label: 'First Name', enabled: true, required: true },\n { id: 'email', type: 'email', label: 'Email', enabled: true, required: true },\n ],\n consent_items: [\n { id: 'default-consent', name: 'Privacy policy', label: 'I agree to the privacy policy and terms of service', order: 0, type: 'consent' },\n ],\n },\n config_schema: {\n type: 'object',\n required: ['fields'],\n properties: {\n title: { type: 'string' },\n fields: {\n type: 'array',\n minItems: 1,\n items: {\n type: 'object',\n required: ['id', 'required'],\n properties: {\n id: { type: 'string' },\n type: { enum: ['text', 'textarea', 'email', 'tel', 'url'], type: 'string' },\n label: { type: 'string' },\n order: { type: 'number' },\n required: { type: 'boolean', default: true },\n is_custom: { type: 'boolean', default: false },\n },\n },\n },\n description: { type: 'string' },\n consent_items: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n label: { type: 'string' },\n order: { type: 'number' },\n type: { type: 'string', enum: ['consent', 'opt_in'] },\n },\n },\n },\n },\n },\n response_schema: {\n type: 'object',\n required: ['fields'],\n properties: {\n fields: {\n type: 'array',\n items: {\n type: 'object',\n required: ['id', 'type', 'label', 'value'],\n properties: {\n id: { type: 'string' },\n type: { type: 'string' },\n label: { type: 'string' },\n value: { type: 'string' },\n },\n },\n description: 'Contact form field entries with metadata',\n },\n consent: {\n type: 'array',\n items: {\n type: 'object',\n required: ['id', 'name', 'label', 'accepted', 'type'],\n properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n label: { type: 'string' },\n accepted: { type: 'boolean' },\n type: { type: 'string', enum: ['consent', 'opt_in'] },\n },\n },\n description: 'Consent checkbox entries',\n },\n },\n },\n output_schema: {\n type: 'object',\n required: ['type', 'fields'],\n properties: {\n type: { type: 'string', const: 'contact' },\n fields: {\n type: 'array',\n items: {\n type: 'object',\n required: ['type', 'value'],\n properties: {\n type: { type: 'string' },\n value: { type: 'string' },\n },\n },\n },\n },\n },\n },\n file_upload: {\n label: 'File Upload',\n shorthand: 'Upload',\n icon: 'Upload',\n color: '#CFFAFE',\n description: 'Collect file uploads from respondents',\n category: 'input',\n sort_order: 6,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: null,\n config_schema: {\n type: 'object',\n properties: {\n max_files: { max: 20, min: 1, type: 'number', label: 'Max files', default: 5, description: 'Maximum number of files respondents can upload' },\n max_file_size_mb: { max: 500, min: 1, type: 'number', label: 'Max file size (MB)', default: 50, description: 'Maximum size per file (1-500 MB)' },\n allowed_media_types: {\n type: 'array',\n items: { enum: ['images', 'videos', 'documents', 'all'], type: 'string' },\n label: 'Allowed media types',\n default: ['images', 'documents'],\n enumLabels: {\n all: 'All file types',\n images: 'Images (JPEG, PNG, GIF, WebP, HEIC)',\n videos: 'Videos (MP4, MOV, WebM, AVI)',\n documents: 'Documents (PDF, DOC, DOCX, XLS, XLSX, TXT, CSV)',\n },\n description: 'Select which types of files respondents can upload',\n },\n },\n },\n response_schema: {\n type: 'object',\n required: ['files'],\n properties: {\n files: {\n type: 'array',\n items: {\n type: 'object',\n required: ['id', 'name', 'storage_path', 'url', 'mime_type', 'size', 'uploaded_at'],\n properties: {\n id: { type: 'string', format: 'uuid', description: 'Unique file identifier' },\n url: { type: 'string', format: 'uri', description: 'Signed Supabase Storage URL for download' },\n name: { type: 'string', description: 'Original filename' },\n size: { type: 'integer', minimum: 1, description: 'File size in bytes' },\n mime_type: { type: 'string', description: 'File MIME type' },\n uploaded_at: { type: 'string', format: 'date-time', description: 'ISO timestamp of upload completion' },\n storage_path: { type: 'string', description: 'Full storage path: workspace_id/form_id/node_id/uuid.ext' },\n },\n },\n minItems: 1,\n description: 'Array of uploaded file metadata',\n },\n },\n },\n output_schema: null,\n },\n payment: {\n label: 'Payment',\n shorthand: 'Payment',\n icon: 'DollarSign',\n color: '#E9D5FF',\n description: null,\n category: 'action',\n sort_order: 7,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: { amount: null, currency: 'usd', provider: 'stripe' },\n config_schema: {\n type: 'object',\n required: ['amount', 'currency', 'provider'],\n properties: {\n amount: { type: 'number', label: 'Amount (in cents)', minimum: 50, required: true, description: 'Payment amount in cents (e.g., 5000 = $50.00)' },\n currency: { enum: ['usd', 'eur', 'gbp', 'cad', 'aud'], type: 'string', label: 'Currency', default: 'usd', required: true, description: 'Three-letter ISO currency code' },\n provider: { enum: ['stripe', 'paddle'], type: 'string', label: 'Payment Provider', default: 'stripe', required: true, description: 'Payment provider to use' },\n workspace_integration_id: { type: 'string', label: 'Workspace Integration ID', description: 'UUID of the workspace_integrations record for the connected payment account' },\n },\n description: 'Payment configuration with provider-agnostic flat structure',\n },\n response_schema: {\n type: 'object',\n oneOf: [\n {\n required: ['stripe'],\n properties: {\n stripe: {\n type: 'object',\n required: ['payment_intent_id', 'status', 'amount', 'currency'],\n properties: {\n name: { type: 'string', description: 'Customer name from Stripe billing details' },\n email: { type: 'string', format: 'email', description: 'Customer email from Stripe billing details' },\n amount: { type: 'number', description: 'Payment amount in cents' },\n status: { enum: ['pending', 'succeeded', 'failed'], type: 'string', description: 'Payment status' },\n currency: { type: 'string', description: 'Three-letter ISO currency code (e.g., usd, eur)' },\n payment_intent_id: { type: 'string', description: 'Stripe payment intent ID' },\n },\n },\n },\n },\n {\n required: ['square'],\n properties: {\n square: {\n type: 'object',\n properties: {\n amount: { type: 'number' },\n status: { type: 'string' },\n order_id: { type: 'string' },\n payment_id: { type: 'string' },\n },\n },\n },\n },\n {\n required: ['paddle'],\n properties: {\n paddle: {\n type: 'object',\n properties: {\n amount: { type: 'number' },\n status: { type: 'string' },\n order_id: { type: 'string' },\n checkout_id: { type: 'string' },\n },\n },\n },\n },\n ],\n description: 'Payment response with provider-specific data',\n },\n output_schema: null,\n },\n binary: {\n label: 'Binary',\n shorthand: 'A/B',\n icon: 'CircleCheck',\n color: '#DBEAFE',\n description: 'Two-option choice - yes/no, true/false, or this vs that',\n category: 'input',\n sort_order: 1.5,\n has_options: true,\n min_options: 2,\n max_options: 2,\n max_option_length: 12,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'eager',\n supports_prompt: true,\n supports_media: true,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: {\n choice: { enable_branching: true },\n options: [\n { content: 'Yes' },\n { content: 'No' },\n ],\n },\n config_schema: {\n type: 'object',\n properties: {\n choice: {\n type: 'object',\n properties: {\n enable_branching: {\n type: 'boolean',\n label: 'Enable branching logic',\n default: true,\n description: 'Allow each option to have its own logic path.',\n },\n },\n },\n content_media_type: {\n enum: ['upload', 'recorded'],\n type: 'string',\n label: 'Content media type',\n description: 'How the node media was provided',\n },\n },\n },\n response_schema: {\n type: 'string',\n description: 'Selected option ID',\n },\n output_schema: {\n type: 'object',\n required: ['type', 'label', 'option_id'],\n properties: {\n type: { type: 'string', const: 'binary' },\n label: { type: 'string', description: 'Human-readable option label' },\n option_id: { type: 'string', format: 'uuid', description: 'Selected option UUID' },\n },\n },\n },\n button: {\n label: 'Button',\n shorthand: 'Button',\n icon: 'RectangleHorizontal',\n color: '#DBEAFE',\n description: 'Simple button for acknowledgment or navigation',\n category: 'input',\n sort_order: 3,\n has_options: true,\n min_options: 1,\n max_options: 1,\n max_option_length: 28,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'eager',\n supports_prompt: true,\n supports_media: true,\n is_system: false,\n is_active: true,\n show_in_results: false,\n default_config: { options: [{ content: 'Continue' }] },\n config_schema: {\n type: 'object',\n properties: {\n button_text: { type: 'string', label: 'Button text', default: 'Continue' },\n button_style: { enum: ['primary', 'secondary', 'outline'], type: 'string', label: 'Button style', default: 'primary' },\n },\n },\n response_schema: {\n type: 'string',\n description: 'Selected option ID',\n },\n output_schema: {\n type: 'object',\n required: ['type', 'label', 'option_id'],\n properties: {\n type: { type: 'string', const: 'button' },\n label: { type: 'string', description: 'Human-readable option label' },\n option_id: { type: 'string', format: 'uuid', description: 'Selected option UUID' },\n },\n },\n },\n redirect: {\n label: 'Redirect',\n shorthand: 'Redirect',\n icon: 'ExternalLink',\n color: '#FFEDD5',\n description: 'Redirect users to an external URL',\n category: 'end',\n sort_order: 101,\n has_options: false,\n is_terminal: true,\n show_nav_bar: false,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: true,\n show_in_results: false,\n default_config: { url: '', auto_redirect: true },\n config_schema: {\n type: 'object',\n properties: {\n url: { type: 'string', label: 'Redirect URL', placeholder: 'https://example.com' },\n auto_redirect: { type: 'boolean', label: 'Auto-redirect', default: true, description: 'Automatically redirect to the URL instead of showing a button' },\n },\n },\n response_schema: {\n type: 'string',\n description: 'URL the user was redirected to',\n },\n output_schema: null,\n },\n link_list: {\n label: 'Link List',\n shorthand: 'Links',\n icon: 'ExternalLink',\n color: '#FFEDD5',\n description: 'Display a list of links for users to choose from',\n category: 'end',\n sort_order: 102,\n has_options: false,\n is_terminal: true,\n show_nav_bar: false,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: false,\n default_config: { links: [{ id: 'default', url: '', title: '', description: '', order: 0 }], auto_redirect: false },\n config_schema: {\n type: 'object',\n properties: {\n links: {\n type: 'array',\n items: {\n type: 'object',\n required: ['id', 'url'],\n properties: {\n id: { type: 'string' },\n url: { type: 'string', label: 'URL', placeholder: 'https://example.com' },\n title: { type: 'string', label: 'Heading' },\n description: { type: 'string', label: 'Description' },\n order: { type: 'number', label: 'Sort order' },\n },\n },\n label: 'Links',\n minItems: 1,\n },\n auto_redirect: { type: 'boolean', label: 'Auto-redirect', default: false, description: 'Automatically redirect to the URL instead of showing a button' },\n },\n },\n response_schema: {\n type: 'string',\n description: 'URL of the link that was clicked',\n },\n output_schema: null,\n },\n file_download: {\n label: 'File Download',\n shorthand: 'Download',\n icon: 'Download',\n color: '#E9D5FF',\n description: 'Provide a file for respondents to download',\n category: 'action',\n sort_order: 103,\n has_options: false,\n is_terminal: false,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: true,\n default_config: null,\n config_schema: {\n type: 'object',\n properties: {\n files: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file_name: { type: 'string', label: 'Display file name', required: true },\n file_path: { type: 'string', label: 'File path in storage', required: true },\n file_size: { type: 'number', label: 'File size in bytes' },\n mime_type: { type: 'string', label: 'MIME type' },\n },\n },\n label: 'Downloadable files',\n },\n button_text: { type: 'string', label: 'Button text', default: 'Download Files' },\n description: { type: 'string', label: 'Description text' },\n },\n },\n response_schema: {\n type: 'object',\n required: ['files'],\n properties: {\n files: {\n type: 'array',\n items: {\n type: 'object',\n required: ['file_path', 'file_name', 'downloaded_at'],\n properties: {\n file_name: { type: 'string', description: 'Display name of the file' },\n file_path: { type: 'string', description: 'Storage path of the downloaded file' },\n downloaded_at: { type: 'string', format: 'date-time', description: 'Timestamp when download was initiated' },\n },\n },\n description: 'List of files downloaded by respondent',\n },\n },\n },\n output_schema: null,\n },\n shopping: {\n label: 'Shopping',\n shorthand: 'Shop',\n icon: 'ShoppingBag',\n color: '#E9D5FF',\n description: 'Product recommendations with direct checkout',\n category: 'action',\n sort_order: 8,\n has_options: false,\n is_terminal: true,\n show_nav_bar: true,\n loading: 'lazy',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: false,\n show_in_results: false,\n default_config: { provider: 'shopify', cta_mode: 'checkout', source_mode: 'manual' },\n config_schema: {\n type: 'object',\n required: ['provider', 'cta_mode'],\n properties: {\n title: { type: 'string', label: 'Heading', description: 'Heading shown above the product list' },\n description: { type: 'string', label: 'Description', description: 'Body text shown below the heading' },\n provider: { enum: ['shopify'], type: 'string', label: 'Provider', default: 'shopify', description: 'Ecommerce provider' },\n workspace_integration_id: { type: 'string', label: 'Workspace Integration ID', description: 'UUID of the workspace_integrations record for the connected store' },\n cta_mode: { enum: ['checkout', 'add_to_cart'], type: 'string', label: 'CTA Mode', default: 'checkout', description: 'Whether to go to checkout or add to cart' },\n source_mode: { enum: ['manual', 'collection'], type: 'string', label: 'Product source', default: 'manual', description: 'How products are selected: manually picked or from a collection' },\n collection_id: { type: 'string', label: 'Collection ID', description: 'Shopify collection GID (when source_mode is collection)' },\n collection_title: { type: 'string', label: 'Collection title', description: 'Display name of the selected collection' },\n products: {\n type: 'array',\n label: 'Selected Products',\n description: 'Products to show (static mode)',\n items: {\n type: 'object',\n properties: {\n product_id: { type: 'string', description: 'Shopify product GID' },\n variant_id: { type: 'string', description: 'Shopify variant GID' },\n title: { type: 'string' },\n handle: { type: 'string' },\n image_url: { type: 'string' },\n price: { type: 'string' },\n currency: { type: 'string' },\n recommended: { type: 'boolean', default: true, description: 'Pre-ticked in viewer' },\n },\n },\n },\n product_mappings: {\n type: 'array',\n label: 'Score-based product mappings',\n description: 'Map score ranges to different product sets. First matching range wins.',\n items: {\n type: 'object',\n required: ['min', 'max'],\n properties: {\n min: { type: 'integer', label: 'Minimum score (inclusive)' },\n max: { type: 'integer', label: 'Maximum score (inclusive)' },\n message: { type: 'string', label: 'Message' },\n products: { type: 'array', description: 'Products for this score range' },\n },\n },\n },\n },\n description: 'Shopping configuration with provider-agnostic structure',\n },\n response_schema: null,\n output_schema: null,\n },\n end_screen: {\n label: 'Ending',\n shorthand: 'End',\n icon: 'Flag',\n color: '#FFEDD5',\n description: 'Final screen shown when form is completed',\n category: 'end',\n sort_order: 999,\n has_options: false,\n is_terminal: true,\n show_nav_bar: false,\n loading: 'eager',\n supports_prompt: false,\n supports_media: false,\n is_system: false,\n is_active: true,\n show_in_results: false,\n default_config: null,\n config_schema: {\n type: 'object',\n properties: {\n title: { type: 'string', label: 'Title', default: 'Thank you!', description: 'Heading shown on completion' },\n message: { type: 'string', label: 'Message', default: 'Your response has been submitted.', description: 'Message shown on completion' },\n show_score: { type: 'boolean', label: 'Show score', default: false, description: 'Display score on the end screen (e.g. \"You scored 4 out of 5\")' },\n icon: { type: 'string', label: 'Icon', enum: ['tick', 'trophy', 'star', 'crown', 'party', 'none'], default: 'tick', description: 'Icon shown above the title' },\n show_share_button: { type: 'boolean', label: 'Show share button', default: false, description: 'Show a share button above the CTA' },\n cta_type: { type: 'string', label: 'CTA type', enum: ['none', 'restart', 'external_link'], default: 'none', description: 'Primary call-to-action button type' },\n cta_text: { type: 'string', label: 'CTA button text', default: 'Continue', description: 'Button label for the CTA' },\n cta_url: { type: 'string', label: 'CTA URL', format: 'uri', description: 'URL to open (only for external_link CTA type)', placeholder: 'https://example.com' },\n score_ranges: {\n type: 'array',\n label: 'Score-based content',\n description: 'Show different content based on cumulative score. First matching range wins.',\n items: {\n type: 'object',\n required: ['min', 'max', 'title'],\n properties: {\n min: { type: 'integer', label: 'Minimum score (inclusive)' },\n max: { type: 'integer', label: 'Maximum score (inclusive)' },\n title: { type: 'string', label: 'Title' },\n message: { type: 'string', label: 'Message' },\n },\n },\n },\n scoring_results: {\n type: 'array',\n label: 'Category-based results',\n description: 'Results keyed by scoring category. The winning category (highest non-knocked-out score) determines which result is shown.',\n items: {\n type: 'object',\n required: ['category', 'title'],\n properties: {\n category: { type: 'string', label: 'Category key (must match keys used in option scores)' },\n title: { type: 'string', label: 'Title' },\n message: { type: 'string', label: 'Message' },\n cta_url: { type: 'string', label: 'CTA URL', format: 'uri' },\n cta_text: { type: 'string', label: 'CTA button text' },\n },\n },\n },\n },\n },\n response_schema: null,\n output_schema: null,\n },\n};\n\n// Derived exports\n\n/** Sorted list of all node types with their type key included */\nexport const NODE_TYPES_LIST = Object.entries(NODE_TYPES)\n .map(([type, def]) => ({ type, ...def }))\n .sort((a, b) => a.sort_order - b.sort_order);\n\n/** All valid node type keys */\nexport const NODE_TYPE_KEYS = Object.keys(NODE_TYPES);\n\n/** Response schemas keyed by node type */\nexport const RESPONSE_SCHEMAS = Object.fromEntries(\n Object.entries(NODE_TYPES).map(([k, v]) => [k, v.response_schema])\n);\n\n/** Config schemas keyed by node type */\nexport const CONFIG_SCHEMAS = Object.fromEntries(\n Object.entries(NODE_TYPES).map(([k, v]) => [k, v.config_schema])\n);\n\n/** Output schemas keyed by node type */\nexport const OUTPUT_SCHEMAS = Object.fromEntries(\n Object.entries(NODE_TYPES).map(([k, v]) => [k, v.output_schema])\n);\n\n/** Metadata subset used by viewer for layout decisions */\nexport const NODE_TYPE_METADATA = Object.fromEntries(\n Object.entries(NODE_TYPES).map(([k, v]) => [k, {\n supports_prompt: v.supports_prompt,\n supports_media: v.supports_media,\n is_terminal: v.is_terminal,\n show_nav_bar: v.show_nav_bar,\n category: v.category,\n loading: v.loading,\n }])\n);\n\n/** Terminal node type keys (is_terminal === true) */\nexport const TERMINAL_TYPES = Object.entries(NODE_TYPES)\n .filter(([, v]) => v.is_terminal)\n .map(([k]) => k);\n\n/** Node types excluded from counts (system + terminal) */\nexport const NON_COUNTABLE_TYPES = Object.entries(NODE_TYPES)\n .filter(([, v]) => v.is_system || v.is_terminal)\n .map(([k]) => k);\n\n/** Supabase .not() filter string for non-countable types */\nexport const NON_COUNTABLE_FILTER = `(${NON_COUNTABLE_TYPES.map(t => `\"${t}\"`).join(',')})`;\n\n/** Node types excluded from results and responses views */\nexport const RESULTS_EXCLUDED_TYPES = Object.entries(NODE_TYPES)\n .filter(([, v]) => !v.show_in_results)\n .map(([k]) => k);\n\n/** Check if a node type is terminal */\nexport function isTerminalType(type) {\n return NODE_TYPE_METADATA[type]?.is_terminal === true;\n}\n\n","// @vid-master/config/integration-catalog\n// Static integration catalog — single source of truth for all apps.\n// Integration metadata rarely changes, so this is version-controlled\n// rather than stored in the database. User connections (workspace_integrations)\n// remain in the DB as dynamic data.\n\nexport const INTEGRATION_CATALOG = {\n stripe: {\n name: 'Stripe',\n category: 'form_action',\n description: 'Accept payments directly in your forms',\n logo_url: 'https://cdn.brandfetch.io/stripe.com/w/400/h/400',\n color: '#635BFF',\n sort_order: 1,\n tags: ['payment'],\n external_account_id_field: 'account_id',\n display_name_field: 'account_name',\n is_active: true,\n },\n paddle: {\n name: 'Paddle',\n category: 'form_action',\n description: 'Accept payments with Paddle',\n logo_url: 'https://cdn.brandfetch.io/paddle.com/w/400/h/400',\n color: '#6837FC',\n sort_order: 2,\n tags: ['payment'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n square: {\n name: 'Square',\n category: 'form_action',\n description: 'Accept payments with Square',\n logo_url: 'https://cdn.brandfetch.io/square.com/w/400/h/400',\n color: '#000000',\n sort_order: 3,\n tags: ['payment'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n calendly: {\n name: 'Calendly',\n category: 'form_action',\n description: 'Schedule meetings directly in your forms',\n logo_url: 'https://cdn.brandfetch.io/calendly.com/w/400/h/400',\n color: '#006BFF',\n sort_order: 4,\n tags: ['booking'],\n external_account_id_field: 'user_uri',\n display_name_field: 'user_name',\n is_active: true,\n },\n calcom: {\n name: 'Cal.com',\n category: 'form_action',\n description: 'Open-source scheduling platform for booking meetings',\n logo_url: null,\n color: '#292929',\n sort_order: 4,\n tags: ['booking'],\n external_account_id_field: 'id',\n display_name_field: 'name',\n is_active: true,\n },\n docusign: {\n name: 'DocuSign',\n category: 'form_action',\n description: 'Collect signatures in your forms',\n logo_url: 'https://cdn.brandfetch.io/docusign.com/w/400/h/400',\n color: '#FF0037',\n sort_order: 5,\n tags: ['document', 'e-signature', 'contract'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n webhook: {\n name: 'Webhook',\n category: 'automation',\n description: 'Send responses to custom webhooks',\n logo_url: null,\n color: '#6B7280',\n sort_order: 100,\n tags: ['webhook', 'automation', 'developer'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n zapier: {\n name: 'Zapier',\n category: 'automation',\n description: 'Connect to 5,000+ apps and automate workflows',\n logo_url: 'https://cdn.brandfetch.io/zapier.com/w/400/h/400',\n color: '#FF4A00',\n sort_order: 101,\n tags: ['automation', 'workflow', 'no-code'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n make: {\n name: 'Make',\n category: 'automation',\n description: 'Advanced automation and integrations',\n logo_url: 'https://cdn.brandfetch.io/make.com/w/400/h/400',\n color: '#6B4AFF',\n sort_order: 102,\n tags: ['automation', 'workflow', 'integration'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n hubspot: {\n name: 'HubSpot',\n category: 'automation',\n description: 'Sync responses to HubSpot CRM',\n logo_url: 'https://cdn.brandfetch.io/hubspot.com/w/400/h/400',\n color: '#FF7A59',\n sort_order: 103,\n tags: ['automation', 'crm', 'marketing'],\n external_account_id_field: 'portal_id',\n display_name_field: 'portal_name',\n is_active: true,\n },\n salesforce: {\n name: 'Salesforce',\n category: 'automation',\n description: 'Sync responses to Salesforce CRM',\n logo_url: 'https://cdn.brandfetch.io/salesforce.com/w/400/h/400',\n color: '#00A1E0',\n sort_order: 104,\n tags: ['automation', 'crm', 'sales'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n slack: {\n name: 'Slack',\n category: 'automation',\n description: 'Send notifications to Slack channels',\n logo_url: 'https://cdn.brandfetch.io/slack.com/w/400/h/400',\n color: '#4A154B',\n sort_order: 105,\n tags: ['automation', 'communication', 'notifications'],\n external_account_id_field: null,\n display_name_field: null,\n is_active: true,\n },\n shopify: {\n name: 'Shopify',\n category: 'ecommerce',\n description: 'Product recommendations from quiz results with direct checkout',\n logo_url: 'https://cdn.brandfetch.io/shopify.com/w/400/h/400',\n color: '#95BF47',\n sort_order: 200,\n tags: ['ecommerce', 'product', 'checkout', 'quiz'],\n external_account_id_field: 'shop_domain',\n display_name_field: 'shop_name',\n is_active: true,\n },\n};\n\n// Derived exports\n\n/** Sorted list of all integrations with their slug included */\nexport const INTEGRATION_CATALOG_LIST = Object.entries(INTEGRATION_CATALOG)\n .map(([slug, def]) => ({ slug, ...def }))\n .sort((a, b) => a.sort_order - b.sort_order);\n\n/** All valid integration slugs */\nexport const INTEGRATION_SLUGS = Object.keys(INTEGRATION_CATALOG);\n\n/** Get integrations filtered by category */\nexport const getIntegrationsByCategory = (category) =>\n INTEGRATION_CATALOG_LIST.filter(i => i.category === category);\n\n/** Get integrations filtered by tags (matches any) */\nexport const getIntegrationsByTags = (tags) =>\n INTEGRATION_CATALOG_LIST.filter(i => i.tags.some(t => tags.includes(t)));\n","import { FEATURES, getLiveFeatures } from './features.js';\nimport { HELP_TOPICS, buildHelpLinks } from './help-links.js';\n\n// @vid-master/config - Essential shared configuration\n\n/**\n * Environment Detection\n * Automatically detects dev/localhost vs production\n */\nconst isServer = typeof window === 'undefined';\nconst isBrowser = typeof window !== 'undefined';\n\n// Detect localhost/development environment\nconst isLocalhost = isBrowser && (\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1' ||\n window.location.hostname.includes('local')\n);\n\nconst isDevelopment = isServer\n ? process.env.NODE_ENV !== 'production'\n : isLocalhost;\n\nexport const ENV = {\n isDevelopment,\n isProduction: !isDevelopment,\n isLocalhost: isDevelopment, // alias for clarity\n};\n\n/**\n * Cookie domain for cross-subdomain auth & tracking\n * undefined in dev (browsers reject explicit domain on localhost)\n * .clipform.io in production (covers www., app., and apex)\n */\nexport const COOKIE_DOMAIN = ENV.isDevelopment ? undefined : '.clipform.io';\n\n/**\n * Browser is accessing the app via the Cloudflare dev tunnel\n * (e.g. dashboard-dev.smith-forge.com → routes to local Next.js).\n * In that case browser fetches must use the matching tunnel hostnames,\n * because the browser cannot reach localhost on the dev's machine.\n */\nconst isTunnelBrowser = isBrowser &&\n window.location.hostname.endsWith('.smith-forge.com');\n\nfunction getUrls() {\n if (isTunnelBrowser) {\n return {\n marketing: 'https://marketing-dev.smith-forge.com',\n dashboard: 'https://dashboard-dev.smith-forge.com',\n viewer: 'https://viewer-dev.smith-forge.com',\n api: 'https://api-dev.smith-forge.com',\n mcp: 'https://api-dev.smith-forge.com/mcp',\n docs: 'https://clipform.io/docs',\n };\n }\n\n if (ENV.isDevelopment) {\n // Per-worktree overrides: a parallel worktree can run its own full stack on\n // a distinct port block by setting NEXT_PUBLIC_*_URL in its .env.local (plus\n // a matching `-p` / PORT). Without these the apps resolve each other at the\n // base ports below and would cross-wire to another worktree's servers.\n // Direct `process.env.NEXT_PUBLIC_*` reads (not destructured) so Next inlines\n // them into client bundles - every app that imports this package client-side\n // transpiles it (see each app's next.config transpilePackages).\n const api = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3003';\n return {\n marketing: process.env.NEXT_PUBLIC_MARKETING_URL || 'http://localhost:3002',\n dashboard: process.env.NEXT_PUBLIC_DASHBOARD_URL || 'http://localhost:3000',\n viewer: process.env.NEXT_PUBLIC_VIEWER_URL || 'http://localhost:3001',\n api,\n // No separate MCP host in dev - tools live on the api subpath.\n mcp: api + '/mcp',\n // The docs app serves under basePath /docs (matching prod\n // clipform.io/docs), so the dev URL must include it too.\n docs: process.env.NEXT_PUBLIC_DOCS_URL || 'http://localhost:3004/docs',\n };\n }\n\n return {\n marketing: 'https://www.clipform.io',\n dashboard: 'https://app.clipform.io',\n viewer: 'https://clipform.io',\n api: 'https://api.clipform.io',\n // Dedicated subdomain for the remote MCP server. Same Render service\n // as `api`, just routed by Host header. Token audience is bound here.\n mcp: 'https://mcp.clipform.io',\n docs: 'https://clipform.io/docs',\n };\n}\n\n/**\n * Core business information - UPDATE THESE AS NEEDED\n */\nexport const BUSINESS = {\n name: \"Clipform\",\n tagline: \"Video-Driven Form Builder\",\n description:\n \"Create engaging forms that combine video content with interactive questions. Capture authentic responses with text, audio, or video recordings.\",\n shortDescription:\n \"Interactive video forms that capture authentic responses. Build engaging forms in minutes.\",\n domain: \"clipform.io\",\n email: {\n support: \"support@clipform.io\",\n sales: \"sales@clipform.io\",\n hello: \"hello@clipform.io\",\n },\n phone: \"+1 (555) 123-4567\",\n urls: getUrls(),\n};\n\n/**\n * In-product \"Learn more\" deep-links (#394) - single source of truth, keyed\n * by concept. Anchors are CI-checked against real docs headings\n * (apps/docs/scripts/check-help-links.mjs). Never hardcode docs URLs in UI.\n */\nexport const HELP_LINKS = buildHelpLinks(BUSINESS.urls.docs);\nexport { HELP_TOPICS };\n\n/** URL builders — single source of truth for public-facing links */\nexport function viewerUrl(shareId) {\n return `${BUSINESS.urls.viewer}/${shareId}`;\n}\nexport function formUrl(shareId) {\n return `${BUSINESS.urls.dashboard}/save/${shareId}`;\n}\n\n/**\n * Brand assets and visual identity\n */\nexport const BRAND = {\n logo: {\n primary: \"/logo.svg\",\n withText: \"/logo_text.svg\",\n icon: \"/favicon.ico\",\n iconSvg: \"/icon.svg\",\n appleTouchIcon: \"/apple-touch-icon.png\",\n minWidth: \"120px\",\n maxWidth: \"200px\",\n spacing: \"16px\",\n },\n colors: {\n primary: \"#171717\",\n secondary: \"#404040\",\n accent: \"#3182CE\",\n background: \"#FAFAFA\",\n surface: \"#FFFFFF\",\n border: \"#E5E5E5\",\n muted: \"#737373\",\n },\n fonts: {\n body: \"Inter, sans-serif\",\n headings: \"'Satoshi', Inter, sans-serif\",\n logo: \"'Plus Jakarta Sans', sans-serif\",\n satoshiImport: \"https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&display=swap\",\n },\n /** HSL design tokens for CSS variable overrides */\n hsl: {\n background: \"0 0% 98%\",\n foreground: \"0 0% 25%\",\n muted: \"0 0% 96%\",\n mutedForeground: \"0 0% 45%\",\n popover: \"0 0% 100%\",\n popoverForeground: \"0 0% 9%\",\n card: \"0 0% 100%\",\n cardForeground: \"0 0% 9%\",\n border: \"0 0% 90%\",\n primary: \"0 0% 9%\",\n primaryForeground: \"0 0% 98%\",\n secondary: \"0 0% 96%\",\n secondaryForeground: \"0 0% 9%\",\n accent: \"0 0% 96%\",\n accentForeground: \"0 0% 9%\",\n ring: \"0 0% 64%\",\n darkBackground: \"0 0% 6%\",\n darkForeground: \"0 0% 92%\",\n darkMuted: \"0 0% 12%\",\n darkMutedForeground: \"0 0% 64%\",\n darkPopover: \"0 0% 8%\",\n darkPopoverForeground: \"0 0% 92%\",\n darkCard: \"0 0% 8%\",\n darkCardForeground: \"0 0% 98%\",\n darkBorder: \"0 0% 16%\",\n darkPrimary: \"0 0% 98%\",\n darkPrimaryForeground: \"0 0% 9%\",\n darkSecondary: \"0 0% 14%\",\n darkSecondaryForeground: \"0 0% 98%\",\n darkAccent: \"0 0% 16%\",\n darkAccentForeground: \"0 0% 92%\",\n darkRing: \"0 0% 30%\",\n },\n};\n\n/**\n * Plan limits — shared between API (enforcement), dashboard (UI gating), and viewer (branding)\n *\n * Keyed by plan_version string (e.g. 'free_v1', 'pro_v1') so we can\n * grandfather old limits when pricing changes. New signups get the version\n * from CURRENT_PLAN_VERSIONS; existing companies keep theirs until\n * explicitly migrated.\n */\nexport const PLAN_LIMITS = {\n free_v1: {\n tier: 0,\n name: 'Free',\n price: '$0',\n period: 'forever',\n stripe_price_id: { test: null, live: null },\n node_limit: null,\n form_limit: 5,\n show_branding: true,\n custom_theme: false,\n response_limit: 100,\n features: [\n 'Up to 5 forms',\n 'Unlimited questions per form',\n '100 responses per month',\n 'Full AI tooling (TTS, media, video)',\n 'Clipform branding',\n ],\n },\n free_internal_v1: {\n tier: 0,\n name: 'Free (Internal)',\n price: '$0',\n period: 'forever',\n stripe_price_id: { test: null, live: null },\n node_limit: null,\n form_limit: null,\n show_branding: true,\n custom_theme: false,\n response_limit: null,\n features: [\n 'Unlimited questions',\n 'Unlimited forms',\n 'Unlimited responses',\n 'Video integration',\n 'Clipform branding',\n ],\n },\n pro_v1: {\n tier: 1,\n name: 'Pro',\n price: '$25',\n period: '/month',\n stripe_price_id: { test: 'price_1TZnmhCWdEPD0KoNWWJTc3B6', live: 'price_1TZnrZEJOD9ik3LhhFwGZ6ut' },\n node_limit: null,\n form_limit: null,\n show_branding: false,\n custom_theme: true,\n response_limit: null,\n features: [\n 'Unlimited forms',\n 'Unlimited questions',\n 'Unlimited responses',\n 'Custom themes & colors',\n 'Remove Clipform branding',\n ],\n },\n};\n\n/** Maps tier integer → version string assigned to new signups */\nexport const CURRENT_PLAN_VERSIONS = { 0: 'free_v1', 1: 'pro_v1' };\n\n/**\n * Product information and features\n */\nexport const PRODUCT = {\n features: {\n get core() {\n return getLiveFeatures()\n .filter(f => ['node-types', 'responses', 'builder', 'analytics', 'ai'].includes(f.category))\n .map(f => f.name);\n },\n get premium() {\n return getLiveFeatures()\n .filter(f => ['sharing', 'api'].includes(f.category))\n .map(f => f.name);\n },\n },\n // Derived from PLAN_LIMITS (source of truth)\n get pricing() {\n const free = PLAN_LIMITS[CURRENT_PLAN_VERSIONS[0]];\n const pro = PLAN_LIMITS[CURRENT_PLAN_VERSIONS[1]];\n return {\n free: { name: free.name, price: free.price, period: free.period, features: free.features },\n pro: { name: pro.name, price: pro.price, period: pro.period, features: pro.features },\n };\n },\n};\n\n/**\n * Social media links\n */\nexport const SOCIAL = {\n twitter: \"@clipform\",\n linkedin: \"company/clipform\",\n github: \"clipform\",\n urls: {\n twitter: \"https://twitter.com/clipform\",\n linkedin: \"https://linkedin.com/company/clipform\",\n github: \"https://github.com/clipform\",\n },\n};\n\n/**\n * Legal and compliance\n */\nexport const LEGAL = {\n company: \"Reco Ventures Ltd.\",\n copyright: \"© 2026 Clipform. All rights reserved.\",\n privacy: \"/privacy\",\n terms: \"/terms\",\n};\n\n/**\n * Standard contact form field definitions\n * Source of truth for both dashboard (field picker) and viewer (form rendering)\n */\nexport const CONTACT_FIELDS = [\n { id: 'first_name', label: 'First Name', type: 'text', placeholder: 'Enter first name', order: 1 },\n { id: 'last_name', label: 'Last Name', type: 'text', placeholder: 'Enter last name', order: 2 },\n { id: 'email', label: 'Email Address', type: 'email', placeholder: 'you@example.com', order: 3 },\n { id: 'phone', label: 'Phone Number', type: 'tel', placeholder: '(555) 123-4567', order: 4 },\n];\n\nexport const CONTACT_FIELDS_MAP = Object.fromEntries(\n CONTACT_FIELDS.map(f => [f.id, f])\n);\n\n/**\n * Node type definitions — re-exported from node-types.js\n */\nexport {\n NODE_TYPES,\n NODE_TYPES_LIST,\n NODE_TYPE_KEYS,\n NODE_TYPE_METADATA,\n RESPONSE_SCHEMAS,\n CONFIG_SCHEMAS,\n OUTPUT_SCHEMAS,\n TERMINAL_TYPES,\n NON_COUNTABLE_TYPES,\n NON_COUNTABLE_FILTER,\n RESULTS_EXCLUDED_TYPES,\n isTerminalType,\n} from './node-types.js';\n\nexport {\n validateAgainstSchema,\n validateConfig,\n validateOptions,\n validateResponse,\n validateOutput,\n} from './validate.js';\n\nexport { FEATURE_FLAGS, FEATURES, getLiveFeatures, getPlannedFeatures, getFeaturesByCategory } from './features.js';\n\nexport { ANALYTICS_METRICS, ANALYTICS_INVARIANTS, ANALYTICS_BREAKDOWNS, ANALYTICS_FUNNEL_ORDER, getMetricLabel } from './analytics.js';\n\n/**\n * Form type definitions — re-exported from form-types.js\n */\nexport {\n FORM_TYPES,\n FORM_TYPES_LIST,\n FORM_TYPE_KEYS,\n WORKFLOW_TYPES,\n FORM_TYPE_ALIASES,\n ALL_VARIANTS,\n resolveFormType,\n getDiscoveryParams,\n isFormTypeAvailable,\n getAvailableFormTypes,\n} from './form-types.js';\n\nexport { validateFormForPublish } from './graph-validation.js';\n\n/**\n * Node logic grammar constants — re-exported from logic-types.js\n */\nexport {\n LOGIC_ACTION_TYPES,\n LOGIC_CONDITION_OPS,\n LOGIC_VAR_TYPES,\n LOGIC_TARGET_TYPES,\n} from './logic-types.js';\n\n/**\n * Integration catalog definitions — re-exported from integration-catalog.js\n */\nexport {\n INTEGRATION_CATALOG,\n INTEGRATION_CATALOG_LIST,\n INTEGRATION_SLUGS,\n getIntegrationsByCategory,\n getIntegrationsByTags,\n} from './integration-catalog.js';\n\n/**\n * API key prefixes — shared between API (validation) and dashboard (generation)\n */\nexport const API_KEY_PREFIXES = ['cf_', 'cf_live_', 'cf_test_'];\nexport const API_KEY_PREFIX = 'cf_';\n\n/**\n * Input validation limits — shared between API routes and MCP server\n */\nexport const VALIDATION_LIMITS = {\n form: {\n title: { max: 1000 },\n nodes: { max: 100 },\n },\n node: {\n prompt: { max: 5000, media_max: 60 },\n options: { max: 50 },\n },\n};\n\n/**\n * Theme defaults and colour validation — single source of truth\n * All colours must be 6-digit hex (#RRGGBB). No rgba, no shorthand.\n */\nexport const HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;\n\nexport const THEME_DEFAULTS = {\n primary_color: '#374151',\n background_color: '#F3F4F6',\n font_family: 'Inter',\n};\n\n/**\n * AI-protected form fields — fields the AI must NOT set unless the user\n * explicitly requests it. Everything else is AI-mutable (set freely).\n *\n * Used by MCP tools to guard descriptions and omit defaults.\n */\nexport const AI_PROTECTED_FIELDS = {\n font_family: {\n reason: 'Brand/design decision — do not set unless the user explicitly requests a different font.',\n },\n author: {\n reason: 'Brand identity — do not invent. Only set when the user provides a value.',\n },\n brand_name: {\n reason: 'Brand identity — do not invent. Only set when the user provides a value.',\n },\n logo_url: {\n reason: 'Brand identity — do not invent. Only set when the user provides a value.',\n },\n is_live: {\n reason: 'Going live is a deliberate action. Never auto-publish unless the user asks.',\n },\n};\n\n/**\n * Ken Burns / Slideshow constants — single source of truth.\n * Used by Remotion compositions, API slideshow route, and MCP tools.\n */\nexport const KEN_BURNS_EFFECTS = [\n 'pan-left',\n 'pan-right',\n 'pan-up',\n 'pan-down',\n 'zoom-in-pan-left',\n 'zoom-in-pan-right',\n 'zoom-in',\n 'zoom-out',\n 'static',\n];\n\nexport const KEN_BURNS_PRESETS = [\n 'cinematic',\n 'dramatic',\n 'calm',\n 'documentary',\n 'dreamy',\n 'moody',\n];\n\nexport const KEN_BURNS_EASINGS = ['ease-in-out', 'ease-in', 'ease-out', 'linear'];\n\nexport const KEN_BURNS_FIT_MODES = ['cover', 'blur-pad', 'auto'];\n\nexport const SLIDESHOW_TRANSITIONS = [\n 'fade',\n 'fadeblack',\n 'fadewhite',\n 'slideleft',\n 'slideright',\n 'circlecrop',\n 'circleopen',\n 'circleclose',\n 'dissolve',\n 'pixelize',\n 'radial',\n 'smoothleft',\n 'smoothright',\n 'wipeleft',\n 'wiperight',\n 'diagtl',\n 'diagbr',\n 'hblur',\n];\n\n/**\n * Composition IDs that require a Mapbox access token.\n */\nexport const MAP_COMPOSITIONS = ['GlobeToCity', 'CityToGlobe'];\n","const telemetryEnabled =\n process.env.DO_NOT_TRACK !== \"1\" &&\n process.env.CLIPFORM_TELEMETRY !== \"off\";\n\nlet mcpVersion = \"unknown\";\n\nexport function setMcpVersion(version: string) {\n mcpVersion = version;\n}\n\nfunction getApiBaseUrl(): string | null {\n return process.env.API_URL || null;\n}\n\nexport interface ErrorReport {\n error_type: string;\n error_message: string;\n tool_name?: string;\n status_code?: number;\n api_path?: string;\n}\n\nexport function reportError(report: ErrorReport) {\n if (!telemetryEnabled) return;\n const base = getApiBaseUrl();\n if (!base) return;\n\n const payload = {\n ...report,\n error_message: report.error_message.slice(0, 500),\n mcp_version: mcpVersion,\n runtime: detectRuntime(),\n timestamp: new Date().toISOString(),\n };\n\n fetch(`${base}/v1/telemetry/errors`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(2_000),\n }).catch(() => {});\n}\n\nexport function isServerFault(status: number): boolean {\n return status >= 500;\n}\n\nfunction detectRuntime(): string {\n if (process.env.CLAUDE_CODE) return \"claude-code\";\n if (process.env.CURSOR_SESSION_ID) return \"cursor\";\n return \"stdio\";\n}\n","import { getMcpAuth } from \"./auth-context.js\";\nimport { reportError, isServerFault } from \"./telemetry.js\";\n\nfunction getApiBaseUrl(): string {\n const url = process.env.API_URL;\n if (!url) {\n throw new Error(\n \"API_URL must be set (e.g. http://localhost:3003 or https://api.clipform.io)\"\n );\n }\n return url;\n}\n\n\nfunction getAuthHeaders(): Record<string, string> {\n const authCtx = getMcpAuth();\n const apiKey = authCtx?.api_key || process.env.CLIPFORM_API_KEY;\n if (!apiKey) {\n throw new Error(\"CLIPFORM_API_KEY must be set.\");\n }\n\n return { \"Authorization\": `Bearer ${apiKey}` };\n}\n\ninterface ApiOptions {\n method?: string;\n body?: Record<string, unknown>;\n params?: Record<string, string>;\n timeoutMs?: number;\n}\n\ntype ApiResult =\n | { ok: true; data: Record<string, unknown> }\n | { ok: false; status: number; error: string };\n\nexport async function callApi(\n path: string,\n options: ApiOptions = {}\n): Promise<ApiResult> {\n const { body, params, timeoutMs = 30_000 } = options;\n const method = options.method || (body ? \"POST\" : \"GET\");\n\n const base = getApiBaseUrl();\n const prefix = path.startsWith(\"/internal/\") ? \"\" : \"/v1\";\n let url = `${base}${prefix}${path}`;\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n // Creative endpoints (/internal/*) authenticate with the same Bearer API\n // key as everything else. The X-Service-Secret header the MCP used to send\n // is webhook-trigger auth only and was dropped here (#412 F7).\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...getAuthHeaders(),\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(timeoutMs),\n };\n\n if (body && method !== \"GET\") {\n fetchOptions.body = JSON.stringify(body);\n }\n\n let response: Response;\n try {\n response = await fetch(url, fetchOptions);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n reportError({\n error_type: \"connection_error\",\n error_message: message,\n tool_name: getMcpAuth()?.tool_name,\n api_path: `${prefix}${path}`,\n });\n return {\n ok: false,\n status: 0,\n error: `Failed to connect to API at ${url}.\\n\\nError: ${message}`,\n };\n }\n\n if (response.status === 204) {\n return { ok: true, data: {} };\n }\n\n const data = (await response.json()) as Record<string, unknown>;\n\n if (!response.ok) {\n const errorMsg = (data.error as string) || `API error (${response.status})`;\n if (isServerFault(response.status)) {\n reportError({\n error_type: `http_${response.status}`,\n error_message: errorMsg,\n tool_name: getMcpAuth()?.tool_name,\n status_code: response.status,\n api_path: `${prefix}${path}`,\n });\n }\n return {\n ok: false,\n status: response.status,\n error: errorMsg,\n };\n }\n\n return { ok: true, data };\n}\n\nexport function errorResult(message: string) {\n return {\n content: [{ type: \"text\" as const, text: message }],\n isError: true,\n };\n}\n\nexport function textResult(text: string) {\n return {\n content: [{ type: \"text\" as const, text }],\n };\n}\n","import { BUSINESS } from \"@vid-master/config\";\nimport { callApi } from \"./api-client.js\";\n\nexport type AuthMode = \"authenticated\" | \"anonymous\";\n\nexport interface SessionContextResult {\n text: string;\n authMode: AuthMode;\n}\n\nexport async function getSessionContextWithAuth(): Promise<SessionContextResult> {\n let result;\n try {\n result = await callApi(\"/me\", { method: \"GET\" });\n } catch {\n return { text: \"\", authMode: \"anonymous\" };\n }\n if (!result.ok) return { text: \"\", authMode: \"anonymous\" };\n\n const me = result.data as any;\n // The API's auth_mode is \"api_key\" | \"session\" | \"anonymous\". Anything\n // credentialed counts as authenticated - the old `=== \"oauth\"` check\n // matched nothing the API returns, so API-key sessions were labelled\n // anonymous with a \"sign in to unlock\" nudge right next to their real\n // plan (#412 F6).\n const apiAuthMode: string = (me.auth_mode as string) ?? \"anonymous\";\n const authMode: AuthMode = apiAuthMode === \"anonymous\" ? \"anonymous\" : \"authenticated\";\n const plan = me.plan;\n const lines: string[] = [];\n\n lines.push(\"## Your Session\");\n if (authMode === \"authenticated\") {\n lines.push(\n apiAuthMode === \"api_key\"\n ? \"Auth: API key (workspace-scoped)\"\n : \"Auth: signed in (connected to a Clipform account)\"\n );\n lines.push(`Workspace: ${me.workspace?.name ?? \"Unknown\"} (${me.workspace?.id ?? \"?\"})`);\n if (me.user_id) lines.push(`User: ${me.user_id}`);\n if (me.company_id) lines.push(`Company: ${me.company_id}`);\n } else {\n lines.push(\"Auth: anonymous (not connected to a Clipform account)\");\n if (me.workspace) {\n lines.push(`Workspace: ${me.workspace.name} (${me.workspace.id})`);\n }\n }\n lines.push(`Plan: ${plan.name} (tier ${plan.tier})`);\n if (plan.node_limit !== null) {\n lines.push(`Question limit: ${plan.node_limit} per form`);\n } else {\n lines.push(\"Questions: unlimited\");\n }\n if (plan.form_limit !== null) {\n lines.push(`Form limit: ${plan.form_limit} forms`);\n } else {\n lines.push(\"Forms: unlimited\");\n }\n if (plan.custom_theme === false) {\n lines.push(\"Custom themes: not available on this plan\");\n }\n if (authMode === \"anonymous\") {\n lines.push(`\\nTo unlock your full plan: sign in to your Clipform account.`);\n }\n\n return { text: lines.join(\"\\n\"), authMode };\n}\n\nexport async function getSessionContext(): Promise<string> {\n const { text } = await getSessionContextWithAuth();\n return text;\n}\n"],"mappings":"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","names":["getApiBaseUrl"]}
|