@clipform/mcp-server 1.23.0 → 1.24.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/dist/{chunk-ZJJBZGO6.js → chunk-2AQPZWXG.js} +3 -2
- package/dist/chunk-2AQPZWXG.js.map +1 -0
- package/dist/{chunk-M3G76QDR.js → chunk-Q4LHGVFQ.js} +26 -99
- package/dist/{chunk-M3G76QDR.js.map → chunk-Q4LHGVFQ.js.map} +1 -1
- package/dist/{chunk-4EXXG7OF.js → chunk-ZFJGTESI.js} +23 -9
- package/dist/chunk-ZFJGTESI.js.map +1 -0
- package/dist/{chunk-UW6HXM2U.js → chunk-ZVBCKXPT.js} +2 -2
- 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-4EXXG7OF.js.map +0 -1
- package/dist/chunk-ZJJBZGO6.js.map +0 -1
- /package/dist/{chunk-UW6HXM2U.js.map → chunk-ZVBCKXPT.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
ALL_VARIANTS,
|
|
3
3
|
FORM_TYPE_KEYS,
|
|
4
4
|
getSessionContext
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZFJGTESI.js";
|
|
6
6
|
|
|
7
7
|
// src/resources.ts
|
|
8
8
|
var GUIDE_TYPES = FORM_TYPE_KEYS;
|
|
@@ -37,6 +37,7 @@ var MEDIA_WORKFLOW = `## Media Workflow
|
|
|
37
37
|
|
|
38
38
|
**Image selection:**
|
|
39
39
|
- ONLY use URLs from clipform_search_media results
|
|
40
|
+
- ALL returned images are pre-cleared for commercial use - pick by visual quality, not by provider or license
|
|
40
41
|
- Search for the specific subject, not generic terms
|
|
41
42
|
- Pick visually distinct images (different angles, colors, subjects)
|
|
42
43
|
- Landscape images work best for pan effects
|
|
@@ -533,4 +534,4 @@ export {
|
|
|
533
534
|
getGuideUri,
|
|
534
535
|
registerResources
|
|
535
536
|
};
|
|
536
|
-
//# sourceMappingURL=chunk-
|
|
537
|
+
//# sourceMappingURL=chunk-2AQPZWXG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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)\n2. **clipform_search_media** (kind: \"image\") - find 3 images per question\n3. **clipform_generate_video** - Ken Burns video from images + audio\n4. **clipform_upload_node_media** - attach video with captions (set show_captions: true)\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- Search for the specific subject, not generic terms\n- Pick visually distinct images (different angles, colors, subjects)\n- Landscape images work best for pan effects\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- **Randomize correct answer position** - never put the correct answer in the same slot for every question. Vary it across A/B/C/D so there's no pattern to guess.\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":";;;;;;;AAIO,IAAM,cAAc;AAGpB,IAAM,gBAAgB;AAG7B,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsB3B,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBvB,IAAM,qBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,aAAa;AAAA,EACb,UAAU;AAAA,EACV,eAAe;AAAA,EACf,eAAe;AAAA,EACf,WAAW;AACb;AAEA,IAAM,4BAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,iBAAiB;AACnB;AAEA,IAAM,gBAA2C;AAAA,EAC/C,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuER,kBAAkB;AAAA;AAAA,EAElB,cAAc;AAAA,EAEd,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCV,kBAAkB;AAAA,EAElB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCb,kBAAkB;AAAA;AAAA,EAElB,cAAc;AAAA,EAEd,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAMV,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiDf,kBAAkB;AAAA;AAAA,EAElB,cAAc;AAAA,EAEd,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqCf,kBAAkB;AAAA;AAAA,EAElB,cAAc;AAAA,EAEd,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2CX,kBAAkB;AACpB;AAEA,IAAM,sBAAmD;AAAA,EACvD,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+Cf,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDnB;AAEO,SAAS,gBAAgB,MAAiB,SAA+B;AAC9E,QAAM,OAAO,cAAc,IAAI;AAC/B,MAAI,SAAS,UAAU,SAAS;AAC9B,WAAO,OAAO,SAAS,oBAAoB,OAAO;AAAA,EACpD;AACA,SAAO;AACT;AAEO,SAAS,YAAY,MAAiB,SAA+B;AAC1E,MAAI,SAAS,UAAU,SAAS;AAC9B,WAAO,0BAA0B,OAAO;AAAA,EAC1C;AACA,SAAO,qBAAqB,IAAI;AAClC;AAEO,SAAS,kBAAkB,QAAmB;AACnD,aAAW,QAAQ,aAAa;AAC9B,WAAO;AAAA,MACL,SAAS,IAAI;AAAA,MACb,YAAY,IAAI;AAAA,MAChB;AAAA,QACE,aAAa,mBAAmB,IAAI;AAAA,QACpC,UAAU;AAAA,QACV,aAAa,EAAE,UAAU,CAAC,WAAoB,GAAG,UAAU,IAAI;AAAA,MACjE;AAAA,MACA,aAAa;AAAA,QACX,UAAU,CAAC;AAAA,UACT,KAAK,YAAY,IAAI;AAAA,UACrB,UAAU;AAAA,UACV,MAAM,gBAAgB,IAAI;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,eAAe;AACnC,WAAO;AAAA,MACL,cAAc,OAAO;AAAA,MACrB,YAAY,QAAQ,OAAO;AAAA,MAC3B;AAAA,QACE,aAAa,0BAA0B,OAAO;AAAA,QAC9C,UAAU;AAAA,QACV,aAAa,EAAE,UAAU,CAAC,WAAoB,GAAG,UAAU,IAAI;AAAA,MACjE;AAAA,MACA,aAAa;AAAA,QACX,UAAU,CAAC;AAAA,UACT,KAAK,YAAY,QAAQ,OAAO;AAAA,UAChC,UAAU;AAAA,UACV,MAAM,gBAAgB,QAAQ,OAAO;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,UAAU;AAAA,MACV,aAAa,EAAE,UAAU,CAAC,WAAW,GAAG,UAAU,EAAI;AAAA,IACxD;AAAA,IACA,YAAY;AACV,YAAM,OAAO,MAAM,kBAAkB;AACrC,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,KAAK;AAAA,YACL,UAAU;AAAA,YACV,MAAM,QAAQ;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
getWorkflowText,
|
|
7
7
|
objectType,
|
|
8
8
|
registerPrompts
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZVBCKXPT.js";
|
|
10
10
|
import {
|
|
11
11
|
GUIDE_TYPES,
|
|
12
12
|
QUIZ_VARIANTS,
|
|
13
13
|
getGuideContent,
|
|
14
14
|
getGuideUri,
|
|
15
15
|
registerResources
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2AQPZWXG.js";
|
|
17
17
|
import {
|
|
18
18
|
BUSINESS,
|
|
19
19
|
CONTACT_FIELDS,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
errorResult,
|
|
30
30
|
resolveFormType,
|
|
31
31
|
textResult
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ZFJGTESI.js";
|
|
33
33
|
import {
|
|
34
34
|
__commonJS,
|
|
35
35
|
__export,
|
|
@@ -17226,11 +17226,7 @@ function registerListFormsTool(server) {
|
|
|
17226
17226
|
for (const f of data.forms) {
|
|
17227
17227
|
const status = f.is_live ? "live" : "draft";
|
|
17228
17228
|
const tagStr = f.tags.length > 0 ? ` [${f.tags.map((t) => t.name).join(", ")}]` : "";
|
|
17229
|
-
lines.push(`-
|
|
17230
|
-
lines.push(` ID: ${f.id}`);
|
|
17231
|
-
lines.push(` Share ID: ${f.share_id}`);
|
|
17232
|
-
lines.push(` Created: ${f.created_at}`);
|
|
17233
|
-
lines.push("");
|
|
17229
|
+
lines.push(`- ${f.title || "(untitled)"} (${status})${tagStr} \u2014 ${f.id}`);
|
|
17234
17230
|
}
|
|
17235
17231
|
if (data.next_cursor) {
|
|
17236
17232
|
lines.push(
|
|
@@ -17268,11 +17264,6 @@ function formatFormState(data) {
|
|
|
17268
17264
|
}
|
|
17269
17265
|
return lines.join("\n");
|
|
17270
17266
|
}
|
|
17271
|
-
async function fetchAndFormatFormState(formId) {
|
|
17272
|
-
const result = await callApi(`/forms/${formId}`);
|
|
17273
|
-
if (!result.ok) return null;
|
|
17274
|
-
return formatFormState(result.data);
|
|
17275
|
-
}
|
|
17276
17267
|
|
|
17277
17268
|
// src/tools/get-form.ts
|
|
17278
17269
|
function registerGetFormTool(server) {
|
|
@@ -17385,14 +17376,7 @@ function registerUpdateFormTool(server) {
|
|
|
17385
17376
|
updates.push(`Logo URL \u2192 ${logo_url === null ? "cleared" : logo_url}`);
|
|
17386
17377
|
if (tags)
|
|
17387
17378
|
updates.push(`Tags \u2192 [${tags.join(", ")}]`);
|
|
17388
|
-
|
|
17389
|
-
${updates.join("\n")}`;
|
|
17390
|
-
const formState = await fetchAndFormatFormState(form_id);
|
|
17391
|
-
return textResult(formState ? `${confirmMsg}
|
|
17392
|
-
|
|
17393
|
-
---
|
|
17394
|
-
|
|
17395
|
-
${formState}` : confirmMsg);
|
|
17379
|
+
return textResult(`Form updated: ${updates.join(", ")}`);
|
|
17396
17380
|
}
|
|
17397
17381
|
);
|
|
17398
17382
|
}
|
|
@@ -17462,18 +17446,9 @@ function registerAddNodeTool(server) {
|
|
|
17462
17446
|
if (!result.ok) {
|
|
17463
17447
|
return errorResult(result.error);
|
|
17464
17448
|
}
|
|
17465
|
-
|
|
17466
|
-
`Node added
|
|
17467
|
-
|
|
17468
|
-
`Type: ${node.type}`,
|
|
17469
|
-
`Prompt: ${node.prompt}`
|
|
17470
|
-
].join("\n");
|
|
17471
|
-
const formState = await fetchAndFormatFormState(form_id);
|
|
17472
|
-
return textResult(formState ? `${confirmMsg}
|
|
17473
|
-
|
|
17474
|
-
---
|
|
17475
|
-
|
|
17476
|
-
${formState}` : confirmMsg);
|
|
17449
|
+
return textResult(
|
|
17450
|
+
`Node added. ID: ${result.data.node_id} | Type: ${node.type}`
|
|
17451
|
+
);
|
|
17477
17452
|
}
|
|
17478
17453
|
);
|
|
17479
17454
|
}
|
|
@@ -17535,13 +17510,7 @@ function registerUpdateNodeTool(server) {
|
|
|
17535
17510
|
changes.push(`Options \u2192 ${options.map((o) => o.content).join(", ")}`);
|
|
17536
17511
|
allLines.push(`Node ${node_id} updated: ${changes.join(", ")}`);
|
|
17537
17512
|
}
|
|
17538
|
-
|
|
17539
|
-
const formState = await fetchAndFormatFormState(form_id);
|
|
17540
|
-
return textResult(formState ? `${confirmMsg}
|
|
17541
|
-
|
|
17542
|
-
---
|
|
17543
|
-
|
|
17544
|
-
${formState}` : confirmMsg);
|
|
17513
|
+
return textResult(allLines.join("\n"));
|
|
17545
17514
|
}
|
|
17546
17515
|
);
|
|
17547
17516
|
}
|
|
@@ -17572,13 +17541,7 @@ function registerDeleteNodeTool(server) {
|
|
|
17572
17541
|
if (!result.ok) {
|
|
17573
17542
|
return errorResult(result.error);
|
|
17574
17543
|
}
|
|
17575
|
-
|
|
17576
|
-
const formState = await fetchAndFormatFormState(form_id);
|
|
17577
|
-
return textResult(formState ? `${confirmMsg}
|
|
17578
|
-
|
|
17579
|
-
---
|
|
17580
|
-
|
|
17581
|
-
${formState}` : confirmMsg);
|
|
17544
|
+
return textResult(`Node ${node_id} deleted.`);
|
|
17582
17545
|
}
|
|
17583
17546
|
);
|
|
17584
17547
|
}
|
|
@@ -17703,13 +17666,12 @@ function registerGetNodeMediaTool(server) {
|
|
|
17703
17666
|
return textResult("No media attached to this node.");
|
|
17704
17667
|
}
|
|
17705
17668
|
return textResult(
|
|
17706
|
-
|
|
17707
|
-
Type: ${media.media_type}
|
|
17708
|
-
Status: ${media.status}
|
|
17709
|
-
|
|
17710
|
-
`
|
|
17711
|
-
|
|
17712
|
-
` : "") + `Transcription: ${media.transcription_status}`
|
|
17669
|
+
[
|
|
17670
|
+
`Type: ${media.media_type}`,
|
|
17671
|
+
`Status: ${media.status}`,
|
|
17672
|
+
media.duration ? `Duration: ${media.duration}s` : "",
|
|
17673
|
+
`Transcription: ${media.transcription_status}`
|
|
17674
|
+
].filter(Boolean).join("\n")
|
|
17713
17675
|
);
|
|
17714
17676
|
}
|
|
17715
17677
|
);
|
|
@@ -17777,10 +17739,7 @@ function registerAttachNodeAudioTool(server) {
|
|
|
17777
17739
|
if (!result.ok) {
|
|
17778
17740
|
return errorResult(result.error);
|
|
17779
17741
|
}
|
|
17780
|
-
return textResult(
|
|
17781
|
-
`Audio attached to node ${node_id}.
|
|
17782
|
-
Audio path: ${result.data.audio_storage_path}`
|
|
17783
|
-
);
|
|
17742
|
+
return textResult(`Audio attached to node ${node_id}.`);
|
|
17784
17743
|
}
|
|
17785
17744
|
);
|
|
17786
17745
|
}
|
|
@@ -17837,13 +17796,7 @@ Example:
|
|
|
17837
17796
|
}
|
|
17838
17797
|
allLines.push(`Node ${node_id}: logic set (${result.data.rules_count} rules)`);
|
|
17839
17798
|
}
|
|
17840
|
-
|
|
17841
|
-
const formState = await fetchAndFormatFormState(form_id);
|
|
17842
|
-
return textResult(formState ? `${confirmMsg}
|
|
17843
|
-
|
|
17844
|
-
---
|
|
17845
|
-
|
|
17846
|
-
${formState}` : confirmMsg);
|
|
17799
|
+
return textResult(allLines.join("\n"));
|
|
17847
17800
|
}
|
|
17848
17801
|
);
|
|
17849
17802
|
}
|
|
@@ -18015,9 +17968,7 @@ Pass one item or many (max 10) - multiple items run in parallel. Returns audio U
|
|
|
18015
17968
|
if (r.status === "fulfilled" && r.value.ok) {
|
|
18016
17969
|
successCount++;
|
|
18017
17970
|
const data = r.value.data;
|
|
18018
|
-
lines.push(`Voice: ${data.voice}`);
|
|
18019
17971
|
lines.push(`Audio URL: ${data.audioUrl}`);
|
|
18020
|
-
lines.push(`Storage path: ${data.storagePath}`);
|
|
18021
17972
|
lines.push(`Captions: ${JSON.stringify(data.captions)}`);
|
|
18022
17973
|
} else {
|
|
18023
17974
|
const error2 = r.status === "rejected" ? r.reason?.message || String(r.reason) : r.value.error;
|
|
@@ -18031,9 +17982,7 @@ Pass one item or many (max 10) - multiple items run in parallel. Returns audio U
|
|
|
18031
17982
|
lines.unshift(`TTS: ${successCount}/${items.length} succeeded
|
|
18032
17983
|
`);
|
|
18033
17984
|
}
|
|
18034
|
-
lines.push(
|
|
18035
|
-
`IMPORTANT: When uploading the final video with clipform_upload_node_media, pass the COMPLETE Captions JSON above as the "captions" parameter \u2014 including the "words" arrays inside each segment. Do NOT strip or simplify the JSON. The viewer needs word-level timing data to display captions.`
|
|
18036
|
-
);
|
|
17985
|
+
lines.push(`Pass the complete Captions JSON as the "captions" parameter when uploading.`);
|
|
18037
17986
|
if (successCount === 0) return errorResult(lines.join("\n"));
|
|
18038
17987
|
return textResult(lines.join("\n"));
|
|
18039
17988
|
}
|
|
@@ -18046,7 +17995,7 @@ function registerSearchMediaTool(server) {
|
|
|
18046
17995
|
"clipform_search_media",
|
|
18047
17996
|
{
|
|
18048
17997
|
title: "Search Media",
|
|
18049
|
-
description: `Search
|
|
17998
|
+
description: `Search images or stock video clips. Pass one query or many (max 10) - multiple queries run in one call instead of separate tool calls. Use results to feed into clipform_generate_video for narrated slideshow videos, or upload directly as still images via clipform_upload_node_media. All results are pre-cleared for commercial use.`,
|
|
18050
17999
|
inputSchema: {
|
|
18051
18000
|
queries: external_exports.array(
|
|
18052
18001
|
external_exports.object({
|
|
@@ -18077,12 +18026,10 @@ function registerSearchMediaTool(server) {
|
|
|
18077
18026
|
allLines.push(`Found ${results.length} ${kind}s:
|
|
18078
18027
|
`);
|
|
18079
18028
|
for (const item of results.slice(0, 10)) {
|
|
18080
|
-
allLines.push(`-
|
|
18029
|
+
allLines.push(`- ${item.title}`);
|
|
18081
18030
|
allLines.push(` URL: ${item.url}`);
|
|
18082
18031
|
if (item.width && item.height) allLines.push(` Size: ${item.width}x${item.height}`);
|
|
18083
18032
|
if (kind === "video" && item.duration) allLines.push(` Duration: ${item.duration}s`);
|
|
18084
|
-
if (item.attribution) allLines.push(` Attribution: ${item.attribution}`);
|
|
18085
|
-
if (item.license) allLines.push(` License: ${item.license}`);
|
|
18086
18033
|
allLines.push("");
|
|
18087
18034
|
}
|
|
18088
18035
|
}
|
|
@@ -18122,16 +18069,7 @@ For narrated Ken Burns slideshows from images, use clipform_generate_video inste
|
|
|
18122
18069
|
if (!result.ok) return errorResult(result.error);
|
|
18123
18070
|
const data = result.data;
|
|
18124
18071
|
return textResult(
|
|
18125
|
-
|
|
18126
|
-
`Render complete.`,
|
|
18127
|
-
``,
|
|
18128
|
-
`Composition: ${compositionId}`,
|
|
18129
|
-
`Format: ${data.format || outputFormat}`,
|
|
18130
|
-
`Public URL: ${data.public_url}`,
|
|
18131
|
-
`Storage path: ${data.storage_path}`,
|
|
18132
|
-
``,
|
|
18133
|
-
`Use clipform_upload_node_media with the public URL to attach to a node.`
|
|
18134
|
-
].join("\n")
|
|
18072
|
+
`Render complete. Public URL: ${data.public_url}`
|
|
18135
18073
|
);
|
|
18136
18074
|
}
|
|
18137
18075
|
);
|
|
@@ -18314,12 +18252,8 @@ Items: type "image" (Ken Burns motion) or "video" (cover-cropped, muted by defau
|
|
|
18314
18252
|
return textResult(
|
|
18315
18253
|
[
|
|
18316
18254
|
`Video rendered (${items.length} item${items.length > 1 ? "s" : ""}).`,
|
|
18317
|
-
``,
|
|
18318
18255
|
`Public URL: ${data.public_url}`,
|
|
18319
|
-
`
|
|
18320
|
-
data.duration_seconds ? `Duration: ${data.duration_seconds}s` : "",
|
|
18321
|
-
``,
|
|
18322
|
-
`Use clipform_upload_node_media with the public URL to attach to a node.`
|
|
18256
|
+
data.duration_seconds ? `Duration: ${data.duration_seconds}s` : ""
|
|
18323
18257
|
].filter(Boolean).join("\n")
|
|
18324
18258
|
);
|
|
18325
18259
|
}
|
|
@@ -18380,16 +18314,9 @@ Returns the current status and, when complete, the output URL. Typical render ti
|
|
|
18380
18314
|
const data = job.result;
|
|
18381
18315
|
return textResult(
|
|
18382
18316
|
[
|
|
18383
|
-
`
|
|
18384
|
-
`Tool: ${job.tool}`,
|
|
18385
|
-
``,
|
|
18317
|
+
`Render complete.`,
|
|
18386
18318
|
...data.public_url ? [`Public URL: ${data.public_url}`] : [],
|
|
18387
|
-
...data.
|
|
18388
|
-
...data.duration_seconds ? [`Duration: ${data.duration_seconds}s`] : [],
|
|
18389
|
-
...data.outputPath ? [`Output: ${data.outputPath}`] : [],
|
|
18390
|
-
...data.format ? [`Format: ${data.format}`] : [],
|
|
18391
|
-
``,
|
|
18392
|
-
`Use clipform_upload_node_media with the public URL to attach this video to a node.`
|
|
18319
|
+
...data.duration_seconds ? [`Duration: ${data.duration_seconds}s`] : []
|
|
18393
18320
|
].join("\n")
|
|
18394
18321
|
);
|
|
18395
18322
|
}
|
|
@@ -18685,4 +18612,4 @@ export {
|
|
|
18685
18612
|
JSONRPCMessageSchema,
|
|
18686
18613
|
createServer
|
|
18687
18614
|
};
|
|
18688
|
-
//# sourceMappingURL=chunk-
|
|
18615
|
+
//# sourceMappingURL=chunk-Q4LHGVFQ.js.map
|