@clipform/mcp-server 2.15.12 → 2.16.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.
@@ -48,6 +48,19 @@ var FEATURES = {
48
48
  status: "live",
49
49
  category: "builder"
50
50
  },
51
+ // Backfilled (#4338): apps/viewer/components/FormViewer.tsx renders exactly
52
+ // one node at a time (`currentNode = nodes[currentIndex]`, single
53
+ // `AnimatePresence` block gating on `currentNode`) and transitions to the
54
+ // next on answer - never a scrollable list of every question. No
55
+ // enabled/status change (this has always been the viewer's shape), so no
56
+ // wentLiveAt.
57
+ one_question_at_a_time: {
58
+ name: "One question at a time",
59
+ description: "The viewer shows a single question and transitions to the next, never a scrollable list of every question",
60
+ enabled: true,
61
+ status: "live",
62
+ category: "builder"
63
+ },
51
64
  branching: {
52
65
  name: "Conditional branching",
53
66
  description: "Choice nodes route to different destinations based on which option is picked",
@@ -140,7 +153,12 @@ var FEATURES = {
140
153
  },
141
154
  node_details: {
142
155
  name: "Details",
143
- description: "Structured fields (name, email, phone, company) with consent checkboxes",
156
+ // Widened (#4338): the checkbox items are typed 'consent' (required,
157
+ // blocks submission until checked) or 'opt_in' (optional) - see
158
+ // CONSENT_TYPES in node-types.js and the viewer's Contact.tsx. Both are
159
+ // plain text checkboxes available to every creator with no gate; only
160
+ // attaching a PDF agreement document is gated (consent_documents, beta).
161
+ description: "Structured fields (name, email, phone, company) with consent and opt-in checkboxes",
144
162
  enabled: true,
145
163
  status: "live",
146
164
  category: "node-types"
@@ -201,11 +219,25 @@ var FEATURES = {
201
219
  },
202
220
  node_camera: {
203
221
  name: "Camera",
204
- description: "Capture a photo from the device camera",
205
- // Scaffolded disabled (#2097): code lands ready, but node.type's DB check
206
- // constraint doesn't accept 'camera' yet - that's a separate parked
207
- // holds-migration PR. Flip once the migration has merged (= applied to
208
- // prod) and the apps have deployed.
222
+ // Description mirrors NODE_TYPES.camera.description (the node SSOT) - the
223
+ // node captures photo OR video (allowed_capture, #2759), not photo only.
224
+ description: "Capture a photo or video from the device camera",
225
+ // Dogfooding in live via NODE_COMPANY_ALLOWLIST.node_camera below. The DB
226
+ // node_type_check constraint already accepts 'camera' in prod (migration
227
+ // #2103 merged + applied 2026-07-17), so GA is now a pure app-config flip:
228
+ // set enabled true + status 'live' and follow feature-lifecycle.
229
+ enabled: false,
230
+ status: "planned",
231
+ category: "node-types"
232
+ },
233
+ node_conditional: {
234
+ name: "If / then",
235
+ description: "Route the flow to different branches based on a score, max score, or category variable.",
236
+ // Scaffolded disabled (#4105, phase 1 of the #4104 variables engine): code
237
+ // lands ready, but node.type's DB check constraint doesn't accept
238
+ // 'conditional' yet - that's a separate parked holds-migration PR. Flip
239
+ // once the migration has merged (= applied to prod) and the apps have
240
+ // deployed (camera precedent, #2097).
209
241
  enabled: false,
210
242
  status: "planned",
211
243
  category: "node-types"
@@ -276,10 +308,26 @@ var FEATURES = {
276
308
  status: "live",
277
309
  category: "responses"
278
310
  },
311
+ // Backfilled (#4338): the respondent-facing recorder (packages/media-recorder)
312
+ // already device-detects and adapts - mobile-first cover framing by default,
313
+ // front/back camera flip control shown only on mobile, iOS Safari getUserMedia
314
+ // quirks handled (browser-detection.ts) - so recording on a phone has always
315
+ // worked and been tuned for it. No enabled/status change, so no wentLiveAt.
316
+ mobile_recording: {
317
+ name: "Mobile-optimized recording",
318
+ description: "Respondents recording audio/video/photo on a phone get a mobile-first layout and a front/back camera flip control",
319
+ enabled: true,
320
+ status: "live",
321
+ category: "responses"
322
+ },
279
323
  // -- Analytics --
280
324
  analytics_overview: {
281
325
  name: "Analytics dashboard",
282
- description: "Views, starts, completions with daily time series",
326
+ // Widened #4338: views/starts/completions update live (useInsightRealtime,
327
+ // apps/dashboard's analytics page) and NodeResultCard computes a per-node
328
+ // drop-off count (`total_views - answeredCount`, "N people dropped off"),
329
+ // not just an aggregate form-level funnel.
330
+ description: "Real-time views, starts, and completions with daily time series, plus per-question drop-off",
283
331
  enabled: true,
284
332
  status: "live",
285
333
  category: "analytics"
@@ -306,6 +354,35 @@ var FEATURES = {
306
354
  wentLiveAt: "2026-06-07",
307
355
  category: "analytics"
308
356
  },
357
+ // Backfilled (#4338): the Responses table's search box (DataSpreadsheet's
358
+ // globalFilter, TanStack default `includesString` across every visible
359
+ // column) already searches every node-response column's displayed value -
360
+ // for audio/video answers that value falls back to the transcription text
361
+ // (list_form_submissions / get_latest_responses_for_session's
362
+ // response_data->'transcription'->>'text', supabase/migrations
363
+ // 20260920190000_submission_grain_per_completion.sql) before the generic
364
+ // "Video/Audio response" label. So a transcribed response is genuinely
365
+ // full-text searchable today - this key just gives that existing behaviour
366
+ // a name marketing can cite. No enabled/status change (search has always
367
+ // been on), so deliberately no wentLiveAt.
368
+ //
369
+ // Scoped honestly (review follow-up, #4338): this is ONE form's Responses
370
+ // table, filtered client-side (TanStack's globalFilter over the rows
371
+ // already loaded for that form) - never cross-form, and a video/audio
372
+ // answer's transcript only becomes searchable once transcription finishes
373
+ // (checked: no write path ever sets response_data.display or .text on a
374
+ // media answer at submit time - only the async transcription pipeline
375
+ // adds `transcription.text` later, so nothing hides the transcript once it
376
+ // lands; transcription itself is not plan-gated, it runs on every
377
+ // audio/video response regardless of plan). It also never jumps playback
378
+ // to the matched moment in the recording - it only surfaces the row.
379
+ response_search: {
380
+ name: "Response search",
381
+ description: "Filter one form's responses table by keyword, including transcript text once transcription finishes - not cross-form, and does not jump to a moment in the recording",
382
+ enabled: true,
383
+ status: "live",
384
+ category: "analytics"
385
+ },
309
386
  tracked_links: {
310
387
  name: "Tracked links",
311
388
  description: "URL tracking and click-through analytics for shared form links",
@@ -394,10 +471,37 @@ var FEATURES = {
394
471
  status: "live",
395
472
  category: "sharing"
396
473
  },
474
+ // Backfilled (#4338): the public /templates gallery (apps/marketing/src/app/templates,
475
+ // apps/marketing/src/components/template-gallery) lets anyone browse and start
476
+ // from a real, live Clipform template - a curated core set, plus the rest
477
+ // (project_template_gallery_curated_core6). No enabled/status change, no wentLiveAt.
478
+ templates_gallery: {
479
+ name: "Template gallery",
480
+ description: "Browse and start a form from a real, prebuilt template",
481
+ enabled: true,
482
+ status: "live",
483
+ category: "sharing"
484
+ },
397
485
  // -- AI --
398
486
  ai_form_generation: {
399
487
  name: "AI form generation",
400
- description: "Generate complete forms from a text prompt via MCP or dashboard",
488
+ // Corrected twice (#4338): not MCP-only (round 4 found the public
489
+ // web AI builder). In practice this mostly means the ChatGPT/Claude
490
+ // connector (chat_connectors) - leading with that per the user.
491
+ description: "Generate complete forms from a text prompt, primarily via the ChatGPT and Claude connectors (see chat_connectors); also the public web AI builder on marketing pages; no in-dashboard entry point",
492
+ enabled: true,
493
+ status: "live",
494
+ category: "ai"
495
+ },
496
+ // Confirmed live by the user 2026-09-27: both the ChatGPT App Directory and
497
+ // Claude Connectors Directory listings are live. Implementation is
498
+ // packages/mcp-server (the same MCP server surfaced as a connector in both
499
+ // directories - see #797 /
500
+ // #3681). No enabled/status change
501
+ // pending, so no wentLiveAt.
502
+ chat_connectors: {
503
+ name: "ChatGPT and Claude connectors",
504
+ description: "Build and edit forms from ChatGPT and Claude via the Clipform connector, listed in both the ChatGPT App Directory and the Claude Connectors Directory",
401
505
  enabled: true,
402
506
  status: "live",
403
507
  category: "ai"
@@ -520,9 +624,9 @@ var FEATURES = {
520
624
  },
521
625
  integration_slack: {
522
626
  name: "Slack",
523
- description: "Send notifications to Slack channels",
627
+ description: "Post a summary of every completed response to a Slack channel",
524
628
  enabled: false,
525
- status: "planned",
629
+ status: "beta",
526
630
  category: "integrations"
527
631
  },
528
632
  integration_shopify: {
@@ -536,7 +640,7 @@ var FEATURES = {
536
640
  name: "Google Sheets",
537
641
  description: "Sync form responses to a Google Sheet, one row per submission",
538
642
  enabled: false,
539
- status: "planned",
643
+ status: "beta",
540
644
  category: "integrations"
541
645
  },
542
646
  notifications: {
@@ -683,6 +787,9 @@ var NODE_TYPES = {
683
787
  supports_media: false,
684
788
  is_system: true,
685
789
  show_in_results: false,
790
+ // Never appears in a completed submission's answers (system node, no
791
+ // output_schema) - false is a no-op default, set for guard-test coverage.
792
+ notify_inline: false,
686
793
  default_config: null,
687
794
  config_schema: null,
688
795
  response_schema: null,
@@ -707,6 +814,8 @@ var NODE_TYPES = {
707
814
  supports_media: true,
708
815
  is_system: false,
709
816
  show_in_results: true,
817
+ // Short selected-option label - safe to render inline in a notification (#4154).
818
+ notify_inline: true,
710
819
  default_config: {
711
820
  selection_mode: "single",
712
821
  choice: { enable_branching: false, record_scores: false },
@@ -814,6 +923,10 @@ var NODE_TYPES = {
814
923
  supports_media: true,
815
924
  is_system: false,
816
925
  show_in_results: true,
926
+ // True for the common short-text case; a channel notification (#4154)
927
+ // still swaps a recorded audio/video answer for a typed placeholder
928
+ // based on the answer's own media type, not this flag.
929
+ notify_inline: true,
817
930
  default_config: {
818
931
  formats: [
819
932
  { order: 0, format: "text" },
@@ -951,6 +1064,8 @@ var NODE_TYPES = {
951
1064
  supports_media: true,
952
1065
  is_system: false,
953
1066
  show_in_results: true,
1067
+ // A bare numeric value - short enough to render inline (#4154).
1068
+ notify_inline: true,
954
1069
  default_config: null,
955
1070
  config_schema: {
956
1071
  type: "object",
@@ -985,6 +1100,9 @@ var NODE_TYPES = {
985
1100
  supports_media: false,
986
1101
  is_system: false,
987
1102
  show_in_results: true,
1103
+ // Structured provider data (calendly/google_meet), not a flat value -
1104
+ // a notification renders a typed placeholder instead (#4154).
1105
+ notify_inline: false,
988
1106
  default_config: null,
989
1107
  config_schema: {
990
1108
  type: "object",
@@ -1063,6 +1181,9 @@ var NODE_TYPES = {
1063
1181
  // charted) but DOES show in the per-response Responses table, where each
1064
1182
  // lead's contact fields are actionable (#746).
1065
1183
  show_in_responses: true,
1184
+ // Key contact fields (first name, email) are the whole point of a
1185
+ // notification for this node type - always inline (#4154).
1186
+ notify_inline: true,
1066
1187
  default_config: {
1067
1188
  fields: [
1068
1189
  { id: "first_name", type: "first_name", label: "First Name", enabled: true, required: true },
@@ -1219,6 +1340,8 @@ var NODE_TYPES = {
1219
1340
  supports_media: false,
1220
1341
  is_system: false,
1221
1342
  show_in_results: true,
1343
+ // Files, not a flat value - a notification renders a typed placeholder (#4154).
1344
+ notify_inline: false,
1222
1345
  default_config: null,
1223
1346
  config_schema: {
1224
1347
  type: "object",
@@ -1308,6 +1431,8 @@ var NODE_TYPES = {
1308
1431
  supports_media: true,
1309
1432
  is_system: false,
1310
1433
  show_in_results: true,
1434
+ // An image, not a flat value - a notification renders a typed placeholder (#4154).
1435
+ notify_inline: false,
1311
1436
  default_config: {
1312
1437
  paper_color: "#FAF9F6",
1313
1438
  stroke_colors: ["#1F2937", "#EF4444", "#3B82F6", "#22C55E", "#FACC15"],
@@ -1478,6 +1603,9 @@ var NODE_TYPES = {
1478
1603
  supports_media: false,
1479
1604
  is_system: false,
1480
1605
  show_in_results: true,
1606
+ // A captured photo/video, not a flat value - a notification renders a
1607
+ // typed placeholder (#4154).
1608
+ notify_inline: false,
1481
1609
  default_config: null,
1482
1610
  config_schema: {
1483
1611
  type: "object",
@@ -1559,6 +1687,46 @@ var NODE_TYPES = {
1559
1687
  }
1560
1688
  }
1561
1689
  },
1690
+ // Phase 1 of the variables engine (#4104, this node #4105): routes the
1691
+ // flow on a generic built-in Number (internally `score`, derived from
1692
+ // node_options.score -> ScoreState.cumulativeScore - see ROUTABLE_VARIABLES
1693
+ // in logic-types.js). Response-less and screen-less - the viewer evaluates
1694
+ // it transparently (no render) and continues to the matching branch. Each
1695
+ // branch is a node_options row (has_options:true); the branch edge is a
1696
+ // `jump` action anchored by the option's id (LogicAction.option_id).
1697
+ conditional: {
1698
+ label: "If / then",
1699
+ shorthand: "If",
1700
+ icon: "Split",
1701
+ color: "#E0E7FF",
1702
+ description: "Route the flow to different branches based on a score, max score, or category variable.",
1703
+ category: "logic",
1704
+ sort_order: 6.7,
1705
+ has_options: true,
1706
+ min_options: 2,
1707
+ max_options: 10,
1708
+ max_option_length: 40,
1709
+ is_terminal: false,
1710
+ show_nav_bar: false,
1711
+ loading: "eager",
1712
+ supports_prompt: false,
1713
+ supports_media: false,
1714
+ is_system: false,
1715
+ show_in_results: false,
1716
+ // Logic/routing node - no respondent answer to render in a channel
1717
+ // notification, same as the other control nodes (redirect, link_list,
1718
+ // end_screen). Required by the #4154 notify_inline invariant.
1719
+ notify_inline: false,
1720
+ default_config: {
1721
+ options: [
1722
+ { content: "Branch 1" },
1723
+ { content: "Else" }
1724
+ ]
1725
+ },
1726
+ config_schema: null,
1727
+ response_schema: null,
1728
+ output_schema: null
1729
+ },
1562
1730
  payment: {
1563
1731
  label: "Payment",
1564
1732
  shorthand: "Payment",
@@ -1582,6 +1750,9 @@ var NODE_TYPES = {
1582
1750
  // case - the publish gate's own showcase waiver (graph-validation.js) still
1583
1751
  // names workspace_integration_id directly since it's the only per-type check today.
1584
1752
  connection_config_keys: ["workspace_integration_id"],
1753
+ // A payment confirmation line is the whole point of a notification for
1754
+ // this node type - always inline (#4154).
1755
+ notify_inline: true,
1585
1756
  default_config: { amount: null, currency: "usd", provider: "stripe" },
1586
1757
  config_schema: {
1587
1758
  type: "object",
@@ -1726,6 +1897,8 @@ var NODE_TYPES = {
1726
1897
  supports_media: true,
1727
1898
  is_system: false,
1728
1899
  show_in_results: true,
1900
+ // Short selected-option label - safe to render inline (#4154).
1901
+ notify_inline: true,
1729
1902
  default_config: {
1730
1903
  choice: { enable_branching: false },
1731
1904
  options: [
@@ -1788,6 +1961,8 @@ var NODE_TYPES = {
1788
1961
  supports_media: true,
1789
1962
  is_system: false,
1790
1963
  show_in_results: false,
1964
+ // Short selected-option label - safe to render inline (#4154).
1965
+ notify_inline: true,
1791
1966
  default_config: { options: [{ content: "Continue" }] },
1792
1967
  config_schema: {
1793
1968
  type: "object",
@@ -1826,6 +2001,9 @@ var NODE_TYPES = {
1826
2001
  supports_media: false,
1827
2002
  is_system: false,
1828
2003
  show_in_results: false,
2004
+ // Terminal node - never appears in a completed submission's answers
2005
+ // (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
2006
+ notify_inline: false,
1829
2007
  default_config: { url: "", auto_redirect: true },
1830
2008
  config_schema: {
1831
2009
  type: "object",
@@ -1856,6 +2034,9 @@ var NODE_TYPES = {
1856
2034
  supports_media: false,
1857
2035
  is_system: false,
1858
2036
  show_in_results: false,
2037
+ // Terminal node - never appears in a completed submission's answers
2038
+ // (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
2039
+ notify_inline: false,
1859
2040
  default_config: { links: [{ id: "default", url: "", title: "", description: "", order: 0 }], auto_redirect: false },
1860
2041
  config_schema: {
1861
2042
  type: "object",
@@ -1901,6 +2082,8 @@ var NODE_TYPES = {
1901
2082
  supports_media: false,
1902
2083
  is_system: false,
1903
2084
  show_in_results: true,
2085
+ // Files, not a flat value - a notification renders a typed placeholder (#4154).
2086
+ notify_inline: false,
1904
2087
  default_config: null,
1905
2088
  config_schema: {
1906
2089
  type: "object",
@@ -1981,6 +2164,8 @@ var NODE_TYPES = {
1981
2164
  supports_media: false,
1982
2165
  is_system: false,
1983
2166
  show_in_results: false,
2167
+ // No response_schema - never carries a flat answer value; false is a no-op default.
2168
+ notify_inline: false,
1984
2169
  default_config: { provider: "shopify", cta_mode: "checkout", source_mode: "manual" },
1985
2170
  config_schema: {
1986
2171
  type: "object",
@@ -2049,6 +2234,9 @@ var NODE_TYPES = {
2049
2234
  supports_media: false,
2050
2235
  is_system: false,
2051
2236
  show_in_results: false,
2237
+ // Terminal node - never appears in a completed submission's answers
2238
+ // (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
2239
+ notify_inline: false,
2052
2240
  default_config: {
2053
2241
  title: "Thank you!",
2054
2242
  message: "Your response has been submitted."
@@ -2869,8 +3057,9 @@ var PLAN_LIMITS = {
2869
3057
  // usage above the base band IS charged once this deploys - the HUMAN LEGAL
2870
3058
  // REVIEW on LEGAL.billing below must clear before that go-live.
2871
3059
  //
2872
- // `response_limit` counts COMPLETED response sets only; partials never
2873
- // consume allowance.
3060
+ // `response_limit` counts COMPLETED submissions only (#4118: per completed
3061
+ // form_session, grandfathered pre-cutover as completed response sets - see
3062
+ // count_workspace_responses_this_month); partials never consume allowance.
2874
3063
  //
2875
3064
  // shopify_plan_handle is null until the matching Partner Dashboard plans
2876
3065
  // exist - so planVersionForShopifyPlan still maps Shopify's "Pro" to pro_v1
@@ -3295,4 +3484,4 @@ export {
3295
3484
  getSessionContextWithAuth,
3296
3485
  getSessionContext
3297
3486
  };
3298
- //# sourceMappingURL=chunk-CW6LYA3K.js.map
3487
+ //# sourceMappingURL=chunk-Z4ZGF6OV.js.map