@clipform/mcp-server 1.48.0 → 2.0.1
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 +5 -2
- package/dist/{chunk-WUORO245.js → chunk-DDBQDDOK.js} +3 -3
- package/dist/chunk-DDBQDDOK.js.map +1 -0
- package/dist/{chunk-4CY5EJCR.js → chunk-ET43M6YO.js} +95 -53
- package/dist/chunk-ET43M6YO.js.map +1 -0
- package/dist/{chunk-BBNREY2Q.js → chunk-PNAMVSVO.js} +14 -14
- package/dist/{chunk-BBNREY2Q.js.map → chunk-PNAMVSVO.js.map} +1 -1
- package/dist/{chunk-3MTEM3VC.js → chunk-SI4C55U6.js} +620 -122
- package/dist/chunk-SI4C55U6.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/prompts.js +2 -2
- package/dist/resources.js +2 -2
- package/dist/server.d.ts +10 -1
- package/dist/server.js +6 -4
- package/package.json +1 -1
- package/dist/chunk-3MTEM3VC.js.map +0 -1
- package/dist/chunk-4CY5EJCR.js.map +0 -1
- package/dist/chunk-WUORO245.js.map +0 -1
package/README.md
CHANGED
|
@@ -71,7 +71,8 @@ Your MCP client lists these automatically on connect (via `tools/list`). Full re
|
|
|
71
71
|
| `clipform_add_node` | Add a new node to an existing form. |
|
|
72
72
|
| `clipform_update_node` | Update one or more existing nodes' text, type, config, or options. |
|
|
73
73
|
| `clipform_delete_node` | Delete a node from a form. |
|
|
74
|
-
| `
|
|
74
|
+
| `clipform_upload_media_asset` | Put one or more media files into your workspace media library (max 10, uploaded sequentially). |
|
|
75
|
+
| `clipform_attach_node_media` | Attach an existing workspace media asset (from clipform_upload_media_asset) to one or more nodes (max 10). |
|
|
75
76
|
| `clipform_get_node_media` | Get the media attached to a node, including processing status. |
|
|
76
77
|
| `clipform_delete_node_media` | Remove media from a node. |
|
|
77
78
|
| `clipform_set_logic` | Set routing logic on one or more nodes. |
|
|
@@ -84,8 +85,10 @@ Your MCP client lists these automatically on connect (via `tools/list`). Full re
|
|
|
84
85
|
| `clipform_render_composition` | Render a specialised video composition to MP4 or PNG - custom animated visuals that clipform_generate_video can't provide, such as geography animations or designed motion graphics. |
|
|
85
86
|
| `clipform_search_music` | Search for royalty-free music tracks and ambient sounds. |
|
|
86
87
|
| `clipform_list_compositions` | Browse available video compositions and their expected props schemas. |
|
|
88
|
+
| `clipform_list_video_templates` | Browse available video templates - curated Scene arrangements (bed + overlay + sane defaults) that render through the Scene composition from a small controls object. |
|
|
89
|
+
| `clipform_render_video_template` | Render a curated video template (a pre-arranged Scene: bed + overlay + sane defaults) to MP4 or PNG from a small controls object, instead of hand-assembling Scene layers. |
|
|
87
90
|
| `clipform_list_assets` | List available creative assets (sound effects, animations, fonts) for video compositions. |
|
|
88
|
-
| `clipform_check_render` | Check the status of render jobs started by clipform_generate_video or clipform_render_composition. |
|
|
91
|
+
| `clipform_check_render` | Check the status of render jobs started by clipform_generate_video, clipform_render_video_template, or clipform_render_composition. |
|
|
89
92
|
| `clipform_fetch_boundary` | Fetch a GeoJSON boundary polygon for a country, city, or region. |
|
|
90
93
|
| `clipform_get_guide` | Retrieve craft knowledge for building a specific form type. |
|
|
91
94
|
| `clipform_get_workflow` | Retrieve a step-by-step build workflow for creating a specific form type. |
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
FORM_TYPE_KEYS,
|
|
4
4
|
callApi,
|
|
5
5
|
getSessionContext
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ET43M6YO.js";
|
|
7
7
|
|
|
8
8
|
// src/lib/guides.ts
|
|
9
9
|
var guidesPromise = null;
|
|
@@ -57,7 +57,7 @@ var GUIDE_DESCRIPTIONS = {
|
|
|
57
57
|
var QUIZ_VARIANT_DESCRIPTIONS = {
|
|
58
58
|
"personality": "Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers",
|
|
59
59
|
"comprehension": "Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation",
|
|
60
|
-
"composition": "Addendum for composition quizzes - guess
|
|
60
|
+
"composition": "Addendum for composition quizzes - guess formats built from rendered compositions: mechanic selection, the clue clip + answer feedback default (with an optional reveal payoff node), difficulty design"
|
|
61
61
|
};
|
|
62
62
|
function getGuideUri(type, variant) {
|
|
63
63
|
if (type === "quiz" && variant) {
|
|
@@ -136,4 +136,4 @@ export {
|
|
|
136
136
|
getGuideUri,
|
|
137
137
|
registerResources
|
|
138
138
|
};
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-DDBQDDOK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/guides.ts","../src/resources.ts"],"sourcesContent":["import { callApi } from \"./api-client.js\";\n\n/**\n * Craft guide bodies live server-side (#470) - the npm package is a shim\n * that fetches them at runtime instead of bundling them in the tarball.\n * One fetch per process (all ~30KB of guides in a single response), cached;\n * a failed fetch is NOT cached so the next read retries.\n */\n\nexport interface RemoteGuide {\n type: string;\n variant: string | null;\n uri: string;\n mimeType: string;\n text: string;\n}\n\nlet guidesPromise: Promise<Map<string, RemoteGuide>> | null = null;\n\nasync function loadGuides(): Promise<Map<string, RemoteGuide>> {\n const result = await callApi(\"/internal/mcp/guides\", { method: \"GET\" });\n if (!result.ok) {\n throw new Error(`Failed to load guides: ${result.error}`);\n }\n const guides = (result.data as { guides?: RemoteGuide[] }).guides ?? [];\n return new Map(guides.map((g) => [g.uri, g]));\n}\n\n/** Fetch a guide body by its clipform:// URI. Returns null when unavailable. */\nexport async function fetchGuideText(uri: string): Promise<string | null> {\n if (!guidesPromise) {\n guidesPromise = loadGuides();\n }\n try {\n const guides = await guidesPromise;\n return guides.get(uri)?.text ?? null;\n } catch (err) {\n guidesPromise = null; // don't cache failures - retry on the next read\n // Loud, not silent: a misconfigured API_URL/key otherwise degrades every\n // guide to the stub with nothing in the logs.\n console.error(`[guides] Failed to fetch ${uri}: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n/** Shown in place of a guide when the API is unreachable or unauthenticated. */\nexport function guideFallbackText(uri: string): string {\n return [\n `# Guide unavailable`,\n ``,\n `The craft guide (${uri}) could not be loaded from the Clipform API.`,\n `Guides are served at runtime and need a reachable API with a valid key -`,\n `check API_URL and CLIPFORM_API_KEY, then try again.`,\n ``,\n `General principles in the meantime: write narration for the ear (short,`,\n `conversational), never reveal answers in narration or media, and keep`,\n `forms tight - every question must earn its place.`,\n ].join(\"\\n\");\n}\n","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// Guide BODIES are not bundled here (#470): the npm tarball ships only this\n// registration metadata. Text is fetched from the API at runtime - see\n// lib/guides.ts (cached per process, stub fallback when unreachable).\nimport { fetchGuideText, guideFallbackText } from \"./lib/guides.js\";\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 \"composition\": \"Addendum for composition quizzes - guess formats built from rendered compositions: mechanic selection, the clue clip + answer feedback default (with an optional reveal payoff node), difficulty design\",\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\nasync function readGuide(uri: string): Promise<string> {\n return (await fetchGuideText(uri)) ?? guideFallbackText(uri);\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: await readGuide(getGuideUri(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: await readGuide(getGuideUri(\"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":[]}
|
|
@@ -112,8 +112,8 @@ var FEATURES = {
|
|
|
112
112
|
status: "live",
|
|
113
113
|
category: "node-types"
|
|
114
114
|
},
|
|
115
|
-
|
|
116
|
-
name: "
|
|
115
|
+
node_details: {
|
|
116
|
+
name: "Details",
|
|
117
117
|
description: "Structured fields (name, email, phone, company) with consent checkboxes",
|
|
118
118
|
enabled: true,
|
|
119
119
|
status: "live",
|
|
@@ -195,8 +195,9 @@ var FEATURES = {
|
|
|
195
195
|
node_file_download: {
|
|
196
196
|
name: "File download",
|
|
197
197
|
description: "Provide files for respondents to download",
|
|
198
|
-
enabled:
|
|
199
|
-
status: "
|
|
198
|
+
enabled: true,
|
|
199
|
+
status: "live",
|
|
200
|
+
wentLiveAt: "2026-07-12",
|
|
200
201
|
category: "node-types"
|
|
201
202
|
},
|
|
202
203
|
node_shopping: {
|
|
@@ -871,12 +872,12 @@ var NODE_TYPES = {
|
|
|
871
872
|
},
|
|
872
873
|
output_schema: null
|
|
873
874
|
},
|
|
874
|
-
|
|
875
|
-
label: "
|
|
876
|
-
shorthand: "
|
|
875
|
+
details: {
|
|
876
|
+
label: "Details",
|
|
877
|
+
shorthand: "Details",
|
|
877
878
|
icon: "User",
|
|
878
879
|
color: "#CFFAFE",
|
|
879
|
-
description: "Collect
|
|
880
|
+
description: "Collect several fields on one screen - name, email, phone, address, date, and more",
|
|
880
881
|
category: "input",
|
|
881
882
|
sort_order: 5,
|
|
882
883
|
has_options: false,
|
|
@@ -896,9 +897,9 @@ var NODE_TYPES = {
|
|
|
896
897
|
{ id: "first_name", type: "first_name", label: "First Name", enabled: true, required: true },
|
|
897
898
|
{ id: "email", type: "email", label: "Email", enabled: true, required: true }
|
|
898
899
|
],
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
]
|
|
900
|
+
// No agreement out of the box - the builder adds one via "Add agreement"
|
|
901
|
+
// when they actually need consent, so a fresh node ships no orphan checkbox. (#1378)
|
|
902
|
+
consent_items: []
|
|
902
903
|
},
|
|
903
904
|
config_schema: {
|
|
904
905
|
type: "object",
|
|
@@ -913,7 +914,7 @@ var NODE_TYPES = {
|
|
|
913
914
|
required: ["id", "required"],
|
|
914
915
|
properties: {
|
|
915
916
|
id: { type: "string" },
|
|
916
|
-
type: { enum: ["text", "textarea", "email", "tel", "url"], type: "string" },
|
|
917
|
+
type: { enum: ["text", "textarea", "email", "tel", "url", "date", "number"], type: "string" },
|
|
917
918
|
label: { type: "string" },
|
|
918
919
|
order: { type: "number" },
|
|
919
920
|
required: { type: "boolean", default: true },
|
|
@@ -976,7 +977,7 @@ var NODE_TYPES = {
|
|
|
976
977
|
type: "object",
|
|
977
978
|
required: ["node_type", "fields"],
|
|
978
979
|
properties: {
|
|
979
|
-
node_type: { type: "string", const: "
|
|
980
|
+
node_type: { type: "string", const: "details" },
|
|
980
981
|
fields: {
|
|
981
982
|
type: "array",
|
|
982
983
|
items: {
|
|
@@ -1090,13 +1091,14 @@ var NODE_TYPES = {
|
|
|
1090
1091
|
show_nav_bar: true,
|
|
1091
1092
|
loading: "lazy",
|
|
1092
1093
|
supports_prompt: false,
|
|
1093
|
-
supports_media:
|
|
1094
|
+
supports_media: true,
|
|
1094
1095
|
is_system: false,
|
|
1095
1096
|
show_in_results: true,
|
|
1096
1097
|
default_config: {
|
|
1097
1098
|
paper_color: "#FAF9F6",
|
|
1098
1099
|
stroke_colors: ["#1F2937", "#EF4444", "#3B82F6", "#22C55E", "#FACC15"],
|
|
1099
|
-
stroke_widths: [3, 6, 12]
|
|
1100
|
+
stroke_widths: [3, 6, 12],
|
|
1101
|
+
background: { fit: "contain", opacity: 1 }
|
|
1100
1102
|
},
|
|
1101
1103
|
config_schema: {
|
|
1102
1104
|
type: "object",
|
|
@@ -1119,6 +1121,19 @@ var NODE_TYPES = {
|
|
|
1119
1121
|
label: "Pen thicknesses",
|
|
1120
1122
|
default: [3, 6, 12],
|
|
1121
1123
|
description: "Stroke widths (px) the respondent can choose"
|
|
1124
|
+
},
|
|
1125
|
+
// The reference image itself is the node's attached media (media_id,
|
|
1126
|
+
// via the same media_asset/create-media.ts pipeline every other
|
|
1127
|
+
// supports_media node uses) - not a config field, to avoid a
|
|
1128
|
+
// duplicated asset ref. This only tunes its display/bake.
|
|
1129
|
+
background: {
|
|
1130
|
+
type: "object",
|
|
1131
|
+
label: "Background image",
|
|
1132
|
+
description: "Display settings for the optional reference image behind the drawing canvas",
|
|
1133
|
+
properties: {
|
|
1134
|
+
fit: { type: "string", enum: ["cover", "contain"], default: "contain", label: "Fit", description: "contain letterboxes the image, cover crops it to fill the canvas" },
|
|
1135
|
+
opacity: { type: "number", minimum: 0, maximum: 1, default: 1, label: "Opacity", description: "Background image opacity, from 0 (invisible) to 1 (fully opaque)" }
|
|
1136
|
+
}
|
|
1122
1137
|
}
|
|
1123
1138
|
}
|
|
1124
1139
|
},
|
|
@@ -1178,6 +1193,13 @@ var NODE_TYPES = {
|
|
|
1178
1193
|
supports_media: false,
|
|
1179
1194
|
is_system: false,
|
|
1180
1195
|
show_in_results: true,
|
|
1196
|
+
// Config keys that reference a workspace-scoped connected account (Stripe/etc
|
|
1197
|
+
// via workspace_integrations). The SoT for save_form to strip on cross-workspace
|
|
1198
|
+
// copy (#2064 part 2 - migration, not yet wired). Standing convention for any
|
|
1199
|
+
// future OAuth/connected-account node (booking, shopify), not a payment special
|
|
1200
|
+
// case - the publish gate's own showcase waiver (graph-validation.js) still
|
|
1201
|
+
// names workspace_integration_id directly since it's the only per-type check today.
|
|
1202
|
+
connection_config_keys: ["workspace_integration_id"],
|
|
1181
1203
|
default_config: { amount: null, currency: "usd", provider: "stripe" },
|
|
1182
1204
|
config_schema: {
|
|
1183
1205
|
type: "object",
|
|
@@ -1353,7 +1375,7 @@ var NODE_TYPES = {
|
|
|
1353
1375
|
color: "#FFEDD5",
|
|
1354
1376
|
description: "Redirect users to an external URL",
|
|
1355
1377
|
category: "end",
|
|
1356
|
-
sort_order:
|
|
1378
|
+
sort_order: 997,
|
|
1357
1379
|
has_options: false,
|
|
1358
1380
|
is_terminal: true,
|
|
1359
1381
|
show_nav_bar: false,
|
|
@@ -1383,7 +1405,7 @@ var NODE_TYPES = {
|
|
|
1383
1405
|
color: "#FFEDD5",
|
|
1384
1406
|
description: "Display a list of links for users to choose from",
|
|
1385
1407
|
category: "end",
|
|
1386
|
-
sort_order:
|
|
1408
|
+
sort_order: 998,
|
|
1387
1409
|
has_options: false,
|
|
1388
1410
|
is_terminal: true,
|
|
1389
1411
|
show_nav_bar: false,
|
|
@@ -1428,7 +1450,7 @@ var NODE_TYPES = {
|
|
|
1428
1450
|
color: "#E9D5FF",
|
|
1429
1451
|
description: "Provide a file for respondents to download",
|
|
1430
1452
|
category: "action",
|
|
1431
|
-
sort_order:
|
|
1453
|
+
sort_order: 9,
|
|
1432
1454
|
has_options: false,
|
|
1433
1455
|
is_terminal: false,
|
|
1434
1456
|
show_nav_bar: true,
|
|
@@ -1446,7 +1468,8 @@ var NODE_TYPES = {
|
|
|
1446
1468
|
items: {
|
|
1447
1469
|
type: "object",
|
|
1448
1470
|
properties: {
|
|
1449
|
-
file_name: { type: "string", label: "
|
|
1471
|
+
file_name: { type: "string", label: "Original file name", required: true },
|
|
1472
|
+
display_name: { type: "string", label: "Friendly name shown to respondents" },
|
|
1450
1473
|
file_path: { type: "string", label: "File path in storage", required: true },
|
|
1451
1474
|
file_size: { type: "number", label: "File size in bytes" },
|
|
1452
1475
|
mime_type: { type: "string", label: "MIME type" }
|
|
@@ -1454,7 +1477,7 @@ var NODE_TYPES = {
|
|
|
1454
1477
|
},
|
|
1455
1478
|
label: "Downloadable files"
|
|
1456
1479
|
},
|
|
1457
|
-
button_text: { type: "string", label: "
|
|
1480
|
+
button_text: { type: "string", label: "Continue button text", default: "Continue" },
|
|
1458
1481
|
description: { type: "string", label: "Description text" }
|
|
1459
1482
|
}
|
|
1460
1483
|
},
|
|
@@ -1477,7 +1500,28 @@ var NODE_TYPES = {
|
|
|
1477
1500
|
}
|
|
1478
1501
|
}
|
|
1479
1502
|
},
|
|
1480
|
-
output_schema:
|
|
1503
|
+
output_schema: {
|
|
1504
|
+
type: "object",
|
|
1505
|
+
required: ["node_type"],
|
|
1506
|
+
properties: {
|
|
1507
|
+
node_type: { type: "string", const: "file_download" },
|
|
1508
|
+
files: {
|
|
1509
|
+
type: "array",
|
|
1510
|
+
description: "The files the respondent downloaded, each a canonical media object with a fresh signed link.",
|
|
1511
|
+
items: {
|
|
1512
|
+
type: "object",
|
|
1513
|
+
properties: {
|
|
1514
|
+
filename: { type: "string", description: "Original filename" },
|
|
1515
|
+
content_type: { type: "string", description: "File MIME type" },
|
|
1516
|
+
downloaded_at: { type: "string", format: "date-time", description: "Timestamp when download was initiated" },
|
|
1517
|
+
url: { type: "string", format: "uri", description: "Direct, time-limited signed link (~48h, supports HTTP range)" },
|
|
1518
|
+
download_url: { type: "string", format: "uri", description: "Same link with a forced download (Content-Disposition: attachment)" },
|
|
1519
|
+
expires_at: { type: "string", format: "date-time", description: "When url/download_url stop working" }
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1481
1525
|
},
|
|
1482
1526
|
shopping: {
|
|
1483
1527
|
label: "Shopping",
|
|
@@ -1622,6 +1666,9 @@ for (const [type, def] of Object.entries(NODE_TYPES)) {
|
|
|
1622
1666
|
var NODE_TYPES_LIST = Object.entries(NODE_TYPES).map(([type, def]) => ({ type, ...def })).sort((a, b) => a.sort_order - b.sort_order);
|
|
1623
1667
|
var ACTIVE_NODE_TYPES = Object.entries(NODE_TYPES).filter(([, def]) => def.is_active && !def.is_system).map(([type]) => type);
|
|
1624
1668
|
var NODE_TYPE_KEYS = Object.keys(NODE_TYPES);
|
|
1669
|
+
var CONNECTION_CONFIG_KEYS = Object.fromEntries(
|
|
1670
|
+
Object.entries(NODE_TYPES).filter(([, def]) => Array.isArray(def.connection_config_keys) && def.connection_config_keys.length > 0).map(([type, def]) => [type, def.connection_config_keys])
|
|
1671
|
+
);
|
|
1625
1672
|
var RESPONSE_SCHEMAS = Object.fromEntries(
|
|
1626
1673
|
Object.entries(NODE_TYPES).map(([k, v]) => [k, v.response_schema])
|
|
1627
1674
|
);
|
|
@@ -1681,7 +1728,7 @@ var FORM_TYPES = {
|
|
|
1681
1728
|
],
|
|
1682
1729
|
composition: [
|
|
1683
1730
|
{ key: "topic", question: "What topic? (flags, movies, geography, music...)", fallback: "General trivia", mode: "all" },
|
|
1684
|
-
{ key: "question_count", question: "How many questions? (composition quizzes use ~
|
|
1731
|
+
{ key: "question_count", question: "How many questions? (composition quizzes use ~1 node per question, plus one more for any optional reveal beat - 5-6 is the sweet spot)", fallback: "5", mode: "all" }
|
|
1685
1732
|
]
|
|
1686
1733
|
},
|
|
1687
1734
|
variant_guide_uris: {
|
|
@@ -1692,7 +1739,7 @@ var FORM_TYPES = {
|
|
|
1692
1739
|
variant_descriptions: {
|
|
1693
1740
|
personality: "Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers",
|
|
1694
1741
|
comprehension: "Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation",
|
|
1695
|
-
composition: "Addendum for composition quizzes - guess
|
|
1742
|
+
composition: "Addendum for composition quizzes - guess formats built from rendered compositions: mechanic selection, the clue clip + answer feedback default (with an optional reveal payoff node), difficulty design"
|
|
1696
1743
|
},
|
|
1697
1744
|
prompt: { name: "create-quiz", title: "Create a Quiz", description: "Build a scored knowledge quiz with narrated video questions" }
|
|
1698
1745
|
},
|
|
@@ -1725,7 +1772,7 @@ var FORM_TYPES = {
|
|
|
1725
1772
|
aliases: ["case-study", "callout"],
|
|
1726
1773
|
variants: [],
|
|
1727
1774
|
required_features: [],
|
|
1728
|
-
required_node_types: ["open", "
|
|
1775
|
+
required_node_types: ["open", "details", "end_screen"],
|
|
1729
1776
|
default_media_style: "video",
|
|
1730
1777
|
guide_uri: "clipform://guides/interview",
|
|
1731
1778
|
guide_description: "Craft knowledge for building interview forms - warm-up pacing, open questions, consent, video responses",
|
|
@@ -1747,7 +1794,7 @@ var FORM_TYPES = {
|
|
|
1747
1794
|
aliases: ["lead-gen", "qualification", "lead-magnet"],
|
|
1748
1795
|
variants: [],
|
|
1749
1796
|
required_features: ["branching", "funnel"],
|
|
1750
|
-
required_node_types: ["choice", "
|
|
1797
|
+
required_node_types: ["choice", "details", "end_screen"],
|
|
1751
1798
|
default_media_style: "text",
|
|
1752
1799
|
guide_uri: "clipform://guides/funnel",
|
|
1753
1800
|
guide_description: "Craft knowledge for lead qualification funnels - planned feature, conditional routing coming soon",
|
|
@@ -1765,7 +1812,7 @@ var FORM_TYPES = {
|
|
|
1765
1812
|
aliases: ["story", "review"],
|
|
1766
1813
|
variants: [],
|
|
1767
1814
|
required_features: [],
|
|
1768
|
-
required_node_types: ["open", "
|
|
1815
|
+
required_node_types: ["open", "details", "end_screen"],
|
|
1769
1816
|
default_media_style: "video",
|
|
1770
1817
|
guide_uri: "clipform://guides/testimonial",
|
|
1771
1818
|
guide_description: "Craft knowledge for collecting testimonials and customer stories on video - storytelling prompts, comfort techniques, consent",
|
|
@@ -1786,7 +1833,7 @@ var FORM_TYPES = {
|
|
|
1786
1833
|
aliases: ["job-application", "admission", "enrollment", "grant"],
|
|
1787
1834
|
variants: [],
|
|
1788
1835
|
required_features: [],
|
|
1789
|
-
required_node_types: ["open", "choice", "
|
|
1836
|
+
required_node_types: ["open", "choice", "details", "end_screen"],
|
|
1790
1837
|
default_media_style: "video",
|
|
1791
1838
|
guide_uri: "clipform://guides/application",
|
|
1792
1839
|
guide_description: "Craft knowledge for application and evaluation forms - multi-section structure, video responses for behavioural questions, screening",
|
|
@@ -1806,7 +1853,7 @@ var FORM_TYPES = {
|
|
|
1806
1853
|
aliases: ["registration", "signup", "event", "rsvp", "workshop"],
|
|
1807
1854
|
variants: [],
|
|
1808
1855
|
required_features: [],
|
|
1809
|
-
required_node_types: ["
|
|
1856
|
+
required_node_types: ["details", "choice", "end_screen"],
|
|
1810
1857
|
default_media_style: "text",
|
|
1811
1858
|
guide_uri: "clipform://guides/booking",
|
|
1812
1859
|
guide_description: "Craft knowledge for event registration and booking forms - minimal friction, video welcome, confirmation flow",
|
|
@@ -1943,7 +1990,8 @@ var BUSINESS = {
|
|
|
1943
1990
|
email: {
|
|
1944
1991
|
support: "support@clipform.io",
|
|
1945
1992
|
sales: "sales@clipform.io",
|
|
1946
|
-
hello: "hello@clipform.io"
|
|
1993
|
+
hello: "hello@clipform.io",
|
|
1994
|
+
founder: "andy@clipform.io"
|
|
1947
1995
|
},
|
|
1948
1996
|
urls: getUrls()
|
|
1949
1997
|
};
|
|
@@ -2001,37 +2049,33 @@ var SLIDESHOW_TRANSITIONS = [
|
|
|
2001
2049
|
];
|
|
2002
2050
|
var COMPOSITION_REGISTRY = [
|
|
2003
2051
|
// Beds (full-bleed backgrounds)
|
|
2004
|
-
{ id: "
|
|
2052
|
+
{ id: "Slideshow", tier: "public", kind: "bed", scene_layer: true },
|
|
2005
2053
|
{ id: "Map", tier: "public", kind: "bed", scene_layer: true },
|
|
2006
2054
|
{ id: "Grid", tier: "public", kind: "bed", scene_layer: true },
|
|
2007
|
-
{ id: "
|
|
2008
|
-
{ id: "
|
|
2009
|
-
{ id: "NumberLine", tier: "public", kind: "bed" },
|
|
2010
|
-
{ id: "CountdownRing", tier: "public", kind: "bed" },
|
|
2011
|
-
{ id: "CountrySilhouetteClip", tier: "public", kind: "bed", scene_layer: true },
|
|
2012
|
-
{ id: "FlagReveal", tier: "public", kind: "bed" },
|
|
2013
|
-
{ id: "ColorCards", tier: "public", kind: "bed", scene_layer: true },
|
|
2014
|
-
{ id: "TitleCard", tier: "public", kind: "bed" },
|
|
2015
|
-
{ id: "ParallaxImage", tier: "public", kind: "bed" },
|
|
2016
|
-
{ id: "Spin3D", tier: "labs", kind: "bed", scene_layer: true },
|
|
2055
|
+
{ id: "Timeline", tier: "labs", kind: "bed" },
|
|
2056
|
+
{ id: "CountrySilhouetteClip", tier: "labs", kind: "bed", scene_layer: true },
|
|
2017
2057
|
// Overlays (assets layered on a bed)
|
|
2018
|
-
{ id: "
|
|
2019
|
-
{ id: "
|
|
2020
|
-
{ id: "BeforeAfter", tier: "public", kind: "overlay", scene_layer: true },
|
|
2021
|
-
{ id: "StatCounter", tier: "labs", kind: "overlay", scene_layer: true },
|
|
2022
|
-
{ id: "ListReveal", tier: "labs", kind: "overlay", scene_layer: true },
|
|
2058
|
+
{ id: "Text", tier: "labs", kind: "overlay", scene_layer: true },
|
|
2059
|
+
{ id: "Rebus", tier: "labs", kind: "overlay", scene_layer: true },
|
|
2023
2060
|
// Container
|
|
2024
2061
|
{ id: "Scene", tier: "labs", kind: "container" },
|
|
2025
2062
|
// Social marketing templates (gated)
|
|
2026
|
-
{ id: "ShortFormQuiz", tier: "social", kind: "
|
|
2027
|
-
{ id: "ScorecardQuiz", tier: "social", kind: "
|
|
2028
|
-
{ id: "ScorecardGK", tier: "social", kind: "
|
|
2029
|
-
{ id: "CountrySilhouetteQuiz", tier: "social", kind: "
|
|
2063
|
+
{ id: "ShortFormQuiz", tier: "social", kind: "video" },
|
|
2064
|
+
{ id: "ScorecardQuiz", tier: "social", kind: "video" },
|
|
2065
|
+
{ id: "ScorecardGK", tier: "social", kind: "video" },
|
|
2066
|
+
{ id: "CountrySilhouetteQuiz", tier: "social", kind: "video" }
|
|
2030
2067
|
];
|
|
2031
2068
|
var compositionIdsByTier = (tier) => COMPOSITION_REGISTRY.filter((c) => c.tier === tier).map((c) => c.id);
|
|
2032
2069
|
var PUBLIC_COMPOSITION_IDS = compositionIdsByTier("public");
|
|
2033
2070
|
var LABS_COMPOSITION_IDS = compositionIdsByTier("labs");
|
|
2034
2071
|
var SOCIAL_COMPOSITION_IDS = compositionIdsByTier("social");
|
|
2072
|
+
function exposedCompositionIds(includeNonPublic) {
|
|
2073
|
+
return [
|
|
2074
|
+
...PUBLIC_COMPOSITION_IDS,
|
|
2075
|
+
...includeNonPublic ? LABS_COMPOSITION_IDS : [],
|
|
2076
|
+
...includeNonPublic ? SOCIAL_COMPOSITION_IDS : []
|
|
2077
|
+
];
|
|
2078
|
+
}
|
|
2035
2079
|
var SCENE_LAYER_COMPOSITION_IDS = COMPOSITION_REGISTRY.filter((c) => c.scene_layer).map((c) => c.id);
|
|
2036
2080
|
var MCP_TOOL_TIERS = {};
|
|
2037
2081
|
|
|
@@ -2257,9 +2301,7 @@ export {
|
|
|
2257
2301
|
KEN_BURNS_PRESETS,
|
|
2258
2302
|
KEN_BURNS_FIT_MODES,
|
|
2259
2303
|
SLIDESHOW_TRANSITIONS,
|
|
2260
|
-
|
|
2261
|
-
LABS_COMPOSITION_IDS,
|
|
2262
|
-
SOCIAL_COMPOSITION_IDS,
|
|
2304
|
+
exposedCompositionIds,
|
|
2263
2305
|
MCP_TOOL_TIERS,
|
|
2264
2306
|
setMcpVersion,
|
|
2265
2307
|
callApi,
|
|
@@ -2269,4 +2311,4 @@ export {
|
|
|
2269
2311
|
getSessionContextWithAuth,
|
|
2270
2312
|
getSessionContext
|
|
2271
2313
|
};
|
|
2272
|
-
//# sourceMappingURL=chunk-
|
|
2314
|
+
//# sourceMappingURL=chunk-ET43M6YO.js.map
|